Ink consumption table for analyzer

This commit is contained in:
Kalle
2022-09-14 14:55:30 +03:00
parent 18c2d3bbab
commit dad5c3c0ac
8 changed files with 100 additions and 41 deletions

View File

@@ -4,6 +4,7 @@ export type {
SubWeaponParams,
Stat,
AnalyzedBuild,
FullInkTankOption,
} from "./types";
export { useAnalyzeBuild } from "./useAnalyzeBuild";

View File

@@ -205,7 +205,7 @@ function inkConsumeTypeToParamsKeys(
case "SWING":
return ["InkConsume_SwingParam", "InkConsume_WeaponSwingParam"];
case "TAP_SHOT":
return ["InkConsumeMinCharge", "InkConsumeMinCharge_ChargeParam"];
return ["InkConsumeMinCharge"];
case "FULL_CHARGE":
return ["InkConsumeFullCharge", "InkConsumeFullCharge_ChargeParam"];
case "HORIZONTAL_SWING":
@@ -216,10 +216,6 @@ function inkConsumeTypeToParamsKeys(
return ["InkConsume_SideStepParam"];
case "SHIELD_LAUNCH":
return ["InkConsumeUmbrella_WeaponShelterCanopyParam"];
case "ROLL_MAX":
return ["InkConsumeMaxPerFrame_WeaponRollParam"];
case "ROLL_MIN":
return ["InkConsumeMinPerFrame_WeaponRollParam"];
default: {
assertUnreachable(type);
}

View File

@@ -21,10 +21,6 @@ export interface MainWeaponParams {
// xxx: morph with another swing one below
/** How much ink one swing of brush consumes? */
InkConsume_WeaponSwingParam?: number;
/** Lower bound of ink consumed per frame when rolling with roller/brush */
InkConsumeMaxPerFrame_WeaponRollParam?: number;
/** Upper bound of ink consumed per frame when rolling with roller/brush */
InkConsumeMinPerFrame_WeaponRollParam?: number;
/** How much ink one vertical swing of roller consumes? */
InkConsume_WeaponVerticalSwingParam?: number;
/** How much ink one horizontal swing of roller consumes? */
@@ -38,9 +34,8 @@ export interface MainWeaponParams {
InkConsume_WeaponShelterShotgunParam?: number;
/** How much ink a dualie dodge roll consumes? */
InkConsume_SideStepParam?: number;
// xxx: some explanations... the below two are for splatana/bow
/** How much ink a fully charger Splatana shot consumes? */
InkConsumeFullCharge_ChargeParam?: number;
InkConsumeMinCharge_ChargeParam?: number;
//InkConsumeMidCharge_ChargeParam?: number;
// xxx: what are these?
// SpeedInkConsumeMax_WeaponRollParam?: number;
@@ -106,10 +101,14 @@ export const INK_CONSUME_TYPES = [
"FULL_CHARGE",
"SHIELD_LAUNCH",
"DUALIE_ROLL",
"ROLL_MIN",
"ROLL_MAX",
] as const;
export interface FullInkTankOption {
subsUsed: number;
value: number;
type: InkConsumeType;
}
export interface AnalyzedBuild {
weapon: {
subWeaponSplId: SubWeaponId;
@@ -120,10 +119,6 @@ export interface AnalyzedBuild {
/** % of special charge saved when dying */
specialSavedAfterDeath: Stat;
subWeaponWhiteInkFrames?: number;
fullInkTankOptions: Array<{
subsUsed: number;
value: number;
type: InkConsumeType;
}>;
fullInkTankOptions: Array<FullInkTankOption>;
};
}

View File

@@ -6,7 +6,7 @@ import { WeaponCombobox } from "~/components/Combobox";
import { Main } from "~/components/Main";
import type { Stat } from "~/modules/analyzer";
import { useAnalyzeBuild } from "~/modules/analyzer";
import type { AnalyzedBuild } from "~/modules/analyzer";
import type { AnalyzedBuild, FullInkTankOption } from "~/modules/analyzer";
import type { MainWeaponId } from "~/modules/in-game-lists";
import styles from "~/styles/analyzer.css";
import { Image } from "~/components/Image";
@@ -33,19 +33,21 @@ export default function BuildAnalyzerPage() {
<div className="analyzer__container">
<div className="stack lg items-center">
<div className="stack sm items-center w-full">
<WeaponCombobox
inputName="weapon"
initialWeaponId={mainWeaponId}
onChange={(opt) =>
opt && setMainWeaponId(Number(opt.value) as MainWeaponId)
}
className="w-full-important"
/>
<div className="w-full">
<WeaponCombobox
inputName="weapon"
initialWeaponId={mainWeaponId}
onChange={(opt) =>
opt && setMainWeaponId(Number(opt.value) as MainWeaponId)
}
className="w-full-important"
/>
</div>
<KitCards analyzed={analyzed} />
</div>
<AbilitiesSelector selectedAbilities={build} onChange={setBuild} />
</div>
<div>
<div className="stack md">
<StatCategory title="Special">
<StatCard
stat={analyzed.stats.specialPoint}
@@ -58,6 +60,12 @@ export default function BuildAnalyzerPage() {
suffix="%"
/>
</StatCategory>
<StatCategory
title="Actions per ink tank"
containerClassName="analyzer__consumption-table-container"
>
<ConsumptionTable options={analyzed.stats.fullInkTankOptions} />
</StatCategory>
</div>
</div>
</Main>
@@ -94,18 +102,21 @@ function KitCards({ analyzed }: { analyzed: AnalyzedBuild }) {
function StatCategory({
title,
children,
containerClassName = "analyzer__stat-collection",
}: {
title: string;
children: React.ReactNode;
containerClassName?: string;
}) {
return (
<details>
<summary className="analyzer__summary">{title}</summary>
<div className="analyzer__stat-collection">{children}</div>
<div className={containerClassName}>{children}</div>
</details>
);
}
// xxx: cobra kai style
function StatCard({
title,
stat,
@@ -136,3 +147,41 @@ function StatCard({
</div>
);
}
function ConsumptionTable({ options }: { options: Array<FullInkTankOption> }) {
const { t } = useTranslation("analyzer");
const maxSubsToUse = Math.max(...options.map((opt) => opt.subsUsed));
const types = Array.from(new Set(options.map((opt) => opt.type)));
return (
<>
<table>
<thead>
<tr>
<th>{t("stat.consumption.bomb")}</th>
{types.map((type) => (
<th key={type}>{t(`stat.consumption.${type}`)}</th>
))}
</tr>
</thead>
<tbody>
{new Array(maxSubsToUse + 1).fill(null).map((_, subsUsed) => {
return (
<tr key={subsUsed} className="bg-darker-important">
<td>×{subsUsed}</td>
{options
.filter((opt) => opt.subsUsed === subsUsed)
.map((opt) => {
return <td key={opt.type}>{opt.value}</td>;
})}
</tr>
);
})}
</tbody>
</table>
<div className="analyzer__consumption-table-explanation">
{t("consumptionExplanation", { maxSubsToUse })}
</div>
</>
);
}

View File

@@ -57,3 +57,18 @@
.analyzer__stat-card__value {
font-size: var(--fonts-xs);
}
.analyzer__consumption-table-container {
width: 100%;
padding: var(--s-3);
background-color: var(--bg-darker);
border-radius: var(--rounded);
margin-block-start: var(--s-4);
padding-block: var(--s-2);
}
.analyzer__consumption-table-explanation {
margin-top: var(--s-2);
color: var(--text-lighter);
font-size: var(--fonts-xxs);
}

View File

@@ -30,6 +30,10 @@
color: var(--theme-success);
}
.bg-darker-important {
background-color: var(--bg-darker) !important;
}
.font-semi-bold {
font-weight: var(--semi-bold);
}

View File

@@ -1,4 +1,14 @@
{
"stat.specialPoints": "Points to special",
"stat.specialLost": "Special lost when splatted"
"stat.specialLost": "Special lost when splatted",
"stat.consumption.bomb": "Bombs",
"stat.consumption.NORMAL": "Shots",
"stat.consumption.SWING": "Swings",
"stat.consumption.VERTICAL_SWING": "Vertical swings",
"stat.consumption.HORIZONTAL_SWING": "Horizontal swings",
"stat.consumption.TAP_SHOT": "Tap shots",
"stat.consumption.FULL_CHARGE": "Fully charged shots",
"stat.consumption.SHIELD_LAUNCH": "Shield launches",
"stat.consumption.DUALIE_ROLL": "Dodge Rolls",
"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}}."
}

View File

@@ -109,10 +109,6 @@ function parametersToMainWeaponResult(
InkConsumeFullCharge: params["WeaponParam"]?.["InkConsumeFullCharge"],
InkConsumeMinCharge: params["WeaponParam"]?.["InkConsumeMinCharge"],
InkConsume_WeaponSwingParam: params["WeaponSwingParam"]?.["InkConsume"],
InkConsumeMaxPerFrame_WeaponRollParam:
params["WeaponRollParam"]?.["InkConsumeMaxPerFrame"],
InkConsumeMinPerFrame_WeaponRollParam:
params["WeaponRollParam"]?.["InkConsumeMinPerFrame"],
InkConsume_WeaponVerticalSwingParam:
params["WeaponVerticalSwingParam"]?.["InkConsume"],
InkConsume_WeaponWideSwingParam:
@@ -131,13 +127,6 @@ function parametersToMainWeaponResult(
params["spl__WeaponStringerParam"]?.["ChargeParam"]?.[
"InkConsumeFullCharge"
],
InkConsumeMinCharge_ChargeParam:
params["spl__WeaponSaberParam"]?.["ChargeParam"]?.[
"InkConsumeMinCharge"
] ??
params["spl__WeaponStringerParam"]?.["ChargeParam"]?.[
"InkConsumeMinCharge"
],
};
}