From f48c49aaa5b8a821513781761d00c5dd75596aa7 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sat, 21 Jan 2023 12:10:40 +0200 Subject: [PATCH] Build Analyzer: AP comparing --- app/features/build-analyzer/analyzer-hooks.ts | 7 +- app/features/build-analyzer/analyzer-types.ts | 2 +- app/features/build-analyzer/analyzer.css | 17 +++ .../build-analyzer/core/utils.test.ts | 7 +- app/features/build-analyzer/core/utils.ts | 2 +- .../build-analyzer/routes/analyzer.tsx | 134 +++++++++++------- app/root.tsx | 1 - app/styles/utils.css | 4 + public/locales/da/analyzer.json | 1 - public/locales/de/analyzer.json | 1 - public/locales/en/analyzer.json | 2 +- public/locales/es-ES/analyzer.json | 1 - public/locales/es-US/analyzer.json | 1 - public/locales/fr/analyzer.json | 1 - public/locales/it/analyzer.json | 1 - public/locales/ja/analyzer.json | 1 - public/locales/nl/analyzer.json | 1 - public/locales/ru/analyzer.json | 1 - public/locales/zh/analyzer.json | 1 - 19 files changed, 110 insertions(+), 76 deletions(-) diff --git a/app/features/build-analyzer/analyzer-hooks.ts b/app/features/build-analyzer/analyzer-hooks.ts index 0303a0745..353519434 100644 --- a/app/features/build-analyzer/analyzer-hooks.ts +++ b/app/features/build-analyzer/analyzer-hooks.ts @@ -47,7 +47,7 @@ export function useAnalyzeBuild() { newBuild2?: BuildAbilitiesTupleWithUnknown; newLdeIntensity?: number; newEffects?: Array; - newFocused?: 1 | 2; + newFocused?: 1 | 2 | 3; }) => { setSearchParams( { @@ -93,13 +93,15 @@ export function useAnalyzeBuild() { return { build, build2, + focusedBuild: focused === 1 ? build : focused === 2 ? build2 : null, focused, mainWeaponId, handleChange, analyzed, analyzed2, abilityPoints, - effects, + abilityPoints2, + allEffects: Array.from(new Set([...effects, ...effects2])), ldeIntensity, }; } @@ -229,6 +231,7 @@ function validatedFocusedFromSearchParams({ const focused = searchParams.get("focused"); if (focused === "2") return 2; + if (focused === "3") return 3; return 1; } diff --git a/app/features/build-analyzer/analyzer-types.ts b/app/features/build-analyzer/analyzer-types.ts index b2a15d281..cbfeaf6ff 100644 --- a/app/features/build-analyzer/analyzer-types.ts +++ b/app/features/build-analyzer/analyzer-types.ts @@ -135,7 +135,7 @@ export interface Stat { } export type AbilityPoints = Map< - Ability, + AbilityWithUnknown, { ap: number; apBeforeTacticooler: number } >; diff --git a/app/features/build-analyzer/analyzer.css b/app/features/build-analyzer/analyzer.css index 938d4fb07..e549dea2f 100644 --- a/app/features/build-analyzer/analyzer.css +++ b/app/features/build-analyzer/analyzer.css @@ -14,6 +14,23 @@ gap: var(--s-8); } +.analyzer__ap-compare { + display: grid; + grid-template-columns: 1fr max-content max-content max-content 1fr; + gap: var(--s-2); + font-size: var(--fonts-xs); + align-items: center; +} + +.analyzer__ap-compare__bar { + height: 100%; + background-color: var(--theme); +} + +.analyzer__ap-compare__bar.analyzer__better { + background-color: var(--theme-success); +} + .analyzer__effects-selector { display: grid; gap: var(--s-2); diff --git a/app/features/build-analyzer/core/utils.test.ts b/app/features/build-analyzer/core/utils.test.ts index bc8dd5f1c..b860acc43 100644 --- a/app/features/build-analyzer/core/utils.test.ts +++ b/app/features/build-analyzer/core/utils.test.ts @@ -12,12 +12,6 @@ const EMPTY_ROW: [ AbilityWithUnknown ] = ["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"]; -BuildToAbilityPoints("Empty build leads to empty AP map", () => { - const aps = buildToAbilityPoints([EMPTY_ROW, EMPTY_ROW, EMPTY_ROW]); - - assert.equal(aps.size, 0); -}); - BuildToAbilityPoints("Calculates ability points", () => { const aps = buildToAbilityPoints([ ["SS", "SS", "RSU", "RSU"], @@ -27,6 +21,7 @@ BuildToAbilityPoints("Calculates ability points", () => { assert.equal(aps.get("SS")?.ap, 13); assert.equal(aps.get("RSU")?.ap, 6); + assert.equal(aps.get("UNKNOWN")?.ap, 38); }); BuildToAbilityPoints("Handles ability doubler", () => { diff --git a/app/features/build-analyzer/core/utils.ts b/app/features/build-analyzer/core/utils.ts index c47d3cc8f..fe85b50aa 100644 --- a/app/features/build-analyzer/core/utils.ts +++ b/app/features/build-analyzer/core/utils.ts @@ -31,7 +31,7 @@ export function buildToAbilityPoints(build: BuildAbilitiesTupleWithUnknown) { if (ability === "AD") { abilityDoublerActive = true; } - if (!isStackableAbility(ability)) { + if (!isStackableAbility(ability) && ability !== "UNKNOWN") { continue; } diff --git a/app/features/build-analyzer/routes/analyzer.tsx b/app/features/build-analyzer/routes/analyzer.tsx index c67fb06b8..a63317fb6 100644 --- a/app/features/build-analyzer/routes/analyzer.tsx +++ b/app/features/build-analyzer/routes/analyzer.tsx @@ -12,7 +12,6 @@ import { Popover } from "~/components/Popover"; import { Toggle } from "~/components/Toggle"; import { useSetTitle } from "~/hooks/useSetTitle"; import { - abilities, ANGLE_SHOOTER_ID, INK_MINE_ID, INK_STORM_ID, @@ -25,6 +24,7 @@ import { type BuildAbilitiesTupleWithUnknown, type MainWeaponId, type SubWeaponId, + abilitiesShort, } from "~/modules/in-game-lists"; import styles from "../analyzer.css"; import { damageTypeTranslationString } from "~/utils/i18next"; @@ -84,21 +84,22 @@ export const handle: SendouRouteHandle = { // Resolves this Github issue: https://github.com/Sendouc/sendou.ink/issues/1053 export const unstable_shouldReload: ShouldReloadFunction = () => false; -// xxx: for comparison AP bar charts show green if the better value (except for unknown), green can be on both sides too export default function BuildAnalyzerPage() { const { t } = useTranslation(["analyzer", "common", "weapons"]); useSetTitle(t("common:pages.analyzer")); const { build, build2, + focusedBuild, mainWeaponId, handleChange, analyzed, analyzed2, focused, abilityPoints, + abilityPoints2, ldeIntensity, - effects, + allEffects, } = useAnalyzeBuild(); const statKeyToTuple = (key: keyof AnalyzedBuild["stats"]) => { @@ -201,8 +202,8 @@ export default function BuildAnalyzerPage() { /> -
-
+
+
{t("analyzer:build2")} + handleChange({ newFocused: 3 })} + > + {t("analyzer:compare")} + - { - handleChange({ - [focused === 1 ? "newBuild" : "newBuild2"]: newBuild, - }); - }} - /> + {focusedBuild ? ( + { + handleChange({ + [focused === 1 ? "newBuild" : "newBuild2"]: newBuild, + }); + }} + /> + ) : ( + + )}
- handleChange({ newEffects: [...effects, newEffect] }) + handleChange({ newEffects: [...allEffects, newEffect] }) } handleRemoveEffect={(effectToRemove) => handleChange({ - newEffects: effects.filter((e) => e !== effectToRemove), + newEffects: allEffects.filter((e) => e !== effectToRemove), }) } - effects={effects} + effects={allEffects} /> - {/* xxx: rework these - maybe 3rd tab "Comparison" */} - {abilityPoints.size > 0 && ( - - )} {showAbilityChunksRequired && ( )} @@ -845,6 +855,56 @@ export default function BuildAnalyzerPage() { ); } +function APCompare({ + abilityPoints, + abilityPoints2, +}: { + abilityPoints: AbilityPoints; + abilityPoints2: AbilityPoints; +}) { + const { t } = useTranslation(["analyzer"]); + + return ( +
+ {([...abilitiesShort, "UNKNOWN"] as const).map((ability) => { + const ap = abilityPoints.get(ability)?.ap ?? 0; + const ap2 = abilityPoints2.get(ability)?.ap ?? 0; + + if (!ap && !ap2) return null; + + return ( + <> +
+ {ap}AP +
+
= ap2, + })} + style={{ width: `${ap}px` }} + /> + +
+
+ {ap2} + {t("analyzer:abilityPoints.short")} +
+ + ); + })} +
+ ); +} + function EffectsSelector({ build, build2, @@ -929,40 +989,6 @@ function EffectsSelector({ ); } -function AbilityPointsDetails({ - abilityPoints, -}: { - abilityPoints: AbilityPoints; -}) { - const { t } = useTranslation("analyzer"); - - return ( -
- {t("abilityPoints")} -
- {abilities - .filter((a) => (abilityPoints.get(a.name)?.ap ?? 0) > 0) - .sort((a, b) => { - return ( - abilityPoints.get(b.name)!.ap - abilityPoints.get(a.name)!.ap - ); - }) - .map((a) => ( -
- -
- {abilityPoints.get(a.name)?.ap} -
-
- ))} -
-
- ); -} - function AbilityChunksRequired({ build, }: { diff --git a/app/root.tsx b/app/root.tsx index b663cf81c..4b2bcbcea 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -12,7 +12,6 @@ import { Outlet, Scripts, useLoaderData, - useLocation, type ShouldReloadFunction, } from "@remix-run/react"; import * as React from "react"; diff --git a/app/styles/utils.css b/app/styles/utils.css index ce5dcedbd..be9f83576 100644 --- a/app/styles/utils.css +++ b/app/styles/utils.css @@ -194,6 +194,10 @@ justify-content: flex-end; } +.justify-self-end { + justify-self: flex-end; +} + .self-center { align-self: center; } diff --git a/public/locales/da/analyzer.json b/public/locales/da/analyzer.json index 60c1cff7d..3d850c62b 100644 --- a/public/locales/da/analyzer.json +++ b/public/locales/da/analyzer.json @@ -104,7 +104,6 @@ "value": "Værdi", "build": "Udrustning", "patch": "Patch:", - "abilityPoints": "Egenskabspoint (AP)", "abilityPoints.short": "AP", "abilityChunks": "Pris i Egenskabs-fragmenter", "consumptionExplanation": "Dette diagram viser, hvor mange handlinger man kan udføre med det primære våben efter brug af det sekundære våben 0-{{maxSubsToUse}} gange. Du kan bruge {{maxSubsToUse}} sekundære våben per fuld blæktank.", diff --git a/public/locales/de/analyzer.json b/public/locales/de/analyzer.json index 8e6ec0599..e7f7b9319 100644 --- a/public/locales/de/analyzer.json +++ b/public/locales/de/analyzer.json @@ -98,7 +98,6 @@ "value": "Wert", "build": "Ausrüstung", "patch": "Patch:", - "abilityPoints": "Effekt-Punkte", "abilityPoints.short": "EP", "abilityChunks": "Effekt-Fragmente erforderlich", "consumptionExplanation": "Dieses Diagramm zeigt die Anzahl der Aktionen, die mit der Hauptwaffe noch durchgeführt werden können, nachdem die Sekundärwaffe 0-{{maxSubsToUse}} mal benutzt wurde. Die maximale Anzahl an aufeinanderfolgenden Sekundärwaffen, die bei vollem Tintentank verwendet werden können, ist {{maxSubsToUse}}.", diff --git a/public/locales/en/analyzer.json b/public/locales/en/analyzer.json index 824846182..937abb4b3 100644 --- a/public/locales/en/analyzer.json +++ b/public/locales/en/analyzer.json @@ -105,8 +105,8 @@ "build": "Build", "build1": "Build 1", "build2": "Build 2", + "compare": "Compare", "patch": "Patch:", - "abilityPoints": "Ability points", "abilityPoints.short": "AP", "abilityChunks": "Ability Chunks Required", "consumptionExplanation": "This chart shows the amount of actions left to perform with main weapon after using sub 0-{{maxSubsToUse}} times. Max amount of consecutive subs to use with full ink tank is {{maxSubsToUse}}.", diff --git a/public/locales/es-ES/analyzer.json b/public/locales/es-ES/analyzer.json index 51145a309..2c7113e0d 100644 --- a/public/locales/es-ES/analyzer.json +++ b/public/locales/es-ES/analyzer.json @@ -87,7 +87,6 @@ "value": "Valor", "build": "Build", "patch": "Parche:", - "abilityPoints": "Puntos de habilidad (AP)", "abilityPoints.short": "AP", "consumptionExplanation": "Este gráfico muestra la cantidad de acciones restantes con el arma principal después de usar un arma secundaria 0-{{maxSubsToUse}} veces. La cantidad máxima de armas secundarias consecutivas que se pueden usar con el tanque lleno es {{maxSubsToUse}}.", "trackingSubDefExplanation": "Tiempos de rastreo de Rastreador, Mina de Tinta y Dardo Resaltador son calculados contra un oponente con 0AP de Resistencia Secundaria." diff --git a/public/locales/es-US/analyzer.json b/public/locales/es-US/analyzer.json index 51145a309..2c7113e0d 100644 --- a/public/locales/es-US/analyzer.json +++ b/public/locales/es-US/analyzer.json @@ -87,7 +87,6 @@ "value": "Valor", "build": "Build", "patch": "Parche:", - "abilityPoints": "Puntos de habilidad (AP)", "abilityPoints.short": "AP", "consumptionExplanation": "Este gráfico muestra la cantidad de acciones restantes con el arma principal después de usar un arma secundaria 0-{{maxSubsToUse}} veces. La cantidad máxima de armas secundarias consecutivas que se pueden usar con el tanque lleno es {{maxSubsToUse}}.", "trackingSubDefExplanation": "Tiempos de rastreo de Rastreador, Mina de Tinta y Dardo Resaltador son calculados contra un oponente con 0AP de Resistencia Secundaria." diff --git a/public/locales/fr/analyzer.json b/public/locales/fr/analyzer.json index 282fe1a68..adaca0fb6 100644 --- a/public/locales/fr/analyzer.json +++ b/public/locales/fr/analyzer.json @@ -102,7 +102,6 @@ "value": "Valeur", "build": "Equipement", "patch": "Version:", - "abilityPoints": "Points de compétence", "abilityPoints.short": " PC", "abilityChunks": "Fragments de bonus requis", "consumptionExplanation": "Ce tableau montre le nombre d'actions restantes à effectuer avec l'arme principale après avoir utilisé l'arme secondaire 0-{{maxSubsToUse}} fois. Le nombre max d'utilisations d'armes secondaires consécutives à utiliser avec un réservoir d'encre plein est de {{maxSubsToUse}}.", diff --git a/public/locales/it/analyzer.json b/public/locales/it/analyzer.json index e829518ba..34c5b932c 100644 --- a/public/locales/it/analyzer.json +++ b/public/locales/it/analyzer.json @@ -98,7 +98,6 @@ "value": "Valore", "build": "Kit", "patch": "Versione gioco:", - "abilityPoints": "Punti abilità", "abilityPoints.short": "AP", "abilityChunks": "Frammenti abilità necessari", "consumptionExplanation": "Questa tabella mostra la quantità di azioni rimaste da eseguire con l'arma principale dopo aver usato l'arma secondaria da 0 a {{maxSubsToUse}} volte. Il numero massimo di armi secondarie da utilizzare consecutivamente con un serbatoio pieno è {{maxSubsToUse}}.", diff --git a/public/locales/ja/analyzer.json b/public/locales/ja/analyzer.json index fe1b8f279..da3fa0816 100644 --- a/public/locales/ja/analyzer.json +++ b/public/locales/ja/analyzer.json @@ -97,7 +97,6 @@ "value": "値", "build": "ギアパワー/ドリンクあり", "patch": "Patch:", - "abilityPoints": "ギアパワー", "abilityPoints.short": "GP", "abilityChunks": "ギアパワーのかけらが必要です", "consumptionExplanation": "このチャートはサブを 0-{{maxSubsToUse}} 回使用したあとに何回メインを使用できるかを表しています。インクタンクが満タンの状態でサブが連続使用できる回数は {{maxSubsToUse}} です。", diff --git a/public/locales/nl/analyzer.json b/public/locales/nl/analyzer.json index 4979e0222..98150f274 100644 --- a/public/locales/nl/analyzer.json +++ b/public/locales/nl/analyzer.json @@ -66,7 +66,6 @@ "value": "Waarde", "build": "Uitrusting", "patch": "Softwareversie:", - "abilityPoints": "Effect punten", "abilityPoints.short": "EP", "consumptionExplanation": "Deze tabel laat zien hoeveel keer je nog een bepaalde actie kunt doen met het hoofdwapen na het 0-{{maxSubsToUse}} keer gebruiken van een subwapen. Het maximale aantal dat je een subwapen achter elkaar kan gebruiken is {{maxSubsToUse}} keer.", "trackingSubDefExplanation": "Detector, Inktmijn en Ketskogel markeringstijden worden berekend voor een tegenstander met 0 Subtopper EP.", diff --git a/public/locales/ru/analyzer.json b/public/locales/ru/analyzer.json index af72507e2..eaa6f8c92 100644 --- a/public/locales/ru/analyzer.json +++ b/public/locales/ru/analyzer.json @@ -102,7 +102,6 @@ "value": "Значение", "build": "Сборка", "patch": "Патч:", - "abilityPoints": "Свойства (AP)", "abilityPoints.short": "AP", "abilityChunks": "Требуется чанков свойства", "consumptionExplanation": "Данная таблица показывает, сколько действий можно совершить после 0-{{maxSubsToUse}}кратного использования запасного оружия. С полным баллоном запасное оружие можно использовать {{maxSubsToUse}} раз(а) подряд.", diff --git a/public/locales/zh/analyzer.json b/public/locales/zh/analyzer.json index 9adf8678a..2bbc6c4a3 100644 --- a/public/locales/zh/analyzer.json +++ b/public/locales/zh/analyzer.json @@ -96,7 +96,6 @@ "value": "值", "build": "配装", "patch": "游戏版本:", - "abilityPoints": "能力点数", "abilityPoints.short": "AP", "abilityChunks": "所需碎片", "consumptionExplanation": "表中的数据表示在使用了副武器 0-{{maxSubsToUse}} 次后主武器的可攻击次数。在满墨下的最大副武器连续使用次数为 {{maxSubsToUse}}。",