From 6b3ca662bf88c239c2b67033eefe3ddaf7f1f957 Mon Sep 17 00:00:00 2001 From: Frederik <112972665+FrederikFraJylland@users.noreply.github.com> Date: Fri, 14 Oct 2022 07:37:38 +0200 Subject: [PATCH 01/47] Fixed misspelling Fixed misspelling of word in the line " "stat.shootingRunSpeedCharging"" --- public/locales/da/analyzer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/da/analyzer.json b/public/locales/da/analyzer.json index 8fb7f5001..32abbb2b4 100644 --- a/public/locales/da/analyzer.json +++ b/public/locales/da/analyzer.json @@ -29,7 +29,7 @@ "stat.runSpeedInEnemyInk": "Løbehastighed i fjendtligt blæk", "stat.shootingRunSpeed": "Løbehastighed under skydning", "stat.shootingRunSpeedCharging": "Løbehastighed under opladning (af skud)", - "stat.shootingRunSpeedFullCharge": "Løbehastig (ved fuld ladning af våben)", + "stat.shootingRunSpeedFullCharge": "Løbehastighed (ved fuld ladning af våben)", "stat.framesBeforeTakingDamageInEnemyInk": "Mængde af tid i billeder/frames, før at du begynder at tage skade af at stå i fjendens blæk", "stat.damageTakenInEnemyInkPerSecond": "Skaden fra fjendtligt blæk per sekund", "stat.enemyInkDamageLimit": "Maksimal mængde skade man kan tage af fjendtligt blæk", From 586c27eaa775023f9b9a90f385f2eca34ef2e179 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Tue, 18 Oct 2022 01:12:52 +0300 Subject: [PATCH 02/47] Object damage calculator page initial --- app/modules/analyzer/constants.ts | 30 + app/modules/analyzer/damageMultipliers.ts | 74 + app/modules/analyzer/index.ts | 4 +- app/modules/analyzer/object-dmg.json | 5579 +++++++++++++++++++++ app/modules/analyzer/stats.ts | 10 +- app/modules/analyzer/types.ts | 15 +- app/modules/analyzer/useAnalyzeBuild.ts | 21 +- app/modules/analyzer/useObjectDamage.ts | 48 + app/modules/analyzer/utils.ts | 17 +- app/routes/object-damage.tsx | 34 + package.json | 1 + scripts/create-object-dmg-json.ts | 55 + 12 files changed, 5852 insertions(+), 36 deletions(-) create mode 100644 app/modules/analyzer/damageMultipliers.ts create mode 100644 app/modules/analyzer/object-dmg.json create mode 100644 app/modules/analyzer/useObjectDamage.ts create mode 100644 app/routes/object-damage.tsx create mode 100644 scripts/create-object-dmg-json.ts diff --git a/app/modules/analyzer/constants.ts b/app/modules/analyzer/constants.ts index 89b7e959a..031244f12 100644 --- a/app/modules/analyzer/constants.ts +++ b/app/modules/analyzer/constants.ts @@ -1,2 +1,32 @@ export const MAX_LDE_INTENSITY = 21; export const MAX_AP = 57; + +export const DAMAGE_RECEIVERS = [ + "Bomb_TorpedoBullet", // Torpedo + "Chariot", // Crab Tank + "Gachihoko_Barrier", // Rainmaker Shield + "GreatBarrier_Barrier", // Big Bubbler Shield + "GreatBarrier_WeakPoint", // Big Bubbler Weak Point + "InkRail", // InkRail + "NiceBall_Armor", // Booyah Bomb Armor + "ShockSonar", // Wave Breaker + "Sponge_Versus", // Sponge + "Wsb_Flag", // Squid Beakon + "Wsb_Shield", // Splash Wall + "Wsb_Sprinkler", // Sprinkler + "BulletUmbrellaCanopyCompact", // Undercover Brella Canopy + "BulletUmbrellaCanopyNormal", // Splat Brella Canopy + "BulletUmbrellaCanopyWide", // Tenta Brella Canopy +] as const; + +export const DAMAGE_TYPE = [ + "NORMAL_MIN", + "NORMAL_MAX", + "DIRECT", + "FULL_CHARGE", + "MAX_CHARGE", + "TAP_SHOT", + "DISTANCE", + "BOMB_NORMAL", + "BOMB_DIRECT", +] as const; diff --git a/app/modules/analyzer/damageMultipliers.ts b/app/modules/analyzer/damageMultipliers.ts new file mode 100644 index 000000000..b83fa374e --- /dev/null +++ b/app/modules/analyzer/damageMultipliers.ts @@ -0,0 +1,74 @@ +import type { DamageType } from "./types"; +import objectDamages from "./object-dmg.json"; +import type { + MainWeaponId, + SpecialWeaponId, + SubWeaponId, +} from "../in-game-lists"; +import { DAMAGE_RECEIVERS } from "./constants"; + +const objectDamageJsonKeyPriority: Record< + DamageType, + Array +> = { + NORMAL_MIN: ["Shooter"], + NORMAL_MAX: ["Shooter"], + DIRECT: [], + FULL_CHARGE: [], + MAX_CHARGE: [], + TAP_SHOT: [], + DISTANCE: [], + BOMB_NORMAL: [], + BOMB_DIRECT: [], +}; + +export function damageTypeToMultipliers({ + type, + weapon, +}: { + type: DamageType; + weapon: + | { + type: "MAIN"; + id: MainWeaponId; + } + | { + type: "SUB"; + id: SubWeaponId; + } + | { + type: "SPECIAL"; + id: SpecialWeaponId; + }; +}) { + for (const key of objectDamageJsonKeyPriority[type]) { + const objectDamagesObj = objectDamages[key]; + + let ok = false; + + if (weapon.type === "MAIN") { + ok = (objectDamagesObj.mainWeaponIds as MainWeaponId[]).includes( + weapon.id + ); + } else if (weapon.type === "SUB") { + ok = (objectDamagesObj.subWeaponIds as SubWeaponId[]).includes(weapon.id); + } else if (weapon.type === "SPECIAL") { + ok = (objectDamagesObj.specialWeaponIds as SpecialWeaponId[]).includes( + weapon.id + ); + } + + if (ok) return objectDamagesObj.rates; + } + + return null; +} + +export function fallbackRates( + multipliers: ReturnType +) { + return DAMAGE_RECEIVERS.map((receiver) => ({ + target: receiver, + rate: multipliers?.find((m) => m.target === receiver)?.rate ?? 1, + })); +} diff --git a/app/modules/analyzer/index.ts b/app/modules/analyzer/index.ts index c60392b72..31afacf81 100644 --- a/app/modules/analyzer/index.ts +++ b/app/modules/analyzer/index.ts @@ -9,6 +9,8 @@ export type { export { useAnalyzeBuild } from "./useAnalyzeBuild"; -export { MAX_LDE_INTENSITY } from "./constants"; +export { useObjectDamage } from "./useObjectDamage"; + +export { MAX_LDE_INTENSITY, DAMAGE_RECEIVERS, DAMAGE_TYPE } from "./constants"; export { lastDitchEffortIntensityToAp } from "./specialEffects"; diff --git a/app/modules/analyzer/object-dmg.json b/app/modules/analyzer/object-dmg.json new file mode 100644 index 000000000..d5f332f4b --- /dev/null +++ b/app/modules/analyzer/object-dmg.json @@ -0,0 +1,5579 @@ +{ + "Blaster_BlasterMiddle": { + "mainWeaponIds": [20900, 210, 20210, 10210, 30200, 30210], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.6 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.9 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.9 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.9 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnBoxL", + "rate": 10 + }, + { + "target": "MsnBoxS", + "rate": 10 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 1.5 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "Blaster_BlasterShort": { + "mainWeaponIds": [200, 20200, 10200], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3.6 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.1 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnBoxL", + "rate": 10 + }, + { + "target": "MsnBoxS", + "rate": 10 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 1.5 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "Blaster_KillOneShot": { + "mainWeaponIds": [ + 20900, 220, 20220, 10220, 210, 20210, 10210, 30200, 30210, 20200, 10200 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.6 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.9 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.9 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.9 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnBoxL", + "rate": 10 + }, + { + "target": "MsnBoxS", + "rate": 10 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 1.5 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "Blaster": { + "mainWeaponIds": [ + 250, 20250, 10250, 230, 20230, 10230, 240, 20240, 10240, 220, 20220, 10220 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.6 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.1 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnBoxL", + "rate": 10 + }, + { + "target": "MsnBoxS", + "rate": 10 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 1.5 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "BlowerExhale_BombCore": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [8, 10008], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 7 + }, + { + "target": "Chariot", + "rate": 2.8 + }, + { + "target": "Gachihoko_Barrier", + "rate": 5.6 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 5.6 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.8 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 4 + }, + { + "target": "ShockSonar", + "rate": 5.6 + }, + { + "target": "Sponge_Versus", + "rate": 5.6 + }, + { + "target": "Wsb_Flag", + "rate": 5.6 + }, + { + "target": "Wsb_Shield", + "rate": 5.6 + }, + { + "target": "Wsb_Sprinkler", + "rate": 5.6 + } + ] + }, + "BlowerInhale": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [8, 10008], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + } + ] + }, + "BombFlower": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + } + ] + }, + "Bomb_CurlingBullet": { + "mainWeaponIds": [], + "subWeaponIds": [6, 11006, 10006, 30006], + "specialWeaponIds": [], + "rates": [ + { + "target": "AttractTarget", + "rate": 1 + }, + { + "target": "Bomb_TorpedoBullet", + "rate": 0.5 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "MsnGoal", + "rate": 5 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "Bomb_DirectHit": { + "mainWeaponIds": [], + "subWeaponIds": [ + 2, 11002, 10002, 30002, 7, 10007, 30007, 0, 21000, 20000, 11000, 10000, + 30000 + ], + "specialWeaponIds": [], + "rates": [ + { + "target": "AttractTarget", + "rate": 1 + }, + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 1 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.5 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Bomb_Fizzy": { + "mainWeaponIds": [], + "subWeaponIds": [5], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 3.6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3.6 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 3.6 + }, + { + "target": "Chariot", + "rate": 1.6 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3.6 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3.6 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.9 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnBoxL", + "rate": 5 + }, + { + "target": "MsnBoxS", + "rate": 4 + }, + { + "target": "MsnGoal", + "rate": 5 + }, + { + "target": "NiceBall_Armor", + "rate": 2.4 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "ShockSonar", + "rate": 1.8 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 3.2 + }, + { + "target": "Wsb_Shield", + "rate": 3.6 + }, + { + "target": "Wsb_Sprinkler", + "rate": 3.2 + } + ] + }, + "Bomb_Suction": { + "mainWeaponIds": [], + "subWeaponIds": [1, 10001], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.5 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 5 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Bomb_TorpedoBullet": { + "mainWeaponIds": [], + "subWeaponIds": [13], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 4 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 4 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 4 + }, + { + "target": "Chariot", + "rate": 2 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 5 + }, + { + "target": "NiceBall_Armor", + "rate": 2.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 3 + }, + { + "target": "Wsb_Flag", + "rate": 3 + }, + { + "target": "Wsb_Shield", + "rate": 4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 3 + } + ] + }, + "Bomb_TorpedoSplashBurst": { + "mainWeaponIds": [], + "subWeaponIds": [13], + "specialWeaponIds": [], + "rates": [ + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "Propeller", + "rate": 5 + } + ] + }, + "Bomb_Trap": { + "mainWeaponIds": [], + "subWeaponIds": [10, 10010], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnEnemyEscape", + "rate": 2.5 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Bomb": { + "mainWeaponIds": [], + "subWeaponIds": [ + 6, 11006, 10006, 30006, 2, 11002, 10002, 30002, 7, 10007, 30007, 0, 21000, + 20000, 11000, 10000, 30000 + ], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 1 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.5 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "BrushCore": { + "mainWeaponIds": [1100, 21100, 11100, 1110, 21110, 11110, 31100, 31110], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "CoopGoldenIkuraBox", + "rate": 1 + }, + { + "target": "CoopSpawnBox", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "InkRail", + "rate": 12 + }, + { + "target": "MsnBoxHard", + "rate": 0.6 + }, + { + "target": "MsnBoxL", + "rate": 100 + }, + { + "target": "MsnBoxS", + "rate": 100 + }, + { + "target": "MsnGoal", + "rate": 6 + }, + { + "target": "Sponge_Versus", + "rate": 2.189 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "BrushSplash": { + "mainWeaponIds": [1100, 21100, 11100, 1110, 21110, 11110, 31100, 31110], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.5 + }, + { + "target": "Chariot", + "rate": 1.4 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.8 + }, + { + "target": "MsnBoxHard", + "rate": 0.8 + }, + { + "target": "MsnGoal", + "rate": 4 + }, + { + "target": "NiceBall_Armor", + "rate": 1.4 + }, + { + "target": "ShockSonar", + "rate": 1.8 + }, + { + "target": "Sponge_Versus", + "rate": 1.8 + }, + { + "target": "Wsb_Flag", + "rate": 1.8 + }, + { + "target": "Wsb_Shield", + "rate": 1.8 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1.8 + } + ] + }, + "CannonMissile": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + } + ] + }, + "ChargerFull_Light": { + "mainWeaponIds": [22900, 2050, 22050, 12050], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 0.8 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 0.9 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 1.6 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 1.6 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "ChargerFull_Long": { + "mainWeaponIds": [2040, 12040, 2030, 22030, 12030], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2.4 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.3 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.3 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.725 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.35 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2.2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2.2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "ChargerFull": { + "mainWeaponIds": [ + 2060, 22060, 12060, 2020, 12020, 2010, 22010, 12010, 2000, 22000, 12000 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.5 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Charger_Light": { + "mainWeaponIds": [22900, 2050, 22050, 12050], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 0.8 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 0.9 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 1.6 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 1.6 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Charger_Long": { + "mainWeaponIds": [2040, 12040, 2030, 22030, 12030], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2.4 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.35 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2.2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2.2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Charger": { + "mainWeaponIds": [ + 2060, 22060, 12060, 2020, 12020, 2010, 22010, 12010, 2000, 22000, 12000 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Chariot_Body": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [12, 20012, 10012], + "rates": [ + { + "target": "EnemyRockBall", + "rate": 10 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 1 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Shield", + "rate": 100 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "Chariot_Cannon": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [12, 20012, 10012], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 3 + }, + { + "target": "Chariot", + "rate": 1.5 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.5 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnEnemyShield", + "rate": 20 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 3 + }, + { + "target": "Sponge_Versus", + "rate": 3 + }, + { + "target": "Wsb_Flag", + "rate": 3 + }, + { + "target": "Wsb_Shield", + "rate": 3 + }, + { + "target": "Wsb_Sprinkler", + "rate": 3 + } + ] + }, + "Default": { + "mainWeaponIds": [ + 20900, 220, 20220, 10220, 210, 20210, 10210, 30200, 30210, 20200, 10200, + 1100, 21100, 11100, 1110, 21110, 11110, 31100, 31110, 22900, 2060, 22060, + 12060, 2050, 22050, 12050, 2040, 12040, 2030, 42030, 22030, 12030, 2020, + 12020, 2010, 22010, 12010, 2000, 22000, 12000, 40000, 1000, 21000, 11000, + 1020, 21020, 11020, 1030, 21030, 11030, 1010, 21010, 11010, 31000, 31010, + 26900, 6020, 26020, 16020, 6000, 26000, 16000, 36000, 36010, 6010, 26010, + 16010, 40040, 40042, 40041 + ], + "subWeaponIds": [8, 6, 11006, 10006, 30006, 12, 10012, 9, 11, 10100], + "specialWeaponIds": [ + 12, 20012, 10012, 15, 20, 2, 30002, 10100, 7, 20007, 10007, 30007 + ], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 1 + } + ] + }, + "EnemyFlyingHohei_BombCore": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "Propeller", + "rate": 5 + } + ] + }, + "GachihokoTimeUpBurst": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 1 + } + ] + }, + "Gachihoko_BombCore": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [20], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.5 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "Gachihoko_Bullet": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [20], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.75 + }, + { + "target": "Propeller", + "rate": 1 + } + ] + }, + "Geyser": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + } + ] + }, + "GoldenIkuraAttack": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + } + ] + }, + "InkStormRain": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [5, 30005], + "rates": [ + { + "target": "BlowerInhale", + "rate": 1 + } + ] + }, + "InkStorm": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [5, 10005, 30005], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.25 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 3 + }, + { + "target": "Chariot", + "rate": 2.5 + }, + { + "target": "Gachihoko_Barrier", + "rate": 5 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 5 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 5 + }, + { + "target": "NiceBall_Armor", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 3 + }, + { + "target": "Sponge_Versus", + "rate": 5 + }, + { + "target": "Wsb_Shield", + "rate": 3 + } + ] + }, + "Jetpack_BombCore": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [10], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 3.5 + }, + { + "target": "Chariot", + "rate": 1.4 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.1 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnBoxL", + "rate": 2 + }, + { + "target": "MsnEnemyShield", + "rate": 20 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2.8 + }, + { + "target": "Sponge_Versus", + "rate": 2.8 + }, + { + "target": "Wsb_Flag", + "rate": 2.8 + }, + { + "target": "Wsb_Shield", + "rate": 2.8 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.8 + } + ] + }, + "Jetpack_Bullet": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [10, 10010, 30010], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 3.5 + }, + { + "target": "Chariot", + "rate": 0.8334 + }, + { + "target": "CoopEnemySakeTamaireOneBomb", + "rate": 1 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.1 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnBoxL", + "rate": 2 + }, + { + "target": "MsnEnemyShield", + "rate": 20 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3334 + }, + { + "target": "ShockSonar", + "rate": 2.8 + }, + { + "target": "Sponge_Versus", + "rate": 2.8 + }, + { + "target": "Wsb_Flag", + "rate": 2.8 + }, + { + "target": "Wsb_Shield", + "rate": 2.8 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.8 + } + ] + }, + "Jetpack_Coop": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [20010], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "ShockSonar", + "rate": 1 + }, + { + "target": "Sponge_Versus", + "rate": 1 + }, + { + "target": "Wsb_Flag", + "rate": 1 + }, + { + "target": "Wsb_Shield", + "rate": 1 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1 + } + ] + }, + "Jetpack_Jet": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [10, 20010, 30010], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.8 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 2.8 + }, + { + "target": "Wsb_Flag", + "rate": 2.8 + }, + { + "target": "Wsb_Shield", + "rate": 2.8 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.8 + } + ] + }, + "Maneuver_Short": { + "mainWeaponIds": [5000, 25000, 15000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.1 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.6 + } + ] + }, + "Maneuver": { + "mainWeaponIds": [ + 5030, 25030, 15030, 5020, 25020, 15020, 5010, 25010, 15010, 35000, 35010, + 5040, 25040, 15040 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.6 + } + ] + }, + "MicroLaser": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [9, 20009, 10009], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.5 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 0.5 + }, + { + "target": "CoopEnemySakelienTowerPart", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "ShockSonar", + "rate": 2.4 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + } + ] + }, + "MissionSalmonBuddy": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnBoxL", + "rate": 1.6 + }, + { + "target": "MsnGoal", + "rate": 45 + }, + { + "target": "NiceBall_Armor", + "rate": 1 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 5 + } + ] + }, + "MovePainter_Burst": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "MsnEnemy", + "rate": 10 + }, + { + "target": "MsnEnemyShield", + "rate": 40 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 10 + }, + { + "target": "SnakeBlock", + "rate": 8 + }, + { + "target": "Sponge_Versus", + "rate": 10 + } + ] + }, + "MovePainter_Direct": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "MsnEnemyShield", + "rate": 20 + } + ] + }, + "MultiMissile_BombCore": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [4, 10004, 30004], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.5 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.75 + }, + { + "target": "MsnBoxHard", + "rate": 2.5 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 5 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "MultiMissile_Bullet": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [4, 10004, 30004], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.5 + }, + { + "target": "Chariot", + "rate": 1.5 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.75 + }, + { + "target": "MsnBoxHard", + "rate": 8 + }, + { + "target": "MsnBoxS", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "NiceBall": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [6, 20006], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2.5 + }, + { + "target": "Chariot", + "rate": 2 + }, + { + "target": "CoopEnemyHardBody", + "rate": 1 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "ShockSonar", + "rate": 3 + }, + { + "target": "Sponge_Versus", + "rate": 3 + }, + { + "target": "Wsb_Shield", + "rate": 3 + } + ] + }, + "ObjectEffect_Up": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 1.3 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.1 + }, + { + "target": "InkRail", + "rate": 1.3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.1 + }, + { + "target": "ShockSonar", + "rate": 1.25 + }, + { + "target": "Sponge_Versus", + "rate": 1.3 + }, + { + "target": "Wsb_Flag", + "rate": 10 + }, + { + "target": "Wsb_Shield", + "rate": 1.5 + }, + { + "target": "Wsb_Sprinkler", + "rate": 10 + } + ] + }, + "RollerCore": { + "mainWeaponIds": [ + 1000, 21000, 11000, 1020, 21020, 11020, 1030, 21030, 11030, 1010, 21010, + 11010, 31000, 31010 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "CoopGoldenIkuraBox", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "InkRail", + "rate": 12 + }, + { + "target": "MsnBoxHard", + "rate": 1 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 0.5 + }, + { + "target": "Sponge_Versus", + "rate": 0.344 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "RollerSplash_Compact": { + "mainWeaponIds": [1000, 21000, 11000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.8 + }, + { + "target": "Chariot", + "rate": 1.4 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.8 + }, + { + "target": "MsnBoxHard", + "rate": 1 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.43 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 1.2 + }, + { + "target": "Wsb_Flag", + "rate": 2.88 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.88 + } + ] + }, + "RollerSplash_Heavy": { + "mainWeaponIds": [1020, 21020, 11020], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.5 + }, + { + "target": "Chariot", + "rate": 1.6 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.35 + }, + { + "target": "MsnBoxHard", + "rate": 1 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 1.8 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.6 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 1.2 + }, + { + "target": "Wsb_Flag", + "rate": 2.88 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.88 + } + ] + }, + "RollerSplash_Hunter": { + "mainWeaponIds": [1030, 21030, 11030], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.5 + }, + { + "target": "Chariot", + "rate": 1.4 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.35 + }, + { + "target": "MsnBoxHard", + "rate": 1 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.4 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 1.2 + }, + { + "target": "Wsb_Flag", + "rate": 2.88 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.88 + } + ] + }, + "RollerSplash": { + "mainWeaponIds": [1010, 21010, 11010, 31000, 31010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.78 + }, + { + "target": "Chariot", + "rate": 1.4 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.8 + }, + { + "target": "MsnBoxHard", + "rate": 1 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.43 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 1.2 + }, + { + "target": "Wsb_Flag", + "rate": 2.88 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.88 + } + ] + }, + "Saber_ChargeShot": { + "mainWeaponIds": [8010, 28010, 8000, 28000, 18000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 4.8 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 4.8 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 4.8 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 4.8 + }, + { + "target": "Chariot", + "rate": 2.6 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3.2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 4.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnEnemyShield", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 2.6 + }, + { + "target": "ShockSonar", + "rate": 4.8 + }, + { + "target": "Sponge_Versus", + "rate": 4.8 + }, + { + "target": "Wsb_Flag", + "rate": 4.8 + }, + { + "target": "Wsb_Shield", + "rate": 4.8 + }, + { + "target": "Wsb_Sprinkler", + "rate": 4.8 + } + ] + }, + "Saber_ChargeSlash": { + "mainWeaponIds": [8010, 28010, 8000, 28000, 18000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 1.2 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.2 + }, + { + "target": "Chariot", + "rate": 0.65 + }, + { + "target": "Gachihoko_Barrier", + "rate": 0.8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.9 + }, + { + "target": "MsnBoxHard", + "rate": 10 + }, + { + "target": "MsnEnemyShield", + "rate": 10 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 4 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 0.65 + }, + { + "target": "ShockSonar", + "rate": 1.2 + }, + { + "target": "Sponge_Versus", + "rate": 1.2 + }, + { + "target": "Wsb_Flag", + "rate": 1.2 + }, + { + "target": "Wsb_Shield", + "rate": 1.2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1.2 + } + ] + }, + "Saber_Shot": { + "mainWeaponIds": [8010, 28010, 8000, 28000, 18000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 4.8 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 4.8 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 4.8 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 4.8 + }, + { + "target": "Chariot", + "rate": 2.6 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3.2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 4.8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 3.6 + }, + { + "target": "MsnEnemyShield", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 2.6 + }, + { + "target": "ShockSonar", + "rate": 4.8 + }, + { + "target": "Sponge_Versus", + "rate": 4.8 + }, + { + "target": "Wsb_Flag", + "rate": 4.8 + }, + { + "target": "Wsb_Shield", + "rate": 4.8 + }, + { + "target": "Wsb_Sprinkler", + "rate": 4.8 + } + ] + }, + "Saber_Slash": { + "mainWeaponIds": [8010, 28010, 8000, 28000, 18000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2.4 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.6 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.8 + }, + { + "target": "MsnBoxHard", + "rate": 3 + }, + { + "target": "MsnEnemyShield", + "rate": 10 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3 + }, + { + "target": "ShockSonar", + "rate": 2.4 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "SakerocketBullet": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Chariot", + "rate": 2.5 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Default", + "rate": 1 + }, + { + "target": "MsnSharkKing", + "rate": 1 + }, + { + "target": "ShockSonar", + "rate": 1 + } + ] + }, + "ShelterCanopy_Compact": { + "mainWeaponIds": [6020, 26020, 16020], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 5 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Shield", + "rate": 1 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "ShelterCanopy_Wide": { + "mainWeaponIds": [6010, 26010, 16010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 5 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Shield", + "rate": 1 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "ShelterCanopy": { + "mainWeaponIds": [26900, 6000, 26000, 16000, 36000, 36010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 5 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "Propeller", + "rate": 3 + }, + { + "target": "ShockSonar", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Shield", + "rate": 1 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "ShelterShot_Compact": { + "mainWeaponIds": [6020, 26020, 16020], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "InkRail", + "rate": 1.175 + }, + { + "target": "NiceBall_Armor", + "rate": 1.56 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2.4 + }, + { + "target": "Sponge_Versus", + "rate": 2.88 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "ShelterShot_Wide": { + "mainWeaponIds": [6010, 26010, 16010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2.4 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "ShelterShot": { + "mainWeaponIds": [26900, 6000, 26000, 16000, 36000, 36010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 2.4 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 1.3 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2.4 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 2.4 + }, + { + "target": "Wsb_Shield", + "rate": 2.4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.4 + } + ] + }, + "Shield": { + "mainWeaponIds": [], + "subWeaponIds": [4], + "specialWeaponIds": [], + "rates": [ + { + "target": "Gachihoko_Barrier", + "rate": 0.2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 0.2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.2 + }, + { + "target": "NiceBall_Armor", + "rate": 3.75 + }, + { + "target": "Sponge_Versus", + "rate": 0.2 + } + ] + }, + "ShockSonar_Wave": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [7, 20007, 10007, 30007], + "rates": [ + { + "target": "Chariot", + "rate": 2 + }, + { + "target": "Gachihoko_Barrier", + "rate": 8 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 8 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 8 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 100 + }, + { + "target": "Wsb_Shield", + "rate": 100 + }, + { + "target": "Wsb_Sprinkler", + "rate": 100 + } + ] + }, + "Shooter_Blaze": { + "mainWeaponIds": [30, 20030, 10030], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.1 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + } + ] + }, + "Shooter_Expert": { + "mainWeaponIds": [70, 20070, 10070], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.6 + } + ] + }, + "Shooter_First": { + "mainWeaponIds": [10, 20010, 10010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.1 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + } + ] + }, + "Shooter_FlashRepeat": { + "mainWeaponIds": [400, 20400, 10400], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + }, + { + "target": "ShockSonar", + "rate": 1.1 + }, + { + "target": "Wsb_Shield", + "rate": 1.1 + } + ] + }, + "Shooter_Flash": { + "mainWeaponIds": [400, 20400, 10400], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + }, + { + "target": "ShockSonar", + "rate": 1.1 + }, + { + "target": "Wsb_Shield", + "rate": 1.1 + } + ] + }, + "Shooter_Gravity": { + "mainWeaponIds": [50], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.85 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + }, + { + "target": "ShockSonar", + "rate": 1.1 + }, + { + "target": "Wsb_Shield", + "rate": 1.1 + } + ] + }, + "Shooter_Heavy": { + "mainWeaponIds": [80], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.1 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.6 + }, + { + "target": "ShockSonar", + "rate": 1.1 + }, + { + "target": "Wsb_Shield", + "rate": 1.1 + } + ] + }, + "Shooter_Long": { + "mainWeaponIds": [90, 20090, 10090], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.6 + } + ] + }, + "Shooter_Precision": { + "mainWeaponIds": [20, 20020, 10020], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.1 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + } + ] + }, + "Shooter_Short": { + "mainWeaponIds": [0, 20000, 10000], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.1 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + }, + { + "target": "Sponge_Versus", + "rate": 1 + } + ] + }, + "Shooter_TripleMiddle": { + "mainWeaponIds": [310], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.8 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.8 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.8 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.2 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + }, + { + "target": "Sponge_Versus", + "rate": 1.2 + }, + { + "target": "Wsb_Flag", + "rate": 1.2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1.2 + } + ] + }, + "Shooter_TripleQuick": { + "mainWeaponIds": [300], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.85 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.85 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.85 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.15 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.15 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.15 + }, + { + "target": "NiceBall_Armor", + "rate": 0.65 + }, + { + "target": "Sponge_Versus", + "rate": 1.1 + }, + { + "target": "Wsb_Flag", + "rate": 1.2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1.2 + } + ] + }, + "Shooter": { + "mainWeaponIds": [ + 400, 20400, 10400, 20050, 10050, 20080, 10080, 10900, 10910, 10920, 40, + 20040, 45, 10040, 60, 20060, 10060, 30000, 30010, 20310, 10310, 20300, + 10300 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.7 + } + ] + }, + "Skewer_Body": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [13, 20013, 10013], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 100 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 100 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 100 + }, + { + "target": "Chariot", + "rate": 7.28 + }, + { + "target": "CoopEnemyHardBody", + "rate": 1 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 0.45 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 5 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 5 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 7.5 + }, + { + "target": "ShockSonar", + "rate": 5 + }, + { + "target": "Wsb_Flag", + "rate": 5 + }, + { + "target": "Wsb_Shield", + "rate": 5 + }, + { + "target": "Wsb_Sprinkler", + "rate": 5 + } + ] + }, + "Skewer": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [13, 20013, 10013], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 9.5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 6 + }, + { + "target": "Chariot", + "rate": 7.28 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 0.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 5 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 5 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 5 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 7.5 + }, + { + "target": "ShockSonar", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 5 + }, + { + "target": "Wsb_Flag", + "rate": 5 + }, + { + "target": "Wsb_Shield", + "rate": 5 + }, + { + "target": "Wsb_Sprinkler", + "rate": 5 + } + ] + }, + "Slosher_Bathtub": { + "mainWeaponIds": [3030, 23030, 13030], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 1.6 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.6 + }, + { + "target": "Default", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 2.5 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.5 + } + ] + }, + "Slosher_Bear": { + "mainWeaponIds": [23900], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemyHardBody", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 1.25 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 2.5 + }, + { + "target": "Wsb_Shield", + "rate": 2.5 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.5 + } + ] + }, + "Slosher_WashtubBombCore": { + "mainWeaponIds": [3040, 23040, 13040], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakeTamaireOneBomb", + "rate": 1 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3.2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3.2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.8 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 4 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 4 + } + ] + }, + "Slosher_Washtub": { + "mainWeaponIds": [3040, 23040, 13040], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3.6 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3.6 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.9 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 1.25 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 5 + }, + { + "target": "Wsb_Shield", + "rate": 2.5 + }, + { + "target": "Wsb_Sprinkler", + "rate": 5 + } + ] + }, + "Slosher": { + "mainWeaponIds": [ + 3010, 23010, 13010, 3020, 23020, 13020, 33000, 33010, 3000, 23000, 13000 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakelienTowerUnite", + "rate": 1 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2.4 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.4 + }, + { + "target": "MsnBoxHard", + "rate": 1.5 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 1.25 + }, + { + "target": "Sponge_Versus", + "rate": 2.4 + }, + { + "target": "Wsb_Flag", + "rate": 2.5 + }, + { + "target": "Wsb_Shield", + "rate": 2.5 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2.5 + } + ] + }, + "Spinner": { + "mainWeaponIds": [ + 4030, 24030, 14030, 4020, 24020, 14020, 4000, 24000, 14000, 4040, 24040, + 14040, 4010, 24010, 14010 + ], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 0.7 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 0.7 + }, + { + "target": "Chariot", + "rate": 1 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1 + }, + { + "target": "NiceBall_Armor", + "rate": 0.6 + } + ] + }, + "Sprinkler": { + "mainWeaponIds": [], + "subWeaponIds": [3], + "specialWeaponIds": [], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.5 + }, + { + "target": "Gachihoko_Barrier", + "rate": 0.6 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 0.6 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 0.6 + }, + { + "target": "Sponge_Versus", + "rate": 0.6 + } + ] + }, + "Stringer_Short": { + "mainWeaponIds": [7020, 27020], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 1.5556 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2.3333 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 1.5556 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.5556 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.5556 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.5556 + }, + { + "target": "ShockSonar", + "rate": 1.5556 + }, + { + "target": "Sponge_Versus", + "rate": 1.5556 + }, + { + "target": "Wsb_Flag", + "rate": 1.5556 + }, + { + "target": "Wsb_Shield", + "rate": 1.5556 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1.5556 + } + ] + }, + "Stringer": { + "mainWeaponIds": [27900, 7010, 27010, 17010], + "subWeaponIds": [], + "specialWeaponIds": [], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 1.3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnBoxHard", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 3 + }, + { + "target": "NiceBall_Armor", + "rate": 1.3 + }, + { + "target": "Propeller", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "SuperHook": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [3, 10003], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnBoxHard", + "rate": 2 + }, + { + "target": "MsnEnemy", + "rate": 2 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 2 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "SnakeBlock", + "rate": 12 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "SuperLanding": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [101, 20101, 30101], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.6 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 10 + }, + { + "target": "EnemyRockBall", + "rate": 2 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "MsnBossWeak", + "rate": 5 + }, + { + "target": "MsnBoxHard", + "rate": 5 + }, + { + "target": "MsnBoxL", + "rate": 2.5 + }, + { + "target": "MsnBoxS", + "rate": 2 + }, + { + "target": "MsnEnemyShield", + "rate": 20 + }, + { + "target": "MsnEnemyTakopodDEV", + "rate": 4 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "MsnLeaderMoray", + "rate": 2 + }, + { + "target": "MsnMantaShadow", + "rate": 2 + }, + { + "target": "MsnRailKingHand", + "rate": 5 + }, + { + "target": "MsnSharkKing", + "rate": 2.5 + }, + { + "target": "NiceBall_Armor", + "rate": 1.5 + }, + { + "target": "Propeller", + "rate": 5 + }, + { + "target": "SnakeBlock", + "rate": 3 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "TripleTornado": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [14, 20014, 10014], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 2 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 2 + }, + { + "target": "Chariot", + "rate": 2 + }, + { + "target": "CoopEnemyHardBody", + "rate": 1 + }, + { + "target": "CoopEnemySakeTamaire", + "rate": 0.8 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2 + }, + { + "target": "NiceBall_Armor", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 2 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 2 + }, + { + "target": "Wsb_Sprinkler", + "rate": 2 + } + ] + }, + "UltraShot": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [1, 20001, 10001], + "rates": [ + { + "target": "BlowoutsRoll", + "rate": 3 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 6 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 6 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 6 + }, + { + "target": "Chariot", + "rate": 1.5 + }, + { + "target": "CoopEnemySakelienCupTwins", + "rate": 1 + }, + { + "target": "EnemyRockBall", + "rate": 3 + }, + { + "target": "Gachihoko_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 2 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.5 + }, + { + "target": "MsnBoxHard", + "rate": 10 + }, + { + "target": "MsnEnemyShield", + "rate": 20 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 2 + }, + { + "target": "ShockSonar", + "rate": 1 + }, + { + "target": "SnakeBlock", + "rate": 5 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Shield", + "rate": 6 + } + ] + }, + "UltraStamp_Swing": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [11, 10011], + "rates": [ + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 20 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 20 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 20 + }, + { + "target": "Chariot", + "rate": 1.5 + }, + { + "target": "EnemyRockBall", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 3 + }, + { + "target": "MsnEnemyShield", + "rate": 10 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.8 + }, + { + "target": "ShockSonar", + "rate": 20 + }, + { + "target": "Sponge_Versus", + "rate": 2 + }, + { + "target": "Wsb_Flag", + "rate": 3 + }, + { + "target": "Wsb_Shield", + "rate": 20 + }, + { + "target": "Wsb_Sprinkler", + "rate": 3 + } + ] + }, + "UltraStamp_Throw_BombCore": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [11, 10011], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 1 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 5 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 5 + }, + { + "target": "Chariot", + "rate": 2 + }, + { + "target": "EnemyRockBall", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 3.5 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 3.5 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 2.625 + }, + { + "target": "NiceBall_Armor", + "rate": 2.5 + }, + { + "target": "ShockSonar", + "rate": 4 + }, + { + "target": "Sponge_Versus", + "rate": 3 + }, + { + "target": "Wsb_Flag", + "rate": 3 + }, + { + "target": "Wsb_Shield", + "rate": 4 + }, + { + "target": "Wsb_Sprinkler", + "rate": 3 + } + ] + }, + "UltraStamp_Throw": { + "mainWeaponIds": [], + "subWeaponIds": [], + "specialWeaponIds": [11, 10011], + "rates": [ + { + "target": "Bomb_TorpedoBullet", + "rate": 0.545 + }, + { + "target": "BulletUmbrellaCanopyCompact", + "rate": 4.091 + }, + { + "target": "BulletUmbrellaCanopyNormal", + "rate": 4.091 + }, + { + "target": "BulletUmbrellaCanopyWide", + "rate": 4.091 + }, + { + "target": "Chariot", + "rate": 1.091 + }, + { + "target": "EnemyRockBall", + "rate": 10 + }, + { + "target": "Gachihoko_Barrier", + "rate": 1.909 + }, + { + "target": "GreatBarrier_Barrier", + "rate": 1.909 + }, + { + "target": "GreatBarrier_WeakPoint", + "rate": 1.4318 + }, + { + "target": "MsnGoal", + "rate": 10 + }, + { + "target": "NiceBall_Armor", + "rate": 1.364 + }, + { + "target": "ShockSonar", + "rate": 2.182 + }, + { + "target": "Sponge_Versus", + "rate": 1.636 + }, + { + "target": "Wsb_Flag", + "rate": 1.636 + }, + { + "target": "Wsb_Shield", + "rate": 2.182 + }, + { + "target": "Wsb_Sprinkler", + "rate": 1.636 + } + ] + } +} diff --git a/app/modules/analyzer/stats.ts b/app/modules/analyzer/stats.ts index beb7affba..39812f140 100644 --- a/app/modules/analyzer/stats.ts +++ b/app/modules/analyzer/stats.ts @@ -10,7 +10,7 @@ import type { StatFunctionInput, SubWeaponParams, } from "./types"; -import { DAMAGE_TYPE } from "./types"; +import { DAMAGE_TYPE } from "./constants"; import { INK_CONSUME_TYPES } from "./types"; import invariant from "tiny-invariant"; import { @@ -24,13 +24,13 @@ import { semiRandomId } from "~/utils/strings"; import { roundToTwoDecimalPlaces } from "~/utils/number"; export function buildStats({ - abilityPoints, weaponSplId, - mainOnlyAbilities, + abilityPoints = new Map(), + mainOnlyAbilities = [], }: { - abilityPoints: AbilityPoints; weaponSplId: MainWeaponId; - mainOnlyAbilities: Array; + abilityPoints?: AbilityPoints; + mainOnlyAbilities?: Array; }): AnalyzedBuild { const mainWeaponParams = weaponParams().mainWeapons[weaponSplId]; invariant(mainWeaponParams, `Weapon with splId ${weaponSplId} not found`); diff --git a/app/modules/analyzer/types.ts b/app/modules/analyzer/types.ts index cb372e50e..3021f2e9d 100644 --- a/app/modules/analyzer/types.ts +++ b/app/modules/analyzer/types.ts @@ -7,6 +7,7 @@ import type { import type { SPECIAL_EFFECTS } from "./specialEffects"; import type weaponParams from "./weapon-params.json"; import type abilityValues from "./ability-values.json"; +import type { DAMAGE_RECEIVERS, DAMAGE_TYPE } from "./constants"; type Overwrites = Record< string, @@ -159,20 +160,10 @@ export interface FullInkTankOption { type: InkConsumeType; } -export const DAMAGE_TYPE = [ - "NORMAL_MIN", - "NORMAL_MAX", - "DIRECT", - "FULL_CHARGE", - "MAX_CHARGE", - "TAP_SHOT", - "DISTANCE", - "BOMB_NORMAL", - "BOMB_DIRECT", -] as const; - export type DamageType = typeof DAMAGE_TYPE[number]; +export type DamageReceiver = typeof DAMAGE_RECEIVERS[number]; + export interface Damage { value: number; type: DamageType; diff --git a/app/modules/analyzer/useAnalyzeBuild.ts b/app/modules/analyzer/useAnalyzeBuild.ts index 593653042..a1f8382fd 100644 --- a/app/modules/analyzer/useAnalyzeBuild.ts +++ b/app/modules/analyzer/useAnalyzeBuild.ts @@ -3,10 +3,8 @@ import { EMPTY_BUILD } from "~/constants"; import { type BuildAbilitiesTupleWithUnknown, type MainWeaponId, - mainWeaponIds, abilities, isAbility, - weaponCategories, } from "../in-game-lists"; import type { Ability, @@ -17,7 +15,10 @@ import { MAX_LDE_INTENSITY } from "./constants"; import { applySpecialEffects, SPECIAL_EFFECTS } from "./specialEffects"; import { buildStats } from "./stats"; import type { SpecialEffectType } from "./types"; -import { buildToAbilityPoints } from "./utils"; +import { + buildToAbilityPoints, + validatedWeaponIdFromSearchParams, +} from "./utils"; const UNKNOWN_SHORT = "U"; @@ -88,20 +89,6 @@ function serializeBuild(build: BuildAbilitiesTupleWithUnknown) { .join(","); } -function validatedWeaponIdFromSearchParams( - searchParams: URLSearchParams -): MainWeaponId { - const weaponId = searchParams.get("weapon") - ? Number(searchParams.get("weapon")) - : null; - - if (mainWeaponIds.includes(weaponId as any)) { - return weaponId as MainWeaponId; - } - - return weaponCategories[0].weaponIds[0]; -} - function validatedBuildFromSearchParams( searchParams: URLSearchParams ): BuildAbilitiesTupleWithUnknown { diff --git a/app/modules/analyzer/useObjectDamage.ts b/app/modules/analyzer/useObjectDamage.ts new file mode 100644 index 000000000..02ba6bcfe --- /dev/null +++ b/app/modules/analyzer/useObjectDamage.ts @@ -0,0 +1,48 @@ +import { useSearchParams } from "@remix-run/react"; +import { type MainWeaponId } from "../in-game-lists"; +import { damageTypeToMultipliers, fallbackRates } from "./damageMultipliers"; +import { buildStats } from "./stats"; +import { validatedWeaponIdFromSearchParams } from "./utils"; + +export function useObjectDamage() { + const [searchParams, setSearchParams] = useSearchParams(); + + const mainWeaponId = validatedWeaponIdFromSearchParams(searchParams); + + const handleChange = ({ + newMainWeaponId = mainWeaponId, + }: { + newMainWeaponId?: MainWeaponId; + }) => { + setSearchParams( + { + weapon: String(newMainWeaponId), + }, + { replace: true, state: { scroll: false } } + ); + }; + + const analyzed = buildStats({ + weaponSplId: mainWeaponId, + }); + + const multipliers = Object.fromEntries( + analyzed.stats.damages.map((damage) => { + return [ + damage.type, + fallbackRates( + damageTypeToMultipliers({ + type: damage.type, + weapon: { type: "MAIN", id: mainWeaponId }, + }) + ), + ]; + }) + ); + + return { + mainWeaponId, + handleChange, + multipliers, + }; +} diff --git a/app/modules/analyzer/utils.ts b/app/modules/analyzer/utils.ts index f36064971..8dcff6526 100644 --- a/app/modules/analyzer/utils.ts +++ b/app/modules/analyzer/utils.ts @@ -1,4 +1,5 @@ import type { Ability, BuildAbilitiesTupleWithUnknown } from "../in-game-lists"; +import { mainWeaponIds, weaponCategories } from "../in-game-lists"; import { abilities } from "../in-game-lists"; import weaponParamsJson from "./weapon-params.json"; import abilityValuesJson from "./ability-values.json"; @@ -10,7 +11,7 @@ import type { SubWeaponParams, } from "./types"; import invariant from "tiny-invariant"; -import type { AbilityWithUnknown } from "../in-game-lists/types"; +import type { AbilityWithUnknown, MainWeaponId } from "../in-game-lists/types"; export function weaponParams(): ParamsJson { return weaponParamsJson as ParamsJson; @@ -150,3 +151,17 @@ export function hasEffect({ return high !== mid || mid !== low; } + +export function validatedWeaponIdFromSearchParams( + searchParams: URLSearchParams +): MainWeaponId { + const weaponId = searchParams.get("weapon") + ? Number(searchParams.get("weapon")) + : null; + + if (mainWeaponIds.includes(weaponId as any)) { + return weaponId as MainWeaponId; + } + + return weaponCategories[0].weaponIds[0]; +} diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx new file mode 100644 index 000000000..4cdfe3aea --- /dev/null +++ b/app/routes/object-damage.tsx @@ -0,0 +1,34 @@ +import { WeaponCombobox } from "~/components/Combobox"; +import { Main } from "~/components/Main"; +import { useObjectDamage } from "~/modules/analyzer"; +import type { MainWeaponId } from "~/modules/in-game-lists"; + +export const handle = { + i18n: ["weapons"], +}; + +export default function ObjectDamagePage() { + const { mainWeaponId, handleChange, multipliers } = useObjectDamage(); + + if (process.env.NODE_ENV !== "development") { + return
WIP :)
; + } + + return ( +
+ + opt && + handleChange({ + newMainWeaponId: Number(opt.value) as MainWeaponId, + }) + } + className="w-full-important" + clearsInputOnFocus + /> +
{JSON.stringify(multipliers, null, 2)}
+
+ ); +} diff --git a/package.json b/package.json index 5e8096080..0f27bcfd0 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "rename-badge": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/rename-badge.ts", "create-weapon-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-weapon-json.ts", "create-gear-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-gear-json.ts", + "create-object-dmg-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-object-dmg-json.ts", "create-misc-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-misc-json.ts", "create-analyzer-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-analyzer-json.ts", "check-translation-jsons": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/check-translation-jsons.ts && npm run prettier:write", diff --git a/scripts/create-object-dmg-json.ts b/scripts/create-object-dmg-json.ts new file mode 100644 index 000000000..3cf41f486 --- /dev/null +++ b/scripts/create-object-dmg-json.ts @@ -0,0 +1,55 @@ +/* eslint-disable */ +// @ts-nocheck + +// 1) WeaponInfoMain.json inside dicts +// 2) WeaponInfoSub.json inside dicts +// 3) WeaponInfoSpecial.json inside dicts +// 4) misc/spl__DamageRateInfoConfig.pp__CombinationDataTableData.json +import params from "./dicts/spl__DamageRateInfoConfig.pp__CombinationDataTableData.json"; +import weapons from "./dicts/WeaponInfoMain.json"; +import subWeapons from "./dicts/WeaponInfoSub.json"; +import specialWeapons from "./dicts/WeaponInfoSpecial.json"; +import fs from "node:fs"; +import path from "node:path"; + +const OUTPUT_DIR_PATH = path.join(__dirname, "output"); + +const weaponParamsToWeaponIds = ( + params: typeof weapons | typeof subWeapons | typeof specialWeapons, + key: string +) => { + return params + .filter((param) => { + return ( + param.DefaultDamageRateInfoRow === key || + param.ExtraDamageRateInfoRowSet?.some( + (row) => row.DamageRateInfoRow === key + ) + ); + }) + .map((weapon) => weapon.Id); +}; + +const result = {}; +for (const cell of Object.values(params.CellList)) { + if (!cell.DamageRate) continue; + + if (!result[cell.RowKey]) { + result[cell.RowKey] = { + mainWeaponIds: weaponParamsToWeaponIds(weapons, cell.RowKey), + subWeaponIds: weaponParamsToWeaponIds(subWeapons, cell.RowKey), + specialWeaponIds: weaponParamsToWeaponIds(specialWeapons, cell.RowKey), + rates: [], + }; + } + + result[cell.RowKey].rates.push({ + target: cell.ColumnKey, + rate: cell.DamageRate, + }); +} + +fs.writeFileSync( + path.join(OUTPUT_DIR_PATH, "object-dmg.json"), + JSON.stringify(result, null, 2) +); From 0af593623ba1c7df7b2b26e9b6975dd4bfe5bed8 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Tue, 18 Oct 2022 19:12:56 +0200 Subject: [PATCH 03/47] Wrap overflowing plus comments --- app/styles/plus.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/styles/plus.css b/app/styles/plus.css index efcbef581..29e6e402c 100644 --- a/app/styles/plus.css +++ b/app/styles/plus.css @@ -61,6 +61,8 @@ .plus__comment { white-space: pre-wrap; + min-width: auto; + overflow-wrap: break-word; } .plus__comment-time { From 3bc75f58d381b124c5322c751a51c980c45d7b54 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Mon, 17 Oct 2022 13:15:55 +0200 Subject: [PATCH 04/47] Add database table for user result highlights --- .../models/calendar/findResultsByUserId.sql | 11 +++++++- app/db/models/calendar/queries.server.ts | 2 ++ app/db/models/users/addResultHighlight.sql | 10 ++++++++ .../users/deleteAllResultHighlights.sql | 4 +++ app/db/models/users/queries.server.ts | 23 ++++++++++++++++- migrations/011-user-result-highlights.js | 25 +++++++++++++++++++ 6 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 app/db/models/users/addResultHighlight.sql create mode 100644 app/db/models/users/deleteAllResultHighlights.sql create mode 100644 migrations/011-user-result-highlights.js diff --git a/app/db/models/calendar/findResultsByUserId.sql b/app/db/models/calendar/findResultsByUserId.sql index db2e6e9fc..249c26623 100644 --- a/app/db/models/calendar/findResultsByUserId.sql +++ b/app/db/models/calendar/findResultsByUserId.sql @@ -12,7 +12,16 @@ select "CalendarEventDate" where "eventId" = "CalendarEvent"."id" - ) as "startTime" + ) as "startTime", + exists ( + select + 1 + from + "UserResultHighlight" + where + "userId" = @userId and + "teamId" = "CalendarEventResultTeam"."id" + ) as "isHighlight" from "CalendarEventResultPlayer" join "CalendarEventResultTeam" on "CalendarEventResultTeam"."id" = "CalendarEventResultPlayer"."teamId" diff --git a/app/db/models/calendar/queries.server.ts b/app/db/models/calendar/queries.server.ts index 5cfb87735..270333f38 100644 --- a/app/db/models/calendar/queries.server.ts +++ b/app/db/models/calendar/queries.server.ts @@ -244,9 +244,11 @@ export function findResultsByUserId(userId: User["id"]) { placement: CalendarEventResultTeam["placement"]; participantCount: CalendarEvent["participantCount"]; startTime: CalendarEventDate["startTime"]; + isHighlight: number; }> ).map((row) => ({ ...row, + isHighlight: Boolean(row.isHighlight), mates: ( findMatesByResultTeamIdStm.all({ teamId: row.teamId, diff --git a/app/db/models/users/addResultHighlight.sql b/app/db/models/users/addResultHighlight.sql new file mode 100644 index 000000000..341911c4d --- /dev/null +++ b/app/db/models/users/addResultHighlight.sql @@ -0,0 +1,10 @@ +insert into + "UserResultHighlight" ( + "userId", + "teamId" + ) +values + ( + @userId, + @teamId + ) \ No newline at end of file diff --git a/app/db/models/users/deleteAllResultHighlights.sql b/app/db/models/users/deleteAllResultHighlights.sql new file mode 100644 index 000000000..adc215286 --- /dev/null +++ b/app/db/models/users/deleteAllResultHighlights.sql @@ -0,0 +1,4 @@ +delete from + "UserResultHighlight" +where + "userId" = @userId \ No newline at end of file diff --git a/app/db/models/users/queries.server.ts b/app/db/models/users/queries.server.ts index c56611f07..cb04ed6ad 100644 --- a/app/db/models/users/queries.server.ts +++ b/app/db/models/users/queries.server.ts @@ -1,5 +1,9 @@ import { sql } from "../../sql"; -import type { User, UserWithPlusTier } from "../../types"; +import type { + CalendarEventResultTeam, + User, + UserWithPlusTier, +} from "../../types"; import upsertSql from "./upsert.sql"; import updateProfileSql from "./updateProfile.sql"; @@ -12,6 +16,8 @@ import updateDiscordIdSql from "./updateDiscordId.sql"; import findByIdentifierSql from "./findByIdentifier.sql"; import findAllPlusMembersSql from "./findAllPlusMembers.sql"; import findAllPatronsSql from "./findAllPatrons.sql"; +import addResultHighlightSql from "./addResultHighlight.sql"; +import deleteAllResultHighlightsSql from "./deleteAllResultHighlights.sql"; const upsertStm = sql.prepare(upsertSql); export function upsert( @@ -123,3 +129,18 @@ export type FindAllPatrons = Array< export function findAllPatrons() { return findAllPatronsStm.all() as FindAllPatrons; } + +const deleteAllResultHighlightsStm = sql.prepare(deleteAllResultHighlightsSql); +const addResultHighlightStm = sql.prepare(addResultHighlightSql); +export type UpdateResultHighlightsArgs = { + userId: User["id"]; + resultTeamIds: Array; +}; +export const updateResultHighlights = sql.transaction( + ({ userId, resultTeamIds }: UpdateResultHighlightsArgs) => { + deleteAllResultHighlightsStm.run({ userId }); + for (const teamId of resultTeamIds) { + addResultHighlightStm.run({ userId, teamId }); + } + } +); diff --git a/migrations/011-user-result-highlights.js b/migrations/011-user-result-highlights.js new file mode 100644 index 000000000..7102dcdab --- /dev/null +++ b/migrations/011-user-result-highlights.js @@ -0,0 +1,25 @@ +module.exports.up = function (db) { + db.prepare( + ` + create table "UserResultHighlight" ( + "teamId" integer not null, + "userId" integer not null, + foreign key ("teamId") references "CalendarEventResultTeam"("id") on delete cascade, + foreign key ("userId") references "User"("id") on delete cascade, + unique("teamId", "userId") on conflict rollback + ) strict + ` + ).run(); + + db.prepare( + `create index user_result_highlight_user_id on "UserResultHighlight"("userId")` + ).run(); + + db.prepare( + `create index user_result_highlight_team_id on "UserResultHighlight"("teamId")` + ).run(); +}; + +module.exports.down = function (db) { + db.prepare(`drop table "UserResultHighlight"`).run(); +}; From 76afa161fce0520e14c820ea22a003fce1a413c6 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Mon, 17 Oct 2022 20:07:27 +0200 Subject: [PATCH 05/47] Implement user result highlights UI --- app/routes/u.$identifier/results.tsx | 84 ------------- .../results/components/UserResultsTable.tsx | 111 ++++++++++++++++++ .../u.$identifier/results/highlights.tsx | 79 +++++++++++++ app/routes/u.$identifier/results/index.tsx | 68 +++++++++++ app/styles/common.css | 4 + app/styles/u.css | 13 +- app/utils/arrays.ts | 6 + app/utils/urls.ts | 2 + public/locales/de/user.json | 5 + public/locales/en/user.json | 5 + translation-progress.md | 60 ++++++++-- 11 files changed, 342 insertions(+), 95 deletions(-) delete mode 100644 app/routes/u.$identifier/results.tsx create mode 100644 app/routes/u.$identifier/results/components/UserResultsTable.tsx create mode 100644 app/routes/u.$identifier/results/highlights.tsx create mode 100644 app/routes/u.$identifier/results/index.tsx diff --git a/app/routes/u.$identifier/results.tsx b/app/routes/u.$identifier/results.tsx deleted file mode 100644 index 2a6a431e2..000000000 --- a/app/routes/u.$identifier/results.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { Link, useMatches } from "@remix-run/react"; -import { useTranslation } from "react-i18next"; -import invariant from "tiny-invariant"; -import { Avatar } from "~/components/Avatar"; -import { Placement } from "~/components/Placement"; -import { Section } from "~/components/Section"; -import { databaseTimestampToDate } from "~/utils/dates"; -import { discordFullName } from "~/utils/strings"; -import { calendarEventPage, userPage } from "~/utils/urls"; -import type { UserPageLoaderData } from "../u.$identifier"; - -export default function UserResultsPage() { - const { t, i18n } = useTranslation("user"); - const [, parentRoute] = useMatches(); - invariant(parentRoute); - const data = parentRoute.data as UserPageLoaderData; - - return ( -
-
- - - - - - - - - - - - - {data.results.map((result) => ( - - - - - - - - - ))} - -
{t("results.placing")}{t("results.team")}{t("results.tournament")}{t("results.participants")}{t("results.date")}{t("results.mates")}
- - {result.teamName} - - {result.eventName} - - {result.participantCount} - {databaseTimestampToDate(result.startTime).toLocaleDateString( - i18n.language, - { - day: "numeric", - month: "numeric", - year: "numeric", - } - )} - -
    - {result.mates.map((player) => ( -
  • - {typeof player === "string" ? ( - player - ) : ( - - {" "} - {discordFullName(player)} - - )} -
  • - ))} -
-
-
-
- ); -} diff --git a/app/routes/u.$identifier/results/components/UserResultsTable.tsx b/app/routes/u.$identifier/results/components/UserResultsTable.tsx new file mode 100644 index 000000000..b2a251d06 --- /dev/null +++ b/app/routes/u.$identifier/results/components/UserResultsTable.tsx @@ -0,0 +1,111 @@ +import { Link } from "@remix-run/react"; +import { useTranslation } from "react-i18next"; +import { Avatar } from "~/components/Avatar"; +import { Placement } from "~/components/Placement"; +import { type UserPageLoaderData } from "~/routes/u.$identifier"; +import { databaseTimestampToDate } from "~/utils/dates"; +import { discordFullName } from "~/utils/strings"; +import { calendarEventPage, userPage } from "~/utils/urls"; + +export type UserResultsTableProps = { + results: UserPageLoaderData["results"]; + id: string; + hasHighlightCheckboxes?: boolean; +}; + +export const HIGHLIGHT_CHECKBOX_NAME = "highlightTeamIds"; + +export function UserResultsTable({ + results, + id, + hasHighlightCheckboxes, +}: UserResultsTableProps) { + const { t, i18n } = useTranslation("user"); + + const placementHeaderId = `${id}-th-placement`; + + return ( + + + + {hasHighlightCheckboxes && + + + + + + + + + {results.map((result) => { + // We are trying to construct a reasonable label for the checkbox + // which shouldn't contain the whole information of the table row as + // that can be also accessed when needed. + // e.g. "20xx Placing 2nd", "Big House 10 Placing 20th" + const placementCellId = `${id}-${result.teamId}-placement`; + const nameCellId = `${id}-${result.teamId}-name`; + const checkboxLabelIds = `${nameCellId} ${placementHeaderId} ${placementCellId}`; + + return ( + + {hasHighlightCheckboxes && ( + + )} + + + + + + + + ); + })} + +
} + {t("results.placing")}{t("results.team")}{t("results.tournament")}{t("results.participants")}{t("results.date")}{t("results.mates")}
+ + + + {result.teamName} + + {result.eventName} + + {result.participantCount} + {databaseTimestampToDate(result.startTime).toLocaleDateString( + i18n.language, + { + day: "numeric", + month: "numeric", + year: "numeric", + } + )} + +
    + {result.mates.map((player) => ( +
  • + {typeof player === "string" ? ( + player + ) : ( + + + {discordFullName(player)} + + )} +
  • + ))} +
+
+ ); +} diff --git a/app/routes/u.$identifier/results/highlights.tsx b/app/routes/u.$identifier/results/highlights.tsx new file mode 100644 index 000000000..70086ff7e --- /dev/null +++ b/app/routes/u.$identifier/results/highlights.tsx @@ -0,0 +1,79 @@ +import { type ActionFunction, redirect } from "@remix-run/node"; +import { Form, useMatches, useTransition } from "@remix-run/react"; +import { useTranslation } from "react-i18next"; +import invariant from "tiny-invariant"; +import { z } from "zod"; +import { Button } from "~/components/Button"; +import { FormErrors } from "~/components/FormErrors"; +import { Main } from "~/components/Main"; +import { db } from "~/db"; +import { requireUser } from "~/modules/auth"; +import { type UserPageLoaderData } from "~/routes/u.$identifier"; +import { normalizeFormFieldArray } from "~/utils/arrays"; +import { parseRequestFormData } from "~/utils/remix"; +import { userResultsPage } from "~/utils/urls"; +import { + HIGHLIGHT_CHECKBOX_NAME, + UserResultsTable, +} from "./components/UserResultsTable"; + +const editHighlightsActionSchema = z.object({ + [HIGHLIGHT_CHECKBOX_NAME]: z.optional( + z.union([z.array(z.string()), z.string()]) + ), +}); + +export const action: ActionFunction = async ({ request }) => { + const user = await requireUser(request); + const data = await parseRequestFormData({ + request, + schema: editHighlightsActionSchema, + }); + + const resultTeamIds = normalizeFormFieldArray( + data[HIGHLIGHT_CHECKBOX_NAME] + ).map((id) => parseInt(id, 10)); + + db.users.updateResultHighlights({ + userId: user.id, + resultTeamIds, + }); + + return redirect(userResultsPage(user)); +}; + +export default function ResultHighlightsEditPage() { + const { t } = useTranslation(["common", "user"]); + const [, parentRoute] = useMatches(); + const transition = useTransition(); + + invariant(parentRoute); + const userPageData = parentRoute.data as UserPageLoaderData; + + return ( +
+
+

{t("user:results.highlights.choose")}

+
+
+ {t("user:results.highlights.explanation")} + +
+
+ + + +
+ ); +} diff --git a/app/routes/u.$identifier/results/index.tsx b/app/routes/u.$identifier/results/index.tsx new file mode 100644 index 000000000..954bd9f6b --- /dev/null +++ b/app/routes/u.$identifier/results/index.tsx @@ -0,0 +1,68 @@ +import { useMatches } from "@remix-run/react"; +import { useTranslation } from "react-i18next"; +import invariant from "tiny-invariant"; +import { LinkButton } from "~/components/Button"; +import { Main } from "~/components/Main"; +import { Section } from "~/components/Section"; +import { useUser } from "~/modules/auth"; +import { userResultsEditHighlightsPage } from "~/utils/urls"; +import type { UserPageLoaderData } from "../../u.$identifier"; +import { UserResultsTable } from "./components/UserResultsTable"; + +export default function UserResultsPage() { + const { t } = useTranslation("user"); + const [, parentRoute] = useMatches(); + invariant(parentRoute); + + const userPageData = parentRoute.data as UserPageLoaderData; + const hasResults = userPageData.results.length > 0; + + const nonHighlights = userPageData.results.filter((r) => !r.isHighlight); + const hasNonHighlights = nonHighlights.length > 0; + + const highlights = userPageData.results.filter((r) => r.isHighlight); + const hasHighlights = highlights.length > 0; + + const user = useUser(); + const isOwnResultsPage = user?.id === userPageData.id; + + const showHighlightsSection = + hasHighlights || (isOwnResultsPage && hasResults); + + return ( +
+ {showHighlightsSection && ( +
+ {hasHighlights && ( + + )} + {isOwnResultsPage && ( + + {t("results.highlights.choose")} + + )} +
+ )} + {hasNonHighlights && ( +
+ +
+ )} +
+ ); +} diff --git a/app/styles/common.css b/app/styles/common.css index 2d1cbf3be..4c4a37b65 100644 --- a/app/styles/common.css +++ b/app/styles/common.css @@ -292,6 +292,10 @@ table > tbody > tr > td { padding-inline: var(--s-1); } +td > input[type="checkbox"] { + vertical-align: middle; +} + hr { border-color: var(--theme-transparent); } diff --git a/app/styles/u.css b/app/styles/u.css index 673c38771..b3e504367 100644 --- a/app/styles/u.css +++ b/app/styles/u.css @@ -147,10 +147,21 @@ font-weight: var(--bold); } -.u__results-section { +.u__results-table-wrapper { + width: 100%; overflow-x: auto; } +.u__results-table-highlights { + border: var(--s-2) solid var(--bg-lighter); + padding-inline: 0 !important; +} + +.u__results-table-highlights > legend { + margin-inline-start: var(--s-2); + padding-inline: var(--s-1); +} + .u__results-players { display: flex; flex-wrap: wrap; diff --git a/app/utils/arrays.ts b/app/utils/arrays.ts index efdccb926..3c29f98a7 100644 --- a/app/utils/arrays.ts +++ b/app/utils/arrays.ts @@ -34,3 +34,9 @@ export function joinListToNaturalString(arg: string[]) { return last ? `${commaJoined} and ${last}` : commaJoined; } + +export function normalizeFormFieldArray( + value: undefined | null | string | string[] +): string[] { + return value == null ? [] : typeof value === "string" ? [value] : value; +} diff --git a/app/utils/urls.ts b/app/utils/urls.ts index c9ead88eb..ef4d3c07c 100644 --- a/app/utils/urls.ts +++ b/app/utils/urls.ts @@ -54,6 +54,8 @@ export const userBuildsPage = (user: UserLinkArgs) => `${userPage(user)}/builds`; export const userResultsPage = (user: UserLinkArgs) => `${userPage(user)}/results`; +export const userResultsEditHighlightsPage = (user: UserLinkArgs) => + `${userResultsPage(user)}/highlights`; export const userNewBuildPage = (user: UserLinkArgs) => `${userBuildsPage(user)}/new`; diff --git a/public/locales/de/user.json b/public/locales/de/user.json index e34fa88cf..e228b04e9 100644 --- a/public/locales/de/user.json +++ b/public/locales/de/user.json @@ -10,12 +10,17 @@ "stick": "Stick", "sens": "Empfindlichkeit", + "results.title": "Ergebnisse", "results.placing": "Platzierung", "results.team": "Team", "results.tournament": "Turnier", "results.participants": "Teilnehmer", "results.date": "Datum", "results.mates": "Mitspieler", + "results.highlights": "Highlights", + "results.nonHighlights": "Weitere Ergebnisse", + "results.highlights.choose": "Highlights wählen", + "results.highlights.explanation": "Wähle Ergebnisse, die du hervorheben möchtest", "forms.errors.invalidCustomUrl.numbers": "Benutzerdefinierte URL kann nicht nur aus Zahlen bestehen", "forms.errors.invalidCustomUrl.strangeCharacter": "Benutzerdefinierte URL kann nicht aus speziellen Zeichen bestehen", diff --git a/public/locales/en/user.json b/public/locales/en/user.json index 760f2a9b5..901b3b64a 100644 --- a/public/locales/en/user.json +++ b/public/locales/en/user.json @@ -10,12 +10,17 @@ "stick": "Stick", "sens": "Sens", + "results.title": "Results", "results.placing": "Placing", "results.team": "Team", "results.tournament": "Tournament", "results.participants": "Participants", "results.date": "Date", "results.mates": "Mates", + "results.highlights": "Highlights", + "results.nonHighlights": "Other Results", + "results.highlights.choose": "Choose Highlights", + "results.highlights.explanation": "Select the results you want to highlight", "forms.errors.invalidCustomUrl.numbers": "Custom URL can't only contain numbers", "forms.errors.invalidCustomUrl.strangeCharacter": "Custom URL can't contain special characters", diff --git a/translation-progress.md b/translation-progress.md index f51cb0f58..6dc638414 100644 --- a/translation-progress.md +++ b/translation-progress.md @@ -78,7 +78,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -91,7 +91,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate @@ -179,7 +184,7 @@ ### 🟢 user.json -**20/20** +**25/25** --- @@ -271,7 +276,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -284,7 +289,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate @@ -394,7 +404,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -407,7 +417,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate @@ -468,7 +483,7 @@ ### 🔴 user.json -**0/20** +**0/25** --- @@ -650,7 +665,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -663,7 +678,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate @@ -774,7 +794,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -787,7 +807,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate @@ -876,12 +901,17 @@ ### 🟡 user.json -**19/20** +**19/25**
Missing +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation
@@ -988,7 +1018,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -1001,7 +1031,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate @@ -1112,7 +1147,7 @@ ### 🟡 user.json -**7/20** +**7/25**
Missing @@ -1125,7 +1160,12 @@ - motion - stick - sens +- results.title - results.participants +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation - forms.errors.invalidCustomUrl.numbers - forms.errors.invalidCustomUrl.strangeCharacter - forms.errors.invalidCustomUrl.duplicate From 4ea1db705b9c0d4d4cef7fb9506c73749e96e46b Mon Sep 17 00:00:00 2001 From: Frederik <112972665+FrederikFraJylland@users.noreply.github.com> Date: Wed, 19 Oct 2022 07:44:30 +0200 Subject: [PATCH 06/47] Added missing translations Added translations for createMapList forms.mapPool --- public/locales/da/calendar.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/locales/da/calendar.json b/public/locales/da/calendar.json index c3e871b93..a5969e530 100644 --- a/public/locales/da/calendar.json +++ b/public/locales/da/calendar.json @@ -8,6 +8,7 @@ "participatedCount": "{{count}} hold deltog", "members": "Medlemmer", "results": "Resultater", + "createMapList": "Lav bane-liste", "forms.dates": "Datoer", "forms.bracketUrl": "Turneringsplans-URL", @@ -17,6 +18,7 @@ "forms.tags.info": "\"Præmiemærker\" tag tilføjes automatisk, hvis den er anvendelig", "forms.badges": "Præmiemærker", "forms.badges.placeholder": "Vælg et premiemærke", + "forms.mapPool": "Banepulje", "forms.participantCount": "Antal deltagere", "forms.reportResultsHeader": "Viser resultater for {{eventName}}", From 2657565f24dfc9b52b62dc5cc8bc30ac1614a092 Mon Sep 17 00:00:00 2001 From: Frederik <112972665+FrederikFraJylland@users.noreply.github.com> Date: Wed, 19 Oct 2022 07:52:50 +0200 Subject: [PATCH 07/47] Added tranlsations for map list Added danish translations for the map list feature The following lines have been translated pages.maps actions.copyToClipboard maps.createMapList maps.halfSz maps.mapPool maps.tournamentMaplist --- public/locales/da/common.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/public/locales/da/common.json b/public/locales/da/common.json index 50ba7d2a9..189a84bc4 100644 --- a/public/locales/da/common.json +++ b/public/locales/da/common.json @@ -8,6 +8,7 @@ "pages.faq": "FAQ", "pages.builds": "Udrustningssæt", "pages.analyzer": "Udrustningsanalysator", + "pages.maps": "Banelister", "header.profile": "Profil", "header.logout": "Log ud", @@ -27,6 +28,12 @@ "actions.remove": "Fjern", "actions.delete": "Slet", "actions.loadMore": "Indlæs flere", + "actions.copyToClipboard": "Kopiér til udklipsholderen", + + "maps.createMapList": "Lav bane-liste", + "maps.halfSz": "50% SZ", + "maps.mapPool": "Banepulje", + "maps.tournamentMaplist": "Lav turneringsbanepuljer på (maps.iplabs.ink)", "results": "Resultater", From d9d4f827399d0a65c90c133ade827873d3cafeaa Mon Sep 17 00:00:00 2001 From: Frederik <112972665+FrederikFraJylland@users.noreply.github.com> Date: Wed, 19 Oct 2022 07:57:58 +0200 Subject: [PATCH 08/47] Added translations for the map list Added Danish translations for the line "maps.description" --- public/locales/da/front.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/locales/da/front.json b/public/locales/da/front.json index c1524c6e4..f3d89e677 100644 --- a/public/locales/da/front.json +++ b/public/locales/da/front.json @@ -6,6 +6,7 @@ "plus.description": "Se plus-serverens valghistorik og mere til", "badges.description": "Liste af alle de premiemærker til din profil, som du kan gøre dig fortjent til", "analyzer.description": "Undersøg hvordan dine udrustinger giver dig af fordele i kamp", + "maps.description": "Lav en liste af baner ud fra en pulje af baner", "recentWinners": "Se de seneste vindere", "upcomingEvents": "Kommende begivenheder", "articleBy": "Af {{author}}" From 7fa025ad046bf645a1dc4a97a2b530503d18a311 Mon Sep 17 00:00:00 2001 From: Frederik <112972665+FrederikFraJylland@users.noreply.github.com> Date: Wed, 19 Oct 2022 07:59:43 +0200 Subject: [PATCH 09/47] Added the acronyms for the game modes Added the english acronyms for the game modes, as there are no Danish translations of those game modes. --- public/locales/da/game-misc.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/locales/da/game-misc.json b/public/locales/da/game-misc.json index de7ff391b..0b0c768a1 100644 --- a/public/locales/da/game-misc.json +++ b/public/locales/da/game-misc.json @@ -11,4 +11,9 @@ "STAGE_9": "Sturgeon Shipyard", "STAGE_10": "MakoMart", "STAGE_11": "Wahoo World" + "MODE_SHORT_TW": "TW", + "MODE_SHORT_SZ": "SZ", + "MODE_SHORT_TC": "TC", + "MODE_SHORT_RM": "RM", + "MODE_SHORT_CB": "CB" } From a08dff20c4034f3fb0f12a263a63c7c7ab5aeff7 Mon Sep 17 00:00:00 2001 From: Frederik <112972665+FrederikFraJylland@users.noreply.github.com> Date: Wed, 19 Oct 2022 08:14:51 +0200 Subject: [PATCH 10/47] Added translations for profile features Note Once the translations are implementend. Check if the following strings The following lines have been translated. customUrl ign ign.short stickSens motionSens motion stick sens results.participants forms.errors.invalidCustomUrl.numbers forms.errors.invalidCustomUrl.strangeCharacter forms.errors.invalidCustomUrl.duplicate forms.errors.invalidSens stickSens motionSens Do not overlap with eachother --- public/locales/da/user.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/public/locales/da/user.json b/public/locales/da/user.json index 0510cdb4f..5ccaf8a92 100644 --- a/public/locales/da/user.json +++ b/public/locales/da/user.json @@ -1,10 +1,24 @@ { + "customUrl": "Brugerdefineret URL", + "ign": "Splatoon 3 Brugernavn", + "ign.short": "Splatnavn", "country": "Land", "bio": "Biografi", + "stickSens": "Styrepindsfølsomhed", + "motionSens": "Bevægelsesfølsomhed", + "motion": "Bevægelse", + "stick": "Styrepind", + "sens": "Følsomhed", "results.placing": "Rang", "results.team": "Hold", "results.tournament": "Turnering", + "results.participants": "Deltagere", "results.date": "Dato", "results.mates": "Holdkammerater" + + "forms.errors.invalidCustomUrl.numbers": "Brugerdefineret URL må ikke kun indeholde numre", + "forms.errors.invalidCustomUrl.strangeCharacter": "Brugerdefineret URL må ikke indeholde specialtegn (Gælder også æ, ø og å)", + "forms.errors.invalidCustomUrl.duplicate": "Brugerdefineret URL er allerede i brug", + "forms.errors.invalidSens": "Bevægelsesfølsomhed kan ikke indstilles før at Styrepindsfølsomheden er indstillet" } From 7b76f901384e06145235edbc581d98ec8d900df5 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Wed, 19 Oct 2022 22:10:15 +0300 Subject: [PATCH 11/47] Update translation progress --- public/locales/da/game-misc.json | 2 +- public/locales/da/user.json | 4 +- translation-progress.md | 99 +------------------------------- 3 files changed, 4 insertions(+), 101 deletions(-) diff --git a/public/locales/da/game-misc.json b/public/locales/da/game-misc.json index 0b0c768a1..be8229456 100644 --- a/public/locales/da/game-misc.json +++ b/public/locales/da/game-misc.json @@ -10,7 +10,7 @@ "STAGE_8": "Inkblot Art Academy", "STAGE_9": "Sturgeon Shipyard", "STAGE_10": "MakoMart", - "STAGE_11": "Wahoo World" + "STAGE_11": "Wahoo World", "MODE_SHORT_TW": "TW", "MODE_SHORT_SZ": "SZ", "MODE_SHORT_TC": "TC", diff --git a/public/locales/da/user.json b/public/locales/da/user.json index 5ccaf8a92..b6fd43150 100644 --- a/public/locales/da/user.json +++ b/public/locales/da/user.json @@ -15,8 +15,8 @@ "results.tournament": "Turnering", "results.participants": "Deltagere", "results.date": "Dato", - "results.mates": "Holdkammerater" - + "results.mates": "Holdkammerater", + "forms.errors.invalidCustomUrl.numbers": "Brugerdefineret URL må ikke kun indeholde numre", "forms.errors.invalidCustomUrl.strangeCharacter": "Brugerdefineret URL må ikke indeholde specialtegn (Gælder også æ, ø og å)", "forms.errors.invalidCustomUrl.duplicate": "Brugerdefineret URL er allerede i brug", diff --git a/translation-progress.md b/translation-progress.md index f51cb0f58..cec40324c 100644 --- a/translation-progress.md +++ b/translation-progress.md @@ -1,103 +1,6 @@ # Translation Progress -## /da (🟡 In progress) - -### 🟢 analyzer.json - -**94/94** - -### 🟢 badges.json - -**7/7** - -### 🟢 builds.json - -**11/11** - -### 🟡 calendar.json - -**44/46** - -
-Missing - -- createMapList -- forms.mapPool - -
- -### 🟡 common.json - -**49/55** - -
-Missing - -- pages.maps -- actions.copyToClipboard -- maps.createMapList -- maps.halfSz -- maps.mapPool -- maps.tournamentMaplist - -
- -### 🟢 contributions.json - -**6/6** - -### 🟢 faq.json - -**6/6** - -### 🟡 front.json - -**10/11** - -
-Missing - -- maps.description - -
- -### 🟡 game-misc.json - -**12/17** - -
-Missing - -- MODE_SHORT_TW -- MODE_SHORT_SZ -- MODE_SHORT_TC -- MODE_SHORT_RM -- MODE_SHORT_CB - -
- -### 🟡 user.json - -**7/20** - -
-Missing - -- customUrl -- ign -- ign.short -- stickSens -- motionSens -- motion -- stick -- sens -- results.participants -- forms.errors.invalidCustomUrl.numbers -- forms.errors.invalidCustomUrl.strangeCharacter -- forms.errors.invalidCustomUrl.duplicate -- forms.errors.invalidSens - -
+## /da (🟢 Done) --- From 255fc6fcdf4ab7fce2f4dd844457b5beb260a32b Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:05:55 +0300 Subject: [PATCH 12/47] Fix stylelint complaint --- app/styles/plus.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/plus.css b/app/styles/plus.css index 29e6e402c..13a57ea16 100644 --- a/app/styles/plus.css +++ b/app/styles/plus.css @@ -60,9 +60,9 @@ } .plus__comment { - white-space: pre-wrap; min-width: auto; overflow-wrap: break-word; + white-space: pre-wrap; } .plus__comment-time { From 6a9efbdd175a3dd011f5b1dcc7d7dde6188e2953 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:14:35 +0300 Subject: [PATCH 13/47] Upgrade deps --- app/styles/analyzer.css | 12 +- app/styles/badges.css | 2 +- app/styles/builds.css | 4 +- app/styles/calendar-new.css | 2 +- app/styles/calendar.css | 2 +- app/styles/common.css | 42 +- app/styles/faq.css | 2 +- app/styles/front.css | 8 +- app/styles/layout.css | 14 +- app/styles/maps.css | 4 +- app/styles/plus-history.css | 6 +- app/styles/plus.css | 2 +- app/styles/u.css | 4 +- package-lock.json | 2050 ++++++++++++++++++----------------- package.json | 44 +- 15 files changed, 1141 insertions(+), 1057 deletions(-) diff --git a/app/styles/analyzer.css b/app/styles/analyzer.css index 6028ba9de..8cb895a66 100644 --- a/app/styles/analyzer.css +++ b/app/styles/analyzer.css @@ -27,8 +27,8 @@ display: flex; align-items: center; justify-content: center; - background-color: var(--theme-transparent); border-radius: var(--rounded); + background-color: var(--theme-transparent); gap: var(--s-1); padding-block: var(--s-1); padding-inline: var(--s-1-5); @@ -47,8 +47,8 @@ .analyzer__ap-summary { width: 100%; - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); font-size: var(--fonts-xxs); font-weight: var(--semi-bold); padding-block: var(--s-1); @@ -62,8 +62,8 @@ } .analyzer__summary { - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); font-size: var(--fonts-md); font-weight: var(--bold); padding-block: var(--s-2); @@ -82,8 +82,8 @@ flex-direction: column; justify-content: space-between; padding: var(--s-2); - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); gap: var(--s-4); } @@ -151,8 +151,8 @@ .analyzer__table-container { width: 100%; padding: var(--s-3); - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); margin-block-start: var(--s-4); padding-block: var(--s-2); } @@ -176,8 +176,8 @@ } .analyzer__patch { - background-color: var(--theme-transparent); border-radius: var(--rounded); + background-color: var(--theme-transparent); color: var(--text-lighter); font-size: var(--fonts-xxxs); font-weight: var(--bold); diff --git a/app/styles/badges.css b/app/styles/badges.css index 11c458176..6c4a08962 100644 --- a/app/styles/badges.css +++ b/app/styles/badges.css @@ -2,8 +2,8 @@ display: flex; flex-direction: column; align-items: center; - background-color: var(--bg-badge); border-radius: var(--rounded); + background-color: var(--bg-badge); color: var(--badge-text); gap: var(--s-6); padding-block: var(--s-2); diff --git a/app/styles/builds.css b/app/styles/builds.css index 17d4559b8..34d8fa9f9 100644 --- a/app/styles/builds.css +++ b/app/styles/builds.css @@ -15,8 +15,8 @@ display: flex; flex-direction: column; padding: var(--s-3); - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); font-size: var(--fonts-sm); font-weight: var(--semi-bold); gap: var(--s-4); @@ -44,6 +44,6 @@ } .builds__category__weapon__img { - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); } diff --git a/app/styles/calendar-new.css b/app/styles/calendar-new.css index 7a6387569..291f6adc1 100644 --- a/app/styles/calendar-new.css +++ b/app/styles/calendar-new.css @@ -9,8 +9,8 @@ .calendar-new__badges { width: max-content; padding: var(--s-2); - background-color: var(--bg-badge); border-radius: var(--rounded); + background-color: var(--bg-badge); font-size: var(--fonts-sm); font-weight: var(--semi-bold); } diff --git a/app/styles/calendar.css b/app/styles/calendar.css index 717db96f5..93f3f0a70 100644 --- a/app/styles/calendar.css +++ b/app/styles/calendar.css @@ -26,8 +26,8 @@ flex-direction: column; justify-content: space-between; padding: var(--s-1-5); - background-color: var(--theme-very-transparent); border-radius: var(--rounded); + background-color: var(--theme-very-transparent); cursor: pointer; font-size: var(--fonts-xxxs); font-weight: var(--bold); diff --git a/app/styles/common.css b/app/styles/common.css index 4c4a37b65..00cf5af50 100644 --- a/app/styles/common.css +++ b/app/styles/common.css @@ -32,9 +32,9 @@ a { align-items: center; justify-content: center; border: 2px solid var(--theme); + border-radius: var(--rounded-sm); appearance: none; background: var(--theme); - border-radius: var(--rounded-sm); color: var(--button-text); cursor: pointer; font-size: var(--fonts-sm); @@ -138,9 +138,9 @@ textarea:not(.plain) { height: 8rem; padding: var(--s-2-5) var(--s-3); border: 1px solid var(--border); + border-radius: var(--rounded); accent-color: var(--theme-secondary); background-color: transparent; - border-radius: var(--rounded); color: var(--text); font-size: var(--fonts-sm); outline: none; @@ -168,9 +168,9 @@ input:not(.plain) { height: 1rem; padding: var(--s-4) var(--s-3); border: 1px solid var(--border); + border-radius: var(--rounded); accent-color: var(--theme-secondary); background-color: transparent; - border-radius: var(--rounded); color: var(--text); font-size: var(--fonts-sm); outline: none; @@ -222,17 +222,17 @@ details summary { fieldset { border: none; - background-color: var(--bg-darker-transparent); border-radius: var(--rounded); + background-color: var(--bg-darker-transparent); font-size: var(--fonts-sm); padding-block-end: var(--s-3); padding-inline: var(--s-3); } legend { - background-color: transparent; border-radius: 2px; border-radius: var(--rounded-sm); + background-color: transparent; font-size: var(--fonts-xs); font-weight: var(--bold); } @@ -245,13 +245,13 @@ select { all: unset; width: 90%; border: 1px solid var(--border); + border-radius: var(--rounded); background: var(--select-background, var(--bg-lighter)); /* TODO: Get color from CSS var */ background-image: url('data:image/svg+xml;utf8,'); background-position: center right var(--s-3); background-repeat: no-repeat; - border-radius: var(--rounded); cursor: pointer; font-size: var(--fonts-sm); font-weight: 500; @@ -311,9 +311,9 @@ abbr[title] { dialog { width: min(90%, 24rem); border: 0; + border-radius: var(--rounded); margin: auto; background-color: var(--bg); - border-radius: var(--rounded); } dialog::backdrop { @@ -346,8 +346,8 @@ dialog::backdrop { width: var(--s-11); height: var(--s-6); align-items: center; - background-color: var(--theme-transparent); border-radius: var(--rounded); + background-color: var(--theme-transparent); } .toggle.tiny { @@ -367,8 +367,8 @@ dialog::backdrop { display: inline-block; width: var(--s-4); height: var(--s-4); - background-color: white; border-radius: 50%; + background-color: white; transform: translateX(var(--s-1)); transition: transform 0.2s ease; } @@ -402,9 +402,9 @@ dialog::backdrop { .input-container { display: flex; border: 1px solid var(--border); + border-radius: var(--rounded); accent-color: var(--theme-secondary); background-color: transparent; - border-radius: var(--rounded); color: var(--text); font-size: var(--fonts-sm); outline: none; @@ -430,8 +430,8 @@ dialog::backdrop { .input-addon { display: grid; - background-color: var(--bg-lighter); border-radius: var(--rounded) 0 0 var(--rounded); + background-color: var(--bg-lighter); color: var(--text-lighter); font-size: var(--fonts-xs); font-weight: var(--semi-bold); @@ -476,8 +476,8 @@ dialog::backdrop { z-index: 1; max-width: 20rem; padding: var(--s-2); - background-color: var(--bg-darker-transparent); border-radius: var(--rounded); + background-color: var(--bg-darker-transparent); font-size: var(--fonts-sm); font-weight: var(--semi-bold); white-space: pre-wrap; @@ -499,9 +499,9 @@ dialog::backdrop { position: absolute; z-index: 2; width: 12rem; + border-radius: var(--rounded); margin-top: var(--s-2); background-color: var(--bg-darker); - border-radius: var(--rounded); color: var(--text); font-size: var(--fonts-sm); padding-block: var(--s-3); @@ -548,8 +548,8 @@ dialog::backdrop { flex-wrap: wrap; align-items: center; justify-content: center; - background-color: var(--theme-info-transparent); border-radius: var(--rounded); + background-color: var(--theme-info-transparent); color: var(--text); font-size: var(--fonts-sm); font-weight: var(--semi-bold); @@ -562,9 +562,9 @@ dialog::backdrop { } .avatar { + border-radius: 50%; background-color: var(--bg-lighter); background-image: url("/svg/background-pattern.svg"); - border-radius: 50%; } .alert > svg { @@ -582,8 +582,8 @@ dialog::backdrop { .section > div { padding: var(--s-2); - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); } .section > h2 { @@ -726,8 +726,8 @@ dialog::backdrop { display: flex; flex-direction: column; padding: var(--s-2-5); - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); gap: var(--s-3); } @@ -756,8 +756,8 @@ dialog::backdrop { .build__weapon { padding: var(--s-0-5); - background-color: var(--bg-darker-very-transparent); border-radius: 50%; + background-color: var(--bg-darker-very-transparent); } .build__weapon-text { @@ -784,8 +784,8 @@ dialog::backdrop { } .build__gear { - background-color: var(--bg-darker-very-transparent); border-radius: 50%; + background-color: var(--bg-darker-very-transparent); } .build__ability { @@ -793,11 +793,11 @@ dialog::backdrop { height: var(--ability-size); padding: 0; border: 2px solid var(--theme-transparent); + border-radius: 50%; border-right: 0; border-bottom: 0; background: var(--bg-ability); background-size: 100%; - border-radius: 50%; box-shadow: 0 0 0 1px var(--bg-ability); transform: scale(1); transition: all 0.1s ease; @@ -864,8 +864,8 @@ dialog::backdrop { .ability-selector__ability-button { padding: var(--s-0-5); border-color: var(--abilities-button-bg); - background-color: var(--abilities-button-bg); border-radius: 50%; + background-color: var(--abilities-button-bg); } .ability-selector__ability-button.is-dragging { diff --git a/app/styles/faq.css b/app/styles/faq.css index e9738d254..752497cf6 100644 --- a/app/styles/faq.css +++ b/app/styles/faq.css @@ -1,7 +1,7 @@ .faq__summary { padding: var(--s-3); - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); font-size: var(--fonts-lg); font-weight: var(--bold); } diff --git a/app/styles/front.css b/app/styles/front.css index 4b0814295..58ceb9595 100644 --- a/app/styles/front.css +++ b/app/styles/front.css @@ -24,8 +24,8 @@ display: flex; align-items: center; padding: var(--s-2); - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); color: var(--text); font-size: var(--fonts-sm); gap: var(--s-2); @@ -63,8 +63,8 @@ min-width: 18rem; flex: 1 1 0px; padding: var(--s-2); - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); } .front__calendar-peek-container > h2 { @@ -76,8 +76,8 @@ display: grid; flex: 1 1 0px; - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); font-size: var(--fonts-sm); grid-template-areas: "name secondary" "content content"; grid-template-columns: 1fr 1fr; @@ -150,8 +150,8 @@ max-width: 12rem; flex: 1 1 0; padding: var(--s-2); - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); color: var(--text); text-align: center; } diff --git a/app/styles/layout.css b/app/styles/layout.css index 871612f73..b4de67cf4 100644 --- a/app/styles/layout.css +++ b/app/styles/layout.css @@ -21,9 +21,9 @@ height: var(--item-size); align-items: center; justify-content: center; + border-radius: var(--rounded); background-color: var(--bg-lighter); background-image: url("/svg/background-pattern.svg"); - border-radius: var(--rounded); } .layout__avatar { @@ -44,8 +44,8 @@ display: flex; width: max-content; align-items: center; - background-color: var(--bg-darker); border-radius: 0 var(--rounded) var(--rounded) 0; + background-color: var(--bg-darker); font-size: var(--fonts-xs); font-weight: var(--semi-bold); gap: var(--s-1); @@ -66,8 +66,8 @@ padding: 0.25rem; border: 2px solid; border-color: var(--theme-transparent-vibrant); - background-color: transparent; border-radius: 50%; + background-color: transparent; color: inherit; cursor: pointer; } @@ -102,8 +102,8 @@ padding: 0.25rem; border: 2px solid; border-color: var(--theme-transparent-vibrant); - background-color: transparent; border-radius: 50%; + background-color: transparent; color: inherit; cursor: pointer; gap: 2px; @@ -169,9 +169,9 @@ .layout__menu__link__icon { width: 2rem; height: 2rem; + border-radius: var(--rounded); background-color: var(--bg-lighter); background-image: url("/svg/background-pattern.svg"); - border-radius: var(--rounded); } .layout__menu__links { @@ -213,8 +213,8 @@ padding: 0.5rem; border: 2px solid; border-color: var(--bg-lighter); - background-color: transparent; border-radius: var(--rounded); + background-color: transparent; color: inherit; cursor: pointer; font-size: var(--fonts-xs); @@ -276,8 +276,8 @@ align-items: center; justify-content: space-between; padding: var(--s-4); - background-color: var(--theme-transparent-vibrant); border-radius: var(--rounded); + background-color: var(--theme-transparent-vibrant); cursor: pointer; font-size: var(--fonts-lg); } diff --git a/app/styles/maps.css b/app/styles/maps.css index 648e5b435..2d7f6bbbb 100644 --- a/app/styles/maps.css +++ b/app/styles/maps.css @@ -25,8 +25,8 @@ flex-grow: 1; align-items: center; justify-content: space-between; - background-color: var(--bg-lighter); border-radius: var(--rounded); + background-color: var(--bg-lighter); font-size: var(--fonts-xs); font-weight: var(--semi-bold); gap: var(--s-2); @@ -51,8 +51,8 @@ padding: 0; padding: var(--s-1-5); border: none; - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); color: var(--theme); opacity: 1 !important; outline: initial; diff --git a/app/styles/plus-history.css b/app/styles/plus-history.css index a122bc66e..9568629b9 100644 --- a/app/styles/plus-history.css +++ b/app/styles/plus-history.css @@ -1,9 +1,9 @@ .plus-history__own-scores { width: max-content; padding: var(--s-2); + border-radius: var(--rounded); margin: 0 auto; background-color: var(--bg-lighter); - border-radius: var(--rounded); font-size: var(--fonts-sm); font-weight: var(--semi-bold); list-style-type: none; @@ -53,8 +53,8 @@ } .plus-history__user-status { - background-color: var(--theme); border-radius: var(--rounded); + background-color: var(--theme); color: var(--button-text); font-size: var(--fonts-xs); font-weight: var(--semi-bold); @@ -67,8 +67,8 @@ } .plus-history__suggestion-s { - background-color: var(--bg-lighter); border-radius: 50%; + background-color: var(--bg-lighter); color: var(--text); font-weight: var(--bold); margin-inline-end: var(--s-1); diff --git a/app/styles/plus.css b/app/styles/plus.css index 13a57ea16..3e990d586 100644 --- a/app/styles/plus.css +++ b/app/styles/plus.css @@ -126,8 +126,8 @@ display: flex; align-items: center; justify-content: center; - background-color: var(--theme-success-transparent); border-radius: var(--rounded); + background-color: var(--theme-success-transparent); color: var(--text); font-size: var(--fonts-sm); font-weight: var(--semi-bold); diff --git a/app/styles/u.css b/app/styles/u.css index b3e504367..891db35eb 100644 --- a/app/styles/u.css +++ b/app/styles/u.css @@ -96,8 +96,8 @@ .u__extra-info { padding: var(--s-1) var(--s-1-5); - background-color: var(--bg-darker); border-radius: var(--rounded); + background-color: var(--bg-darker); font-size: var(--fonts-xxs); } @@ -111,8 +111,8 @@ max-width: 24rem; align-items: center; padding: var(--s-2); - background-color: var(--bg-badge); border-radius: var(--rounded); + background-color: var(--bg-badge); margin-inline: auto; } diff --git a/package-lock.json b/package-lock.json index 836301043..af36fc181 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,12 +6,12 @@ "": { "name": "sendou.ink", "dependencies": { - "@faker-js/faker": "^7.5.0", - "@headlessui/react": "^1.7.2", + "@faker-js/faker": "^7.6.0", + "@headlessui/react": "^1.7.3", "@popperjs/core": "^2.11.6", - "@remix-run/node": "^1.7.1", - "@remix-run/react": "^1.7.1", - "@remix-run/serve": "^1.7.1", + "@remix-run/node": "^1.7.2", + "@remix-run/react": "^1.7.2", + "@remix-run/serve": "^1.7.2", "better-sqlite3": "^7.6.2", "clsx": "^1.2.1", "countries-list": "^2.6.1", @@ -29,7 +29,7 @@ "node-cron": "3.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-flip-toolkit": "^7.0.16", + "react-flip-toolkit": "^7.0.17", "react-i18next": "^11.18.6", "react-popper": "^2.3.0", "react-use": "^17.4.0", @@ -38,36 +38,36 @@ "remix-i18next": "^4.1.1", "slugify": "^1.6.5", "swr": "^1.3.0", - "tiny-invariant": "^1.2.0", + "tiny-invariant": "^1.3.1", "zod": "^3.19.1" }, "devDependencies": { - "@remix-run/dev": "^1.7.1", - "@remix-run/eslint-config": "^1.7.1", - "@types/better-sqlite3": "^7.6.0", + "@remix-run/dev": "^1.7.2", + "@remix-run/eslint-config": "^1.7.2", + "@types/better-sqlite3": "^7.6.2", "@types/i18next-fs-backend": "^1.1.2", "@types/node-cron": "^3.0.4", - "@types/react": "^18.0.20", + "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", - "@typescript-eslint/eslint-plugin": "^5.38.0", - "@typescript-eslint/parser": "^5.38.0", + "@typescript-eslint/eslint-plugin": "^5.40.1", + "@typescript-eslint/parser": "^5.40.1", "cross-env": "^7.0.3", - "cypress": "^10.8.0", - "dotenv": "^16.0.2", - "eslint": "^8.23.1", - "eslint-plugin-react": "^7.31.8", + "cypress": "^10.10.0", + "dotenv": "^16.0.3", + "eslint": "^8.25.0", + "eslint-plugin-react": "^7.31.10", "eslint-plugin-react-hooks": "^4.6.0", - "ley": "^0.7.1", + "ley": "^0.8.1", "prettier": "^2.7.1", - "stylelint": "^14.12.1", - "stylelint-config-idiomatic-order": "^8.1.0", + "stylelint": "^14.14.0", + "stylelint-config-idiomatic-order": "^9.0.0", "stylelint-config-prettier": "^9.0.3", - "stylelint-config-standard": "^28.0.0", + "stylelint-config-standard": "^29.0.0", "stylelint-order": "^5.0.0", "ts-node": "^10.9.1", "tsconfig-paths": "^4.1.0", "tsm": "^2.2.2", - "typescript": "^4.8.3", + "typescript": "^4.8.4", "uvu": "^0.5.6" }, "engines": { @@ -100,30 +100,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", + "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz", - "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helpers": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -171,12 +171,12 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.18.2.tgz", - "integrity": "sha512-oFQYkE8SuH14+uR51JVAmdqwKYXGRjEXx7s+WiagVjqQ+HPE+nnwyF2qlVG8evUsUHmPcA+6YXMEDbIhEyQc5A==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", "dev": true, "dependencies": { - "eslint-scope": "^5.1.1", + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", "semver": "^6.3.0" }, @@ -198,12 +198,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", - "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", + "version": "7.19.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", + "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", "dev": true, "dependencies": { - "@babel/types": "^7.18.7", + "@babel/types": "^7.19.4", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -263,14 +263,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", - "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", + "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.18.6", + "@babel/compat-data": "^7.19.3", "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.20.2", + "browserslist": "^4.21.3", "semver": "^6.3.0" }, "engines": { @@ -378,9 +378,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", - "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -399,13 +399,13 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", - "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "dependencies": { - "@babel/template": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -448,19 +448,19 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.8.tgz", - "integrity": "sha512-che3jvZwIcZxrwh63VfnFTUzcAM9v/lznYkkRxIBGMPt1SudOKHAEec0SIRCfiuIzTcF7VGj/CaTT6gY4eWxvA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.8", - "@babel/types": "^7.18.8" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -557,10 +557,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -591,14 +600,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz", - "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", + "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", "dev": true, "dependencies": { - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.4", + "@babel/types": "^7.19.4" }, "engines": { "node": ">=6.9.0" @@ -633,9 +642,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.8.tgz", - "integrity": "sha512-RSKRfYX20dyH+elbJK2uqAkVyucL+xXzhqlMD5/ZXx+dAAwpyB7HsvnHe/ZUGOF+xLr5Wx9/JoXVTj6BQE2/oA==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", + "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1967,12 +1976,12 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz", - "integrity": "sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.4.tgz", + "integrity": "sha512-HzjQ8+dzdx7dmZy4DQ8KV8aHi/74AjEbBGTFutBmg/pd3dY5/q1sfuOGPTFGEytlQhWoeVXqcK5BwMgIkRkNDQ==", "dev": true, "dependencies": { - "core-js-pure": "^3.20.2", + "core-js-pure": "^3.25.1", "regenerator-runtime": "^0.13.4" }, "engines": { @@ -1980,33 +1989,33 @@ } }, "node_modules/@babel/template": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", - "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.8.tgz", - "integrity": "sha512-UNg/AcSySJYR/+mIcJQDCv00T+AqRO7j/ZEJLzpaYtgM48rMg5MnkJgyNqkzo88+p4tfRvZJCEiwwfG6h4jkRg==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", + "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.7", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", + "@babel/generator": "^7.19.4", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.8", - "@babel/types": "^7.18.8", + "@babel/parser": "^7.19.4", + "@babel/types": "^7.19.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2038,12 +2047,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.8.tgz", - "integrity": "sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", + "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2202,9 +2212,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -2263,9 +2273,9 @@ "dev": true }, "node_modules/@faker-js/faker": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.5.0.tgz", - "integrity": "sha512-8wNUCCUHvfvI0gQpDUho/3gPzABffnCn5um65F8dzQ86zz6dlt4+nmAA7PQUc8L+eH+9RgR/qzy5N/8kN0Ozdw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", + "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==", "engines": { "node": ">=14.0.0", "npm": ">=6.0.0" @@ -2278,9 +2288,9 @@ "dev": true }, "node_modules/@headlessui/react": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.2.tgz", - "integrity": "sha512-snLv2lxwsf2HNTOBNgHYdvoYZ3ChJE8QszPi1d/hl9js8KrFrUulTaQBfSyPbJP5BybVreWh9DxCgz9S0Z6hKQ==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.3.tgz", + "integrity": "sha512-LGp06SrGv7BMaIQlTs8s2G06moqkI0cb0b8stgq7KZ3xcHdH3qMP+cRyV7qe5x4XEW/IGY48BW4fLesD6NQLng==", "engines": { "node": ">=10" }, @@ -2290,9 +2300,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -2326,16 +2336,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2402,6 +2402,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2472,6 +2481,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/@pkgr/utils": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "is-glob": "^4.0.3", + "open": "^8.4.0", + "picocolors": "^1.0.0", + "tiny-glob": "^0.2.9", + "tslib": "^2.4.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@popperjs/core": { "version": "2.11.6", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", @@ -2482,9 +2511,9 @@ } }, "node_modules/@remix-run/dev": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-1.7.1.tgz", - "integrity": "sha512-yjxcCDb48mPUjiogGtxbWpoxauiM6jnSel2oyhztYlenfCM3wDzN2tOqBkfidNFlqpNQCkiRBN4FV97I03hDNw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-1.7.2.tgz", + "integrity": "sha512-oJcaju9zID+xOUnkMQJBEbjiiYBvILVsX64Fzi1itlm5vjNuo99nmKM7gleaDawNLo3lyd6Xd+JyMa3aIwDKOQ==", "dev": true, "dependencies": { "@babel/core": "^7.18.6", @@ -2493,7 +2522,7 @@ "@babel/preset-typescript": "^7.18.6", "@esbuild-plugins/node-modules-polyfill": "^0.1.4", "@npmcli/package-json": "^2.0.0", - "@remix-run/server-runtime": "1.7.1", + "@remix-run/server-runtime": "1.7.2", "@yarnpkg/esbuild-plugin-pnp": "3.0.0-rc.11", "arg": "^5.0.1", "cacache": "^15.0.5", @@ -2534,7 +2563,7 @@ "node": ">=14" }, "peerDependencies": { - "@remix-run/serve": "1.7.1" + "@remix-run/serve": "1.7.2" }, "peerDependenciesMeta": { "@remix-run/serve": { @@ -2549,27 +2578,27 @@ "dev": true }, "node_modules/@remix-run/eslint-config": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/eslint-config/-/eslint-config-1.7.1.tgz", - "integrity": "sha512-rroBQio5hhLf1mb/7IXoFXTkyrrZewbm8ZLbnYTgDA4Un0+MTFHr/7eQoyY+Xa858CWVdj0eZoGhCfmJQNkWVQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/eslint-config/-/eslint-config-1.7.2.tgz", + "integrity": "sha512-ikYWq570XnBt+E1FZ3PZxJliYPONaWNNG16eER+4/dp9GNQQApKBGfn5hs6256+678RNgFCCBx++W9BaJTBjgQ==", "dev": true, "dependencies": { - "@babel/core": "^7.18.6", - "@babel/eslint-parser": "^7.18.2", + "@babel/core": "^7.19.1", + "@babel/eslint-parser": "^7.19.1", "@babel/preset-react": "^7.18.6", - "@rushstack/eslint-patch": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^5.12.1", - "@typescript-eslint/parser": "^5.12.1", + "@rushstack/eslint-patch": "^1.2.0", + "@typescript-eslint/eslint-plugin": "^5.38.0", + "@typescript-eslint/parser": "^5.38.0", "eslint-import-resolver-node": "0.3.6", - "eslint-import-resolver-typescript": "^2.5.0", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^26.1.1", - "eslint-plugin-jest-dom": "^4.0.1", - "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-import-resolver-typescript": "^3.5.1", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jest": "^26.9.0", + "eslint-plugin-jest-dom": "^4.0.2", + "eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-testing-library": "^5.0.5" + "eslint-plugin-react": "^7.31.8", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-testing-library": "^5.6.4" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2587,11 +2616,11 @@ } }, "node_modules/@remix-run/express": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-1.7.1.tgz", - "integrity": "sha512-2m+kBiBQktRVMqf7m1e0CL8dvB7Pp9o7aaDy90IP6PAbiYrM3Hex11ad7cWe0PeqtYPexIKP5L/rAxIoUMuRGA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-1.7.2.tgz", + "integrity": "sha512-s2r5EOhOWLHH7cQtJfxcucI1K7iQA66mvoTstPjtU0/0pe8ZI+wBZopKxQMUEdjFG/ShnRIb1cPFHHF5VJLNfA==", "dependencies": { - "@remix-run/node": "1.7.1" + "@remix-run/node": "1.7.2" }, "engines": { "node": ">=14" @@ -2601,11 +2630,11 @@ } }, "node_modules/@remix-run/node": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-1.7.1.tgz", - "integrity": "sha512-vAffiWDXQ1RHzN9cicSHWOJgvcC9A4KZA8nrJlBf5TU0w/DrnrsdrCaaESs9eQ2rby2R1YiRA8kE3HBg8efScA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-1.7.2.tgz", + "integrity": "sha512-cLm5IuVPV7E0VK8LzrFAurG8dq8/HRc0WIE6Urj8bhbv0tCTJvFRfcCbCmDRRHmR72VmPkRahJov5f1Ab9jjQw==", "dependencies": { - "@remix-run/server-runtime": "1.7.1", + "@remix-run/server-runtime": "1.7.2", "@remix-run/web-fetch": "^4.1.3", "@remix-run/web-file": "^3.0.2", "@remix-run/web-stream": "^1.0.3", @@ -2620,13 +2649,12 @@ } }, "node_modules/@remix-run/react": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-1.7.1.tgz", - "integrity": "sha512-RraUPjLZc4vSgT51uloamOn1Gm/YCohL1jDTBbiWuDgnTwBu741vC0zoulzoD+eV2svfKijOHL0tXc8kEAWPdg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-1.7.2.tgz", + "integrity": "sha512-019y9WGdMA2i7/grLwpH1xqK3QxSmzNoMAwZ2ytnM/if6AHXrSz9BCn4urt6jYrDEuSOAwzOm65xd/fKNU45aQ==", "dependencies": { "history": "^5.3.0", - "react-router-dom": "6.3.0", - "type-fest": "^2.17.0" + "react-router-dom": "6.3.0" }, "engines": { "node": ">=14" @@ -2636,23 +2664,12 @@ "react-dom": ">=16.8" } }, - "node_modules/@remix-run/react/node_modules/type-fest": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.18.0.tgz", - "integrity": "sha512-pRS+/yrW5TjPPHNOvxhbNZexr2bS63WjrMU8a+VzEBhUi9Tz1pZeD+vQz3ut0svZ46P+SRqMEPnJmk2XnvNzTw==", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@remix-run/serve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-1.7.1.tgz", - "integrity": "sha512-qPqu9+Aa3VJKvLw71tdoBTc59PjSKKk/I6MXl6NPULimcIdvvwmWXfqmfRdpOaCAYlNBMIqIacZGyFxMpzF5Dw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-1.7.2.tgz", + "integrity": "sha512-5zSwbuka3agWL8mD3qHAG/b3iQWfRfkem8NtgtU5YzWkXHwOnXFyenak+3Jku3PRSZ+g00RhWE9cilzCtiAiGQ==", "dependencies": { - "@remix-run/express": "1.7.1", + "@remix-run/express": "1.7.2", "compression": "^1.7.4", "express": "^4.17.1", "morgan": "^1.10.0" @@ -2665,9 +2682,9 @@ } }, "node_modules/@remix-run/server-runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-1.7.1.tgz", - "integrity": "sha512-bvKuESSf7cW5ORlXayVPWHDpU8xiglKu7PQtiyKi+Gwjasp/GnUO6Xwqpy2HqHtoC7RNQYt2oRkWc/pRhpe55g==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-1.7.2.tgz", + "integrity": "sha512-YqdYHjqAukh5wbfix6ZqibUX5wYLm4SyyhibPiTthAV6SXHbTMu952jqf6Fa+asJRSf+QlNVwsizxH0zUGPAtw==", "dependencies": { "@types/cookie": "^0.4.0", "@web3-storage/multipart-parser": "^1.0.0", @@ -2694,14 +2711,15 @@ } }, "node_modules/@remix-run/web-fetch": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.2.0.tgz", - "integrity": "sha512-Bll+4Z3CT4ryYKRFTbdanLaXbOjtSuwYcj8s6DSXehVcZWWrz7mA3O394T52iFjvhaJ+ELSstNhVeBQc6NUfGg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.3.1.tgz", + "integrity": "sha512-TOpuJo3jI7/qJAY0yTnvNJRQl4hlWAOHUHYKAbEddcLFLydv+0/WGT6OaIurJKsBFJJTjooe3FbKiP74sUIB/g==", "dependencies": { "@remix-run/web-blob": "^3.0.4", "@remix-run/web-form-data": "^3.0.3", "@remix-run/web-stream": "^1.0.3", "@web3-storage/multipart-parser": "^1.0.0", + "abort-controller": "^3.0.0", "data-uri-to-buffer": "^3.0.1", "mrmime": "^1.0.0" }, @@ -2753,9 +2771,9 @@ "dev": true }, "node_modules/@rushstack/eslint-patch": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz", - "integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", "dev": true }, "node_modules/@sindresorhus/is": { @@ -2783,9 +2801,9 @@ } }, "node_modules/@testing-library/dom": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", - "integrity": "sha512-9VHgfIatKNXQNaZTtLnalIy0jNZzY35a4S3oi08YAt9Hv1VsfZ/DfA45lM8D/UhtHBGJ4/lGwp0PZkVndRkoOQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", + "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==", "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -2841,9 +2859,9 @@ "dev": true }, "node_modules/@types/better-sqlite3": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.0.tgz", - "integrity": "sha512-rnSP9vY+fVsF3iJja5yRGBJV63PNBiezJlYrCkqUmQWFoB16cxAHwOkjsAYEu317miOfKaJpa65cbp0P4XJ/jw==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.2.tgz", + "integrity": "sha512-RgmaapusqTq6IMAr4McMyAsC6RshYTCjXCnzwVV59WctUxC8bNPyUfT9t5F81lKcU41lLurhjqjoMHfauzfqGg==", "dev": true, "dependencies": { "@types/node": "*" @@ -3020,9 +3038,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.0.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", - "integrity": "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==", + "version": "18.0.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", + "integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -3054,6 +3072,12 @@ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.3.12", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", + "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", + "dev": true + }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -3083,14 +3107,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.0.tgz", - "integrity": "sha512-GgHi/GNuUbTOeoJiEANi0oI6fF3gBQc3bGFYj40nnAPCbhrtEDf2rjBmefFadweBmO1Du1YovHeDP2h5JLhtTQ==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", + "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/type-utils": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/type-utils": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -3138,14 +3162,14 @@ "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.0.tgz", - "integrity": "sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", + "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "debug": "^4.3.4" }, "engines": { @@ -3188,13 +3212,13 @@ "dev": true }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz", - "integrity": "sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", + "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0" + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3205,13 +3229,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.0.tgz", - "integrity": "sha512-iZq5USgybUcj/lfnbuelJ0j3K9dbs1I3RICAJY9NZZpDgBYXmuUlYQGzftpQA9wC8cKgtS6DASTvF3HrXwwozA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", + "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -3255,9 +3279,9 @@ "dev": true }, "node_modules/@typescript-eslint/types": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.0.tgz", - "integrity": "sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", + "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3268,13 +3292,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz", - "integrity": "sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", + "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3338,17 +3362,19 @@ "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.0.tgz", - "integrity": "sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", + "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3362,12 +3388,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz", - "integrity": "sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", + "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", + "@typescript-eslint/types": "5.40.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -3627,9 +3653,9 @@ "dev": true }, "node_modules/aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", "dev": true, "engines": { "node": ">=6.0" @@ -3791,7 +3817,7 @@ "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", "dev": true }, "node_modules/astral-regex": { @@ -3872,9 +3898,9 @@ "dev": true }, "node_modules/axe-core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", - "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", + "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==", "dev": true, "engines": { "node": ">=4" @@ -4152,9 +4178,9 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -4164,7 +4190,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -4214,9 +4240,9 @@ } }, "node_modules/browserslist": { - "version": "4.20.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", - "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, "funding": [ { @@ -4229,11 +4255,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001349", - "electron-to-chromium": "^1.4.147", - "escalade": "^3.1.1", - "node-releases": "^2.0.5", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" }, "bin": { "browserslist": "cli.js" @@ -4445,9 +4470,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001356", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001356.tgz", - "integrity": "sha512-/30854bktMLhxtjieIxsrJBfs2gTM1pel6MXKF3K+RdIVJZcsn2A2QdhsuR4/p9+R204fZw0zCBBhktX8xWuyQ==", + "version": "1.0.30001422", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz", + "integrity": "sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog==", "dev": true, "funding": [ { @@ -5068,9 +5093,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.4.tgz", - "integrity": "sha512-4iF+QZkpzIz0prAFuepmxwJ2h5t4agvE8WPYqs2mjLJMNNwJOnpch76w2Q7bUfCPEv/V7wpvOfog0w273M+ZSw==", + "version": "3.25.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.5.tgz", + "integrity": "sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg==", "dev": true, "hasInstallScript": true, "funding": { @@ -5206,9 +5231,9 @@ "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==" }, "node_modules/cypress": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.8.0.tgz", - "integrity": "sha512-QVse0dnLm018hgti2enKMVZR9qbIO488YGX06nH5j3Dg1isL38DwrBtyrax02CANU6y8F4EJUuyW6HJKw1jsFA==", + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.10.0.tgz", + "integrity": "sha512-bU8r44x1NIYAUNNXt3CwJpLOVth7HUv2hUhYCxZmgZ1IugowDvuHNpevnoZRQx1KKOEisLvIJW+Xen5Pjn41pg==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -5576,6 +5601,15 @@ "node": ">=10" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -5748,9 +5782,9 @@ "dev": true }, "node_modules/dotenv": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", - "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "dev": true, "engines": { "node": ">=12" @@ -5784,9 +5818,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.161", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.161.tgz", - "integrity": "sha512-sTjBRhqh6wFodzZtc5Iu8/R95OkwaPNn7tj/TaDU5nu/5EFiQDtADGAXdR4tJcTEHlYfJpHqigzJqHvPgehP8A==", + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, "node_modules/emoji-regex": { @@ -5819,6 +5853,19 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -6288,14 +6335,13 @@ } }, "node_modules/eslint": { - "version": "8.23.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz", - "integrity": "sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", + "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.2", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.10.5", "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -6369,19 +6415,24 @@ "dev": true }, "node_modules/eslint-import-resolver-typescript": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz", - "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.1.tgz", + "integrity": "sha512-U7LUjNJPYjNsHvAUAkt/RU3fcTSpbllA0//35B4eLYTX74frmOepbt7F7J3D1IGtj9k21buOpaqtDd4ZlS/BYQ==", "dev": true, "dependencies": { "debug": "^4.3.4", - "glob": "^7.2.0", + "enhanced-resolve": "^5.10.0", + "get-tsconfig": "^4.2.0", + "globby": "^13.1.2", + "is-core-module": "^2.10.0", "is-glob": "^4.0.3", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "synckit": "^0.8.3" }, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" }, "peerDependencies": { "eslint": "*", @@ -6405,16 +6456,23 @@ } } }, - "node_modules/eslint-import-resolver-typescript/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "node_modules/eslint-import-resolver-typescript/node_modules/globby": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", + "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", "dev": true, "dependencies": { - "minimist": "^1.2.0" + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint-import-resolver-typescript/node_modules/ms": { @@ -6423,38 +6481,33 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/eslint-import-resolver-typescript/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "node_modules/eslint-import-resolver-typescript/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/eslint-module-utils/node_modules/debug": { @@ -6466,70 +6519,12 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-module-utils/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==", "dev": true }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-plugin-es": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", @@ -6612,15 +6607,6 @@ "json5": "lib/cli.js" } }, - "node_modules/eslint-plugin-import/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -6634,9 +6620,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "26.1.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.1.5.tgz", - "integrity": "sha512-su89aDuljL9bTjEufTXmKUMSFe2kZUL9bi7+woq+C2ukHZordhtfPm4Vg+tdioHBaKf8v3/FXW9uV0ksqhYGFw==", + "version": "26.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", + "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -6658,9 +6644,9 @@ } }, "node_modules/eslint-plugin-jest-dom": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-4.0.1.tgz", - "integrity": "sha512-9aUaX4AtlFBziLqKSjc7DKHQ/y1T32qNapG3uSeLDMJYKswASoQLJWOfLIE+zEHKvCNzNIz8T7282tQkuu0TKQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-4.0.2.tgz", + "integrity": "sha512-Jo51Atwyo2TdcUncjmU+UQeSTKh3sc2LF/M5i/R3nTU0Djw9V65KGJisdm/RtuKhy2KH/r7eQ1n6kwYFPNdHlA==", "dev": true, "dependencies": { "@babel/runtime": "^7.16.3", @@ -6673,27 +6659,28 @@ "yarn": ">=1" }, "peerDependencies": { - "eslint": ">=6.8" + "eslint": "^6.8.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz", + "integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==", "dev": true, "dependencies": { - "@babel/runtime": "^7.16.3", + "@babel/runtime": "^7.18.9", "aria-query": "^4.2.2", - "array-includes": "^3.1.4", + "array-includes": "^3.1.5", "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", + "axe-core": "^4.4.3", "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", + "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", + "jsx-ast-utils": "^3.3.2", "language-tags": "^1.0.5", - "minimatch": "^3.0.4" + "minimatch": "^3.1.2", + "semver": "^6.3.0" }, "engines": { "node": ">=4.0" @@ -6721,6 +6708,15 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-node": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", @@ -6775,9 +6771,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.31.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz", - "integrity": "sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==", + "version": "7.31.10", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz", + "integrity": "sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==", "dev": true, "dependencies": { "array-includes": "^3.1.5", @@ -6846,9 +6842,9 @@ } }, "node_modules/eslint-plugin-testing-library": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.4.0.tgz", - "integrity": "sha512-XjxIf4g33KaZXxRNbR33+0WcRQ/zt8N0R58IY6/kkHnrY6zPsC1gs3u5cTZr5eUmCZN/sjoPak3uF5vHGKg2wg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.8.0.tgz", + "integrity": "sha512-QzOKgu4x8WmNq4LdbHb8lz5nBR+KX5kSg5VvIdr/5f1BvHx2IoO1B/tgDa5pD/ng2LsiQ0/HIH6gsUuxpbcrkQ==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.13.0" @@ -7404,13 +7400,13 @@ } }, "node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -7429,7 +7425,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", @@ -7850,9 +7846,9 @@ "dev": true }, "node_modules/flip-toolkit": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/flip-toolkit/-/flip-toolkit-7.0.16.tgz", - "integrity": "sha512-MeoLilutfKSGtN8kdUsIU3x0y+84RnnK2rgUcQ6CgVTeIsWxmEAmLBq+p3YGT0lNIZf6bqqUyyKLo0jkBTgRvg==", + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/flip-toolkit/-/flip-toolkit-7.0.17.tgz", + "integrity": "sha512-bybUdLNbC80F0+v+t3TBfxEAMVGhvXLi3pZ+qTtr4aCu/Y/5YQimMij0xJKT1qtz4SO31V4zftIgaTJdCCFiHA==", "dependencies": { "rematrix": "0.2.2" }, @@ -8129,6 +8125,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.2.0.tgz", + "integrity": "sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -8273,6 +8278,12 @@ "node": ">=4" } }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "dev": true + }, "node_modules/globby": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", @@ -8298,6 +8309,12 @@ "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", "dev": true }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, "node_modules/got": { "version": "11.8.5", "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", @@ -9029,9 +9046,9 @@ } }, "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -9117,6 +9134,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -9407,6 +9439,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -9708,13 +9752,13 @@ } }, "node_modules/jsx-ast-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz", - "integrity": "sha512-XzO9luP6L0xkxwhIJMTJQpZo/eeN60K08jHdexfD569AGxeNug6UketeHXEhROoM8aR7EcUoOQmIhcJQjcuq8Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", "dev": true, "dependencies": { - "array-includes": "^3.1.4", - "object.assign": "^4.1.2" + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" }, "engines": { "node": ">=4.0" @@ -9769,15 +9813,15 @@ "dev": true }, "node_modules/language-subtag-registry": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", "dev": true }, "node_modules/language-tags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", "dev": true, "dependencies": { "language-subtag-registry": "~0.3.2" @@ -9806,9 +9850,9 @@ } }, "node_modules/ley": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ley/-/ley-0.7.1.tgz", - "integrity": "sha512-oVgyFF+i/Uzm5q6HYY5jT+ADHkv2Z1wh8LNt2dYLvWiKN5tsEjzWmWAk8gn1VVpwI8Drj+lLYIHio7A67zskUA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/ley/-/ley-0.8.1.tgz", + "integrity": "sha512-8Nd5uzie4PxiEJcQNv5YL1IQCMzye/0sE8VPB4KczJkyd44NfDyK/7Vbmp9eHYt+dJ4hxaXy+gF4DORSxYGArg==", "dev": true, "dependencies": { "kleur": "^4.1.0", @@ -10038,7 +10082,7 @@ "node_modules/lz-string": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", "dev": true, "bin": { "lz-string": "bin/bin.js" @@ -11438,9 +11482,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "node_modules/normalize-package-data": { @@ -11591,13 +11635,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -11722,6 +11766,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -12063,9 +12124,9 @@ } }, "node_modules/postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", + "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", "dev": true, "funding": [ { @@ -12345,9 +12406,9 @@ } }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { "side-channel": "^1.0.4" }, @@ -12468,11 +12529,11 @@ "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, "node_modules/react-flip-toolkit": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/react-flip-toolkit/-/react-flip-toolkit-7.0.16.tgz", - "integrity": "sha512-ZLnXYJfYhZZ5lKP+FiUjX0lHKe8ZZoAd2HMuOAW3w5ZESNgNTyzu0pRu/bDBqlIox5UkeSlTDBt3dVBcTqv1gg==", + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/react-flip-toolkit/-/react-flip-toolkit-7.0.17.tgz", + "integrity": "sha512-dvL7CddwsPm5QHH3rRC5/I5Vjl6hp/QwqcFNIfA4ScfnbSf2xMaAMaPg0frIt0Vm+GO0PXf89hJ9RDmkGzqHKw==", "dependencies": { - "flip-toolkit": "7.0.16", + "flip-toolkit": "7.0.17", "prop-types": "^15.5.7" }, "engines": { @@ -14095,6 +14156,15 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -14152,9 +14222,9 @@ } }, "node_modules/stylelint": { - "version": "14.12.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.12.1.tgz", - "integrity": "sha512-ZEM4TuksChMBfuPadQsHUkbOoRySAT9QMfDvvYxdAchOJl0p+csTMBXOu6ORAAxKhwBmxqJiep8V88bXfNs3EQ==", + "version": "14.14.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz", + "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==", "dev": true, "dependencies": { "@csstools/selector-specificity": "^2.0.2", @@ -14180,7 +14250,7 @@ "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.16", + "postcss": "^8.4.17", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", @@ -14208,79 +14278,20 @@ } }, "node_modules/stylelint-config-idiomatic-order": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-idiomatic-order/-/stylelint-config-idiomatic-order-8.1.0.tgz", - "integrity": "sha512-iTPY6JjbkIdzy+21x3a1xi/tG33zKhLJb6lZl1xg6jZrXjgIYelnRZ5xVtbcEP9rElxZq/Zu1eGthfvI+ri+YQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-idiomatic-order/-/stylelint-config-idiomatic-order-9.0.0.tgz", + "integrity": "sha512-+LtfPycY1Paayf1MaERyh6BzVPnZxemX5NtzdUPqi4u8hyAR7859f/4EL02+Kr9va76iX7mbYC4HendocXKJZQ==", "dev": true, "dependencies": { - "stylelint-order": "^3.1.1" + "stylelint-order": "^5.0.0" + }, + "engines": { + "node": ">=12" }, "peerDependencies": { "stylelint": ">=11" } }, - "node_modules/stylelint-config-idiomatic-order/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/stylelint-config-idiomatic-order/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/stylelint-config-idiomatic-order/node_modules/postcss-sorting": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-5.0.1.tgz", - "integrity": "sha512-Y9fUFkIhfrm6i0Ta3n+89j56EFqaNRdUKqXyRp6kvTcSXnmgEjaVowCXH+JBe9+YKWqd4nc28r2sgwnzJalccA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14", - "postcss": "^7.0.17" - }, - "engines": { - "node": ">=8.7.0" - } - }, - "node_modules/stylelint-config-idiomatic-order/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stylelint-config-idiomatic-order/node_modules/stylelint-order": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-3.1.1.tgz", - "integrity": "sha512-4gP/r8j/6JGZ/LL41b2sYtQqfwZl4VSqTp7WeIwI67v/OXNQ08dnn64BGXNwAUSgb2+YIvIOxQaMzqMyQMzoyQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15", - "postcss": "^7.0.17", - "postcss-sorting": "^5.0.1" - }, - "engines": { - "node": ">=8.7.0" - }, - "peerDependencies": { - "stylelint": ">=10.0.1" - } - }, "node_modules/stylelint-config-prettier": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz", @@ -14307,15 +14318,15 @@ } }, "node_modules/stylelint-config-standard": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz", - "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-29.0.0.tgz", + "integrity": "sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==", "dev": true, "dependencies": { "stylelint-config-recommended": "^9.0.0" }, "peerDependencies": { - "stylelint": "^14.11.0" + "stylelint": "^14.14.0" } }, "node_modules/stylelint-order": { @@ -14578,6 +14589,22 @@ "react": "^16.11.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/synckit": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.4.tgz", + "integrity": "sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/table": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", @@ -14616,6 +14643,15 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -14746,10 +14782,20 @@ "xtend": "~4.0.1" } }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "dev": true, + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, "node_modules/tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, "node_modules/tmp": { "version": "0.0.33", @@ -14959,15 +15005,6 @@ "node": ">=6" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -15063,9 +15100,9 @@ } }, "node_modules/typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -15405,6 +15442,32 @@ "node": ">=8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -15445,15 +15508,14 @@ } }, "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", "which-typed-array": "^1.1.2" } }, @@ -15970,27 +16032,27 @@ } }, "@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", + "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", "dev": true }, "@babel/core": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz", - "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helpers": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -16022,12 +16084,12 @@ } }, "@babel/eslint-parser": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.18.2.tgz", - "integrity": "sha512-oFQYkE8SuH14+uR51JVAmdqwKYXGRjEXx7s+WiagVjqQ+HPE+nnwyF2qlVG8evUsUHmPcA+6YXMEDbIhEyQc5A==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", "dev": true, "requires": { - "eslint-scope": "^5.1.1", + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", "semver": "^6.3.0" }, @@ -16041,12 +16103,12 @@ } }, "@babel/generator": { - "version": "7.18.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", - "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", + "version": "7.19.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", + "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", "dev": true, "requires": { - "@babel/types": "^7.18.7", + "@babel/types": "^7.19.4", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -16090,14 +16152,14 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", - "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", + "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", "dev": true, "requires": { - "@babel/compat-data": "^7.18.6", + "@babel/compat-data": "^7.19.3", "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.20.2", + "browserslist": "^4.21.3", "semver": "^6.3.0" }, "dependencies": { @@ -16174,9 +16236,9 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", - "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "dev": true }, "@babel/helper-explode-assignable-expression": { @@ -16189,13 +16251,13 @@ } }, "@babel/helper-function-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", - "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { - "@babel/template": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" } }, "@babel/helper-hoist-variables": { @@ -16226,19 +16288,19 @@ } }, "@babel/helper-module-transforms": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.8.tgz", - "integrity": "sha512-che3jvZwIcZxrwh63VfnFTUzcAM9v/lznYkkRxIBGMPt1SudOKHAEec0SIRCfiuIzTcF7VGj/CaTT6gY4eWxvA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", + "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.8", - "@babel/types": "^7.18.8" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0" } }, "@babel/helper-optimise-call-expression": { @@ -16308,10 +16370,16 @@ "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true + }, "@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true }, "@babel/helper-validator-option": { @@ -16333,14 +16401,14 @@ } }, "@babel/helpers": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz", - "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", + "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", "dev": true, "requires": { - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.4", + "@babel/types": "^7.19.4" } }, "@babel/highlight": { @@ -16368,9 +16436,9 @@ } }, "@babel/parser": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.8.tgz", - "integrity": "sha512-RSKRfYX20dyH+elbJK2uqAkVyucL+xXzhqlMD5/ZXx+dAAwpyB7HsvnHe/ZUGOF+xLr5Wx9/JoXVTj6BQE2/oA==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", + "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -17254,40 +17322,40 @@ } }, "@babel/runtime-corejs3": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz", - "integrity": "sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.19.4.tgz", + "integrity": "sha512-HzjQ8+dzdx7dmZy4DQ8KV8aHi/74AjEbBGTFutBmg/pd3dY5/q1sfuOGPTFGEytlQhWoeVXqcK5BwMgIkRkNDQ==", "dev": true, "requires": { - "core-js-pure": "^3.20.2", + "core-js-pure": "^3.25.1", "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", - "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" } }, "@babel/traverse": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.8.tgz", - "integrity": "sha512-UNg/AcSySJYR/+mIcJQDCv00T+AqRO7j/ZEJLzpaYtgM48rMg5MnkJgyNqkzo88+p4tfRvZJCEiwwfG6h4jkRg==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", + "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.7", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", + "@babel/generator": "^7.19.4", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.8", - "@babel/types": "^7.18.8", + "@babel/parser": "^7.19.4", + "@babel/types": "^7.19.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -17310,12 +17378,13 @@ } }, "@babel/types": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.8.tgz", - "integrity": "sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", + "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, @@ -17445,9 +17514,9 @@ } }, "@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -17488,9 +17557,9 @@ } }, "@faker-js/faker": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.5.0.tgz", - "integrity": "sha512-8wNUCCUHvfvI0gQpDUho/3gPzABffnCn5um65F8dzQ86zz6dlt4+nmAA7PQUc8L+eH+9RgR/qzy5N/8kN0Ozdw==" + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", + "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==" }, "@gar/promisify": { "version": "1.1.3", @@ -17499,15 +17568,15 @@ "dev": true }, "@headlessui/react": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.2.tgz", - "integrity": "sha512-snLv2lxwsf2HNTOBNgHYdvoYZ3ChJE8QszPi1d/hl9js8KrFrUulTaQBfSyPbJP5BybVreWh9DxCgz9S0Z6hKQ==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.3.tgz", + "integrity": "sha512-LGp06SrGv7BMaIQlTs8s2G06moqkI0cb0b8stgq7KZ3xcHdH3qMP+cRyV7qe5x4XEW/IGY48BW4fLesD6NQLng==", "requires": {} }, "@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -17532,12 +17601,6 @@ } } }, - "@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true - }, "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -17588,6 +17651,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -17643,15 +17715,29 @@ "json-parse-even-better-errors": "^2.3.1" } }, + "@pkgr/utils": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "is-glob": "^4.0.3", + "open": "^8.4.0", + "picocolors": "^1.0.0", + "tiny-glob": "^0.2.9", + "tslib": "^2.4.0" + } + }, "@popperjs/core": { "version": "2.11.6", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" }, "@remix-run/dev": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-1.7.1.tgz", - "integrity": "sha512-yjxcCDb48mPUjiogGtxbWpoxauiM6jnSel2oyhztYlenfCM3wDzN2tOqBkfidNFlqpNQCkiRBN4FV97I03hDNw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-1.7.2.tgz", + "integrity": "sha512-oJcaju9zID+xOUnkMQJBEbjiiYBvILVsX64Fzi1itlm5vjNuo99nmKM7gleaDawNLo3lyd6Xd+JyMa3aIwDKOQ==", "dev": true, "requires": { "@babel/core": "^7.18.6", @@ -17660,7 +17746,7 @@ "@babel/preset-typescript": "^7.18.6", "@esbuild-plugins/node-modules-polyfill": "^0.1.4", "@npmcli/package-json": "^2.0.0", - "@remix-run/server-runtime": "1.7.1", + "@remix-run/server-runtime": "1.7.2", "@yarnpkg/esbuild-plugin-pnp": "3.0.0-rc.11", "arg": "^5.0.1", "cacache": "^15.0.5", @@ -17704,43 +17790,43 @@ } }, "@remix-run/eslint-config": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/eslint-config/-/eslint-config-1.7.1.tgz", - "integrity": "sha512-rroBQio5hhLf1mb/7IXoFXTkyrrZewbm8ZLbnYTgDA4Un0+MTFHr/7eQoyY+Xa858CWVdj0eZoGhCfmJQNkWVQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/eslint-config/-/eslint-config-1.7.2.tgz", + "integrity": "sha512-ikYWq570XnBt+E1FZ3PZxJliYPONaWNNG16eER+4/dp9GNQQApKBGfn5hs6256+678RNgFCCBx++W9BaJTBjgQ==", "dev": true, "requires": { - "@babel/core": "^7.18.6", - "@babel/eslint-parser": "^7.18.2", + "@babel/core": "^7.19.1", + "@babel/eslint-parser": "^7.19.1", "@babel/preset-react": "^7.18.6", - "@rushstack/eslint-patch": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^5.12.1", - "@typescript-eslint/parser": "^5.12.1", + "@rushstack/eslint-patch": "^1.2.0", + "@typescript-eslint/eslint-plugin": "^5.38.0", + "@typescript-eslint/parser": "^5.38.0", "eslint-import-resolver-node": "0.3.6", - "eslint-import-resolver-typescript": "^2.5.0", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^26.1.1", - "eslint-plugin-jest-dom": "^4.0.1", - "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-import-resolver-typescript": "^3.5.1", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jest": "^26.9.0", + "eslint-plugin-jest-dom": "^4.0.2", + "eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-testing-library": "^5.0.5" + "eslint-plugin-react": "^7.31.8", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-testing-library": "^5.6.4" } }, "@remix-run/express": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-1.7.1.tgz", - "integrity": "sha512-2m+kBiBQktRVMqf7m1e0CL8dvB7Pp9o7aaDy90IP6PAbiYrM3Hex11ad7cWe0PeqtYPexIKP5L/rAxIoUMuRGA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-1.7.2.tgz", + "integrity": "sha512-s2r5EOhOWLHH7cQtJfxcucI1K7iQA66mvoTstPjtU0/0pe8ZI+wBZopKxQMUEdjFG/ShnRIb1cPFHHF5VJLNfA==", "requires": { - "@remix-run/node": "1.7.1" + "@remix-run/node": "1.7.2" } }, "@remix-run/node": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-1.7.1.tgz", - "integrity": "sha512-vAffiWDXQ1RHzN9cicSHWOJgvcC9A4KZA8nrJlBf5TU0w/DrnrsdrCaaESs9eQ2rby2R1YiRA8kE3HBg8efScA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-1.7.2.tgz", + "integrity": "sha512-cLm5IuVPV7E0VK8LzrFAurG8dq8/HRc0WIE6Urj8bhbv0tCTJvFRfcCbCmDRRHmR72VmPkRahJov5f1Ab9jjQw==", "requires": { - "@remix-run/server-runtime": "1.7.1", + "@remix-run/server-runtime": "1.7.2", "@remix-run/web-fetch": "^4.1.3", "@remix-run/web-file": "^3.0.2", "@remix-run/web-stream": "^1.0.3", @@ -17752,37 +17838,29 @@ } }, "@remix-run/react": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-1.7.1.tgz", - "integrity": "sha512-RraUPjLZc4vSgT51uloamOn1Gm/YCohL1jDTBbiWuDgnTwBu741vC0zoulzoD+eV2svfKijOHL0tXc8kEAWPdg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-1.7.2.tgz", + "integrity": "sha512-019y9WGdMA2i7/grLwpH1xqK3QxSmzNoMAwZ2ytnM/if6AHXrSz9BCn4urt6jYrDEuSOAwzOm65xd/fKNU45aQ==", "requires": { "history": "^5.3.0", - "react-router-dom": "6.3.0", - "type-fest": "^2.17.0" - }, - "dependencies": { - "type-fest": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.18.0.tgz", - "integrity": "sha512-pRS+/yrW5TjPPHNOvxhbNZexr2bS63WjrMU8a+VzEBhUi9Tz1pZeD+vQz3ut0svZ46P+SRqMEPnJmk2XnvNzTw==" - } + "react-router-dom": "6.3.0" } }, "@remix-run/serve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-1.7.1.tgz", - "integrity": "sha512-qPqu9+Aa3VJKvLw71tdoBTc59PjSKKk/I6MXl6NPULimcIdvvwmWXfqmfRdpOaCAYlNBMIqIacZGyFxMpzF5Dw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/serve/-/serve-1.7.2.tgz", + "integrity": "sha512-5zSwbuka3agWL8mD3qHAG/b3iQWfRfkem8NtgtU5YzWkXHwOnXFyenak+3Jku3PRSZ+g00RhWE9cilzCtiAiGQ==", "requires": { - "@remix-run/express": "1.7.1", + "@remix-run/express": "1.7.2", "compression": "^1.7.4", "express": "^4.17.1", "morgan": "^1.10.0" } }, "@remix-run/server-runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-1.7.1.tgz", - "integrity": "sha512-bvKuESSf7cW5ORlXayVPWHDpU8xiglKu7PQtiyKi+Gwjasp/GnUO6Xwqpy2HqHtoC7RNQYt2oRkWc/pRhpe55g==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-1.7.2.tgz", + "integrity": "sha512-YqdYHjqAukh5wbfix6ZqibUX5wYLm4SyyhibPiTthAV6SXHbTMu952jqf6Fa+asJRSf+QlNVwsizxH0zUGPAtw==", "requires": { "@types/cookie": "^0.4.0", "@web3-storage/multipart-parser": "^1.0.0", @@ -17802,14 +17880,15 @@ } }, "@remix-run/web-fetch": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.2.0.tgz", - "integrity": "sha512-Bll+4Z3CT4ryYKRFTbdanLaXbOjtSuwYcj8s6DSXehVcZWWrz7mA3O394T52iFjvhaJ+ELSstNhVeBQc6NUfGg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.3.1.tgz", + "integrity": "sha512-TOpuJo3jI7/qJAY0yTnvNJRQl4hlWAOHUHYKAbEddcLFLydv+0/WGT6OaIurJKsBFJJTjooe3FbKiP74sUIB/g==", "requires": { "@remix-run/web-blob": "^3.0.4", "@remix-run/web-form-data": "^3.0.3", "@remix-run/web-stream": "^1.0.3", "@web3-storage/multipart-parser": "^1.0.0", + "abort-controller": "^3.0.0", "data-uri-to-buffer": "^3.0.1", "mrmime": "^1.0.0" } @@ -17857,9 +17936,9 @@ } }, "@rushstack/eslint-patch": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz", - "integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", "dev": true }, "@sindresorhus/is": { @@ -17878,9 +17957,9 @@ } }, "@testing-library/dom": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.13.0.tgz", - "integrity": "sha512-9VHgfIatKNXQNaZTtLnalIy0jNZzY35a4S3oi08YAt9Hv1VsfZ/DfA45lM8D/UhtHBGJ4/lGwp0PZkVndRkoOQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.0.tgz", + "integrity": "sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", @@ -17933,9 +18012,9 @@ "dev": true }, "@types/better-sqlite3": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.0.tgz", - "integrity": "sha512-rnSP9vY+fVsF3iJja5yRGBJV63PNBiezJlYrCkqUmQWFoB16cxAHwOkjsAYEu317miOfKaJpa65cbp0P4XJ/jw==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.2.tgz", + "integrity": "sha512-RgmaapusqTq6IMAr4McMyAsC6RshYTCjXCnzwVV59WctUxC8bNPyUfT9t5F81lKcU41lLurhjqjoMHfauzfqGg==", "dev": true, "requires": { "@types/node": "*" @@ -18112,9 +18191,9 @@ "dev": true }, "@types/react": { - "version": "18.0.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz", - "integrity": "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==", + "version": "18.0.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", + "integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==", "dev": true, "requires": { "@types/prop-types": "*", @@ -18146,6 +18225,12 @@ "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "dev": true }, + "@types/semver": { + "version": "7.3.12", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.12.tgz", + "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", + "dev": true + }, "@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -18175,14 +18260,14 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.0.tgz", - "integrity": "sha512-GgHi/GNuUbTOeoJiEANi0oI6fF3gBQc3bGFYj40nnAPCbhrtEDf2rjBmefFadweBmO1Du1YovHeDP2h5JLhtTQ==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", + "integrity": "sha512-FsWboKkWdytGiXT5O1/R9j37YgcjO8MKHSUmWnIEjVaz0krHkplPnYi7mwdb+5+cs0toFNQb0HIrN7zONdIEWg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/type-utils": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/type-utils": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -18208,14 +18293,14 @@ } }, "@typescript-eslint/parser": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.0.tgz", - "integrity": "sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.40.1.tgz", + "integrity": "sha512-IK6x55va5w4YvXd4b3VrXQPldV9vQTxi5ov+g4pMANsXPTXOcfjx08CRR1Dfrcc51syPtXHF5bgLlMHYFrvQtg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "debug": "^4.3.4" }, "dependencies": { @@ -18237,23 +18322,23 @@ } }, "@typescript-eslint/scope-manager": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz", - "integrity": "sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz", + "integrity": "sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0" + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1" } }, "@typescript-eslint/type-utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.0.tgz", - "integrity": "sha512-iZq5USgybUcj/lfnbuelJ0j3K9dbs1I3RICAJY9NZZpDgBYXmuUlYQGzftpQA9wC8cKgtS6DASTvF3HrXwwozA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.40.1.tgz", + "integrity": "sha512-DLAs+AHQOe6n5LRraXiv27IYPhleF0ldEmx6yBqBgBLaNRKTkffhV1RPsjoJBhVup2zHxfaRtan8/YRBgYhU9Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/typescript-estree": "5.40.1", + "@typescript-eslint/utils": "5.40.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -18276,19 +18361,19 @@ } }, "@typescript-eslint/types": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.0.tgz", - "integrity": "sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.40.1.tgz", + "integrity": "sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz", - "integrity": "sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz", + "integrity": "sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/visitor-keys": "5.40.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -18328,26 +18413,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.0.tgz", - "integrity": "sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.40.1.tgz", + "integrity": "sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.40.1", + "@typescript-eslint/types": "5.40.1", + "@typescript-eslint/typescript-estree": "5.40.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz", - "integrity": "sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz", + "integrity": "sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", + "@typescript-eslint/types": "5.40.1", "eslint-visitor-keys": "^3.3.0" }, "dependencies": { @@ -18535,9 +18622,9 @@ "dev": true }, "aria-query": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", - "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", "dev": true }, "arr-diff": { @@ -18651,7 +18738,7 @@ "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", "dev": true }, "astral-regex": { @@ -18708,9 +18795,9 @@ "dev": true }, "axe-core": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", - "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", + "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==", "dev": true }, "axobject-query": { @@ -18933,9 +19020,9 @@ "dev": true }, "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.4", @@ -18945,7 +19032,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", + "qs": "6.11.0", "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -18987,16 +19074,15 @@ } }, "browserslist": { - "version": "4.20.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", - "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001349", - "electron-to-chromium": "^1.4.147", - "escalade": "^3.1.1", - "node-releases": "^2.0.5", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" } }, "buffer": { @@ -19148,9 +19234,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001356", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001356.tgz", - "integrity": "sha512-/30854bktMLhxtjieIxsrJBfs2gTM1pel6MXKF3K+RdIVJZcsn2A2QdhsuR4/p9+R204fZw0zCBBhktX8xWuyQ==", + "version": "1.0.30001422", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz", + "integrity": "sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog==", "dev": true }, "caseless": { @@ -19616,9 +19702,9 @@ } }, "core-js-pure": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.4.tgz", - "integrity": "sha512-4iF+QZkpzIz0prAFuepmxwJ2h5t4agvE8WPYqs2mjLJMNNwJOnpch76w2Q7bUfCPEv/V7wpvOfog0w273M+ZSw==", + "version": "3.25.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.5.tgz", + "integrity": "sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg==", "dev": true }, "core-util-is": { @@ -19721,9 +19807,9 @@ "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==" }, "cypress": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.8.0.tgz", - "integrity": "sha512-QVse0dnLm018hgti2enKMVZR9qbIO488YGX06nH5j3Dg1isL38DwrBtyrax02CANU6y8F4EJUuyW6HJKw1jsFA==", + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-10.10.0.tgz", + "integrity": "sha512-bU8r44x1NIYAUNNXt3CwJpLOVth7HUv2hUhYCxZmgZ1IugowDvuHNpevnoZRQx1KKOEisLvIJW+Xen5Pjn41pg==", "dev": true, "requires": { "@cypress/request": "^2.88.10", @@ -20001,6 +20087,12 @@ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true + }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -20126,9 +20218,9 @@ "dev": true }, "dotenv": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz", - "integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "dev": true }, "duplexify": { @@ -20159,9 +20251,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.4.161", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.161.tgz", - "integrity": "sha512-sTjBRhqh6wFodzZtc5Iu8/R95OkwaPNn7tj/TaDU5nu/5EFiQDtADGAXdR4tJcTEHlYfJpHqigzJqHvPgehP8A==", + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, "emoji-regex": { @@ -20188,6 +20280,16 @@ "once": "^1.4.0" } }, + "enhanced-resolve": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -20449,14 +20551,13 @@ "dev": true }, "eslint": { - "version": "8.23.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz", - "integrity": "sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.25.0.tgz", + "integrity": "sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.2", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.10.5", "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -20652,16 +20753,18 @@ } }, "eslint-import-resolver-typescript": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz", - "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.1.tgz", + "integrity": "sha512-U7LUjNJPYjNsHvAUAkt/RU3fcTSpbllA0//35B4eLYTX74frmOepbt7F7J3D1IGtj9k21buOpaqtDd4ZlS/BYQ==", "dev": true, "requires": { "debug": "^4.3.4", - "glob": "^7.2.0", + "enhanced-resolve": "^5.10.0", + "get-tsconfig": "^4.2.0", + "globby": "^13.1.2", + "is-core-module": "^2.10.0", "is-glob": "^4.0.3", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "synckit": "^0.8.3" }, "dependencies": { "debug": { @@ -20673,13 +20776,17 @@ "ms": "2.1.2" } }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "globby": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", + "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", "dev": true, "requires": { - "minimist": "^1.2.0" + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" } }, "ms": { @@ -20688,34 +20795,21 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true - }, - "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } } } }, "eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "dependencies": { "debug": { @@ -20727,54 +20821,11 @@ "ms": "^2.1.1" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true } } }, @@ -20835,12 +20886,6 @@ "minimist": "^1.2.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -20856,18 +20901,18 @@ } }, "eslint-plugin-jest": { - "version": "26.1.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.1.5.tgz", - "integrity": "sha512-su89aDuljL9bTjEufTXmKUMSFe2kZUL9bi7+woq+C2ukHZordhtfPm4Vg+tdioHBaKf8v3/FXW9uV0ksqhYGFw==", + "version": "26.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", + "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" } }, "eslint-plugin-jest-dom": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-4.0.1.tgz", - "integrity": "sha512-9aUaX4AtlFBziLqKSjc7DKHQ/y1T32qNapG3uSeLDMJYKswASoQLJWOfLIE+zEHKvCNzNIz8T7282tQkuu0TKQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-4.0.2.tgz", + "integrity": "sha512-Jo51Atwyo2TdcUncjmU+UQeSTKh3sc2LF/M5i/R3nTU0Djw9V65KGJisdm/RtuKhy2KH/r7eQ1n6kwYFPNdHlA==", "dev": true, "requires": { "@babel/runtime": "^7.16.3", @@ -20876,23 +20921,24 @@ } }, "eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz", + "integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==", "dev": true, "requires": { - "@babel/runtime": "^7.16.3", + "@babel/runtime": "^7.18.9", "aria-query": "^4.2.2", - "array-includes": "^3.1.4", + "array-includes": "^3.1.5", "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", + "axe-core": "^4.4.3", "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", + "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", + "jsx-ast-utils": "^3.3.2", "language-tags": "^1.0.5", - "minimatch": "^3.0.4" + "minimatch": "^3.1.2", + "semver": "^6.3.0" }, "dependencies": { "aria-query": { @@ -20910,6 +20956,12 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -20951,9 +21003,9 @@ } }, "eslint-plugin-react": { - "version": "7.31.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz", - "integrity": "sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==", + "version": "7.31.10", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz", + "integrity": "sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==", "dev": true, "requires": { "array-includes": "^3.1.5", @@ -21004,9 +21056,9 @@ "requires": {} }, "eslint-plugin-testing-library": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.4.0.tgz", - "integrity": "sha512-XjxIf4g33KaZXxRNbR33+0WcRQ/zt8N0R58IY6/kkHnrY6zPsC1gs3u5cTZr5eUmCZN/sjoPak3uF5vHGKg2wg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.8.0.tgz", + "integrity": "sha512-QzOKgu4x8WmNq4LdbHb8lz5nBR+KX5kSg5VvIdr/5f1BvHx2IoO1B/tgDa5pD/ng2LsiQ0/HIH6gsUuxpbcrkQ==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.13.0" @@ -21268,13 +21320,13 @@ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -21293,7 +21345,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.10.3", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.18.0", @@ -21630,9 +21682,9 @@ "dev": true }, "flip-toolkit": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/flip-toolkit/-/flip-toolkit-7.0.16.tgz", - "integrity": "sha512-MeoLilutfKSGtN8kdUsIU3x0y+84RnnK2rgUcQ6CgVTeIsWxmEAmLBq+p3YGT0lNIZf6bqqUyyKLo0jkBTgRvg==", + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/flip-toolkit/-/flip-toolkit-7.0.17.tgz", + "integrity": "sha512-bybUdLNbC80F0+v+t3TBfxEAMVGhvXLi3pZ+qTtr4aCu/Y/5YQimMij0xJKT1qtz4SO31V4zftIgaTJdCCFiHA==", "requires": { "rematrix": "0.2.2" } @@ -21831,6 +21883,12 @@ "get-intrinsic": "^1.1.1" } }, + "get-tsconfig": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.2.0.tgz", + "integrity": "sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==", + "dev": true + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -21943,6 +22001,12 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "dev": true + }, "globby": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", @@ -21965,6 +22029,12 @@ "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", "dev": true }, + "globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, "got": { "version": "11.8.5", "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", @@ -22516,9 +22586,9 @@ } }, "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "requires": { "has": "^1.0.3" @@ -22583,6 +22653,12 @@ } } }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -22770,6 +22846,15 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -23026,13 +23111,13 @@ } }, "jsx-ast-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz", - "integrity": "sha512-XzO9luP6L0xkxwhIJMTJQpZo/eeN60K08jHdexfD569AGxeNug6UketeHXEhROoM8aR7EcUoOQmIhcJQjcuq8Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", "dev": true, "requires": { - "array-includes": "^3.1.4", - "object.assign": "^4.1.2" + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" } }, "just-capitalize": { @@ -23078,15 +23163,15 @@ "dev": true }, "language-subtag-registry": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", - "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", "dev": true }, "language-tags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", "dev": true, "requires": { "language-subtag-registry": "~0.3.2" @@ -23109,9 +23194,9 @@ } }, "ley": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ley/-/ley-0.7.1.tgz", - "integrity": "sha512-oVgyFF+i/Uzm5q6HYY5jT+ADHkv2Z1wh8LNt2dYLvWiKN5tsEjzWmWAk8gn1VVpwI8Drj+lLYIHio7A67zskUA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/ley/-/ley-0.8.1.tgz", + "integrity": "sha512-8Nd5uzie4PxiEJcQNv5YL1IQCMzye/0sE8VPB4KczJkyd44NfDyK/7Vbmp9eHYt+dJ4hxaXy+gF4DORSxYGArg==", "dev": true, "requires": { "kleur": "^4.1.0", @@ -23283,7 +23368,7 @@ "lz-string": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", "dev": true }, "magic-string": { @@ -24225,9 +24310,9 @@ } }, "node-releases": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "normalize-package-data": { @@ -24343,13 +24428,13 @@ } }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, @@ -24435,6 +24520,17 @@ "mimic-fn": "^2.1.0" } }, + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -24693,9 +24789,9 @@ "dev": true }, "postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", + "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", "dev": true, "requires": { "nanoid": "^3.3.4", @@ -24905,9 +25001,9 @@ "dev": true }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "requires": { "side-channel": "^1.0.4" } @@ -24988,11 +25084,11 @@ "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, "react-flip-toolkit": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/react-flip-toolkit/-/react-flip-toolkit-7.0.16.tgz", - "integrity": "sha512-ZLnXYJfYhZZ5lKP+FiUjX0lHKe8ZZoAd2HMuOAW3w5ZESNgNTyzu0pRu/bDBqlIox5UkeSlTDBt3dVBcTqv1gg==", + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/react-flip-toolkit/-/react-flip-toolkit-7.0.17.tgz", + "integrity": "sha512-dvL7CddwsPm5QHH3rRC5/I5Vjl6hp/QwqcFNIfA4ScfnbSf2xMaAMaPg0frIt0Vm+GO0PXf89hJ9RDmkGzqHKw==", "requires": { - "flip-toolkit": "7.0.16", + "flip-toolkit": "7.0.17", "prop-types": "^15.5.7" } }, @@ -26242,6 +26338,12 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, "strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -26284,9 +26386,9 @@ } }, "stylelint": { - "version": "14.12.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.12.1.tgz", - "integrity": "sha512-ZEM4TuksChMBfuPadQsHUkbOoRySAT9QMfDvvYxdAchOJl0p+csTMBXOu6ORAAxKhwBmxqJiep8V88bXfNs3EQ==", + "version": "14.14.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.14.0.tgz", + "integrity": "sha512-yUI+4xXfPHVnueYddSQ/e1GuEA/2wVhWQbGj16AmWLtQJtn28lVxfS4b0CsWyVRPgd3Auzi0NXOthIEUhtQmmA==", "dev": true, "requires": { "@csstools/selector-specificity": "^2.0.2", @@ -26312,7 +26414,7 @@ "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.16", + "postcss": "^8.4.17", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", @@ -26455,57 +26557,12 @@ } }, "stylelint-config-idiomatic-order": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-idiomatic-order/-/stylelint-config-idiomatic-order-8.1.0.tgz", - "integrity": "sha512-iTPY6JjbkIdzy+21x3a1xi/tG33zKhLJb6lZl1xg6jZrXjgIYelnRZ5xVtbcEP9rElxZq/Zu1eGthfvI+ri+YQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-idiomatic-order/-/stylelint-config-idiomatic-order-9.0.0.tgz", + "integrity": "sha512-+LtfPycY1Paayf1MaERyh6BzVPnZxemX5NtzdUPqi4u8hyAR7859f/4EL02+Kr9va76iX7mbYC4HendocXKJZQ==", "dev": true, "requires": { - "stylelint-order": "^3.1.1" - }, - "dependencies": { - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "postcss-sorting": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-5.0.1.tgz", - "integrity": "sha512-Y9fUFkIhfrm6i0Ta3n+89j56EFqaNRdUKqXyRp6kvTcSXnmgEjaVowCXH+JBe9+YKWqd4nc28r2sgwnzJalccA==", - "dev": true, - "requires": { - "lodash": "^4.17.14", - "postcss": "^7.0.17" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "stylelint-order": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-3.1.1.tgz", - "integrity": "sha512-4gP/r8j/6JGZ/LL41b2sYtQqfwZl4VSqTp7WeIwI67v/OXNQ08dnn64BGXNwAUSgb2+YIvIOxQaMzqMyQMzoyQ==", - "dev": true, - "requires": { - "lodash": "^4.17.15", - "postcss": "^7.0.17", - "postcss-sorting": "^5.0.1" - } - } + "stylelint-order": "^5.0.0" } }, "stylelint-config-prettier": { @@ -26523,9 +26580,9 @@ "requires": {} }, "stylelint-config-standard": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-28.0.0.tgz", - "integrity": "sha512-q/StuowDdDmFCravzGHAwgS9pjX0bdOQUEBBDIkIWsQuYGgYz/xsO8CM6eepmIQ1fc5bKdDVimlJZ6MoOUcJ5Q==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-29.0.0.tgz", + "integrity": "sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==", "dev": true, "requires": { "stylelint-config-recommended": "^9.0.0" @@ -26600,6 +26657,16 @@ "integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==", "requires": {} }, + "synckit": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.4.tgz", + "integrity": "sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==", + "dev": true, + "requires": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.4.0" + } + }, "table": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", @@ -26633,6 +26700,12 @@ } } }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, "tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -26751,10 +26824,20 @@ "xtend": "~4.0.1" } }, + "tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "dev": true, + "requires": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, "tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, "tmp": { "version": "0.0.33", @@ -26904,14 +26987,6 @@ "json5": "^2.2.1", "minimist": "^1.2.6", "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } } }, "tslib": { @@ -26984,9 +27059,9 @@ } }, "typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, "unbox-primitive": { @@ -27223,6 +27298,16 @@ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -27253,15 +27338,14 @@ } }, "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "requires": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", "which-typed-array": "^1.1.2" } }, diff --git a/package.json b/package.json index 0f27bcfd0..71292579d 100644 --- a/package.json +++ b/package.json @@ -33,12 +33,12 @@ "cf": "npm run test:unit && npm run lint:styles -- --fix && npm run lint:ts -- --fix && npm run prettier:write && npm run typecheck" }, "dependencies": { - "@faker-js/faker": "^7.5.0", - "@headlessui/react": "^1.7.2", + "@faker-js/faker": "^7.6.0", + "@headlessui/react": "^1.7.3", "@popperjs/core": "^2.11.6", - "@remix-run/node": "^1.7.1", - "@remix-run/react": "^1.7.1", - "@remix-run/serve": "^1.7.1", + "@remix-run/node": "^1.7.2", + "@remix-run/react": "^1.7.2", + "@remix-run/serve": "^1.7.2", "better-sqlite3": "^7.6.2", "clsx": "^1.2.1", "countries-list": "^2.6.1", @@ -56,7 +56,7 @@ "node-cron": "3.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-flip-toolkit": "^7.0.16", + "react-flip-toolkit": "^7.0.17", "react-i18next": "^11.18.6", "react-popper": "^2.3.0", "react-use": "^17.4.0", @@ -65,36 +65,36 @@ "remix-i18next": "^4.1.1", "slugify": "^1.6.5", "swr": "^1.3.0", - "tiny-invariant": "^1.2.0", + "tiny-invariant": "^1.3.1", "zod": "^3.19.1" }, "devDependencies": { - "@remix-run/dev": "^1.7.1", - "@remix-run/eslint-config": "^1.7.1", - "@types/better-sqlite3": "^7.6.0", + "@remix-run/dev": "^1.7.2", + "@remix-run/eslint-config": "^1.7.2", + "@types/better-sqlite3": "^7.6.2", "@types/i18next-fs-backend": "^1.1.2", "@types/node-cron": "^3.0.4", - "@types/react": "^18.0.20", + "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", - "@typescript-eslint/eslint-plugin": "^5.38.0", - "@typescript-eslint/parser": "^5.38.0", + "@typescript-eslint/eslint-plugin": "^5.40.1", + "@typescript-eslint/parser": "^5.40.1", "cross-env": "^7.0.3", - "cypress": "^10.8.0", - "dotenv": "^16.0.2", - "eslint": "^8.23.1", - "eslint-plugin-react": "^7.31.8", + "cypress": "^10.10.0", + "dotenv": "^16.0.3", + "eslint": "^8.25.0", + "eslint-plugin-react": "^7.31.10", "eslint-plugin-react-hooks": "^4.6.0", - "ley": "^0.7.1", + "ley": "^0.8.1", "prettier": "^2.7.1", - "stylelint": "^14.12.1", - "stylelint-config-idiomatic-order": "^8.1.0", + "stylelint": "^14.14.0", + "stylelint-config-idiomatic-order": "^9.0.0", "stylelint-config-prettier": "^9.0.3", - "stylelint-config-standard": "^28.0.0", + "stylelint-config-standard": "^29.0.0", "stylelint-order": "^5.0.0", "ts-node": "^10.9.1", "tsconfig-paths": "^4.1.0", "tsm": "^2.2.2", - "typescript": "^4.8.3", + "typescript": "^4.8.4", "uvu": "^0.5.6" }, "engines": { From 68cdbde5954b506af8db6d04b93b1b237fe4c95b Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:17:36 +0300 Subject: [PATCH 14/47] Upgrade i18next major --- package-lock.json | 78 ++++++++++++++++++++++++++++++++++------------- package.json | 4 +-- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index af36fc181..0d9452c77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,8 @@ "date-fns": "^2.29.3", "fuse.js": "^6.6.2", "gray-matter": "^4.0.3", - "i18next": "^21.9.2", - "i18next-browser-languagedetector": "^6.1.5", + "i18next": "^22.0.1", + "i18next-browser-languagedetector": "^6.1.8", "i18next-fs-backend": "^1.1.5", "i18next-http-backend": "^1.4.4", "just-capitalize": "^3.1.1", @@ -1965,9 +1965,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", - "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", + "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -2942,6 +2942,29 @@ "i18next": "^21.0.1" } }, + "node_modules/@types/i18next-fs-backend/node_modules/i18next": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", + "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.17.2" + } + }, "node_modules/@types/js-cookie": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", @@ -8690,9 +8713,9 @@ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, "node_modules/i18next": { - "version": "21.9.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz", - "integrity": "sha512-00fVrLQOwy45nm3OtC9l1WiLK3nJlIYSljgCt0qzTaAy65aciMdRy9GsuW+a2AtKtdg9/njUGfRH30LRupV7ZQ==", + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.0.1.tgz", + "integrity": "sha512-CRbtl6urEcIDbIzP4sGoPf9YuDNto1JgCRsfdvcVUOPb8nPAQ0azhPZiSdD5AFg/Erb58+/nDRmhm8bzVyjABQ==", "funding": [ { "type": "individual", @@ -8712,11 +8735,11 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.5.tgz", - "integrity": "sha512-11t7b39oKeZe4uyMxLSPnfw28BCPNLZgUk7zyufex0zKXZ+Bv+JnmJgoB+IfQLZwDt1d71PM8vwBX1NCgliY3g==", + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", + "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", "dependencies": { - "@babel/runtime": "^7.18.9" + "@babel/runtime": "^7.19.0" } }, "node_modules/i18next-fs-backend": { @@ -17314,9 +17337,9 @@ } }, "@babel/runtime": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", - "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", + "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -18093,6 +18116,17 @@ "dev": true, "requires": { "i18next": "^21.0.1" + }, + "dependencies": { + "i18next": { + "version": "21.10.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", + "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.17.2" + } + } } }, "@types/js-cookie": { @@ -22330,19 +22364,19 @@ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, "i18next": { - "version": "21.9.2", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz", - "integrity": "sha512-00fVrLQOwy45nm3OtC9l1WiLK3nJlIYSljgCt0qzTaAy65aciMdRy9GsuW+a2AtKtdg9/njUGfRH30LRupV7ZQ==", + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.0.1.tgz", + "integrity": "sha512-CRbtl6urEcIDbIzP4sGoPf9YuDNto1JgCRsfdvcVUOPb8nPAQ0azhPZiSdD5AFg/Erb58+/nDRmhm8bzVyjABQ==", "requires": { "@babel/runtime": "^7.17.2" } }, "i18next-browser-languagedetector": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.5.tgz", - "integrity": "sha512-11t7b39oKeZe4uyMxLSPnfw28BCPNLZgUk7zyufex0zKXZ+Bv+JnmJgoB+IfQLZwDt1d71PM8vwBX1NCgliY3g==", + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", + "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", "requires": { - "@babel/runtime": "^7.18.9" + "@babel/runtime": "^7.19.0" } }, "i18next-fs-backend": { diff --git a/package.json b/package.json index 71292579d..d4dabad2a 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,8 @@ "date-fns": "^2.29.3", "fuse.js": "^6.6.2", "gray-matter": "^4.0.3", - "i18next": "^21.9.2", - "i18next-browser-languagedetector": "^6.1.5", + "i18next": "^22.0.1", + "i18next-browser-languagedetector": "^6.1.8", "i18next-fs-backend": "^1.1.5", "i18next-http-backend": "^1.4.4", "just-capitalize": "^3.1.1", From 7f9bc0b5bc6d372af00e0eeafcf255d7fb9520c2 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:18:34 +0300 Subject: [PATCH 15/47] Revert "Upgrade i18next major" This reverts commit 68cdbde5954b506af8db6d04b93b1b237fe4c95b. --- package-lock.json | 78 +++++++++++++---------------------------------- package.json | 4 +-- 2 files changed, 24 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d9452c77..af36fc181 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,8 @@ "date-fns": "^2.29.3", "fuse.js": "^6.6.2", "gray-matter": "^4.0.3", - "i18next": "^22.0.1", - "i18next-browser-languagedetector": "^6.1.8", + "i18next": "^21.9.2", + "i18next-browser-languagedetector": "^6.1.5", "i18next-fs-backend": "^1.1.5", "i18next-http-backend": "^1.4.4", "just-capitalize": "^3.1.1", @@ -1965,9 +1965,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", - "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -2942,29 +2942,6 @@ "i18next": "^21.0.1" } }, - "node_modules/@types/i18next-fs-backend/node_modules/i18next": { - "version": "21.10.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", - "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://locize.com" - }, - { - "type": "individual", - "url": "https://locize.com/i18next.html" - }, - { - "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" - } - ], - "dependencies": { - "@babel/runtime": "^7.17.2" - } - }, "node_modules/@types/js-cookie": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", @@ -8713,9 +8690,9 @@ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, "node_modules/i18next": { - "version": "22.0.1", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.0.1.tgz", - "integrity": "sha512-CRbtl6urEcIDbIzP4sGoPf9YuDNto1JgCRsfdvcVUOPb8nPAQ0azhPZiSdD5AFg/Erb58+/nDRmhm8bzVyjABQ==", + "version": "21.9.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz", + "integrity": "sha512-00fVrLQOwy45nm3OtC9l1WiLK3nJlIYSljgCt0qzTaAy65aciMdRy9GsuW+a2AtKtdg9/njUGfRH30LRupV7ZQ==", "funding": [ { "type": "individual", @@ -8735,11 +8712,11 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", - "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.5.tgz", + "integrity": "sha512-11t7b39oKeZe4uyMxLSPnfw28BCPNLZgUk7zyufex0zKXZ+Bv+JnmJgoB+IfQLZwDt1d71PM8vwBX1NCgliY3g==", "dependencies": { - "@babel/runtime": "^7.19.0" + "@babel/runtime": "^7.18.9" } }, "node_modules/i18next-fs-backend": { @@ -17337,9 +17314,9 @@ } }, "@babel/runtime": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz", - "integrity": "sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -18116,17 +18093,6 @@ "dev": true, "requires": { "i18next": "^21.0.1" - }, - "dependencies": { - "i18next": { - "version": "21.10.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.10.0.tgz", - "integrity": "sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.17.2" - } - } } }, "@types/js-cookie": { @@ -22364,19 +22330,19 @@ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, "i18next": { - "version": "22.0.1", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.0.1.tgz", - "integrity": "sha512-CRbtl6urEcIDbIzP4sGoPf9YuDNto1JgCRsfdvcVUOPb8nPAQ0azhPZiSdD5AFg/Erb58+/nDRmhm8bzVyjABQ==", + "version": "21.9.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz", + "integrity": "sha512-00fVrLQOwy45nm3OtC9l1WiLK3nJlIYSljgCt0qzTaAy65aciMdRy9GsuW+a2AtKtdg9/njUGfRH30LRupV7ZQ==", "requires": { "@babel/runtime": "^7.17.2" } }, "i18next-browser-languagedetector": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.8.tgz", - "integrity": "sha512-Svm+MduCElO0Meqpj1kJAriTC6OhI41VhlT/A0UPjGoPZBhAHIaGE5EfsHlTpgdH09UVX7rcc72pSDDBeKSQQA==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.5.tgz", + "integrity": "sha512-11t7b39oKeZe4uyMxLSPnfw28BCPNLZgUk7zyufex0zKXZ+Bv+JnmJgoB+IfQLZwDt1d71PM8vwBX1NCgliY3g==", "requires": { - "@babel/runtime": "^7.19.0" + "@babel/runtime": "^7.18.9" } }, "i18next-fs-backend": { diff --git a/package.json b/package.json index d4dabad2a..71292579d 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,8 @@ "date-fns": "^2.29.3", "fuse.js": "^6.6.2", "gray-matter": "^4.0.3", - "i18next": "^22.0.1", - "i18next-browser-languagedetector": "^6.1.8", + "i18next": "^21.9.2", + "i18next-browser-languagedetector": "^6.1.5", "i18next-fs-backend": "^1.1.5", "i18next-http-backend": "^1.4.4", "just-capitalize": "^3.1.1", From dc5fc84c83c12e8439ddbc66c7424678763d674d Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Wed, 19 Oct 2022 23:34:14 +0300 Subject: [PATCH 16/47] Option to get wpn damage multiplier from all keys --- app/modules/analyzer/constants.ts | 17 +++++++++++ app/modules/analyzer/damageMultipliers.ts | 36 ++++++++++++++++------- app/modules/analyzer/useObjectDamage.ts | 11 ++++++- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/app/modules/analyzer/constants.ts b/app/modules/analyzer/constants.ts index 031244f12..21181eda9 100644 --- a/app/modules/analyzer/constants.ts +++ b/app/modules/analyzer/constants.ts @@ -1,3 +1,5 @@ +import type { DamageType } from "./types"; + export const MAX_LDE_INTENSITY = 21; export const MAX_AP = 57; @@ -30,3 +32,18 @@ export const DAMAGE_TYPE = [ "BOMB_NORMAL", "BOMB_DIRECT", ] as const; + +export const damageTypeToWeaponType: Record< + DamageType, + "MAIN" | "SUB" | "SPECIAL" +> = { + NORMAL_MIN: "MAIN", + NORMAL_MAX: "MAIN", + DIRECT: "MAIN", + FULL_CHARGE: "MAIN", + MAX_CHARGE: "MAIN", + TAP_SHOT: "MAIN", + DISTANCE: "MAIN", + BOMB_NORMAL: "SUB", + BOMB_DIRECT: "SUB", +}; diff --git a/app/modules/analyzer/damageMultipliers.ts b/app/modules/analyzer/damageMultipliers.ts index b83fa374e..21ca5a706 100644 --- a/app/modules/analyzer/damageMultipliers.ts +++ b/app/modules/analyzer/damageMultipliers.ts @@ -7,21 +7,29 @@ import type { } from "../in-game-lists"; import { DAMAGE_RECEIVERS } from "./constants"; -const objectDamageJsonKeyPriority: Record< - DamageType, - Array +/** Keys to check in the json. Lower index takes priority over higher. If key is omitted means any key with valid weapon id is okay. One json key can only map to one DamageType. */ +const objectDamageJsonKeyPriority: Partial< + Record> > = { - NORMAL_MIN: ["Shooter"], - NORMAL_MAX: ["Shooter"], - DIRECT: [], + // NORMAL_MIN: [], + // NORMAL_MAX: [], + DIRECT: ["Blaster_KillOneShot"], FULL_CHARGE: [], MAX_CHARGE: [], TAP_SHOT: [], - DISTANCE: [], - BOMB_NORMAL: [], - BOMB_DIRECT: [], + // DISTANCE: [], + // BOMB_NORMAL: [], + BOMB_DIRECT: ["Bomb_DirectHit"], }; +const commonObjectDamageJsonKeys = () => + Object.keys(objectDamages).filter( + (key) => + !Object.values(objectDamageJsonKeyPriority) + .flat() + .includes(key as any) + ) as Array; + export function damageTypeToMultipliers({ type, weapon, @@ -41,7 +49,10 @@ export function damageTypeToMultipliers({ id: SpecialWeaponId; }; }) { - for (const key of objectDamageJsonKeyPriority[type]) { + const keysToCheck = + objectDamageJsonKeyPriority[type] ?? commonObjectDamageJsonKeys(); + + for (const key of keysToCheck) { const objectDamagesObj = objectDamages[key]; let ok = false; @@ -58,7 +69,10 @@ export function damageTypeToMultipliers({ ); } - if (ok) return objectDamagesObj.rates; + if (ok) { + console.log(`for ${type} used ${key ?? "FALLBACK"}`); + return objectDamagesObj.rates; + } } return null; diff --git a/app/modules/analyzer/useObjectDamage.ts b/app/modules/analyzer/useObjectDamage.ts index 02ba6bcfe..561782976 100644 --- a/app/modules/analyzer/useObjectDamage.ts +++ b/app/modules/analyzer/useObjectDamage.ts @@ -1,5 +1,6 @@ import { useSearchParams } from "@remix-run/react"; import { type MainWeaponId } from "../in-game-lists"; +import { damageTypeToWeaponType } from "./constants"; import { damageTypeToMultipliers, fallbackRates } from "./damageMultipliers"; import { buildStats } from "./stats"; import { validatedWeaponIdFromSearchParams } from "./utils"; @@ -28,12 +29,20 @@ export function useObjectDamage() { const multipliers = Object.fromEntries( analyzed.stats.damages.map((damage) => { + const weaponType = damageTypeToWeaponType[damage.type]; + const weaponId: any = + weaponType === "MAIN" + ? mainWeaponId + : weaponType === "SUB" + ? analyzed.weapon.subWeaponSplId + : analyzed.weapon.specialWeaponSplId; + return [ damage.type, fallbackRates( damageTypeToMultipliers({ type: damage.type, - weapon: { type: "MAIN", id: mainWeaponId }, + weapon: { type: weaponType, id: weaponId }, }) ), ]; From fa0268536644d082419d07a00f639a6b8c31dba6 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:22:22 +0200 Subject: [PATCH 17/47] Fix glitchy safari behaviour for map mode selection --- app/styles/maps.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/maps.css b/app/styles/maps.css index 2d7f6bbbb..cc680c1d4 100644 --- a/app/styles/maps.css +++ b/app/styles/maps.css @@ -71,7 +71,7 @@ } .maps__mode.selected { - filter: grayscale(0%); + filter: unset; } .maps__map-list-creator { From 26b6a4169bd80ff924c3347fe0d1ff53b258ccc0 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:25:03 +0200 Subject: [PATCH 18/47] Use pointer cursor for toggles --- app/styles/common.css | 1 + 1 file changed, 1 insertion(+) diff --git a/app/styles/common.css b/app/styles/common.css index 00cf5af50..ab61e10dc 100644 --- a/app/styles/common.css +++ b/app/styles/common.css @@ -348,6 +348,7 @@ dialog::backdrop { align-items: center; border-radius: var(--rounded); background-color: var(--theme-transparent); + cursor: pointer; } .toggle.tiny { From 52d6e6caeaffd6059261fcc9a6015c474f17467c Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Thu, 20 Oct 2022 21:47:40 +0200 Subject: [PATCH 19/47] Improve check-translations-jsons speed --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 71292579d..03016a5d5 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,14 @@ "create-object-dmg-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-object-dmg-json.ts", "create-misc-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-misc-json.ts", "create-analyzer-json": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/create-analyzer-json.ts", - "check-translation-jsons": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/check-translation-jsons.ts && npm run prettier:write", + "check-translation-jsons": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/check-translation-jsons.ts && npm run prettier:write-translation-progress", "replace-img-names": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/replace-img-names.ts", "remove-bad-custom-urls": "node --experimental-specifier-resolution=node --loader ts-node/esm -r tsconfig-paths/register scripts/remove-bad-custom-urls.ts", "lint:ts": "eslint . --ext .ts,.tsx", "lint:styles": "stylelint \"app/styles/**/*.css\"", "prettier:check": "prettier --check . --loglevel warn", "prettier:write": "prettier --write . --loglevel warn", + "prettier:write-translation-progress": "prettier --write translation-progress.md --loglevel warn", "typecheck": "tsc --noEmit", "test:unit": "uvu -r tsm -r tsconfig-paths/register -i cypress", "cy:open": "cypress open", From ab98a106bb20fe8223b1054e2ac20fbc79565893 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Tue, 18 Oct 2022 23:17:37 +0200 Subject: [PATCH 20/47] Show dialog for failed login attempts --- app/components/layout/UserItem.tsx | 64 +++++++++++++--- app/modules/auth/errors.ts | 1 + app/modules/auth/index.ts | 2 + app/modules/auth/routes.server.ts | 16 +++- app/utils/urls.ts | 3 + public/locales/de/common.json | 8 +- public/locales/en/common.json | 6 ++ translation-progress.md | 117 ++++++++++++++++++++++++++--- 8 files changed, 191 insertions(+), 26 deletions(-) create mode 100644 app/modules/auth/errors.ts diff --git a/app/components/layout/UserItem.tsx b/app/components/layout/UserItem.tsx index d0beec8ab..5078346c0 100644 --- a/app/components/layout/UserItem.tsx +++ b/app/components/layout/UserItem.tsx @@ -1,9 +1,10 @@ -import { Link } from "@remix-run/react"; +import { Link, useSearchParams } from "@remix-run/react"; import { useTranslation } from "react-i18next"; import { useUser } from "~/modules/auth"; import { LOG_IN_URL, LOG_OUT_URL, userPage } from "~/utils/urls"; import { Avatar } from "../Avatar"; import { Button } from "../Button"; +import { Dialog } from "../Dialog"; import { DiscordIcon } from "../icons/Discord"; import { LogOutIcon } from "../icons/LogOut"; import { UserIcon } from "../icons/User"; @@ -12,8 +13,9 @@ import { Popover } from "../Popover"; export function UserItem() { const { t } = useTranslation(); const user = useUser(); + const [searchParams, setSearchParams] = useSearchParams(); - if (user) + if (user) { return ( ); + } + + const authError = searchParams.get("authError"); + const closeAuthErrorDialog = () => { + const newSearchParams = new URLSearchParams(searchParams); + newSearchParams.delete("authError"); + setSearchParams(newSearchParams); + }; return ( -
- -
+ <> +
+ +
+ {authError != null && ( + +
+ + +
+
+ )} + ); } + +function AuthenticationErrorHelp({ errorCode }: { errorCode: string }) { + const { t } = useTranslation(); + + switch (errorCode) { + case "aborted": + return ( + <> +

{t("auth.errors.aborted")}

+ {t("auth.errors.discordPermissions")} + + ); + case "unknown": + default: + return ( + <> +

{t("auth.errors.failed")}

+ {t("auth.errors.unknown")} + + ); + } +} diff --git a/app/modules/auth/errors.ts b/app/modules/auth/errors.ts new file mode 100644 index 000000000..76abc84ad --- /dev/null +++ b/app/modules/auth/errors.ts @@ -0,0 +1 @@ +export type AuthErrorCode = "aborted" | "unknown"; diff --git a/app/modules/auth/index.ts b/app/modules/auth/index.ts index 34bd8c3be..4163a74e6 100644 --- a/app/modules/auth/index.ts +++ b/app/modules/auth/index.ts @@ -9,3 +9,5 @@ export { export { getUser, requireUser } from "./user.server"; export { useUser } from "./user"; + +export { AuthErrorCode } from "./errors"; diff --git a/app/modules/auth/routes.server.ts b/app/modules/auth/routes.server.ts index 39bf7653a..609af9fbf 100644 --- a/app/modules/auth/routes.server.ts +++ b/app/modules/auth/routes.server.ts @@ -1,7 +1,7 @@ import type { ActionFunction, LoaderFunction } from "@remix-run/node"; import { redirect } from "@remix-run/node"; import { canPerformAdminActions } from "~/permissions"; -import { ADMIN_PAGE } from "~/utils/urls"; +import { ADMIN_PAGE, authErrorUrl } from "~/utils/urls"; import { authenticator, DISCORD_AUTH_KEY, @@ -11,11 +11,19 @@ import { authSessionStorage } from "./session.server"; import { getUser } from "./user.server"; export const callbackLoader: LoaderFunction = async ({ request }) => { + const url = new URL(request.url); + if (url.searchParams.get("error") === "access_denied") { + // The user denied the authentication request + // This is part of the oauth2 protocol, but remix-auth-oauth2 doesn't do + // nice error handling for this case. + // https://www.oauth.com/oauth2-servers/server-side-apps/possible-errors/ + + return redirect(authErrorUrl("aborted")); + } + await authenticator.authenticate(DISCORD_AUTH_KEY, request, { successRedirect: "/", - // TODO: should include query param that displays an error banner explaining that log in went wrong - // and where to get help for that - failureRedirect: "/", + failureRedirect: authErrorUrl("unknown"), }); throw new Response("Unknown authentication state", { status: 500 }); diff --git a/app/utils/urls.ts b/app/utils/urls.ts index ef4d3c07c..8333bd9ea 100644 --- a/app/utils/urls.ts +++ b/app/utils/urls.ts @@ -10,6 +10,7 @@ import type { SubWeaponId, } from "~/modules/in-game-lists/types"; import type navItems from "~/components/layout/nav-items.json"; +import { type AuthErrorCode } from "~/modules/auth"; export const SPLATOON_2_SENDOU_IN_URL = "https://spl2.sendou.ink"; export const PLUS_SERVER_DISCORD_URL = "https://discord.gg/FW4dKrY"; @@ -59,6 +60,8 @@ export const userResultsEditHighlightsPage = (user: UserLinkArgs) => export const userNewBuildPage = (user: UserLinkArgs) => `${userBuildsPage(user)}/new`; +export const authErrorUrl = (errorCode: AuthErrorCode) => + `/?authError=${errorCode}`; export const impersonateUrl = (idToLogInAs: number) => `/auth/impersonate?id=${idToLogInAs}`; export const badgePage = (badgeId: number) => `${BADGES_PAGE}/${badgeId}`; diff --git a/public/locales/de/common.json b/public/locales/de/common.json index af077500e..c846839b6 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -27,6 +27,7 @@ "actions.remove": "Entfernen", "actions.delete": "Löschen", "actions.loadMore": "Mehr laden", + "actions.close": "Schließen", "results": "Ergebnisse", @@ -54,5 +55,10 @@ "weapon.category.DUALIES": "Doppler", "weapon.category.BRELLAS": "Pluviatoren", "weapon.category.STRINGERS": "Stringer", - "weapon.category.SPLATANAS": "Splatanas" + "weapon.category.SPLATANAS": "Splatanas", + + "auth.errors.aborted": "Login Abgebrochen", + "auth.errors.failed": "Login Fehlgeschlagen", + "auth.errors.discordPermissions": "Für dein sendou.ink Profil braucht die Seite die Erlaubnis deinen Discord-Namen, Avatar, und verbundene Social Accounts auszulesen.", + "auth.errors.unknown": "Der Login via Discord ist aus unbekannten Gründen fehlgeschlagen. Falls dies wiederholt auftritt, kontaktiere uns bitte." } diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 72115dee2..8734a1df7 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -14,6 +14,11 @@ "header.logout": "Log out", "header.login": "Log in", + "auth.errors.aborted": "Login Aborted", + "auth.errors.failed": "Login Failed", + "auth.errors.discordPermissions": "For your sendou.ink profile, the site needs access to your Discord profile's name, avatar and social connections.", + "auth.errors.unknown": "The login via Discord failed for an unknown reason. If this keeps happening, please reach out for help.", + "footer.github.subtitle": "Source code", "footer.twitter.subtitle": "Updates", "footer.discord.subtitle": "Help & feedback", @@ -29,6 +34,7 @@ "actions.delete": "Delete", "actions.loadMore": "Load more", "actions.copyToClipboard": "Copy to clipboard", + "actions.close": "Close", "maps.createMapList": "Create map list", "maps.halfSz": "50% SZ", diff --git a/translation-progress.md b/translation-progress.md index f47c0e262..5a12774e0 100644 --- a/translation-progress.md +++ b/translation-progress.md @@ -1,6 +1,68 @@ # Translation Progress -## /da (🟢 Done) +## /da (🟡 In progress) + +### 🟢 analyzer.json + +**94/94** + +### 🟢 badges.json + +**7/7** + +### 🟢 builds.json + +**11/11** + +### 🟢 calendar.json + +**46/46** + +### 🟡 common.json + +**55/60** + +
+Missing + +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown +- actions.close + +
+ +### 🟢 contributions.json + +**6/6** + +### 🟢 faq.json + +**6/6** + +### 🟢 front.json + +**11/11** + +### 🟢 game-misc.json + +**17/17** + +### 🟡 user.json + +**20/25** + +
+Missing + +- results.title +- results.highlights +- results.nonHighlights +- results.highlights.choose +- results.highlights.explanation + +
--- @@ -32,7 +94,7 @@ ### 🟡 common.json -**49/55** +**54/60**
Missing @@ -123,14 +185,19 @@ ### 🟡 common.json -**48/55** +**48/60**
Missing - pages.s2 - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool @@ -239,7 +306,7 @@ ### 🟡 common.json -**46/55** +**46/60**
Missing @@ -247,8 +314,13 @@ - pages.s2 - pages.analyzer - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.loadMore - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool @@ -350,7 +422,7 @@ ### 🔴 common.json -**0/55** +**0/60** ### 🔴 contributions.json @@ -501,7 +573,7 @@ ### 🟡 common.json -**46/55** +**46/60**
Missing @@ -509,8 +581,13 @@ - pages.s2 - pages.analyzer - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.loadMore - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool @@ -619,7 +696,7 @@ ### 🟡 common.json -**35/55** +**35/60**
Missing @@ -627,8 +704,13 @@ - pages.s2 - pages.analyzer - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.loadMore - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool @@ -748,14 +830,19 @@ ### 🟡 common.json -**48/55** +**48/60**
Missing - pages.analyzer - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool @@ -843,7 +930,7 @@ ### 🟡 common.json -**35/55** +**35/60**
Missing @@ -851,8 +938,13 @@ - pages.s2 - pages.analyzer - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.loadMore - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool @@ -972,7 +1064,7 @@ ### 🟡 common.json -**35/55** +**35/60**
Missing @@ -980,8 +1072,13 @@ - pages.s2 - pages.analyzer - pages.maps +- auth.errors.aborted +- auth.errors.failed +- auth.errors.discordPermissions +- auth.errors.unknown - actions.loadMore - actions.copyToClipboard +- actions.close - maps.createMapList - maps.halfSz - maps.mapPool From f535ded72f183acc43a4995d2233a60184b1bf89 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Thu, 20 Oct 2022 23:43:35 +0300 Subject: [PATCH 21/47] Add Splatalittle badge --- public/badges/splatalittle.avif | Bin 0 -> 1351 bytes public/badges/splatalittle.gif | Bin 0 -> 168436 bytes public/badges/splatalittle.png | Bin 0 -> 4560 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/badges/splatalittle.avif create mode 100644 public/badges/splatalittle.gif create mode 100644 public/badges/splatalittle.png diff --git a/public/badges/splatalittle.avif b/public/badges/splatalittle.avif new file mode 100644 index 0000000000000000000000000000000000000000..637548b0832089e0c2c395a3a7cf3e13fa7beeb9 GIT binary patch literal 1351 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

e7c>-EQ^;x_!u>Z#!2^#)>ZQ&!@5|c4E%G zIY%;7eW|H#Ec+ulR+=qNV$<^5~u7Z4Q9xAz|wCE&R zS6-efuwui>|H0fjHr4^IU3$l6qehKwyHT6QY@9T8lhj%}l{ZJX0`Ud(xC z=KGv~v7YB%>$+wmt~nq_uzo1evZ&;pD?mwF=Re48<%AF17P&$c;}(Ttk1PDKQe7*t zs1N(840CIB^i0RpD>au#6;K`nq8D->6o*v7F8CHX%yAKl<)&JlW6+N(pT@18<`G}1 z*mm-B=U5d@IIe0dt(0bQb}pXFC2ffRgnO26DfK5;0aOb^5r-vem5XY07K*tUd+R`- zXhcOsd-PXHt=}!EaE*zwh0Ho52rC`;xoqQ>dM=iWHm`qDx^!ezK9Bxc{2;`I1jC%6 zkc6ik2$8guW>jj^?`W;-yEcQYiLAM2bawevntRR)Y~1LP7d*I|Yh*82$Te4W0*Xj^ zIizfYvsLdQ5xrgd6@0{Mf05ocb%4QDK*N$>NBEER??17Ej`_r4xnbG@E#U(RSoE&+ zz=HTu27#>0iD+eTL<8giD`|#bYBLeyw7OS;TBqClY`E%d_bic?r^N`k`MoGOjM2t} zb-I9*E`DN%=qj6AIIZQ7yTo z@iQJWj1Fm5cK(WMcm`N)imbd$_s^D%j^(4?o;gX;nW#VIL@@(Og>Z{MK8 zr$G}pxl1x;8ghIS2{`Ko>_mc?D5@!8=i%Eh(&{r!W}^Gm?n z`+h%?IwL;N9}9q~Vt7IV47kPVF%Plx6Ad+*F$e$cT8DpE!r)JR3IXN)h$dxB7AP^^ zYXLD#g0)%L3$en`M0)B|ruF(`Y27`#n^}ve7>)>i*gWE;X0pDya(%-`iC049EMlrb z{7EfasF`Co-V8EYOiZgxtU$a!{jDuD%#?79gQ)FnaWLQR;3}e9ZvBAoPWJ#+T<&L! zPHfL(w@n=Wjid18aY%i@idK!uLBnBxT#hf81;_BX zYGcQ2>z78<^cD&Jdm<<|HO!FEA{Je|C%e7=Sw4aFZhhNBo&neey*GB3FMk)%hm}lE zu3K*X{LCM(0{ge)vf8d2eurUCw~ECXl^xIaHy=;N)n9z6@?rIWxX3&@ppS;&Y+pbC z?uOgf-wz2UXi>t%zMpKeNqjzsRg;3qRNc@+Nd5FS5MVu$a=q*erpP?;I>0zyY+OI` zBJoqfdI*SoK(c5|8Zc3y(YPDwZ(_WqFR?yHV2ZdOQj3PMLa36)(B$uUqJLw;;dUZ% z7%w1L?R%(kfMM*>&t%;~grXSh76c40iNt2A4E|+z2uI{|4fzZRdoxl2WgOv|Tqa1w z{Ai2o6tkS5+NGl0ND~iQNi!ijGb<&s7KMUDs*%IORH|iK1Ue1(tO2~<8NIekUveAr1ztIw2W;zuVRIs;2DqMlV{W3GjDt*j^?b^0uyR!Q~i zI9+9Zf1+hYs=Gr`McJR0fC}2_F#fZ)&W^Iv7K?%%rqI$p>C@)H)H1qGhuT)ghRaie z1G;I|6T2=zYicF%@fluA^*(Hdr4Nn#l(h&t>9NEQmmmJ1FVX6?ri*YVl{Mfu@u|Wv zr`)9j^*f^7Lg{GK>CQObEn!`^c#{+o<2sX<)CB(xef`+i;Pi?~6*TMHX=sW_2TGY< zvWz5oT%v{<7BQWMB{9PcXDDIM?J2NbZ({u)>@3;(7MEaIws~!#k}DCrXnO7y=h=*= z4eu|N;8Y80pV1Z2Bp(ly2W}Ks{6|uFh1(9gm3OEn$lvd_J=~O7d#|8X>SnbTh}v{m zb!pMOAH;9-eCoNNRCGZ5f%Qz4C$IBzmQ^dqe-%_E=N4Q77GgTJtP6X&Ey)w&7#hpl zZfolrJU_Y|47L@#hBHKC(&$7(_v+pWmlu4jNSz$J|EOeUd%cLecrTig2tt0_RmytE zS8IPgL-RE{`eovFz_rm{={aqf1+gO0okgRd7BZU&HRw$G;%)9n!mycYHqfOAsP>17 z&xXes60Q5q;{Uds4OYPGemSc0qYs!xs%r}W)RPzR4N)Hn?NGEzKPLDkAN@Q=>Ck^Azr$6G^jO~KEPdBm~4Hk$L5gwB}uo05q= zT@!LPoN?1AThvr^^RrR8Xy~wF?R0V*LoTzgy0kC!Cy&WfGP+LnBui12v?6g5?zL@M z(^$o{X%!;2Z*@u1GwA6xW2+>?!(*(fYAW8E0t+x``q5ZaB&@&rT>J z3vQEcWVcEqr$eG>;vc-h1I#%cDaFHnZVKPN%kbheQmzA9Ds3>R^Mfgl7`}!PsmaL& z(p9L6M{g?`;d2zCrWs^TFE9ETP`kyVblLc(j_}dJ zft#_6nj~(@w%k;esxsl4r@x&zWvH%6lft*wy%jALw<;Zo!nLAikK2_r zE`=?llzEESLd~^mPo!3~iv`%~?2ZDSh2~A1doKvurPIes@3A50DIaO<6hr10s9+Nr z{iwB;b6CNxQ9tDZu!X~+KRI>-n5ssJ3F8(Wc$!Zd?2Mhk6IJGm4O6mJHj?Sh{iSt9 zr%sWfNa(9r3(o!Au;o$YNID-gs@=wa%q6(Sb`a z#ei$`d$Wt|w^X6bf*v!VbS&%B-lrRc9yh$Zj$bL?E4;)Vl~>IP2CZrZnQ#tJQvrWl zAC?Njp?vgqyxo9s1CrupCPU=)P|8cT38!%s`#YY72H_?Sc()W!w??d&Ab^5BlW^+H7kjv$%cDMjn*jwy>+WQh)IHt%h^tP_qb?)z@>?a z^G524L2r`lXy6>L60U!D)QWFBOZVL0h%m9r<7L!Z(h2KgsL#c-P?DIxexjz|BNw-veMN(070T zlUKr2^rNR0GJbd-G1St+(>(||)kV7Fx-9hlkvH|lE_vhV5DoY&sQg&FlfG3a+4*s= zICXcQl*vFWjzl9yVAbTr1;;QdfiAOen;;I#XhZUVzqonsvwJFa{j zO}(CzKBaVQYTY%zFpue%l zFZe)7njk|OSLBdD{g5E@!vLUZkmg|!YmDV}khz{)kkcci3@qaMKESUj*n!j4hsT-) zBgF4e`6r%WpgO@mFeLPl*7Xi41}{`2*el*lIWa`-su6^&5So@O>kJ*16I&dT3HH-c z4>RHlODzs#ilNRw49kUwsG$i@#)W7w3lI1%CR`j|_3)#E28um4y!+6s*vzxvEP~@v zb~rf*2=?e)hzLv8w5N=$8v5c2ikSbwH#Zcq;ublp7`ZVNx^)=210S`U6M4V`c?^!C zn2I{5fxN_vzEzLDcZ+^Zj(!G5zb;0^n0)f?fQhqRh~5TAh!~~>(XVBAU z6`G9P@3^rtd~meNbYIDNyq_uP0!mcU)V+b6W#~?7Mec{k*zoF=2K+IMCp+c-6-e{7 z-yoYntIcA^Y~XP2kae*1OYRnZGSXI$CMx;B%=Fndb7YesG2QglE|KqEasYXPdnrj zNzyItSkXe<7!fJb4I7D!Et2oWbD^7w+7pEyg(N9$>ro*XB|hcRn_0N`rjpld6tdd; ze2xmCvclf=!f#HAN!ayT+Rj{W*rb+b4xpgP_=9Cp3<$9(risLOMbOWV?kJHG{uP9U znlBwvDqEBp1z8$jh$>u)S&_RuS}HXVX8s*Na`~uS8;7L?;I%CUv=YYtj8u_B)$+aU zL+LY;X;mjIKWyC}PIm?mk4z6s{KfXLA?Br)7DoKFD0-wurQ=jOg1yQY+7_u&0*Tgj zI!K$AqZf)?%$}-mOWMsR_9T01c+Dom?xg2?G5V# zENGv1dhNrDz1zfwKD}!h41dxBT?>&{30&5*r;SC8bWK<(jWeELI!+`ePM?c4dVS8F z&_a$>oHnN;slb*}?yFCS5zzTI_eHinfA+`A96P7xsJin4uQ!V9qMqhj;5ax0n`woi zZS~VKt|2M6oD*DI|C)xij_?{B@fP@uETcU`H)eO z!(N`_%W=_2Kj3rUH$uXBuFgx+dox@7V%vKk-7vv(OJ;T~a@`fm+{{Ch zyaDmtchCWN#RpG9yv=-zQrc!c{OCSAx!O?o82pL~i15Y+kbIy%Wz?r}9AgC=i^r_L)m&N-(#qQY;~%bnHC#UV(6+F+8H{EKC9F+c$ji!wza+r#6>e$Em-DVFU< zm%^z6+Z`{nm0Q54A(&a?V2)F2_{MSsd70r55t>U$l5!}O5E2WS6&ebs0hMkjN0P#z zL6s1(GX_Dbm|~zs$?5;Zc>@!wk{=Ps1nQHPzDG~*XBg&*Q=hOcR89+VGU6XKuRw8Q zNvFJ`67+=e^Xy>fe7?;$dA@`2U7sP*dO~Kqy{0#*rOf%EO#?x|_c7iqe4C9LSOiCt zD%Linl-G)7CP9iGg=4*^HZwLN0arTUs9BuP`;0GDXFjd%P#1gd^+_gFWjMueIFHL& z_Xm+)cZ}B&wGijg*SMM)v-*ZEX)QNM+1{}s+SaiHObn=yKUBybG7C)~vLJLit z%D&0YsVw~bnF+~RM)J*)H*^u$pp;!<)E=NgZ!wrW<{XMzeFA;iq5^tkEmHhbTGcZm z5A#@`>4dxsg-$S1S#f8Y#900n^+YK;gr<)8Zx5EbZURb6v3 zvCkcylQ+FinNkwoe8yg5ZJCZWG;>SiABM#q0yTt~2k?FZgNMJg*nKU>x23>~+uhN% zKb3=upFA%f@5>gE9-D*!HhI8>gF&cX>TXgLrGoF9o0m&T83PqoAQYb2i$-f53oRBM zdEpH@U7oO~KX!;x0-tS#-5|+y$s9OI7N^0<$|qs=Hzw&Id;-?C^(p%U)iL$0(%peD z?Ak*&EmHC%=;17xE43tTD71y`K6C}PdswUQg>FUnU+1bcQir$0almxV?N@v zl&Z>4H;_Z8``j0Q(ybEhtu|gY!Cb%z&wX|_|CW7tWR1Zo8ga)|4G1$Pay}?MT@E_@ zw?lSM)fqsxQ^6lmvj+wD*+ed<1yqz{@fQuqe5O0t?AcZMGCt_?d#99ND3&!LG=J*3 z?qKXPPJY^kFSG~UR_PF(LL}z#bTKtnM`sip(XZ4GQQg<^$|}Ilxi3R~8)&F$r_6v& zU11=cw5CF~!KjAh+-2gHnj+djDSJsVkbG!;;NG;5Tfw=`Y^s?(wedcg=QF=|we2G^ z0TH}z!pnnua3?N<_+PisqrrXDa#vw-B>yJ8=Kmmgx&Z$91qt}qFUbE*@N9~KYQZP~ zhqpkrrFVpN_2l&ZH!SWy0Y(1pOUu2hek&W6(7X6s+vdB_`|F2Cd--SQb`W=eFP#v7 zYgI2EPY18l5H#|egnmQF|6KF*621`=*HbIX^@SNlaDqc>J|e!u67okqfl2azh)~Jr zN|wwZk0uJweRD&Y4U>WAuvBV(A}N|+6k>*cTQW3*$rE=b$*AU_{X6i;-~vf0(&3gq zm&$|3rD>gvKbddinLL9Y6R@XreNEhm-E&Kk6TDaU$z+3AJ0H&hsV6N zKv`nfTN*xEkv7>Nwb4Jm%aZa0ZuRvu=~{b0T<@ACdD<}Xao%pvaX)&kD-f|K3TtpXv# z0O<32+PbJVkU0QM6IUGwY)Cu(pc(5&;b2^!Lq9#%sXd_YSd2PZ5H)_GJ^~$A*ESnd z;v-}j%iK^`A)w;cuYu>?49oK!5FEI_LPX<|k&XPdM zw8+l~>_LekG{MpL*kl+{bR(20h(idZEGq$;w6Fm_B$-*MQlDtET0&A4N(>9}drLxl znj?!Kfya?$h*7DK74aj8vY8njL!YV|sHA(iJ`A2iN=wt(?DlI~RbNW0+TCZZJTSXb z5o=&%2ykkZ9SMGwz>BvepN-Usai~} zlCK0-U75%c``zfc5q20tYyx4uVp4=P9Y0he&KU66o39!u2&`%li66rATA5SFY6e7P zG%p4NYhSAeSfEJRyEtYs9TIptR~@4vD)AWWZMlGDqm&n;HE5>&7M3E?{A;&Euwq1s z({$WWHhz*>e;hi zVbdghJwoSh}-BLJvV9>lKb5+Xgc$uNKV>NMB@5qx z?0m^v*2RKuc_B>BVLrXWBAFhDA~%u*ttRKdNI&x6l`4=lS!g_4Jc?it4HAr!=ORS% zfJlU7LIsU-Vcf`=usm4oUY~MAKZ?y5p4%riKlSBsf`WlIrf0)-{|c;jVnGPuyEp5s%twO!cnKvL7Wn}~X9^uUH%x{wHAIPj ztwb1NB>O#2gq3eIN@;8N3vS|fRNxG4t~lv}z!FfIY{0o1MDhH1h^Ow;#g?ia&M5CV z1h-quplDbC7w{CRmv|jC=oP}s4Tdu4FpaN?H-L9BPt%o(gP7X|LfZ0oZUq_-4BSpKk0OU@*4rV%qWfF>Sq!?YuPe&`(D-G*c@48 z?T13RH;rhgioe}|7KkN{)HQ$KtcpdpBCsD(YYPO_oXF5}eD?fPqXei0CY0-iE+>Zr z5dP5uL6F&AIstLj^8G2(Uo*h}5XO$2X(qjAj_f47z$E-4Jw9D#EU?dD? z>tU_>noPB%Qs+;ea83&_Z424HBb5r*(|AwC{$6Ona!2~4jRR-rjt|*O9T+d2B^TLF zif?v)5T^jxJZ^$|_fm&+6<{%nk`b>#sTOtimbAlSZv=ErN=K_=D2`hlo8Z-r5OO`X znt2Vfw|#gX0a+j;aNrbt$<1c9+3r&-R8l|@p0=n5r3C1qKVyw01?;-PH;eFPqWTh5 zGg%cr4%8D}s(umBIGcEY{CS>es3T*7$9_Mi{K}@>k6f#$n4GU|!wl;pd5~&-IiWbg z?rp2KFBJXxW87r7COdfKfJ)haNb?!bx2(1fMP+8H5y;_6)t)S6xj7S+8B|Cqcm(6N z+^R>lm!O}tm*iKNPZ;HB-1Cc!2T*+196<*1xoU**!cwbTTW^EemIjD;>RaR7S?ii>1*SYWj z<#lS~^x-zrXzZGFk|E_h^fGi-`Oq47dZCo$xdG{W6!7-$?mz$ zRN?lVZ;kI^ncfKSW$XCr1Ck6|-J4`oFyf89+q7jdH9|)TQwn(X_av@a@{i5 zO>APDo_dPDF|ahPdmm7qarQlnWz`=Uv3b&a1-15NO%~z2-E`%G=m*y(ocv=C!TV*1 zeA_neI#Z9vF-m28{YcPnYGP^iNEJrlDtx z|BNj9F0Z1_Z~hb5+ue!?ad84XgSmjX^1ZoxczJz$|A-!efTpm^&hmpD9+M6+B^BdG z{UVkAqb9fi%XXViE12qo94dft+D#k4mOmUvqg)!FZEKvC$h6QE@l;4L&cH)y>)oo8IBs%3Yz1I2l#}vN*C3O|M6{wlqI-3K&)F9#8U&)OMuTG1$Yu|_k&53 zO;lL=iyTY|w#Zm*?m39eIf`0m(C361(<6vqKlOmLs;kAV8&GKFJX}OJd8qsTN>I5Y z_Inmvck7-9W^4hQ`n?T!eY~K<6P&62(0^1?9bLB@C$ftkGlax!cy-7V~g10 zt`_S1Q|Tvf`4X@_rUtrgaT_?3rX=Ttq4vN-gy4i6t_QKwxfuit&x8E}V4fDXoN%9$ z^x>k7+TmpZDz=(s5>zx*R* zRhq+=O<(mfXd!-Tp(~VDTvPX+QeK$Grga9@D~Ep8SfUtCQ~hvRf2v<0C4DY&)In#H z9GGcn(|CAaYE##-gk)1vNc_2q_Xbw;qWz^(`Vw4!@3{})c_%Z6(ny_R?1B06deWN9 zkv`fxG85XksZhvK085=I%Etj`UVL&CdU7+b6iIP!Ys%!&w{&lFnld{R)Z+xFL>pt z$lQCk#Le&Ryx2Y>-1d#BJTweY`s^y6jyxURAJK?=3U4e|2`fAxV5DykI~1 z2JZQ|qt<%S;lwJ_6p5w=7hCBF>CU&HKc%N4EIR zyD!KdRy3Z6YxCOQ^^4&7Qh3(p=^~^v)pP0OTF&o6&R;k8*uSZ=@?KCC&Gl-Ln$UZ{ zSj&_C%5#B;f2Rmz9dMN)Ksq*Jh^jeI z@#{afW2VX^Y}JhkSckOHr=n-Q{HCS}UX&LPx=~%mI}j4Nq&2;>H4@&E6kXu`P+*0< z$-odWgQh~1a;QBrF7b+^Pz)*h6$OkS-OK)Z;f@tb7fXz^2aqC?>PhIpP=@y|k+}N| z45}@&xo_H-sjtsuANpJ_-kjq?c_xuF zEq7FN^(U}1Lz?$?h&7M&w92&0Vi>@qEQ~*Yl|p4Q8<{BK-Q!1g?pmwpAFqi8OIVdA zothd46KI*Wag{%fSH_S1vMm>7GaQPvR4;r0ZR|3k(n<6h=f|7P;I&MLP>9cdS%a#HyDuo9 z_5(D=bKKJplbD_h`lQ%$ew!Sw86+3YE8G@Hl$rn7DV<#*VJqlwJA`p!11`@TLIVU= z8g=>p_;MBGi7kyePvehnfE&u3QBIl~vHq0o)uq}-9vOcEjt+{u_*I-*>2q)XsS#?d z5@cMqh<;w~n{cUOW-*8HRhk1w3B%h*Y_uk%72OFp#Roo`(ZO-JT-=W}Gp?P&mGciZ zo;JlzTbnvh+Rl1n^B6-3+XcS7Y!;qNcH^#JI@x~SzQ?(4Ttd2VRndm3GI33(jJbg8 zy59K=&)b#Pel?ewzEL5^Tl39kQ-gmMf_bo^!F6XL(lvdHz zoBL*R8sSl|%k#|FWv842fn(9E7Vzh4$8@o^6`X~ZoOsKFGJl;@bxP09@l4B-y!L~i zzg`wrGVhu`wI6+pbe)Q{aWz~aT(G+E*w}i1X!G>C(ElQ^)m(Y&&XRT!*7>rO5#U@P zk$JS~(z5f#*S$?hm>|v6+Ai(feE0t$Xnl9 zUT@V=_aT2$fJqL`s}#wXrjPl3J5R`Kp8m^?wX5)TR;L@keAcsJbjxi<^jl^f-+j!5 zP*n$WSW9>(?=YnIQ?IX&Zpp?&ovm;Cx~(+7`M1;qQ~$;Mr!L&_8%*@99ng6}GG&i*x zyRxx1vOT$rTDKRtb#y$mUR!$Zow{{%arY2@clmrWb^m&0P8EaR?e{T3Dg#DW>Tbi1wr32UDDs(WQU!Jf_nLvf~u~_z7ckNk3-=@>88hRm*i+y}Yp#k!EqUM|*fi z$tpB)t<=EYX-Bl`u#QJe%~JOwy6uvWjV(xv2opVOsN|KoZmjWHO%}26!YMt!20xQX z#0mI007e5?J*QUj{7t94zXeZ4XgYtI|HRaK5259Ex+Gw+)0peYov_}Kb=v2~&l9($@KlJ=>LOt;LQD&qm z%D-9HSxBMCnFe+Pc?6n;<3nVh^b&}^1C8}BL)DidSHGDWLp7k#DkPIel?bOuaoJHp znGb|wrs1_{0Mg-=SPmea?-8&vArbWsb0iQg2x5J|C!#sIn1~nq1e2xaQfEWuAqsEnq(MGpxw8Z!o)p)Ssh5?8ZzGnLJ)dcs zSE0TxAAvqBYHxEGyBYfiuQ0Cs^RZ8Y=mwBs=e?KN)nRr4GY-;Jdg zao_t8;D~xcO0~^2+RB8|&jE2b39TFs1$96i7knXVu}U*(p)SQfL@3Otsgj~P!&lsvM9*E<6OhPN1YG8jj ztBWZ&Q-u#7=Uzh7bVG*K@N4C(f2MZ)j#p`KVv7aB+WP*TN#{3|)2jh~4sxO@w@SRuWx-Ts7$oHG5;mkx99G;h?;cT4JnJ+ zxZ2rtUT*~1R)p!aZKVQuKSa^H5}B;^+6?6Oa3!KrU_fkK5>KRs(nalD2%i-sO$Cs7 zP2*2eNL&f~u(bM{${5xCUb*f#UfKL|`%yb*vZ`~irZ3&JIv+_nne&&}Lpo5+dqUNi z=!r0`@FF~3BLq;Vg!mwAG2Q}8Brx}wl$K+0Wd5c$7(2n_=6Ga6s3BWn*y`I=u6p`X zMU6wQ4rufE%TkxBM=d3~^_ij8q;9rQUB9Jeo;hem2uCVRMZOtQYjFGHxv{djy}&_j zV0Box3vB(Z(rLC%dzfjc-s_g$C>#bP_Vd9%Ua&&F&Xe*wN(FGRX6(_6r2T+T-_gUt zC>Xt>`&2v;bhO6oiG5l65v2$Tqg&ZZrg;N_VGJqcH*Q1FdJgaD3`WC<#aztaYvG_>j9oCm1Dfl#33vX+EWyo#u19S0 zwO%Hq1u0{1dX8!R5gI&IOJk0Oj{Ix^NW2FclgwM}9Ivkj*sjvvQ@bQiIfjIXx2NLM z;jovPMB`{bB%YPxsJim5yv(^Dz6qvQI~Ad(mrRX zxG$4@iU_WAk29Xg5WJd0K4haA$-2QRWlC&rTfFDTIDe&8DBJC@s20_ zmP$phQSyU`j?tqrViwYH#mAjMtrDlj>MW@HE6w)!r$gybdcrHPxJ2Uh$jaj=_O>wIwHZuYydjf9c zH3p9t-D&s0%dHe)W*2+Hr_gP>RDN8M+Oj(|=|Jl=Il&63=~h;w&V~&BkmCUB!YCGE zVfP!-Y*(`n;&-?w!b9IWdB_jgw~w96K@bayj!TBYmNiEz>m7nR1jzhz@;c~-aYzq{ zY68$#PyG=>68NMsq!&bx{je3lq#Z&Uijxe#jzm|R3<@7@K+lWl*)1lQ6wZP751WxK z+KB;NCdYd;WB`nqQ8AnIT+av*awBnJkJ96M144}aC>c_W+!R;5e#!q1AugnO(uhFHBS zK2BN{;0VFT-hI>b>y7XhQ;Y!lW|RWglC7HSi%I<~quAPwjB=IwU9BQqB4>sex>v)H z47VKzhQTN6g$0!_zZ+*hD+3zQZATlAS4HL+%a?hZtOM4^6Wg!He6_|OW^~eI-7q9q z7{OzNG;ev+i?y@i6gSId3Rr3;*>#uQl;N<;$(<>c#;w( zm|^}DI`8V$!e7HM;R=u`UFnwSWk+Hn17^r*LCNBBdAw+}@N^eI6_lUw=- zRb*tw^&t7t;3lP*d+Ss@&ye~p;$10E*562C8gE>gv|fO4k5Uo^e<)71K8sG4N|+U> zl#E!H{w0Ir8_0DseviHAt}TcCA!ydvhb=qp#C$r)LM21j-X2MzR5d>pB-3(jrcxlK zioH9>jCva=6PYHF)}oAPl|VZKVZAQ8tQ1+A*Nwxpe^UlHY2}-K%Wl*ZB(%Ap zP#*l4xN7YF)1`DDvRXpN-SU$N#aaGDbMyHpcvg0765d0@)uo{s8SmoTQOH^>VME)| z8iPCe%E(;tLKe1qrRSvd!eEfS=5yq{=Q!OjXwipOZCNVYvJ>SGocaPpu1ZL}(^kkq zq;3-0Fe;p}wX_bGUcAO67Y&-3?-pFXB&e*oH7QD;266jI>@dx zcJ71J`uTCJqCpYVx3Ek83vZP_8$x!-kvUt9#?s_EDt~^GB+;hNk;F2r!^-}94Ox|DFlAi7urBf}otXFJX+Lg^s_tAVTyAmw1o|c)mb@mhgdzACn_5sDkH7GeNF3IJ?CmjF^Z53{|n8gbuFFr-ga8(Sv~csX@vn?xLvrf z-!*c#%?Vm~KH%V-+&^@_P}*S*wftZ8si@QccIEv0p^)kRH#rmo5HqNgVuSrl=1j z44KnmRPJ|o64_G2Bgq_SwGgY#If^+Sr9UFYn%5Rx<(G{!Eh+4D5hciA7l!b=@_9H5 z&f2$QE{4?_dfWb=AeZj-FpsP4!?I20{w}Z+I+I>9>Gl8>PH#Z@Ma?Eb?3L1lDX)Fh zSSI)2iNM0(?kJ9A9+#&IyG2(iQMJwSGW);;lF0{;^$VE|OpEM-t|hPQ3Q3!-);wc& zvtuWS$O}sl)B>Iu%is>KRD0Gs!RYeu_0b01p9SV|C%?A@xY=}mNypU_r8&GjgBfsT z>GXMj`7pS1nesuoJy`d(H+9xXcS)epYf1F|RQ6oAfXBnG>qrF4 z1=+!*&o`vLeVfCmJ_-5d55xikN z4yjZ%att{#^JoPbNJZm_guSFaG%c!tz4&jj?i5MsXFL=h-(Hh-14(*@$-KXV-S^{W z#WjE#vbDoRnKOq^d#EnQw0Wu0sYhZtAuhDk(O&mmhk5o&=(K2YJwYb9PKdvc^i_4G zinDAj_)Lntb2aIT;~k_ZOH5ObDa*rq{=P|y!ldF8L?)IEF`G={=qtpaSM-YeVEZja zKBSLYR%)L~%PcSkwvWp&{~&rYR!`lB71s4wKPxoiyIAHlkA(4KG}BijZ8RPU!7w`< zhVfoh9$P%?)mH3{9(T+J(O)#Z&g@^b+}&@Ub0K|ks}@IzL%-tcmi%1ZP4~0Sw3|z& zJaS-jX7h?0KUyIdmfTah7M|KP#(|qYc!~{{`Jiqw3qI9MWc+dUwa}YTwd+PuXd{Jv z1Yx#Mw+tQ2d%IVdaXev`h3y+?Zb~VVd@hQTNMi~M8AWzn6Usbcfik|`Ld`5L+ojyp zF{5Y2;Hwzd;-7{J10U9C;imPd?^E1-Zqf=(?7HojO{)jFykP#ook6z(bOAZ}-46&< z1~+#veYu?d1jqM=i6AuGhkd8Vs$GwN-3{oUsUdc*%6xJM{H>3!0D zgVMUPE}iw3vr?D+KD$49-?4F3^;MAVPdL#P-evm-208GOAlv?Rp?D5#>pf4N^_slj z^&BY=iO;^tf#l_I*jX%@%U6y*NQwl@o7UETT?zax(UBTv@E`Paj$|NwoKs zVJ})~4!S%7ETYvGIuwQv>#V}`O!fl042DwxKQUYz`$)5#JmkC|o&2KFk@>SbpO=!p ze~mgP_hZ;Na)HMYr-}u6&22sPn2AYHVfu!r?~?GFNs4SU#4fYv1Nch@<@c)~4p#sq zXV*V=IPD@>S1B+d%oA7JYhy6u3*b~WMjP=ElkoD5;M|sQw3K3aj-~cs))nzt3yo+; z>H+L(JEPn|Y)QSARHTZK<4TBjOlnS<2?9^D7MLXIa|A`)pWx*z&(HLxfWOj)Y2_scYy&bXBt_d76L6}d0df1Yn7-{H^5I(Scjxn>4Gm1r1 z45sx>;(=J4QWCQd(=dEa6bOHS;vy}IW!8*|bc{!ETE|MJ7Hox9R%Ty4W2gSUEwefI z3|P#MGt$}EijxUT<&8&_@Y0Qq*g5HC+aS@wsVw<&C@WAWbbr7~oK-8@WjezMiy0-7G2h9o^qEO0 z`cfrp!m*e2?~>KqzN=P2I-K^OkIawyFqOT6tILy~qJ6K!mw+gFOxHJ(1Lp5yjwKlI^3Om{vEh1m)G<1-gc>9f+tZc8eA;i^M zk_&9K(j9e9rEma$h|X*pq;b!g7Fy+zF5IVEIkz+u+apjEUANMj7CVwUu3#>_ucX-z z&XYQ;Gnj#JGMkVDk6r%_g-j;+@2U*c|1jwA{Qq%VJ3{}nt_=OJb!Ena|HLq7W;ZmZ zfYV!=+B%YJvjP3x@x5vNfWf$7=+W_nwyA-ciMHv5*tzAE$mWgJ_U)nFz39oqsN<7} zv-9A~tB{-9p!f)rlhTTs~~Dk?p&&%hghoV9A*icuVAY|eMG#c;;kifN<8aU@n3G>Up8?=N`hN%k&4-OQDNrMCwZk;SOU+-qY-5|=WK(|NB=Kp8c9sBeZ&aJKnh zllOsqcSV!@nymxX%l@ZJI2KurL1|d0#7&-J@Ir~~$lE;x=)UQY?$Z{METv01Tg+qNsI*s3_GsAAi;ogF6?+qP}nPP)$dyT|SBJNo6G*FDB> zzpn3GYtGM0^}3Z6c{{uWD5jZv&Ir5PDIUT=Gm^=Q=A|p#Pdt zADx~LY)S`UgEw6#x7EFEz$Mdsi{@y{4G9r+%WDW*cs&Dg-DIa@6Z$3pi&Np#r7h;H zs42}sQm94$N?0f*Jix=|2~0n$^93aGNtY+uHJ^Ydz2J)71Ge_6xh<&d?)6~+!+a5%DjCVJn;RRtt^LWiL9Wiw_PM zG4=XJ+poy*0G-ar^BB1Mm9uMZl=GBYB6uBmt-LScCHV4 zvLuEsfZ_$czx_3?Ax_Rw6yZ3t`?6m8jmrom%qGxiwFaw)F*`0=vUU&RI+T|mMaNF`hb2F^8-|wujx#4ntXJ6qXjb9wuoI7 zy0b!a(Xk;VZ>@7sDEUMZ)>i4nxDL=}JY>DN9MfI79S^`f`jha)13A=%+ zBPF1>>e4R~ z!CGs~WVy{2#&;-_4ze91nu6QK)RR8!=NAt@n+ryL4n(<>FtgT}rAvL1DZQoetJZRr z3tFW-eS9h9T02E!qfil~ksqA@**!*GAvsNf$qY+o+G%pc`S{XMsjvzsR5(QhOGAUYOu`3k7bVwT>VXZ$F}s1 zX&Ij}{f1YSVh9dEL^fc1mEoBc!TTaWUvmpQ1G5Xg(cUMhK_7t@tFP*z##wRR5XDDB zjGW`fT{_bcz3q8`DY`cDr`#US+VddSWNoy^e-Fc^{L|E&s&jVAE(g>M1zmBu5LMr48kA?Hp)(P$NeLh~QTrIz0O6UVwg ziNnwTS%~7aH;paMOpp}!hhjEGL0ly2w19d6Q?0sj80ZYKR7KtC&rj@P9ad*1nJbTL zM8Ae)3t;%sJu1HL;|Mjs!Lwko*+F;ty5efl_Z!k{w%6Rd2rdVsTl3*)5nhDTHHy(?50DN~iuk7CXWK%- z%n2=k2Qj?onvkJa)xy29OZyAc1ba>RdYd9zU`Zji?S2Hlvw(t_fcM_(5b&<1*e3Qi zinzHILFgwC@%**dpqlOWQTF#<53rRa0{^T8$@SPL9@6#Oddbb{<0o=gg%l-#{eU4u6ah*V{x))vK8&(ru*gdZ z7|`6$v=fjf&PF;QKS=d5dnw8AJG3zMQeoNunISw&y^}480c(*DLmy6+8xA{4l^*Tg za!_QKWpG%W7tKUdS`-eX29|{zSd;^Cc&I9f+hu4y$~VKyD+*6r{VF^CL9A;C;AQEc z1_yc6>b`cIX;iBad8||eOQgco($VpMT(~dEz+pG!YeZ~7EX&+486tgSH)?swjL0_M z;x~KIwt1Fks?Jkgjj#pBtSygk`vxv&rw*=Yz|@sT;b{$pDEMC9btRK2+>c@G z`)d%xdYl=8z=uwFm}E`t*T{bMxkhJlSp}$FVT&Bzm~vc&T076kIo_nei6{Pq_lq^? zcnypf#?%y!`_+sPtr;7PSl`oMHkD8LeHX7f|Mfgc=H1$ClEcO#m%g!0)iRN*4af3_ zp6<<*X%{^;xb<)O$5pc_8<|bHp^f@Azl{%<4agPi-yq(U_<$V?xJ!^d_t^=~`DjiM zx3n+wz8~CRDSa@{qhX3~FJl?iEN*KNIo__vGNzY)s{!SD&1d-CpUvlgLHxhBT(1Zo zk6G)p>6_~+E8e!6FcsbBvX*3v9mWW&n-Av18C$MORjS{|XCtyb?{Iy=KT}4GgEpR> z1!CTIHkzsg9_5+@-`@^dy95sJRVcnzUhYf<-=F6eKX9G|pJ0%ERoC>_5H$oL2nuD2 zMRN~fxdi*7qWs_Mi2(Rqyi68IUg*eMAah3y$Qb9Iq>*V*-0B^9c}o6T4v8@6k0M~B zOhK5)#PIyiefVZVAsi;DdRoJsNV`gwwC|fJ+eeuns(5TbDs-B2nXsygP7Y~_3;u+Twr;IB~C@ieR@t|8v&T2qhy z0?7Aa$;x9W&%keF8tbW&jG)Z)kz_g~)v5e2V$8a~+6lCYO8I?F9qgjoVJSLintuAge8HJ)G4j1nk;hdpM1*2)BeSl*>DKvF1dkJ)4n3} zc}3xh;^aKaTktAIIF*!=k}|XL>Gy?H@?|pWqqE7a^YH&#Qty9IH~t-t_y1>j?6?B< zi9n8aW%mJx$0yQf7a&*v>*4WlMdW=U$fW<4iuk)+wOk*r{VI^eI66c?5kfVRA|ZoF zb)qCYkcp$072xCkUM!l<{A1DtyZ=BTmEVS=A6xZEK3m9>03uzLN;F?S3Q_!3^yF{+ zG>aiH{l}>aP@uwl07tD{q{_6z)>JyTQXBScmmNB6(SNytX`?d>xoKUe)#M^wK2*g{ zyV(mL1W{+_vS%Rpf#(>v`(|q(62I^d9rE8obOb6#Jzs3Pz=;4}uuu4OzvKBrS$(0( z987G#ZBzb%+y zfB$p9GLiqsP6%?qgECic(ATerO;}_M=w&~yz~=2xwB+HuP*k(hU6<~L=A2-pD%bqT zOYTtrFckOFJs7^jko*Wv@G_j})em$3IDjG7Uc~Xn@tzqw6HIIZ_jl=lq%VWC!emza zlb96cO{f9~sbtNaG)zS9y%3?*Wzrv(w!>y2P6|y$nIgqyKT|z7U5PSfKiw8`Wx|z? zd_rfN3-XMKQ_P_w>Zr;Je)+qVI;CO&EebQ$V5s#{!e6P&@-E#hBa47C$4SLr7N_O9 zgED8(NwDcOx#jsQG}TRy1$rgq`#5=Ew$$V)P+wg1Z-<3%_DL1;lMd4r`q+@Xgg@qR zeq2B<)v@L^&J4CLfo)k{SJrw-*xTCfy4PHmR)}2NI^MW2*;U)HxG=UZ4<@I9zQva- zx_tGPYgF_>WES-tywKu-Z<#IGcOr>;)U=@GDAf$2w5`>`5Ta?9_m7t;-O7@bWcH2< zHjIOg%Z{{zPGktg+QXcfjns9J-kmeWv4dT(!19mb)X%UYeeBQjK*@{DBJTy%%#$i1 z)GgoEDRW&N_!YgTo87=2dxvg07z336Z>z|goG zq)vbtR<78|1)bQF-F#kI^64I4n)U$MR*!JHS8#>Pb7m>K z)ppx8=FxsvD)Qxa=SnHqef!6b@bfO;$L`~L8B<^2IW$61;QDYV=5N0a5`8m&pt|7w zyJTJ3>t{*_h1;d+1Fk;6FeqvG+0F)p%>WGHuKQkk((ff;8&vVI5!!*swK*djlsrKg zZqqK1U>yWHj8X(1Q7Pck3iIrHX%+ZvjUyV_4xIclKS3{oH|aNGIN4CaM~J`ru3Znc z3$h>A*2+NAWVb0(gMsRM93#g%(dt)4sW@Ckjh6`BE>g+z0Oj}XaMWj`Zv#i7uk5vv zKiWZXcEkss~7~W@h?otd# z3I7URCDkPt4IYx9uu0GnMJ2H+m4;OdjAdQlrj(aPQQc(-Di7SJ-sopzG*eE-{6$WI zawnmqC6;3F$COccq?@%aK049bq=Rf*#3Y#|4pq~H^&wTxTmn2bQZ5ZAOmdu5Iw5K8 zzJO)sULHS~HG@zyl}hvXq(!lc!GZM=^A?O^aD!rYXJH8_Mwy>&T^!gaA2Bp&IHtEk zch+lrq;MMdR3OcKHo8!$D51N}h^kgX_A=gq7;UU_gzYylxQzqJJe3*p=)}Sgyq`R^ z)H4YpzC{Sm7T^ZyifNOH$;W@nAlv7^XKj9y=6@&yXA)D2L@X=4A_L0ky5kmBIdLm| zNU5aI%mcL^fEp7(wWiU9D))zSgAQ@f|FBa3E6JDt-gJrzUR9A<1zwX;_ve4qb^q;r z8yfzAP-LnJ$p9$^BgRPSuP^AK z=$%2oeyZ7E-vm->PtRZ9g+^g$b^mx$6Prb(u@Ntu__3A*WYM}ue*=P)!sg@0;mG@` z7R<)8r|WsTPf{WR)vEKYYuL_UD)b6$O{dxEU~0@vbLHWT>9y00F%!MsdTiF3887Pk zGrlwGqzHU$;?X+i8Ds~(NbupYF>e=o9yve@xd~78LSrZ7;&s>U<;CSyZJ)m|oB7kT zGZJn1*0(H?Ya%sQJR6)&|DYY#lgECv+RQ?q_HKWERGdL|p|!u@burz^DZx1k$8&|+ zs*B5pbj@&`IUUQf>t@jNxbWMEIdaLx1AE!7f3f{a(etYa&OBO565KHO0DL`h|E=aF zNKMf)`+!K*_CAU-Ao6=z7TK`+>M&3a0!T|?SYtKX8~T7+P+^7;wO;S|frmYBxN~Mg z8}id260N{6a5O7MvZgB){07;9CP2df+#`(;1V5RI6~kIVil-+jDU7X_3+;=BX0`xJ zg3{CkONO+N21|i(;|5EmmS`c4V~ORCO|{_B+)X!&4mE?f48}SN7v^)@&tmy3MGx1# zO*1z34W_2D7HBV>iVg5KHI51STnxxZxuyP@A0xsYq2N6$L@mIq$750KVf!jnK;h}G zSn3)*T98)^3^^$$%A@hm{(hhTbe6k>|0FBb^dl$`@{0VCB*Z> z7)a;+@mV$GM=vI09Vm=76BL9b$TeU3#o8&@6A7MDKbS0x@W9z?2rdNb6Za7aUcg|1 z^2LfOixe=Zsb-kyC!YQgM1x#i7tPpv4If894T}jSEpP9Xg4a3d%q#>yODm7|c-9O( zk-YL0p_FdsETah~{&XFI?&hMn@ddkQU)s9!yne;oDbx>**u-M z-Yo3>@Wi%-yMOzyIWuXe-lcVEB%%G%ECJ9JhQa9``eH>Z;Yro*wCQ08MWvF4B*PLS zk*CsufH12q)Em6F--vb|BYTOq=R!Zsh!ODLcq!``aee_c`iPS4gTykkP_mB2i%o9= z@3u+c$29yO@2^QLO}fz~p(LnZkwcEsjG@-C29KiRG~6@g@EeAsxLi=e^!fI_IZE<# zkNQWYl^YYi3HM5hIK;%a7eWadNsEcx#3t-R!O%B%Pz5^>7DVP!)8`A7S$ioKb$oiwlzzZ77VJA zDl|W6G)N6*nn?b{Ib>NuB&Vo%^nzFOJ<#?U%>ib#n%>SI9u)Y79h&)T%kt^$=O9 zr;#+)#!pn3agMD_x9rl5solMO z%>zmO!y`ju@uQP7{|ooZfo9vG*YSzR+4=w6&Z$j*SbhS;{-aP$XSgQsKLwUJ>m`HQ zKgJvEP&AQfI9`jGuXOx(IancVadKHI27R6|>I9gHbQ#;z>99F~BA%cJ1GHs8sZs%3 z?5-+JK$%<#Q*Lx3PJpFUIb)5>{Hp(%cr|Ue+P4hH4P-gtCbkuiFj&%VcJA91|ai7f?6Ai5pctlKOc3~#%P!UPe= z5JBEtY8Z(=fdvmnvn%BvO@50N7qj_GY#&}06^e*cYO%D? zhmDOoH4Z^sdM9yj!QcP{fq=UJ?1|Ze2+UBVu;{n&cJiU9)#CDDnu0`%Qs%eUYtt-5 zhQOa`jOT6#32X1tM+pA@7Wrb-1eSd%cHifZBe;cHOAFZ!R|1MOSkkF;8JgWr#1c+V z%nJ*>PfJruqEAm^tZi2-IU9kFQurs+SO!CZCn;*4uQ;MujO1{J-fNq zwU)qitE74cT!s2jH8}dr*-Ijt%Cc2hvO0QCEBczW!PnA8uV7q2DP?L~r6@$%*y*3} z#x>*CrmBdmmhs#2vM%1bz{<3*$unE9>qf5fo(;2%n$9+fcQ7C^emmG8kwtq#IllHe zSoeu*CfLYfDtuz^TliWH992reEdp}_tD`cV@u`E~bF`4&BwUP@@f69s+)WrpSESzz zyEv6^_<9ROFOSF~U-X>P9_0g+s-67#436PMeUKidtMLjG$3 zNB7!CJibs5OBnyXp}8Qk(RP2?$6koNdz*)`mX(^BZ_^*+SA&cZC;tSl_E{V@#@W05XdmYElK9*FRu(o!94Q zdICk$iUeO*adThZx=(0=U$tUzJr5$mBo8q3o*uOEJ0N}J;J5PL5M&#GfVr;yj~K(Z zy>5`WLxB$nWN=*gH3&-cR#+ap!1e&mr~CzBkSc3W`mr21i$;-P^ATU_@d<6qC*FgD zX?I>#T_k1m_PdRskWW$N_(@ek_)sdR&FR^cbXPyh#c4(3cvQ46)?)x|Z;je?Hv;-a ziV&NwGVyn(d8`FAE-Dw&sAnzG?NNSQUz_yVK)yZE zV{AB&(uVz} zJa!{)(sU&U`fo`DHr>*iMl(r}EJe#?)Y4isD$c!50EWM&lKRrV42ipZ7HSm*o7b5g zwz^V&aT=*D&UyIAZ>4`wEagYsT8cZxfJ&7{KT6zx{B8Ym-0VM5mu($`-nNJ~!?#i& zgY~Qb&R!wNP6OWjBA;!EUgbOi)Hyj_oZ4xqcG#FzpoUregUV4;Tv(>3{%4_&Zqs@27sm@gBu_l_L9Nj!n&sJZ1)pjP#X=0&V1z!!s59Fz7Ly_Nt073lKf@#g^DNB z2ejW~B@B;8up2HWN;{TJWD5iZ&ST#XD&>kh;tixFQqC0%hKdXjI|HKDGtV?C*MjhhqTOn(dD&gR4lQ8nBzke!o6KPJ{Zx2`IUUAiY>wuCyIXy1 zNBXt}!UuDAE?aP=rx9TJM7k}zDX^904)^sG^+4c>x^YJcX}{AX;$r1?sPBbGMwP2O z$u2eJcP3q&3kx5=pwI0#!4YW5$*+M8Mgl9mD@VZ-YlKYOId24pkD**3wl0rm6eO{} zEEINeUaA|zCjdgmE7DmS5CgxjAs>I!qhaDVgB`q^NNTjQAF_d0YJ$kjBOR5Z42nXL zvMuC#;H_ELQWW_E_0TAdk7dn6B`uW)sEMB=Yw1RrtEk0Ynjugaddx0@ zxUwN9y)S&M6Y zICt-FvS9F_mPssbJ!+^8$Bk{_1lP7{zV0<(6fAs5vl02gIJIeOz*sx)-p2_Y1%c=E ztKzI+;`8kTAEIU+fLU{7M#dfdbAyE6bYF`^T>kA>AIK=J4kV>wrb8#K-Lyk6a|Y9G zD{`SmT`ldF98DIFVru;;NkO|AxG*7QPbc9-(G4`2&45MOJz7N=PFR{kNOf# z+79PB(3eQ|8G^)jdrmX3C>JP8^>>9egRTkTb?g+YhB19onp^|@~X?On8Ov#OJAoV3)@@;z6hGLd|Bql(?00`!78cK4`qF;hdR zlv~XZt6P2ieVf&n&*wU#woXseKKjDXRr!;@UpfmE8*gs6qTN3Fzo?qRYTB~jl7DtJ z{4(|g%hlJqHR`q@Qu3o=LInF-iiT>O^2CnaF2!+006(2_?4#8aVjAt`Xl_B#wkchfh$^S#igL}A-CQE=~)tmE$;JASTlTV+{Gfz2Mc2x z$49H&7qt|+G3~Q5g8iaTZY4v!@e=P>xogD||J)f4Lsrp2PI(-_%>ET|-fRSshy{3_ zu<_cTGsJa+7F`7(#lXyyLITu<*!YLb~XhNMj0n{pRY3!Yh+r6N)lOEhD52N{%t zFIkv!L~$cIxXfhwr%yV}OM{rZAg483PjXAgPAXO1kwMFi2(WW1`kbDS0w6|(gw>~2 z2JeVr9>zs9OTO^jA?3V0=SIX~WaI*b=gn~*j-fNl7y|w8S#V9wC1rsq)yhOgfjSm) zIy`{XY{g>wyfSd>bYbhdKjxkh-C~SF-?NSGi;#jc6r(J;*Mtp9#dN4uAmT|%CuhA? zi(FYG4=kw=*xy=JuX+~@MvTTSq# zXwn8f))$aps4X~YjTkjn-pf_!;AgD;&pEwZt}bYAP3Tx^iPIfwA&Mc>i#ZB}Bo zg^0CEs`b=uY@9qexAhqEJ1SOd!Jt2P>cXHqyToXVTex&#MAtZp#&kSbxNu{JS=$Q# z-LYPj@OwvA?FS%v1mK@HaCkhkX<({5A>ma`z2HcL4f% zCJd)W4n%NGFz5IVqQ`R|5n^qqq}(p*66wDbH1|JzEg<=D;6=G55cwd5#icpG3h=7> zKMjrli-BxaR5uzqJ~>r66E;1+Ft-%ExVpBo5wO0!v$gk6V4L0Una9PY+x5-=-f7Ym zjD;ul2=r@l00|q)n(nE0ZwQfCk|V?Lc0V|g-=NjAjM;1=4aekiI_wT~>aTMC4(%RL zIt?vhMaF+hwErDT!Hz{7$NA?%8ESs`d>*>hVmZ84>)%2E(3P43qfGiWgG$g^`t`aW zM3@Y4Eskf!L9i~DpdID&j}O`)Oc5ZVUzSOui`TIIfNzWxI4r(IV!H6H_x;+Un z9)ohm%zJeOU~5br&OqO#3|8;MHY^6#Xn1|NP=13)xW&f5M6S||rmNcGfURPU%&G(Y z-U2jpy*QpDyxAa?pNMNMb3`k4c7kpnTw&L6PUTku^?VlS$LJO6TXP+j7&ma^gkLkC zhW%g77em>ypZt(S(zh@gTaI=eKS50ZG+Zdo?%li@{aGv60hYQ&-lKExk`nO}^ut zPzYTMQIsT@uCB}^=GUkx<#eCFab)K$@?X z)9{#@QHmbx`Y$05tNO|x+K528Z?dPUYn`h$6)pa}c%^-iJ2oYrB<5$$ncroRZ96WR zY+CMGwW|@IKr^l!5YDaoTH`-k()ei>%;(GT{}0@=U-SOTIqu; zt}^%A%&e!}`c|&nPH{ij-KqsPZ3&#)%qT{zYI7_j5odEEx;*{X+I?rJx|jS4h{5-# zaY(0k-AWJW<~HK@5nw$~{cZcOlOTxbC!J;l!h0g7zt6RUHXdC9)taI(b8&dW@Tv!7 z9Dh2oi{Q6D7n;&|&*pvf@^c#>3njnMCj25-kN^}IS!s(NSp480s!-&6W<++KNXyeNHdYm-Lu@g2(s0L(kz-MW9Hy@Vx*`~*PD zi23sr7(mcrp};H12Z&PVo+Li?035pQN#Qjh<)zS)8*I$bObiu3pW5d7r~UAc^+9ld z_Mz{_g7H`rKG{C|6EVaFBG8dM^8IFyA)kSekRzTzh8`fVy7cFFB7*)p`YFCA&J=;O zybG4E(MO!E7`arR2-F_@KabRIWmGmko<#S|lvxsH{51_OF-Fyh z^&_N?gGMDeg71(xZ$#31vrMdqj1VjAWP;a!E)B3_%2tl$>-b&8Y#rW|`(t?$(aj-R zrM;MK16#q9qZ+K!bJh1ud}2(1W&6% z4-id7Befb1B2%*5Q`xpx5#YUJ1p``7`u6F9YIEeVfX1LLj+=YR!_@lbv0cAP%w+;zJ6NG*uWrdW z^>T#imNVw|@tu@tyvrPk)S^Cn>EP$M%K?lYE&02OO!p<&W~11EB1NRl9H-9|5PxWM zisFm_YwwG8+A-zrUgLnN_a&tCr^DE z5a;9-;uRGA?WQfO_&3KBeR+LlLt|NUOHo^UUT0TUPj6~^|3K_e@<{Gj#zYqQ-0)1~ z9QeXw`10yn#MD;G&Tjnv!RXj=+|gOo#pU+t&DGug?a))?)aI-E`}jLLD6~9Lp6w$% ztVpWj4pHz2-X<}XGV(yUFN4v2!LKjUoM?hC0DRgnvJrkF#Z~FDc*L<}2ff}vQb#j9 zR}Ni@@v?g2DRL11&eE4VNhJ_bc?@<3HtMb-&Lj~VQ74)-pqdq1ksmv4WF>2>yE8y7 zc)6C2#63QIF<1-r=b9O;d2;1?jgv95r-wSYewPQ_W6+Jd>UNJa1iXe0DT5JmItG%t z^;2#5aAb>GW4jttU>y~-{~=%gsySMIP`pIeQ_sodlwNf)>hhg6ZG)ZFNTo;6et)#b z&*#dgn(J@3$9OE>I><;PJOFQ>aK72EKWBl!^Szd1YUO! zc~(sVJUAI|Q`d^aIf{f9U~hl#%}Se4Z!3#AKJXw|L||Z(z7qlS){VLWEJDu)_Jzt= z0YS(Yfog_~;6z5?cp@6x21KnyMj&L#%Z45fMa#Y6^sT8A-VV%#fl+f@_D0$~6g{K> zfn8{mz(y2ilepU`(;d)w@~5m|Tt04LKdu`SQ-HFWT6f}0T8*i@#_ON?WLPP%>&+1!4{~yIB~XJVucDom#?W5m`VBAd*wMIapO4v{gko zf$6CmJp>JHdHo^hDg4(k;@da5!PoH8!pgtDsRht%TPG8Uw}I4cYSPj-&O2z92O`c` zP@`>g#1_k(Udo8K!MA&SZ;!APW=zzbEZlBdIi}E173MMkP2(J8~{jL7~d1 zxK@iqVKwg9$Mm%>I!&y&a5p4F)WMW1Mu_J)$HR-=(1)ph@ncFumicZ{t?0dfiF=if z{hJBli@|`ol^5m`Q_8u^%C{}P2V{#bFXwgcEreSGdqvrXEyX$hx-Frp4fSma)^b<7 zs4*h#onCQ*zWpyY!k;hdLEob_wk7vFaE|5pZLv=XGCr~PxZrkPPCVc~`_IaUI^7Wd zFgEvHwC;6#TyeY$xSvbzd*hvoVKL&}ic(EwUK55^@!k_ibrC(_YY-A88PJyl=CA|! zz0P!(+~}dUzYyBbv7CH9Ay0S(Q;*ii&N?;_Mz=6O_U~+t-_XbO4{iGd`&XhspAynR z29|Iav9GPW;xX!?Ds7Ri^}og`dwi9VeRt}k!Md7yWZamj(DAmdVWoPZ6h?gz zYjSlomP-(V;e=C-b8XE_g)!COLb6nLu9=|yC;Scq_KeaH?fTjYqPIh-!1G>H=lU^& zLBc_#c2K|6sl@JAVpW%WveiwXB?u|tLe16EC7pHP<%Z&Ij($KpS)2` zV%@qaaual$ar|vszYYZ*K8(E3;`i{*Kd=ntC9+>PsGuvEqa2LbUM6ielcg76}1~+4K^zpMoFKW3=AiK_Bt-xs#-u{qjvS@7Mqs zDM?>S8A6E}aQxfs30wmUI*FO6&IfNaJhlF#bGi4Cd7_mVQ)ecLUcnVhGEKpXzS(TW z??#88r7yGhnkZr3)?<<#&o!a8Y^6vCWdu=FvmiuCMHC0VL8~zT_`L85cmh=noC1Pw z16hCkR4oT51{$GM@W`Kn_?G$Y8w8Y@^CkM%$e@nYICJT_TXA;Ks0YljlesL=K(6y3 zH1kwcH@}`qyDpEh(FZHgo0t=R;HcREudOWntr1j!zAb8MnJEjJW)qOJUJ4wwITNtP zeMigfsCM=77w2r>*5ViZD;jt`fD#?o}q2tl;w&5ab00R)la7M1F9i76n&qW9F zwG8#rl*qFoBj<&tveVecPAR)_D`4@cp!{NLkRdPx=!n!^x>r6jWG&6+R_zL(+YJ?R# zR!67kW}oTo5MH)f>@Ri`>;#wSUOpRN&@q!h@fSfw20Njm3f`Y16a$(J$J{OOe2kc| z<5SMYD)`g8ZK>R5<`NrXl9?ud169L@joP4Vk=b0NuHzb2^;uxY`)q`^k5hsKe?Z~9 zj(;p@Oot2LWphXNgNgFYR@L5u;bBp8P~yx5KCVF%cOO0Etqd1_vXx@eTdtu4=RMz- zlTB3if8@k1n)Nm0*=&gD(he^H4<9u6qiDtSwU&J{ef=Y&tP?Mn4aRLB`Eb>(EVg1- z-5MW}YCEiKkm`+V4jU9zysYg~P}X}mnhH6wY)xWtM^5!<+UD@DoSRzL9tMvK*XV5o zQ+T)5yxBVd-nM>U8QXvu?5?}03QN+=OoLy~eO*!bVTzvhD1^@gaM8IzXze>VTds9k zv<~Pd@7v@}`9ms`x5;hq2TU<7<3APd(%0S(*QEc$diQ_&DFpJ*rx3`$KZU>x@`~^a zz>9&{rR7!CHMMpBW5WWh?9S@#OC1>eH|rgD&Q$cwY~=jH@;|J1Rl^8d8!kI=`@4>Z z5GO~TXXoyhSFSg=j!O?-PtP8&Z=SCo?=1jx>D&%~cu<_cd?m1sAb1piSLhjOQME#v z#hGuHU-^Sfc&rqO&o^?zstA0^;Q1_~V@VQvda*E$&=atnR_=Kexg`o5d|scbXsX@Q z9NaMue<`MLbH&=(A`K+YG)X|U93|3bYOCZ*GB|^WQB-2}I_AM$_=vwxAy~UL?@(I5 zs&yo=+hjBtQ0pZqmn)uOUIWHaWN%V%jB($Z9h5L)IltF^+pQ4rQ`&g9Ctbq{ zjD*uV{Wr&?=IR(Ht87l^BZRcapSYsu$Eyp!p58b5UM5b0s(m_kKQ^BErR!@LF}rSG zzTT3cvLR2<)$xs{5U51_Qt0gs^kHbAK?Cm5ueWtjWT;?$_t=lMJ(~PVh1^w6mJEX? z!_4t4$wW-^g9xfhjlxm>Xv9S^>K$)7^6&(X#(-B)?AsFV3=>CEX$=`iq5;B2V?}yR z_6;Ff%J%is??dAfghiyuRDY;RZALPf9+RfjyN#s(Fyt8~h=OGrAlD}ap8Uw5bZ_#_ zbSyq85}H%?l}To{3?oWI8h6u(a(P8N1`km4FM;Kxmhnrs+Py0Uj{{}0paAusI|5I& zgxv>KX{9#HQzK~osgdjrQdB0G|61g(TGwhBUo{AGR!T6g6_e0t)~Z|82E^Gd|GF5! zIgkCr!&LmIl_uk7DLh{3RH30|er(NcAgc}7`l)+DqhV58c@v!oFI|?Dt@cG2FnbNy zJ~Hc3*%T=;f>^uXI+)$MXhd|~PTKI3s(!201F?IBK+e2V3d6If=NqdmeRX*4T6NT# zP{nB~_?gvp55^nNz8wD!4$w@TgHzM}jInOh3Z3Fv>Iu%JR#LkX>bcvDqT+csDseQ< zVxDw;?g$`KCuNHlTdQ!g;G(Q_4p%sPsOLI4rh8mab9^^sHjhDdW;IN(xn0)IfTsbm zAbi}foce?Rd%&)3;%N)cSgJ|Nxq4!J9xbKPb;|>)vtX&u?;^J#s4 zp1*}7RDYA}urPz(_$V;umYZ`IQK$8g2kJTHNG}AAaip3R@okne*S6`jp=*w3G5Zj) z`KB%+K(!#pj6`u>9h@i8WMh^7qh!T+gYDQ>xs#|_NN&q0?}v|PHm6%<%-OLx6lyD zT2~5u$KCnzRmUQXW(;}T+o<~n-TByZ9V&FMeVaPmNwT;fpuDaf`nA|pmSeyirgg99 z&4JY!@5vna{o9@omxcr`0dtTA9{@A#ILXyS*?pF{04>Hyl4-XV-0^&cAmmn5aIwUq z4Umh%3q8d2h!|(}eIGr~Tnb*mAvny_*z(d~d+ZD0mD)XD=m|pzj=_*uElVbt@kU$*L=n%SZ$a$(0J>u6!x!3M2+@MV1I0S#%@X zqvbj%o0AG(D|(CHm*PC-D%aC@@H zo!pCnI+QYu1#hHC^=SlxRgLBfd{~ap)Ni(CUngu5@B_7k}eQmrQ`2 zt!u?-M2o$UvA|ub+DtCMWL39pODWwXQOk{tsx+2Y(r)}Bc>+e$mO!VkeJl6Bj)_XL zge}!pS%PG4?$4-H6^EPrneI}>5Wb z5PQ-EJvk@>xCSgI;WE+&jf(P@+iCjhgm}p}sTD82ri?JyWMJ?OM8_ikgbj}6N)jKe z>m5!{@?Xmz(n--?wq#83I7aE8*TUPsTI6v2Eam<9`Car9w4_QGNPR=A)}%Ifu;aAE zCx3LVpjqEIz@G19Bd7ZG`p1Qx)oSP5G6vZrYS8vYh(P4<(f>JR<3O<$|)dIWuw(N*%LEn&v^+$L?|S2>IVT&!++LgAh#=b4wm zb2W(IQ&$K2wTB}X6LgQ0vk$IaFzvbn##MDUzN~#n-~M(T#)xH=acWe`%I4W${DeO4 zZC~WNTt0B!w=C-R@w-|X;}EJPS@yZ7Ht(G2*Z4~>dat9v(tDxs6^wf5r#TmM?ly8y zO-^#>U9tYj@qupEH0AV_@b|(E=Bbj!B)#k^-sk@3Vz=eE&CbfDB2?3No**{}=ctNH z@^g{Irk-}=$nsTE5A|zl%+IG=a6QrM%X#@*1}d4;-wVS#Y=C4Bex*d2elb$+c#=697>4JXPzV1yN3ifZ9cCB zNKUz11%I1GX5wy~?VfiEBJT-GyiOl3J^cng?`JuA3Vp>)c8mqzPOLs-TE85xRqAi{ z6d8{vd`c&21z*o|I^W!yJg=b$53atv)89GmzvwS=9C6jWza-rNp)Oz=9)>@hpq{ys zjGW<8N&Y6$kX)r1m3`2tFo3_kFqfs#p?z?N-FBb+>gL=?hW&^&{7E&eFhc!%N_?rH ziK|`cXrKMDpt)J40%-Plxt>8Yeg|-+{$^+nxPVd?kO~kw_7$NLgG>#S-Tx_98mRCb z_?;_ARU=5vHAo{hNUJ$WXE{jk8T4P+q4RH9MS}lIie!PbG^MqGw54`*{WlPtQ{zPV z)O6_V+^?R+kmZ%2we{@HEx(;zpZx>d706_{Q<(;osD@~m`m$TaR?>9LVhKHp ztJmTWBQl+#Rl+q`hqY$OHdSq~7+lGWlw-nfb*fK-9um9OME3@x(dvyi_iYV|6NoMX zf8BxuQt=Hi?EMZQ`?2^^)+)H`A!g228-+fioWPdQHI`H+L>dK_8OiEn2i6u2w~7&V zUGhA{?KZo8NbxrFo5T0&;#qSj;1~i=e&m)bFjTv*ob}Y3r~V>BOz~6sE$#!j`~1RQZpv`^mbxV8SshdY;+rRY59W=El{)?ljtP1d+LIe9 z4-%C`bjN?|m-re2wi-oGFt(HHcnE|BS3UxHI2#}wtJHk_*F8+LzavrL{1`6>Mu2fB z53qX=O5js!222>0)x;g*TUu`%0ojW&xcp`BE-0~Pntvj;HF;XRY-`8{qc+X7sf2;R z^dW>%`Y}kF#_5rv9Z}_r8JLF}a!I5ujpmUDEwGUy*L!3Hkd`5xa6o^9#{-ds!W5oX z;DRBe2Z+BcGWU|<0L~SZ7miS8AQA{$_~y|plW1aE8Ua(JD^|B-zIt9s=<4&eicuO} z7Ej&bOVO?97$Ic?>b{z?-6|;GnP>z4lpO4ySM`d$ov5!RPmeWZY=%5PJ@f6zzfNF;d28i8?|Khv)^CP|k2L(hn0v?m zO5^NLH`%dm+qSBbRBSsH+qP}nwvCF7ic_&|JK3kYr%(Uq%$%9eJe%Gx;eN1xYppM? zHbRXvyI(LrI_yghzZ7l&sAMuAK~oQr=16!+aD5rXO_SQWWcLb<{ZtF@mBXvyQ#O-i z4|qZo%jQw{jmSZ>cD3w9`}c@UPT7nF7_{C$8-+&Wod>1SHsktmx^m z3CW6I(4+N27&a7u-UE}sgs8E4p}1>k_oj?mZN+0TU&f2ADH7k~BR}nL!e>cz=v~LP zQ6PNhP!(5Yr}!I$$=js$Hm+)YVZ{7rtiUhBywN1f=Zleh-zvXxx)Q#$`8+v+ZAINW z)2Agy56atFD1)6p%V|hMuXfUhzhE!02+-e19unO={(4ZpZ-Q*-^}Q&r>g_o0eg`?L z^HD)tAGA~_%YdmT<;TJWH#geD-yGf3?lX%gpuk`BM+;Iyj~WE@rKXo z=BI&| z)8Y1g7Dp5LQ|BPq(8GuvkjL!mM<||f&=5zl6MmerBp_RnYT>_*HmWLxC+Lvlq8JYF zWWpJSu!~V;5oai18YRn6QxHK6jDh|{CCm6Qq`PLBL=>ENO!VHPRJ50l9(PQGG*BQY zI+mQCzP1^>NO+Kugf}=tv6$2`5yV!hC-{aYX$OC_UMV?b)!C3vQDDmX$Vp{4!9w@j z+XTZXLe4ldN#p{(h;J!FRHp|ma2=nj_o@O^bx$r!^j;6|^R(YPa3PAG_ypy6wbcCq z70_WU$%|JB%nXA(OOuls6M2OJ4Rd@@c^WcTej`UP<&>i#Uy6{Vc%BjSWd~5C9Kon{ z!a5K>h*XZxiRTRdO_mLoejlevaP4f#1vC)}VhHg&OU+=h&X(gaNbm~vq0CY%S+lDS zt9(~b%?L#<#F@0DZC#5T*W}0@xq#N>=tD8;7${7K_t&s!SYG^Cr~&t`Ps7h)j_u>{gh%T`=SXFkWjKS#%*Rv-6hVvNPBX{VNoA3IEGOtU;6 zR8G-Q%s`dlD?+54p-;WbZ)4W`vbqGwZ@GL^(s+MESpBWmkk!aw_2WRx?y|KROvn(_ za#92exQp4LH@#cty|xZ(8`M#0gPUAGuy9J~lDX`H>?&KjIc=EV#ZY9+P(<*8XELtRd=H(pp?}KWt{3kM=rBc5;N$ru5|FE{R)-~oB}?!tAl>;O`vz2= z4+XE6dkCq$GMbNmov`a}BxR5(OqzSKw6Lm|kc>bN(QAUTH?@H}lm)E1-5682LY^wt zF)@eNcrrK+K)>ghF-<=pRjL`4-+gVUb9axal|Q|Mb=-=1gA5(l{sH`_f#azGf&~jxx&T! zOiF%jR^@4;wCm$k!^~v)2!pL$`%;hUIP*{KlZ$1*rI7&>*TT?9OF;y}kcxWWva2Ge zoZGauia73?XF{t~y$_a6QtG--0%toEnXR#UR$nv6bBCABnM=^z>V7F%s^6vUJ|oTW zqwQ1cQjXo7Z`StbvNqEV!427Q;0^@vJ`Oq8z80rz7gxe`fCBM0Qu|{Md!~Ja>-TM} z*T+6_nAE>hvHzD(b7=pc(_BGeQE|!tzLx@+#|Q>dqbX^)E3T^xfz4>(hYh2C+ZT1(7tn330VO z#2gp(?`bYtBoZUZU)ekWXe367w{LOtq9`fhg(s1!Gu~Jtt&hzk;q5_w6q>;vwX*2X zcAQ~C>*ESat8{{0NFCF-TH*ZnG^d#>EI`8Xqc>OCN@dvoQ8yr8Q{DR4Y|7T3LIaoR z9DnEjwPx}yG4m=x#tmfG0u-0?N5-WdL(un-glFO1el7?zrRelwNi>s^0{)HmzJ1h$ z^IHz>*Fh81j2Su8jnzQPtYoer2Ael_Gw6zQHLdB)!1F&yhT6F?t*(0uto3iHr@Zaz zYl8+@aU}d6q3f)|WNwUj?(nC-Dy02=1@xRQJM5BN^R*WqcK1fPsAu?S+z0>W}r|BpAs4 zK5e;9yUMuBvm~sw5qf$|+HS^$@BQaId0XxD+Ix@Md z!kNyJeWh74O8S)k+_N2jz}@DRj$=`fBZVXIy(2&q+yO2A1xSK#hH1kJo+de1%)Cc= z5E5(tWe%EaYoVUGN+ETKq_0xBgw1Y+NI8*Oc1CKqhk^ys=jxY z&YnBM&*H+B0%0HS4^Zt|a0x>Zso~(7Ah_}9(C3bL8AO+R0&7}9i!-*X;3T988|Bob-mmR$QO^VFn(pYLdLd`{%zlAUQQHqbUuhq7 z!SV8o_K=wyGL*xCnO~)%hr#xZN-Wc|cK)!Z4;+Q11G#IwsU2lSV%%4SnUFmTtQnCx zfCo%ru`xUKa@@P!BMN)9I!)!2Ua^c5H?(jE*nygyD)mp=t6GWa1xib(_Oy>ZQ(4-9&RqWv){o) zuOGQ@1LL{KUgyc>Jy{pS+z^ORQk3^FDhtXoxlaSP->v2^@vrT+|r;`L$-|&_D82hVI@4Pn(clBk9 zSt(gbfvMW#K|e(YWKRk~yt=T5(=$QCdaHnI-U$&0E0~h$NW%Ep3pa8=`kk}oc~1!! zBZfkRBJ}OrnsbxknTm!%+-HA%JNS{>ZKM0u6bUcBG|-GcXDS)2`kWnF03vr7Ar(cc z2~1sSr!}l)n*`Y_*huRb2~LRm+BJAmI}tJtzh$zdFZ%4n9;BJS^-#;+hd*~0;5br@ zb2Ik8M1K(%G#v33VIzkhNR<%n^iObcGCt0y9>+hh3QS4X9%uH5D=L9eOu03NTrV3| zOc6^isaBz7Xq(8!zl+wA-U`m%n$(?tWO`U!CVjz^XA6pEUcFnk_wfqvbVX(cnIrfu<`gaXj13&_G3EzOBrq`C zbl#n^=?H=;Q`9WcH2Z8JUQ7?5R27g!Ish*w8KkfHYgUPvj$-S3$Ei|cqjGMwNFg#6 z@`BUWVw%e0DLcj=Wyc}3aws%-YPb~HV1HU!4e%38v(CZbue}N+41?9+&VUfDB`l4S za_~Z_g_oRUT``_Y7-ChGg^a_hUkX+*D{G4d9uT$N@pLdJopXj#ODPjmlXGezGfkw* z)aBs)`gW=sm89?u0n~UTR_g%{507L z#^f&0BVXq>M2}h%B)Ux<1+L}+pK7%nE15dj(yp!-MtP?ymHBGq&e0kxs#QGEN5r<$ z9}v`zAqIM-p>4nLJg;3%==40uF#(??I6iY-tFO+K0V3!)7nfTa^0wIE48+B-hX%K0j> zJ04R}StQ3Tede{`>C=xqLL>7TF6Kap zJoPnfCklnS(-$n|3*zOR)kwP+SOwN*a6+q-uGdfJ4RIGk$sWALKgVCehx^k~*<+~8 z(bo8vr-#yQ)Z#X@Q2%x*0%uz^p2t!TJ~M~@f{%!-Vp5HGa92N+U59lxFEns)*D(5B z;xOEh&9X9!M!Puy;_$YVoqr}YV_iB1eXf|@G&j#(tJ*isFYl%B;`eGsaROd5+$Xy> z-@mo?s`A(Y4rJCB$J;VbY{Y}Lp_|`KU)rF4p1||!@WJ->4Wl7Cz+2<<<6LtLSG1?Z zT~i&r5b%t z`?#)+HJqcgSpR}uI?U+Mt(P|C>IwVz5_CvuR!vfo_>ScD%$IPMQmV@fWGN6Er(t#Df$n~bH#YJQ3eB?HHb zHCtT~LN>$l%`X&&mVN9uGFMb5H!Nv|5~j>|ZlB0xlAvs&dc<(477^YWf@a4{-aR@Y z6hpQ|9~RZa)r^6)+F@d>W9=M=n%}aDZNgdrpJzG!7KG{@%HSp3Z{6e$qo7eZRJ#;x zj-kOK6iN9X%Z=+G85~hN)d~T}>0m#iY$GdgberqiDiP>cZvz+7jO>c0S6WY3h`$(j zd{$g6#`@IJSbX_997(49i2QPk9nFr(MwH_8Ke=s@*4nGHQtyRhqb~aK;9N+Hx1KNwHQV~$-abI^=pM94G;)p z7|fE))1OgLd|I5w)^kc3fF}bJn2kESDw%> zWmQ)@-&t1EepcdN3(PJ)t7_=gI->$_ozSAMzbDDEj*T&VO>emrl|F5U#;jVZj-tSu z1EWZtpYQl1g?C+omJQ9+yvkc<3x3IKxue<;L1)|Xf(U2de^}DR0RHJYnd1bQ>B8=; zqWq|aB<6@d>a_`sVi>r?J$D$x#QUi3$1=Vsq`4NRznvsSgJbntTK05+q`e+v9p#+C zZg-JbZkAC*bEcxb?gGfkQ6?woHN7yACId6`SSg>ea+Hshh6Bd)7u zl{sx1w^m=?eSFCzkD;wY(Q8_2oxdyVd0e&#;bEJoib1u}J&xgN(BCPieOtI!tG{Q` z6|Ry|{aN6754Z_)1$qFMedL(vVTT-moSeMU73VEG_k zVm%+Cu_7N{37}~1y%1k<^4MNPEA0V-kE%CjWmX`d+UWfn;MYOZa3pgRZ3U>m_ktgT zHt*@}&THgs_Ys!QdMUlcM&gbxBDfDb5Q*;VhO|y0nm7R+lZdUIS z3HWK$S1%%~L zGuXU5z>mR(En-}I(A02WcJV0;XY@iL;@)(qB;Pc}5M^lc+sVr)p-g8xLlz_-k|Bkz zUx7F^#L3bqF(V?MG?a1!@;NdS)a=k&(~6(>+}#Q>oEQ^|o*sgfG%+f&61?MDuIRDn zN;G`qn)50H79c$dc?xT*%KETyWxNE`@>Xxn5WgtONmEW(u`2tDgo!IKGbmN*%$K0_ zQ}UD_^%Zj_%IY{ps*3S4q`M-^d;s7zQOZ^nx|Yk;p&Yea&PVd=w6j6T9R7}vr_x4X zOO>lGS&wklig;_e1EDr$;Skn8Yj{>hS|JN0UQzCY9QmQpwuLneeVT#>Rz~+uNAHg{<~8KGl{G$k;+mE=v+H5Elzv?uT}*YyySP zBo!ebbzG`I&yGr~n<3~}I98X~SgE_repR`A2b)Qfg6{T(sQoF)tX>nmOfjx|{__}4 zWyw^H;5Ns~!_IR2ROm_OEhpIx#!GX~605JMxz96FTMwjKjc{SZ4jOYxj~#QR*ABxj zkS;$DK{~zebhGw{^z5#>R394>;;6F#e*h|5dK=`GxcB(tI_N!3^IXnww4{y^W*!=V zyT?vo$qNvRJvf2_-Do%5V2GCY+#rmR0LyW_g6!lp^jMym5W-?Yua47!>w2f!vSGv$ zH#&)RmHXW_+k_fVN(wypGLb|20CDA1nbEn<=a?Unb98i?b=oPL#0wvq#85mktB^OJ+`Pu0mMLopJ=j7ZWeOA6*$R1DpL<%z_69%o@TjL#-{ndV~V z5ppG{0O#+LmzG*r`_dT)OOa!$rBwLGWAxH<>^7rJnv7=fzzNGcfX57v8bqUyfT>o} z-O}`teC-b{%NRzs)xMvctqi)lK0;mVWE4~a$q2s;2UoghuAG}?=YG3{b!|SGBR6dS zGIdeLQ)#oc?+NL?KGy0GZS8SG8bz?`)qfp_qEZ~FneGa>e+}&I;pQs66!gEw-3G$O zkqBVi{>0+j>1cgUjKVq-et$n83Nsmf{W}XWW^Ocmxdtc_+NIo=?H~Z%IuO*8FMp`L zCv$zd4S`~arjYrpQ_a|;a#~x*d`^gU;&xPH z)aaypy7vACPB8kU1+F4uD*xIWcRugDn1ksyqp;=G<2ESwbVMFz9S7;>T1MB<3#s0{ zvs(-J-M>QUncB88+Tmiv{I$mB$9M!q;1L5($eg@waw5RtIcfQG|Ln&5OjqAy4hrU0 zH$h;{M8Ru$J9oZ`D&op*)~l-R^d5?oe=Q~nx!3O7Yh|eWOg56&37p$wm=?xkO`T_o z)%oLw+rhj3hfikM_wf=IA9%T^AEw_;0=l=Ge`69T!ioRSBnQ+Lz|M#tM!0s@s4tF&M{=3}E)**9m=CGB zA3?d>q*)-fg%ef8e;w67$+%YHSEdBF;_ty%UB;31tWpOxl!ZoVa9yjvlMsd)0_i zmXY)C|53#~%y_P`F93tgnYthy)*V+h(Aj^!L?ZKBNTea{5~W%l<9MYi0(-5lkM}0F z+Jr`gNrePO*3-CFvrSQV3|uL-E{*H8@OV|**lLf$7r>R&ojIu^6bVXXoRbA*C^m_h z9{-g^a3Uo{W(%5=4Q?to#2*pCnB5{HMvq-Uw&1>hxO#3^gMcsaJS;f9$WQ2A=bZc#dDml>ALM>1j``-tMKx|DEzqd&o-gd*27e ziJ^HOuU!8xiWh@}-ae-OZ)|VC*M2oHKa>~o2v0%oV?Y2JwtJqf7WE1s=u^^-FqrNT z@~0|@+D<+>I%#npI$16;so-vKu?{6k?wDuHf(c636(?ODP#`Visn&PwnBMPE@NtWI*v>hBFjjdg4hTG$ci2fm=)n?VoazWZu&X`qDG%luF(m%d&b@9HE-T23SBD z*9hROTGhM~wBCP$)j9>Ji;YJUbEqj1Rnl#FbY3t^t6xgHhygFdRZpeC~Gvbiyrj<&mZLi&pF3NyKt<6x(#TEchIhl$!3qXL#RzQ(Ers~ zZ}^h)xI}Xw1m7+NSX)9zSTpCo{U9Be%8Bv2ST;YGCS(QYL1a zZYO(h6a`AX&g3c4-fETuNdSD3f+(7W6%E+uoP%|pHMeNs31`2=n-=T>r9l*PC$0x9 z;(#&?(#c9Rv&-LGv1-zNfVQh5XxpG!oK{?{Y`MIdp;{L}+5YzSNx#DsCDJ|>8WzPp zFPQQvxT5o8E9n3z#_21xrfaYTaww<$IcLYu2EsdQA0^^hOPx*Feuz`kLjqs>Bm3>d zh)(N$R7|wG>j?8iAo;r5OrUKT>Ygy|I0sQLQ6T#ODZ8Eg4(r^(HKzf(|()X=?nCb1K`A=`mhqQ@&An*f(__dNs;COn(zp^U_ zjf~}R#JT2&gL8C1X;d?iG!UUvkf|w{tR;gq?;J?ItoOIAgQUqZ z8$)6aM3`At#SL3gxeAP@*s2<)G&s=!J^ZF3FDNVqxKkN!(ZwWDr%|@73*hYJW<`ak z0~Shy*~=nS=pFOulAQ|y{%Zu_^Byxg^LMy(^HfPknlic*r1`+^y}ut%lF1UyBMVLa z#hnyLWY^vfliIF`BO0MiiqSnYcQVsTKaeLFQrrYd-XR=wjKf8wC(u1CNQ3<8f zVmV*EHw_qn7>We1`qRtuP>&&DO@#?p(2x1pfRTT$mm{>gs_9ykE_*Vt~HaZri?13<{M$q24`Yr4_$Fb&K^H$_wi<#eJAnJMA zx^-ELM)HJi>8;4Jy?fRAOWMZ{?bQSRqq8m2*2yA3(ODmy=ywKOu3``YzfAGnNFQja zec+*|0i>D6AW|zc9kYxIvbuXEaw5HcxV9nM_0m91g%vtOrQzVL#t4|NO$=0#E>>0k z=r=LY_@L~zx5TtDf$7OuIyU37os}VhpN(dPAI8Yantc+nR=!O#+XGS=?7nZTR%7Hx z3-KKjBH!3jJLo})Q+POS#hg<2yG=RQUw^y*ZpwY0I{xM2IUC+1 z{BNP~KW{Xk`X4V@;o$!;MS=ehrYOVuf0?5Gjs~l1#h{yr{p%i^pxd3h?)!&5$0kb` z-dES2w|DSP3W;A%dBo7IWGr;LpIRtJKhWkNkCBoHSoS-A+aQ2N7F zcAuT|4CNz+X$W3jYAL)(9#70z(uF#vXJ$Xi`vohtY9H0FieOx0cySLz=DmoL2EM_V7zD39jG-y1LTq9Y+Nq9LZ9RZ}|cp@ifhasdwX8X^? z6ou8W1Z?Bey$B^*o`V!S|J8tW?IUwjH-z%l&}_VV8bYs3g>fS+=WiJ%StbCdQamqS z{bLa39WZn!*5BG%M6L0DDzd*MVnn9c;6dwEZ`bzZCB3z_H~*dZeiGtQ4z zWc#LL@Tq~mFF9oOzr!S)SH z2GEh;5s~h@xBLY25d7H`lb23o33^y{Tt5zok9EgACV8_ipH;W*9Dv}L`aC5QL4}yy zy5Nnd>L2?S5zU4AmT&Atw;bOM@K~O{nP54zT4}4=u+=amEpsjsck4O`!FI@UrBZD_ zTmZak5$3mH!MEHLf|2yw2f2t++AUHrPn@LUe&p|N0?Aar`VN!c_f7wh`^Qcnd;QSv z6e$+}8GQ0b|0>y$vSTawXmIQs%0)$uujdtC{ckVm9=oPgV@ehA_xg5qL2sB5s<^g$ zG@zEJn{`*ap>$59VGbA6WKk`KWPYo+qL)-^lhQ4Sge%BtyO3g@A66bUbK_6U8 zM30|aGusJY{86A^`i8`y780HW*u*g;*fne;qm!o@E6=aPyvaeQt(L;(83Z_smuvj z@sMQi(A*41EJUhF#Sj>?65tLD38W-rdVguC1LP(Te@k?Xw!ku~(2H0xB&Fq86CzP~$Vu}x zWnrj8)AgH;IcX%}Y%O=Prn*bH)r(|B)13erJSwoi?j~I+_j0z#kHHQsWT6j{(+H}e zzLksveAj04cIgke%QB(^&ie9WgLOm>cY(9`f{RJ=%H`i;6czDx&v{zcykS1$SW>?atw*IOqxXWG_I+5an7!fFUspC_(9!>yRKfIDJ zj{-fiB=16Jz80N@li!O>OKJD9gI=N2t4nC>vHWExc)JdGt9+*Xa$)jwIn*6Sd})B# zx(-0;UWTaJDMI|s-~p^chZfgp*(zaHK`hxVwb$swqO6uK!ZS=atr%2BL5pl+-9uf+ z0-Yzs32lve3;AuDc)<}f68W$3I5Lr9{7KY;QjYLAG^GNp*H`g zlB4{V(Wvo>h^cAEnc0x}g`lP7f41Kjf$VGr?||$D9UOVAoVuM~xLjQ)+}=4nJl3YZ z7@fR(etzA6z^@$TLI#0H5D(Qe8^nhuKk(?FgP&XpJVaC7Vj8v$&n)m^E!7WO9hz8(&}+gB0@UqqI)TRp1v&^>c+8GLldF zi$G-_IyO0tyS%d zC7|T6A#1fm8<$;YCXvkqhu%JX$F&CxKp@MX&2!%z_{3J3CcW<7LW~yx69~(A*Uw=a zk+u=PVxEaM2BV;ox5V!8jvbmudw$M(<6heg^*Z?ZyB`9dQq+I=M)#+r`k$E`Z&<@4 zmy7u!ewaZAvv8+FhQLcmAOx~$ghPft(6p1-BVIsBis2;eC%T3`nC+2Ks}=7_;>7+T z4P)X(H3DIKQX%t?WNtEoC0sVm2NMu8CnFOcksyz;vj7)LM5rG#R{Bw>V5}m}DR>wc zr;8S^R;(Pr!p%i)&D1x7ys-hjuhecH5;Vt$6X zXsLf$-YiIWiMpA|V-)_UHt|BKCDgv0@mx*Owxx|Rt;THqCre%1;}dEf+I!}?QF#By zx=5cZVl)*qr2KkqDJ)p$8506lzzxJTrt+;V(mJj~Cpr}0@Gz$F)O0&{yiUOQRzAGm zXvLFN?BrWNeAU#&>_^}Pdi_W2Z;w?S`rmgTn}8X#7oE5{O6E<}IZz(iz(uKRvPWo@ z9}IFy15fsk3q(Qd2!DjU1q7Fjj56#dtk|ktc#Y5XIoB?Rat1f-dX2c&b@K$DMNGy0 z-B!>h(Ye8c=rrAB!oJ75rx;R^OYg5eZCY&sv1GTN%(J#-++{Ph37b!@46jgv5?!v2 zk3)pCiBAQxYEjS7(BIqyQ|5bwOxviEyZ#>H*ZG8cx9PyI8z+nTmNCWwtY&@M8{Hx^ z+s)n3I6Oohk8@7&?<#-71UvY5gP41^Hl-DNdQZh0zA;@RE%kiQjP~l;sSFeI|9ow- z2Xa216YYVIbzD~zyC1R5rYha^{>?Lj$!ikB;z~qAc@hWuC4xfKup}ZFhWbxr5%s{o z@HRUm2N(UAOy^JMMcpzEp)Qt&mjwL4TAm8+3=sZs979IAQ-I=w4+kIS8YBvo4H9MF zLq-c9^ihcnp(!3mOL7ONJ~E7y1;@q!{t6go(m=t|eHg&9Lm6R=o(sp~mPd9e5+f?S z1-D_}nr{scX1f}QrRy_dd>9ktJ(`LG(Cxy3W-tq_6$eNU5t76y{z_|R`fjspM1zZy zEN&XlYKyOrIV?1eL=T>r;k-c_Gbj11qr_IA<4-QBI02e7PgjL6N_Trdp%Pn9=?Pwf z&wwoMchH#HRV~O=!#Oc8I>l0ePx%cM229tLIJI2=2rhdZ)I3)>lQIA3DpIpwP%~U; zZAz-7$3ohZ04=G1Xq;O zxk52uM+M761zW~PSk=LKN#A%0Mw?LhC5#Wo}uq|B;d!pj)L;B)S|AdR$MCS*1WByu!c9UMI6+MM29K zHyMjwohW-|igyl|{!^&wo$L}X2~*3nwiU|2hXKiuPJ5;G?@yNAw!(9L^C&f2`H^AB zpH8Ra%(bwefpLhseq`MQS-oS#2ZUV7_M4y*gf_}ZhNMDG!h-*fp%@7)x!`kC0=`-M>dKf$eE`jKPngQ;Y8LI2$Y z^q;pl|91}C5b&mkv?lPD)V7Z9Up>8j{oJ5K1F=J(BQawW|FnSgbj>$5F9k2In60h* zZ*KYS>}KvCcpe?QpPt!FU3y>Nc;4OXUl70i)#V63-zC2skfHyH&0Io}kuW9s!GcKi z5AqqQFbFo^ViPn3kPIYdm|N-=nl)pLbYG%2-2F~uBATwQrTO;GNJfXv>1<Z3Ha`oGL0F4t)*p?pb&>T&rWujw-kYgki=qKAs7~ zI+g78X#|7d-v1;1F06+ePW#Cp z$6<4jkC$v~Dv(`pfmUH%83CQ$u#;7vj+*WO(@M0_;GmRXsP$a6<2E$84=?Ud5;FC>Qp3S!lte^mfk5NJY<4YDqR%kT<35z<*%d`PnrixT32BbTQBdoDI zY#1}c$u7~U=vY9cZaB11*b_pcp&woSSV$C7pZj(g(tLSfjP}lne=K0)1ux#6Si(3c zv_9y7Kq?h_DC`(SmlF$d8 zj8bt^#QGvKr>ENkYxh=*TymcgBQxcIWp!inkmcKBkO0`qxCl{7u`9%A*i zh*1-1K&~%Ov&O8>0qgkRq_8%O3zh-Zr9H-c!>t8kQ8u~LxOjlNUUxc(cI^SBq)zF2 zzLNIpZfRSLJ4CIhUx``?*ToN=19iPimi|}lVJ4Aw{W$m=lYMYmbfxv6$AAVj;2P}I za3^bYz~B}IJnaaf9!MiAK2m~J)rMhGBQo8BXU!z(zK6&ZRTvsg_kiR@;K)a)Oo_1_jyJC26DSz~wV)>mO6-{s?g^9Pt7HtC#r% zd5fg=0!T9yJ2DQ^&PEV!5IoY!&+1;vvu=FP7WZy3UP#~McUcL(jP~5vhTKhK%lZoU zfRGkNPcY5~vGGR%y)iAvPytsQ$T{MS^ELuRRBlJTLIKg|6G}s!a82(|o?p?)#OJA|LYjTaf7LLYyDy6Xm~)oPYf?iVOjZ6tHEV zf6IMG3*u`Bh7r62u`fmgXFH2T_@V!aO+E0Lf(%2#zYD2UJ^)`|kI96e1(|~~*gRd2 z!-2l}qdP1FKQ%B+{f30bUxFFcHYgmE82U3eP^1_;-h{!L6e5|s84VUCa<6C%186cr zL>6ikCEeYJDH#yW9N8C*ij2TNp&^Q!&jPTthQdoR4dN0ejy13<0_QXmhm3YW_t-BY z6uJ>t1iyVlWji`5f&)UD84nu-guXMLpuB|_JEeD0}l8$$D>eER`!fDym{MEap)bl$-O=%3H0$ z4;(B~odRoodZrNs%GRhej%iv|s5zm=nJ%|@ZYFzEG96peoJ+u9o{*`v^fhlf z;CutC^zb`Ev8nglRj?WG1pN#IH#G<#E&)p}ob)J7Fx1Ktmf8E5?c^^w}zpXv@yiC{m zKI3iv+gka5Ik}RQoRXTB{;%3z!v6ytwNNzz$kckxMBo(M@7aH7)&DP!`meR} zpUD-D`BR7U3%jf9f8waCibz4{p9q^2$5d+;|n zATVqfYTNhx(M%5sWNk;z_mcex&JR^ZT--HR5IZ2)Nns@-1X*7rj1R_j_9r2iZh9^O zF(LF|xO?)-ZUj*-1}PN%*6tn{;TB6@EFw2s5vg`cnh_x%;w%~KcS=-pM+Eo?@dR-| zJUOYf)F1L_PeBj(MA~ntv&O=P<6)`O_7(Hwdaf`+>2DCiN9?9*iANde^&QdFcCUAehP6_!m?iVkY_bDPbCPLS1sPfPm7xNawTa- z+*?+ETgtP>gloXN?YtchkQVtS^g36uzUsFxD>Dup(S}qj3_}-aTepIa=n%qWAqxin zOx5J5Y_JUcxJ)`f{DgFQHT>kgW;N)@QlIrsK})Dt%(QSjzD)1J7ZqF6v1>Kl?2mio z=3HL7AokxZKV+@vNa2j;=E?P^?}HFgQ=JjC+Rmnz^cIkxe(f+P;VlznPsgs+G$JUh zVp|KqZyZe6Aa7!=T(V2}I*qhJ1pEkcL$>|n)czw#U7?*Lif;48%0G%AYZ2%z+7q+| zW>F3}u5#JDKfv~=#W=;vAOt(vE=L4AH;SqSzu0WQ3cBpusZF~m`12ler9<`ja#WsF z^g1#e=fpoY?zB&GW6IS#ecvrE^v<;S9y|OvWX$!kk?!{Mb1HSF?{jnC?B;W8w@8h0 z?Fy{H_k(ikTJw!(Q2sl3=eoQq@Nhkk=H^coNav1sH%R^$BDH`Gbv*}yir7=_@%Q?2 z3B#3ieeiSRz8T$F^VM1XcR2+i=m+qi7P5SFf$_0;{?g&`0HvrCV0|>|R zK^PsRkcW2?Xb9?|%3-8%di%t4Iqo3?Vh0GRos)+dvV8u1WUv*Iidx{0a#-e z-;m-ylFhU+82ZLAzUrcg4Qfd^om-ofp*fru^FZk*Mu<2WLo|D9nm|Q=0D3+4JPb{&EU(n%PZ3yNd_htFJP;#@9wM zLw$eo57Az(%u+%tW?U4|xtkwss)ESnY+WaCegNWJ;&#&SLAyYOa9_bfFbXlzg$%H0 zM)n|xLvulK9z}iQYq-A;{*!Q~ENwA+5y#Y`P=da6imQAnoQ|-p0W43pmO&YjE`>dz zD};8dbUA?dOkVGF%=4&_SE?pZ@vsFUsumh2&Rc@d$Y2SJo2;sFm6pEqEU=EX1w_k* zmT}Be6~uTh8GuHEHYFtq=xfn-)CK5*(L{F5+tu|fg6e}s1@)tHLWK&@BcN7k;4rr~ zu<0jgkieB?%cV9xDHUt6ObWf|rZ#0@P?;<0m(7*x$CfU|5-L||2{t}84;ffl(UI;Kr-9O3gmcg)7rI+saro@qUIu1wdu zwoPtcc|LbZN&JVju%Z1gPr(1Jkk&D;sko)Ju>D_)sAktd{Lpah=)bZESQB%>3yXov ze@s@_d^a||w|DaQ_T3MUTu)Aw&o7!&ul=w720fpNA0CySL0@m*2Oi$rX!84mpwVcP z3++fULJ@}rqp89DMI)W*0e#%!K(bL5G%EOD@af);n+lTfq--PWrEWYe6S zcD3UbO_Nhd|5!xV0{*dxa{XOINhp6(n~hXlp|{ZbzV zVPZ-mu*D7##-Ae|V_83HGsJViHeeKTzjF?h#VXHRlmXmRE6Pa1EHh3>7DO{cOW=?t zEgaKx=PW{eZ6i0zOuQ>CNO=;@LMjSa6VHk~>UmGe>M&u$tMeBt!{X?(aU*IQ2s;An z;z6w9>S>X)##n$OBL%eOO=1Jpjx(IM)s0aybjB?*I_s6qSsYcNZF7!=myz|cLRbE~ zN?BJb*OC60ab(rV1N_LGoLOS~|A<$VArHBWljsrGw?h^rXYm>GZ74J>^sWL(J{b=FF^Q-eIF-2mE)x zsr2ZhWc#3jQ-*$fLKueVbp@E(HqUmq)j#VIK3DgGqjQz zh-Rp)s6N}ghE5pJnyJFq)C%cjM$7I%GP%hKVfXx}4aI}*#)VA;N|AdCief8h+Jf$Y z8!3L_*X#k1Po>sv6WRkxbSJ(f1LB0p;|u&0Kcffytf1E#;=Cm4C&Wce+d1zd-gZvo zrKU&;-$=L7uGdD(AG49`3*26WTS$`Y!2334A|01``CgsJWv~DqDE4bnN9pyZ&tC|e zU})dA{Pa?N1=_ted%y?jn0N%Q>hgp?h+6D`GlDyIpYP~5+YcbrsCYtkIN-r~pbc2~ zOEsYZJq|mth%bmRonpSzLHY9R?g+4%;Xx)~1(^KQFsPMw-f3vN^G{_6Xr7@V1S%v~ z=6eJ4eaykw!C0`zX@hNJ$Y21G@Sq#ip}klCaJUN+zA>kEn6G*>`42%frgUM79{ot) z22yKadYGuZ$Svi`Nuhm@#1F=+8VC-Nq3fZ)mY0%SWGnuCXq7v$A43UF6!~O0Rjs3F z^>Y9i8Hk53jR3(bxhNiDV-UL+I7pmEKxD8WO3SW<*ppQ3hO{9sZO0&y$emEf`Mxkc zH*Qq%aS}?o5xvAJNK7_rk}gV#u*Nuude0q1C3_nEW@)zk8A^ickdT}=PL7UYAje?v zA?arOFjAX2#Bc^mZmJZcM=AndRZ|8`OH8tDotakAV*Ap z!V{gszYiwBZ2&FnOh$`hc2C&LbiwvrM)`Xc%(NdVV?GmJc|5l9l(e~FwxGMIC-FRR z)`{5J89b*Pl5V0j%223qx}aPL?LZMm&>4~#qmOG3h6~_)RLm-IDs`I?8#b>D${Z6Q zLo=jgY0jP}CvnQ!0TY`SDO3*eVXFAI#}uDfH9+bzRB?Pq?ixk4QU>De7@Akb$#Mx( znc#;ih2(;5`XwASFQj+|IzL;n3!7C)*sWt{a2qaDtpm3n_C+PC3L&c$7Xg@F(Z2c) zN@%SDwsiq)RyQ9qT%D+;B^n`}W|&%QEmqKlGJDDY!`)l9)fHyhqMOae-Q8{D?gS5R zAqfyHcyM0O^dHT28OX~E!&hx~43$}GZU4ey_+4Kr_TwR-?h=PGe{N@=~Q#%&A z&7hCkj&MO%^TZnn``l1qID;zv{2L~RU4!Uj%lp<1q)O*O*|n?x%_7Q7hW;<|sQ#xd z^gp(W|25_PKSi5%b^nK~sJ|Kfr~nIdb_;+d+wZG-px>?Hpx>?HPV2|!r)Q=Ymzqa6 zCU^H=9-n?2{N7)tvM}q!dZWYRYx=PG^!VEWrTkze^Z+5B8T7)wS-<4QM-Uf#AxiI& z!Gu#fC9Qa|8Ain8tGC!g*crv9a3yYxE$LG#QVD(~hoh@2`j#tYi2AXLy*M-DEgSw@A?*DU$(`izQEDoZI|q4G>fEh{HyHm$m;>z({# zaJXfWl>wbW*AZCUYQmdUWayCdWJxU8MYC6&72Fe{#L!gi6n8Q^R4Ya2$a%I&;lxW#ZV<#_S~M8FOBFm6gN8Z06WFlodGCY(=swuc(NNQcevy)`#vO!Jm!d6d1>QKU+ zLyj>K9GGCMa!8p)h-?az`;{vOoNb=ayq_MdnF5m^W3+XcldLYBMUe~r$uu?FGUh0u zRN4B7va$oBBqw|JXrR12tJ$oq+AunFm+0y%7u0BkrVp$46tZgS#9`GRQC!ChavX5?snM>a=Rn4AwMbz)Id||yR*U3 zBDAr6T%*gbW}D8@uo2+wbgSj>BVuJ|c|&k%*I;AB%E3zAIVLhKLsDQnGcWMQIzoh? z*M8tbdb0>;|6`xY%tzzjLa!%e8T;a}h(j z{_fdX<+OpbBi95QK!Pl~72?*_1d?>yaO8-TM0J6AZF3{Kmgb*~;$@fq{HuF^)NhTq z--C&ThoPWwt#V=Nc6{Kda>}ytq-XIL+FAF3w*Pr4K*;|BcsW75F^I}6Vi=f{k$g$Z z(&>AU4<_-x;Zq_R;hOI}<2zWe&%8KnvPSvYu(Pfw2(j$+cmS72LDa!>`u(v3?h>We z^JlwYWLCqA84m;@c~v?Nj(I%gqFovDv@ z{Ae(#_i?ZjdLA-fFqY7Row8XhaC9IfgqgvXM>0iN*0>48PSr3R4Et--VMJ7vX>(Y`$f@C zsq>3vEeJn^yMFk}=RhZ0Mh9C{GB=b~SBe_7uha=YUz2iMW-MQ-zA!T1&~jUD9bT%r zFSF3Hd|Tl>UaEaRqFVWP7V=-|T8j10*V6d1+O+zHl)o*1f8MD|h~dG=VTjR)@yS2+ z;CouNL$|Y5b*S$URD^`^6cr7^t z&BA>db(A9TE>}mgBD5@KUCsT}VL^~!7~1ZOW3J`RW8>XVhd)|Y ziffJB{f3r4>I8yaVLXy?`{E>t9co7PovhMoT)oP-2rPRCBA>ecrK+!s2|?d4qE|&t z1|7-Vd8SteoNgGk`AcB{Q@OI4g7eLJyF=apRhIVFo1-GI?tQv}8^rlRw<510F^t4j z!m`;HlC|My`74K+K-%_nE&?mq=8T|lZR?pKy2)j zLv8O{_c)viKxFGmx78CZBy&QJ+NW~Ep5D()0J%zKdN5V(kq1!w9HfWzNK5Ai3GfN$ zIVc?MK!&30(H0c|zntZgtri5Yyqe96>V-NJtkdQQ+gEDgad8|j`>$g!qF{31Kt zTQ1)A4FR)L?-H-X@ML5F2`SC8vGXSQ0+T3~Fl-o!KmHt+_`0X24<}fza-^NIq-%^x zKg@18>dbwAxU7RgbgcP66ELZf*JjBo!+r`g-6j6Ue$+(?=_X$kMfiq5y^`=|T6M-9 zWTA_qU%#M+<9#a+Yay0TYwaB%T6CIY#u$PnzE5lH8w0zb0ma0EF+kTr-0PwH$TXBH5G znZ!Z}the61R24xm!uyBfUFaE=9YC_G2>S;C^s%FPfE>i4;aUc{KXlX*z{Rp+mLCF% zO8q7ITn!_E2NbZ~--Ow<0TC(SJVHfL2~%)P2$Qe@#g#s#n5b|Jj%gkoOfgV4MKrbn za(ByhLmEcM7Ohag8?QNfM7*vBRLU?!zYZRu>YHY%?ZO!lvDy? z*n3k_)A-uRX_p|xv=vifW;720rq2;({ivaAbPAL$?I2gn_PF1pDp;^lN@`txMjUa0 zP?4FzKH$jV)9q3~Xu3|B45AUlW0}O6y$-8!|3VMzAE0}7ogr(lAe65&g@v7!>_&Qk zhtIb^5(xhR3$+~LEpuUb*tAYA#*aQV4 zK+;26p>sv}z9|#>Ua;7oQeOSmgTY_{j;H~jhA)8#+31vSX~OlcHVdizwHtMLI_0je zNWR=ub#!^Y<*vReyxjbY?Dys6yN0Ima-zTQX#dg*oWImhFuht=qF=2mQGd5 z8XgH48~+o+GSM>UHM#hjz!(Fu@hZWA*z(xf(_KAuI6kpEJ5Rm5vbwpoxPK6QdN%p_ zYXX3%W6)4N?)ImjBmcFR9oH_ zfzc}2wxZ_PdpN$`xEEQEg=WR~2yqdO_{g-**^a<|*jW0p5ZB}UPJO-H38sovfcDy; z;+!$_C$_8K_EI9|T}PPfmEqTw$x0!?uj?=EuL5ZgAJia8FW|_2u(uQGqNWZK%R`_a z40#j4FH@-~&=;oyCM3Ycx(E<}&=45x+a5KP6r7Tk6dID?br2W|>QW01TWT`i{%Ul1 zKo-e8)kG2XCWmK-bd#t#C`yPr#vr!sAt=+9K`+aILQWyrARb5aQ7R!opm>)`2b;Wr z#!%2}8{>;ljFGHn$+tZkD+$~$_;vxxG?dy6U_&YoqndpR?}=@4qI0ZexbUF0C91e0 z7CyMBK2z_Ud@p?1;=&|&*ph;xCz#S`;wRJm)}|1cvV@T% zn2IuP>HzqA3?T_7Cu3#@D66_Flz zt1jzaRQp_JrC||@>Xt3e!tw!lIf1^ed=*0IPo%NRSE!VsWn;r#4TCiqxo;3JftN!9 z*8t9KH#=BN*B|dEai0-x-1*tNswTyVh&Z}sFpw@s8+a{{XWx>(fuGZ7)Iyw(D-H`= zc=Yl>SdfisM<0CKsKeE5#w|zaKN)=6Fpt^yb8h7|hlg9$8-H_`wXrItJ19%V;RpEUAPU?{Jk;_u>ISM?v z_dBNOvK;s2Ll9|&ZNQm+hHh27c|MF9<#31YP8DCdB-WW2zDi-={6RgHo8EuJOO@FG zvus7;dil5{*B!Mg+2s!2QWO?^AWK7$c|tEEQHMKIHGYGAF+=E4c2AMU4|{7i^(!t) z2nsZX4D-SJSTjbLj{_A7fnf~Nfvt;C+*%MLObnWAs3ZJawtMg52Ar^37?97~uaiX= zL#YV?tD(Yo?b+*x9@qzO8WqGvs0!6eDrCfB9cT>P!gd{sBDu3t6P*R3rRs}o1XV$2 z9lpgdyA;P4XT^D+_ZBPRi}hQe!R31e8!{|4T(-Jk8+ZebPq;4&0UX+l!G>K?1aGVR zafZ+W^nEGt&UiWrGQ1)^Uk!thygnl6F`$65Tq*S8!8+EfpujRf7^X{%G}p9Sf}a6p zbRwS2NM2~_tOgA;-Z1;wSRA*QAy{>IM5W~_zA7xA;fwUB`tnsm(^x)})9|SF(^X;@ zVgXB_^q8Iu)!(|9{|%t}zjQIDLktc03_*-|k4^l^%W?%R&Mz!2J1>G(|A;zhr}k_P z4y}$)&Mz+ih&t{c9-p574Y{Iw!a{gjBbbL{ zN^-gAA7kot<|tKRjNa66>ZnqFKJ_ zsf7RG7^aZ!=n`@;ulzXZ?bjN$FeF^~%zg@qqdlO=jC$^E8 zBB4Rg;TDopK@BgIms$(ktKG;MV(nqKoXfZs3Lhcq4)Uk46ZW1?sTcBJFCh;LuwDn@ z!aCk$gh5%b@Jx#$zQ~pUT|YuFSO){gQIE{Y#9(MRV7zWKn+79?l^jf!VY5X;n^LU@ zW>l6E31gEH)(^*6;pq=8I{-sPmOkJ@MU}%!qXq8ZCWE3Y!7gYqdn-^-v2{|9p!iy~ zLr_A!u?ukob9;Puq7L!~m78IN@E*!k`RgwJrY@NJjrA32q20YToLKtB!6Pv9{NWIo zHShy#3*eKX6rIq9%eR!R!azsO8DR>&8%4<05}Fgj<6H1C z=Lw8oW^`DRA2l-nrC7D-D5QenVkD%J4&WA2#f0`frkbd{mOT4qSh?XOjfXb0G-b** z4yy)9i@&@W*;s?V5$nUUZb9rX@`~V{63MYs7#ts&X@0 z2FjhyL4KHLzvXdJ2g#9Tl|u6IOZQs9N#L{s#$Lejoy$4)h2>3(&*236r8{0H`V|no zKD{F?Cgfh<&NJzMQKHrfbysX$33XrO{PpMl7WxC~VVm7R#R1bO%`M)ok4Ga$brT1)7A7XmSc^YEYX@2qh%Ieym^uIq6HQMDvqvI2U zzev>VKo56151^;dKYjsU(M$=Y%SR2Fye`N370pm7luf|j;QB-4nDkbLs$X&?aqxxE zU*l9@hhxC+OEg_@BU2G`2NTA72h~}|4&U<*R}8SFMGt+ z(NB)BtCe3XQMI2R5Oxp6ahP1Z?m3U&=VxMkopa~9)mRP86j<`)e0ii@SaaKFy!h;m zLKsBq3>o4C;hjRu1L2n_4TkVf{{;KitIPNS6xiu}01E03Qp*b7&ko88k&h}u2$gF} zLI{%`YT5|r+2c`mv@Wo6BX4G94;%>xngGF5*fK zDE0@}VU{79^F@}GPPcfKUu_)G>6M~)mkPFsrhu9Hf1%RSOb$O)nHNk+d>_%whG#X0 z9)}k#_f^zvHLU6|HzUSe^Mqq!oHTMSi#e3QRcj#l&>B{$H&lw)uDeKJ(QJI>R?s;u z2w;|gRQ+JhhYD=d>WSMMVkwXkM5Jp(0jH(*wbqRm#(y()PZ-ouD_d{z3L1kS`kWL- z`lT(W4Sf_zmG`m@S zgQ~^toZ6T2+j&i=)7u4|K*qa8gG7tFCF8>KyJhpnQ!dnh6=UW9e**Bg3^fGw9Sve_ zN&h=&b$vs3YX@TQ_~i7g`QZG^<(1*h?SDV9pi=y{cl=o{UniE=e|#{KR4jy0x+YH= z`(9y0su&%5G=W8bPtEZrt#c_uE85tfac(X%G2KfjOMH z;aT^O*;QkF7=0>fTC(n^cz1n^HIx%MSlN!JK@FB~y23|wnO2bDTV$t>pa=BbIsMRA+}{bG36H8IUa@dZB;J>oPMJP8 ztV!u6s{PQLip%mm5uUh4O$vT9Hn8b|1qI|_JNwQjw19gf-iAg?`c>}Ljnn}(D9&0Qm%;mRGY0O_l)#kLHJ(S!`Y-5k<4n_`byiY|Gw-SXHLT zC89&FNaZ4nrbrdS2d2nn`L;*MRi*IXk*irAmNhe8mRLj6YahJ=PYNQRj2QT*OO{0~ zN7Q32Lb_EDL>i~%WP9DFwDr#r52oQJTG;9c_SxFV_e?8|r`;+)JwJ67bl@~7F(bT) zLNX(*?0p~WW~Y=ZU`Gse%kMcHF8$(&{StiXs(rLz<3>`5!xkRIMS5OC^+Mwn&bI4V z!+cZK7BH6EmsUf}5vo_)w7as zs~R3U`$-AOAyg+Y9Dc#kSPOp1AxR#7*}h2Ydd?p#5BFVUJq>=0!eU$MRt_h^FFUD~$W>VLM8a>2W7c)$(x{Ch1GX+XvGQ?XMFPcSt3v|ERg;CYrM16Gi{gl; z>s0b#sNa8EJ}JcUy7`+973mh&U{G9K(0uSteamHmKr9i@77oK42@wC@u(D_>#))ze&MlO zgE(6Zl0?ZBUEJqy*A#p(tAkT#|-H)(_F15fC+)JG59%twRZS zV|ej0VZ*F(A!CSwCcsi%7`C1~Y#yBS#w@~@}c_&qRZgJnz^tbC2WXLgF z0sk2r2!3P3UYgU{<9=2k)6+p-qUFVvlUwu%8If|xG#i4NDJdqtL7Z7EL-jX`d1(vAbsO1&`%v7K?mN+k->PtB)poS8{ zvmDF)8Z61W>bLBez%`DQv*{`b%%8d3DsO+fky&B)HldomGY@6O9;_oJp%xISp&kvT z?VJ-pxHjm<68Masj(1ZGC=!XHivwUvfB}w~n)X`-4pWDD{ zn^NgK1O%}e2W14NMGg6dTxKVQhpu$1!GuOm!N!HPEjs%|aBjU`KP<91fl-UF&71bz zcrN5IytI%0!RtJaWac|kOHgr}YKMU617qHVNEVl5(pZ~d+5vzulh+<#A_;FG#k624 zELEqg*eiW(%B3J}^5Bs=(;|clCd0@XiB7D3PiJn0O^0LOee^~LC|D3cxwK_eFqKgk00h}-7DVfQgo!@p z59Z8#xUE^$r9b&*F44)v*lW~?AQ5-lIblukA6as>C& z5Yp+tM}5$pyL5;DMk--b2PJad!x685;m=Vkv#nf*<-C?QIRDY!em{Rm_JxCnk5*g!{=~9Wu_FFAd>5V}T1f4QR4&7`xXC z1dw$da$+QfU1$@W{F>(;xh%sn)uo6Zi1WVaJ}p+|Mf4vTzo&cLQyFJ^%5R`w!#n;M z_0}z{8YO7soc2n=|GaTw%QbJ5d-=zfBkJdbo6qkuQ0Y*nhfyaQ{nc zOa7;@^_P-^*A=Mrbp-3^$EqG>mu1`Th9xk) zX3G=hOV%w_s$#lMJWh`ZB)OvPV=PTq!*i@S;!3qdF)Q`;<~lmLpQimqxyJ_gU5 zOSG~*hA=V+(i>DJ$4kENTW+9U>!BiZIty%Z6xkR*eyxG5&M)Hwlm%XZyO9vL-x0#I zLJqj&@Mr^g*?foL=`>Wln!SuV(uFjTJsfMHr_EV|x%`%Ajzr7(+o>_1XHEp`#a8!X z31-jUw9Bi)GOYkFw=g3pzD~LD2JTHLiv7H8MYPwN8`hkR_ZYj=T5Wbe$MPI?*50j8 zi=60af4;xio_W30di~7LPhUjw61t83`LZ#^o#(+ga_WhLkw_K|Jq8cu^J<$m?<5&i_!>aV z4A@gco3zyJL0L@W?t`qTsg0l<8rTa#F3OHHP#zVvUqIfjcQolMs2m5up(%^T$+SeK zTZu&PWTJdyRF=H+A$3iuI3w}Bu@cVw)ccAQ6I?%I6)Dpmltf|cn7Y?CsM16FN7x?& zn?vf%q26>V`Z=Olz3Xnoc;UMN8k+PuyLZL9|n2F|d7iB$#a+ z^pmZ?-l~}{ORIWivyF}i=+4^=&v+Qc?>bsFJC>#qPI#<&9IYr0mC33)nlT0XyMJa3 zVf9SBS*Z#}e>S`9?*WJPcZC@f9`@m762J`NCYswyP`-z~3Z`w{yc|NcyJ90`Y-GJA z;LI$$o)EY{xtGe@{G5J2__f`A14`>`+o zxL4Z#H~Y%^^1+v*W5d(4-|Wj6;Qm(k9`LC1{HORI+{-7ill7Od;dA(PPD&+hrgF~YGd=x~B0W+RLx3LMzu`7(s5KLS_#McLZ z!;y##0F>N7&lGTGh^EWbn{pRpT|)I8QJU~n;MS|BZ#tX=)fkCoQNdsbc{Q4i*Z;g! z5ni#i^O$W<#TIRC*L%)+K;V9L2>G4j&&S*^c4W9mb8y``tNRW~Qsb1mpI&V-rv%Sw zc_m99=;mU@Y1^u+9YK_$jAjtAa#_GOSn&^)KSP}Jb`n5Evb(>#rHW))JHV}ba-e%1S(w<*DP#vS31^-Er>p1GTumg3ouCKeKK(AqRZ5+Q z_RBNew@lNQQ*<3v$Q~6PW|*TW9p7Z(pk7~uU*wxem_1G;PB7wx}fE?R1Ll$y7 zD$j>`ORSXmEhw58J6%}T6m|+&&IG${7~X&(;YdL)fI$=jV)J-}?56=hOdiW4gaM=A zb{>q9snkxq8Xf1ZtVYW$)w}XXT%#a;Ba^*kV^d|r6vVRO0-z6#7@ncDqdFW` zI{jsEOyh=#!GYp zH$-hbA3a1}vJAah)#%a@P6MU-s7MVky}$yq8JnV_Q7cY%tog`4n~5i;!Sq|}dY|ku z@->~y3B}zJ{IuT97WzVyiWmP#*FlJG6&SYBY@laSq%Ey)lheT*XO14bwN_NDfg(@4IdlOcblQ6f9&f94poR zR-;zoH$9@(K$mZ#)-}^Oxb^u`$(=Xd5Cw-eg-~*uC?X@Vnm@+QSUm1>O?*^{-+OQ4 z8MiO*T@iPX^w)jm>8Pyn?CH2_km>oPZo%^Tv}wQM`K;~!?D@PaFzMgd7f}HEP2__9 zPUOk}7Ux|T0n08cug>sScRv6BfXGFaYzj?!g%S#E=08L(ArA!}fhPlc%%&9iA0n4+ zVK_lZyXS<=?oZy_E0N0%U7IQF`&)DK>WdH`ofY@1D}L47#KwGb1((c~s`=85&)1^N zRWNt>Sdcj~gwzP0 zJ}2ASMXnK zLB`{CC4WxIr%u%c#>PMy!*hIra)7q~Vq;NL{{@Q;i4-jGRT=Fd>l~A>KO1rfja@qGS=Nh%Un~za*@fp-M)$Fv~Kj zG`pJI*DS4Ps>P?gvmo~XBicx!xca5sG`h@lG{vqAW0DW`w6sbz6x@KrGQtSGc63va zkPCD;mD}#AI#k^6iK|EifaWS>&RdjDBN*mn6N;YT_`^EtuiSFjtLFe0pfc8@N;0S! z>nac&y~a@mmJ!z}EQ%y*bwj-JkC7f&x0S5E@CmvrWCD#=i%^>5C|k&DPyQ+(j-6TQ z7~V>lo$anD&h-R;j5^yC{(W25S-dIx8}!M+|*(38GF(6SwZkXePI!|3sYW{pdlz zFdEga^6mB-8ldnb?m_24_99sH*CXIsgJ zZ%xb`Ni`&MO2Qpwr;|eazT=5eiM~rzRvJHjd$qtpkO(ozzA$Zl&=5l)lnP`&w79p@ zH&pe|$QLfPYGiPd38KVJ7uF640f-BJmFRnsK>Ji^m_X}Zi0&yIF-%c36X!l{N>*6e z9SICORz3*V^FVmm9JZs9CSl4ZrO<&5a{H8vx08qPZx880v8*oMv>37=eUR4onK$<3 zsyGcd4x-qZU3|;7HyKXm=QnXx3%v_b6Oe~X2|_TDs^7ds46%>L$3Gkr-V%3-Y=fa@ zbcvNGXT#FT%_V_r3RSv`MwCtSryb;xWCmdU@(=Wmb1@@&UU6-#j9>xjqtlLvLKbl1sqfC6}+#_x~Wd44a(uSXgvh{;mu9Ex82!mRu&T z9@-zD*q)tBTwYn;+?wA%9JM^3{`|E8fe0&3(#-~q5+Pj_h29(RnOOAXuae6KQJCzP zoB>Kg66YVzlzG0zV2xkS!=wdc#2h$_ZNs&NlbIHdKqPYegUB3-SURnd z8`$Xr?hMg#GKb&rUmH+VQV+FILEqtX8f8}&Rb%9xb?ahv+U8C9J;04zC1u6dev_+2 zcIcF{!}o^_kU^?StX&h4p1jQG61hK^FgGd<@`|lb4t!kgj#-N_?!xm7SY5oP{`N+y zR;eB6Ksv82FJyxRduO_&VEj^@j(^XZ(#HRM1--(Zypa@wGU)q*4PZ-_N)dg=fOFFf zEb7$yRl4BNwiI6IkEZqG0e81K^J|zE|J&<`x_qZe|6exk*P9qMov2@*wO^h-7827u zBB{ZBHNHXk0orZ-UxO0R8mPXuu4Y%IQQgRNoi@Q`iOYN>F(V)t?G) zYkEmD!&ryd;>Kz~Or3}#V>MF@!T=tOcbEKJ+k{>d_@gs+6JjRG#lJzu@9OIzvX1m4U18&kzAz7DK&t-H8XHao8+4RpN7wd?&*&J=${CekBVOtk z;LlyjP5{uT_cHf6acnB}seFfemz8C5N929!}0>DH^mOhe~ReC;w znwh({u5zQkvZ60_@*q5m1$h2|=_ChD;r^^8UWb?RgS9HbtWnraxa5uG z)o+bTq9bm)2(Z|OeLuvIdgQ56@7E7Yxn9L)A?AZ6rAL%guHuU1^6CDUlFNTh$1*V> zCo2yn2asQkP+0Pp7?9Neg%j-WqNJ&BRG`^uzgf_{@8a@*6eay}f}Qkv8t5+V*W3 zA+_$GaJEFQc3`Y5UI>_Jk?{GCXI?Q3e|6GZ6G%N@9deU()(&#L{y1%Cw$SAfd3|AT zit?7^P{2{>X!O{|3M}aM_6BX~>u1`R?4K{G4~ei|p@cgb?mxp4A$;_4hvxKuV2Ngt zBda%Rf2n3kLe(A|&)LMr;=9l#r7%L%gQUW@Cvl-Ku_1?~^~u%@lW&97_8YAaf(Vye zbWW#aKLQ6t;;5igMp&W_>-&nTS5czLa7pLH;lIO^2uvd6&2&`E$ToDuUOO00bh96Z zPIgUdhE8#L?QlrdflY!>`#kgsK3#jUSjNTK(oi?k=E5W&!?lGR9OEL$QxqMl065@) z|78mnj(%c0jE@J}6=SQJE+05%K1~(pWov(=L&=4{Ea(C8XuuU}vcAav){MD`;#)v}`}RssTYK0V=He=Zk~XmP{eTz}g~6yIst5h}@d|UqjAT?h zQzn~s?(vMnc^g()B5lX5YFy@C)|zZ}JC%ApN&jhq(Ofj3x{Q!V@g6b2u zATz)k0PI78_;&9PNsa8J`u;N{Ax}iTII25KRu&J#fdCwvuFvD za9VLaie(oNPy8APZ!Se)`l6tSPsEU%Zh07Yreq<*;(l22K%l0;b4%ENLUrR2-#R1> zz7y30WOfUYVJiW};{ceWm5pAE$Y#OFLrW;!8~yqpF4gqXbWui(!`K5@jr3;$1os2+ z91#}|xEFy$mj{JVC()5i4-}-INryy;ks?e9<;Yx&htL>eAU^dCQ{bRVhcxBId~Qae z=1gdiS7#H*7|ZJu9UexAx{7V*+ch|Q2o5irhOznZjxPNnK&@ai-lRMKll{`rZ#8_< z5gChg*JvRoJ7pq40c=dM94bp~@>Ey>N1^n%srq%w;#dJ!vie|Vj<6<^gkx^ z=H$QUBK{kU-v32H|BoZC+kYXEX_q&wwze&H_w-&#WQ$i4+5G%+Y39b{;NI{ri4+=_ z2#bcK-HgyE9Z7{32)zMXuWly_8@+@O>`I+6T>aOWC)(E|E*$MN@^Fm&>k&7{)-c|W zDX}Xo*?{_wgnmrd?n_jL;8y_B>*eKLE?FS4Vf5^pGNF7Wl*J<^U2BP0k)8vFLuq)0 zwux7LUR{WasbO)Ne**T-oTo*5|68_14J`_%>fJXr+{YT^W-fd`r&Xmk@B^(d_xN#T zx9}p(7%G-<)9Q!q>A$v?Eg|fEPRmb`emJ`ZhZVfSppvTt(`-d=ly)K?rujEBqh4R7 z@6q+&ZR{lvRuAq!L-nP??i01fU9KX=2z}BPY02D2E)&aE5aA~|L2BdQ6clMAzWA2f zO4ixkma>nsDyds3B8dNBb*lK82(Q^y{N+KUaNYd}(ZbqS?>Gz+AN#4qZZALHdQ!`; zJV6kC8PZ84zK&|n5CLcwQeKRHR>0ZxYvnTmcKg(FmYqznCT)`*rBhDgq{~U*+D0wD)#3Y&> z6XZNn);bk;K`9w@DL8j#M)LZ(*GK6+RM)vWwSw{JFXpO#x zEgxaa=5&1UY2^{$ye0RKv}fP8w!Y^IteZ2v$|4P&I4g!{K7)>!Bp8nsrKwD6>2 zG^EG8R)U`bqe51w5|cyb3QFgu?=1^wQw>wr5Z2Z`{ z%2|W-%loE$IL>aj7e`{$w_bWweqC<)@~>6x(V0cKAVlSwJOFJPk(LfSaFboVdF}yC zX=Ml(Pb>B8@y|?=tAhQ2F1s22`E{U>*G0fHlm8_Wts>MlyzqMDbteo-`|S({3Lnz6 zEVG<;F8`aA?9I>@z(YoAX0EY%ywIBI8bG$6YgZI=3Sm$Nti*wQ0@IK`CqJI>dzSlkInpM-Hc(m`bW5>IF}# z2WhbA0~b-EjS{wn-lzHiMXvxCdg2y}nR(Ys=FBRqkmvVnMe;2P=_R6B7%5(OQzVB1 zc|>e08PV{?z&9TMaKoEuBC2=D!e`$i`3&BY?KXLF0kb1H;PbG;V1|i^Y7pZHcT6Zh z`O8r&<3up1g8MmTtW1>M;{~MX;K+GyJ+k5}P5=!0E?F$vF$pLmxJ>fg6nr=D+6mu~v!n`il}XMZsRe zyoJD_cN{K4dqEhCxMT1(*DEItiKLK>n{`q)kRhRmXjr*X4x^6coLMnQ#u!&fe&e0x zr(EOa4p&TfeJ#8*i|9Vq#$q;-fh&NR&#_S-*;%7Zlsa4C5l5f>#{7z_D zIpFVgeL6US^kgG|}B){(~J4XUM@0I^BqNlpiyHEYo z#i_jZ6MiZXd;YoS=#1@;_6O}{pT%q#TjlhY>*-e_(g}tvr=o2XQ3WHKIM!;yE1}n9 z9+PIX(?Y$GWn6KOTA~!YwIyR6(APz*3%9l0;x9-BCTS;sAUx5ZulHJ#&~~^mUQMoB zwSJZLgnKy}N8LbpiI&L3fEZlrMJ+Ck`mSyUC2P?qbYs%x!OpmTHYTSD_ zv6$8a`JN%_6G4X=;t+<_7|Jkt3WEsSf>cMe z7obPzlzLn?9(mRxH_kzHTRLy&WNz^3=T$0PoCxJA zIGYDGOs_?aV{zF-ZQ(r^xduoMUp=7Ql&#Z z_NQAwJ#Q36LjBm?UrW`!Tc1?=_4G#_#E^1v;L`!{k+i&FCta3{>M|N)hS6$~f=s>? zCKUgFn0x2;O5<%^bI#bdDz@#4ZM$OIww+XL+qP{~Y}=_+DyZ4D*6O|bbnmnK-?P5M zdtKxAj`2MAy%Yl3Oyb;tva57V|L~NHRIru(Lf0L<*m3{Z@}io08? z#OELcQ<*hZD#O*K0Ikeui=n6eCLUv@v`%JkD}b7KM#;s8W>CJ`5Qc44F0H-*mSxuo zRbPn6Y`j2rZQ@zr4+Z-LIdh0A=~=5jr0ix4A@<%%FnfRW6v7E}Y9m8Av7Dy#gJ)B| zwI7X$73k1UHL3zkfDQp`Rp`@WLf!}->VUfMFu>kZA(n-Cm~&@vSOJS}q-fAYFz<6d zc_cLyJ8go8LO~%!i6uO@H845LIsZ$mrIeGQ3S7%G1@R5M#KT2$dKr1y1cnugqtSBG zKE@ZeUZCRS#vJnVo9)JC2eY@LM|;ZfiD0yCNu5rm)Nsw*o~$0|d4&FEy}HQooaf1K zO_i<=_8BqRO$sDulLH70bj9;mZUkQ6wAViW|cWmqp|*8k9!S8X|_nX zwIoc`MwAb3eb=b1V#my$>q_14b`_(}ZQ7PUftx%P2G6shF7Xut+mRdbb9>(Zld}0C&06~d$(kXrq})$-M9Lx>i2(vbn?#a;nC$^<(|7GtXq`Z2b;rsFd@}>C_x&jgMIceF^FJ87}Tf{WDGjI&T|q_ z@z_7gJtZSa;*&{~=u_NLDv;9{OuGNDrk!HN6Dg0hbOO&7)CWD4bfoQUCx zUnrJo`A;^ENYRs z%as^XYLHg>_4)D;uGFlSDQyGBaz(kUcMIJ#gFlCU;T@$!;Kjis&a6T^2nuzXw{Nj4CGu?|%aq7eReW|)KpTFC?Rt|a*Xvz<8 zpLj|1pIN}#mycs;HDrfXXoU-~$5|f;2^6C)1jAvKG6W{LQAdPBLm3xBkd6r-hGA?j z6T8OxQ5%L*AUTuLAhmJN$Kawq9k@8THS;g<0qq$8*N#~JX zM~USV_TSH4^qc?NIafHM}x6c=9cJP3YYQNURu!RN#I&x7GddB zQj|IaXpt&ey=cj6om;KdP7$bOYw>#UL~HtPVW?8-=Cai4;P7OV)j>{GZ((Y)=0jIX zQ&>QT#%8$~;RYH#pHjw6gMnI@%aKdj4y;&wkzWPoS1?lsW>loflvaQ)y03!#w}_j^b@o(!?0Hqq0?ugLc7eey?@@+dJDz8~ z@=MJ3adCT$0Q=g9ibCA*B#X3pGrtw zaCsgBUW`Rt2%;ARIq@+^-g^L_YmOO(cZ9Y*BGKEf{sEsmHtIQE*t#oH{>`-Nx`l_U z8YO=E$~ER5(_1)w>1TGi`Lz>l&5%!oP4xNC!QWIeh-pg;`t_YXB>f=pBuxm7K9TF2kM1-PPR~OSS@21=A>fjB*~LX z#$wR8iiQ##g%1%XBZg>;zr@K(SWFkRirqHPL-?|;L!A){(I^JSiC&$|HWrFu;FTs& z2v}ns)l7)La7jV4qd_Db3sDMiORwuaf@l8_qV6u7ka0)yvi!Y3{jfH(OB`A)a<6Sw>$Z zIA%9en)O6Pal=h9|6A;y4b@jgFSVWEE_aL;6=XxX$Qj@yBZc$GV?%!+Kjtl6P|#PI z^=XM6;CD+`l)ZI{c7dmcfb#ARW_(J82@4dpn>?L~bT%wPxY@x&)KO-#easD6w*+Uk zmJA?8!zaBt5w5*o^sy(+9?`4(t`|M$s1R172B;)9d|S|Mvq)1i9lOud#L7DStAN%o z!E}XFEO}G=%K#zApb=8*|ERC>>a0>>=nC93;$Sw|q1D7iS=EVGFOu5M(VCZ8ZONLi zu@%2kTY+2a;3bZ9UjZ0AMF;ghwz}DT+CcPeat;|#5{07G)FxYMO%bO_M1Q9I1uJXo zDz`QL02?r4(ajui#;VH46gCn4|D`6`>HgdI{hu`Y{#&R!1@I4T8Q}lXmQh0dLt6&% zZ*5s#_fpu8m5{ad@0)NtTW))M`!0tq$Hqs0C*PIF&8`2;gYVO`_scKad#uxrH}zNb zduZl;9%Kmkf08&v@xZ=hMNuaqj7DoS8bcI2fr``PiK33DQ3_0@XvtVo5FDLlrr_yx z@qm>i6!Mvr_QnlfC>Dsh*q(o$CLyVnsU;G4rT=!%ieN!gCc-5XVe*XElI&cMd0UC{@%2m!_ueQEAB?A z*f^aICTn5fs)c?2rNAfHMe&5DQeU!P2MFPqYt$d|n1UFk0oJX+|LAYI6&(I8ao-Q( zMYtg7Y$ff$7=sgMA`Dppk9MRM4FKtyfbK#E1tXIU6=GCQFk!;2JY z5<|ObDH%6Ph*qp2vMPLR-3+sT{2gT1WNIZZcww57C5NkB zJd&p@JvopDK3yqIIx4$sK-xTdJV%?H(%K!CoYeKvsvPinf?7f8Hx_k9Vq2Dco*T;^ zJyjg~2RE{$N=fG&KN}8iAS0ELSE{@XL53E;+#Ali%CsRXsw{2ypsLDdjJKq=Zh-c( zw!5o?imvM~X@YiewfM}U?63>U7c_to1Kr%uO=lC)|47O}ut4j=Q2s-(xfXweSM=h$ zYT<@X`+Dq^Y3B+QDx+&ia*RjcnVbKuVeqKiE9!Oy-_bcL>L?ff@}KcwYqYnS;%?ZQ^) zwBj0MMY+h^*1A$>7dAA%$F)k@Vpp_T(2O8*?x3#=aP5*2*Z$h_t>5=pL)<3h1`k2r z4?KvVOMJzHc6jW-OR{10!ULsRIP)CQI_6EE`hXvJF%*F3xt(8q#EHrURr`Zq`F7ib zUwcmPz9P2m8T=i6!;Ug1-gxv&1(ch=jf&OoO5#RXV8ORx5&KsxeU*GTH?fYMUuigAvH!Ao-lT0Oq zjiH1AA-2lwu7S{3G9fmY|6d;E6?GydDrop9_%*1qrmFz%784fLpn~#qiZILpxP{xpHOd2cHX}sQwd3=Wjut_eusipSCIga z4#wPOkjY(kNRaHaxUpUXu;V<(*)ByBY>$gk*gO+E^pj8`QwE5$UjuEp(PHZ&O(7_y z#nF*Yk`)PX0qh$9g}DXDfLIcO-k?dj#{1Yr7BdtTFAmn5V}O4KrKY4g0Ij0W2z&hG>AINr+` z`#(y#y`-h#QdBdxq%6LSYfq>fpXHQFS!kVSqWb!?rN5h6P*EH!x`Mgp+P9b}!)49u zFec}#qv&!#7OqcWh@`-wnNicwz9|LeHRYWWm@{!#^>8xU7YGS$ihVs^NKSqz`C=C= z!@&!eOgjAcKkfqAoK{77?52pFKuWgoVzIzIutZG$oGs2<(Qp&JOip}4>8f=3fh4tx z#q3fY6Hgt<)~!-s{!pzGZxz87Q`PKdTx&5)qmdW0?8a73c4JecuX zFIj!sZyR-4>h+qJpLl^M2*%LwL!)?Y^+R$s7WO0?b4qEAiL*84T+{y}Fc1s=->cRC z!@~~!e_XBl{Ev2Q@Bgx6m;Ar%*a?3LfuVm1fq(7T(`grh>(}nLcN!0m&d)y`f4zqP zmmRx9JpX^OV`CBX@{9b_jt%=yJN6N76e<)g;6fQ{5}Fh~hyJ&*Sx5?__P_1em#!#m zrX5fM9z=TOV3f**lnF)5U9dC>@d~3tad76e>NLW1roC0_Rx!1DG+t&v&KhKM@TIKM zV2vA{8iQpdPr9P46&&Xa?*^MB34>mOSL^31towyBkw19x+-(tuqZm{1o(R8#_S2l; zHPak7#J4)LM@iisHAl}DipWwZvvJw23*z8w44mFLt``x_v+eD+q&TK}eLhwR^gM0% zWBBGP^Z`8jC(=$_OxGU_&p0#H=AxE~dV5!`J!%>O8l+u}mv6bRkx*Aq6 z*+G+5&^gANUNE_^mlxso_H~0)FhMfFiu@m*VF!?55>6F9@qr!GCW(Cy)YQo@D;A{z z)-n|3Nk!aNngvZxmDHJ8zlDp%a`56R^6H{3)f>mOFS8n|y4GsGby!CSd#-v_WA`l; zeQUsP*c5F9l>^?*^m~j4uieK5yRC3>Xk#Lpnc@rV5H}?FVB3o&C>b#hklru9x1xF9 zhTX(JGg5_!RNrDO52@U>8XenA_ucNo*VlQ$`4V;iZF4rD{W%0{7}8^}nI7(DlLTLpR$$v+1#+?M2lU=TkUtE))d_sT9^#)21>rp98;&R z^V-~`Zhki9Ds4(ERoQGD^y+i1s(%w}kJmNLo!dkGb+fp_k`RY?h(JSxcNEL}2k-c? zO`o6=RDx@td7O@&<297waT{z*h8@(-P}1$oJIz&!^mZAg`v=Lf0b7#qtSH2>`?@o~ zfv+oT>zOZTaE-kOJ@|+WKDc+Sp(k|q=$=1f@qPadskPaq7ipus*$-(a`^gUxkc!zy zbF{1^czc$f{0HIcDUbbjoFHJeW^&D>-wEoBY5ottRwT&WB5$*`9tY5q|DmHP^tM6A zBW7gqlPDAiRsn?#GjtcyBS|fmrlm(J@H)ypY=!MvNGy(W0j^2Z6o=_p~D_D%I%_Nws2dn*t?_xq}o7 zB)K*~YL5yoCMPU&3^s~_z>IICHwB9=G)9}ZAG<1b1Ut4afji)Y=S%=3oIDS_%o#~g z9T6uIZ;;#vsJKVSO%RJJNj;H2f+rwMkn$}^U7DeKGuw`k^C(FZh%J4|-WH;AxR-X2 zQg$ysCZ+_pqQ3}z1gm^LrtLj%Ag?ktXe2+O$IQgSR}LfqOiJNuGtYp2I!j>!PGQ3? z#wa+y6FWbgK%{8Llc5%5&<>oUY6&akCQPb^y)yO?0o>nuMBy7e*bD}D^4nh%>(3}-;9B?I1dw>(Xayw*e!BylDPxeumpPOvaQ|Jya|mayA)IUG0LkZd zm>8)sQc~^^E&FwZTA?xe_rGK0|A*)D|0YJx3|>)IQ~_R9SX1{ead5H#|5BDwLo6@GEkmrtu5H9jZHMpfg&rJQ44zY-`=G>JqN!0 z^8fwjd;IDB2RK6J_^*>^%aB81PB_wmP;3SHZUg`a8>1w01XKha3uG@lgc&t~P9)V$ zYH4<&$Vy|J9f++QCZA>JbjbUwEQ=kF!cwBm*k~S8w8mybBGks1P_~s8WmMltL0qiT ztuvl2a=U`fGw2RP>^7sSr+UAxGW)IaVchSVGYg`N7?agsdaez&@ zG(Z8BK)rp-e25zTPV3jBiH$gx(yx;j#M2BvKt(nGvj)fx-J>R5&0MSDYOq2;ntzVa z9b${#V&l-kpj~xK*BQVB%g7J=aERpG1Qmq$8{#BhpWTB9$g764T={js_ORmxY+KcH zjfiOURlj%YNo%)T=WSML9X;>kx|fOO5qmko{Hwp~9O%8(FyGtt`IneKX%5v;;5~_P z0Xj^0fgudS?wS-6m?_LeXkza#m~gy5g9pJxykJEDe5luRSJ}m2=B=O9buV0YJy!Xk-1iM6uvBXsz=sQ($V! zB%Zjz`+AK>1t3-iX3B+TQf4AHXhUa(4^9T=$aH91xFL#&SeUq{ZCK!XgH4r(rGD^~ z*@es{Vdd$8(I}?Hl3I@!$Gy>1g2jxbSrKIDSVtA5BvW7F<=X$UA}wjax@P*i>`^a!Hcz{^ zdPngP97qAGkqv0zSGvXxJ&!Sv-TnL(^f2(_fh>d9w*1$_EWBF}2^R-COs%TEA9o|9 zOz^j;jAX@5qd-YzHn!R_$43~twIw#VuQ4d>45BuiY$%dj$vx%y1DYPSBZb~yZe_uxcOT*T`gp#N@urId!{8?qna`96VXy@zA1nkQWPPLX za?m|KS&js(pSy^CNg{xbTnD}omE~G25gZOe3h|qxkb=Mh1z*Y>B3Ghlh|;~O06PYR zF?BTATq2nC$V#E>p%}p5H1Y+03mxpGx=av{QP zo=EE)Z3<3FGZD&-_C1lkB$QHA+A{PyxjE|yoSg=kn3C*-RaEfD6QTgn;~dy1W|m_< zF$L4n^c~!(AorMCYVSuNr<@!H5F{%16xo!aDi_JTmojO=yPVOjM!_byG4tE-JFr+8 zk?WyiR-TnPrv#S@!OLrIE%ZJOVgJ|-f;7>T7d#I>(L#n)X`Y`KA|GzyOzrhzPTTwR zI}~D^!*QX^BB9^AtT#F7Fds}I^BG5BsK@%Jd zA87jZT5Zllr!v)5K*yRIYWXy!R9OdT6-XVmz7yH>>e7I0Xsu!%fvXrKch7h3y^#S9 z>FWJ%Ya5saDyvLam4XCcZ2Ac;9p$T4t;(L0J;MNcAxi3}t5fkF0@o02@S(S3ZTf5K zw(go<8n;BPHP6)c@&Zj8iL@^;2lsX4$FhwxGS1EWrFF=UKD*lY9=$&inf-Sv_fAh$ zdO_0nT4B1ol9#LI7rn)~r=wu2WKcCO$Fkn9F>**K$*BZ9`q7h<%w>;| zrm#UYHl0(yM$yu~f1I>ybE1j*k)sDH=I*-{agZHEN_|457pKKMV2 z5#awUM&tqNYb)ykjit@4tu-C_UER68eR%_enZqOLW8=w_Q{QK1ljau^fGbPO(JR2U z^~lZb9q)Fm{R6in%#%}>bBxQYz`OgP$ESdwFAv3VufN@TKR;%H9g6$e?zmuh&%r1m zLt%P&2A(hvac$ANRYv@-P9T%)a0n3vdZ|S+^hDChBzj9U1Q{?gap4_s<;xg!5qQu!=rn$&bcUtUPC*0Y65MF&@$hTJy$lYuzC5^I=BSEF^vAg=nD-Y;)&xykOS8-oUL^J+0#v4>#6_%1NCnFuFS z#*8NJm2QK2Xh~ci0ED*&OWYF4P(gvi=BSk#feuC>A7{iyDejhip%+)$ZeJ|`IWJWM ze7jyA{Yw&__{|AqR=(#gAGPz@RH047?lYv@>UP4=tG{>03)Sg7mvnvJlpE%8dcPuS z{;ThG7vx+PMM1##chG(2C=tzj?@~Shl%02a-{+l1d$ga^AE{$BT7TfQu90fgPiW zoC=kMr4i7GC3Dkf7Eyi>uIDS;Ve&wyaqO;_1ZltxlzQq+jh2ENjKP$pnlLJv6WDPk zQpQ6zX$j>Z_jp0&*<-z$$OaB4Fr16-QOU8fD}mb_EryFmIM8 zVjm1@P0k>h2NURspfY-(FWW=J$zm!x}ERh1IAR6*D``14$p!_{={R2c1hUs5$e zUD`mkQIgP?gW5{0ZR1+Ownm#;F{+CT_`?%zQGbjXGgMI8;*+vr^e)kY_42RFBJ{0K(Eu+UEn4`iqgazo?1iQ7^WV3LNcNOXK?&TtIh_nG*aic$VLiXSq57t>B8B_au`^vgpi0Gk)W;IL6uwq4ph&@A6BF0Ut~A z^U&KVGx(R^bbaH3nfHQZ0Xz?opMrc2Q)HBmGo{NMe$OOoU)FxkmlyP2EcLbXZJdQk z4!-WKnf~cn_i^y`>13RHeSP#n3HTJsF~<0OX3K>W?D#=OhgB2jQVpWGJZK2;3UK_ah*_rymldKlGF$a-lB=PFX>GY^(Z#Aax}Z^ zAQDKHc(~QH5mGlLb6ep_94i#nBBi^igmIvr&6zk>A7kru6J`Wuz$w;VnFNz?e++S( zCC-OkQfaCKl4HrrKJ-U0NqzVP0n{UO%(GY;QDvMoZ)0?toG``rSE-+-Xpq^q#+Wyf zqk{I4A#be>>!DC)08g{3gI(qGUKCDPqP%@8iZ5e24_!Tf3# zSnvzvu$vxIfssON;A8~~kM{8kDdrsMlYv&w3OWNngjoG1NgNo>66234zl3ebI~&jE zNC}rC8*wY>onGW_+0IZ26vQz*598EEA5*++1o<~T<%_~ra2yCPaN+#`!mPxJtl)wa zq28V_`Ve5aAf}>N^)ZTB1`7ogY48$=Fp9~{%9u#12;w!03UOd4WL0T{yir_8n0o`| z)MZrdUQ)^zCMzM`H|O%Rj7wvzV$Br>NkSyhE4U{uRA5_`wv=Nl*Ih2<)XCH*Tz}?h zVv4JNfm`Wz#mo~+Du?*=R4KL=%CtlzI<8XY>ebY;9%3^%2r+?-1N zC4?a@=VH`GS&L3=&h@QURE&;%BT?F#+zo6<-naqxzS6-5Xy!wf;5a#WYgU2AUZ|Sm z2AscMX-8?Sd|5nU(AJ&S%P+d<`aN;$*lwds1iyocI!c z-1~dF#us1s+uu?y;Pq43cX2B=oY^VY{e<34*GrI+umcFIsc1}H|Ipspn0^o`>Um?a;0T7T8wuu#7@LHY9`E4sM zewVozhqYKlvU3Kl%Da@-$Nv1`Yb5XUwp@VJS|KTasgnKnqe7vzN^|y7qx2m(;01H*uerI&nc0Qd|;EiC0_m=tw86W_mCEwMOunei< zp+#8GYD3gu=2Bqy-iDOZCCT?f2=1wg78zB}Y=HCI@nm$Fmw$KA$l;uO3~J5rlg<6h zW~Iw{9pi701J6-DCeR1}>GQ0-p2uGBdGzmR<%-<8zBi{Q&~LMbF9DP#P=nz#6D5tEsxADN%fs zzNm<3qeYDXJMOBguDq4Osldc}JE-=gl|iWMLffjU2h|s88|Sw$>R9K@-3HeHW?ri3 z>#;T9gB!H%uLdf|AJeZo*X^_I${XBa4r)S@Q{!cKi=1yduNbRu%Nu3j?0T-3WG!ib zQC8m!UQ^21^%wrBUhTPAsh(T2L6h&+s9{;e4`z&h9Lk0UW& z+f$M0(l<|%hi#Wk2{!2+L2&x0Gypu*;p>J4U$&WhM9F4Z7+PZa8hTHQ;MwVyyfR%| z#J~EnE$Y#IGA-A0Gf@3lmKJbhQ2(~`u&EH=+q&jx^2xDoT0pjUxoKel45ae~YBXp!MiBx*#??J?Lk~UqGwo$onBYAREzYIwsmWn5C~PZxWKzL#?sJ+|Q@jD-51ohJ1kA3OQ|A8$;Ga-TQ% zWK02{7sX%BI_3?JeXsz{<3hkkS}q;%J+P7V0VWQ|AS5+>;P2G0!8geI*j4*u zte(QRp9&Vk=o`@Um_x6rOo2Ef#BdvDgZI+4VSjv#U~eQv>Sh~4%5;tDy2OXMZcxH0 z2?$p#Q$#*DP(tr5jW0ZLhRLCr*i^{3AV3Z{qohz*k%rd?$V?PsKrJ{aqZ(4o-f?~} zf`!;N5fkK<3Sn%s#VFm-q8S`^NxEBh@mkI7%7N~D;7^*t~sN5spK;fps<{#~MchhrxvTv?-MvJUwUBUTD2Dm|U7E>GPc zmrmu9F~#wg>|$ao!lHK~vC34GnrTV#WL2S0BU#Kqm(0OO%Xk==l9Y*Rj{5byf9rOEI(AyR$(i{&bCsuj+Xz7O-Yqgt1$GO0?V1BFG(P|go~{zO&Ci~ zr+=&LDNFsLL#+-eS939O1dtDYKye0Y0)l^HDO<6hp+;62B9rh@>3VGTKpBL@z=r-GU zjj=oakP#Yop6&$Xwz4kT4Y=y#Q!VMB6`qCJJEnHy9sZf^!xpf&I-Cyt{o*bUh%XQP zg1-4liIZOd|HH#9O-I~-v$x*!9_Gt)J@p zY$msZbPgs{K`>OfBfd#bnOoY}7~DW(OeNnar2$KY7}jZ+L(T!ovgWu4rd(tuzcJO9 z4qxTn>6DP|W56r6BZUP0&3)J2O_`i4KGwCyG{3=Z7Sn8G?Y;B}ygD~N++5NFVvtpm z3E!8{5&rNspYoDpix#a%wz&4Mr&-ZHS` z;%_`qS+Sd<^E;zyk4mnJYBd%B!ayj07{T=SZ>{O-9fuf_++*mG_=NU6sv0+jZ**53 ztD10}U(;t!BxAhS>9K$gDm|GD*n#soP-Zn>neFCZx>8Jq-P(|Q>{c4WH&ZKHz3;ZJ zzHwzwd8mcw$fw$%YA#H$#=o?FLv?V8Rh{}-_Sh?*?La&H-uxKvDnuY~RlAWs@L4w9 zb28{?l5l@8vg@Q)_L>p>^d^I|<}t#fpr!Q0aty_lql8<29~PPY<5Bc?xB9M4T0k}h z(^sDIX#w*Bsh*P?kW#xN1JQ{pj6xnUO!^G2-5H*Iv>?cS+f-u&9S<0M@g4 zS<5L0T23`_p~{@CB|ui$?>WejU(a#PpxL_I#BkXo9QCdGF^vGNX3f-Nk0@*|*66 zh&f3Fqvn9Zj%NNxs;E$mlm?sc|+SpK%_A9m*OJU$F6g{G+ zYn&!<`V8-Tgxerh0HhQ+q?*ZDgeOs?FY$RGZikb%WbkXb-&=Yx&V=9fTJV{&a7!Xy zi&Kz(dvLh0$@vL@$CH4MIz&J!qz5|mz)ewfoj@E1V0IR=R35r+WY>QmsvH>_cxb-n z5+KK)wrI`hTp0gg+ zrcRfXAr)El3Kpsv-QX5&OidAO8C_GMiGdQ`XsOi<6Vpl^gDw=)iK9L{DAg+k&NdV? zcpl>~5<9A;%$DIl31cx$?K5i`TTjh5gA<3+WbA4d7e4XDLpg5KGwx?v+@7V@@j=`X zOnilL{MiK62~6Bo2iWCnJPAs|<16r4E8#UG;jJU#V?E)|YXSf_5sW7hLOT)4E3y1P z7+J^+_{Xsk@Q-6-K|^C+b4yNJdv0e}Mo({A|3J#naPsI_;>2WF|MX1AT;)Q{Qtgi* z@J;NR`E{2~@a>(oJ)eW4ozwW^ldI^PyV!@vxaXgde?vfT?{2&Q*#Ai>>=OoGB1}EB z6%dMs853bSawC%BM`7$}Lx>iD$RcC$$6d+qlZ>TU$Ygo>C#eFb1L?0i5CCkaIhh=G z{z>Z#C3BIO%O@Y1VdY?nVxZr0ypA->+*0{EEVLw5Kd9Bnw0hsj=|XGuq6*&eQoz?6 zM8*W~r}pV}h^+}5ZaN zu_w0Z=cS}IOd?}*IL2WZu<(--v#`Va>i2C5)P5o16RMGE_qlUM9RAV^qz^F~%U-m^R(v`{wT z5VIT%#PA;`K_t=u6orGut>@a%1W84P5FD$eeU$uH&8_Kp|zH)wm|?Ky#(mGfaXT ziS<}qN`d0QUWbA1t}>DE3r=7&*wy|rkGFHuXT)BJ#2_=~;P zdlBD8Ufb?=PJhN^;eov`Rrdov@J-)e_~oUzwBd;tB%rQxc)Y0YfO^1tEf@!m#p@Ul83V!oms* z03=kR;6sk0Ts;GD!UNpn6Lt~5h7Il5pG1FMNJJW;A*vfgi9r?2Gs?~!Kx9RBudFnf z;~5sAf~f9C+KG$3_c9fcO*H>55Us&X#AdKvJm6SJS-w3O$yb6oQqiD^$CDKwmR`T2 z^J6&xy;J7Dz?(>5aYo05{}3iY?+g`UMT3s_EkPu;nxIB%0?3z`LSRjz$+jiLt8N!T zb5C~b&nAIog#u_o#>a_DSm-rP2kAP|WDiQ>xzkN4@;_dsab1&WY_3;nSWHJXvdA*< zuP9g=Q)Me_n%KU$PQvJd=UN=HW&tx!Q9?{+O_PQENolUZ_qhZ#*`fx!(1s%QV{ z1Xaljws50DV)7eZC?SftdZ6u4GfYbT>-aiEyHf*&u>p5LGF^k|g~7=hBK5 zps?zCLd7Fhy>=7*i+E|7v<0g=m9=Hf3oV`a*CdUk%fwo{+9L3M8DOXViZw6hndSrB ziv5Edn7=@^LY1Z>v>|kzG&ttho1yhQ@6*O_aFI$>?`cz07)%+x)>-ruDsx5RdD_nx z_-B%;lSQPBE1_1_zg>It6|B9pKd%IpvV$^rS;5-E=xp(=ndV>a0tOlAlqBEP7(o)L z(xG+$XWeSO)H!vBQ9pZ#`_0u0q=K%ZFbtiZLEZDF72xTzkaM>8PP9rv&sH2G_)>Pz z&r^*?D3W^HQg1ywjM+XeyLw*bR=V3JcfblhV*sZ*Ke)|&|7KWV@ZIqKVBW7mnD~2e z%Io3Z%+rJRKQEzgtHqGNVvl%>1EZoWjZwb>M*CEq0^NKXuF(eYncKENcp2Jw^`iY; zd5ZD+>A}NQP!rr~4wxP}K(h4pu?jWT^$c5rkH7Ut<2vq(zK%^K6@FhMV~{fTVp6xy0qlx|b5bUKXOKOCr$ld{59D+a6a7f370| z|LZ#PUj&JN)>#w5yHHCzV!FV4a{8hNh6+diZy)8qMGYI9e|?np5c_z&yHoWsYK zr{@!wj=+aIzX#xx@6TVJKabvAKQ8{haLyI}6{j*yaxnTEr`i*W#TnBIiNYAwG7V$_ zk!8fe^Ll@fIh$rCQ;rwNZG;eprqY*p_yX9>Q!E%aoGA0zq2xqhhyaon1Wt5k<@*t9(Z&*_3BoEUb# z_(i6kJFY9l8nZ^%a8LU<5G>l8x$!q_s3>iRP||H!nu+c(;ekQaq>{8n zfIF$@U>fJkI2DV3kyg2@$I?j|k`L#lT#+~&V1_$GCVH@t+!ot1=SWRwr}V;<)-p4z zY@epMJPW2AtVpLSrZPWm-~y)FIg_@io>l2suBAz*8V+ff`z+;n)YXM<+x+EJ zJGgO3;`?>enHqd;Tl*npZPuamf*oD?=-YK?>FtzgT~NG@OlMKim2KBkn+!yEO&1?r zPwEukb+gR=R!v{|eN18h_EPmo97MUXqZ^1e$FUbaLbj-@iQo3Pjeu;XF%PTT@{Scx zQtn}79ITN#-Z@X(Fo|+J_7R1yJ%)vWVt%`E>=Tj`#ns6)b-3U2Do@IeO%5tXrTePf^uGJ_ zwvu_>x=jM2)r3KHu}6>Z@(uVf7ndK$fge|%^H$*3+u41>7j2(GA9F6#dyf+N%bKYE?^95W)l@GNb&~{K|lhZs2 zL3iF>X?6vKBZm$biV%Xogz~1uH3I*cK8O*zfKOXO{7JMPjLkVo*lBWbpQW1ZdfX7o zeq7k$>sdPBRqroSG9b4OJ>tEQ=)s~*8a-CtPbG+ouOhem0U|gb0UGQ_GrCA(C7=qy z7^C>G;Ev-ga*1M?69>yElQl1u45JS;Qm3#;W+igxp>88ndqIp7g{(`WemGGDkq;36 zq9XWefE-Q6BmXe)8psFMB=r6H5Sl(pN-odIFzXpWb#vG?$1ejGL4HCd|GO5c06M>PrSUF;AWw9--k`*A8 zedD@P`tU+^#&?>{L-$g^CYqqooVY3}$6EF4lUfEZp!)UwJi85#3mlK7(D)?q2NsQb zQ;}h0^h7*-izYJPRf9Psl}&`#`kI>R@TBY#m#Vm@WS(ni z!t9_-yU90=lgh$-ZGxmCfs-OjWQ=a~=DOnB@E{zI)+wnvvvk>M%v+5XSy2R4z9!Z! z{{1A|&3E!077h2Y&{ zd<>J-o8sQ+fc_Os@}<$=sqJ`f?pJjJIcoy^_8Pxz&&tmdZrfW_ zwhggfyH=hC->Xdy-@TD*=3JYqd{xAjVVt@5(u{1QZMdi{qqdi3C|-0+;q-;mt{c^n zO~~-j{iZSh`iGG!-A<(hdw1vME%PwnE+XeIum!)nq1$zWHx0o5#ob$W)fuf>n;Q%6 z1b26L3&A}QJh;0%K{oCi4esvl?(PuW-QBgRbE-~Pje2|Z$3CNZvkUi$Sr&stc&}Bl%!lcf7^e)T zbYr>6$5|Q1i>x2%$A~V^e}n%x7u$N7?@T=}cx9MZMiHDIp}Z_H%x%`%0?)u*e)9=U zyEKQ_EVyjAtaF7vw7hnz0WMeLuL^qq#BE&4mM=(D_vG{3ojaCmgw-3kYGaRNMp zx&XWKxw(6Id3}5Th#CQdB)7}T^!qYACKF;xBEpA6^iNPQ(RQ15YZK)M8AJg7w3`-y zHE%fX69yiiWow+8z_`#A@l-%Q&dO;E`pmL_R-y|zE5g%Kk}5KYN0H){%*o6YsQd%2 zQ=&rr!yOduaVI=)OVi|1e(7weUSODbiIJKx_^Zx3yzLBA4Pph^@x-I)grrgj$&>H# zZH0t6xH~|kTh5oe8mbo$mk$JZ5^nc{N|j4cSnAocO%Aq5Uv2I=h|E3$t<&psK#l3) z#jl@wfLqnpVAT#Nv~nCSBA9H{inl#-Lp8-BtH>wzpY1>e6w=9ikvSeN#GD9TY4K?v z9hTrdfV`TYE>`56qPz+7-2mX*rlwIHf?St~@^P=$+U%F19~b>pU7nB`!9)scA8&Wia z+=e0CAa&sgPT}AjH^Kq6^+>85JN@tANKynqp)WkUacBj0yIfLX)FZKIf2jfSJbu)B zd?zYPdjNGoWs_(^2aR0_rk0@%@3%E|N)gi>n!G=vsv%oGIAw{rPL7nyh3OU^NBcpz zk5A*CzPRkvDG2AG%c;Q)!<6~4J?_$ZP9Qa4x&Up+k;kqZ?PAfZbqPsa9|PbxxFnmG zCMTyMEU_%51dghdqWu}SAb+Ce1X2l3lP)k7>7=Om1MblRuL_r@^;h)_V+m~`faAE# zc0gzOtWIy+qs(=ImJj8}3MH*gL48HRVcFicxjFNppT}`yO-pM9#}$Z&iTMuAW3l7) zD4eOSWn{FFCz6+#G89@3@2crkbe>tQ%bu!J)Izj2?av!A-WO6|GVB zs+C-~nVFk9cNlw!F&v-Ok$QH_YD7M#>w1(Moq&oKLap|-J6q)6qRSS4)*EJZb zll0-i%l17u>yPx(O`MZAj@63$$og%~1zfh|4^XAyBYY@C2lr(1Mf&{~gOi}kW|m0C z*`a0TId8wMW?l0}hFZm4(!R+s?^)%BPD4PzH$va>wiTO}J?tM|=RJK~+N~F^Y!$D^ zc3eyiS3VDXZ{KQvyz`H_jh3|}xBlMXdyF^`@Gjh$Y-io$)g^ot1Z(})bJaLl@$)TK z7x`_1IAy~wX|Qfy9~tNXNAOg#(7F8x-CK>NNIlBtAYA9T zqo!=>ZX{qTPGZ*h&Nn30od%W&}%s?^($HWhm~1T*6tJ#IY1jZYNix?-cI{j zNgCDMtOLS9DzMBU2{nD8mAoM^keHts;bUO|vdOfnwAM!-FYu%p3`?kXM7f zglP>^M99Vy-;&|lTdK|~m=rKryNcbDD^?sm-DE`VBPLB%GcDnKB}si||9vtbJWeDc zpMAA@+T-SZX5`;{-wA;mfG&G*+#umF(hr*n>Bt>MvmND^~iF0-|;N-0szSXNmCr3JN z3y$g)?{v^p=PU2&2UMQ!Q9AeR`9KenpUr$oIV6X`?)}2Rj*G}q1Vj9cYFQr>LbUdU zN$l8{=gWyB&FP^SZHtUuO&tVdWKrIIXm5PaO~G+mA&X2{OA=BY73LeIIP|`_fWauO z)LZd~`jcq#40#D%`Z0B>hjKa!dJ*0bO{3fKa0=sB2!qJ3{u!zc>6E|O-^D2F25=Pw zQy@z@|I*sZmME5N-j$_}QD2tf#&z~^fV7QG%h2$|476{naGOwI&^+Q?O;jLb-vGue zhxO4Q;@aOV7C&BKmk`*M4CkX2b+vy^O>U#t_bZe$@yPtD62Gr!m9s7il3szqo^OyP z@J*WI`nBPATiqo_Zpi1tvHd}dVbl575;|yQ{s31k-@U&~A&{;a;>o{Y5$crXtc3OA z9-{5%-wLh77vS~rumH{7DN0f6qRjwSvuM_Z#TNY94sCrM&(ww0!@=xm&?dW!GtiMv zbMut&F#&cWQs``D;}U$46@`*sqlE9z;Q)szF3>Q5XnU(lJ}wUnr8-FD=k|&>dOxND z%kRz=jn|R|T*B)3mxcxPgvH11lksYB*H^appF$l%1NL&xo|1$o6+K7JRpF!LyY~bR zo$MCOv4y9_v`Rt)7#%k8{VxDWpWab)KrN)@>&9-+;TT6`8X!S(7Y9CUT+y34t(wl1 zm&?81Rq!C{t}P};-TGsq>uNjX=zyaw>?VP5Iw+e?^*{{S&J&bi8f{5?#H~~|1JuDR zcsp5^Gi;poe80`K7Mm9D{5uZPz5rJcI8oNoh!fQqS0iGugqm7jXz(_Iq9@=|)5M+^ zJa-23Za>w7=3E${yoo6cJ(lwMxyTf0Qpe;u_DgLAY@wi}K|&5-KDfLxcHfXP?(Qp_ z%Ml-Q@ASLya5w&TU=4e~s7*=0ma->wk==!?BT6I6%O`nVY@VW1yX`^>`G*5QEwoqe z1r#*;veg4}lcsz>2dH~)p(rE|Budz@PG0ZeHo3I_=JWMU#92=}cN+0;zfL+#nS-o! z8>0|#1cxcwFZ45KW1YHDaVlaDn>v>xw6Se;ko@^cr_r5Ab=F7+b#`E{PjkAzJ z`!Oel$E^GM-KH?{n#{t({HV=6be6y=FH!5vQpev~K7#ME5?qT%j5duMZ-oX6d<#!H zuCSgQmtB;6TPuwFe@Hu)!gOD25kHOxJGHMBHc)C06wlfXJ1+c!DR!AY+$$~L&(khE zk8m~s)_LzMrC4Pfu$LY)gYU;*E8aG2JJnQwJY%F2@n2|YL~n$XKK6F1UF{)y{-q+S z-UNMNwEB2mm&m*q$@adJ`wZAzc)!Fo-am9#YT4@gobO(=K9Xg6?=gOs;R^Y@gmxb6 z!~489`E)A0U45G|XnKFl81zYg@VUYQfE=hB-b$Lxq%{i?J?cF`Sef`e%gIY%#*l9VPU zGDx1l+K*xmrZ^~~NB}O9X1uWR)N4?tj-vkbT8Lu|2!!}&XgjP>a<+n0Ol&8XV%}q zA1ihXO?8*vypg|aRMN@VtaXZY8_d@+4cqIOkTkaQrKa@N%!5)}AkQqs` zQVh#FGYJG4P;&XqP7qlltH$Q&HI{_E$`QLl^sVTVSx>R$yB?x4^BFHo%?r8`#eN~ zHlfZaDavYIT)M7mJ3>Q##UZE&EA`>BFRzT<1m7O?M|(TU>@ZG~=#P4T?#i&j*V#Uf^OR=r+-_5v?bUNe*%C~48ZasDt6l8cGCEDgl`yJJ4m=Qyk=^lHWc#o`m zoTmjb;$4b7K(%F;DP4axt!6oHgN)|NcsoN-xDa^2 z4yeR+_q5P!AFFFDX-XqVdGdlhmJsxK!D-7pvN88vGdhR%eI2&;q`%xK@k19n%NFv@ zFdzn319WdoDJX)UB7hO;b+yVVKz%jJIAEprL)kWV0+Hy$$Szi(@?JvHD+|2_<@6xY zSAw%aN+a^v_0Bg%dr}_iKkOf*5Kx-=6AbD9h&U7^cMuBY(Kq-=YXYOj>w|4qZ4D>&Cw$m9YYD6LP1^U)~CT`?7jw73G+&nxd;SICo?u$+<;XW5=QT6UAX*@Z)*g)9zZb$0+E5dMeX zsXq>n&U}SZ4P-0?EcVI^P zrN6hJ`G?YHGxE6Cn#`l74CC*z!kWl2lCu4o#m{G9I2yY~P)a2|{KZhaHOdm?nCN5# z!r;M>K~k1QKfxH{XJVFc%PB^Cx*Zf`n3{~&M$9ai#ZLqmA{>XB!*oP;M!B2(~#apJhVVp=gohidvJ7Cvr()N-)xsnX6&tOMgYj@@gML zhK03i%`4?@M-)D)i_QN{Rw+D=KW3wunm1}!DSnU0vc3MP_PjR(b|ZR3GPtaSxBgW+ zQ2VcRbN50Y;Z-Ff485cjt#60PRX#9ZSrv) zudbRq8U-ybT+F2|RhOD}eA6FKwJVIQjkFZy;iq$|weRFzwfL(&RTS!+D6)g z{A`^&SJvUMxoY3m(xGH6`#!`Q)WHd(JRv+wo-sE&V7b>?}F(eW|{y_i2(_{E&;#!zje=qIh2q)n3(?Gzsa)E3l6obT!0jR3A*NsXn%| z+Jb>k24uiW#E5zBlFOJ3f!8Nz?L<*io|oX zGZ}7jD}%3%EGfY|6em9^Pw#a!ub48Mj&z$0n+2;7j2nSG??fT%bxiP(Kc`~Dfpi0P zGCQ&iv0ZXkt~iCHeX$JLuH#(h6R9Tu_1AnPA!oI-$Eh~e%KRv(p{`Kw%tG^Jd2ynl zp>h1oMw1xqKY`N!AMZb)L;mAB0{P#sBifmTB`C$E74YSig(=|mfX14Fx`w9ayjJi= zKu2LccwgzjP|3(>Zr8-*pYiFeslQ3(bBnRd^{a{NgPT$1DPV`YdkJs{N5_%-e-6Pe zqpR;@9-mH9U*F&l-wfxZH-*HYHVEj+qk!Fk0l0zz)RH;EVcxhpNg=2oAaQtnzLqC- zlDr|V7uk%lxa;i^0fv+IIYY&L*`!mrrdsznEt2u;2R_c+=8;lb67Ly{seA%VG z2oF=*zr3oI9%EARh4ba_*g|h9lyn-!k_5C29t{z*;D#&S?s#eym@QUkLER@RmDnBL zqYhpz4Yr%j{#%%WvXqwE0}5XxzaT7y?}EkCIX0(h+^p3hiyR=5j5$V*MRCP*3P9YM zp_FRO+P(e~wOV2|!(+6^<3d=Y_ju8nb`QMVN)}>rvB!T3-KI_9!}?xRdWS3%Xq_rA zP!2KO%3{=6pUxL@9AI4lVkQ)FzahzTHTxiZhkn98^r`&;{_*AQW9M?vml;vpCEZ}l znmvW(4ptq^*BmEl-S>uJNDqi)0?=1akqjXYe9{=w3&P8K*a~3O3Ly!_OoCa5r>#ly z4IiyX$&KjQEh3W=%7*a|n~^Kri3VII#e3AJ1B{rE(3*2y&+uV$BC)<4rN#9Igc$iz z&?g(m$*VR|M5wUR5GNSOC;KIu1{LS0*ve-a`1fYx9E6heaU6KxFFol-5+633rt;_j z5IC3&xKdpFuetKFXSLimJx~B{hMBy=(p~wX9(u)j`%gz**}q+I4|8_U%#Dq6IE9YW z3TSZ&a~&(-G)fWLN({;}a*i`fOlpEkD?Dq|a?256epyz16d>XqrC~UQm8nae;~>;# z@U)ueqDh9IL5|cMt>h{O8C%26;^G182l8Yvn|b$~7~#$Zg^*j@Jd>>p_86HjVDG$x zkvbNRN3j!Lw4R0AAJEb+%H=5$Xb}*QPwl!<&}pthSd`n&`@tR{D7NZbWRD3A z%cqT1>d?OMv0yM_9jlGORjrDSlT-#cg7LC--!$sJ;oqW(;33?Ml4Du2R!Kvf)Xg%8 zv{#NJPbG_vtI4>sqe4F5&&}bJMOH47vaNM3hy=*h&DkEv-l5t^c-gHAO{Es+0|?9Xx;2QU}!z)K*#Mq;y{r#IBlranubaFK~Ndokgd zg1ONQ47Pvv;Rz#!A}AZELz5B>@3ZJAiFOl=VhHh`+e7*rp=`4@_=`4#N9_3J z!Qnqukz>X}#rGvq*b7C;GG5yxVi-}S9|{W}E5uS_Q_w`2jmWKc`F=8oX?L1Ns2W(q zviZU2-;%^=3}!+aly~V<_eQ^-)0$P+nHSPAG@PCF&U!@^CQAubNe-*X2=V&K$|Pm5&J7O=J0-#wdYIyBCevKafI$j z+D=I)y-XMVlOdl{i$<`1X*e!LG22DIh}!aaDpB>?lXd)%+B!@~?%h7QX2uMe;TS)! zLAhAeh}I#Ema>Q!PniormSw7tCli1!muf;IYxyg26^4Ej z5yV()RsV&RZ%YYMU0>7fI;FMdK1_gwo$dV`IV00%KeL+52;>M7PgK`=)%cg!$XtVe zuU*hm^RN76pdRI$EeXO(OGY$sTq(`ZKPBrB`U7zJ&N??$Q(p(2Ht*f~cLUlBGw2$x zs^zEuhEYvoGCv11a5_X6O09%CCF$Hvvy~Qp1-=(&T@}dLwgMX$-?4cn6C%d1cDFp+ ziX$KAqyH>XGqKQn|A!=WA$0(I{7M(uQy4=DHCK2ZCFbRB^?}k|Nal-?%e3V> zRij(SH0@=mfYlz7DO)+~-Y3p1!hjilZctTq+*eJuA3v98T!GWR*>6~T#O9PZWnBPbB(W%63cICuLN1YYs${s^OngveKAYs8py@Nj z1Aj{TH!l^MFpsG`N(R0k>4(aiLdKQLtR>pkhFg6pleq=XHdLOL0v^8>EC!atnEsgR ziTqk5p>zp})HXLVRbT2fxzEhJwG#ZQxlD#VQ&rw>Wfdp1GQ96n*G_PN`2Bo&*QTKv zI^^8Rl2>Betg$tU0MBsOV|}jNmEk<{;uqWSdhI!v`5gnm8$PX?3Bs)u`TaQHf^QRn zi9L=CiJ1~7ZCj0zb%1N)3iSJRhZwneNJ9QPHuZHENAlmqgZV#{R?$NItF$WjvpG5Q zvpG4VvAM0iqqFOu9?X9OY|hNi{heP}{71@aePeTLduKPPiWKZJ{>}9E`f^KT=ka<1*MLB)v@kHRub+W}_@EWcd$HkD8z#zEsUW2YviC zmiciBjLDw>HZw{&a!y;^;o>-$$qZp{aHvoAF(^meomj5K@JK2fQZ2-4bB=t@`{&>9 zMZc~sy2>saW?GWjXd{Xdnq26^@5<((EjVi4jydU9tLbd}ReW8#*TX!nwhv1;nfkk$ zoKP6`l1R1(C^35j$}Xxm@nWxjPMGr8gT^wr22c1G26sm>rE)ocE3;X2l@L_f951sC zOu(Cba9h8S+Ca6)E$CSCxULYl*=o)+WHmc>`Vx3z2>7-%O^l^;1y`s&Yo4HX`S*T8 zbMMarbGee-#D1xo!cEhh5j<@s{(mf=QllNPNgBue5@}w`&c28Az`TemzAd zkVY=k*ps<_86Oe~5K#k%9EN$Dae9@>Bpz-CGH_>o)={% zDq(7nC9;M!lY5B0Cg}tc_Y9MIi8s0Dr9s)7o5oo=JnXW2B*24sWeKE6QGwh* zONS|;aQaj!e>9p+k>h?9=i~<r|fCu0RF<}6*q2_Le3YmaHSd;D${5OZo1$p z)-Oz0bxD~pDW6?I;A>iD6Vwu(v6HULgZfbXczrsh$S4GKN*MIxe`cA51$^h)e~wf4 zVf%k|S^&XDPE2Ev%SA3hnIT%J8MKPHI9nIOy1-d<4&Na;Z@6e|WxxZ^>y{XN?sj*}^;n>JWFoIAWW?`}ph->kVhax_7H^TXMM zUFZZ-MJ?>YCGVP9gWhR9le}4n;L60d-3h=CFPIVl6%vN+Ji5bev_c-% zW?EfJaKk}HTkpQ;ULUHpoAgCF?Xw|4Y;b{~*X4cCjc~g$)deBWD}9HnHm{kn=}<^T z0-nN&?cz;)46~|$=u_(Okykwv?$O?sN=UQwjbJ(7ErWVC(U3VdMf|~7u!YI95UDOj z;Ccpq7}RCQKrj)w1=0R?JGwg`XxRNja?_zJRol?(Bw`dludobm0XXeu;>;Fgk=2@H zm=p&CTHjHB8{rcR*}3sXcg1))q^%QP<%%_rqehu6k-?u}5Ab<2MbRnmzRwg6UVDkg zLX!^@{l=C&(`WUM$H=4DxRz>BfYZ|wC8zloS}UA#;_Zn~LM{+GtQv%tP=Wx|h;S9h z`eh!1sh-QY(jy}dI!Kg`Aj5H8N>Dn!405BFBT}is&{N$cm?_iMiN=xf$RkT_MRz}a_?+vU{IEY|FSsAAzjliY-QXzuiz~t zQ^b)DFC@sfI4+M~ohMgjZXLQTujo=A9~c1QgS%z* zoq0s6w4M88y!Atm8f0XiVOCOMb<$x+Kj~z>;Z||sdGXPeWhY6G8#R>YFl@z}IaTB& zUH+?bvCL)k%%gL&%1xFrb@H&zW89{7*pU37!({58WtWA z35tr2iT$V6Izs*<(G2;|L^E3czYK;Ni0azH`i9)5=A^9FwuFwfu8hw>b7FZGU~DLU zBy|ih5jO=nGxuj;ap`Z*>RQao_!g*hFY4eh^7tfV{(Qf;?&d1&^8VuH>uFlqkkioV5(9LT1A!;Q4<$JeiXeP0@))RY;YvBhD5WWe78nIUgsLsOGMZEsK*Z zu<3MqvwX2ERcAK(8X%BLaVFGYR^`DA*BHEtdphdm&v-uk8RkwFFP^PU(PXU73L!_aBdYT;1Mp<(HXGU~t%AzTl6IF_5=wUyz&~ z1+c#d)W{VPz(KPDNi1>w9)yDzDbzFBDX*!3Vwl;7If}Q=huiGn6WG3C^y2Kf?93^L zzz9ZKGcri-{U$Otff;qMXzCiST?krCcT{^yR*jt40f8f-_}3V-?~bapm)VBDIJ@@3 zFdYCUDTK6K1$xG;b_EFf9tVb|_KeJ?2+kc(Y8h~+up*hR;$IE{exRfssNh%}@))g| z=EKA&kc(Lk<1ROa;~zg4^E@Ho?4d!XI8H!O`gU?jTGl(zBCg<1$#$^~<}r1dLc?)y zDOyEIVTHgYu2x#oH8H(yAGoDe`G>kmlSTC&%~7FF{tRt-dAtf9ZLP*Lu9$mvEcL^LLAqwlh#-PR-3YpH2J5daG5(Rrd;UhuU%YNy1gf zfo%(X>XKb2WF|ICDKv7LT{qUsZ=3#G&c=!X0|U#W4jc)-<5oaoYK;dUZ|LRnuCnhXR_-x4Q{M=BBO{w&>QmFcaLN!*K0_x%V|LDl(Nl_NZertjarh!o zmql=ba~U2@ymdIq6v_R(hOO#lqi5y4b{9zjCjKf$6QM1qym5(ts>}+8>!xty*|T7= zlhE>XO4qIJ<}b95>qDPXXY(ELZAP;fZ4;5l=m=I|$3(`m_2EORuF-0#K-ODjcpfK_m@*WWH#%QkyQ|(F$QVeGTYaR$`R{}U3ZWGA zo3QDR!T>Q;7k2hcn2%VP4ALI+V5-fWuOvxg&;r%rGP}6gldc0S&*vdzD2Cv}i+#-Z zD3NNfIye;S{X8A^k-}}cU)y1@xNQ`pVadrg5!~B3DOn?zQ*#I=7vaEyj;t6KW>{+pBaw6e^l+RGMY%kVN?9cP1C2bRBw{&cJRpS`$0!_IkJjh5vLJ4 z%SbULgFPYgr^t|kfxuKoR~RWt6?LE08XKV1hmuI2nvWTSjcO@QmY_aIdE4fWXtzJ3 z-5VhkTp=ZH@4(~_;afnZ_D3G3>?YMcO`kxUdid!qF6<3~gmV0G^3|>|qd#|-z1l4; zaQR2}iYz`YzQ>1j$To7oNjNoIbBF>NCR}!khrUFoB!9HLg+ou%;T9wFShR&ho)4>r z%#U9QawYMCY{oH?G#*k3*G?|%Dx*K{XwtHg7>gzpkEFv(rqhYP7R1a=DqJinC#y`w zE31^?<^NLA5kxAXZ=)5fE%^(*=~Sl6Q3BfxC++5^5=kLv{-x+ywZ==iLf)B9XVhZ8 zb(y`gtMr5x*+QVDI!u(m9_ms)?D^0Acj8j8*j?nev zL$p>z^b4YCSl#U52d_UC{X-!u>l?d`9USc!ufn@5XK-#EMP9|GFRgQVU);J8D69M? zM>of$dvT%Xk0Y27w&1?S*;EWO>t^=pB4+~onmDRq7234F2J7|GxLk#4D;wanVu^7y zRD)c{b_ib{2ZfMoqJw33N%1uPZ|=gsg?#^KCiZ_phW^>_{Qt-*|JOoN0@%uu?F!hM z&BoU5-aj(2C#PrU7nfJpH@A2H@l<~PMZuSE1X;IJ188qGqet!~ly`@%z!{XKWxAOj6rs>YnwtJzf+mA$-rV9|3-X3X7n?1*swbpi{fWv|v79 z6DXulKQY@s{kt1UC~s0zcK8{^BT4v(%0hM+`u1ZMi0s;p%;!BTL_bRO-jF|7*eiHO>sBVPD z{$pmO(?IA>+ULA=H`A3f`5@|d4^DKtXNEI)E~o@xo<|LoGS625_b7%*un8;9Qp7wy zf{p`?&}2uZ9Dgq^i4C(TC8>g=gRYq<`Ci^&0JN;YJbhlz=4~$_t`dZ$qp23omQYLl z(Bny_PZ@1lpsyi)!zhoO_4_<+wx&%oAc%SSkQ*Zeram#S$FN|(*IAQ(wrr1xFhU{s zhtIU3&!sZza@SZg8r-X{*fzH50ByT*@FS|aArf2dDiObxS@xlcl$CdWZ56d2K&Kw7 z9>7Ak61M&&4!ly^fWxop9n7bn9cXXH!y024O~d}A1bH$|khNN&Pf~vpcZW%#+y4ym z5FxU|k{34AsS854vchjX{=Uxn5w5_|t=1^TKFXu1%|5TBSs%Hmw~*|tVd^N*uyE2* z?!2Ps`nI=BY^B|}Dz+VoxrVg3=DI|CNWi_}k4DJ0{EbeBZRe+t9LFXiOh(i0hY2*m zy&4pJ=CbVVvR=EN$pv!Xif8-$D}_ut9=rDb6HdqQWf_!pna1lLBJ=y8mhpy@*%ynJ zK^u>~j={E8;a=!TF!71fQjcp6rb^E9nkXBu!(da}x~r-m7jLIsWD~sCJ0jZN&j;b1 zSdVG0AMX&;N@~V$lc~X-Z4arF_s^5K>#w_md>qyNJ_JBQ@cIDuv+fHI#8<*M%tLmr zP+Ond86v1N)9z)(D9;r<{AT7PCd3*hiD8m#$j|a=qI^65LKc0%ONmG`_(way`@@! z902Q}rw<$)HB`r_3p;#~oB7-}(l{a$Du+v)MlevwsZACpO3j!5mr0aJDgci}VURJl zKhl$q9B1~C9uDDJ*T<7sRY6opvIZqwH*aeZ<4MvxeHxU&PC^NNAh}`B3X;yIX;XS z7nM?u04Xl&&+9TrK4sUU^^GxR+cJx3AgR4Dx+*4XAstr2M0F&a+FAS>pYD;2)BXQKH2&qUx`FKy0}i%jcER=!kEBk{02lv5G$7#c zCI8{CqW^~ zYN>FAal4JNR93kr+{rcvOz6DdVm=H~$lw8e5b|H(YaOr$ ztexk(3^^+b}*T@nL!B9-3=lHDpZ{)6ruv#Fr22t%rHP%t_VDW-(b%W zP6#t(JA&4xXf@_#I%yLmF3nAVD8@*=XTqV36CELkq~VtUus>RlX9GS(B|#fVQN*j> zOBNuQJo{66F!wD@rr8eY9e8q298$pk9yuyVG2Rcw3i1I7Q3Z$a!W3mkNFR{Hg)@ex z<%S7c6z6GJSY(@Lw$7_8MZuVIvc9P2cso@kD^{w@O!YLOVZm73vAkZ6~2pM#MKh{B3 zZ}n|yea8Z8X^uPrYyE6{1Zx`~UIA@;Z*}A1y{ESW4^CrF^SZ%f z_9H(NweE*aa~PZkB!8^|=E=+u8w3mr+pm|Ubp>43JV(a?Yov?TE{irqh+NZJ5^pZm zkuT-0v*Bt4Ppcn3ScH#z{-%U}TUPMA)d$4Db*}xmIPIr-UcL(M&O+A=-c9@Fp(pSF zpA2lUw8uG*4tA}HDis01PS}>nxmx%|9Y%WE+2}5E+8JPL*Bu{x0DzBg>7xlp^ zpt2~*=G1+#I`$HL`a0sjaxkCJM47)#g&D>J(Q{$MP)pSKv56F61cVB%tYnuph*>y$xr3&`edm@*gSiLUrLUvo1M(=+Ii>Uv(E_lW z@`$MX3dAjh;?q~RsU(&}<^5(z^F2v%YKKO``(h(&0}N?tnnvKuSiD>Lb0J}laNlSy z$>7u}=Dle~LDY^`V}1E-FT1QxV(3XpvVYlhUB>agut^%+8gjinj%$`Xr1goKuogG7 zId%L@ua+{JTh)+p8<>UM!`FenUJ^&Tbfou0IQVvjrocWwn}N_|Oo1FWHHx9^0!{~u2@2>M7dDhuvI3; zS#t1(44TP?Sn*yj-PS8jOlLKHsXv*t5(VGZ@#&ni^)dpU#QE{rSvK=L4;)~G+`muu zz~IDX;dj;SWXEJzY@R-`nD{YpFcGf-YnvA+G?1Ih9`%l=ROp6ucAxnAL41V_Q~cW zQOCC|DD7b3&$l(bH?WTf9xR|YVN&8RlQ*a&P49z9J!0RdMd3Bek9Ix9KrksuOe^dL zJAEH;b84($;+D%TU&zqMH4m;d7<~a+B;qAlM$V=m5o{?6xvqdM7(!%%_Z_nEZ;(fm z(W2N($gvEhg?Z7HvLU@77#4GgKhPQ)5D8z*r63Za+<739XvCXIVpyYjqLa*dHMUbe zo1aV&EP}8P!oKsn@20c97kv%WzD_nY1P0MiTM4!mO-B2B8yiLizt8*UpkC9M=0pke zgv)!+2+;_#=bk^o%tr<|=ELp+e; zEA&Cgz<%#P`P_wsLVMsj0O0!%CYL2B(GZ4!uP7+CKr_C@KVG&H#5NfZ_iy5AAc=jf*I?w5* z?z4L-)MnK$v**s=o0%t?+y`uTSaXdw?P)i*xMm)4E$LB}uWuq%o*}D*h*UZ9N5E@4 z&)VlMH12*7s-G$B%7kY%>nFMr_8g3pNw zW7+{lozq;dw{Cv{L;elXv0?an-aAT2e^$nI!FxLhaVUL#Pfyh5R->mIb${>RBXG6G zN%cInjlSu{zn^*G{(RCq>pg!NM^y22+q=;IwzvK59{j~o=jt_>^DXiRaGF%_7T_jS zI(Ff6Z=UsoP+jOtNtDlCoHA5QaQBP3oiD!V=JzgFzZGX@&7_;;PW33}-YulAb$03TBNLv=n-Lxp7z?GMx zmI2pCiFz+_f?c3!S~_a_p;&?ORlvYgJeVKRqTO- z$QX5xG+BcBp-65Q)KFdi9Slba0iF@R$mCK(;+O9|62cBqv2A(K-wdQgg|DLHcA;Sz zn%b#@9EfrwvZ$(Iq~-1}{86~`ZCIN}0FrloCnfy$Y5G=~5fe&i;j}f!9AF2PaFV@M;T z2?3<6Mu=Z?*`ETY9p@c$vHsxDJPgzP{&k&H9YHNMiRmk!gOM|@RXp&^{-=wHQh}R{ z{x_Ad*|e5QaE!BJ)aw^BKvhj`OnoC{ zb4qo4M^aZ$Z&UxDzMHkA`Wly7Z-|O(`_sQx1bmUa0-Ynk1ME{GprZrTR z{jbNB7~46c>VN1P+#rZpBn-b<6etz@Qx;ALM~p&-no*ZGlqL>#JVn~(cq()j><9k0 z-;6L8{zVG8?9toGwEo4ih0Ix?cwB!A$x@~&m$_xX6R}FVE>(9-x$hp z28=V)HB<|(n!9(sbBS8_+*5Rqp@?MSF`qZ<{T9hhW;w@~SWeaGoGvElo7rs8MKyP7 z1vcG6ceBMI__ zjjl|Df`LyT*F}(WF8BQlLf!;frtpw4+FS`z5c7>$-srqQVraM#EF4L2LXpjYChey0 zK?pXBsLW6?+`tgZE;SO{B#i(Awo~6E!f=YFBK?T3nI$L%4ei5u2Zf zy|G#2%?jzt9YCrG6PsSsG|tyyU>thBq#0rm=`vZQ%l*{h9}Jpj1EjcP*qD4*v}3dU z==-Cd6ePhX!<1MLY4eb%iC7&#{pSIeI&S?Pzg9$txA`rKeN5WH{nFE)kxiG}w^{RK>3f$t$E(D3&I2Bzh< zkXoHydduU&k#|!+H8%;D9HB37WfWHq9XFm7ADpLLnHaj)9lqH$ty%9dJi$P1HVFw^zP51FfYxp|=+za&FGxL2vW>ov%{nzdi8u?q{f)ubVGCEHsG$ z?pS{B+L2xu{6vr^COim&OtcSiA+O--tgtPS0USWx%B;M02-P2uKFurp3ZflPisuZh zkZUk(Fe3QkHbGO&7~m|#q+h+sWQ9HTp}b5*ZHZ$vh~f#*MGm8>dMrb*s7b$mbocd0 z3IM`kSF>)N+z?iQiULaH#P1`LMQntW)<7^)yvia`L`Gte(Q6FOiTXE~?P@3O)t&d# zB0v|rBA#jl5RWRFNW`XE&ew{J=m~mIT{Ob_dq55rk(-2!>ZxBceiVd&niRNJ4bX9J z1M%%}SpBKeb67+h7umf)qyJ}^fe|qSl(Eb_EOTO^=i0{?NBYCP>nI0y3KkA?0iDwt zJi*V{h_U;aDjZa@;;A;rpJMTbE2Eh38v;(g$8o87v9$S9SQ{YNM2+=L@`k!8{qho* zsUR!qH90__JxJaLE|B+jMDE+x5h8G3ChMY&N)+LkQERz2l~}*%P88!qAwhC32}7Vr zj74=?(4;P#Ro_hF4UJF-K_U-#53qyHJQI_JkrxjcCFLrTpJ1|?+q<;|u#)cc-e*sx zm!pwtd{V-Y2Nv3i5dBpAsg&Kpl9(QF^zBcR@*vIMViIE$h~wKi7-i?&9DWO|S~r#A z8RgRN`CD?Mzm&ytI7-OAqN%O$Qh-3tmd0-us=c(n&DZE9fo*i!2d;{xBN*Tw`Qz-l zDRaGo#MMfBrE176Gs#E|;7oh+QmAx`qr$|sk4vY9d?!na_x0g_)@aRTUMdm?tP9nR z&kP{Ka~6c}3u^)yq^_H^{zdOz|Q zd^BoEk3IhcgGDn0QVHz8V7prnR5Ju4$QXcfzYBifFoY8Di_NRxmCaGxPM@Obo`ef^Zzn?>H`Gl zg91Z<(-A=p5sd~(VQ`>5Gxqm}@zJS_$0HZM3rC@Gy+XgnO-ZH5$Q6jCDifhr(@WRR#K!~%4hQU!$Oy_o<4>D_Zs--lf?1~?K<(T%MBQ+%e*^wZ3t`6w_B-A zI2@;w;=R{dy>UI8BKsO@>CkW~c*qL0sG z13`cdvI75ymgH4iLD{u_xf|bceI#OL!J>$8Ccps#l|6?_6rFk-Q8b72Z~-g1wS{PG z?lq=d0>cf!)QY81Gc$$@-l-&U3DL_KQQ_t_E+q*`$t>a=RkH-Xs&<^f2;MhSBtt5G z{Se8r7d0VW<)xl1g;#srG>wS8(m0DXX+1ELZQ9C=%Z9tMJXZHb%RGnIR?0ALe;?|w zFqf~hBrfS=o;-IIm3p`=#2v~CC~y&AT_jDPMU|049Q8Mcq`XdD4i~RY4I6(VvQdj& z*LhkUE!=Mt97|j^S2vQCRa5;v79U+%7Q5I9*Vqe=ZC5eC&sY<>3e1yGE+M%I*G_MQ zlUqCWK}gSerj9ezI-`$W`Qsc~v<~j>;-V&Jn_LvTr?>8MrmqIvwvM+3w!jeuI3Xr_ z5QNe9E*pVCcX9Ym5LYym$qE*9jLz!|WSpAJ)(H#~p8^+>Ttau(nDl3?&=f*^df_x~ ziX-5dwPwY{QH^5j_zKaF3r0xJxj4fxIRR80?B*Oe=1o4VdlP`D*^hG& ze}Co!l{Ussfr8W7!JFStf69;X0CNgcHQnv6prf}TywsB@3eT4s5Kp{73vIJPj~|h+ zPA`2b2p;S^G_d~KEeie*uT%64K(8O{bPS=kg%Ppn7>G+jIZ480T39-TX06(N75aMBIHh8HNs-#j7%P43aXQXuRMKhmh zbs4!L5aU&qL`JNB8Q`}Etnq2>2m5B(?4X5|9#(U%BC0;C56hIZAsKc(E(H6*Btm%V z0XNNaSvz(mBSBqBZmD{CFx2Fn2gdTNES5Q>Wt8meVG2ITj3oaRJFY8I%-fan`rwTT z&~Mf=;TG_3rihPo9>|tc5h-HkT*_s))h|mVg_8xph2#u!IY|iylEtY)Reb^=Trh3u ziNrEickS$RIX!EY3~SLclmaVcJVMpyV^m<|9#e&wtd310w_;v0YE_<-<#t)L7@6&J zDgBgXA?1Wh)cp%J8bRiIa&s-c++&TFjUh?{|%y)cZTaBH? z%f?2Of3n#O8!abCqWbxyBFL|n8`p+vooo2p4)pOlk6d?}d+*owB)J>=^v}(E{m7o- zxH_K&AMN)}4&^GQTfe^S-J2VZ#M;H%fOj8aAOuVmKc>5&2_3_4`n6a`rMnO;S}Z65 zO(FC=#xNG%{VT_}!P)ov@PDzC|Hs?hm4OZQ?^ydl0~Eo4mKKzQ6#+`hD)OspKM~|HrKa9w)XaS5C4&6aX7g2xxVqbyZ^sC zOL~GZb7!0af3J)nU_sc@z78Ia!4pZaXB#~ng{SZtcKTK_na^Zmo8HVvJp#}Dot%{+ zy+bPIA;oP-`7Q{LlriNUn8mQ&EPhoY7ey}@qS>re!)kY)U7!K4*B2Y-&}|yl0yofY zHL4L}(8F}NT$Y7FyWar!R4>0g>i`&I0FmF;sgo;r(8EBe4CK0=j#WKWgfgQsYSnrJ z$xuF{vL;N2jm03Fj6H5ufvedp{wH0S^epkP1~8F)hA%KHtqwn9E3(^e8_Gg<%QSQ9 zj`0Q^F75SyaG&BXWXeU@Equ7(t;^W$#yx&GA@6I%m)|V%TA`g|)SU7!^;o0dqfJv7 ze19H)ep3pDZ~F7Cdte%a%xV+_oCXmRN_|jqBDqatzG)hx#Cjlwm1n3Pr;S7erHE2`wAzFaSrUC7{kzl7MkUCmo9LFe5J7vN02q zCZeN4_5Xk&>j0R_z*`ALV>ntBrxfW@B&I?et`~=38t)y07>1wkW(;x}nmcH#*PAC= ziO-V*jKM(>OkLQ$%<}MBCbWeDfUyPB6lWzZVSMnV6^jCys|IpuM6I!NrbavuQI#84 zPPwI|p{#!t^`6UDisgBmRLS3qoCMTW0biGtjvPZeaR;kYsf#aYl4Hwz_jD)rSS1MPiuc zCznF(Q4f7=IZMjh8A|t`3h-8j&RdD5{B$134jFx= zO`V_qE|*Y!5I$RMhkgTI<37|B#)E&SiA~!Tte(}73;a8&CIN%@WF%SzmfK2<@6sLl zGOp}*D;iY)l*29tlCL!hzn+ivCIsPUkInqIFNmaVy--h(uQ(v3wifc=a3Fw`aRppW zt`ypOVwBi*5I<+3OFx+qv?Ia2a0<2;yLn)er-FIpNZc-|J62TE0*JdYfe6$2P@*jW z9NwxR;$%Gt59~Jd`Kt&#=#Nmnn0=V|3gO@|;)wJjeF!3Fku4!78Raj0@NXl{4ixT5 zpG+Sk1hcb|2Q#MFk559ZpO)n;!SckKQ-WAT{lkE&g=jI=WE=&GQJ%>kah|}3I3&s= z0w)bJKCyVh(C6HO@&)mZv_$v_q>}t)PLXlEr06u2;~~RL$tke~Tb*g$Y}UxZDqC1f zvXz2#`i%j}wnW%CgX5a5{l2J`r9|l&<6jdAFLRQ zHT&yX>p-T94e5)rk@Q06!4OCV$sp_GFb+`#@Jw@r2c*OdAc{qgJ&h^9e9Z|rq2v>l zl0jB{139AJnWYX?@)BrIIUwGrm_{E{B4cA+Xtfjt>dSh1lO??3M&xn!H1KLKxx;ezi;-=H zVjV?jRJkwv6`M7aqwX7&qHKZ8*@Anu(-Pxz!A;MLkw?w@n@T_pK3H*JmV{mEgfsDM z$YL0g3eu<=$>=~iKZ7>i$(w!xX=w2H@N9USH3K8w*b8(`?0^4Rq3TqkSIqp}I4*N1 zzh;$6*4^aWO(W~_S*Ld+xzPI=sKIv7V^26GlUXGn*k<5r@00zpGr_*v`Iy@8wU;gX zexecg+2SA_A-#5wEZ$k#Vtd&>g$|0*-U{+pQ}Ap<4>c{V1iDfkw0UU=CxSVIoOkyD z{Iy?kpfM~;>f{mAwGJ24J`@Z_RUjODu%V{eOUUmO2gj9tW}7fTc~hUDg?or+(Kt5v z-VhTv-GczgoRE9zPtLp=p~Ar$<XfJz<3L zobi-p$Poja5YMfHxUt{lo^PG3SbNP0i!^2e;aOl+W(v}M>k zt@>GC(b!bh(puEsk=xasQPA6$JdiWgKQfj9Iz2daKB&a>0)D0Zub?i!xn4@-|NQ_M8Y@pq%%g3hS72R%DCx+G}yhE()9w> znkD}Vx`91lnL{g5NM2E1y|t#UW$0@~_F<11G1S@A58@HO-lp=tZ5L6NPA zGdgbsAPBBN4D?8a9EzfEdMWnCKaNJeP z5K7vLYM+-?M6WL~JwAR7OvY5@%1eP@Q#($L^(r?D6t3MP12qiKT*?B=i8RPU!YVU1T;ATD9Uykl6ZCQ026^&oYDO^wKx7(l{RGl!0ol>*($C$bzty4LS zy8inywB)RMbkN%BC!6ThRSFuP4sBHd@uzjm6!PdEi=%U;Xfu4GlyXOvc91>D1vgJk z(6#zKJ;;5Ys&!hd{e7+@-L=opu4nBiv;LOF&7bJs_%(~Yt7u!p{m@4-cL|SD)1V{Z z3{o_sI@aBwW9S0B4#Qp>I*k3Qd9debaOvw7!ItJoEULgRpP&;O2RV$BC%~mFy?in6 zEO|nY{Y_)yA-YYd9427*Q;MQ-M+?vjMlEx!9Eq&(Ix^SHeQH0i?tbZ6^fawA!<;v- z5`QALYN{mnFm3w&`ppLC;!*0c#r@PnvO<|3!(kjyt{b{neGNC{M2m6y29uZ%w{`SQ zue#%I;YKjvxf4op|E`ydDkt{>qoTZ_()p zIw2tb`HotW&^&%k^77}p!$14}17(?D?RWI0Iv|Qn@Z$}^)j=iu&3>%X5{%3jf>iHn zFFgpn=pyKYWaGqksS^xd5g1(;6TA}a=fe;1K zFG9HOa1qS#Sa}lDd?=%IL6P@6tFPcaL>iZF41dP3Dkx%5cTaR`?9<3knys5}?v)`5 zXTk`bBV#C4Ofg#Kdk+KFVstZ%QSu!{P(#>a|M_;Hu@R;CABV_TK^5YkxpE19s(X)} zNfHD%PI2v1nHZ%by!_nCkvLC!z{%nh%>2&LGNOdY&!(e1jgA~)x+Q?ZLrF66MwUX> zBFY4{Nm%FGlvF7*5~(O=6<~=URnx~){1ZYoYR;(|-K01&kW*uO&S~Q*cnlUKGG}1S z5v`!d1U&DuGU9(vaYv+#5>e$g%8^-{(+Bhx8565t%ITA&7EB&4v!**tddDe;abGA_99Gg2uVg7H z%ywn~Yw7{1EF|IUtFvBy?}kKcK;@pUiDH`fLK)Yy6tuK8e5JK=4edz=CZarR@W#A8 zQe-9dyR|qPwYqttTe-O$rnW+ndT}F~jL9!cEeyw%D*2J{L{gNT0!rE1ro=jYKPs;cwP>{EuhCo8p6CF9JQ+pb>#YsL*A-3%F`C)b z=^emtw60iG+ZuRnonmp6l>Tn5n?=nnaEuJw6*!Cce_Fe%;p`+JPz^w%Jy4Fe3%nOT z=YGT2MZ!5c)J&f4-Xz_10B+2JF$nj*Mj>;--L8WTSh~UcFw(%n&B0-OmD6Xfd?DRy zEYEq2!1|Ca3G_)V`6|iazh8$RKN-Q)b9CO8F;YW`=6iZsbl>sEMxth%2Hkb*@ekEA zNKX{>lxjHf9bU&HWpCpQsOi6|pohijZ^FxIwSWlLC(@2BLr*mi(ABj7V*?M#Exv|? zj}kLRe~jL?u6hc8czT+c19E39EU3n?V6SA1_-QPgRVRZTiq!(d)|^=L0Q z#Xo>RqMk9Ia(Cv$C(}%PU8YK7oA%JVLkfPKtC(c1qa?O8TIDK3@pS!~-(jmOk0Yno z<5^u7XKfo>vw-sLTH7aoX`jelQuv7j=E(oreAsjC@r^kBfbUUtX?Kg6#Z0*itHcA6boaxG9)AkY#KCE05EIj^8QDCg-3S?``Zq5gL>V9g`Zf z4{2Rr$29+5G!6Ivt>ODmh5ElZi;7Cy(>uFTdwTy#)8GP3j3xZV=Eu*>{UeZ2*$=nA znw5jNx#hYCeYo#;eByIQoU5Iv zaF7C)jng->Y`rz|ue0cB6!2{#&WIzzcK3z^IRQ%{gDvG1R60pSPc!U$Zbm-C!0zDw z7n@H$kZ0!!JVNYhnN}oTNhn8cMzuu#1kUZ_{Zy`6rB;sK9*q{R0&UP03`rAIvj%TY zRKmAu6u1e7GNAqY+>lNO+#aI;nA5#(rPKAcXuM0qG_oRyha6qENF#7e9_iccYmn(^ z1ea7L&4^3Tv@cr^5)*IV34r1*!h=ay@MN-_p_XrW{oxw5+=x*Rp1R6vTidR7yR-cH zY&YMb0!yK|#SS$yp)^lEw(xX1u^=bQF#qoDj<(q~wt|>*|8flD`;#)@8m=q4GNQAou8 zYGD|(spWDwIQN;60UMLAvupGpeMB0#POGvdxrQJ~OfqP4#v`c|C6|;tbWeO#Mv8 zJg)-|y}D6y{_Y+&Aj+9`FM~8!aVek-qm|@xeINV9(^Q5$M3t*w|4H z3Xnv3!3thce=SQRha{_uuusyJN(k{_>*5Odc1`Lkol5QUV6IMWlA4Vt&njRA`#VCn z-~;a?o=wg4jQnquG;EZJFGe177TA_(T7&+V-F1r4h#;GeXKoiYre;m3j z11O|Hv18@u3ylLf(kD*?$bh_VZO@8r_f0P;1n+et{g|$k`2?-RT2`@g@k1!>Da~Uy z>gVNs1iOaxF$<3b?9ZX?!Rep{hUt(p}PfmmV55@a7&reoLNEUOj{ zwZLn`=;JFW0)986l zyUXo;Hivuj9J=0_6>6F=XlC2);5|oD?b+&ZUR|W6^z-w(d5r9!GB> zp;CAaO(7ujVT^YcQ9QU?hA5P}Xd&{jv#U@Q4IKbZM?oDltEi_HqzCA%oQKV~9xYG5(K~f*04bGVa7V8D-RJ zCcIU3rYiXq{pU&&y>m^O3*0z(vusPS3os%`MQBK=B01A?)XIFlu-8zGZpSHBHorNmA^IbY}u$9WR8gJsc4r%fmG@TZXNZX_-;QVpE0I9Oo>L+7qa51abwAo>CZ$q!=zqA0y#39 zQaRf8wO^CvHk{&X{rsV&haTXlg5`U#H!3&+%una0v;~Z*aMu7ze->6tlMnCyM$(*X z9j=zBmkYWM@~0-&)#}0M%y`d@IL%QfPE!*m8!*Yr?_lNhl|+8K2CV7Mv{J*f285H@ zM>0N@kd11%ed94|93PlvbJ0O;0b0rG-k;-BCB);S*(zprT6%D`=W=8F-Dw0KRDhOx zj0CYa&n5o^fi4$Fse`fTVDBXR^3};^fWl)@!v!L_z zN%V&0#@7Sj9SJ|4%-!f1jyx!Sz$;VEHul=9!Ux{@yn7j$EMK9hQ+c?$+Owt&o80r{ZhaCUBe&^RtLsSO~5x%n5rW8Q=+bD8YV8-SCqZ^2W zpnaYLpCaoOH&%*4hS{47$)0EXOpzc?;;weLYHsV0?bc+O4jfSRx^ZDhU_qdwd@bs? zwPwK1{m1w>SDVhtgghSSHXrj%dwJV_Y#mS40$zoWxa!Kpy2~a6!y9D3 zjg5nk%80^!KLuV}Y1sKMJ|`qXKz0)XhA|99`)AM&kl-?!@H2lDd1lILrO_h%QY?=KDSw+Nuy zv4FA&#Al4ayjM!u^1$jgb&=D+wbKB5jX-3~fHt!r3{F9+!XO;az$u78oN><@ieM7X zATrNj?37??PT|UxKsrq#h72F3GcK01Ahz)!l=MKZb`KuQV7{}E+My7k3V))Y5HU+e zB+bxS*HF>%(2EFvMNK{t$WRr`Ff#Wr?e;L;wJ`m+Fhk66W6p3>&G4`Ef5&^^zjoX4 z|EDRE3+QOe>;QCS^z{7$#s5zXoNMb$^xS;p;*!(AO2pcF*ydK=&Ti2DLBP?m!70|S zGm{I%pz^KB3)D2tWcc)3<9XeM3n= zV1d~B{&Jce11FN0rM8M7l3}7Z2#%s!0_#Y=lU#XnQaOdp;W2vBl>)X@q!mxlma0mD zUMf>8md^F2Gz%$LjnFg;WV1=ErS4h86nqiWXuunXXS_tIg=w*k>dcjCtJ`Kayp^7) z#(>`K)tCi7A@Zz`9}GvK(VuP~+8q_c7g?!tdH@B=z%xX53_1ZH#^g=ktl??`Te#e4 z75p9N3bKl(xvDZF+{(YkK-!czvia*|w+!yUz0gO@VW&TU1b3&XJ^HXQi6x&LhCcLM zt)N<-{-^i)>WR-kCi3d?DyC#d#d7sAlxDIRw85R*vms{TU={y&lnAVSD2rruzvnS(#@N#9LC zg-vb}Sv`t0YWk{{=D;M6d6=*iJ4B#>$jo)o~UNsb7j5Hz5 z<;MqCb%Uax=Ng-7^HVL^JCPLmmB2!Fwkw_3=)Q-{^W{*d%6GM$(7Z6wmA7e#x1f*6 zmw`P+cgYM;pPf8ceP3bi2JO(Wu|{q9nimc|P$C_UrN@61?|_j>WC0=5PtleLILR>m znS@PKI(a0Iij4ylOP^IE>yguTQzTC~LX#_&F^`RiA@dG(ti^|q@C+_F^o3~DzWR+q zV~MUqGAP>#{a6Y(Zo_I_lP+AE-`qpXO7493)4*YIAnPJN*Q|opGCeKxGE=A=u%ZIVf*+bC2y#)24Qqtir>D2Q{O*g#_NR=ZXrFJGV64d zPR0G{uXd)1{7+8;bohlYl4(%8PU~U-JeLraH|6KJTlguv#PxRW>irRfycf*he~k0T zlC58_Mj!pF1MD$=^WK2U1aLoF1Z@Af(X}?XPEuC^`vVQ`9kBdPUGm+kdR4yH`^;0R zzya_|Pxn=Qfyk5j1IC%G`Z31#74=j6GX#1LT%9qc=chjcZT1?zIuGaroaj^a1aK32 zH^?LeFla2~9AKQ;iwja0B$g0Lsj^P&ji00UIZ0uZWW}s5bEskH}UM z-eq(M@{Q3%Ft$K8oDz5iSIJgtdJj3(vQD8Ekx*z_DE9j%X{1F~{&M*#&2%8WXZp)d>k<+GNCOLV{2_+OVMvRh~lE!63a~ace7yarp zUtl57FCsSTRH;Dg zO~mIlGXiXcnYM$(1vG&sLgi5-Z9s~JrKXkwFYDiBo}P>O{mW!*G2#?Rnyv-blN69_ z+=$V^Pe2666fjJkEJ?&A3X6=CBlR2;$)m~?%yfeC9zZHN(x_lOY+%A7hzYp4%Ur%# zWo+Tl!9~dD6*@9iGS36c2%Kor7^Q)#rR_@cRj8%OAaJB3=*!AiO_fH!&p}2v+T(M6 z{pB@Qf~`?=b+D%tQyfP&=>GTx6WLTe6{|{wj)*rUE>XJ&QKiN^!YJdrmn{R-h=M zQkF3#X?`V-V;j{zwPe%XkIJM1Zp1+dNB8G9JO*GyPfPfR%(^?HQh7~J(nJ#elB;mAa)N7ci$O z(VPuP=L`e#7fj19pA=kWi?0++~SieqZ|}2ut|I-1UP?4p7f2x5GtLfceuC{ih|$g65(XYI7m& zjEStr-iX&9X3*s?WX1H1*b?)o%I)lNB^>R=>QQ*h@Ab&sE(M zB8h2OTm540x=MKHiU_+?J_)@JHxHnh+P`5Q9+Zc!V z#734qba=!b?#1&Y2*N*iZf@N;%x%Wqr``6P>pE!N>VU!ed*}hjUk7lkZ-E;e%7Xc) z+Y$2a4}kX%5yju=%H|xz{aF}c%Cm~!94^Dpcl|H+?SC)se3}1U;!r4nf1v*X|BC+q zKlXP28i&HnM+6;*83!Hq9z~d%oS5;PgI|DNTaH=T4BOrb+50EjCva}#{8!rg()CUD z-SmSe(EF?ZJJ6@!??1ndDDL0~g5BVWbDH4S+ruoekv$<7Vnw6Tk^@yNgZ}RA$Z-y> z?%tH7BzqPNKe8uS!33g16fWp&8Yp{fvAVsiss2R52Xcf>8L1?jgC-3yW2E}!Xt z^%?_xhW&UI-XGuqvrvxB7?DCTD=p;RYVSWp{&9KFrt>~zhMYMkZ@#r2OrD*>5khD8 z!D<0nd8w{FlNEfqieRjh7uV{3u*6*dk#^4AuCXy>gpokR>lMDqEKK4-kK+k@-cu

|UU=^t694#z8s9L*;pV09XC(x8vcx#n9Vl;b?GqfA#&THnt7>(c_VC z&-?o{F9_mbEGHPqeq|R9jC-}f4Xysv5Jr-Yj=d!PYy)sY4Oc-uC8~JEw4jhb^ zn{f~^K+Dn}w@T=82w*>u6tQH;iCm1OTB#^bfPET2`~k8ID1i~C7c7bHqs$}$;?aID z_Ml5cECp6s^o&VErqs%ZVT?vs%>dpLKGBuUTNlo9mFh3cmQ^++59FNhSOxW1R6dPI zLW~xU!u5>;`r!%O5?F{J_+gwrqUddwi^0f!k`E@i5m@e|wXqTIomUZ5)=CIgNe&c5 zO0A(gx(cXjsfZ@6{%DuJfG~rjJdTY^imDdqEStY{hMmWTDf@hq(a)hkgyG$30m<`s$T}1-z&*{^Ti1O=tiY~e!^oJf^@j;Xw==f7 z3KbTU&XAt?t}*#~>k43U8*JZ>ov^%}>DIe-&j9B4U)Q)-xo_|RwvNwx%MY3XE;5?pkopEOH@ zZ@e6meO*&*R>*pY8M8=PDft=yI`ww%}}7I4%pFVu$7uR zGNC=Kf?+W85em-R^Hc33$VWE8vore085*r&5A{MUD;huHOvB;S4{h_#1#)*2e0^xN zfL$n1+3F>++rsErJ!nq%>S?%xk;U@^)s2ng8b zSoTK7GU8hYnQrY?;P!JvYAeO7mKWxbRX(s&%tuE!oNhcRsHBG@{#hYezA5H&Mh$*LqUEYDjx*3i1A^le| zLd~3prbxtPEhYMp8l&6^I|j)nDGl|*JcB^!1V@1?KaPzql~(D*AcKoKS`vkL)fAte zr$fdPn}~G_wT$Dib;g(;RQ0E8EEi3%yv~bN?%K3AHx*=FcR`uOUg)Xx6<5Cf??u}E z6bJ#b(>V*!W;|9NO3(+XnKDwO&^(tjC7Pa6q+*|aXp~W1fV-Lc90ZGAv4; zI6p=M-PlWZWb)M**2k!w}Z1B7Jb$4?~2=qiGCEe$QgcyGx6`M0@o-5@vCBXzd*~M)M~ZfyQ+f530S<3Iwf{ zeq!rmr+q>mzaj0E+^j-ry%Tb@Hh60Ph{B;m8F1FPpm=HY!0mzK!0w#Ye%-%jRK zRz$vB1H@DPLguxymUr%}El`d5J#WT-$78JJ{6?MV@iNz-)5#mK{mgbnSAZrD! z$vtg^#f%}NcFsQfGoC8o>s)!RRU^EXH4f>Vr@emvmSnHmQ{dBlY0HB&%m<5%tLLCf(r)wk;8 zI`_4%z|?`ORQLG%{_BuK-GI4O58oA;0{2Wz;l4Cc-_-|&?_6BNZjLYOwlb#qLN?+f zux4kx)&lS12iU{vz#o%3od+q#ke8(6M?W)=A=?M8 ztmCtY95J1o(8QI>=&}Nwe$gpJAvpx~@R8CjqTIE3&Cb`{2Q)%R#wMk_*088aDx% zY%zN^ib1CtAR;mL(N%YP%|F|!;Aq$HgO}1x9ExYwTF=)A|IqLGt+`o^_iLaq`SWx* z6HNyY1mu-CTbz=NDkm8J=CnuHXcIWw@#T)bJ3teau;&lGd-^~%a3Iia(|*HP36R*v z=ktI0J_dut@w?c5B>+2;;utjk6O~RF2qHdT;EcdO9>#u4Xad6h07;_H54?V4 z!kT7S3@yQ&Xv&DiTxk}hU=OvQj&8120>!87SW2n(XN@c!I2g(}lqrR4AhWRKyd<5a z_nbTkM;0nL2YG&7Diyxs+$_ZhAE+XeE=ibD#-owSst8*BnS>2wB?VV#lg9&TT15 z4kSbKI(NA}=ryTEF3iqqW1BlLLblkGKD%I> z`>_Y?OQ&%t4cvzmtS-yRE<~BD#_?fd-Rg<4-bukpp1SG#Y32kRr@5EK>5Wcq_lw&$ zrf=BBIR+iwYfE*snQ9tZoEp{%O%}boB{ih&q6K)B&#OfZ8@ZP?#Y1Yg@D|k>w{^#C znr79BI=+1}`z2hCdAUd4YmkeL9+qDrw|?xqI&;?py;JTmRrG2E^j<3hE_|#E-xfQ$ zQb#GTcJ8Ob+VUKAFsA(NNskKGEBvJby#5Iz=HeR6*vE;xSwe(xXJa=YhB z7KnR4_vrI}yL#2{eVS%b5O{eJaarD67BTSn1CI3KWa-}UmcIjxDUf%q;0wX4&w|Ry zcgt39?z;#$1g~#({GtzFARz>WZ6^ZVI0%8Q$(dmc?|~F%z@cp3+YyCqM^94>{uNpH z1zOQQWi%JM;Ij{A(Jl;QJ0JEnPlRB$Hnh-y5ZPa_2frjS1pEgvVlVLk`MXPF1RVE1 zT$nThJpyx(SbZ-BIPd`UK3%xO%+a-LX-!}cVsMoWA(+|*5^oceo23yk;aUY6khwO- zK|dQFR5D3ep3!wT!jzz=b%c%=35-mxOrl#!a*sYLB$-E=?0coTaWRIXh>Yx8d}N?> z#3{96r|hd|M26+_GPymnm|SIZT!FjZF7roJ0(&W61JO&yFy1!Jmxx>~FiOT~=l(}8 zFBD7AxvbKnm{zVV2|5n59G=>eGWIYzvc|d`vR|_Ps_yE|GG@Fp^j;3=Qa@+@fxPF+ zRP3XwG@r;s5Y=&V&UVTX*iccsSFjw(XU!fel(j^N{0tdXOSu6w^tU*90}Bq6SxH_f z8*X(4IVsk!WAPDJTz%hV5+X5jPN|Irw_Mc1DE&MLre`)xWC+PSQj_R@-|H04c7 zC7TsDAY1BENovU*;7uIQ$5L6HFYL` zv~rV_2I0+hV^X6eyQgL!!>;gIQE7%~rPXD?otbjrXuvsMH<`hW>u~)&N{OZw%K0Uk zWH)Rq!jHC)q}l}JuV-}>4kQoGWZ-gKxTazK~Hl4<=@=YSy z4Ox=kEw9M#u#;pE2*f931yqebpsy33*~z35#Fl?@uYY#|!dW7aiO;y^PUdvg8NyNM z_R*QJv)`SbOtx%<>y)uO=&YaeRN92l2(lCu`B@@FYqOLsFh|%z@2Vwmtz~r#=Q$2b zDha|bm|s27mt>*pJakWZhN9Q(|FqBs+u2-NX92Uby@>kc+KOm|tY669H#yK;E?d!$ zs)yTioiknSx%0IC3WMxan~`;P;K_ZlL~O65zOnE0S>EU6=;4XEawEXXs2hDfJFq(w z7ZzM^?q^T1u(J>D)9T$7;;i4Sz4Y)P-1tGRIb0jJ;PmaWy4A}OaAIeU?bE$UnBEWm zyVi-gi)(U?{*_3|R{w`J&jrv$KtUAWi^xnUvZ4S44-qqLbdHMTASju>5n0 zjKh^FTMfI0=&R0pIcL zYg#&(oy+TK-XofciM0)r`%m&HCf5AfzP6}m{Arm@vwG*MI*1pol;7~y3~nfge*`$H7Ax8K8p5XuR>=BS~UOD~sRsHp6|0Ljp!^f1uANWne+udu4 z!uGdE;JkYP^qL>6Wgxt#lNLtM83ZyWr$6>uAlh5tMY;z;1@LXU6Umw1u|yC>J5YC9 z(DiCCetYmYMlii*z=g9S^SFDwQpkfx2uoTBDP*AFxVwlXNS{WiWJaiTd#LPMsQg=~ zB4(H}XPByHn7U_}QR07HL;nr`sQ(}A0@wP%xZ#nQvGLT&sfd}`u=$05NU^*Dn;1*$ z)|-Is%3X*3!`kD&9CgpDYxmnbgNH}w=NHGfce7JmAOPOgVcYO7cpwmH5{czV0eC3% z5>srO<3W8i`mNFQ`0zK81Sh^gClr-3(l9uPj5*f?Vd*3dEk?WVx(T@)J-dVTMCBvY zM4qWXFdB&~Wnl)iC$?I!Yv5w3WEOu|v@!KBa`m6|6IE((taW;RzT24UlbTUxm6BxH zFB96$cE#OsFlCf_RPMLJ6V+|w>%EG9fZd5b8IwE05go&lZmPWmHPa^eKj zrL(e>!ujJ(JeN&-4UYninz0{?qC(y=PxuRj!Kt)p8q#0;MCz>^6js1mnPC0vYSXKB-Wq)RgXBCZXQ*Z%Q zd;?^*V$%1B@P&;J#-j3heI@(lK!f83^Iyavzw~8Oe^%qQ^oo1nb$&agjAaLI&Sgwz zdSh2mS5JR+T6c9Y&Nage`@m&4yKt8o({JjNYsePjDTlhPj~It8pa>bc8g|84v;Jc< zo`exrM_KaGK5N*7G3LZA@^N6DAuAYi1VIKinx^@Osex^5v=+qbjQjpo)Gv`K7*bm2 zIar+)M=0Uqn7BE9fL~)GFb(gIC49wPRykD8wq>4lxR(Xe z8qVeo^>91-N#)a_rv&FyT^lKnrW}rb?ueRZF~6xVkKUm2nqR93IXy1hf=s=K`#r*R zOe^0h5qs@>i3(3T)B5KA1HZWa>|LO8O_gYboHV%ad3gH?Kl+A$y-U#mv zRg(oGu*ju_bVrTmDh&GLhfsuGA~hbX=DcD!e^#g?6fF|;nXQv>*)W1#tW^FgIj1n@ z$92ei@&1x@*-*A;EW_s|(TSsEUo=!hBMH_cofwo!E955+$^bK9+&VFtRymoJ2}Lw$qaMU*%`K+gBP~Q2H2J)&HXI zE!*nsvb5{X#@*fB-8CBt?iPYO1PGd7A+T|GcXxMp*8suY-Ce^&-BoW@>v6o_y8B05 z*IH}N^Be;hd2FmB{bGp#8jy>kqco*Qa$}WPQjW%C562;78yu6y2#e6&q8?8gzMt*o zmW3Lj9i%PbBQTHSU@{>2fzdCl8We{Km(QxrPo^acN@&lbMh1NuvD&DPNsggl6cM}puj!EtW6)-M0jH&YsCI|Z!uwucCH7mq2D!3JJ=XQ^q=79W{u&{VY zlNI&joKomP`+O$N6G0cgA6uuxMi+~l25gzzihMuI^toNqDnKRK_h$H*IKYKx!gTSBa>*i zWO1xzUcYLn(&n~6WqWS0r=_+s|A`TVt1~j-9G@1|Ze{%Owk&V0CWDpV#)Rr!It8DQ z(Z>{Q$!$F!sM?TR{4=XOL|i+jBLRZ#E3=UF$K~;it~y&&eH;3PlC`6|#`N?O`$j9V z^*5s2h7fATTof8f2%-5#E%~!A4$o}yb+)0xfC^%9DLpO$T7x>0>Bgk7eTAcHcU&HIf z*RJg%n%)th;xJU{*dqts==Djd+${O`RJ z(Ei7{RS?wQ5>inAAt7a4^^b(qU!u%Bh*gyCWw%v`^_ET7?cI)jv)L1mvvc>$tAE)) zkZ%4|!_z4vcl+3O`6~xq!1tn}5^@ADc;`rv!LmjS7rl=L1|x!*e6T1Tsgh!7zGsz1 zRdkQU@#-sD4ufdq33wGw{C)#GS=vDZVo#lxWJN zjHc|;f1=dyEZJ_>kkqQ?Zp^r?!Z`)_f93DP7Q6>)Hc}jEH-+N*=_jl`c|I~W!EE+$ zqCBe$_0VY#P!RoQ4rRyQf{TKP^^Iya*-!Q+_2}T!wm7Ix)KkS#)i$(lC}r)ez$3i0 znM_T*SxT1!+nF>{Ur_h_XtaaqvR=j$$#bpTCQq*<>`jxpgdWUhjSHhpW? zb5A~Ja5EwOMfXB`hF-_(cn&WD^>{k_9u5L{J)XT;Ww`)_--DDi6 zLvxrPCC^|;MP%(>l^+V(H8dJ!(lKQYYgduDN@FOn*q=_cv$&g)4n7RXM1doq{qa2I zb`bBKz+V*8#kT~L^Fg+SE;|R$9i{+P{?Uj&BL%`LN7uGQwirGD-lwRPqKGC>eJaGF zB#tMA2C|T5iV@V5!9OC~Nup8)teVD1Lwy@Wi7I0ry_-C#t(O?>t?Q0xK`hlUWX#WK zZs}phUX!KVZ%EKrsR-Ujcn3Qk_bjropL3wIHud~bJ;%6LOgZNo??7X#S)AjvM}$@T zG11LLrOU?k4716W=5CD1j)s|9%-nZKV0{dWpyT9#g5UYTI@rp=BsNT&u`)KqSEXAm z#5PEFo%Jw-)H`0XmRs9J+WN>Q#$cjc*BpjH%r#k&0Ol%$#{N1#O;(#)C!xBI#xbWZ zSp8l6^YX=akq?CIcOquE4hF^b>fUQQt}D>=^TC>ZjrD{? zbp0iTEMol|yX`c&Oc1vNyiGvQqPzL_Ez-34OW3C-hpni=u;#T_I{XIsLTi(j9f7=z z@uPI9egUy$LF^XEdfsX`_GYDTKddl*p$HB4pnCZppOjJKABmo$oSsXOu!w)3_=G47 zHJS)|y?r5z?BScG+w7=uOo!_+RQ@}~l$9@UQbc$A{E{U){Y*Q=OZXU{Y5 z=6d-{ArR0b0gk3HL_kWyfP}Y{T)YNA3T|~(h_Y!QkCMJXsdg`1me`}8bV2$0bi92* z<9zxd1&`<|Hjx)a%&2RK`0-k7JK8RQhp7k7iO!Gs${uK6oNZ2bBRyU*7AAxBMrzpq;P%B|V`c;6Lv%mUOMWOzTMkyImJmjoO4tZ~ zF4c&1KQo5n&!_Bcf^u&VUK@I3Ym5oi(}T~45Q(TLvOGkjcNtqqWjLh7CP^WTw1m5{ z2b9r{?F8&Flq|T{Cr2*U{UBX=y=_0GHB^VS&P}Lc>DLkX&Y8| zbJ9DGe=Pq4(#$CH9}K%5CSq1=emRph)u5`Cbq?&L0W6|eNX@VyYIIR~bIohoUr>9* zkK#BESGFkx%46KTQRA~VYUrzZd+6iE)C%#x8K=@Lgtr#u-St5#_wq&}>&bAQz^Ul$ znnK3wB5!YsIvki?2oP?|+c44&X6V65x5R#OT<98Qj^KhN9Y3$C8(tAEIn;imy4n;u zhk8n;crmX9*>s|QMGUI2g}hVrv>IJpZs)b7$WCoc1_~Pq4?2USl*UZ5_I06*!rq4< z1pZtav|`ctBQ|CUIkyhObgFuKQC!hkz0cfGhW=pj*Wj=kN!Gkg`5aC9mKn#Kky0+{ zV^{}-?CPG_(o+6X_!|Mm>b)5p+i@)YF9e_JCp0qIG=dC2ffo9Ia@6P~mmx3+0y-Yz z(Fdc;)V_Cp{zc-9o4tEz>6P{AcZ~*qF*Vq{b7`Sn-?^wG`q232q_+0YyANs$MS9H7 z3N`6GFg^K<4!1!K+a*0@%~7XicIm0&2X{U7A3cs_Z-Z7(p1!pn9aOkzXphZD@Vf5` zv$}nm>ahBde^4Wpa8DmjIsMd<&|#nC zw+WUX2KXlav%JggU%;dP;U_%~)L#i7sQ;YsvCI4inV{i6;s~?q2SbNPg2%=ke@*&N z|Ms1o`wNAi3)oom+W>6&?(DfO9J(Bzd_OynzPxg{xvfZeFgbX3fBka-Kw8+#fboS2 zChMzWGl~j`yW!Wx%-ZS`z=qV#i+v{(V4FjJ1l>qOn(`@O$S}wklbHrZGnkB|$-Kj| zQu&+|**@Ds%cqmM);z$^_$p^Ig=!xbslSs64By?G$#DnWd1^9jwJF}#bFezq6stG4 ze)BbA6FJa1&deV}(Uw~L$?LsWnpuuGnsjc8kUK!HbAU26HjNtBN{WhX7YL)&NO~?! zv}AKL_*huof#%PmdlOOpB@avj4$zZ%xTz63?zb3|6&hU;#5CMrDI4rChZUCD$Q4qc z;MRAa3G9JA&}d3W(|i{@KO;)bV;?s!p@*~IqDcw`mX8r?P}foZgx`~{^oGL5tw~-J z?mN^CcIZ!f5S)MQ>vZq}yY9Z-#eWj_4C{_h03Vs{uh<}=6-j!byjZ~bvGXOt_#;V6 zBl~b_1;GT|&^M9WqnyCXNa9Ct$2bSxSZqnHUCB$@<_A zsbZX6Eb=4g24xEDm7l!xeHmmeQZ0jyAc`GBfK~)0&Rr$+l?5$_Md=|)a=EH~Bce$J zS3TBP9kzh7!d4{2kJWDkM5WdYXLPAhwU!fjTltd>Jm5NM<

A`2^X}h82>{Q|Jlf zR@ri`G@bHDau(iI;4aGMS)*Ko6=LhBl~CJ?j*Hfla&jt!ur8$sYwzw(vJ<}^Y&N2> z-aU*l`Zjk0adumr?U3rMCq)mdOvqeIpT6Z8LC8L=td;N)jw&JV(UmSD-!Y8IlkoA} z?`;fS&lhRH3G@S-h)Fs$hT6z;z{E1|h`z&E$|u4`KTR9V;F682dmBv-85 zqG0pn+Y#>k>9h0pJhath5jQ&0Ae-WnQFk!lsi=C8(AmYghr;gaa)g*_o7@21LsEUh z*?h)(s0B&#JHI71ocH(-KuK_=ciS`i@_H$?ZAAh4gP3Fu*ZAV)M`hONTV5GfpSvIj zQtfLw8{3F`t8_rNik-IIT9=8dM-UlKL236YAdQaS#TP9^|@EXR#fD~HRUYe@uS$8N>pem1>y!D;(=HS!cNR{SA4&UA@Ub$P$#51S+T z%@ZP1DLKL+q%@DNzGF3QQ>DOm)x#SJm?s20$r2hleGyGR0t8!y z7jlr7+|QK2TUcp$whU@JJ79b&+|-~2Yh?LQGDcOTaMqoDEa#AkV2W~|E*tnx=^hVf z-~eAy7ow35k3FI9wdC8_QdA5fIAQ3tv2aDkqZ(sYhQ^SZKWfZS%lZ*$q2eNt8Guvb z9M1rh`=LHgVpJD@agrgQ3cY{9!Z*+T#y2hZp25f8^U}ka*1nKs= zuzZ3UZ$IYDOl{m209O<&?td%R0iHVIwp{g9SQ|gB+6UCNF_W>nkC&>~Ry1Z!{A6`q zZq<7fn338-HkLb;(<;8YF9QsnqYslCQeZ5!zxmtwD76>@cptjaBC7mo1{3ss-c*!*|+ARk0uPedQYK={zeUlEXw z*6EtMS-+VDi=}1o>YC@qX3F-C``*6m;nCNzQ;+it_p58e6S9Xp`6rUsXPG|^XmEcy z(Pq)*rOnC3*-=RU=0u|q1Kn^WM zREw5Jc}{x*HXh{v+oqpaFoG!!Z90s9K`cK0h-zL4Y{sl9Ok zjsT845JtI>Nt^lxj1`en$|k_A1qbpyO2_de<55y*B2ZAl%5hAaks0t%=er3yx>1FD z#ubYuMTE(qrV_hCU{gl<#9z6LMnP$rxW$)^$D zb{PJON#HfFUIVOxd9WnfQv1A0(g^kK&v3_j)D zpn)ptD#fnyrZyyd*H?GJPqTRA5J^JElZ#?~Q^q3Y5``0G7b~-=!Wp!lf;Wj4b2Eyv z%fl3hXPoNszB%{sFW!WK^AYbpP=*v5i-&fY??qJg3lfu9N8I%8)AF|qJ_Sjl>#+65 zNPxT$^OP~(zAE=)ha-fhL~Y?%Pxd1R!H}4($m4f6^yubQdwnO!MW?-zj7T;N|Ke-R zb*3g&GZd}&$uAf377khD4||le-z;$>UL3waPn2REK=2}oQW7BsBEqJxjIOvu+!M@$ zK1@Z)b2yA(@Ax(PMV?}JZa_VXBmTxG|6N5TqoTSM$C*&hz+xP%v?VvZ1N?JOD8zQDq$$u6AHxj%&Q>biV28iqGqcN zF7`}QA=sBMWNIE#gl)PGotH3LH{V2egXyN+UZI9=hnTK?XGZ&PJsxqM;5Mq12kmz=Nh2^Q|7U=h@6fHcZweLkNxO2+9!x9m?|GO$a;I z#UMcY$oD!{2S&``%}gD@Ifo=DvXCCtC zYvO!TEUS?u-*g07X>L|xOu#4~Z}`p_<#ry^J;wazHdocNg=0z#)LRu0@f?|j{}GR; zJ;>4D?U-NXJf1~wWTn-xQC027Ol^wFxY);#VBnQjX2NN`I4TfUYj?|}aq1^M)zhUa z!hMRUoH{j8;#{3qZ)Iul{9ap*Z(uQG)^xCzU$(kqEqguH_c_*H3kXZ^!4CTvi>SN9 zg)`rjiCws#6$&g+O$^a!uW)W0T|INZZ{0wybRCpiyGprlJ5Z=}pC4VjYq@W~cm@4a zF8aTTu}=b(la+^>1C?KlSXlCJa5Mk5wjx@F3>fP39Y7iajQETpPE5}JHIrUmSzY@p zOZk_PntS@t;rPVv?EEhyb!jdI#Phw3Of z!E{<&Xk9>xT8Ye!q+h!G?e3QrTI8D7sE6~7N*7wywMn-d>pslta`n4|+Jo}O=nsA( zh;MI!o3QJi$F~*+sDPynMbA^NJwz`Ibtx(53=p2TpOf-Jus@oiR-hof^Q1lruU=9H zF&PP5Z;)%;!e%gO1~vsO)7s`1B*_|kR|EwB}YmwBZr%P!eJqe{d>RUUL|o4Msr@IlSaP zI2N3yY60Lx+H_idRy-2?)ga?k84r#o5lum)4&4^SX zg+78+-u5E>Zjo8YMR9g;Ueggt-n1n{*~;(&LwT#u1w&r+kU%j`@1Kz1s?ZLVlk&GN zMIWX_Cng>0f+jHvM&fA^?d*z4hE$v4-x;#Q^;4eK)=jgTVl0G<+KVR*#Xzewyi*P` zTbknvm2=>|Z44{^GsEP0z)B7}Tm5;#6>Iyom0=l6FNwoNSCxcKU*F+?u>(3DZQAGn zCU;tQZx1*uYX~ojC~R2hn=bMwcasP57}t;u@;K)L(O8eHP1zNj5bY*s?JQI|-Utfj z&+q^?B;j&i`OXb4ew9|Xdj7EuCY)(X16giq?b815Bl?lCw+rmK;pU6GX{)CwpMGyU zqdENIY!tWpq)a(yxL+Q>-gx`!Y~y?V-DMO!zcaB`Pt7v5Wz&1wWM;vh;k@~#qOp3j zb8gAPy?^3r%Y9JF-{kK|5@_3kQ-n&@qQ91}@2;AFsPM!)_TE_8d)*;<#58)_+B{B_ z<9az#gE}9*yfn`injFex|SvGk+Pqm2DhM4y<5P#VE1?qUH%w*MmT1i|7 zJS(-5LcEl(Mj*fXeIRLfKD{=5V;e)vcoLe#3^Aevzr}U|1eLqO%pkqjwhdm6eltTl z`??CalCZKRK_Z{|_}+$Y@Pp_+AVyXBVeye8P@@SUCRF;P#E~MI1rp%abjhSxlOdNH z^d+C%KB0=!=;k;D2(M@i`c^`=5u`2|7h;Jc9Jdk4FD&sR?C1JiLTcR=IT$;g$ z#ZG(l^do|*i3nbjKj+~|d`+edH+hl8Xm1j?XHteze_10IkCK`>L5KROYlJXr=?&tk zj+mu1g+?m&VJwLVCp9#Ew{;+*x`tWi@$U#sgCotPJmX$gUQ+k^V`4qH=a@D~cNv}G&sCap(+9YT~Oj~A5 z^!VAVM?KXqRILS{w7BKFIn^LBUzQ6+@$wK1X|zcunPT!AwuC&wR#6? zs_CLIO%=!%hZ%Sx65_K6Idy>Cj?PfZpGz&pjT`re$n`` zls$bX*U(R)XAO?{3qm!Zlgg7u6 zBVAX$^?ZOM<}HEa-`s|bp-{>SGn{^3*)ntW=u$eFztddUm zgxVC?x!;OExGPo??GCe+6qbk-u*?!*mCoYvbvnZ{IwLODsHMzpJZUf^H)yU-fLo(0 zq>3yR7V^n>D+Al9FQ3dDG+{U5{GEt!lJN$&Jl6?w4+N8n=3!%$lq=*9YkbFOc%1gG zT)9H03#8m9tdYMRk(ASRNMby1**KQkv5J_Zz&( zK20$x)WAG^u;7c5V`_}Dgk=3unIEkf{JMs>#{-~NBNS?U51|Wz!wH4!mbqeJ*u|>RV%3) z!aD|;+7=Q-V0Ds>_+2NvhN9NPffr!a|$7vMbS1UsVq^+eZ78q_3$ z^|leLyi?l5Zz2g~hUw9FYu*$p>FOmnE$`4R6iY3pGnytN;jcwd-fIQO=DO-~)}Rsd z9>u9tVRBVq=k-qVcukq-qxUi!pM?Lsy{mWye>LC7aNbKkiD*vtN8z_Y^*@}x+J!OA ztzR4}$X61-OjI0Piq1R+<%-X_ zz{-4CIN$Jj@#!@f^6RqO61^XNBNXJ?F|iYQP|QF73Az7a z+w*b#*O{Ps);ijo;IG`OPQh0-_~$MjP&$^f<=qbzAiGPK5!VI&n@;zOKDsEj{3JHE zd^faCboa1)B_Z+57;O3-C?PxwjOd|^Al%e}ol@>c$tSNSmc)z~0t#4MPDK`0=7eam zw-P)7q26NjokxTrTv?Eu^KS6t6R}@}eOU^T7kL)4YE}eFQZ}K=)Sz$;APO0c z3M*P==-?F)jihX91#AL@#=*wirkeiYF&vhg8|U?HgQdov9G2_I3TygIg-WYif2POKuQ-=%%jgA1ElunNGS;g(gv}t0KdbrkDc^`eu zX(W8|)ovsvJs((uYYp7|D zh86ZVe#a6|StQNKC=R|}$3TR?%a)gZ(H+zX!DCynJ}kb~2ViVw4?n^P$Vh|7!W?1n zu)&hq_==G@TyW&X^zl$uut5y!_OSjllG&T8!7Su?M~F0hRtzv{9lw%!;-Qs>C*=j=e(#Z?$3RP)Sl^7*xn0#in&9JFT;i3DKe>bY7YdB{r>7a52}TxMCo-<^#$FfJ4c z0%}vBV)N}ubhcriPyp-zOK*;3qk)}tb!ep!gY=7%!o3`KrJ zW%^f}?}X9KS2%ecugu6y#yW*)yp287`4S)-9v*!%;%v+3;q~l%mmYgC;3J>82N5i zt=m`d8;lmBapVhD4IDvc(&=!ezkWBXD%ftlpgZixWQfE9kY($NrgC`$7$$?U0;YlT zsV(ne=#tq|t#FR8WbDDYP`&T(320~3`5Mqf&TaM_ZEuOSN*gnN;()Hh_s6A`HX)j{mg6FXPvV@2U_XKU(AjKy*d9}NxqtTi^AQ|liMEMvUpM{ zG<&s!JejKGUJxl2T!Y1MV z4MMC&&tr0GO35dZsfg72s@QkKFH2f_!v%Yydcr8FY91{B8t=gH3zEV^s~6z;PUq!qzw+hsx~B9;^wfrP{_9ZiMevjddH>DdVg6lzuvCB}f? zjttR)$4)?&U0jKe;>XW}Q6X_mb2Uhy4@&$(P(u?JrLqW{W+-xHnC|W>Q}~{gEZXz8 z-P)v0Mu%gd&88=CrwMmct+B{}Kttcp{_&zd$<5SeQaBWf#vJ1sh2G1l)m>>%FBB@!K- zC(D)1Zv%{xU8hf@P+i?*x)nVi*@VJ+??}k2*|5ar`}+G#N4g^*=u6Q&47@c}eJ}>`aumFXVvAF@|CHeG!ca4j7`J^S0L4<2|hx=FH z66j_@F+6nR8rox$rzt=RW))$eMdHzi%_Hzniea?b_j$!xq9Alxwl4)uX)-4Pj@4s<*SykA8RQvWl1f>Rg3)N$iN@ zg_MU(@L8HyL=`7m-57rZ&8nXq7gcX8sK(=O!t>t+a!3JJ>kdD*WQ>K8OcX9NF-zh~ptl%Ug z8EAfX@nPkCTC4q~nVyLzA+yz-*1-tbQ3MrnA8Sla3u8jQu9on=R!j(*P3e0;CD-l> zP=NJe_!GoUx*^^HN9QYZ%dX5y1+nt=c zRCHH1ppgeuu72Amd>#+eN?=mC17c+Ng;?N!&?sf+V>14nwa{OZRUHuy;kvXGKfK3X zg9RirtHnSOo5rriJ2)X>Mbw@Wv#2%7hP7(V(Vq6fQPKZ?YW-HXRP*A{U@xC%H{DPxmj2i;S43qb+AxCZu!E^rpa>-5!A5Hlq?ppxROqP_)!1x`W zh%lZarpwc`C`vnlE`ocpgLXq3lmi`L3$o(sA1Tn!5KGrmKAa&C$)7NE*ASa4p)s&O zMc8B<%`?&qqh9Vlf@-u`E}(|sJqu_-yQtwVy+5F9#eA6Pf5Nqg>b7tx<30f~hIWKu z^XWtIUzuXZTc=l7_#uXUw zMsyK;k>1c1onYT_6WMA)jagW&&U5}K5R4iJIAAw(mR#CYj&ZdK)=PxCeE=k>;tUWc zBUA^Plc>ey%%uM4gC9v#NhmVU$lOTICxe8tvY_!Kz&HT-8mn582hz9?=L8bD9{|5` z0KZVgz{t{P#^{Df7eLxP?Neni085IBk{6|l!_rCsNj4(gM-&zM?;4GgD|Tzj`W~xY z{OYHv<8sSg2C1r_NP-L&Zvz9~C!`|H!B+&B`Z-k}X2@SxUFCoz55e*V zEOogGnmza6GpHlmY1?F`zGa#6eV%9U_RNjriVl*CJ$P(Y4nW2rD6Tl4xF2+yc~pP1Um+ z1S()m(}?RSEb3rJuPk&`eZ5AvJGL30N6$fqSWz+2t6P^9Do0tvJ$ePK52AhjJs9*M z*A?5IyJKuyUBb3e;7!PUGiqnrR0Q)!+K27Okt~A=lu+ALKX=wrL>0y3<}Q@JW7q~t z!EcwF5r(HN_h--NU9GmR7Zb=zLS_S`=jvBQJfBxin-|QT1AkqgMcjNH1hx7!=qSD3 z(3hOOa!*2>l$0JfXnZ^1j|O`?u1Lm|yuPih+vyr@PDjeUjXaZH-|zwfIH;B< zY-G1wIiMYKdtziFmD?+qb_g7D&-SAnW*s&5Mb{ER-|!40Entpy_Tgs7kq_N}!jJbY>t^gs+AJ&I{Vp$@HbHvMWwQ!Fq(=|VrXtpoIDQ)z5wv_Zcyb}Y4* zkHmuZQm`i~N^E6fq=XlPAS_i#U(+t~H!=_pL3iMaRvsxqGPE>~M9jP35#PvgxYjTR zHSV3{d_7c#!XO=nhi68{2p&QGG94|goUdz$AEpE&uP1*J$ov>I%1dLKNOX|Ty37YD zKpm5$zp}(0{Tae!Pn9&fZtdB2W6UVU4m&rs}9-xlNQ#sqAb6aI;=xNv?xz;L8H^OnKHT^oMHHNYsdX&MHEOrwl|QKtw) z3@O%H-7$$Hubz#L-TQGkaf&&wI_Jw)0fETU)Ms!V6csi-r(PDN5lKNFV>n3e$D?Ze zzzrm4znOyFl26)MTp{Ddm(PX>Gn|)SOlY~qRSn40KVp3MQ^FQktN!v^izz-|s(x9+ zfnzpjB&$^4A403w-PbH;7HBSPy)+{`ep1a{Wc$+^VTAq@x~WB}X|uKZF@xI4Mtmh0 zxy%q&ZlQJGcj1I)s&z(J^)x+<{Cr)SQsh3xF zH@9E!A4Hy>zr6mL03d07A?s#`K`m)5u$Sry&?gbwp>W9Qf8Q*Qgaj(SZR1323RyvX zR?HiYrBlN(J;=%(p{FuX4W|DqF1xEf_QjM|i9*B+fmpWAQYk?)6H4I-jsADxI}bR& z`Wu5rp=PN1_);(R-`Xx1@1xTJO+r)RH0;I%$t9Stjs5YL3Ee9{zn=pZMjI>FJ3Uxe zh;gS;H+qAhP1@t;QMLv>v7e1O9u&73fgIw+Hv2X4V?Z9(fSqOp%cR`MxQ1^n2>Upt zjP)7G1U8$>wdHLQn5|N6D_YLIhvVCgdy)0n=yn2+5Es!%k1Xrl?TDO*jinlect6kY zwAagBV5`W4=&wyH&Y3e`aoqj37Zb7WI>Owq%)C~9RelihT7PSQ7zF+FK?{-s14s6Q zyPfDVhL&naV|hzPJ^zApvgoMSuXrhQMIo_Nbwx;FPSS(2xZ1L0~9U zmsW7tVw2^zm-*oVc_i;-6J?Ze4&M&hCUJ96)CZav)7Z9$piD<5<1AB3dBtGUcwF5_ z>4X5G;$3P(9Et*3GZFAMriD+8xtwmv)E=#!B%TFbN2{0jZp*5(;|4xQN4%d}~ty#6m{_EAO0qFaca~VG;sdNkP#QY-u#f zlU06eQwVHX!iW`Kc@JOEF&fOD7J8o^7<8t}zK0N|)VCb%W*hbqtEIl`X<5uuteKjR zC$%Nq&zAL5NGW|OGeMzH&A*eDPd#{p`9RfrZgNqr7gyj4_8UjRiZ+R>Sl!N#z!N(s zAg;|tx5r8-8x#U75^XC=>7+uhI2gkYQZd6+2Dj zto~?j7g05kM?ZGrt7;5Ac=UUUTQAVv{W)*HI@cn@11z9dNrLn?F6xT5mge4YLV<473Nn2 zy`o$?eK9{bQJL7;-y;OmPP@W{%6Z%}Mw+0xA-u)w{9f6_(bX5*^JnXIgU*Nr2$1JM zc8DKRrila{M?Jq{oFt4^V4UJskzk(@g=H`fXg_2ioD;%T#+-Qvf<3NCnGDq136Kuk zp!$9Qf5J>Jqln$6>z*?;{g&$bDTstm+TKAPrX+RrLvFMEA=aRb4Ch=tOGIe5)HdY~ z3D>z(@zHu6Pj>&ki|qZ=nk?&WYo2|hncSn7jSPWoff2^t+o!LH6q~IH5n0jOxA7ti z3p6AIW6H`!jnxgWRwSk$9fge{)D4d=&51ZY9H5(I1i(cT=enta5?EOQ5=-+Fl|XQ{ z(`BLOH%M@ivE#~8ZB^wJ1=3=Wg)|%lz(v$wh^bhj|3uwcXYPPw5%{K}q(B83FmX`8 z6=4)^JeEV)50JvDL4*F@mJ5GXB!zKN9SM4wvhj3{`G7G^6_7@GZTL+(j!iXs_y-j> z#4rS-Y7JCE+YTH@vCIdb>R9ZBE#i;xBdRG^aYgd^44;NaG+VCXtHSb`EM!Ktm#z|; z#`0NQhDY_Et`Zq!{tx}4|3jl89b#y}X9!}%d+gm7_gDE?hV{t5ml#fpoj^<;j~&AQh9@vBwOe5 zd_m{fmL{bZEO}>^?)t>B$T)`5V-o$X(eR$4tldXQ$_2o^|Dq2jr9dC?^|Y}LU_-r%s)-(P6Rf@Av0u)LEsIQHsFqx|drs zy?Q{nSk|oM>o!&;(J)-VH|7ZOXR$0hxl9^T!-o`E!M$os4#ii-;TG`O<;WD3vsETg zKZY$7_R>dlzuMERB<|yht#d9}@o=xyhxUlP80)hW6d=iNBH#B)5(g^=xsx8Ema(dd zz_%*ltaX;cvHr2pS&yw_q+pf#NpTmw!s=5g?Me9*e8SliDgAbJ{ni_w2=oH_fDFCK ziGs*r5m<^ueNk*dSze0D2g80V*+xdRcs#!c0y06aFhSWtmN3CtNm?)=IYoGzP%IsI zqG24epj<4b21gSt{+b#}Ea8?b6AaNFj-8MA5l%bkA4eQI)uC*RZ!_ofadyV0aMhmcuh5S|o|8IU-uOvSeW zp8B&4R85L-gO;d18GXKjr_A$~P3g`_&`&8M^qZUhf}1&kafFlGp=IV)7?NmJP}Z=d z8a4J%j8Qf;w1i#`v9P3E>~WP+Sm_KD{Fpld7fR_ekPyQZ_ZH7kRVGxbdSN3prFc{% z9lghPN$0gk`I^y`|0~wM?>H#(sE}bjo_lA*j#>JLo|wf5Pi@k6 zh)Ek6RYT5t99)RVj(K(7f-Y|FG=Y6G#z{)aJ8vH@s>E9t_R+%S=9fJ0YUD4Ix)<7R zIVE!LR`uu_5_D;W4?#*2Y z6B~(sz%Dh48wm=7HWew)7*c$YE6}z*_%qOUfYKdk^Ny${XH|Owe^vvxinS)74vK<0 zpbiU@*8I#$8mFEPEjv2`PGqXi+)C57MQS&ZcRHGti!4xtmf8f_)GyFUl{_wy=-zm) z+fm!ogU496M1lG`?B#@95;w zL{!b5F>B7m ze@WCa283RV^4XlQ8{sCfb`F&_L+?*yiHDLXwA5jZ_$s@o5(nMV%zGK8W+=2aoGv#( z$~926#^{N()4#4^u1wnt^s^IZ#=cBD@{e<7zuLIBY%R@^Z+A!wH$t7wx2pjv_1d7X zh6pjmf9bxm-A%6I`gYO?Fg;nFboOLQdNKWZ+v5iqf{~D<4IyD9C-p4h#j40Gkwq@D zEYW#3Guf~?9E{lTS*kaGv@)}8dK2$y=D5Z1cVYO1bQQ|9RU0(__v}%2^K9y zy|kwa?SCw>A5ukYI?zkCe$^Jsxu)BphtC?JEJ;+3EBRIAsp*bbir;MYURN}AKPYcX z$+Lo~!>MD0X~(!ZhVI5Nw$>g@i9gZEEkuDC$erY3gsJ-_O$bxpjAEVNpy8N$4D4UR zI+Nc)N@uhTKO!hGY31n|wRJ_$dd@5pV6l$x(6}u1Z!dpHh3+bY3xn>4aQ;-% zO+(*y20#kjscJ>r{z2Gqoj^-Fuqwht+r#6NRy_nyD_P?fnJ!N@2wT&}(Y`*wbUns3 zZ*x7)w_kQWA#{Io{R;%kd^0J5`}Jl@nzsCATJwJ~&*1<6hVSnj&iCwS2-Gq<#M+|C zGSuq&hSAmz#NP3HIHvjF+~V@e?B@2rzdoQ*{;h=Z*9-6c`cVCr``3n#NTw!F2IpRJ zM7kIQW;B7#WJLWsh8&zKWyR74Pe#idEEIo0g%>wG>HRU02s^3no&2GYDKv{aJ3Ql| zkzF;`5@8)z&UfrK`xM)~U}Mplpcm!52U8`yngC|Rgb)D2SubAahM?_u*waUxdHd3L-~IOV7dQ3kjfWKmyCP*eI#Bk+|Gj~ zsIfeOYr9>M^`p^$t%DMP`p1yZ0d8P(W-k6^{7QFxRp>)TgnQuOT&czSM0@M~`G$eS zxi_)Z0^M$LMqrFc8!W`dsuGwL)B*K$N4)Xt&G5q;%-bKmxeU+CM;?I&YrCgvcW5Tby=Ekp7Fy6rI0qNMcj zxlQTx2b$pHjz z^!Q2m!EWAhngzw?f|fAz1$K64IQt={SG@ZU=5z6dx<4uo_cJ4I7rR_h;H~D|$?->U za=?;FWI$jY&G|#<0Yf$#ZyHl=_Nv@K}DR|6KqzT`6Kovd6Axc#U7PB498`Z z`PhuM4GmU$6}QmhN+sm4OF14rJ(lZ*p5(2GH8yp&4ven9JaNmJ$7DBW>uS^q`|De- za+tAJ?v_rPb}+8K5-zkj(^DRfG@MbKme5SJ`jv$Yx80x^pHn|XY!7wp!Z2NQLH+H8 z2S;0W(SyW$@_v1gV!G_Z`ebw2k7rSKIY8ucayght{eSoV{;z}c)4x{i|Nh`4fH*$1 zIEFYiKfk>B7f|HwU&^Jw-QOpH;6UU=At*GJ;l7af@HSGx*Eh=O2oirV()$NE45m~% zlP>0f{p$n#{~F0L?rzH9Uz9?~PgsC&+P&GbK1cG|-wuNd6jeas0`HJ9G|kEoLw<*h zIaFOz_tzzICUCW>u<7@Jo3SPHuj6fIIJo1wbu||pMWuTzt=jIm7Yf_BBpaQmFqO&A zat?$89YnR>D{?i2BY8maDkRuzy76GIy-Oy9I>-q}X#;uxlnAS!vX9Sh3hX>8qIpX7 zBwy=lPDGm(PS-GBeqV_63ls0hw*9_ZZ0Aj0ds$Yw2K^Ra5BNr`eD`~{S?aB-Wy(ps zf0R?efKJ%vdXw?HRGAJZN|!|@7>3~>%MZuuAUkL)SSttP<#S=K z0fbv@9*@e%L4J~X$zeg7r!l=k<^+~iVO~PZND+HBLTpJv!_iS`)c}JvG7rjUYwgB~ zlH-c1HTt4TZ=fJTDFgbCm}(Bur-GUk8;(&%%w|vQa?Rf&)~EIVueS zK3u8AcfO@>;ta`gL`B$PzUu$n_~6_kaP;YI>-3`obQ6ME#=wM?{QGe|w%f;g8KW=w26P6-*oFV4m-K4kLm)q~gcJ$$W4nFCxkq}L+jT;``?Rt* zwv(_Kfqr^1G<;7=1aHEDh!>j6_jirP8LMc<6I;d`8O;f@6;$>m#WMbvZJQzS*KRsF zmlfT3kzrts^nN}Yckl&bTYFo0Vg;%4HM>6S?l$zm=_|C|l5@li^=KVJvB=l%QB?D_ zKba1@>xEKln>ToRK2Ye7e8rePD-#asb5mP1xAH5M0Y-dDZrzpp6EA9V4809rzhZD! zoG|pgN_nslkUp{J$J9NBI8+!N^k1lj+Wc9a_wAlm^;Lh43qK9^IOm$2Z~0?)a9f^J ziOGk%>SEvA)_Ut;`hW2s9?q^a<)U}Fn6n?=09j;(Gm!%6(At_YI@a7LOhJLHA^q4O zezRc^uVBG0$cz02S3ziayanZvZ$(z*<5L+y%yAtARbYI=lwNp(5_Ruse6~$3PZGyT z*At0-e3mCtM!{-i%qLYT#kj%%M$tRSsTf2%IHOM`wJR`vG+P1 zTSlK1S6Q+t!qmP7p?6rM*mFS%+A=811V1CFFS)lacg{QcJ{|a=zxK@S=ySazhLe%X zLnS2J`_RidSMA3$JDMhkDf5nXe9rw)>L~U^Ghs@egBsA_J-Jk8qF+{OJ`UR>k+ceVR^m?jwpd!X`faI#B73l0Gvaly@^XQ6u-f=5 z_s&yOG+@J|p9_yyr_KP?_n_~zE!&TnsczlZRy)LVdHhe3xF!Wn@@prjex5H8vUSK~wxAqav7oyijk-*FBifS`xp zsE)mX8TQb5rLZ3hg;nR=7NQJKZ^ z<=QJB=TilTRxdRf-J(Ih)2~mTOE^!-M+HaC_rNquwqL#Tw|?JcQ=b0d-H!FgdQ|Tp zVQ+(M=4x{jdzzaLcGqUw^$tbRKZ=X!YQW!Su}6P^e0K3{_+%K5T)9ZDxlQnE%qDDK z9Oht5XwRahV1Bp5K2C4kMmy3}ZJDuYU zWzpHvK+-bawb1$Q&&8$UR$~zY)6)8dQidst1XKEzw>o_grmkTtkNAFWK_|=@i~wn z%0W)fR93vc`V(%^!L6ZF*@50Rd~|1iAbGvn-KSAjMmUi^y3?>{K%UbkK8{M&sL8E@ z$Q_8>d!xGWE`e-01Yz#A*gMPICskj%d1RjBANKu_>Q>}OP}cobMPLfGe5UQbwF5SR zE88RX(a@byWTxlNm`h37&bUY2%FYKL3UqhEf5db5W6(m`?kCiTl)n%C|MJDm?>FE- zIZkt4T)MlmdVIKl2iVbQ#-!SDRa zR+aBr`ATRKjbk&~WBZBM`K(@NFv|omSo+&MWVQ$$wjCFC2iDl`4(m?T-xaTUwWQ>Y zY4SMub_s4ocRS2(QRqV^4~*vxnUB|LD(K{_V@kOaeqy#tq36$wlJqMGMTLO~^XCCE zA@?JPNy04&Yz{BZeMs^d>|cqgJ3CnuaZ1>@@#VUB%Yv9j%|+wQ@Nn@<&O#6Rw-6(} z$dUxr!29p%+9F0t@+kEBq-~Dw>9;XIlU}kfTMq~`95wA6Hm{WoTkX>^ z$D!5sbe}wI6N!lkKcyOkiB#6a10J2TR0TwVTsxoX3Mqi!hww*^3VDh-+Kc*1*;P!d z2?wlA!{zlv zgMvKRosmp!IZa*XZPLb7!)gN&EA;fvfuq`O&i9XhoS` LaFe5F`09TH(H{R- literal 0 HcmV?d00001 diff --git a/public/badges/splatalittle.png b/public/badges/splatalittle.png new file mode 100644 index 0000000000000000000000000000000000000000..6929a7efc9b1ca6744666c16bf1cc371dc73e1d4 GIT binary patch literal 4560 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 literal 0 HcmV?d00001 From db4f633a476b14d98acad1b7502b2e8b7a4b4ba1 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Thu, 20 Oct 2022 22:25:00 +0200 Subject: [PATCH 22/47] Add type for route handles --- app/root.tsx | 3 ++- app/routes/analyzer.tsx | 3 ++- app/routes/badges.tsx | 3 ++- app/routes/builds.tsx | 3 ++- app/routes/builds/index.tsx | 3 ++- app/routes/calendar/$id/index.tsx | 4 ++-- app/routes/calendar/$id/report-winners.tsx | 3 ++- app/routes/calendar/index.tsx | 3 ++- app/routes/calendar/new.tsx | 3 ++- app/routes/contributions.tsx | 3 ++- app/routes/faq.tsx | 3 ++- app/routes/index.tsx | 3 ++- app/routes/maps.tsx | 3 ++- app/routes/object-damage.tsx | 3 ++- app/routes/u.$identifier.tsx | 4 ++-- app/routes/u.$identifier/builds/index.tsx | 8 ++++++-- app/routes/u.$identifier/builds/new.tsx | 4 ++-- app/routes/u.$identifier/index.tsx | 3 ++- app/utils/remix.ts | 14 ++++++++++++++ 19 files changed, 54 insertions(+), 22 deletions(-) diff --git a/app/root.tsx b/app/root.tsx index cd7ba038d..b93d03d18 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -32,6 +32,7 @@ import { Theme, ThemeHead, useTheme, ThemeProvider } from "./modules/theme"; import { getThemeSession } from "./modules/theme/session.server"; import { COMMON_PREVIEW_IMAGE } from "./utils/urls"; import { ConditionalScrollRestoration } from "./components/ConditionalScrollRestoration"; +import { type SendouRouteHandle } from "~/utils/remix"; export const unstable_shouldReload: ShouldReloadFunction = ({ url }) => { // reload on language change so the selected language gets set into the cookie @@ -94,7 +95,7 @@ export const loader: LoaderFunction = async ({ request }) => { ); }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "common", }; diff --git a/app/routes/analyzer.tsx b/app/routes/analyzer.tsx index d66e243e9..8253e30c1 100644 --- a/app/routes/analyzer.tsx +++ b/app/routes/analyzer.tsx @@ -34,6 +34,7 @@ import { type SubWeaponId, } from "~/modules/in-game-lists"; import styles from "~/styles/analyzer.css"; +import { type SendouRouteHandle } from "~/utils/remix"; import { makeTitle } from "~/utils/strings"; import { specialWeaponImageUrl, subWeaponImageUrl } from "~/utils/urls"; @@ -49,7 +50,7 @@ export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["weapons", "analyzer"], }; diff --git a/app/routes/badges.tsx b/app/routes/badges.tsx index 42bd6307c..0106ce443 100644 --- a/app/routes/badges.tsx +++ b/app/routes/badges.tsx @@ -9,6 +9,7 @@ import styles from "~/styles/badges.css"; import { BORZOIC_TWITTER, FAQ_PAGE } from "~/utils/urls"; import { Trans, useTranslation } from "react-i18next"; import { useAnimateListEntry } from "~/hooks/useAnimateListEntry"; +import { type SendouRouteHandle } from "~/utils/remix"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; @@ -18,7 +19,7 @@ export interface BadgesLoaderData { badges: FindAll; } -export const handle = { +export const handle: SendouRouteHandle = { i18n: "badges", }; diff --git a/app/routes/builds.tsx b/app/routes/builds.tsx index e3800cf64..3841500d5 100644 --- a/app/routes/builds.tsx +++ b/app/routes/builds.tsx @@ -6,6 +6,7 @@ import { LinkButton } from "~/components/Button"; import { Main } from "~/components/Main"; import { useUser } from "~/modules/auth"; import type { MainWeaponId } from "~/modules/in-game-lists"; +import { type SendouRouteHandle } from "~/utils/remix"; import styles from "~/styles/builds.css"; import { atOrError } from "~/utils/arrays"; @@ -15,7 +16,7 @@ export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["weapons", "builds"], }; diff --git a/app/routes/builds/index.tsx b/app/routes/builds/index.tsx index 63b0b7080..87553e8e4 100644 --- a/app/routes/builds/index.tsx +++ b/app/routes/builds/index.tsx @@ -4,8 +4,9 @@ import { Image } from "~/components/Image"; import type { MainWeaponId } from "~/modules/in-game-lists"; import { weaponCategories, weaponIdIsNotAlt } from "~/modules/in-game-lists"; import { mainWeaponImageUrl, mySlugify, weaponCategoryUrl } from "~/utils/urls"; +import { type SendouRouteHandle } from "~/utils/remix"; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "weapons", }; diff --git a/app/routes/calendar/$id/index.tsx b/app/routes/calendar/$id/index.tsx index 2ba78c7fb..714e686c8 100644 --- a/app/routes/calendar/$id/index.tsx +++ b/app/routes/calendar/$id/index.tsx @@ -28,7 +28,7 @@ import { import calendarStyles from "~/styles/calendar-event.css"; import mapsStyles from "~/styles/maps.css"; import { databaseTimestampToDate } from "~/utils/dates"; -import { notFoundIfFalsy } from "~/utils/remix"; +import { notFoundIfFalsy, type SendouRouteHandle } from "~/utils/remix"; import { discordFullName, makeTitle } from "~/utils/strings"; import { calendarEditPage, @@ -60,7 +60,7 @@ export const meta: MetaFunction = (args) => { }; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["calendar", "game-misc"], }; diff --git a/app/routes/calendar/$id/report-winners.tsx b/app/routes/calendar/$id/report-winners.tsx index a3c501115..588ec5fc7 100644 --- a/app/routes/calendar/$id/report-winners.tsx +++ b/app/routes/calendar/$id/report-winners.tsx @@ -17,6 +17,7 @@ import { notFoundIfFalsy, safeParseRequestFormData, validate, + type SendouRouteHandle, } from "~/utils/remix"; import { actualNumber, id, safeJSONParse, toArray } from "~/utils/zod"; import * as React from "react"; @@ -135,7 +136,7 @@ export const action: ActionFunction = async ({ request, params }) => { return redirect(calendarEventPage(parsedParams.id)); }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "calendar", }; diff --git a/app/routes/calendar/index.tsx b/app/routes/calendar/index.tsx index 735bd364e..ec8983c2f 100644 --- a/app/routes/calendar/index.tsx +++ b/app/routes/calendar/index.tsx @@ -25,6 +25,7 @@ import type { Unpacked } from "~/utils/types"; import { calendarReportWinnersPage, resolveBaseUrl } from "~/utils/urls"; import { actualNumber } from "~/utils/zod"; import { Tags } from "./components/Tags"; +import { type SendouRouteHandle } from "~/utils/remix"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; @@ -45,7 +46,7 @@ export const meta: MetaFunction = (args) => { }; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "calendar", }; diff --git a/app/routes/calendar/new.tsx b/app/routes/calendar/new.tsx index dbc2e7f21..af102411e 100644 --- a/app/routes/calendar/new.tsx +++ b/app/routes/calendar/new.tsx @@ -44,6 +44,7 @@ import { badRequestIfFalsy, parseRequestFormData, validate, + type SendouRouteHandle, } from "~/utils/remix"; import { makeTitle } from "~/utils/strings"; import { calendarEventPage } from "~/utils/urls"; @@ -181,7 +182,7 @@ export const action: ActionFunction = async ({ request }) => { } }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "calendar", }; diff --git a/app/routes/contributions.tsx b/app/routes/contributions.tsx index e53836dd1..d6e8228d3 100644 --- a/app/routes/contributions.tsx +++ b/app/routes/contributions.tsx @@ -11,6 +11,7 @@ import { SENDOU_TWITTER_URL, UBERU_TWITTER, } from "~/utils/urls"; +import { type SendouRouteHandle } from "~/utils/remix"; export const meta: MetaFunction = () => { return { @@ -18,7 +19,7 @@ export const meta: MetaFunction = () => { }; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "contributions", }; diff --git a/app/routes/faq.tsx b/app/routes/faq.tsx index dd1e6089b..1f93a218e 100644 --- a/app/routes/faq.tsx +++ b/app/routes/faq.tsx @@ -4,6 +4,7 @@ import { Main } from "~/components/Main"; import { useSetTitle } from "~/hooks/useSetTitle"; import styles from "~/styles/faq.css"; import { makeTitle } from "~/utils/strings"; +import { type SendouRouteHandle } from "~/utils/remix"; const AMOUNT_OF_QUESTIONS = 3; @@ -18,7 +19,7 @@ export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "faq", }; diff --git a/app/routes/index.tsx b/app/routes/index.tsx index 02d3a7cd9..334a69d73 100644 --- a/app/routes/index.tsx +++ b/app/routes/index.tsx @@ -26,6 +26,7 @@ import { userPage, } from "~/utils/urls"; import { Tags } from "./calendar/components/Tags"; +import { type SendouRouteHandle } from "~/utils/remix"; const RECENT_ARTICLES_TO_SHOW = 3; @@ -33,7 +34,7 @@ export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["weapons", "builds"], }; diff --git a/app/routes/maps.tsx b/app/routes/maps.tsx index 6d4589039..3b7d8b661 100644 --- a/app/routes/maps.tsx +++ b/app/routes/maps.tsx @@ -44,6 +44,7 @@ import { modeImageUrl, stageImageUrl, } from "~/utils/urls"; +import { type SendouRouteHandle } from "~/utils/remix"; const AMOUNT_OF_MAPS_IN_MAP_LIST = stageIds.length * 2; @@ -63,7 +64,7 @@ export const meta: MetaFunction = (args) => { }; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "game-misc", }; diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx index 4cdfe3aea..c26bfedfd 100644 --- a/app/routes/object-damage.tsx +++ b/app/routes/object-damage.tsx @@ -2,8 +2,9 @@ import { WeaponCombobox } from "~/components/Combobox"; import { Main } from "~/components/Main"; import { useObjectDamage } from "~/modules/analyzer"; import type { MainWeaponId } from "~/modules/in-game-lists"; +import { type SendouRouteHandle } from "~/utils/remix"; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["weapons"], }; diff --git a/app/routes/u.$identifier.tsx b/app/routes/u.$identifier.tsx index c19c9ef27..f5395163a 100644 --- a/app/routes/u.$identifier.tsx +++ b/app/routes/u.$identifier.tsx @@ -15,7 +15,7 @@ import { db } from "~/db"; import { useUser } from "~/modules/auth"; import { i18next } from "~/modules/i18n"; import { translatedCountry } from "~/utils/i18n.server"; -import { notFoundIfFalsy } from "~/utils/remix"; +import { notFoundIfFalsy, type SendouRouteHandle } from "~/utils/remix"; import { discordFullName, makeTitle } from "~/utils/strings"; import styles from "~/styles/u.css"; import invariant from "tiny-invariant"; @@ -39,7 +39,7 @@ export const meta: MetaFunction = ({ data }: { data: UserPageLoaderData }) => { }; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "user", }; diff --git a/app/routes/u.$identifier/builds/index.tsx b/app/routes/u.$identifier/builds/index.tsx index 4a0937312..94d7a356b 100644 --- a/app/routes/u.$identifier/builds/index.tsx +++ b/app/routes/u.$identifier/builds/index.tsx @@ -10,7 +10,11 @@ import { BUILD } from "~/constants"; import { db } from "~/db"; import { getUser, requireUser, useUser } from "~/modules/auth"; import { atOrError } from "~/utils/arrays"; -import { notFoundIfFalsy, parseRequestFormData } from "~/utils/remix"; +import { + notFoundIfFalsy, + parseRequestFormData, + type SendouRouteHandle, +} from "~/utils/remix"; import { userNewBuildPage } from "~/utils/urls"; import { actualNumber, id } from "~/utils/zod"; import { type UserPageLoaderData, userParamsSchema } from "../../u.$identifier"; @@ -39,7 +43,7 @@ export const action: ActionFunction = async ({ request }) => { return null; }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["weapons", "builds"], }; diff --git a/app/routes/u.$identifier/builds/new.tsx b/app/routes/u.$identifier/builds/new.tsx index b46e2e5fa..44cf417d7 100644 --- a/app/routes/u.$identifier/builds/new.tsx +++ b/app/routes/u.$identifier/builds/new.tsx @@ -30,7 +30,7 @@ import type { BuildAbilitiesTupleWithUnknown, MainWeaponId, } from "~/modules/in-game-lists/types"; -import { parseRequestFormData } from "~/utils/remix"; +import { parseRequestFormData, type SendouRouteHandle } from "~/utils/remix"; import { modeImageUrl, userBuildsPage } from "~/utils/urls"; import { actualNumber, @@ -154,7 +154,7 @@ export const action: ActionFunction = async ({ request }) => { return redirect(userBuildsPage(user)); }; -export const handle = { +export const handle: SendouRouteHandle = { i18n: ["weapons", "builds", "gear"], }; diff --git a/app/routes/u.$identifier/index.tsx b/app/routes/u.$identifier/index.tsx index 00a488d29..6d5e4f0bb 100644 --- a/app/routes/u.$identifier/index.tsx +++ b/app/routes/u.$identifier/index.tsx @@ -14,8 +14,9 @@ import type { Unpacked } from "~/utils/types"; import { assertUnreachable } from "~/utils/types"; import { badgeExplanationText } from "../badges/$id"; import type { UserPageLoaderData } from "../u.$identifier"; +import { type SendouRouteHandle } from "~/utils/remix"; -export const handle = { +export const handle: SendouRouteHandle = { i18n: "badges", }; diff --git a/app/utils/remix.ts b/app/utils/remix.ts index 2f381cef4..6ebce50d6 100644 --- a/app/utils/remix.ts +++ b/app/utils/remix.ts @@ -1,4 +1,6 @@ import { z } from "zod"; +import { type ReactNode } from "react"; +import { type Namespace } from "react-i18next"; export function notFoundIfFalsy(value: T | null | undefined): T { if (!value) throw new Response(null, { status: 404 }); @@ -89,3 +91,15 @@ export function validate(condition: any, status = 400): asserts condition { throw new Response(null, { status }); } + +/** + * Our custom type for route handles - the keys are defined by us or + * libraries that parse them. + * + * Can be set per route using `export const handle: SendouRouteHandle = { };` + * Can be accessed for all currently active routes via the `useMatches()` hook. + */ +export type SendouRouteHandle = { + /** The i18n translation files used for this route, via remix-i18next */ + i18n?: Namespace; +}; From 85fda204c0efc162bb38d9c7d69109ecf662fdb2 Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Fri, 21 Oct 2022 00:48:01 +0200 Subject: [PATCH 23/47] Refactor breadcrumbs into a component that uses route handles --- app/components/Breadcrumbs.tsx | 58 ++++++++++++++++++++++++++++++++++ app/routes/builds.tsx | 44 +++----------------------- app/routes/builds/$slug.tsx | 14 +++++++- app/styles/builds.css | 7 ---- app/styles/common.css | 7 ++++ app/utils/arrays.ts | 5 +++ app/utils/remix.ts | 12 +++++-- 7 files changed, 98 insertions(+), 49 deletions(-) create mode 100644 app/components/Breadcrumbs.tsx diff --git a/app/components/Breadcrumbs.tsx b/app/components/Breadcrumbs.tsx new file mode 100644 index 000000000..c17d627be --- /dev/null +++ b/app/components/Breadcrumbs.tsx @@ -0,0 +1,58 @@ +import { Link, useMatches } from "@remix-run/react"; +import { useMemo, Fragment } from "react"; +import { useTranslation } from "react-i18next"; +import { isDefined } from "~/utils/arrays"; +import { type SendouRouteHandle } from "~/utils/remix"; + +type Crumb = { + path: string; + name: string; +}; + +function useBreadcrumbs(): Crumb[] { + const matches = useMatches(); + const { t } = useTranslation("common"); + + return useMemo( + () => + matches + .map((match) => { + const handle = match.handle as undefined | SendouRouteHandle; + const name = handle?.breadcrumb?.({ match, t }); + return name ? { path: match.pathname, name } : undefined; + }) + .filter(isDefined), + [matches, t] + ); +} + +export function Breadcrumbs() { + const breadcrumbs = useBreadcrumbs(); + + const showBreadcrumbs = breadcrumbs.length > 0; + + if (!showBreadcrumbs) { + return null; + } + + return ( +

+ ); +} diff --git a/app/routes/builds.tsx b/app/routes/builds.tsx index 3841500d5..6eddd29c6 100644 --- a/app/routes/builds.tsx +++ b/app/routes/builds.tsx @@ -1,16 +1,13 @@ import { type LinksFunction } from "@remix-run/node"; -import { Link, Outlet, useMatches, useParams } from "@remix-run/react"; -import type * as React from "react"; +import { Outlet } from "@remix-run/react"; import { useTranslation } from "react-i18next"; import { LinkButton } from "~/components/Button"; import { Main } from "~/components/Main"; import { useUser } from "~/modules/auth"; -import type { MainWeaponId } from "~/modules/in-game-lists"; import { type SendouRouteHandle } from "~/utils/remix"; - import styles from "~/styles/builds.css"; -import { atOrError } from "~/utils/arrays"; -import { BUILDS_PAGE, userNewBuildPage } from "~/utils/urls"; +import { userNewBuildPage } from "~/utils/urls"; +import { Breadcrumbs } from "~/components/Breadcrumbs"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; @@ -18,34 +15,17 @@ export const links: LinksFunction = () => { export const handle: SendouRouteHandle = { i18n: ["weapons", "builds"], + breadcrumb: ({ t }) => t("pages.builds"), }; export default function BuildsLayoutPage() { const user = useUser(); - const matches = useMatches(); const { t } = useTranslation(["weapons", "common", "builds"]); - const params = useParams(); - - const weaponId: MainWeaponId | undefined = atOrError(matches, -1).data?.[ - "weaponId" - ]; return (
- + {user && ( {t("builds:addBuild")} @@ -56,17 +36,3 @@ export default function BuildsLayoutPage() {
); } - -function SometimesLink({ - children, - isLink, -}: { - children: React.ReactNode; - isLink: boolean; -}) { - if (isLink) { - return {children}; - } - - return
{children}
; -} diff --git a/app/routes/builds/$slug.tsx b/app/routes/builds/$slug.tsx index 3fe2fc6bf..b0f716385 100644 --- a/app/routes/builds/$slug.tsx +++ b/app/routes/builds/$slug.tsx @@ -11,6 +11,7 @@ import { BUILDS_PAGE_BATCH_SIZE, BUILDS_PAGE_MAX_BUILDS } from "~/constants"; import { db } from "~/db"; import { i18next } from "~/modules/i18n"; import { weaponIdIsNotAlt } from "~/modules/in-game-lists"; +import { type SendouRouteHandle } from "~/utils/remix"; import { makeTitle } from "~/utils/strings"; import { weaponNameSlugToId } from "~/utils/unslugify.server"; @@ -40,9 +41,12 @@ export const loader = async ({ request, params }: LoaderArgs) => { BUILDS_PAGE_MAX_BUILDS ); + const weaponName = t(`weapons:MAIN_${weaponId}`); + return { weaponId, - title: makeTitle([t(`weapons:MAIN_${weaponId}`), t("common:pages.builds")]), + weaponName, + title: makeTitle([weaponName, t("common:pages.builds")]), builds: db.builds.buildsByWeaponId({ weaponId, limit, @@ -51,6 +55,14 @@ export const loader = async ({ request, params }: LoaderArgs) => { }; }; +export const handle: SendouRouteHandle = { + breadcrumb: ({ match }) => { + const data = match.data as SerializeFrom | null; + + return data ? data.weaponName : "Unknown"; + }, +}; + export default function WeaponsBuildsPage() { const data = useLoaderData(); const { t } = useTranslation(["common"]); diff --git a/app/styles/builds.css b/app/styles/builds.css index 34d8fa9f9..3960f1f83 100644 --- a/app/styles/builds.css +++ b/app/styles/builds.css @@ -4,13 +4,6 @@ justify-content: space-between; } -.builds__breadcrumbs { - display: flex; - font-size: var(--fonts-xs); - font-weight: var(--bold); - gap: var(--s-1); -} - .builds__category { display: flex; flex-direction: column; diff --git a/app/styles/common.css b/app/styles/common.css index ab61e10dc..2aa9a71f0 100644 --- a/app/styles/common.css +++ b/app/styles/common.css @@ -872,3 +872,10 @@ dialog::backdrop { .ability-selector__ability-button.is-dragging { box-shadow: 0 0 100px inset rgb(255 255 255 / 25%); } + +.breadcrumbs { + display: flex; + font-size: var(--fonts-xs); + font-weight: var(--bold); + gap: var(--s-1); +} diff --git a/app/utils/arrays.ts b/app/utils/arrays.ts index 3c29f98a7..2ab5b0efd 100644 --- a/app/utils/arrays.ts +++ b/app/utils/arrays.ts @@ -40,3 +40,8 @@ export function normalizeFormFieldArray( ): string[] { return value == null ? [] : typeof value === "string" ? [value] : value; } + +/** Can be used as a strongly typed array filter */ +export function isDefined(value: T | undefined | null): value is T { + return value !== null && value !== undefined; +} diff --git a/app/utils/remix.ts b/app/utils/remix.ts index 6ebce50d6..be1be09f9 100644 --- a/app/utils/remix.ts +++ b/app/utils/remix.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { type ReactNode } from "react"; -import { type Namespace } from "react-i18next"; +import { type TFunction, type Namespace } from "react-i18next"; +import { type RouteMatch } from "@remix-run/react"; export function notFoundIfFalsy(value: T | null | undefined): T { if (!value) throw new Response(null, { status: 404 }); @@ -102,4 +102,12 @@ export function validate(condition: any, status = 400): asserts condition { export type SendouRouteHandle = { /** The i18n translation files used for this route, via remix-i18next */ i18n?: Namespace; + /** + * A function that returns the breadcrumb text that should be displayed in + * the component + */ + breadcrumb?: (args: { + match: RouteMatch; + t: TFunction<"common", undefined>; + }) => string | undefined; }; From 3ce7c00d5bbe2f089a69db6c6a866ac2d0d161eb Mon Sep 17 00:00:00 2001 From: Remmy Cat Stock <3317423+remmycat@users.noreply.github.com> Date: Fri, 21 Oct 2022 18:29:23 +0200 Subject: [PATCH 24/47] Detect active nav item via route handle instead of path matching --- app/components/layout/index.tsx | 34 ++++++++++++++++++++++++--------- app/routes/admin.tsx | 10 +++++++++- app/routes/analyzer.tsx | 1 + app/routes/badges.tsx | 1 + app/routes/builds.tsx | 1 + app/routes/calendar/index.tsx | 1 + app/routes/maps.tsx | 1 + app/routes/plus.tsx | 5 +++++ app/utils/remix.ts | 4 ++++ 9 files changed, 48 insertions(+), 10 deletions(-) diff --git a/app/components/layout/index.tsx b/app/components/layout/index.tsx index b05710e8d..b04831c4d 100644 --- a/app/components/layout/index.tsx +++ b/app/components/layout/index.tsx @@ -1,7 +1,8 @@ -import { Link, useLocation } from "@remix-run/react"; +import { Link, useMatches } from "@remix-run/react"; import * as React from "react"; import { useTranslation } from "react-i18next"; import type { RootLoaderData } from "~/root"; +import { type SendouRouteHandle } from "~/utils/remix"; import { LOGO_PATH, navIconUrl } from "~/utils/urls"; import { Image } from "../Image"; import { ColorModeToggle } from "./ColorModeToggle"; @@ -12,6 +13,25 @@ import { Menu } from "./Menu"; import navItems from "./nav-items.json"; import { UserItem } from "./UserItem"; +function useActiveNavItem() { + const matches = useMatches(); + + return React.useMemo(() => { + let activeItem: { name: string; url: string } | undefined = undefined; + + for (const match of matches.reverse()) { + const handle = match.handle as SendouRouteHandle | undefined; + + if (handle?.navItemName) { + activeItem = navItems.find(({ name }) => name === handle.navItemName); + break; + } + } + + return activeItem; + }, [matches]); +} + export const Layout = React.memo(function Layout({ children, patrons, @@ -22,12 +42,8 @@ export const Layout = React.memo(function Layout({ isCatchBoundary?: boolean; }) { const { t } = useTranslation(); - const location = useLocation(); const [menuOpen, setMenuOpen] = React.useState(false); - - const currentPagesNavItem = navItems.find((navItem) => - location.pathname.includes(navItem.name) - ); + const activeNavItem = useActiveNavItem(); return (
@@ -51,15 +67,15 @@ export const Layout = React.memo(function Layout({
setMenuOpen(false)} /> - {currentPagesNavItem && ( + {activeNavItem && (
- {t(`pages.${currentPagesNavItem.name}` as any)} + {t(`pages.${activeNavItem.name}` as any)}
)} {children} diff --git a/app/routes/admin.tsx b/app/routes/admin.tsx index 768532035..8490107ac 100644 --- a/app/routes/admin.tsx +++ b/app/routes/admin.tsx @@ -18,7 +18,11 @@ import { Main } from "~/components/Main"; import { requireUser } from "~/modules/auth"; import { getUser, isImpersonating } from "~/modules/auth/user.server"; import { canPerformAdminActions } from "~/permissions"; -import { parseRequestFormData, validate } from "~/utils/remix"; +import { + parseRequestFormData, + type SendouRouteHandle, + validate, +} from "~/utils/remix"; import { makeTitle } from "~/utils/strings"; import { impersonateUrl, SEED_URL, STOP_IMPERSONATING_URL } from "~/utils/urls"; import { db } from "~/db"; @@ -69,6 +73,10 @@ export const loader: LoaderFunction = async ({ request }) => { }); }; +export const handle: SendouRouteHandle = { + navItemName: "admin", +}; + export default function AdminPage() { return (
diff --git a/app/routes/analyzer.tsx b/app/routes/analyzer.tsx index 8253e30c1..c1bb42f10 100644 --- a/app/routes/analyzer.tsx +++ b/app/routes/analyzer.tsx @@ -52,6 +52,7 @@ export const links: LinksFunction = () => { export const handle: SendouRouteHandle = { i18n: ["weapons", "analyzer"], + navItemName: "analyzer", }; export default function BuildAnalyzerPage() { diff --git a/app/routes/badges.tsx b/app/routes/badges.tsx index 0106ce443..8b64d95ed 100644 --- a/app/routes/badges.tsx +++ b/app/routes/badges.tsx @@ -21,6 +21,7 @@ export interface BadgesLoaderData { export const handle: SendouRouteHandle = { i18n: "badges", + navItemName: "badges", }; export const loader: LoaderFunction = () => { diff --git a/app/routes/builds.tsx b/app/routes/builds.tsx index 6eddd29c6..87c234620 100644 --- a/app/routes/builds.tsx +++ b/app/routes/builds.tsx @@ -16,6 +16,7 @@ export const links: LinksFunction = () => { export const handle: SendouRouteHandle = { i18n: ["weapons", "builds"], breadcrumb: ({ t }) => t("pages.builds"), + navItemName: "builds", }; export default function BuildsLayoutPage() { diff --git a/app/routes/calendar/index.tsx b/app/routes/calendar/index.tsx index ec8983c2f..841e684f6 100644 --- a/app/routes/calendar/index.tsx +++ b/app/routes/calendar/index.tsx @@ -48,6 +48,7 @@ export const meta: MetaFunction = (args) => { export const handle: SendouRouteHandle = { i18n: "calendar", + navItemName: "calendar", }; const loaderSearchParamsSchema = z.object({ diff --git a/app/routes/maps.tsx b/app/routes/maps.tsx index 3b7d8b661..ff152df1a 100644 --- a/app/routes/maps.tsx +++ b/app/routes/maps.tsx @@ -66,6 +66,7 @@ export const meta: MetaFunction = (args) => { export const handle: SendouRouteHandle = { i18n: "game-misc", + navItemName: "maps", }; export const loader = async ({ request }: LoaderArgs) => { diff --git a/app/routes/plus.tsx b/app/routes/plus.tsx index 1425f0f9e..66b061bf8 100644 --- a/app/routes/plus.tsx +++ b/app/routes/plus.tsx @@ -3,11 +3,16 @@ import { Outlet } from "@remix-run/react"; import { Main } from "~/components/Main"; import { SubNav, SubNavLink } from "~/components/SubNav"; import styles from "~/styles/plus.css"; +import { type SendouRouteHandle } from "~/utils/remix"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; +export const handle: SendouRouteHandle = { + navItemName: "plus", +}; + export default function PlusPageLayout() { return ( <> diff --git a/app/utils/remix.ts b/app/utils/remix.ts index be1be09f9..3bf68b402 100644 --- a/app/utils/remix.ts +++ b/app/utils/remix.ts @@ -102,6 +102,7 @@ export function validate(condition: any, status = 400): asserts condition { export type SendouRouteHandle = { /** The i18n translation files used for this route, via remix-i18next */ i18n?: Namespace; + /** * A function that returns the breadcrumb text that should be displayed in * the component @@ -110,4 +111,7 @@ export type SendouRouteHandle = { match: RouteMatch; t: TFunction<"common", undefined>; }) => string | undefined; + + /** The name of a navItem that is active on this route. See nav-items.json */ + navItemName?: string; }; From 17b34f6fe2f63ac0b10644c7dec81badf7e66713 Mon Sep 17 00:00:00 2001 From: lolametro <13728127+lolametro@users.noreply.github.com> Date: Fri, 21 Oct 2022 21:08:53 +0200 Subject: [PATCH 25/47] Update calendar.json for DE --- public/locales/de/calendar.json | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/public/locales/de/calendar.json b/public/locales/de/calendar.json index 7c495c47c..d0294be1d 100644 --- a/public/locales/de/calendar.json +++ b/public/locales/de/calendar.json @@ -1,6 +1,6 @@ { - "inYourTimeZone": " Alle Zeiten sind konvertiert zur lokalen Zeitzone:", - "addNew": "Turnier hinzufügen", + "inYourTimeZone": "Alle Zeiten sind konvertiert zur lokalen Zeitzone:", + "addNew": "Event hinzufügen", "noEvents": "Keine Events in dieser Woche", "reportResults": "Ergebnisse können eingetragen werden für:", "day": "Tag {{number}}", @@ -8,19 +8,21 @@ "participatedCount": "{{count}} teilnehmende Teams", "members": "Mitglieder", "results": "Resultate", + "createMapList": "Arenen-Liste erstellen", "forms.dates": "Datum", - "forms.bracketUrl": "Turnierbaum URL", - "forms.discordInvite": "Discord server Einladung URL", + "forms.bracketUrl": "Turnierbaum-URL", + "forms.discordInvite": "Discord-Server Einladungs-URL", "forms.tags": "Tags", "forms.tags.placeholder": "Wähle einen Tag", - "forms.tags.info": "\"Abzeichen-Preis\" tag wird automatisch hinzugefügt (falls anwendbar)", + "forms.tags.info": "\"Abzeichen-Preis\"-Tag wird automatisch hinzugefügt (falls anwendbar)", "forms.badges": "Abzeichen-Preis", "forms.badges.placeholder": "Wähle ein Abzeichen für das Event", + "forms.mapPool": "Arenen-Pool", "forms.participantCount": "Anzahl Teilnehmer", "forms.reportResultsHeader": "Berichten der Ergebnisse von {{eventName}}", - "forms.reportResultsInfo": "Die Anzahl der eintragbaren Resultate ist frei wählbar. Es kann nur das erste Team sein, die Top 3 oder mehr.", + "forms.reportResultsInfo": "Die Anzahl der eintragbaren Ergebnisse ist frei wählbar. Es kann nur das erste Team sein, die Top 3 oder mehr.", "forms.team.add": "Team hinzufügen", "forms.team.remove": "Team löschen", "forms.team.name": "Name des Teams", From 1efd49f15edcc0dcf5a6e0b821ecea4b4d176380 Mon Sep 17 00:00:00 2001 From: lolametro <13728127+lolametro@users.noreply.github.com> Date: Fri, 21 Oct 2022 21:14:30 +0200 Subject: [PATCH 26/47] Update common.json for DE --- public/locales/de/common.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index c846839b6..99e54e858 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -8,10 +8,16 @@ "pages.faq": "FAQ", "pages.builds": "Ausrüstungen", "pages.analyzer": "Ausrüstungs-Analyse", + "pages.maps": "Arenen-Listen", "header.profile": "Profil", "header.logout": "Ausloggen", "header.login": "Einloggen", + + "auth.errors.aborted": "Einloggen abgebrochen", + "auth.errors.failed": "Einloggen fehlgeschlagen", + "auth.errors.discordPermissions": "Für dein sendou.ink-Profil wird Zugriff auf den Namen, Avatar und Social-Media-Verlinkungen in deinem Discord-Profil benötigt.", + "auth.errors.unknown": "Das Einloggen über Discord ist aus einem unbekannten Grund fehlgeschlagen. Falls das weiterhin passiert, kontaktiere bitte für mehr Hilfe.", "footer.github.subtitle": "Sourcecode", "footer.twitter.subtitle": "Updates", @@ -28,6 +34,11 @@ "actions.delete": "Löschen", "actions.loadMore": "Mehr laden", "actions.close": "Schließen", + + "maps.createMapList": "Arenen-Liste erstellen", + "maps.halfSz": "50% Herrschaft", + "maps.mapPool": "Arenen-Pool", + "maps.tournamentMaplist": "Arenen-Liste für Turnier erstellen (maps.iplabs.ink)", "results": "Ergebnisse", From bc892dc2fb8cd63bb7158a5d5294feafc0097099 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Fri, 21 Oct 2022 22:15:15 +0300 Subject: [PATCH 27/47] Fix TS error --- app/modules/auth/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/modules/auth/index.ts b/app/modules/auth/index.ts index 4163a74e6..1d5424444 100644 --- a/app/modules/auth/index.ts +++ b/app/modules/auth/index.ts @@ -10,4 +10,4 @@ export { getUser, requireUser } from "./user.server"; export { useUser } from "./user"; -export { AuthErrorCode } from "./errors"; +export type { AuthErrorCode } from "./errors"; From afe24d150a887271875ec03f445302ce37b43231 Mon Sep 17 00:00:00 2001 From: lolametro <13728127+lolametro@users.noreply.github.com> Date: Fri, 21 Oct 2022 21:16:05 +0200 Subject: [PATCH 28/47] Update front.json for DE --- public/locales/de/front.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/locales/de/front.json b/public/locales/de/front.json index 3b6ff1cb4..8405878f5 100644 --- a/public/locales/de/front.json +++ b/public/locales/de/front.json @@ -6,6 +6,7 @@ "plus.description": "Sieh vergangene Plus Server Abstimmungen und mehr", "badges.description": "Liste aller Abzeichen, die du für dein Profil verdienen kannst", "analyzer.description": "Analysiere, was deine Ausrüstungen wirklich bewirken", + "maps.description": "Erstelle aus einem Arenen-Pool die Liste für dein Spiel", "recentWinners": "Aktuelle Gewinner", "upcomingEvents": "Bevorstehende Events", "articleBy": "von {{author}}" From c25d4fbd977c727f379ba99e61db8d64c693e650 Mon Sep 17 00:00:00 2001 From: lolametro <13728127+lolametro@users.noreply.github.com> Date: Fri, 21 Oct 2022 21:18:19 +0200 Subject: [PATCH 29/47] Update game-misc.json for DE --- public/locales/de/game-misc.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/locales/de/game-misc.json b/public/locales/de/game-misc.json index 446fe7423..4e3c81ce7 100644 --- a/public/locales/de/game-misc.json +++ b/public/locales/de/game-misc.json @@ -10,5 +10,10 @@ "STAGE_8": "Perlmutt-Akademie", "STAGE_9": "Störwerft", "STAGE_10": "Cetacea-Markt", - "STAGE_11": "Flunder-Funpark" + "STAGE_11": "Flunder-Funpark", + "MODE_SHORT_TW": "RK", + "MODE_SHORT_SZ": "HS", + "MODE_SHORT_TC": "TK", + "MODE_SHORT_RM": "OG", + "MODE_SHORT_CB": "MC" } From 63a80c8ecd63d04c6c38a1ba9b905299e9b0fa99 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 22 Oct 2022 11:43:19 +0300 Subject: [PATCH 30/47] Object damage hitpoints initial --- app/modules/analyzer/index.ts | 1 + app/modules/analyzer/objectHitPoints.ts | 53 +++++++++++++++ app/modules/analyzer/stats.ts | 12 ++-- app/modules/analyzer/types.ts | 2 + app/modules/analyzer/useObjectDamage.ts | 3 + app/modules/analyzer/weapon-params.json | 1 + app/routes/object-damage.tsx | 85 +++++++++++++++++++++++-- app/styles/object-damage.css | 6 ++ scripts/create-analyzer-json.ts | 5 +- 9 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 app/modules/analyzer/objectHitPoints.ts create mode 100644 app/styles/object-damage.css diff --git a/app/modules/analyzer/index.ts b/app/modules/analyzer/index.ts index 31afacf81..129d5339d 100644 --- a/app/modules/analyzer/index.ts +++ b/app/modules/analyzer/index.ts @@ -5,6 +5,7 @@ export type { Stat, AnalyzedBuild, SpecialEffectType, + HitPoints, } from "./types"; export { useAnalyzeBuild } from "./useAnalyzeBuild"; diff --git a/app/modules/analyzer/objectHitPoints.ts b/app/modules/analyzer/objectHitPoints.ts new file mode 100644 index 000000000..21f71320e --- /dev/null +++ b/app/modules/analyzer/objectHitPoints.ts @@ -0,0 +1,53 @@ +import invariant from "tiny-invariant"; +import { BIG_BUBBLER_ID, CRAB_TANK_ID, SPLASH_WALL_ID } from "../in-game-lists"; +import { specialDeviceHp, specialFieldHp, subStats } from "./stats"; +import type { + AbilityPoints, + HitPoints, + SpecialWeaponParams, + SubWeaponParams, +} from "./types"; +import weaponParams from "./weapon-params.json"; + +const PLACEHOLDER_HP = 1000; + +export const objectHitPoints = (abilityPoints: AbilityPoints): HitPoints => { + const Wsb_Shield = subStats({ + abilityPoints, + subWeaponParams: weaponParams.subWeapons[SPLASH_WALL_ID] as SubWeaponParams, + }).subHp?.value; + const GreatBarrier_Barrier = specialFieldHp({ + abilityPoints, + specialWeaponParams: weaponParams.specialWeapons[ + BIG_BUBBLER_ID + ] as SpecialWeaponParams, + })?.value; + const GreatBarrier_WeakPoint = specialDeviceHp({ + abilityPoints, + specialWeaponParams: weaponParams.specialWeapons[ + BIG_BUBBLER_ID + ] as SpecialWeaponParams, + })?.value; + + invariant(Wsb_Shield); + invariant(GreatBarrier_Barrier); + invariant(GreatBarrier_WeakPoint); + + return { + BulletUmbrellaCanopyNormal: PLACEHOLDER_HP, // ?? needs defaults + BulletUmbrellaCanopyWide: weaponParams.mainWeapons[6010].CanopyHP, + BulletUmbrellaCanopyCompact: weaponParams.mainWeapons[6020].CanopyHP, + Wsb_Shield, + Bomb_TorpedoBullet: PLACEHOLDER_HP, // ?? + Chariot: weaponParams.specialWeapons[CRAB_TANK_ID].ArmorHP, + Gachihoko_Barrier: PLACEHOLDER_HP, // ?? + GreatBarrier_Barrier, + GreatBarrier_WeakPoint, + InkRail: PLACEHOLDER_HP, // ?? + NiceBall_Armor: PLACEHOLDER_HP, // ?? + ShockSonar: PLACEHOLDER_HP, // ?? + Sponge_Versus: PLACEHOLDER_HP, // ?? + Wsb_Flag: PLACEHOLDER_HP, // ?? + Wsb_Sprinkler: PLACEHOLDER_HP, // ?? + }; +}; diff --git a/app/modules/analyzer/stats.ts b/app/modules/analyzer/stats.ts index 39812f140..185f21289 100644 --- a/app/modules/analyzer/stats.ts +++ b/app/modules/analyzer/stats.ts @@ -765,7 +765,9 @@ const SUB_WEAPON_STATS = [ }, { analyzedBuildKey: "subHp", abilityValuesKey: "MaxHP", type: "HP" }, ] as const; -function subStats(args: StatFunctionInput) { +export function subStats( + args: Pick +) { const result: Partial = {}; const SUB_STATS_KEY = "BRU"; @@ -1126,8 +1128,8 @@ function specialPaintRadius( }; } -function specialFieldHp( - args: StatFunctionInput +export function specialFieldHp( + args: Pick ): AnalyzedBuild["stats"]["specialFieldHp"] { if (!hasEffect({ key: "MaxFieldHP", weapon: args.specialWeaponParams })) { return; @@ -1150,8 +1152,8 @@ function specialFieldHp( }; } -function specialDeviceHp( - args: StatFunctionInput +export function specialDeviceHp( + args: Pick ): AnalyzedBuild["stats"]["specialDeviceHp"] { if (!hasEffect({ key: "MaxHP", weapon: args.specialWeaponParams })) { return; diff --git a/app/modules/analyzer/types.ts b/app/modules/analyzer/types.ts index 3021f2e9d..1803e4da2 100644 --- a/app/modules/analyzer/types.ts +++ b/app/modules/analyzer/types.ts @@ -164,6 +164,8 @@ export type DamageType = typeof DAMAGE_TYPE[number]; export type DamageReceiver = typeof DAMAGE_RECEIVERS[number]; +export type HitPoints = Record; + export interface Damage { value: number; type: DamageType; diff --git a/app/modules/analyzer/useObjectDamage.ts b/app/modules/analyzer/useObjectDamage.ts index 561782976..c49fa468f 100644 --- a/app/modules/analyzer/useObjectDamage.ts +++ b/app/modules/analyzer/useObjectDamage.ts @@ -2,6 +2,7 @@ import { useSearchParams } from "@remix-run/react"; import { type MainWeaponId } from "../in-game-lists"; import { damageTypeToWeaponType } from "./constants"; import { damageTypeToMultipliers, fallbackRates } from "./damageMultipliers"; +import { objectHitPoints } from "./objectHitPoints"; import { buildStats } from "./stats"; import { validatedWeaponIdFromSearchParams } from "./utils"; @@ -53,5 +54,7 @@ export function useObjectDamage() { mainWeaponId, handleChange, multipliers, + damages: analyzed.stats.damages, + hitPoints: objectHitPoints(new Map()), }; } diff --git a/app/modules/analyzer/weapon-params.json b/app/modules/analyzer/weapon-params.json index 247507468..a01399359 100644 --- a/app/modules/analyzer/weapon-params.json +++ b/app/modules/analyzer/weapon-params.json @@ -1246,6 +1246,7 @@ } }, "12": { + "ArmorHP": 5000, "overwrites": { "SpecialDurationFrame": { "High": 660, diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx index c26bfedfd..90d89e3e9 100644 --- a/app/routes/object-damage.tsx +++ b/app/routes/object-damage.tsx @@ -1,22 +1,54 @@ import { WeaponCombobox } from "~/components/Combobox"; +import { Image } from "~/components/Image"; import { Main } from "~/components/Main"; -import { useObjectDamage } from "~/modules/analyzer"; -import type { MainWeaponId } from "~/modules/in-game-lists"; -import { type SendouRouteHandle } from "~/utils/remix"; +import { + DAMAGE_RECEIVERS, + useObjectDamage, + type HitPoints, +} from "~/modules/analyzer"; +import { + type MainWeaponId, + BIG_BUBBLER_ID, + BOOYAH_BOMB_ID, + CRAB_TANK_ID, + SPLASH_WALL_ID, + SQUID_BEAKON_ID, + TORPEDO_ID, + WAVE_BREAKER_ID, + SPRINKLER_ID, +} from "~/modules/in-game-lists"; +import { + mainWeaponImageUrl, + modeImageUrl, + specialWeaponImageUrl, + subWeaponImageUrl, +} from "~/utils/urls"; +import styles from "~/styles/object-damage.css"; +import type { LinksFunction } from "@remix-run/node"; +import type { SendouRouteHandle } from "~/utils/remix"; +import type { DamageReceiver } from "~/modules/analyzer/types"; + +export const links: LinksFunction = () => { + return [{ rel: "stylesheet", href: styles }]; +}; export const handle: SendouRouteHandle = { i18n: ["weapons"], }; export default function ObjectDamagePage() { - const { mainWeaponId, handleChange, multipliers } = useObjectDamage(); + const { mainWeaponId, handleChange, multipliers, damages, hitPoints } = + useObjectDamage(); if (process.env.NODE_ENV !== "development") { return
WIP :)
; } + console.log(JSON.stringify(multipliers, null, 2)); + console.log(JSON.stringify(damages, null, 2)); + return ( -
+
-
{JSON.stringify(multipliers, null, 2)}
+
+ +
); } + +const damageReceiverImages: Record = { + Bomb_TorpedoBullet: subWeaponImageUrl(TORPEDO_ID), + Chariot: specialWeaponImageUrl(CRAB_TANK_ID), + Gachihoko_Barrier: modeImageUrl("RM"), + GreatBarrier_Barrier: specialWeaponImageUrl(BIG_BUBBLER_ID), + GreatBarrier_WeakPoint: specialWeaponImageUrl(BIG_BUBBLER_ID), + InkRail: modeImageUrl("CB"), + NiceBall_Armor: specialWeaponImageUrl(BOOYAH_BOMB_ID), + ShockSonar: specialWeaponImageUrl(WAVE_BREAKER_ID), + Sponge_Versus: modeImageUrl("CB"), + Wsb_Flag: subWeaponImageUrl(SQUID_BEAKON_ID), + Wsb_Shield: subWeaponImageUrl(SPLASH_WALL_ID), + Wsb_Sprinkler: subWeaponImageUrl(SPRINKLER_ID), + BulletUmbrellaCanopyNormal: mainWeaponImageUrl(6000), + BulletUmbrellaCanopyWide: mainWeaponImageUrl(6010), + BulletUmbrellaCanopyCompact: mainWeaponImageUrl(6020), +}; +function DamageReceiversHeader({ hitPoints }: { hitPoints: HitPoints }) { + return ( + <> + {DAMAGE_RECEIVERS.map((receiver, i) => ( + <> + +
{hitPoints[receiver]}
+ + ))} + + ); +} diff --git a/app/styles/object-damage.css b/app/styles/object-damage.css new file mode 100644 index 000000000..fc072f924 --- /dev/null +++ b/app/styles/object-damage.css @@ -0,0 +1,6 @@ +.object-damage__grid { + display: grid; + width: 100%; + gap: var(--s-3); + grid-template-columns: repeat(var(--columns-count), 1fr); +} diff --git a/scripts/create-analyzer-json.ts b/scripts/create-analyzer-json.ts index 9577fe7de..75aab23cc 100644 --- a/scripts/create-analyzer-json.ts +++ b/scripts/create-analyzer-json.ts @@ -314,7 +314,10 @@ function parametersToSpecialWeaponResult(params: any) { resultUnwrapped["SplashAroundPaintRadius"] = undefined; } - return { overwrites: resultUnwrapped }; + return { + ArmorHP: params["WeaponSpChariotParam"]?.["ArmorHP"], + overwrites: resultUnwrapped, + }; } function unwrapSubSpecialSpecUpList(result: any) { From 89c388e1c35a2f967dd7c85c0224aef7cfac9fb6 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 22 Oct 2022 12:08:20 +0300 Subject: [PATCH 31/47] Fix hp showed wrong for Crab Tank/brellas --- app/modules/analyzer/objectHitPoints.ts | 11 ++++++++--- app/modules/analyzer/stats.ts | 7 ++++--- app/modules/analyzer/utils.ts | 2 ++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/modules/analyzer/objectHitPoints.ts b/app/modules/analyzer/objectHitPoints.ts index 21f71320e..d3b9136e6 100644 --- a/app/modules/analyzer/objectHitPoints.ts +++ b/app/modules/analyzer/objectHitPoints.ts @@ -7,6 +7,7 @@ import type { SpecialWeaponParams, SubWeaponParams, } from "./types"; +import { hpDivided } from "./utils"; import weaponParams from "./weapon-params.json"; const PLACEHOLDER_HP = 1000; @@ -35,11 +36,15 @@ export const objectHitPoints = (abilityPoints: AbilityPoints): HitPoints => { return { BulletUmbrellaCanopyNormal: PLACEHOLDER_HP, // ?? needs defaults - BulletUmbrellaCanopyWide: weaponParams.mainWeapons[6010].CanopyHP, - BulletUmbrellaCanopyCompact: weaponParams.mainWeapons[6020].CanopyHP, + BulletUmbrellaCanopyWide: hpDivided( + weaponParams.mainWeapons[6010].CanopyHP + ), + BulletUmbrellaCanopyCompact: hpDivided( + weaponParams.mainWeapons[6020].CanopyHP + ), Wsb_Shield, Bomb_TorpedoBullet: PLACEHOLDER_HP, // ?? - Chariot: weaponParams.specialWeapons[CRAB_TANK_ID].ArmorHP, + Chariot: hpDivided(weaponParams.specialWeapons[CRAB_TANK_ID].ArmorHP), Gachihoko_Barrier: PLACEHOLDER_HP, // ?? GreatBarrier_Barrier, GreatBarrier_WeakPoint, diff --git a/app/modules/analyzer/stats.ts b/app/modules/analyzer/stats.ts index 185f21289..c6059f83c 100644 --- a/app/modules/analyzer/stats.ts +++ b/app/modules/analyzer/stats.ts @@ -17,6 +17,7 @@ import { abilityPointsToEffects, apFromMap, hasEffect, + hpDivided, weaponParams, } from "./utils"; import { assertUnreachable } from "~/utils/types"; @@ -789,7 +790,7 @@ export function subStats( case "NO_CHANGE": return roundToTwoDecimalPlaces(effect); case "HP": - return roundToTwoDecimalPlaces(effect / 10); + return roundToTwoDecimalPlaces(hpDivided(effect)); case "TIME": return framesToSeconds(effect); default: @@ -1170,8 +1171,8 @@ export function specialDeviceHp( }); return { - baseValue: Math.round(baseEffect / 10), - value: Math.round(effect / 10), + baseValue: Math.round(hpDivided(baseEffect)), + value: Math.round(hpDivided(effect)), modifiedBy: SPECIAL_DEVICE_HP_KEY, }; } diff --git a/app/modules/analyzer/utils.ts b/app/modules/analyzer/utils.ts index 8dcff6526..543b207ed 100644 --- a/app/modules/analyzer/utils.ts +++ b/app/modules/analyzer/utils.ts @@ -165,3 +165,5 @@ export function validatedWeaponIdFromSearchParams( return weaponCategories[0].weaponIds[0]; } + +export const hpDivided = (hp: number) => hp / 10; From 71998bf4852020fd57f56e11ee38c275eb08d639 Mon Sep 17 00:00:00 2001 From: lolametro <13728127+lolametro@users.noreply.github.com> Date: Sat, 22 Oct 2022 11:17:18 +0200 Subject: [PATCH 32/47] Merge existing and new locs in common.json DE --- public/locales/de/common.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 99e54e858..6b8866bda 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -16,8 +16,8 @@ "auth.errors.aborted": "Einloggen abgebrochen", "auth.errors.failed": "Einloggen fehlgeschlagen", - "auth.errors.discordPermissions": "Für dein sendou.ink-Profil wird Zugriff auf den Namen, Avatar und Social-Media-Verlinkungen in deinem Discord-Profil benötigt.", - "auth.errors.unknown": "Das Einloggen über Discord ist aus einem unbekannten Grund fehlgeschlagen. Falls das weiterhin passiert, kontaktiere bitte für mehr Hilfe.", + "auth.errors.discordPermissions": "Für dein sendou.ink-Profil benötigt die Seite Zugriff auf den Namen, Avatar und verbundene Social-Media-Accounts in deinem Discord-Profil.", + "auth.errors.unknown": "Das Einloggen via Discord ist aus unbekannten Gründen fehlgeschlagen. Falls dies wiederholt auftritt, kontaktiere uns bitte.", "footer.github.subtitle": "Sourcecode", "footer.twitter.subtitle": "Updates", @@ -67,9 +67,4 @@ "weapon.category.BRELLAS": "Pluviatoren", "weapon.category.STRINGERS": "Stringer", "weapon.category.SPLATANAS": "Splatanas", - - "auth.errors.aborted": "Login Abgebrochen", - "auth.errors.failed": "Login Fehlgeschlagen", - "auth.errors.discordPermissions": "Für dein sendou.ink Profil braucht die Seite die Erlaubnis deinen Discord-Namen, Avatar, und verbundene Social Accounts auszulesen.", - "auth.errors.unknown": "Der Login via Discord ist aus unbekannten Gründen fehlgeschlagen. Falls dies wiederholt auftritt, kontaktiere uns bitte." } From e705c58ebb3caa580e80430bccbf6ea727957c6a Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 22 Oct 2022 12:40:36 +0300 Subject: [PATCH 33/47] More type safety to SendouRouteHandle.navItemName --- app/utils/remix.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/utils/remix.ts b/app/utils/remix.ts index 3bf68b402..f54507633 100644 --- a/app/utils/remix.ts +++ b/app/utils/remix.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { type TFunction, type Namespace } from "react-i18next"; import { type RouteMatch } from "@remix-run/react"; +import type navItems from "~/components/layout/nav-items.json"; export function notFoundIfFalsy(value: T | null | undefined): T { if (!value) throw new Response(null, { status: 404 }); @@ -113,5 +114,5 @@ export type SendouRouteHandle = { }) => string | undefined; /** The name of a navItem that is active on this route. See nav-items.json */ - navItemName?: string; + navItemName?: typeof navItems[number]["name"]; }; From ce50e62172b0e39e4a73f8b556662424b384a8c5 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 22 Oct 2022 12:43:13 +0300 Subject: [PATCH 34/47] Run check-translation-jsons --- public/locales/de/common.json | 6 ++--- translation-progress.md | 45 ++++++----------------------------- 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 6b8866bda..af292c7b5 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -13,7 +13,7 @@ "header.profile": "Profil", "header.logout": "Ausloggen", "header.login": "Einloggen", - + "auth.errors.aborted": "Einloggen abgebrochen", "auth.errors.failed": "Einloggen fehlgeschlagen", "auth.errors.discordPermissions": "Für dein sendou.ink-Profil benötigt die Seite Zugriff auf den Namen, Avatar und verbundene Social-Media-Accounts in deinem Discord-Profil.", @@ -34,7 +34,7 @@ "actions.delete": "Löschen", "actions.loadMore": "Mehr laden", "actions.close": "Schließen", - + "maps.createMapList": "Arenen-Liste erstellen", "maps.halfSz": "50% Herrschaft", "maps.mapPool": "Arenen-Pool", @@ -66,5 +66,5 @@ "weapon.category.DUALIES": "Doppler", "weapon.category.BRELLAS": "Pluviatoren", "weapon.category.STRINGERS": "Stringer", - "weapon.category.SPLATANAS": "Splatanas", + "weapon.category.SPLATANAS": "Splatanas" } diff --git a/translation-progress.md b/translation-progress.md index 5a12774e0..e8a162076 100644 --- a/translation-progress.md +++ b/translation-progress.md @@ -80,31 +80,18 @@ **11/11** -### 🟡 calendar.json +### 🟢 calendar.json -**44/46** - -
-Missing - -- createMapList -- forms.mapPool - -
+**46/46** ### 🟡 common.json -**54/60** +**59/60**
Missing -- pages.maps - actions.copyToClipboard -- maps.createMapList -- maps.halfSz -- maps.mapPool -- maps.tournamentMaplist
@@ -116,31 +103,13 @@ **6/6** -### 🟡 front.json +### 🟢 front.json -**10/11** +**11/11** -
-Missing +### 🟢 game-misc.json -- maps.description - -
- -### 🟡 game-misc.json - -**12/17** - -
-Missing - -- MODE_SHORT_TW -- MODE_SHORT_SZ -- MODE_SHORT_TC -- MODE_SHORT_RM -- MODE_SHORT_CB - -
+**17/17** ### 🟢 user.json From b448c19b719d01e74590439ba11f94c462ec7295 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 22 Oct 2022 16:43:31 +0300 Subject: [PATCH 35/47] Object damages with calculation --- app/modules/analyzer/damageMultipliers.ts | 14 +-- app/modules/analyzer/useObjectDamage.ts | 8 +- app/routes/object-damage.tsx | 118 ++++++++++++++++------ app/styles/object-damage.css | 57 ++++++++++- 4 files changed, 156 insertions(+), 41 deletions(-) diff --git a/app/modules/analyzer/damageMultipliers.ts b/app/modules/analyzer/damageMultipliers.ts index 21ca5a706..f1ab1b6c3 100644 --- a/app/modules/analyzer/damageMultipliers.ts +++ b/app/modules/analyzer/damageMultipliers.ts @@ -1,4 +1,4 @@ -import type { DamageType } from "./types"; +import type { DamageReceiver, DamageType } from "./types"; import objectDamages from "./object-dmg.json"; import type { MainWeaponId, @@ -78,11 +78,13 @@ export function damageTypeToMultipliers({ return null; } -export function fallbackRates( +export function multipliersToRecordWithFallbacks( multipliers: ReturnType ) { - return DAMAGE_RECEIVERS.map((receiver) => ({ - target: receiver, - rate: multipliers?.find((m) => m.target === receiver)?.rate ?? 1, - })); + return Object.fromEntries( + DAMAGE_RECEIVERS.map((receiver) => [ + receiver, + multipliers?.find((m) => m.target === receiver)?.rate ?? 1, + ]) + ) as Record; } diff --git a/app/modules/analyzer/useObjectDamage.ts b/app/modules/analyzer/useObjectDamage.ts index c49fa468f..2207d89ee 100644 --- a/app/modules/analyzer/useObjectDamage.ts +++ b/app/modules/analyzer/useObjectDamage.ts @@ -1,7 +1,10 @@ import { useSearchParams } from "@remix-run/react"; import { type MainWeaponId } from "../in-game-lists"; import { damageTypeToWeaponType } from "./constants"; -import { damageTypeToMultipliers, fallbackRates } from "./damageMultipliers"; +import { + damageTypeToMultipliers, + multipliersToRecordWithFallbacks, +} from "./damageMultipliers"; import { objectHitPoints } from "./objectHitPoints"; import { buildStats } from "./stats"; import { validatedWeaponIdFromSearchParams } from "./utils"; @@ -40,7 +43,7 @@ export function useObjectDamage() { return [ damage.type, - fallbackRates( + multipliersToRecordWithFallbacks( damageTypeToMultipliers({ type: damage.type, weapon: { type: weaponType, id: weaponId }, @@ -52,6 +55,7 @@ export function useObjectDamage() { return { mainWeaponId, + subWeaponId: analyzed.weapon.subWeaponSplId, handleChange, multipliers, damages: analyzed.stats.damages, diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx index 90d89e3e9..46a3342fc 100644 --- a/app/routes/object-damage.tsx +++ b/app/routes/object-damage.tsx @@ -1,11 +1,7 @@ import { WeaponCombobox } from "~/components/Combobox"; import { Image } from "~/components/Image"; import { Main } from "~/components/Main"; -import { - DAMAGE_RECEIVERS, - useObjectDamage, - type HitPoints, -} from "~/modules/analyzer"; +import { DAMAGE_RECEIVERS, useObjectDamage } from "~/modules/analyzer"; import { type MainWeaponId, BIG_BUBBLER_ID, @@ -27,26 +23,32 @@ import styles from "~/styles/object-damage.css"; import type { LinksFunction } from "@remix-run/node"; import type { SendouRouteHandle } from "~/utils/remix"; import type { DamageReceiver } from "~/modules/analyzer/types"; +import React from "react"; +import { roundToTwoDecimalPlaces } from "~/utils/number"; +import { useTranslation } from "react-i18next"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; }; export const handle: SendouRouteHandle = { - i18n: ["weapons"], + i18n: ["weapons", "analyzer"], }; export default function ObjectDamagePage() { - const { mainWeaponId, handleChange, multipliers, damages, hitPoints } = - useObjectDamage(); + const { + mainWeaponId, + subWeaponId, + handleChange, + multipliers, + damages, + hitPoints, + } = useObjectDamage(); if (process.env.NODE_ENV !== "development") { return
WIP :)
; } - console.log(JSON.stringify(multipliers, null, 2)); - console.log(JSON.stringify(damages, null, 2)); - return (
-
- -
+
); } @@ -88,21 +90,75 @@ const damageReceiverImages: Record = { BulletUmbrellaCanopyWide: mainWeaponImageUrl(6010), BulletUmbrellaCanopyCompact: mainWeaponImageUrl(6020), }; -function DamageReceiversHeader({ hitPoints }: { hitPoints: HitPoints }) { + +function DamageReceiversGrid({ + subWeaponId, + hitPoints, + damages, + multipliers, +}: Pick< + ReturnType, + "hitPoints" | "damages" | "multipliers" | "subWeaponId" +>) { + const { t } = useTranslation(["weapons", "analyzer"]); + return ( - <> - {DAMAGE_RECEIVERS.map((receiver, i) => ( - <> - -
{hitPoints[receiver]}
- +
+
+
+ {damages.map((damage) => ( +
+ {damage.type.startsWith("BOMB_") + ? t(`weapons:SUB_${subWeaponId}`) + : t(`analyzer:damage.${damage.type as "NORMAL_MIN"}`)} +
))} - + {DAMAGE_RECEIVERS.map((receiver, i) => { + const damageReceiverHp = hitPoints[receiver]; + + return ( + + +
{damageReceiverHp}hp
+ {damages.map((damage) => { + const multiplier = multipliers[damage.type]![receiver]; + const damagePerHit = roundToTwoDecimalPlaces( + damage.value * multiplier + ); + + const hitsToDestroy = Math.ceil(damageReceiverHp / damagePerHit); + + return ( +
+
+ + DMG + +
{damagePerHit}
+ + HTD + +
{hitsToDestroy}
+
+
×{multiplier}
+
+ ); + })} +
+ ); + })} +
); } diff --git a/app/styles/object-damage.css b/app/styles/object-damage.css index fc072f924..3aa602cd1 100644 --- a/app/styles/object-damage.css +++ b/app/styles/object-damage.css @@ -1,6 +1,59 @@ .object-damage__grid { display: grid; width: 100%; - gap: var(--s-3); - grid-template-columns: repeat(var(--columns-count), 1fr); + column-gap: var(--s-6); + + /* xxx: make dynamic */ + grid-template-columns: max-content max-content 1fr 1fr 1fr 1fr 1fr; + place-items: center; + row-gap: var(--s-3); +} + +.object-damage__hp { + font-size: var(--fonts-xs); + font-weight: var(--semi-bold); +} + +.object-damage__table-header { + position: sticky; + top: 0; + width: 100%; + border-radius: var(--rounded); + background-color: var(--bg-darker); + font-size: var(--fonts-xs); + font-weight: var(--semi-bold); + padding-block: var(--s-2); + text-align: center; +} + +.object-damage__table-card { + display: grid; + width: 100%; + height: 100%; + padding: var(--s-2); + border-radius: var(--rounded); + background-color: var(--bg-lighter); + font-size: var(--fonts-xs); + font-weight: var(--semi-bold); + place-items: center; +} + +.object-damage__table-card__results { + display: grid; + column-gap: var(--s-2); + grid-template-columns: 1fr 1fr; +} + +.object-damage__abbr { + color: var(--text-lighter); + font-weight: var(--bold); + text-decoration: none; +} + +.object-damage__multiplier { + color: var(--theme); + font-size: var(--fonts-xxs); + font-weight: var(--bold); + letter-spacing: 0.5px; + margin-block-start: var(--s-2); } From 430d347f797408e1b363f55380480b855990d386 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 23 Oct 2022 10:39:23 +0300 Subject: [PATCH 36/47] Add damages from Lean --- app/modules/analyzer/constants.ts | 4 ++-- app/modules/analyzer/objectHitPoints.ts | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/modules/analyzer/constants.ts b/app/modules/analyzer/constants.ts index 21181eda9..046c160c0 100644 --- a/app/modules/analyzer/constants.ts +++ b/app/modules/analyzer/constants.ts @@ -9,10 +9,10 @@ export const DAMAGE_RECEIVERS = [ "Gachihoko_Barrier", // Rainmaker Shield "GreatBarrier_Barrier", // Big Bubbler Shield "GreatBarrier_WeakPoint", // Big Bubbler Weak Point - "InkRail", // InkRail + // "InkRail", // InkRail "NiceBall_Armor", // Booyah Bomb Armor "ShockSonar", // Wave Breaker - "Sponge_Versus", // Sponge + // "Sponge_Versus", // Sponge "Wsb_Flag", // Squid Beakon "Wsb_Shield", // Splash Wall "Wsb_Sprinkler", // Sprinkler diff --git a/app/modules/analyzer/objectHitPoints.ts b/app/modules/analyzer/objectHitPoints.ts index d3b9136e6..ced8e7121 100644 --- a/app/modules/analyzer/objectHitPoints.ts +++ b/app/modules/analyzer/objectHitPoints.ts @@ -11,6 +11,9 @@ import { hpDivided } from "./utils"; import weaponParams from "./weapon-params.json"; const PLACEHOLDER_HP = 1000; +const WAVE_BREAKER_HP = 400; +const SPRINKER_HP = 100; +const RAINMAKER_HP = 1000; export const objectHitPoints = (abilityPoints: AbilityPoints): HitPoints => { const Wsb_Shield = subStats({ @@ -45,14 +48,12 @@ export const objectHitPoints = (abilityPoints: AbilityPoints): HitPoints => { Wsb_Shield, Bomb_TorpedoBullet: PLACEHOLDER_HP, // ?? Chariot: hpDivided(weaponParams.specialWeapons[CRAB_TANK_ID].ArmorHP), - Gachihoko_Barrier: PLACEHOLDER_HP, // ?? + Gachihoko_Barrier: RAINMAKER_HP, GreatBarrier_Barrier, GreatBarrier_WeakPoint, - InkRail: PLACEHOLDER_HP, // ?? NiceBall_Armor: PLACEHOLDER_HP, // ?? - ShockSonar: PLACEHOLDER_HP, // ?? - Sponge_Versus: PLACEHOLDER_HP, // ?? + ShockSonar: WAVE_BREAKER_HP, Wsb_Flag: PLACEHOLDER_HP, // ?? - Wsb_Sprinkler: PLACEHOLDER_HP, // ?? + Wsb_Sprinkler: SPRINKER_HP, }; }; From 97080434638fdd75d2f27259e3c04d4f9febfdc9 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 23 Oct 2022 10:50:53 +0300 Subject: [PATCH 37/47] Add distance to obj dmg table headers --- app/routes/object-damage.tsx | 10 ++++++++-- app/styles/object-damage.css | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx index 46a3342fc..4e9dbab39 100644 --- a/app/routes/object-damage.tsx +++ b/app/routes/object-damage.tsx @@ -26,6 +26,7 @@ import type { DamageReceiver } from "~/modules/analyzer/types"; import React from "react"; import { roundToTwoDecimalPlaces } from "~/utils/number"; import { useTranslation } from "react-i18next"; +import clsx from "clsx"; export const links: LinksFunction = () => { return [{ rel: "stylesheet", href: styles }]; @@ -79,10 +80,8 @@ const damageReceiverImages: Record = { Gachihoko_Barrier: modeImageUrl("RM"), GreatBarrier_Barrier: specialWeaponImageUrl(BIG_BUBBLER_ID), GreatBarrier_WeakPoint: specialWeaponImageUrl(BIG_BUBBLER_ID), - InkRail: modeImageUrl("CB"), NiceBall_Armor: specialWeaponImageUrl(BOOYAH_BOMB_ID), ShockSonar: specialWeaponImageUrl(WAVE_BREAKER_ID), - Sponge_Versus: modeImageUrl("CB"), Wsb_Flag: subWeaponImageUrl(SQUID_BEAKON_ID), Wsb_Shield: subWeaponImageUrl(SPLASH_WALL_ID), Wsb_Sprinkler: subWeaponImageUrl(SPRINKLER_ID), @@ -114,6 +113,13 @@ function DamageReceiversGrid({ {damage.type.startsWith("BOMB_") ? t(`weapons:SUB_${subWeaponId}`) : t(`analyzer:damage.${damage.type as "NORMAL_MIN"}`)} +
+ Distance: {damage.distance} +
))} {DAMAGE_RECEIVERS.map((receiver, i) => { diff --git a/app/styles/object-damage.css b/app/styles/object-damage.css index 3aa602cd1..845d61dd5 100644 --- a/app/styles/object-damage.css +++ b/app/styles/object-damage.css @@ -26,6 +26,12 @@ text-align: center; } +.object-damage__distance { + color: var(--text-lighter); + font-size: var(--fonts-xxs); + margin-block-start: var(--s-1); +} + .object-damage__table-card { display: grid; width: 100%; From cca225c780383c7c21da9277dd5303f6ea63c86d Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 23 Oct 2022 11:13:02 +0300 Subject: [PATCH 38/47] Remove calculations from component code --- .../{damageMultipliers.ts => objectDamage.ts} | 68 ++++++++++++++++++- app/modules/analyzer/useObjectDamage.ts | 37 ++-------- app/routes/object-damage.tsx | 56 ++++++--------- 3 files changed, 93 insertions(+), 68 deletions(-) rename app/modules/analyzer/{damageMultipliers.ts => objectDamage.ts} (55%) diff --git a/app/modules/analyzer/damageMultipliers.ts b/app/modules/analyzer/objectDamage.ts similarity index 55% rename from app/modules/analyzer/damageMultipliers.ts rename to app/modules/analyzer/objectDamage.ts index f1ab1b6c3..fa26662db 100644 --- a/app/modules/analyzer/damageMultipliers.ts +++ b/app/modules/analyzer/objectDamage.ts @@ -1,11 +1,18 @@ -import type { DamageReceiver, DamageType } from "./types"; +import type { + AbilityPoints, + AnalyzedBuild, + DamageReceiver, + DamageType, +} from "./types"; import objectDamages from "./object-dmg.json"; import type { MainWeaponId, SpecialWeaponId, SubWeaponId, } from "../in-game-lists"; -import { DAMAGE_RECEIVERS } from "./constants"; +import { damageTypeToWeaponType, DAMAGE_RECEIVERS } from "./constants"; +import { roundToTwoDecimalPlaces } from "~/utils/number"; +import { objectHitPoints } from "./objectHitPoints"; /** Keys to check in the json. Lower index takes priority over higher. If key is omitted means any key with valid weapon id is okay. One json key can only map to one DamageType. */ const objectDamageJsonKeyPriority: Partial< @@ -88,3 +95,60 @@ export function multipliersToRecordWithFallbacks( ]) ) as Record; } + +export function calculateDamage({ + analyzed, + mainWeaponId, + abilityPoints, +}: { + analyzed: AnalyzedBuild; + mainWeaponId: MainWeaponId; + abilityPoints: AbilityPoints; +}) { + const hitPoints = objectHitPoints(abilityPoints); + const multipliers = Object.fromEntries( + analyzed.stats.damages.map((damage) => { + const weaponType = damageTypeToWeaponType[damage.type]; + const weaponId: any = + weaponType === "MAIN" + ? mainWeaponId + : weaponType === "SUB" + ? analyzed.weapon.subWeaponSplId + : analyzed.weapon.specialWeaponSplId; + + return [ + damage.type, + multipliersToRecordWithFallbacks( + damageTypeToMultipliers({ + type: damage.type, + weapon: { type: weaponType, id: weaponId }, + }) + ), + ]; + }) + ); + + return DAMAGE_RECEIVERS.map((receiver) => { + const damageReceiverHp = hitPoints[receiver]; + + return { + receiver, + hitPoints: damageReceiverHp, + damages: analyzed.stats.damages.map((damage) => { + const multiplier = multipliers[damage.type]![receiver]; + const damagePerHit = roundToTwoDecimalPlaces(damage.value * multiplier); + + const hitsToDestroy = Math.ceil(damageReceiverHp / damagePerHit); + + return { + value: damagePerHit, + hitsToDestroy, + multiplier, + type: damage.type, + id: damage.id, + distance: damage.distance, + }; + }), + }; + }); +} diff --git a/app/modules/analyzer/useObjectDamage.ts b/app/modules/analyzer/useObjectDamage.ts index 2207d89ee..f72413a75 100644 --- a/app/modules/analyzer/useObjectDamage.ts +++ b/app/modules/analyzer/useObjectDamage.ts @@ -1,11 +1,6 @@ import { useSearchParams } from "@remix-run/react"; import { type MainWeaponId } from "../in-game-lists"; -import { damageTypeToWeaponType } from "./constants"; -import { - damageTypeToMultipliers, - multipliersToRecordWithFallbacks, -} from "./damageMultipliers"; -import { objectHitPoints } from "./objectHitPoints"; +import { calculateDamage } from "./objectDamage"; import { buildStats } from "./stats"; import { validatedWeaponIdFromSearchParams } from "./utils"; @@ -31,34 +26,14 @@ export function useObjectDamage() { weaponSplId: mainWeaponId, }); - const multipliers = Object.fromEntries( - analyzed.stats.damages.map((damage) => { - const weaponType = damageTypeToWeaponType[damage.type]; - const weaponId: any = - weaponType === "MAIN" - ? mainWeaponId - : weaponType === "SUB" - ? analyzed.weapon.subWeaponSplId - : analyzed.weapon.specialWeaponSplId; - - return [ - damage.type, - multipliersToRecordWithFallbacks( - damageTypeToMultipliers({ - type: damage.type, - weapon: { type: weaponType, id: weaponId }, - }) - ), - ]; - }) - ); - return { mainWeaponId, subWeaponId: analyzed.weapon.subWeaponSplId, handleChange, - multipliers, - damages: analyzed.stats.damages, - hitPoints: objectHitPoints(new Map()), + damagesToReceivers: calculateDamage({ + abilityPoints: new Map(), + analyzed, + mainWeaponId, + }), }; } diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx index 4e9dbab39..dc6fcd63c 100644 --- a/app/routes/object-damage.tsx +++ b/app/routes/object-damage.tsx @@ -24,7 +24,6 @@ import type { LinksFunction } from "@remix-run/node"; import type { SendouRouteHandle } from "~/utils/remix"; import type { DamageReceiver } from "~/modules/analyzer/types"; import React from "react"; -import { roundToTwoDecimalPlaces } from "~/utils/number"; import { useTranslation } from "react-i18next"; import clsx from "clsx"; @@ -37,14 +36,8 @@ export const handle: SendouRouteHandle = { }; export default function ObjectDamagePage() { - const { - mainWeaponId, - subWeaponId, - handleChange, - multipliers, - damages, - hitPoints, - } = useObjectDamage(); + const { mainWeaponId, subWeaponId, handleChange, damagesToReceivers } = + useObjectDamage(); if (process.env.NODE_ENV !== "development") { return
WIP :)
; @@ -66,9 +59,7 @@ export default function ObjectDamagePage() { />
); @@ -92,23 +83,23 @@ const damageReceiverImages: Record = { function DamageReceiversGrid({ subWeaponId, - hitPoints, - damages, - multipliers, + damagesToReceivers, }: Pick< ReturnType, - "hitPoints" | "damages" | "multipliers" | "subWeaponId" + "damagesToReceivers" | "subWeaponId" >) { const { t } = useTranslation(["weapons", "analyzer"]); return (
- {damages.map((damage) => ( + {damagesToReceivers[0]?.damages.map((damage) => (
{damage.type.startsWith("BOMB_") ? t(`weapons:SUB_${subWeaponId}`) @@ -122,43 +113,38 @@ function DamageReceiversGrid({
))} - {DAMAGE_RECEIVERS.map((receiver, i) => { - const damageReceiverHp = hitPoints[receiver]; - + {damagesToReceivers.map((damageToReceiver, i) => { return ( - + -
{damageReceiverHp}hp
- {damages.map((damage) => { - const multiplier = multipliers[damage.type]![receiver]; - const damagePerHit = roundToTwoDecimalPlaces( - damage.value * multiplier - ); - - const hitsToDestroy = Math.ceil(damageReceiverHp / damagePerHit); - +
+ {damageToReceiver.hitPoints}hp +
+ {damageToReceiver.damages.map((damage) => { return (
DMG -
{damagePerHit}
+
{damage.value}
HTD -
{hitsToDestroy}
+
{damage.hitsToDestroy}
+
+
+ ×{damage.multiplier}
-
×{multiplier}
); })} From 3fe59c1a88bfbe979161abdf2a4f2159d3bba284 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 23 Oct 2022 11:18:57 +0300 Subject: [PATCH 39/47] Table layout to work with any number of data cols --- app/routes/object-damage.tsx | 17 +++++++++++++---- app/styles/object-damage.css | 3 --- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/routes/object-damage.tsx b/app/routes/object-damage.tsx index dc6fcd63c..a14500dc2 100644 --- a/app/routes/object-damage.tsx +++ b/app/routes/object-damage.tsx @@ -1,7 +1,7 @@ import { WeaponCombobox } from "~/components/Combobox"; import { Image } from "~/components/Image"; import { Main } from "~/components/Main"; -import { DAMAGE_RECEIVERS, useObjectDamage } from "~/modules/analyzer"; +import { useObjectDamage } from "~/modules/analyzer"; import { type MainWeaponId, BIG_BUBBLER_ID, @@ -93,9 +93,11 @@ function DamageReceiversGrid({ return (
@@ -154,3 +156,10 @@ function DamageReceiversGrid({
); } + +function gridTemplateColumnsValue(dataColumnsCount: number) { + return `max-content max-content ${new Array(dataColumnsCount) + .fill(null) + .map(() => `1fr`) + .join(" ")}`; +} diff --git a/app/styles/object-damage.css b/app/styles/object-damage.css index 845d61dd5..cc0a54a0a 100644 --- a/app/styles/object-damage.css +++ b/app/styles/object-damage.css @@ -2,9 +2,6 @@ display: grid; width: 100%; column-gap: var(--s-6); - - /* xxx: make dynamic */ - grid-template-columns: max-content max-content 1fr 1fr 1fr 1fr 1fr; place-items: center; row-gap: var(--s-3); } From 86a5e9ee2af881344792149b92b400d85ff01dd1 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 23 Oct 2022 11:59:03 +0300 Subject: [PATCH 40/47] Objective damage table change SPU/BRU --- app/components/Label.tsx | 4 +- app/modules/analyzer/index.ts | 2 + app/modules/analyzer/useObjectDamage.ts | 24 ++++++++- app/modules/analyzer/utils.ts | 12 +++++ app/routes/object-damage.tsx | 70 +++++++++++++++++++------ app/styles/object-damage.css | 11 ++++ 6 files changed, 105 insertions(+), 18 deletions(-) diff --git a/app/components/Label.tsx b/app/components/Label.tsx index 828456dc7..08e349d28 100644 --- a/app/components/Label.tsx +++ b/app/components/Label.tsx @@ -13,6 +13,7 @@ type LabelProps = Pick< }; required?: boolean; className?: string; + labelClassName?: string; }; export function Label({ @@ -21,10 +22,11 @@ export function Label({ children, htmlFor, className, + labelClassName, }: LabelProps) { return (
-
- +