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,