From d96f77bf05db14edc05a925191b7474f4d0e3175 Mon Sep 17 00:00:00 2001
From: tresabhi <43380238+tresabhi@users.noreply.github.com>
Date: Thu, 29 Oct 2026 15:29:37 -0500
Subject: [PATCH] i am tired boss
---
packages/i18n/strings/en.json | 33 +++++++--
.../src/components/GuessBackground/index.css | 14 ----
.../GuessBackground/index.module.css | 54 ++++++++++++++
.../src/components/GuessBackground/index.tsx | 72 ++++---------------
packages/website/src/components/Guesser.tsx | 70 +++++++-----------
.../src/components/ToolOpenGraph.astro | 4 +-
.../[...locale]/guesser/_index.tsx | 56 ++++++---------
.../[...locale]/guesser/index.astro | 6 +-
packages/website/src/stores/guess.ts | 13 ++--
9 files changed, 151 insertions(+), 171 deletions(-)
delete mode 100644 packages/website/src/components/GuessBackground/index.css
create mode 100644 packages/website/src/components/GuessBackground/index.module.css
diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json
index 9d79b350a..9e18a6ad1 100644
--- a/packages/i18n/strings/en.json
+++ b/packages/i18n/strings/en.json
@@ -1,4 +1,24 @@
{
+ "guesser": {
+ "help": {
+ "title": "Partially reveal tank?",
+ "description": "Reveals the tank without showing the name. This round will be considered incorrect and break your streak!",
+ "cancel": "Cancel",
+ "reveal": "Reveal"
+ },
+
+ "search": {
+ "skip": "Skip",
+ "guess": "Guess",
+ "next": "Next"
+ },
+
+ "stats": "{correct} / {total} correct, {streak} streak",
+ "tier": "Tier {tier}",
+ "select_all": "Select all",
+ "clear": "Clear"
+ },
+
"units": {
"m": "{value}m",
"mm": "{value}mm",
@@ -261,6 +281,13 @@
"common": {
"name": "BlitzKit",
+ "search": {
+ "hint_players": "Search players...",
+ "hint_tanks": "Search tanks...",
+ "no_results": "No results",
+ "searching": "Searching..."
+ },
+
"units": {
"m": "{value}m",
"mm": "{value}mm",
@@ -473,12 +500,6 @@
},
"common": {
- "player_search": {
- "hint": "Search players...",
- "no_results": "No results",
- "searching": "Searching..."
- },
-
"copy_button": {
"copied": "Copied!"
},
diff --git a/packages/website/src/components/GuessBackground/index.css b/packages/website/src/components/GuessBackground/index.css
deleted file mode 100644
index 27600f511..000000000
--- a/packages/website/src/components/GuessBackground/index.css
+++ /dev/null
@@ -1,14 +0,0 @@
-.guess-background {
- animation: moveBackground 180s linear infinite;
-}
-
-@keyframes moveBackground {
- from {
- top: 0;
- left: 0;
- }
- to {
- top: -100%;
- left: -100%;
- }
-}
diff --git a/packages/website/src/components/GuessBackground/index.module.css b/packages/website/src/components/GuessBackground/index.module.css
new file mode 100644
index 000000000..deb5d3d75
--- /dev/null
+++ b/packages/website/src/components/GuessBackground/index.module.css
@@ -0,0 +1,54 @@
+.foreground {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+
+ transition-duration: var(--duration-subtle);
+ background-color: var(--accent-2);
+
+ &[data-guess-state="correct"] {
+ background-color: var(--jade-3);
+ }
+
+ &[data-guess-state="incorrect"] {
+ background-color: var(--tomato-3);
+ }
+
+ .overlay {
+ width: 100%;
+ height: 100%;
+ background: radial-gradient(circle, var(--gray-a9), var(--gray-3));
+ }
+}
+
+.background {
+ animation: moveBackground 180s linear infinite;
+
+ position: absolute;
+ width: 200%;
+ height: 200%;
+ top: 0;
+ left: 0;
+
+ background-image:
+ radial-gradient(circle, var(--white-a1) 20%, transparent 20%),
+ radial-gradient(circle at 0 0, var(--white-a1) 10%, transparent 10%),
+ radial-gradient(circle at 100% 0, var(--white-a1) 10%, transparent 10%),
+ radial-gradient(circle at 0 100%, var(--white-a1) 10%, transparent 10%),
+ radial-gradient(circle at 100% 100%, var(--white-a1) 10%, transparent 10%);
+
+ background-size: 4rem 4rem;
+}
+
+@keyframes moveBackground {
+ from {
+ top: 0;
+ left: 0;
+ }
+ to {
+ top: -100%;
+ left: -100%;
+ }
+}
diff --git a/packages/website/src/components/GuessBackground/index.tsx b/packages/website/src/components/GuessBackground/index.tsx
index 941635d3d..039dfb406 100644
--- a/packages/website/src/components/GuessBackground/index.tsx
+++ b/packages/website/src/components/GuessBackground/index.tsx
@@ -1,77 +1,31 @@
-import { Box } from "@radix-ui/themes";
import { useEffect } from "react";
import { api } from "../../api/dynamic";
-import { tankToDuelMember } from "../../core/blitzkit/tankToDuelMember";
-import { Var } from "../../core/radix/var";
-import { Duel } from "../../stores/duel";
-import { Guess, GuessState } from "../../stores/guess";
+import { Guess } from "../../stores/guess";
import { Tankopedia } from "../../stores/tankopedia";
-import "./index.css";
+import { createTankState } from "../../tankopedia/createTankState";
+import styles from "./index.module.css";
-const [modelDefinitions, provisionDefinitions] = await Promise.all([
- api.models(),
- api.provisions(),
-]);
+const [models, tanks] = await Promise.all([api.models(), api.tanks()]);
export function GuessBackground() {
const guessState = Guess.use((state) => state.guessState);
- const tank = Guess.use((state) => state.tank);
+ const id = Guess.use((state) => state.tank);
useEffect(() => {
- Duel.mutate((state) => {
- state.protagonist = tankToDuelMember(tank, provisionDefinitions);
- });
+ const tank = tanks.tanks[id];
+
Tankopedia.mutate((state) => {
- state.model = modelDefinitions.models[tank.id];
+ state.protagonist = createTankState(tank);
});
- }, [tank]);
+ }, [id]);
return (
<>
-
-
-
+
-
+
>
);
}
diff --git a/packages/website/src/components/Guesser.tsx b/packages/website/src/components/Guesser.tsx
index 184f1cc20..720e33c7b 100644
--- a/packages/website/src/components/Guesser.tsx
+++ b/packages/website/src/components/Guesser.tsx
@@ -10,48 +10,38 @@ import {
StarFilledIcon,
TrashIcon,
} from "@radix-ui/react-icons";
-import {
- AlertDialog,
- Box,
- Button,
- Card,
- DropdownMenu,
- Flex,
- IconButton,
- Spinner,
- Text,
- TextField,
-} from "@radix-ui/themes";
import fuzzysort from "fuzzysort";
import { debounce } from "lodash-es";
import { useCallback, useEffect, useRef, useState } from "react";
import { api } from "../api/dynamic";
import { awaitableTankNames } from "../core/awaitables/tankNames";
import { awaitableTiers } from "../core/awaitables/tiers";
-import { api } from "../core/blitzkit/api";
-import { useLocale } from "../hooks/useLocale";
+import { useStrings } from "../hooks/useStrings";
+import { useUnwrapper } from "../hooks/useUnwrapper";
import { Guess, GuessState } from "../stores/guess";
-import { classIcons } from "./ClassIcon";
+import { ClassIcon } from "./ClassIcon";
import { SearchResults } from "./SearchResults";
const { go } = fuzzysort;
const [tankNames, tankDefinitions, TIERS] = await Promise.all([
awaitableTankNames,
- api.tankDefinitions(),
+ api.tanks(),
awaitableTiers,
]);
const ids = Object.keys(tankDefinitions.tanks);
export function Guesser() {
+ const strings = useStrings();
+ const unwrap = useUnwrapper();
+
const tank = Guess.use((state) => state.tank);
const guessState = Guess.use((state) => state.guessState);
const correctGuesses = Guess.use((state) => state.correctGuesses);
const totalGuesses = Guess.use((state) => state.totalGuesses);
const helpingReveal = Guess.use((state) => state.helpingReveal);
const streak = Guess.use((state) => state.streak);
- const { strings, unwrap } = useLocale();
const input = useRef(null);
const [searching, setSearching] = useState(false);
const [results, setResults] = useState(null);
@@ -97,7 +87,7 @@ export function Guesser() {
const interval = setInterval(() => {
if (!status.current) return;
- status.current.innerText = literals(strings.website.tools.guess.stats, {
+ status.current.innerText = literals(strings.guesser.stats, {
correct: correctGuesses,
total: totalGuesses,
streak: streak,
@@ -125,16 +115,12 @@ export function Guesser() {
{results.length === 0 && (
-
- {strings.website.tools.guess.search.no_results}
-
+ {strings.common.search.no_results}
)}
{results.map((result) => {
- const Icon = classIcons[result.class];
-
return (
-
+
{romanize(result.tier)}
}
@@ -214,7 +204,7 @@ export function Guesser() {
});
}}
>
- {literals(strings.website.tools.guess.tier, {
+ {literals(strings.guesser.tier, {
tier: romanize(tier),
})}
@@ -232,7 +222,7 @@ export function Guesser() {
});
}}
>
- {strings.website.tools.guess.select_all}
+ {strings.guesser.select_all}
- {strings.website.tools.guess.clear}
+ {strings.guesser.clear}
@@ -255,7 +245,7 @@ export function Guesser() {
ref={input}
onChange={requestSearch}
style={{ flex: 1, maxWidth: "14rem" }}
- placeholder={strings.website.tools.guess.search.placeholder}
+ placeholder={strings.common.search.hint_tanks}
size={{ initial: "2", sm: "3" }}
variant="classic"
>
@@ -275,18 +265,14 @@ export function Guesser() {
-
- {strings.website.tools.guess.help.title}
-
+ {strings.guesser.help.title}
- {strings.website.tools.guess.help.description}
+ {strings.guesser.help.description}
-
+
@@ -299,7 +285,7 @@ export function Guesser() {
});
}}
>
- {strings.website.tools.guess.help.reveal}
+ {strings.guesser.help.reveal}
@@ -316,7 +302,7 @@ export function Guesser() {
onClick={() => {
if (guessState === GuessState.NotGuessed) {
const correct =
- selected !== null && selected.id === tank.id && !helpingReveal;
+ selected !== null && selected.id === tank && !helpingReveal;
Guess.mutate((draft) => {
draft.guessState = correct
@@ -340,7 +326,7 @@ export function Guesser() {
Guess.mutate((draft) => {
if (!input.current) return;
- draft.tank = tank;
+ draft.tank = tank.id;
draft.guessState = GuessState.NotGuessed;
draft.helpingReveal = false;
@@ -351,16 +337,12 @@ export function Guesser() {
>
{guessState === GuessState.NotGuessed ? (
<>
- {
- strings.website.tools.guess.search[
- selected === null ? "skip" : "guess"
- ]
- }
+ {strings.guesser.search[selected === null ? "skip" : "guess"]}
{selected === null ? : }
>
) : (
<>
- {strings.website.tools.guess.search.next}
+ {strings.guesser.search.next}
>
)}
diff --git a/packages/website/src/components/ToolOpenGraph.astro b/packages/website/src/components/ToolOpenGraph.astro
index 6e025cbf7..7cf57f13b 100644
--- a/packages/website/src/components/ToolOpenGraph.astro
+++ b/packages/website/src/components/ToolOpenGraph.astro
@@ -1,7 +1,7 @@
---
import { AstroSeo } from "@astrolib/seo";
+import { api } from "../api/dynamic";
import type { Tool } from "../constants/tools";
-import { getStrings } from "../core/i18n/getStrings";
interface Props {
tool: Tool;
@@ -9,7 +9,7 @@ interface Props {
}
const { locale, tool } = Astro.props;
-const strings = getStrings(locale);
+const strings = await api.strings(locale);
const toolStrings =
strings.website.tools[
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/_index.tsx
index 32c7c88bc..5d8ebc4ab 100644
--- a/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/_index.tsx
+++ b/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/_index.tsx
@@ -5,13 +5,10 @@ import { GuessBackground } from "../../../../components/GuessBackground";
import { Guesser } from "../../../../components/Guesser";
import { GuessRenderer } from "../../../../components/GuessRenderer";
import { GuessRendererLoader } from "../../../../components/GuessRendererLoader";
-import { PageWrapper } from "../../../../components/PageWrapper";
-import {
- type LocaleAcceptorProps,
- LocaleProvider,
- useLocale,
-} from "../../../../hooks/useLocale";
-import { Duel } from "../../../../stores/duel";
+import { withErrorWrapper } from "../../../../hocs/withErrorWrapper";
+import { withLocale } from "../../../../hocs/withLocale";
+import { DuelModule, useDuel } from "../../../../hooks/useDuel";
+import { useUnwrapper } from "../../../../hooks/useUnwrapper";
import { Guess, GuessState } from "../../../../stores/guess";
import { Tankopedia } from "../../../../stores/tankopedia";
import type { MaybeSkeletonComponentProps } from "../../../../types/maybeSkeletonComponentProps";
@@ -23,42 +20,34 @@ const [tankDefinitions, modelDefinitions] = await Promise.all([
const ids = Object.keys(tankDefinitions.tanks);
-export function Page({
- locale,
- skeleton,
-}: LocaleAcceptorProps & MaybeSkeletonComponentProps) {
- const id = Number(ids[Math.floor(Math.random() * ids.length)]);
- const tank = tankDefinitions.tanks[id];
+export const Page = withLocale(
+ withErrorWrapper(({ skeleton }: MaybeSkeletonComponentProps) => {
+ const id = Number(ids[Math.floor(Math.random() * ids.length)]);
- Guess.useInitialization(tank);
+ Guess.useInitialization(id);
- return (
-
-
-
- );
-}
+ return ;
+ }),
+);
function Container({ skeleton }: MaybeSkeletonComponentProps) {
- const tank = Guess.use((state) => state.tank);
- const model = modelDefinitions.models[tank.id];
+ const id = Guess.use((state) => state.tank);
+ const tank = tankDefinitions.tanks[id];
- Tankopedia.useInitialization(model);
- Duel.useInitialization({ tank, model });
+ Tankopedia.useInitialization(tank);
- return (
-
-
-
- );
+ return ;
}
function Content({ skeleton }: MaybeSkeletonComponentProps) {
- const { unwrap } = useLocale();
- const tank = Guess.use((state) => state.tank);
+ const tank = useDuel("protagonist", DuelModule.Tank);
+
+ const unwrap = useUnwrapper();
+
+ const name = unwrap(tank.name!);
+
const guessState = Guess.use((state) => state.guessState);
const isRevealed = guessState !== GuessState.NotGuessed;
- const name = unwrap(tank.name!);
const fontSize = `min(48vh, ${55 / name.length}vw)`;
const transitionDuration = isRevealed ? "2s" : undefined;
const tiers = Guess.use((state) => state.tiers);
@@ -78,10 +67,9 @@ function Content({ skeleton }: MaybeSkeletonComponentProps) {
const id = Number(
filteredIds[Math.floor(Math.random() * filteredIds.length)],
);
- const newTank = tankDefinitions.tanks[id];
Guess.mutate((draft) => {
- draft.tank = newTank;
+ draft.tank = id;
draft.guessState = GuessState.NotGuessed;
draft.helpingReveal = false;
});
diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/index.astro b/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/index.astro
index 1816e5479..fdfe8a50a 100644
--- a/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/index.astro
+++ b/packages/website/src/pages/[...chunk_default]/[...locale]/guesser/index.astro
@@ -1,6 +1,4 @@
---
-import ToolOpenGraph from "../../../../components/ToolOpenGraph.astro";
-import { tools } from "../../../../constants/tools";
import BaseLayout from "../../../../layouts/BaseLayout.astro";
import { Page } from "./_index";
@@ -9,9 +7,7 @@ export { getStaticPaths } from "../index.astro";
const { locale } = Astro.props;
---
-
-
-
+
diff --git a/packages/website/src/stores/guess.ts b/packages/website/src/stores/guess.ts
index fa413ee89..45a5c9d8e 100644
--- a/packages/website/src/stores/guess.ts
+++ b/packages/website/src/stores/guess.ts
@@ -1,17 +1,16 @@
-import type { TankDefinition } from "@blitzkit/core";
-import { Varuna } from "varuna";
+import { Soapstone } from "soapstone";
import { awaitableTiers } from "../core/awaitables/tiers";
const tiers = await awaitableTiers;
export enum GuessState {
- Correct,
- Incorrect,
- NotGuessed,
+ Correct = "correct",
+ Incorrect = "incorrect",
+ NotGuessed = "not-guessed",
}
export interface Guess {
- tank: TankDefinition;
+ tank: number;
guessState: GuessState;
totalGuesses: number;
correctGuesses: number;
@@ -20,7 +19,7 @@ export interface Guess {
tiers: number[];
}
-export const Guess = new Soapstone((tank) => ({
+export const Guess = new Soapstone((tank) => ({
tank,
guessState: GuessState.NotGuessed,
totalGuesses: 0,