mirror of
https://gitlab.com/lecarore/breakout71.git
synced 2025-04-20 04:05:06 -04:00
5 colors /level, sound when ball or brick change color
This commit is contained in:
parent
b6fe46c9bc
commit
2e3ab3011f
21 changed files with 1379 additions and 598 deletions
115
Readme.md
115
Readme.md
|
@ -32,41 +32,40 @@ There's also an easy mode for kids (slower ball).
|
||||||
- add pwe manifest
|
- add pwe manifest
|
||||||
- offline mode with service worker
|
- offline mode with service worker
|
||||||
- see how to do fullscreen on ios, or at least explain to do aA/hide toolbars
|
- see how to do fullscreen on ios, or at least explain to do aA/hide toolbars
|
||||||
|
- translation
|
||||||
|
- when game resumes near bottom, be unvulnerable for .5s ? , once per level
|
||||||
|
|
||||||
# Game engine features
|
# Game engine features
|
||||||
|
|
||||||
- shinier coins by applying glow to them
|
|
||||||
- ask for permanent storage
|
- ask for permanent storage
|
||||||
- experiment with showing the combo somewhere else, maybe top center, maybe instead of score.
|
|
||||||
- more help somewhere accessible
|
- more help somewhere accessible
|
||||||
- limit GC by reusing coins and particles
|
- limit GC by reusing coins and particles
|
||||||
- convert captures to mp4 unsing ffmpeg wasm because reddit refuses webm files
|
- convert captures to mp4 unsing ffmpeg wasm because reddit refuses webm files
|
||||||
- disable zooming (for ios double tap)
|
- disable zooming (for ios double tap)
|
||||||
- few puck bounces = more choices / upgrades
|
- few puck bounces = more choices / upgrades
|
||||||
- show total score on end screen (score added to total)
|
- show total score on end screen (score added to total)
|
||||||
- show stats on end screen compared to other runs
|
|
||||||
- handle back bouton in menu
|
- handle back bouton in menu
|
||||||
- mouvement relatif du puck
|
- balls could collide with each other
|
||||||
- balls should collide with each other
|
|
||||||
- when game resumes near bottom, be unvulnerable for .5s ? , once per level
|
|
||||||
- apply global curve / brightness to canvas when things blow, or just always to make neon effect better
|
|
||||||
- manifest for PWA (android and apple)
|
- manifest for PWA (android and apple)
|
||||||
- lights shadows
|
|
||||||
- Offline mode web for iphone
|
- Offline mode web for iphone
|
||||||
- controller support on web/mobile
|
- controller support on web/mobile
|
||||||
- webgl rendering
|
|
||||||
- enable export of gameplay capture in webview
|
- enable export of gameplay capture in webview
|
||||||
- endgame histograms could work as filters, when you hover a bar, all other histograms would show the stats of those runs only, without changing reference of categories
|
- endgame histograms could work as filters, when you hover a bar, all other histograms would show the stats of those runs only, without changing reference of categories
|
||||||
- sound when ball changes color
|
|
||||||
- option : don't pause on mobile when lifting finger
|
|
||||||
- option : accelerated relative movements on mobile
|
|
||||||
- maybe just have 10 background, and always use the same one for the nth level of each run ?
|
|
||||||
- would be nice to have a leaderboard for not using each perk too. Like "best runs without hot start"
|
- would be nice to have a leaderboard for not using each perk too. Like "best runs without hot start"
|
||||||
- restart run on r
|
- restart run on r
|
||||||
- when missing, redo particle trail, but give speed to particle that matches ball direction
|
- when missing, redo particle trail, but give speed to particle that matches ball direction
|
||||||
|
|
||||||
|
# graphics
|
||||||
|
- apply global curve / brightness to canvas when things blow, or just always to make neon effect better
|
||||||
|
- lights shadows
|
||||||
|
- webgl rendering
|
||||||
|
- shinier coins by applying glow to them
|
||||||
|
- different visual effects on ball to represent which perks it's imbued with (pierce, sapper…). remove visual while it's not affected (can't pierce/sap anymore until touching the puck).
|
||||||
|
- experiment with showing the combo somewhere else, maybe top center, maybe instead of score.
|
||||||
|
- the white outline on bricks associated with picky eater kinda works but i feel it's more distracting than anything. maybe try something different ? put a cross on matching coloured bricks, or the contrary, grey out other bricks.
|
||||||
|
|
||||||
# New perks ideas
|
# New perks ideas
|
||||||
- second puck (symmeric to the first one)
|
- second puck (symmetric to the first one)
|
||||||
- keep combo between level, loose half your run score when missing any bricks
|
- keep combo between level, loose half your run score when missing any bricks
|
||||||
- offer next level choice after upgrade pick
|
- offer next level choice after upgrade pick
|
||||||
- ban 3 random perks from pool, doesn't tell you which ones, gain 2 upgrades
|
- ban 3 random perks from pool, doesn't tell you which ones, gain 2 upgrades
|
||||||
|
@ -99,7 +98,7 @@ There's also an easy mode for kids (slower ball).
|
||||||
- bricks attract coins
|
- bricks attract coins
|
||||||
- breaking bricks stains neighbours
|
- breaking bricks stains neighbours
|
||||||
- extra kick after bouncing on puck
|
- extra kick after bouncing on puck
|
||||||
- transparent coins
|
- transparents coins
|
||||||
- coins of different colors repulse
|
- coins of different colors repulse
|
||||||
- bricks follow game of life pattern with one update every second
|
- bricks follow game of life pattern with one update every second
|
||||||
- 2x coins when ball goes downward / upward, half that amount otherwise ?
|
- 2x coins when ball goes downward / upward, half that amount otherwise ?
|
||||||
|
@ -138,18 +137,8 @@ There's also an easy mode for kids (slower ball).
|
||||||
- ball avoids brick of wrong color
|
- ball avoids brick of wrong color
|
||||||
- coins avoid ball of different color
|
- coins avoid ball of different color
|
||||||
- colored coins only (coins should be of the color of the ball to count )
|
- colored coins only (coins should be of the color of the ball to count )
|
||||||
|
- level flips horizontally every time a ball bounces on puck
|
||||||
|
- coins that hit the puck disappear, missed ones are scored
|
||||||
# Balancing ideas
|
|
||||||
|
|
||||||
The dominant strategy now is Compound Interest lvl 3 + coin magnet/viscosity/
|
|
||||||
and hot start + explosives and multiball
|
|
||||||
|
|
||||||
- make Compound Interest less OP making it full reset when coins lost
|
|
||||||
- cap hot start to lvl 2, or make it decrease faster
|
|
||||||
- make puck smaller as combo increases ?
|
|
||||||
- coin magnet has no effect when too close, or coins might overshoot, or coins bounce and spread more ?
|
|
||||||
- add red anti-coins, they destroy your combo and your score, and they behave like heavier coins.
|
|
||||||
|
|
||||||
# extra levels
|
# extra levels
|
||||||
|
|
||||||
|
@ -159,17 +148,30 @@ and hot start + explosives and multiball
|
||||||
- animals
|
- animals
|
||||||
- countries flags and shapes, with name as background
|
- countries flags and shapes, with name as background
|
||||||
|
|
||||||
# big features
|
# extra settings
|
||||||
|
|
||||||
- use ts and a bundler to get fewer bugs and compatibility with old browsers / webviews
|
|
||||||
- final bosses (large vertical level that scrolls down faster and faster)
|
|
||||||
- split screen multiplayer
|
|
||||||
- translation
|
|
||||||
- Add color schemes into the game (ex : Catppuccin, Dracula, Terminal, etc)
|
|
||||||
- add a toggle to switch between the “coin” design and colored bubbles
|
- add a toggle to switch between the “coin” design and colored bubbles
|
||||||
- sandbox mode
|
- on mobile, relative movement of the touch would be amplified and added to the puck
|
||||||
|
- option : don't pause on mobile when lifting finger
|
||||||
|
|
||||||
|
# Unlockable infinite mode
|
||||||
|
|
||||||
|
Allow players to loop the game, adding one hasard per loop, making it harder and harder to exploit each strategy. The high score are separated from the main mode. The scores are added for unlock. You no longer get upgrades after the first 7 levels. The score you make in each level is instead multiplied by the number of "upgrades" and "choices" you would have had.
|
||||||
|
|
||||||
|
Possible challenges :
|
||||||
|
- Add negative coins that make the coin magnet less usage
|
||||||
|
- add negative bricks that clear coins and reset combo
|
||||||
|
- add a brick eating enemy that forces you to play fast
|
||||||
|
- add a force field for 10s that negates hots start
|
||||||
|
- other perks can be randomly turned off
|
||||||
|
- ball keeps accelerating until unplayable
|
||||||
|
- graphical effects like trail, contrast, blur to make it harder to see what's going on
|
||||||
|
|
||||||
|
# extend re-playability
|
||||||
- hard mode : bricks take many hits, perks more rare, missing clears level score, missing coins deducts score..
|
- hard mode : bricks take many hits, perks more rare, missing clears level score, missing coins deducts score..
|
||||||
- stats by lack of perk, like "best score without using hot start".
|
- stats by lack of perk, like "best score without using hot start".
|
||||||
|
- split screen multiplayer
|
||||||
|
- Add color schemes into the game (ex : Catppuccin, Dracula, Terminal, etc)
|
||||||
|
|
||||||
Instead of automatically unlocking things at the end of each run, add the coins to the user's account,
|
Instead of automatically unlocking things at the end of each run, add the coins to the user's account,
|
||||||
and let them spend those coins on upgrades. The upgrades would then be explained. They could have a condition like
|
and let them spend those coins on upgrades. The upgrades would then be explained. They could have a condition like
|
||||||
|
@ -177,27 +179,36 @@ and let them spend those coins on upgrades. The upgrades would then be explained
|
||||||
This requires recording a bit more info about each run.
|
This requires recording a bit more info about each run.
|
||||||
I could unlock the "pro stand" at $999 that just holds the play area higher.
|
I could unlock the "pro stand" at $999 that just holds the play area higher.
|
||||||
|
|
||||||
# bad ideas
|
# increase skill ceiling
|
||||||
-
|
|
||||||
- particles when bouncing on sides / top
|
- make puck smaller as combo increases ?
|
||||||
-
|
- nerf coin magnet :
|
||||||
|
- no effect when too close
|
||||||
|
- coins overshoot
|
||||||
|
- coins bounce and spread more ?
|
||||||
|
- add red anti-coins that apply downgrades
|
||||||
|
- destroy your combo
|
||||||
|
- hurt your score
|
||||||
|
- behave like heavier coins.
|
||||||
|
- deactivate a perk for this level
|
||||||
|
- reduce your number of coins
|
||||||
|
- destroy all coins on screen
|
||||||
|
- lowers your combo
|
||||||
|
- reduce your choice for your next perk
|
||||||
|
|
||||||
|
- final bosses (large vertical level that scrolls down faster and faster)
|
||||||
|
- when the player reaches the last level, allow them to loop the run, unlocking a permanent bonus for this run. For example: +5 combo, +1 life per loop… the counterpart would be hazards that slowly populate the levels.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Colin's feedback (cwpute/obigre)
|
# Colin's feedback (cwpute/obigre)
|
||||||
|
|
||||||
IMPROVEMENTS ON EXISTING PERKS :
|
|
||||||
|
|
||||||
* limit levels to only a handful of coulours, like 5 max, so that the colour-related perks are more viable.
|
|
||||||
|
|
||||||
GENERAL REMARKS ON DIFFERENT ASPECTS :
|
|
||||||
|
|
||||||
* when the player reaches the last level, alow them to loop the run, unlocking a permanent bonus for this run. For example: +5 combo, +1 life per loop… the counterpart would be hazards that slowly populate the levels.
|
|
||||||
* different visual effects on ball to represent which perks it's imbued with (pierce, sapper…). remove visual while it's not affected (can't pierce/sap anymore until touching the puck).
|
|
||||||
* always visually put the ball on top of coins so as to clearly see it. sometimes a black outline appears to distinguesh it from coins, this should be used more often imo.
|
|
||||||
* not brick-shaped bricks, or tilted bricks, that can bounce the ball into fun angles to spice up the game. or even moving blocks !
|
|
||||||
* reward the player with more choices/perks for breaking a brick while having reached an increasing combo thresholds. 5 combo, then 10, then 20, then 40 etc… once a threshold is reached you aren't rewarded for that threshold again until you start a rew run
|
* reward the player with more choices/perks for breaking a brick while having reached an increasing combo thresholds. 5 combo, then 10, then 20, then 40 etc… once a threshold is reached you aren't rewarded for that threshold again until you start a rew run
|
||||||
* inspired by Balatro's score system : have some perks add to the multiplicator, and some others to the amount of coins in a brick (or the raw value of coins inside), so that you users want to improve both for maximized profit ! maybe tie one of the to perks that help you, and the other to perks that are bad to you, so that gambling players are forced to make their life harder
|
* inspired by Balatro's score system : have some perks add to the multiplicator, and some others to the amount of coins in a brick (or the raw value of coins inside), so that you users want to improve both for maximized profit ! maybe tie one of the to perks that help you, and the other to perks that are bad to you, so that gambling players are forced to make their life harder
|
||||||
* the white outline on bricks asociated with picky eater kinda works but i feel it's more distracting than anything. maybe try something different ? put a cross on matching coloured bricks, or the contrary, grey out other bricks.
|
|
||||||
* also regarding colour : make it so the ball always start with a colour that matches one currently present in the level. sometimes you don't have white present and it's a waste of a combo :/
|
|
||||||
* negative coins, they would spawn from bricks as a hazard and do any of the following: -deactivate a perk for this level -reduce your number of coins -reduce your choice for your next perk -despawn all current coins on screen -lowers your combo. they could either be a negative perk with a bonus, like the small puck, or a hazard that spawns in later levels.
|
|
||||||
* the way combos look on the puck was better when you didn't see the coin visual on it ! now it easily overflows out of the puck with reduced visibility
|
|
||||||
|
|
||||||
|
|
||||||
|
# other
|
||||||
|
|
||||||
|
* not brick-shaped bricks, or tilted bricks, that can bounce the ball into fun angles to spice up the game. or even moving blocks !
|
||||||
|
|
2
dist/index.c0fd3053.js
vendored
2
dist/index.c0fd3053.js
vendored
File diff suppressed because one or more lines are too long
2
dist/index.c0fd3053.js.map
vendored
2
dist/index.c0fd3053.js.map
vendored
File diff suppressed because one or more lines are too long
358
dist/index.html
vendored
358
dist/index.html
vendored
File diff suppressed because one or more lines are too long
220
dist/levels_editor.ef3c2e1a.js
vendored
220
dist/levels_editor.ef3c2e1a.js
vendored
File diff suppressed because one or more lines are too long
2
dist/levels_editor.ef3c2e1a.js.map
vendored
2
dist/levels_editor.ef3c2e1a.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/levels_editor.html
vendored
2
dist/levels_editor.html
vendored
|
@ -1,6 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head><script src="/index.c0fd3053.js"></script>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Level editor</title>
|
<title>Level editor</title>
|
||||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎨</text></svg>">
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎨</text></svg>">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/** @type {import('ts-jest').JestConfigWithTsJest} **/
|
/** @type {import('ts-jest').JestConfigWithTsJest} **/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
testEnvironment: "node",
|
testEnvironment: "jsdom",
|
||||||
transform: {
|
transform: {
|
||||||
"^.+\.tsx?$": ["ts-jest",{}],
|
"^.+\.tsx?$": ["ts-jest",{}],
|
||||||
},
|
},
|
||||||
|
|
619
package-lock.json
generated
619
package-lock.json
generated
|
@ -15,6 +15,7 @@
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"nodemon": "^3.1.9",
|
"nodemon": "^3.1.9",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"parcel": "^2.13.3",
|
"parcel": "^2.13.3",
|
||||||
|
@ -737,7 +738,6 @@
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
|
||||||
"integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
|
"integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/fake-timers": "^29.7.0",
|
"@jest/fake-timers": "^29.7.0",
|
||||||
|
@ -780,7 +780,6 @@
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
|
||||||
"integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
|
"integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/types": "^29.6.3",
|
"@jest/types": "^29.6.3",
|
||||||
|
@ -858,7 +857,6 @@
|
||||||
"version": "29.6.3",
|
"version": "29.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
|
||||||
"integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
|
"integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sinclair/typebox": "^0.27.8"
|
"@sinclair/typebox": "^0.27.8"
|
||||||
|
@ -945,7 +943,6 @@
|
||||||
"version": "29.6.3",
|
"version": "29.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
|
||||||
"integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
|
"integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/schemas": "^29.6.3",
|
"@jest/schemas": "^29.6.3",
|
||||||
|
@ -2792,14 +2789,12 @@
|
||||||
"version": "0.27.8",
|
"version": "0.27.8",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||||
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
|
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@sinonjs/commons": {
|
"node_modules/@sinonjs/commons": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
|
||||||
"integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
|
"integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type-detect": "4.0.8"
|
"type-detect": "4.0.8"
|
||||||
|
@ -2809,7 +2804,6 @@
|
||||||
"version": "10.3.0",
|
"version": "10.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
|
||||||
"integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
|
"integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sinonjs/commons": "^3.0.0"
|
"@sinonjs/commons": "^3.0.0"
|
||||||
|
@ -3023,6 +3017,15 @@
|
||||||
"@swc/counter": "^0.1.3"
|
"@swc/counter": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@trysound/sax": {
|
"node_modules/@trysound/sax": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||||
|
@ -3090,14 +3093,12 @@
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||||
"integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
|
"integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/istanbul-lib-report": {
|
"node_modules/@types/istanbul-lib-report": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
|
||||||
"integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
|
"integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/istanbul-lib-coverage": "*"
|
"@types/istanbul-lib-coverage": "*"
|
||||||
|
@ -3107,7 +3108,6 @@
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
|
||||||
"integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
|
"integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/istanbul-lib-report": "*"
|
"@types/istanbul-lib-report": "*"
|
||||||
|
@ -3123,11 +3123,21 @@
|
||||||
"pretty-format": "^29.0.0"
|
"pretty-format": "^29.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/jsdom": {
|
||||||
|
"version": "20.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
|
||||||
|
"integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/tough-cookie": "*",
|
||||||
|
"parse5": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.13.10",
|
"version": "22.13.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
|
||||||
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
|
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.20.0"
|
"undici-types": "~6.20.0"
|
||||||
|
@ -3155,14 +3165,18 @@
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||||
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
|
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
|
||||||
"dev": true,
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/tough-cookie": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/yargs": {
|
"node_modules/@types/yargs": {
|
||||||
"version": "17.0.33",
|
"version": "17.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
||||||
"integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
|
"integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/yargs-parser": "*"
|
"@types/yargs-parser": "*"
|
||||||
|
@ -3172,9 +3186,15 @@
|
||||||
"version": "21.0.3",
|
"version": "21.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
|
||||||
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
|
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/abab": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
|
||||||
|
"deprecated": "Use your platform's native atob() and btoa() methods instead",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
|
@ -3187,6 +3207,75 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/acorn": {
|
||||||
|
"version": "8.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||||
|
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"acorn": "bin/acorn"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/acorn-globals": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.1.0",
|
||||||
|
"acorn-walk": "^8.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/acorn-walk": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.11.0"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/agent-base/node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/agent-base/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ansi-escapes": {
|
"node_modules/ansi-escapes": {
|
||||||
"version": "4.3.2",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||||
|
@ -3316,6 +3405,12 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/available-typed-arrays": {
|
"node_modules/available-typed-arrays": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||||
|
@ -3775,7 +3870,6 @@
|
||||||
"version": "3.9.0",
|
"version": "3.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
|
||||||
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
|
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
@ -3851,6 +3945,18 @@
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "12.1.0",
|
"version": "12.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||||
|
@ -4114,12 +4220,50 @@
|
||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
|
||||||
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="
|
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="
|
||||||
},
|
},
|
||||||
|
"node_modules/cssom": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/cssstyle": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"abab": "^2.0.6",
|
||||||
|
"whatwg-mimetype": "^3.0.0",
|
||||||
|
"whatwg-url": "^11.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/data-view-buffer": {
|
"node_modules/data-view-buffer": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||||
|
@ -4179,6 +4323,12 @@
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/decimal.js": {
|
||||||
|
"version": "10.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz",
|
||||||
|
"integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/dedent": {
|
"node_modules/dedent": {
|
||||||
"version": "1.5.3",
|
"version": "1.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
|
||||||
|
@ -4238,6 +4388,15 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
@ -4318,6 +4477,19 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"deprecated": "Use your platform's native DOMException instead",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"webidl-conversions": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/domhandler": {
|
"node_modules/domhandler": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||||
|
@ -4622,11 +4794,31 @@
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/escodegen": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"esprima": "^4.0.1",
|
||||||
|
"estraverse": "^5.2.0",
|
||||||
|
"esutils": "^2.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"escodegen": "bin/escodegen.js",
|
||||||
|
"esgenerate": "bin/esgenerate.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"source-map": "~0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/esprima": {
|
"node_modules/esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"bin": {
|
"bin": {
|
||||||
"esparse": "bin/esparse.js",
|
"esparse": "bin/esparse.js",
|
||||||
|
@ -4636,6 +4828,24 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/estraverse": {
|
||||||
|
"version": "5.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||||
|
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/esutils": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/etag": {
|
"node_modules/etag": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
|
@ -4954,6 +5164,21 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
|
@ -5419,6 +5644,43 @@
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tootallnate/once": "2",
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-proxy-agent/node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-proxy-agent/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/http-server": {
|
"node_modules/http-server": {
|
||||||
"version": "14.1.1",
|
"version": "14.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
|
||||||
|
@ -5445,6 +5707,42 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/https-proxy-agent/node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/https-proxy-agent/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/human-signals": {
|
"node_modules/human-signals": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||||
|
@ -5824,6 +6122,12 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-regex": {
|
"node_modules/is-regex": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
|
||||||
|
@ -6349,6 +6653,33 @@
|
||||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jest-environment-jsdom": {
|
||||||
|
"version": "29.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz",
|
||||||
|
"integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jest/environment": "^29.7.0",
|
||||||
|
"@jest/fake-timers": "^29.7.0",
|
||||||
|
"@jest/types": "^29.6.3",
|
||||||
|
"@types/jsdom": "^20.0.0",
|
||||||
|
"@types/node": "*",
|
||||||
|
"jest-mock": "^29.7.0",
|
||||||
|
"jest-util": "^29.7.0",
|
||||||
|
"jsdom": "^20.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"canvas": "^2.5.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"canvas": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jest-environment-node": {
|
"node_modules/jest-environment-node": {
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
|
||||||
|
@ -6437,7 +6768,6 @@
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
|
||||||
"integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
|
"integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.12.13",
|
"@babel/code-frame": "^7.12.13",
|
||||||
|
@ -6458,7 +6788,6 @@
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
|
||||||
"integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
|
"integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/types": "^29.6.3",
|
"@jest/types": "^29.6.3",
|
||||||
|
@ -6645,7 +6974,6 @@
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
|
||||||
"integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
|
"integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/types": "^29.6.3",
|
"@jest/types": "^29.6.3",
|
||||||
|
@ -6768,6 +7096,51 @@
|
||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsdom": {
|
||||||
|
"version": "20.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
|
||||||
|
"integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"abab": "^2.0.6",
|
||||||
|
"acorn": "^8.8.1",
|
||||||
|
"acorn-globals": "^7.0.0",
|
||||||
|
"cssom": "^0.5.0",
|
||||||
|
"cssstyle": "^2.3.0",
|
||||||
|
"data-urls": "^3.0.2",
|
||||||
|
"decimal.js": "^10.4.2",
|
||||||
|
"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.2",
|
||||||
|
"parse5": "^7.1.1",
|
||||||
|
"saxes": "^6.0.0",
|
||||||
|
"symbol-tree": "^3.2.4",
|
||||||
|
"tough-cookie": "^4.1.2",
|
||||||
|
"w3c-xmlserializer": "^4.0.0",
|
||||||
|
"webidl-conversions": "^7.0.0",
|
||||||
|
"whatwg-encoding": "^2.0.0",
|
||||||
|
"whatwg-mimetype": "^3.0.0",
|
||||||
|
"whatwg-url": "^11.0.0",
|
||||||
|
"ws": "^8.11.0",
|
||||||
|
"xml-name-validator": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"canvas": "^2.5.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"canvas": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsesc": {
|
"node_modules/jsesc": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
|
||||||
|
@ -7674,6 +8047,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
|
||||||
"integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="
|
"integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/nwsapi": {
|
||||||
|
"version": "2.2.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.18.tgz",
|
||||||
|
"integrity": "sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/object-inspect": {
|
"node_modules/object-inspect": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||||
|
@ -7905,6 +8284,30 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parse5": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"entities": "^4.5.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5/node_modules/entities": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/parseurl": {
|
"node_modules/parseurl": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
|
@ -8103,7 +8506,6 @@
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
|
||||||
"integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
|
"integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/schemas": "^29.6.3",
|
"@jest/schemas": "^29.6.3",
|
||||||
|
@ -8118,7 +8520,6 @@
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
|
@ -8169,11 +8570,32 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/psl": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "^2.3.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/lupomontero"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pstree.remy": {
|
"node_modules/pstree.remy": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
|
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/punycode": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pure-rand": {
|
"node_modules/pure-rand": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
|
||||||
|
@ -8205,6 +8627,12 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/querystringify": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/range-parser": {
|
"node_modules/range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
|
@ -8257,7 +8685,6 @@
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
|
@ -8499,6 +8926,18 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/saxes": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"xmlchars": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v12.22.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.25.0",
|
"version": "0.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
|
||||||
|
@ -8752,7 +9191,6 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
|
@ -8844,7 +9282,6 @@
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||||
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
|
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"escape-string-regexp": "^2.0.0"
|
"escape-string-regexp": "^2.0.0"
|
||||||
|
@ -8857,7 +9294,6 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||||
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
|
@ -9074,6 +9510,12 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/term-size": {
|
"node_modules/term-size": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
|
||||||
|
@ -9139,6 +9581,33 @@
|
||||||
"nodetouch": "bin/nodetouch.js"
|
"nodetouch": "bin/nodetouch.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tough-cookie": {
|
||||||
|
"version": "4.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
|
||||||
|
"integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"psl": "^1.1.33",
|
||||||
|
"punycode": "^2.1.1",
|
||||||
|
"universalify": "^0.2.0",
|
||||||
|
"url-parse": "^1.5.3"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-jest": {
|
"node_modules/ts-jest": {
|
||||||
"version": "29.2.6",
|
"version": "29.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.6.tgz",
|
||||||
|
@ -9196,7 +9665,6 @@
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||||
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
|
@ -9339,7 +9807,6 @@
|
||||||
"version": "6.20.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/union": {
|
"node_modules/union": {
|
||||||
|
@ -9353,6 +9820,15 @@
|
||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/universalify": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unpipe": {
|
"node_modules/unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
@ -9395,6 +9871,16 @@
|
||||||
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
||||||
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
|
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/url-parse": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"querystringify": "^2.1.1",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/utility-types": {
|
"node_modules/utility-types": {
|
||||||
"version": "3.11.0",
|
"version": "3.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz",
|
||||||
|
@ -9444,6 +9930,18 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/w3c-xmlserializer": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"xml-name-validator": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/walker": {
|
"node_modules/walker": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
||||||
|
@ -9459,6 +9957,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz",
|
||||||
"integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw=="
|
"integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw=="
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/whatwg-encoding": {
|
"node_modules/whatwg-encoding": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
||||||
|
@ -9481,6 +9988,28 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "^3.0.0",
|
||||||
|
"webidl-conversions": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
|
@ -9617,6 +10146,42 @@
|
||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
"body-parser": "^1.20.3",
|
"body-parser": "^1.20.3",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"nodemon": "^3.1.9",
|
"nodemon": "^3.1.9",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"parcel": "^2.13.3",
|
"parcel": "^2.13.3",
|
||||||
|
|
58
src/combo.ts
Normal file
58
src/combo.ts
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import {GameState} from "./types";
|
||||||
|
import {sounds} from "./sounds";
|
||||||
|
|
||||||
|
export function baseCombo(gameState: GameState) {
|
||||||
|
return 1 + gameState.perks.base_combo * 3 + gameState.perks.smaller_puck * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetCombo(gameState: GameState, x: number | undefined, y: number | undefined) {
|
||||||
|
const prev = gameState.combo;
|
||||||
|
gameState.combo = baseCombo(gameState);
|
||||||
|
if (!gameState.levelTime) {
|
||||||
|
gameState.combo += gameState.perks.hot_start * 15;
|
||||||
|
}
|
||||||
|
if (prev > gameState.combo && gameState.perks.soft_reset) {
|
||||||
|
gameState.combo += Math.floor((prev - gameState.combo) / (1 + gameState.perks.soft_reset));
|
||||||
|
}
|
||||||
|
const lost = Math.max(0, prev - gameState.combo);
|
||||||
|
if (lost) {
|
||||||
|
for (let i = 0; i < lost && i < 8; i++) {
|
||||||
|
setTimeout(() => sounds.comboDecrease(), i * 100);
|
||||||
|
}
|
||||||
|
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
||||||
|
gameState.flashes.push({
|
||||||
|
type: "text",
|
||||||
|
text: "-" + lost,
|
||||||
|
time: gameState.levelTime,
|
||||||
|
color: "red",
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
duration: 150,
|
||||||
|
size: gameState.puckHeight,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lost;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decreaseCombo(gameState: GameState, by: number, x: number, y: number) {
|
||||||
|
const prev = gameState.combo;
|
||||||
|
gameState.combo = Math.max(baseCombo(gameState), gameState.combo - by);
|
||||||
|
const lost = Math.max(0, prev - gameState.combo);
|
||||||
|
|
||||||
|
if (lost) {
|
||||||
|
sounds.comboDecrease();
|
||||||
|
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
||||||
|
gameState.flashes.push({
|
||||||
|
type: "text",
|
||||||
|
text: "-" + lost,
|
||||||
|
time: gameState.levelTime,
|
||||||
|
color: "red",
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
duration: 300,
|
||||||
|
size: gameState.puckHeight,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
144
src/game.ts
144
src/game.ts
|
@ -6,18 +6,19 @@ import {
|
||||||
colorString,
|
colorString,
|
||||||
GameState,
|
GameState,
|
||||||
PerkId,
|
PerkId,
|
||||||
PerksMap,
|
RunHistoryItem,
|
||||||
RunHistoryItem, RunParams,
|
RunParams,
|
||||||
RunStats,
|
RunStats,
|
||||||
Upgrade,
|
Upgrade,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
import {OptionId, options} from "./options";
|
import {OptionId, options} from "./options";
|
||||||
import {getAudioContext, getAudioRecordingTrack, sounds} from "./sounds";
|
import {getAudioContext, getAudioRecordingTrack, sounds} from "./sounds";
|
||||||
import {putBallsAtPuck, resetBalls} from "./resetBalls";
|
import {putBallsAtPuck, resetBalls} from "./resetBalls";
|
||||||
import {sumOfKeys} from "./game_utils";
|
import {makeEmptyPerksMap, sumOfKeys} from "./game_utils";
|
||||||
|
import {baseCombo, decreaseCombo, resetCombo} from "./combo";
|
||||||
|
|
||||||
|
|
||||||
export const gameCanvas = document.getElementById("game") as HTMLCanvasElement;
|
const gameCanvas = document.getElementById("game") as HTMLCanvasElement;
|
||||||
const ctx = gameCanvas.getContext("2d", {
|
const ctx = gameCanvas.getContext("2d", {
|
||||||
alpha: false,
|
alpha: false,
|
||||||
}) as CanvasRenderingContext2D;
|
}) as CanvasRenderingContext2D;
|
||||||
|
@ -29,69 +30,6 @@ bombSVG.src =
|
||||||
<path d="m6.1528 26.516c-2.6992-3.4942-2.9332-8.281-.58305-11.981a10.454 10.454 0 017.3701-4.7582c1.962-.27726 4.1646.05953 5.8835.90027l.45013.22017.89782-.87417c.83748-.81464.91169-.87499 1.0992-.90271.40528-.058713.58876.03425 1.1971.6116l.55451.52679 1.0821-1.0821c1.1963-1.1963 1.383-1.3357 2.1039-1.5877.57898-.20223 1.5681-.19816 2.1691.00897 1.4613.50314 2.3673 1.7622 2.3567 3.2773-.0058.95654-.24464 1.5795-.90924 2.3746-.40936.48928-.55533.81057-.57898 1.2737-.02039.41018.1109.77714.42322 1.1792.30172.38816.3694.61323.2797.93044-.12803.45666-.56674.71598-1.0242.60507-.601-.14597-1.3031-1.3088-1.3969-2.3126-.09459-1.0161.19245-1.8682.92392-2.7432.42567-.50885.5643-.82851.5643-1.3031 0-.50151-.14026-.83177-.51211-1.2028-.50966-.50966-1.0968-.64829-1.781-.41996l-.37348.12477-2.1006 2.1006.52597.55696c.45421.48194.5325.58876.57898.78855.09622.41588.07502.45014-.88396 1.4548l-.87173.9125.26339.57979a10.193 10.193 0 01.9231 4.1001c.03996 2.046-.41996 3.8082-1.4442 5.537-.55044.928-1.0185 1.5013-1.8968 2.3241-.83503.78284-1.5526 1.2827-2.4904 1.7361-3.4266 1.657-7.4721 1.3422-10.549-.82035-.73473-.51782-1.7312-1.4621-2.2515-2.1357zm21.869-4.5584c-.0579-.19734-.05871-2.2662 0-2.4545.11906-.39142.57898-.63361 1.0038-.53005.23812.05708.54147.32455.6116.5382.06279.19163.06769 2.1805.0065 2.3811-.12558.40773-.61649.67602-1.0462.57164-.234-.05708-.51615-.30498-.57568-.50722m3.0417-2.6013c-.12313-.6222.37837-1.1049 1.0479-1.0079.18348.0261.25279.08399 1.0071.83911.75838.75838.81301.82362.84074 1.0112.10193.68499-.40365 1.1938-1.034 1.0405-.1949-.0473-.28786-.12558-1.0144-.85216-.7649-.76409-.80241-.81057-.84645-1.0316m.61323-3.0629a.85623.85623 0 01.59284-.99975c.28949-.09214 2.1814-.08318 2.3917.01141.38734.17369.6279.61078.53984.98181-.06035.25606-.35391.57327-.60181.64992-.25279.07747-2.2278.053-2.4097-.03017-.26013-.11906-.46318-.36125-.51374-.61323" fill="#fff" opacity="0.3"/>
|
<path d="m6.1528 26.516c-2.6992-3.4942-2.9332-8.281-.58305-11.981a10.454 10.454 0 017.3701-4.7582c1.962-.27726 4.1646.05953 5.8835.90027l.45013.22017.89782-.87417c.83748-.81464.91169-.87499 1.0992-.90271.40528-.058713.58876.03425 1.1971.6116l.55451.52679 1.0821-1.0821c1.1963-1.1963 1.383-1.3357 2.1039-1.5877.57898-.20223 1.5681-.19816 2.1691.00897 1.4613.50314 2.3673 1.7622 2.3567 3.2773-.0058.95654-.24464 1.5795-.90924 2.3746-.40936.48928-.55533.81057-.57898 1.2737-.02039.41018.1109.77714.42322 1.1792.30172.38816.3694.61323.2797.93044-.12803.45666-.56674.71598-1.0242.60507-.601-.14597-1.3031-1.3088-1.3969-2.3126-.09459-1.0161.19245-1.8682.92392-2.7432.42567-.50885.5643-.82851.5643-1.3031 0-.50151-.14026-.83177-.51211-1.2028-.50966-.50966-1.0968-.64829-1.781-.41996l-.37348.12477-2.1006 2.1006.52597.55696c.45421.48194.5325.58876.57898.78855.09622.41588.07502.45014-.88396 1.4548l-.87173.9125.26339.57979a10.193 10.193 0 01.9231 4.1001c.03996 2.046-.41996 3.8082-1.4442 5.537-.55044.928-1.0185 1.5013-1.8968 2.3241-.83503.78284-1.5526 1.2827-2.4904 1.7361-3.4266 1.657-7.4721 1.3422-10.549-.82035-.73473-.51782-1.7312-1.4621-2.2515-2.1357zm21.869-4.5584c-.0579-.19734-.05871-2.2662 0-2.4545.11906-.39142.57898-.63361 1.0038-.53005.23812.05708.54147.32455.6116.5382.06279.19163.06769 2.1805.0065 2.3811-.12558.40773-.61649.67602-1.0462.57164-.234-.05708-.51615-.30498-.57568-.50722m3.0417-2.6013c-.12313-.6222.37837-1.1049 1.0479-1.0079.18348.0261.25279.08399 1.0071.83911.75838.75838.81301.82362.84074 1.0112.10193.68499-.40365 1.1938-1.034 1.0405-.1949-.0473-.28786-.12558-1.0144-.85216-.7649-.76409-.80241-.81057-.84645-1.0316m.61323-3.0629a.85623.85623 0 01.59284-.99975c.28949-.09214 2.1814-.08318 2.3917.01141.38734.17369.6279.61078.53984.98181-.06035.25606-.35391.57327-.60181.64992-.25279.07747-2.2278.053-2.4097-.03017-.26013-.11906-.46318-.36125-.51374-.61323" fill="#fff" opacity="0.3"/>
|
||||||
</svg>`);
|
</svg>`);
|
||||||
|
|
||||||
const makeEmptyPerksMap = () => {
|
|
||||||
const p = {} as any;
|
|
||||||
upgrades.forEach((u) => (p[u.id] = 0));
|
|
||||||
return p as PerksMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export function baseCombo() {
|
|
||||||
return 1 + gameState.perks.base_combo * 3 + gameState.perks.smaller_puck * 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resetCombo(x: number | undefined, y: number | undefined) {
|
|
||||||
const prev = gameState.combo;
|
|
||||||
gameState.combo = baseCombo();
|
|
||||||
if (!gameState.levelTime) {
|
|
||||||
gameState.combo += gameState.perks.hot_start * 15;
|
|
||||||
}
|
|
||||||
if (prev > gameState.combo && gameState.perks.soft_reset) {
|
|
||||||
gameState.combo += Math.floor((prev - gameState.combo) / (1 + gameState.perks.soft_reset));
|
|
||||||
}
|
|
||||||
const lost = Math.max(0, prev - gameState.combo);
|
|
||||||
if (lost) {
|
|
||||||
for (let i = 0; i < lost && i < 8; i++) {
|
|
||||||
setTimeout(() => sounds.comboDecrease(), i * 100);
|
|
||||||
}
|
|
||||||
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
|
||||||
gameState.flashes.push({
|
|
||||||
type: "text",
|
|
||||||
text: "-" + lost,
|
|
||||||
time: gameState.levelTime,
|
|
||||||
color: "red",
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
duration: 150,
|
|
||||||
size: gameState.puckHeight,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lost;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function decreaseCombo(by: number, x: number, y: number) {
|
|
||||||
const prev = gameState.combo;
|
|
||||||
gameState.combo = Math.max(baseCombo(), gameState.combo - by);
|
|
||||||
const lost = Math.max(0, prev - gameState.combo);
|
|
||||||
|
|
||||||
if (lost) {
|
|
||||||
sounds.comboDecrease();
|
|
||||||
if (typeof x !== "undefined" && typeof y !== "undefined") {
|
|
||||||
gameState.flashes.push({
|
|
||||||
type: "text",
|
|
||||||
text: "-" + lost,
|
|
||||||
time: gameState.levelTime,
|
|
||||||
color: "red",
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
duration: 300,
|
|
||||||
size: gameState.puckHeight,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function play() {
|
export function play() {
|
||||||
if (gameState.running) return;
|
if (gameState.running) return;
|
||||||
|
@ -341,7 +279,7 @@ async function openUpgradesPicker() {
|
||||||
|
|
||||||
gameState.runStatistics.upgrades_picked++;
|
gameState.runStatistics.upgrades_picked++;
|
||||||
}
|
}
|
||||||
resetCombo(undefined, undefined);
|
resetCombo(gameState, undefined, undefined);
|
||||||
resetBalls(gameState);
|
resetBalls(gameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +299,7 @@ export function setLevel(l: number) {
|
||||||
gameState.levelMisses = 0;
|
gameState.levelMisses = 0;
|
||||||
gameState.runStatistics.levelsPlayed++;
|
gameState.runStatistics.levelsPlayed++;
|
||||||
|
|
||||||
resetCombo(undefined, undefined);
|
resetCombo(gameState, undefined, undefined);
|
||||||
recomputeTargetBaseSpeed();
|
recomputeTargetBaseSpeed();
|
||||||
resetBalls(gameState);
|
resetBalls(gameState);
|
||||||
|
|
||||||
|
@ -536,7 +474,7 @@ export function shouldPierceByColor(
|
||||||
|
|
||||||
export function coinBrickHitCheck(coin: Coin) {
|
export function coinBrickHitCheck(coin: Coin) {
|
||||||
// Make ball/coin bonce, and return bricks that were hit
|
// Make ball/coin bonce, and return bricks that were hit
|
||||||
const radius = gameState.coinSize / 2;
|
const radius = coin.size / 2;
|
||||||
const {x, y, previousX, previousY} = coin;
|
const {x, y, previousX, previousY} = coin;
|
||||||
|
|
||||||
const vhit = hitsSomething(previousX, y, radius);
|
const vhit = hitsSomething(previousX, y, radius);
|
||||||
|
@ -646,7 +584,7 @@ export function tick() {
|
||||||
|
|
||||||
if (gameState.levelTime > gameState.lastTickDown + 1000 && gameState.perks.hot_start) {
|
if (gameState.levelTime > gameState.lastTickDown + 1000 && gameState.perks.hot_start) {
|
||||||
gameState.lastTickDown = gameState.levelTime;
|
gameState.lastTickDown = gameState.levelTime;
|
||||||
decreaseCombo(gameState.perks.hot_start, gameState.puckPosition, gameState.gameZoneHeight - 2 * gameState.puckHeight);
|
decreaseCombo(gameState, gameState.perks.hot_start, gameState.puckPosition, gameState.gameZoneHeight - 2 * gameState.puckHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remainingBricks <= gameState.perks.skip_last && !gameState.autoCleanUses) {
|
if (remainingBricks <= gameState.perks.skip_last && !gameState.autoCleanUses) {
|
||||||
|
@ -662,8 +600,8 @@ export function tick() {
|
||||||
setLevel(gameState.currentLevel + 1);
|
setLevel(gameState.currentLevel + 1);
|
||||||
} else {
|
} else {
|
||||||
gameOver(
|
gameOver(
|
||||||
"Run finished with " + gameState.score + " points",
|
"Run finished ",
|
||||||
"You cleared all levels for this run.",
|
`You cleared all levels for this run, catching ${gameState.score} coins in total.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (gameState.running || gameState.levelTime) {
|
} else if (gameState.running || gameState.levelTime) {
|
||||||
|
@ -698,7 +636,7 @@ export function tick() {
|
||||||
coin.vy += delta * coin.weight * 0.8;
|
coin.vy += delta * coin.weight * 0.8;
|
||||||
|
|
||||||
const speed = Math.abs(coin.sx) + Math.abs(coin.sx);
|
const speed = Math.abs(coin.sx) + Math.abs(coin.sx);
|
||||||
const hitBorder = bordersHitCheck(coin, coinRadius, delta);
|
const hitBorder = bordersHitCheck(coin, coin.size / 2, delta);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
coin.y > gameState.gameZoneHeight - coinRadius - gameState.puckHeight &&
|
coin.y > gameState.gameZoneHeight - coinRadius - gameState.puckHeight &&
|
||||||
|
@ -712,7 +650,7 @@ export function tick() {
|
||||||
} else if (coin.y > gameState.canvasHeight + coinRadius) {
|
} else if (coin.y > gameState.canvasHeight + coinRadius) {
|
||||||
coin.destroyed = true;
|
coin.destroyed = true;
|
||||||
if (gameState.perks.compound_interest) {
|
if (gameState.perks.compound_interest) {
|
||||||
resetCombo(coin.x, coin.y);
|
resetCombo(gameState, coin.x, coin.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,6 +665,7 @@ export function tick() {
|
||||||
) {
|
) {
|
||||||
gameState.bricks[hitBrick] = coin.color;
|
gameState.bricks[hitBrick] = coin.color;
|
||||||
coin.coloredABrick = true;
|
coin.coloredABrick = true;
|
||||||
|
sounds.colorChange(coin.x,0.3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof hitBrick !== "undefined" || hitBorder) {
|
if (typeof hitBrick !== "undefined" || hitBorder) {
|
||||||
|
@ -783,10 +722,10 @@ export function tick() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.combo > baseCombo()) {
|
if (gameState.combo > baseCombo(gameState)) {
|
||||||
// The red should still be visible on a white bg
|
// The red should still be visible on a white bg
|
||||||
const baseParticle = !isSettingOn("basic") &&
|
const baseParticle = !isSettingOn("basic") &&
|
||||||
(gameState.combo - baseCombo()) * Math.random() > 5 &&
|
(gameState.combo - baseCombo(gameState)) * Math.random() > 5 &&
|
||||||
gameState.running && {
|
gameState.running && {
|
||||||
type: "particle" as const,
|
type: "particle" as const,
|
||||||
duration: 100 * (Math.random() + 1),
|
duration: 100 * (Math.random() + 1),
|
||||||
|
@ -955,7 +894,7 @@ export function ballTick(ball: Ball, delta: number) {
|
||||||
borderHitCode % 2 &&
|
borderHitCode % 2 &&
|
||||||
ball.x < gameState.offsetX + gameState.gameZoneWidth / 2
|
ball.x < gameState.offsetX + gameState.gameZoneWidth / 2
|
||||||
) {
|
) {
|
||||||
resetCombo(ball.x, ball.y);
|
resetCombo(gameState, ball.x, ball.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -963,11 +902,11 @@ export function ballTick(ball: Ball, delta: number) {
|
||||||
borderHitCode % 2 &&
|
borderHitCode % 2 &&
|
||||||
ball.x > gameState.offsetX + gameState.gameZoneWidth / 2
|
ball.x > gameState.offsetX + gameState.gameZoneWidth / 2
|
||||||
) {
|
) {
|
||||||
resetCombo(ball.x, ball.y);
|
resetCombo(gameState, ball.x, ball.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.perks.top_is_lava && borderHitCode >= 2) {
|
if (gameState.perks.top_is_lava && borderHitCode >= 2) {
|
||||||
resetCombo(ball.x, ball.y + gameState.ballSize);
|
resetCombo(gameState, ball.x, ball.y + gameState.ballSize);
|
||||||
}
|
}
|
||||||
sounds.wallBeep(ball.x);
|
sounds.wallBeep(ball.x);
|
||||||
ball.bouncesList?.push({x: ball.previousX, y: ball.previousY});
|
ball.bouncesList?.push({x: ball.previousX, y: ball.previousY});
|
||||||
|
@ -1010,7 +949,7 @@ export function ballTick(ball: Ball, delta: number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gameState.perks.streak_shots) {
|
if (gameState.perks.streak_shots) {
|
||||||
resetCombo(ball.x, ball.y);
|
resetCombo(gameState, ball.x, ball.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.perks.respawn) {
|
if (gameState.perks.respawn) {
|
||||||
|
@ -1025,7 +964,7 @@ export function ballTick(ball: Ball, delta: number) {
|
||||||
if (!ball.hitSinceBounce) {
|
if (!ball.hitSinceBounce) {
|
||||||
gameState.runStatistics.misses++;
|
gameState.runStatistics.misses++;
|
||||||
gameState.levelMisses++;
|
gameState.levelMisses++;
|
||||||
resetCombo(ball.x, ball.y);
|
resetCombo(gameState, ball.x, ball.y);
|
||||||
gameState.flashes.push({
|
gameState.flashes.push({
|
||||||
type: "text",
|
type: "text",
|
||||||
text: "miss",
|
text: "miss",
|
||||||
|
@ -1245,6 +1184,11 @@ export function gameOver(title: string, intro: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let unlockedItems = list.filter((u) => u.threshold > startTs && u.threshold < endTs);
|
||||||
|
if (unlockedItems.length) {
|
||||||
|
unlocksInfo += `<p>You unlocked ${unlockedItems.length} item(s) : ${unlockedItems.map(u => u.title).join(', ')}</p>`
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid the sad sound right as we restart a new games
|
// Avoid the sad sound right as we restart a new games
|
||||||
gameState.combo = 1;
|
gameState.combo = 1;
|
||||||
|
|
||||||
|
@ -1254,6 +1198,7 @@ export function gameOver(title: string, intro: string) {
|
||||||
text: `
|
text: `
|
||||||
${gameState.isCreativeModeRun ? "<p>This test run and its score are not being recorded</p>" : ""}
|
${gameState.isCreativeModeRun ? "<p>This test run and its score are not being recorded</p>" : ""}
|
||||||
<p>${intro}</p>
|
<p>${intro}</p>
|
||||||
|
<p>Your total cumulative score went from ${startTs} to ${endTs}.</p>
|
||||||
${unlocksInfo}
|
${unlocksInfo}
|
||||||
`,
|
`,
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -1480,6 +1425,7 @@ export function explodeBrick(index: number, ball: Ball, isExplosion: boolean) {
|
||||||
|
|
||||||
gameState.coins.push({
|
gameState.coins.push({
|
||||||
points,
|
points,
|
||||||
|
size: gameState.coinSize,//-Math.floor(Math.log2(points)),
|
||||||
color: gameState.perks.metamorphosis ? color : "gold",
|
color: gameState.perks.metamorphosis ? color : "gold",
|
||||||
x: cx,
|
x: cx,
|
||||||
y: cy,
|
y: cy,
|
||||||
|
@ -1515,10 +1461,16 @@ export function explodeBrick(index: number, ball: Ball, isExplosion: boolean) {
|
||||||
color
|
color
|
||||||
) {
|
) {
|
||||||
if (gameState.perks.picky_eater) {
|
if (gameState.perks.picky_eater) {
|
||||||
resetCombo(ball.x, ball.y);
|
resetCombo(gameState, ball.x, ball.y);
|
||||||
}
|
}
|
||||||
|
sounds.colorChange(ball.x,0.8)
|
||||||
|
gameState.lastExplosion=gameState.levelTime
|
||||||
gameState.ballsColor = color;
|
gameState.ballsColor = color;
|
||||||
|
if(!isSettingOn('basic')) {
|
||||||
|
gameState.balls.forEach(ball=>{
|
||||||
|
spawnExplosion(7, ball.previousX, ball.previousY, color, 150, 15)
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sounds.comboIncreaseMaybe(gameState.combo, ball.x, 1);
|
sounds.comboIncreaseMaybe(gameState.combo, ball.x, 1);
|
||||||
}
|
}
|
||||||
|
@ -1668,7 +1620,7 @@ export function render() {
|
||||||
drawCoin(
|
drawCoin(
|
||||||
ctx,
|
ctx,
|
||||||
coin.color,
|
coin.color,
|
||||||
gameState.coinSize,
|
coin.size,
|
||||||
coin.x,
|
coin.x,
|
||||||
coin.y,
|
coin.y,
|
||||||
level.color || "black",
|
level.color || "black",
|
||||||
|
@ -1738,7 +1690,7 @@ export function render() {
|
||||||
// The puck
|
// The puck
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
ctx.globalCompositeOperation = "source-over";
|
ctx.globalCompositeOperation = "source-over";
|
||||||
if (gameState.perks.streak_shots && gameState.combo > baseCombo()) {
|
if (gameState.perks.streak_shots && gameState.combo > baseCombo(gameState)) {
|
||||||
drawPuck(ctx, "red", gameState.puckWidth, gameState.puckHeight, -2);
|
drawPuck(ctx, "red", gameState.puckWidth, gameState.puckHeight, -2);
|
||||||
}
|
}
|
||||||
drawPuck(ctx, gameState.puckColor, gameState.puckWidth, gameState.puckHeight);
|
drawPuck(ctx, gameState.puckColor, gameState.puckWidth, gameState.puckHeight);
|
||||||
|
@ -1781,7 +1733,7 @@ export function render() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Borders
|
// Borders
|
||||||
const hasCombo = gameState.combo > baseCombo();
|
const hasCombo = gameState.combo > baseCombo(gameState);
|
||||||
ctx.globalCompositeOperation = "source-over";
|
ctx.globalCompositeOperation = "source-over";
|
||||||
if (gameState.offsetXRoundedDown) {
|
if (gameState.offsetXRoundedDown) {
|
||||||
// draw outside of gaming area to avoid capturing borders in recordings
|
// draw outside of gaming area to avoid capturing borders in recordings
|
||||||
|
@ -1795,11 +1747,11 @@ export function render() {
|
||||||
if (hasCombo && gameState.perks.right_is_lava) ctx.fillRect(width - 1, 0, 1, height);
|
if (hasCombo && gameState.perks.right_is_lava) ctx.fillRect(width - 1, 0, 1, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameState.perks.top_is_lava && gameState.combo > baseCombo()) {
|
if (gameState.perks.top_is_lava && gameState.combo > baseCombo(gameState)) {
|
||||||
ctx.fillStyle = "red";
|
ctx.fillStyle = "red";
|
||||||
ctx.fillRect(gameState.offsetXRoundedDown, 0, gameState.gameZoneWidthRoundedUp, 1);
|
ctx.fillRect(gameState.offsetXRoundedDown, 0, gameState.gameZoneWidthRoundedUp, 1);
|
||||||
}
|
}
|
||||||
const redBottom = gameState.perks.compound_interest && gameState.combo > baseCombo();
|
const redBottom = gameState.perks.compound_interest && gameState.combo > baseCombo(gameState);
|
||||||
ctx.fillStyle = redBottom ? "red" : gameState.puckColor;
|
ctx.fillStyle = redBottom ? "red" : gameState.puckColor;
|
||||||
if (isSettingOn("mobile-mode")) {
|
if (isSettingOn("mobile-mode")) {
|
||||||
ctx.fillRect(gameState.offsetXRoundedDown, gameState.gameZoneHeight, gameState.gameZoneWidthRoundedUp, 1);
|
ctx.fillRect(gameState.offsetXRoundedDown, gameState.gameZoneHeight, gameState.gameZoneWidthRoundedUp, 1);
|
||||||
|
@ -1837,7 +1789,7 @@ export function renderAllBricks() {
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
|
|
||||||
const redBorderOnBricksWithWrongColor =
|
const redBorderOnBricksWithWrongColor =
|
||||||
gameState.combo > baseCombo() && gameState.perks.picky_eater;
|
gameState.combo > baseCombo(gameState) && gameState.perks.picky_eater;
|
||||||
|
|
||||||
const newKey =
|
const newKey =
|
||||||
gameState.gameZoneWidth +
|
gameState.gameZoneWidth +
|
||||||
|
@ -2447,11 +2399,11 @@ async function openSettingsPanel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions.push({
|
actions.push({
|
||||||
text: "Creative mode",
|
text: "Sandbox mode",
|
||||||
help:
|
help:
|
||||||
getTotalScore() < creativeModeThreshold
|
getTotalScore() < creativeModeThreshold
|
||||||
? "Unlocks at total score $" + creativeModeThreshold
|
? "Unlocks at total score $" + creativeModeThreshold
|
||||||
: "Test runs with custom perks",
|
: "Test any perk combination",
|
||||||
disabled: getTotalScore() < creativeModeThreshold,
|
disabled: getTotalScore() < creativeModeThreshold,
|
||||||
async value() {
|
async value() {
|
||||||
let creativeModePerks: Partial<{ [id in PerkId]: number }> = {},
|
let creativeModePerks: Partial<{ [id in PerkId]: number }> = {},
|
||||||
|
@ -2549,7 +2501,7 @@ async function openUnlocksList() {
|
||||||
help:
|
help:
|
||||||
ts >= threshold ? fullHelp : `Unlocks at total score ${threshold}.`,
|
ts >= threshold ? fullHelp : `Unlocks at total score ${threshold}.`,
|
||||||
disabled: ts < threshold,
|
disabled: ts < threshold,
|
||||||
value: {perk: id} as RunParams,
|
value: {perks: {[id]: 1}} as RunParams,
|
||||||
icon,
|
icon,
|
||||||
})),
|
})),
|
||||||
...allLevels
|
...allLevels
|
||||||
|
@ -2944,7 +2896,7 @@ document.addEventListener("keydown", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener("keyup", (e) => {
|
document.addEventListener("keyup", async (e) => {
|
||||||
const focused = document.querySelector("button:focus");
|
const focused = document.querySelector("button:focus");
|
||||||
if (e.key in pressed) {
|
if (e.key in pressed) {
|
||||||
setKeyPressed(e.key, 0);
|
setKeyPressed(e.key, 0);
|
||||||
|
@ -2966,6 +2918,8 @@ document.addEventListener("keyup", (e) => {
|
||||||
openSettingsPanel();
|
openSettingsPanel();
|
||||||
} else if (e.key.toLowerCase() === "s" && !alertsOpen) {
|
} else if (e.key.toLowerCase() === "s" && !alertsOpen) {
|
||||||
openScorePanel();
|
openScorePanel();
|
||||||
|
} else if (e.key.toLowerCase() === "r" && !alertsOpen) {
|
||||||
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2987,7 +2941,7 @@ function newGameState(params: RunParams): GameState {
|
||||||
restInRandomOrder.slice(0, 7 + 3).sort((a, b) => a.sortKey - b.sortKey),
|
restInRandomOrder.slice(0, 7 + 3).sort((a, b) => a.sortKey - b.sortKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
const perks = {...makeEmptyPerksMap(), ...(params?.perks || {})}
|
const perks = {...makeEmptyPerksMap(upgrades), ...(params?.perks || {})}
|
||||||
|
|
||||||
const gameState: GameState = {
|
const gameState: GameState = {
|
||||||
runLevels,
|
runLevels,
|
||||||
|
|
42
src/game_utils.test.ts
Normal file
42
src/game_utils.test.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import {getMajorityValue, sample, sumOfKeys} from "./game_utils";
|
||||||
|
|
||||||
|
describe('getMajorityValue', ()=>{
|
||||||
|
|
||||||
|
it('returns the most common string',()=>{
|
||||||
|
expect(getMajorityValue(['1','1','2','2','3','2','3','2','2','1'])).toStrictEqual('2')
|
||||||
|
})
|
||||||
|
it('returns the only string',()=>{
|
||||||
|
expect(getMajorityValue(['1'])).toStrictEqual('1')
|
||||||
|
})
|
||||||
|
it('returns nothing for empty array',()=>{
|
||||||
|
expect(getMajorityValue([])).toStrictEqual(undefined)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
describe('sample', ()=>{
|
||||||
|
|
||||||
|
it('returns a random pick from the array',()=>{
|
||||||
|
expect(['1','2','3'].includes(sample(['1','2','3']))).toBeTruthy()
|
||||||
|
})
|
||||||
|
it('returns the only item if there is just one',()=>{
|
||||||
|
expect(sample(['1'])).toStrictEqual('1')
|
||||||
|
})
|
||||||
|
it('returns nothing for empty array',()=>{
|
||||||
|
expect(sample([])).toStrictEqual(undefined)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
describe('sumOfKeys', ()=>{
|
||||||
|
it('returns the sum of the keys of an array',()=>{
|
||||||
|
expect(sumOfKeys({a:1,b:2})).toEqual(3)
|
||||||
|
})
|
||||||
|
it('returns 0 for an empty object',()=>{
|
||||||
|
expect(sumOfKeys({})).toEqual(0)
|
||||||
|
})
|
||||||
|
it('returns 0 for undefined',()=>{
|
||||||
|
expect(sumOfKeys(undefined)).toEqual(0)
|
||||||
|
})
|
||||||
|
it('returns 0 for null',()=>{
|
||||||
|
expect(sumOfKeys(null)).toEqual(0)
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
import {PerksMap, Upgrade} from "./types";
|
||||||
|
|
||||||
export function getMajorityValue(arr: string[]): string {
|
export function getMajorityValue(arr: string[]): string {
|
||||||
const count: { [k: string]: number } = {};
|
const count: { [k: string]: number } = {};
|
||||||
|
@ -16,4 +17,10 @@ export function sample<T>(arr: T[]): T {
|
||||||
export function sumOfKeys(obj:{[key:string]:number} | undefined | null){
|
export function sumOfKeys(obj:{[key:string]:number} | undefined | null){
|
||||||
if(!obj) return 0
|
if(!obj) return 0
|
||||||
return Object.values(obj)?.reduce((a,b)=>a+b,0) ||0
|
return Object.values(obj)?.reduce((a,b)=>a+b,0) ||0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const makeEmptyPerksMap = (upgrades:Upgrade[]) => {
|
||||||
|
const p = {} as any;
|
||||||
|
upgrades.forEach((u) => (p[u.id] = 0));
|
||||||
|
return p as PerksMap;
|
||||||
|
};
|
|
@ -41,7 +41,7 @@
|
||||||
{
|
{
|
||||||
"name": "Dots",
|
"name": "Dots",
|
||||||
"size": 9,
|
"size": 9,
|
||||||
"bricks": "b_t_a_c_C__________b_t_a_c__________v_b_t_a_c__________v_b_t_a__________p_v_b_t_a",
|
"bricks": "b_t_a_c____________b_t_a_c__________P_b_t_a_c__________P_b_t_a____________P_b_t_a",
|
||||||
"svg": null
|
"svg": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
{
|
{
|
||||||
"name": "Temple",
|
"name": "Temple",
|
||||||
"size": 11,
|
"size": 11,
|
||||||
"bricks": "_______________WWW______WWWWWWW___WWWWWWWWW___t_t_t_t____b_b_b_b____v_v_v_v____p_p_p_p____P_P_P_P____WWWWWWW___WWWWWWWWW_",
|
"bricks": "_______________WWW______WWWWWWW___WWWWWWWWW___b_b_b_b____b_b_b_b____v_v_v_v____P_P_P_P____P_P_P_P____WWWWWWW___WWWWWWWWW_",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
{
|
{
|
||||||
"name": "Ship",
|
"name": "Ship",
|
||||||
"size": 11,
|
"size": 11,
|
||||||
"bricks": "____sWW________sWWW_______sWWW_______s___OOOOOOOOOOOOOO_OBOBOBOBOO__OOOOOOOO_bbbbbbbbgbbbbgbbbbggbbbggbbbbbbbb",
|
"bricks": "____sWW________sWWW_______sWWW_______s___OOOOOOOOOOOOOO_OBOBOBOBOO__OOOOOOOO_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb___________",
|
||||||
"svg": 19
|
"svg": 19
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -279,7 +279,7 @@
|
||||||
{
|
{
|
||||||
"name": "Ocean Sunrise",
|
"name": "Ocean Sunrise",
|
||||||
"size": 8,
|
"size": 8,
|
||||||
"bricks": "SSSSSSSSSSSyySSSSSyyyySSSyyWWyySbttaattbbbttttbbbbbttbbbbbbbbbbb",
|
"bricks": "SSSSSSSSSSSyySSSSSyyyySSSyyyyyySbttttttbbbttttbbbbbttbbbbbbbbbbb",
|
||||||
"svg": 12,
|
"svg": 12,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
@ -648,7 +648,7 @@
|
||||||
{
|
{
|
||||||
"name": "Bird",
|
"name": "Bird",
|
||||||
"size": 13,
|
"size": 13,
|
||||||
"bricks": "_______RRR____R____RSSSR___RR__RSSWWWR__RSR_RSWWBWR__RSSRRSW_WWyy_RSSSRSWWWR___RSSSSSSRR_____RRSSyyyy______RSyyyyy___RRRRSyyyy____RSSSRyyy_____RRRR________",
|
"bricks": "_______RRR____R____RSSSR___RR__RSSWWWR__RSR_RSWWBWR__RSSRRSWWWWyy_RSSSRSWWWR___RSSSSSSRR_____RRSSyyyy______RSyyyyy___RRRRSyyyy____RSSSRyyy_____RRRR______________________",
|
||||||
"svg": null,
|
"svg": null,
|
||||||
"color": ""
|
"color": ""
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,7 +45,10 @@ function App() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return <div onMouseUp={() => setApplying('')} onMouseLeave={() => setApplying('')}>
|
return <div onMouseUp={() => {
|
||||||
|
console.log('mouse up')
|
||||||
|
setApplying('')
|
||||||
|
}} >
|
||||||
<div id={"levels"}>
|
<div id={"levels"}>
|
||||||
{
|
{
|
||||||
levels.map((level, li) => {
|
levels.map((level, li) => {
|
||||||
|
@ -58,9 +61,12 @@ function App() {
|
||||||
brickButtons.push(<button
|
brickButtons.push(<button
|
||||||
key={index}
|
key={index}
|
||||||
onMouseDown={() => {
|
onMouseDown={() => {
|
||||||
const color = selected === bricks[index] ? '_' : applying
|
if(!applying){
|
||||||
setApplying(color)
|
console.log(selected, bricks[index],applying)
|
||||||
updateLevel(li, setBrick(level, index, color))
|
const color = selected === bricks[index] ? '_' : selected
|
||||||
|
setApplying(color)
|
||||||
|
updateLevel(li, setBrick(level, index, color))
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
if (applying) {
|
if (applying) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ export function moveLevel(level: RawLevel, dx: number, dy: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBrick(level: RawLevel, index: number, colorCode: string) {
|
export function setBrick(level: RawLevel, index: number, colorCode: string) {
|
||||||
|
console.log('setBrick', level.name, index, colorCode)
|
||||||
const {size} = level
|
const {size} = level
|
||||||
const newBricks=[]
|
const newBricks=[]
|
||||||
for (let x = 0; x < size; x++) {
|
for (let x = 0; x < size; x++) {
|
||||||
|
|
28
src/loadGameData.test.ts
Normal file
28
src/loadGameData.test.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
import _palette from "./palette.json";
|
||||||
|
import _rawLevelsList from "./levels.json";
|
||||||
|
import _appVersion from "./version.json";
|
||||||
|
|
||||||
|
describe('json data checks', ()=>{
|
||||||
|
it('_rawLevelsList has icon levels', ()=>{
|
||||||
|
expect(_rawLevelsList.filter(l=>l.name.startsWith('icon:')).length).toBeGreaterThan(10)
|
||||||
|
})
|
||||||
|
it('_rawLevelsList has non-icon few levels', ()=>{
|
||||||
|
expect(_rawLevelsList.filter(l=>!l.name.startsWith('icon:')).length).toBeGreaterThan(10)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('_rawLevelsList has max 5 colors per level', ()=>{
|
||||||
|
const levelsWithManyBrickColors=_rawLevelsList.filter(l=>{
|
||||||
|
|
||||||
|
const uniqueBricks = l.bricks.split('').filter(b=>b!=='_' && b!=='black').filter((a,b,c)=>c.indexOf(a)===b)
|
||||||
|
return uniqueBricks.length>5
|
||||||
|
}).map(l=>l.name)
|
||||||
|
expect(levelsWithManyBrickColors).toEqual([])
|
||||||
|
})
|
||||||
|
it('Has a few colors', ()=>{
|
||||||
|
expect(Object.keys(_palette).length).toBeGreaterThan(10)
|
||||||
|
})
|
||||||
|
it('Has an _appVersion', ()=>{
|
||||||
|
expect(parseInt(_appVersion)).toBeGreaterThan(2000)
|
||||||
|
})
|
||||||
|
})
|
|
@ -19,7 +19,6 @@ const levelIconHTMLCanvasCtx = levelIconHTMLCanvas.getContext("2d", {
|
||||||
function levelIconHTML(
|
function levelIconHTML(
|
||||||
bricks: string[],
|
bricks: string[],
|
||||||
levelSize: number,
|
levelSize: number,
|
||||||
levelName: string,
|
|
||||||
color: string,
|
color: string,
|
||||||
) {
|
) {
|
||||||
const size = 40;
|
const size = 40;
|
||||||
|
@ -49,8 +48,8 @@ function levelIconHTML(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// I don't think many blind people will benefit for this, but it's nice to have something to put in "alt"
|
|
||||||
return `<img alt="${levelName}" width="${size}" height="${size}" src="${c.toDataURL()}"/>`;
|
return `<img alt="" width="${size}" height="${size}" src="${c.toDataURL()}"/>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const icons = {} as { [k: string]: string };
|
export const icons = {} as { [k: string]: string };
|
||||||
|
@ -61,7 +60,7 @@ export const allLevels = rawLevelsList
|
||||||
.split("")
|
.split("")
|
||||||
.map((c) => palette[c])
|
.map((c) => palette[c])
|
||||||
.slice(0, level.size * level.size);
|
.slice(0, level.size * level.size);
|
||||||
const icon = levelIconHTML(bricks, level.size, level.name, level.color);
|
const icon = levelIconHTML(bricks, level.size, level.color);
|
||||||
icons[level.name] = icon;
|
icons[level.name] = icon;
|
||||||
return {
|
return {
|
||||||
...level,
|
...level,
|
||||||
|
|
340
src/sounds.ts
340
src/sounds.ts
|
@ -1,233 +1,237 @@
|
||||||
import {
|
import {
|
||||||
gameState,
|
gameState,
|
||||||
isSettingOn,
|
isSettingOn,
|
||||||
} from "./game";
|
} from "./game";
|
||||||
|
|
||||||
export const sounds = {
|
export const sounds = {
|
||||||
wallBeep: (pan: number) => {
|
wallBeep: (pan: number) => {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
createSingleBounceSound(800, pixelsToPan(pan));
|
createSingleBounceSound(800, pixelsToPan(pan));
|
||||||
},
|
},
|
||||||
|
|
||||||
comboIncreaseMaybe: (combo: number, x: number, volume: number) => {
|
comboIncreaseMaybe: (combo: number, x: number, volume: number) => {
|
||||||
if (!isSettingOn("sound")) return;
|
if (!isSettingOn("sound")) return;
|
||||||
let delta = 0;
|
let delta = 0;
|
||||||
if (!isNaN(lastComboPlayed)) {
|
if (!isNaN(lastComboPlayed)) {
|
||||||
if (lastComboPlayed < combo) delta = 1;
|
if (lastComboPlayed < combo) delta = 1;
|
||||||
if (lastComboPlayed > combo) delta = -1;
|
if (lastComboPlayed > combo) delta = -1;
|
||||||
|
}
|
||||||
|
playShepard(delta, pixelsToPan(x), volume);
|
||||||
|
lastComboPlayed = combo;
|
||||||
|
},
|
||||||
|
|
||||||
|
comboDecrease() {
|
||||||
|
if (!isSettingOn("sound")) return;
|
||||||
|
playShepard(-1, 0.5, 0.5);
|
||||||
|
},
|
||||||
|
coinBounce: (pan: number, volume: number) => {
|
||||||
|
if (!isSettingOn("sound")) return;
|
||||||
|
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
||||||
|
},
|
||||||
|
explode: (pan: number) => {
|
||||||
|
if (!isSettingOn("sound")) return;
|
||||||
|
createExplosionSound(pixelsToPan(pan));
|
||||||
|
},
|
||||||
|
lifeLost(pan: number) {
|
||||||
|
if (!isSettingOn("sound")) return;
|
||||||
|
createShatteredGlassSound(pixelsToPan(pan));
|
||||||
|
},
|
||||||
|
|
||||||
|
coinCatch(pan: number) {
|
||||||
|
if (!isSettingOn("sound")) return;
|
||||||
|
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
||||||
|
},
|
||||||
|
colorChange(pan: number, volume: number) {
|
||||||
|
createSingleBounceSound(400, pixelsToPan(pan), volume , 0.5, "sine")
|
||||||
|
createSingleBounceSound(800, pixelsToPan(pan), volume * 0.5, 0.2, "square")
|
||||||
}
|
}
|
||||||
playShepard(delta, pixelsToPan(x), volume);
|
|
||||||
lastComboPlayed = combo;
|
|
||||||
},
|
|
||||||
|
|
||||||
comboDecrease() {
|
|
||||||
if (!isSettingOn("sound")) return;
|
|
||||||
playShepard(-1, 0.5, 0.5);
|
|
||||||
},
|
|
||||||
coinBounce: (pan: number, volume: number) => {
|
|
||||||
if (!isSettingOn("sound")) return;
|
|
||||||
createSingleBounceSound(1200, pixelsToPan(pan), volume, 0.1, "triangle");
|
|
||||||
},
|
|
||||||
explode: (pan: number) => {
|
|
||||||
if (!isSettingOn("sound")) return;
|
|
||||||
createExplosionSound(pixelsToPan(pan));
|
|
||||||
},
|
|
||||||
lifeLost(pan: number) {
|
|
||||||
if (!isSettingOn("sound")) return;
|
|
||||||
createShatteredGlassSound(pixelsToPan(pan));
|
|
||||||
},
|
|
||||||
|
|
||||||
coinCatch(pan: number) {
|
|
||||||
if (!isSettingOn("sound")) return;
|
|
||||||
createSingleBounceSound(900, pixelsToPan(pan), 0.8, 0.1, "triangle");
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// How to play the code on the leftconst context = new window.AudioContext();
|
// How to play the code on the leftconst context = new window.AudioContext();
|
||||||
let audioContext: AudioContext,
|
let audioContext: AudioContext,
|
||||||
audioRecordingTrack: MediaStreamAudioDestinationNode;
|
audioRecordingTrack: MediaStreamAudioDestinationNode;
|
||||||
|
|
||||||
export function getAudioContext() {
|
export function getAudioContext() {
|
||||||
if (!audioContext) {
|
if (!audioContext) {
|
||||||
if (!isSettingOn("sound")) return null;
|
if (!isSettingOn("sound")) return null;
|
||||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
audioRecordingTrack = audioContext.createMediaStreamDestination();
|
audioRecordingTrack = audioContext.createMediaStreamDestination();
|
||||||
}
|
}
|
||||||
return audioContext;
|
return audioContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAudioRecordingTrack() {
|
export function getAudioRecordingTrack() {
|
||||||
getAudioContext();
|
getAudioContext();
|
||||||
return audioRecordingTrack;
|
return audioRecordingTrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSingleBounceSound(
|
function createSingleBounceSound(
|
||||||
baseFreq = 800,
|
baseFreq = 800,
|
||||||
pan = 0.5,
|
pan = 0.5,
|
||||||
volume = 1,
|
volume = 1,
|
||||||
duration = 0.1,
|
duration = 0.1,
|
||||||
type: OscillatorType = "sine",
|
type: OscillatorType = "sine",
|
||||||
) {
|
) {
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
if (!context) return;
|
if (!context) return;
|
||||||
const oscillator = createOscillator(context, baseFreq, type);
|
const oscillator = createOscillator(context, baseFreq, type);
|
||||||
|
|
||||||
// Create a gain node to control the volume
|
// Create a gain node to control the volume
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
oscillator.connect(gainNode);
|
oscillator.connect(gainNode);
|
||||||
|
|
||||||
// Create a stereo panner node for left-right panning
|
// Create a stereo panner node for left-right panning
|
||||||
const panner = context.createStereoPanner();
|
const panner = context.createStereoPanner();
|
||||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
||||||
gainNode.connect(panner);
|
gainNode.connect(panner);
|
||||||
panner.connect(context.destination);
|
panner.connect(context.destination);
|
||||||
panner.connect(audioRecordingTrack);
|
panner.connect(audioRecordingTrack);
|
||||||
|
|
||||||
// Set up the gain envelope to simulate the impact and quick decay
|
// Set up the gain envelope to simulate the impact and quick decay
|
||||||
gainNode.gain.setValueAtTime(0.8 * volume, context.currentTime); // Initial impact
|
gainNode.gain.setValueAtTime(0.8 * volume, context.currentTime); // Initial impact
|
||||||
gainNode.gain.exponentialRampToValueAtTime(
|
gainNode.gain.exponentialRampToValueAtTime(
|
||||||
0.001,
|
0.001,
|
||||||
context.currentTime + duration,
|
context.currentTime + duration,
|
||||||
); // Quick decay
|
); // Quick decay
|
||||||
|
|
||||||
// Start the oscillator
|
// Start the oscillator
|
||||||
oscillator.start(context.currentTime);
|
oscillator.start(context.currentTime);
|
||||||
|
|
||||||
// Stop the oscillator after the decay
|
// Stop the oscillator after the decay
|
||||||
oscillator.stop(context.currentTime + duration);
|
oscillator.stop(context.currentTime + duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
let noiseBuffer: AudioBuffer;
|
let noiseBuffer: AudioBuffer;
|
||||||
|
|
||||||
function getNoiseBuffer(context: AudioContext) {
|
function getNoiseBuffer(context: AudioContext) {
|
||||||
if (!noiseBuffer) {
|
if (!noiseBuffer) {
|
||||||
const bufferSize = context.sampleRate * 2; // 2 seconds
|
const bufferSize = context.sampleRate * 2; // 2 seconds
|
||||||
noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate);
|
noiseBuffer = context.createBuffer(1, bufferSize, context.sampleRate);
|
||||||
const output = noiseBuffer.getChannelData(0);
|
const output = noiseBuffer.getChannelData(0);
|
||||||
|
|
||||||
// Fill the buffer with random noise
|
// Fill the buffer with random noise
|
||||||
for (let i = 0; i < bufferSize; i++) {
|
for (let i = 0; i < bufferSize; i++) {
|
||||||
output[i] = Math.random() * 2 - 1;
|
output[i] = Math.random() * 2 - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return noiseBuffer;
|
||||||
return noiseBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createExplosionSound(pan = 0.5) {
|
function createExplosionSound(pan = 0.5) {
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
if (!context) return;
|
if (!context) return;
|
||||||
// Create an audio buffer
|
// Create an audio buffer
|
||||||
|
|
||||||
// Create a noise source
|
// Create a noise source
|
||||||
const noiseSource = context.createBufferSource();
|
const noiseSource = context.createBufferSource();
|
||||||
noiseSource.buffer = getNoiseBuffer(context);
|
noiseSource.buffer = getNoiseBuffer(context);
|
||||||
|
|
||||||
// Create a gain node to control the volume
|
// Create a gain node to control the volume
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
noiseSource.connect(gainNode);
|
noiseSource.connect(gainNode);
|
||||||
|
|
||||||
// Create a filter to shape the explosion sound
|
// Create a filter to shape the explosion sound
|
||||||
const filter = context.createBiquadFilter();
|
const filter = context.createBiquadFilter();
|
||||||
filter.type = "lowpass";
|
filter.type = "lowpass";
|
||||||
filter.frequency.setValueAtTime(1000, context.currentTime); // Set the initial frequency
|
filter.frequency.setValueAtTime(1000, context.currentTime); // Set the initial frequency
|
||||||
gainNode.connect(filter);
|
gainNode.connect(filter);
|
||||||
|
|
||||||
// Create a stereo panner node for left-right panning
|
// Create a stereo panner node for left-right panning
|
||||||
const panner = context.createStereoPanner();
|
const panner = context.createStereoPanner();
|
||||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime); // pan 0 to 1 maps to -1 to 1
|
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime); // pan 0 to 1 maps to -1 to 1
|
||||||
|
|
||||||
// Connect filter to panner and then to the destination (speakers)
|
// Connect filter to panner and then to the destination (speakers)
|
||||||
filter.connect(panner);
|
filter.connect(panner);
|
||||||
panner.connect(context.destination);
|
panner.connect(context.destination);
|
||||||
panner.connect(audioRecordingTrack);
|
panner.connect(audioRecordingTrack);
|
||||||
|
|
||||||
// Ramp down the gain to simulate the explosion's fade-out
|
// Ramp down the gain to simulate the explosion's fade-out
|
||||||
gainNode.gain.setValueAtTime(1, context.currentTime);
|
gainNode.gain.setValueAtTime(1, context.currentTime);
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.01, context.currentTime + 1);
|
gainNode.gain.exponentialRampToValueAtTime(0.01, context.currentTime + 1);
|
||||||
|
|
||||||
// Lower the filter frequency over time to create the "explosive" effect
|
// Lower the filter frequency over time to create the "explosive" effect
|
||||||
filter.frequency.exponentialRampToValueAtTime(60, context.currentTime + 1);
|
filter.frequency.exponentialRampToValueAtTime(60, context.currentTime + 1);
|
||||||
|
|
||||||
// Start the noise source
|
// Start the noise source
|
||||||
noiseSource.start(context.currentTime);
|
noiseSource.start(context.currentTime);
|
||||||
|
|
||||||
// Stop the noise source after the sound has played
|
// Stop the noise source after the sound has played
|
||||||
noiseSource.stop(context.currentTime + 1);
|
noiseSource.stop(context.currentTime + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function pixelsToPan(pan: number) {
|
function pixelsToPan(pan: number) {
|
||||||
return Math.max(
|
return Math.max(
|
||||||
0,
|
0,
|
||||||
Math.min(1, (pan - gameState.offsetXRoundedDown) / gameState.gameZoneWidthRoundedUp),
|
Math.min(1, (pan - gameState.offsetXRoundedDown) / gameState.gameZoneWidthRoundedUp),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastComboPlayed = NaN,
|
let lastComboPlayed = NaN,
|
||||||
shepard = 6;
|
shepard = 6;
|
||||||
|
|
||||||
function playShepard(delta: number, pan: number, volume: number) {
|
function playShepard(delta: number, pan: number, volume: number) {
|
||||||
const shepardMax = 11,
|
const shepardMax = 11,
|
||||||
factor = 1.05945594920268,
|
factor = 1.05945594920268,
|
||||||
baseNote = 392;
|
baseNote = 392;
|
||||||
shepard += delta;
|
shepard += delta;
|
||||||
if (shepard > shepardMax) shepard = 0;
|
if (shepard > shepardMax) shepard = 0;
|
||||||
if (shepard < 0) shepard = shepardMax;
|
if (shepard < 0) shepard = shepardMax;
|
||||||
|
|
||||||
const play = (note: number) => {
|
const play = (note: number) => {
|
||||||
const freq = baseNote * Math.pow(factor, note);
|
const freq = baseNote * Math.pow(factor, note);
|
||||||
const diff = Math.abs(note - shepardMax * 0.5);
|
const diff = Math.abs(note - shepardMax * 0.5);
|
||||||
const maxDistanceToIdeal = 1.5 * shepardMax;
|
const maxDistanceToIdeal = 1.5 * shepardMax;
|
||||||
const vol = Math.max(0, volume * (1 - diff / maxDistanceToIdeal));
|
const vol = Math.max(0, volume * (1 - diff / maxDistanceToIdeal));
|
||||||
createSingleBounceSound(freq, pan, vol);
|
createSingleBounceSound(freq, pan, vol);
|
||||||
return freq.toFixed(2) + " at " + Math.floor(vol * 100) + "% diff " + diff;
|
return freq.toFixed(2) + " at " + Math.floor(vol * 100) + "% diff " + diff;
|
||||||
};
|
};
|
||||||
|
|
||||||
play(1 + shepardMax + shepard);
|
play(1 + shepardMax + shepard);
|
||||||
play(shepard);
|
play(shepard);
|
||||||
play(-1 - shepardMax + shepard);
|
play(-1 - shepardMax + shepard);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createShatteredGlassSound(pan: number) {
|
function createShatteredGlassSound(pan: number) {
|
||||||
const context = getAudioContext();
|
const context = getAudioContext();
|
||||||
if (!context) return;
|
if (!context) return;
|
||||||
const oscillators = [
|
const oscillators = [
|
||||||
createOscillator(context, 3000, "square"),
|
createOscillator(context, 3000, "square"),
|
||||||
createOscillator(context, 4500, "square"),
|
createOscillator(context, 4500, "square"),
|
||||||
createOscillator(context, 6000, "square"),
|
createOscillator(context, 6000, "square"),
|
||||||
];
|
];
|
||||||
const gainNode = context.createGain();
|
const gainNode = context.createGain();
|
||||||
const noiseSource = context.createBufferSource();
|
const noiseSource = context.createBufferSource();
|
||||||
noiseSource.buffer = getNoiseBuffer(context);
|
noiseSource.buffer = getNoiseBuffer(context);
|
||||||
|
|
||||||
oscillators.forEach((oscillator) => oscillator.connect(gainNode));
|
oscillators.forEach((oscillator) => oscillator.connect(gainNode));
|
||||||
noiseSource.connect(gainNode);
|
noiseSource.connect(gainNode);
|
||||||
gainNode.gain.setValueAtTime(0.2, context.currentTime);
|
gainNode.gain.setValueAtTime(0.2, context.currentTime);
|
||||||
oscillators.forEach((oscillator) => oscillator.start());
|
oscillators.forEach((oscillator) => oscillator.start());
|
||||||
noiseSource.start();
|
noiseSource.start();
|
||||||
oscillators.forEach((oscillator) =>
|
oscillators.forEach((oscillator) =>
|
||||||
oscillator.stop(context.currentTime + 0.2),
|
oscillator.stop(context.currentTime + 0.2),
|
||||||
);
|
);
|
||||||
noiseSource.stop(context.currentTime + 0.2);
|
noiseSource.stop(context.currentTime + 0.2);
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.2);
|
gainNode.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.2);
|
||||||
|
|
||||||
// Create a stereo panner node for left-right panning
|
// Create a stereo panner node for left-right panning
|
||||||
const panner = context.createStereoPanner();
|
const panner = context.createStereoPanner();
|
||||||
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
panner.pan.setValueAtTime(pan * 2 - 1, context.currentTime);
|
||||||
gainNode.connect(panner);
|
gainNode.connect(panner);
|
||||||
panner.connect(context.destination);
|
panner.connect(context.destination);
|
||||||
panner.connect(audioRecordingTrack);
|
panner.connect(audioRecordingTrack);
|
||||||
|
|
||||||
gainNode.connect(panner);
|
gainNode.connect(panner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to create an oscillator with a specific frequency
|
// Helper function to create an oscillator with a specific frequency
|
||||||
function createOscillator(
|
function createOscillator(
|
||||||
context: AudioContext,
|
context: AudioContext,
|
||||||
frequency: number,
|
frequency: number,
|
||||||
type: OscillatorType,
|
type: OscillatorType,
|
||||||
) {
|
) {
|
||||||
const oscillator = context.createOscillator();
|
const oscillator = context.createOscillator();
|
||||||
oscillator.type = type;
|
oscillator.type = type;
|
||||||
oscillator.frequency.setValueAtTime(frequency, context.currentTime);
|
oscillator.frequency.setValueAtTime(frequency, context.currentTime);
|
||||||
return oscillator;
|
return oscillator;
|
||||||
}
|
}
|
||||||
|
|
1
src/types.d.ts
vendored
1
src/types.d.ts
vendored
|
@ -69,6 +69,7 @@ export type Coin = {
|
||||||
color: colorString;
|
color: colorString;
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
|
size: number;
|
||||||
previousX: number;
|
previousX: number;
|
||||||
previousY: number;
|
previousY: number;
|
||||||
vx: number;
|
vx: number;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue