mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-31 22:49:52 +01:00
i am tired boss
This commit is contained in:
1 parent
3b34b01536
commit
d96f77bf05
9 files changed
+151
-171
No files matched your search
@@ -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": {
|
"units": {
|
||||||
"m": "{value}m",
|
"m": "{value}m",
|
||||||
"mm": "{value}mm",
|
"mm": "{value}mm",
|
||||||
@@ -261,6 +281,13 @@
|
|||||||
"common": {
|
"common": {
|
||||||
"name": "BlitzKit",
|
"name": "BlitzKit",
|
||||||
|
|
||||||
|
"search": {
|
||||||
|
"hint_players": "Search players...",
|
||||||
|
"hint_tanks": "Search tanks...",
|
||||||
|
"no_results": "No results",
|
||||||
|
"searching": "Searching..."
|
||||||
|
},
|
||||||
|
|
||||||
"units": {
|
"units": {
|
||||||
"m": "{value}m",
|
"m": "{value}m",
|
||||||
"mm": "{value}mm",
|
"mm": "{value}mm",
|
||||||
@@ -473,12 +500,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"common": {
|
"common": {
|
||||||
"player_search": {
|
|
||||||
"hint": "Search players...",
|
|
||||||
"no_results": "No results",
|
|
||||||
"searching": "Searching..."
|
|
||||||
},
|
|
||||||
|
|
||||||
"copy_button": {
|
"copy_button": {
|
||||||
"copied": "Copied!"
|
"copied": "Copied!"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
.guess-background {
|
|
||||||
animation: moveBackground 180s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes moveBackground {
|
|
||||||
from {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
top: -100%;
|
|
||||||
left: -100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,77 +1,31 @@
|
|||||||
import { Box } from "@radix-ui/themes";
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { api } from "../../api/dynamic";
|
import { api } from "../../api/dynamic";
|
||||||
import { tankToDuelMember } from "../../core/blitzkit/tankToDuelMember";
|
import { Guess } from "../../stores/guess";
|
||||||
import { Var } from "../../core/radix/var";
|
|
||||||
import { Duel } from "../../stores/duel";
|
|
||||||
import { Guess, GuessState } from "../../stores/guess";
|
|
||||||
import { Tankopedia } from "../../stores/tankopedia";
|
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([
|
const [models, tanks] = await Promise.all([api.models(), api.tanks()]);
|
||||||
api.models(),
|
|
||||||
api.provisions(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
export function GuessBackground() {
|
export function GuessBackground() {
|
||||||
const guessState = Guess.use((state) => state.guessState);
|
const guessState = Guess.use((state) => state.guessState);
|
||||||
const tank = Guess.use((state) => state.tank);
|
const id = Guess.use((state) => state.tank);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Duel.mutate((state) => {
|
const tank = tanks.tanks[id];
|
||||||
state.protagonist = tankToDuelMember(tank, provisionDefinitions);
|
|
||||||
});
|
|
||||||
Tankopedia.mutate((state) => {
|
Tankopedia.mutate((state) => {
|
||||||
state.model = modelDefinitions.models[tank.id];
|
state.protagonist = createTankState(tank);
|
||||||
});
|
});
|
||||||
}, [tank]);
|
}, [id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<div className={styles.foreground} data-guess-state={guessState}>
|
||||||
position="absolute"
|
<div className={styles.overlay} />
|
||||||
width="100%"
|
</div>
|
||||||
height="100%"
|
|
||||||
top="0"
|
|
||||||
left="0"
|
|
||||||
style={{
|
|
||||||
transitionDuration: "2s",
|
|
||||||
backgroundColor: Var(
|
|
||||||
guessState === GuessState.NotGuessed
|
|
||||||
? "accent-2"
|
|
||||||
: guessState === GuessState.Correct
|
|
||||||
? "jade-3"
|
|
||||||
: "tomato-3",
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
style={{
|
|
||||||
background: `radial-gradient(circle, ${Var("color-panel-translucent")}, ${Var("color-panel-solid")})`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
<div className={styles.background} />
|
||||||
className="guess-background"
|
|
||||||
position="absolute"
|
|
||||||
width="200%"
|
|
||||||
height="200%"
|
|
||||||
top="0"
|
|
||||||
left="0"
|
|
||||||
style={{
|
|
||||||
backgroundImage: `
|
|
||||||
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%)
|
|
||||||
`,
|
|
||||||
backgroundSize: "4rem 4rem",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -10,48 +10,38 @@ import {
|
|||||||
StarFilledIcon,
|
StarFilledIcon,
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
} from "@radix-ui/react-icons";
|
} 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 fuzzysort from "fuzzysort";
|
||||||
import { debounce } from "lodash-es";
|
import { debounce } from "lodash-es";
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { api } from "../api/dynamic";
|
import { api } from "../api/dynamic";
|
||||||
import { awaitableTankNames } from "../core/awaitables/tankNames";
|
import { awaitableTankNames } from "../core/awaitables/tankNames";
|
||||||
import { awaitableTiers } from "../core/awaitables/tiers";
|
import { awaitableTiers } from "../core/awaitables/tiers";
|
||||||
import { api } from "../core/blitzkit/api";
|
import { useStrings } from "../hooks/useStrings";
|
||||||
import { useLocale } from "../hooks/useLocale";
|
import { useUnwrapper } from "../hooks/useUnwrapper";
|
||||||
import { Guess, GuessState } from "../stores/guess";
|
import { Guess, GuessState } from "../stores/guess";
|
||||||
import { classIcons } from "./ClassIcon";
|
import { ClassIcon } from "./ClassIcon";
|
||||||
import { SearchResults } from "./SearchResults";
|
import { SearchResults } from "./SearchResults";
|
||||||
|
|
||||||
const { go } = fuzzysort;
|
const { go } = fuzzysort;
|
||||||
|
|
||||||
const [tankNames, tankDefinitions, TIERS] = await Promise.all([
|
const [tankNames, tankDefinitions, TIERS] = await Promise.all([
|
||||||
awaitableTankNames,
|
awaitableTankNames,
|
||||||
api.tankDefinitions(),
|
api.tanks(),
|
||||||
awaitableTiers,
|
awaitableTiers,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const ids = Object.keys(tankDefinitions.tanks);
|
const ids = Object.keys(tankDefinitions.tanks);
|
||||||
|
|
||||||
export function Guesser() {
|
export function Guesser() {
|
||||||
|
const strings = useStrings();
|
||||||
|
const unwrap = useUnwrapper();
|
||||||
|
|
||||||
const tank = Guess.use((state) => state.tank);
|
const tank = Guess.use((state) => state.tank);
|
||||||
const guessState = Guess.use((state) => state.guessState);
|
const guessState = Guess.use((state) => state.guessState);
|
||||||
const correctGuesses = Guess.use((state) => state.correctGuesses);
|
const correctGuesses = Guess.use((state) => state.correctGuesses);
|
||||||
const totalGuesses = Guess.use((state) => state.totalGuesses);
|
const totalGuesses = Guess.use((state) => state.totalGuesses);
|
||||||
const helpingReveal = Guess.use((state) => state.helpingReveal);
|
const helpingReveal = Guess.use((state) => state.helpingReveal);
|
||||||
const streak = Guess.use((state) => state.streak);
|
const streak = Guess.use((state) => state.streak);
|
||||||
const { strings, unwrap } = useLocale();
|
|
||||||
const input = useRef<HTMLInputElement>(null);
|
const input = useRef<HTMLInputElement>(null);
|
||||||
const [searching, setSearching] = useState(false);
|
const [searching, setSearching] = useState(false);
|
||||||
const [results, setResults] = useState<TankDefinition[] | null>(null);
|
const [results, setResults] = useState<TankDefinition[] | null>(null);
|
||||||
@@ -97,7 +87,7 @@ export function Guesser() {
|
|||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
if (!status.current) return;
|
if (!status.current) return;
|
||||||
|
|
||||||
status.current.innerText = literals(strings.website.tools.guess.stats, {
|
status.current.innerText = literals(strings.guesser.stats, {
|
||||||
correct: correctGuesses,
|
correct: correctGuesses,
|
||||||
total: totalGuesses,
|
total: totalGuesses,
|
||||||
streak: streak,
|
streak: streak,
|
||||||
@@ -125,16 +115,12 @@ export function Guesser() {
|
|||||||
<Box py="2" px="3">
|
<Box py="2" px="3">
|
||||||
{results.length === 0 && (
|
{results.length === 0 && (
|
||||||
<Flex justify="center">
|
<Flex justify="center">
|
||||||
<Text color="gray">
|
<Text color="gray">{strings.common.search.no_results}</Text>
|
||||||
{strings.website.tools.guess.search.no_results}
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<SearchResults.Root>
|
<SearchResults.Root>
|
||||||
{results.map((result) => {
|
{results.map((result) => {
|
||||||
const Icon = classIcons[result.class];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SearchResults.Item
|
<SearchResults.Item
|
||||||
key={result.id}
|
key={result.id}
|
||||||
@@ -162,7 +148,11 @@ export function Guesser() {
|
|||||||
width="38px"
|
width="38px"
|
||||||
justify="center"
|
justify="center"
|
||||||
>
|
>
|
||||||
<Icon width="1em" height="1em" />
|
<ClassIcon
|
||||||
|
class={result.class}
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
/>
|
||||||
{romanize(result.tier)}
|
{romanize(result.tier)}
|
||||||
</Flex>
|
</Flex>
|
||||||
}
|
}
|
||||||
@@ -214,7 +204,7 @@ export function Guesser() {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{literals(strings.website.tools.guess.tier, {
|
{literals(strings.guesser.tier, {
|
||||||
tier: romanize(tier),
|
tier: romanize(tier),
|
||||||
})}
|
})}
|
||||||
</DropdownMenu.CheckboxItem>
|
</DropdownMenu.CheckboxItem>
|
||||||
@@ -232,7 +222,7 @@ export function Guesser() {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StarFilledIcon /> {strings.website.tools.guess.select_all}
|
<StarFilledIcon /> {strings.guesser.select_all}
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
@@ -245,7 +235,7 @@ export function Guesser() {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TrashIcon /> {strings.website.tools.guess.clear}
|
<TrashIcon /> {strings.guesser.clear}
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
@@ -255,7 +245,7 @@ export function Guesser() {
|
|||||||
ref={input}
|
ref={input}
|
||||||
onChange={requestSearch}
|
onChange={requestSearch}
|
||||||
style={{ flex: 1, maxWidth: "14rem" }}
|
style={{ flex: 1, maxWidth: "14rem" }}
|
||||||
placeholder={strings.website.tools.guess.search.placeholder}
|
placeholder={strings.common.search.hint_tanks}
|
||||||
size={{ initial: "2", sm: "3" }}
|
size={{ initial: "2", sm: "3" }}
|
||||||
variant="classic"
|
variant="classic"
|
||||||
>
|
>
|
||||||
@@ -275,18 +265,14 @@ export function Guesser() {
|
|||||||
</AlertDialog.Trigger>
|
</AlertDialog.Trigger>
|
||||||
|
|
||||||
<AlertDialog.Content>
|
<AlertDialog.Content>
|
||||||
<AlertDialog.Title>
|
<AlertDialog.Title>{strings.guesser.help.title}</AlertDialog.Title>
|
||||||
{strings.website.tools.guess.help.title}
|
|
||||||
</AlertDialog.Title>
|
|
||||||
<AlertDialog.Description>
|
<AlertDialog.Description>
|
||||||
{strings.website.tools.guess.help.description}
|
{strings.guesser.help.description}
|
||||||
</AlertDialog.Description>
|
</AlertDialog.Description>
|
||||||
|
|
||||||
<Flex justify="end" gap="2">
|
<Flex justify="end" gap="2">
|
||||||
<AlertDialog.Cancel>
|
<AlertDialog.Cancel>
|
||||||
<Button variant="outline">
|
<Button variant="outline">{strings.guesser.help.cancel}</Button>
|
||||||
{strings.website.tools.guess.help.cancel}
|
|
||||||
</Button>
|
|
||||||
</AlertDialog.Cancel>
|
</AlertDialog.Cancel>
|
||||||
|
|
||||||
<AlertDialog.Action>
|
<AlertDialog.Action>
|
||||||
@@ -299,7 +285,7 @@ export function Guesser() {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{strings.website.tools.guess.help.reveal}
|
{strings.guesser.help.reveal}
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDialog.Action>
|
</AlertDialog.Action>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -316,7 +302,7 @@ export function Guesser() {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (guessState === GuessState.NotGuessed) {
|
if (guessState === GuessState.NotGuessed) {
|
||||||
const correct =
|
const correct =
|
||||||
selected !== null && selected.id === tank.id && !helpingReveal;
|
selected !== null && selected.id === tank && !helpingReveal;
|
||||||
|
|
||||||
Guess.mutate((draft) => {
|
Guess.mutate((draft) => {
|
||||||
draft.guessState = correct
|
draft.guessState = correct
|
||||||
@@ -340,7 +326,7 @@ export function Guesser() {
|
|||||||
Guess.mutate((draft) => {
|
Guess.mutate((draft) => {
|
||||||
if (!input.current) return;
|
if (!input.current) return;
|
||||||
|
|
||||||
draft.tank = tank;
|
draft.tank = tank.id;
|
||||||
draft.guessState = GuessState.NotGuessed;
|
draft.guessState = GuessState.NotGuessed;
|
||||||
draft.helpingReveal = false;
|
draft.helpingReveal = false;
|
||||||
|
|
||||||
@@ -351,16 +337,12 @@ export function Guesser() {
|
|||||||
>
|
>
|
||||||
{guessState === GuessState.NotGuessed ? (
|
{guessState === GuessState.NotGuessed ? (
|
||||||
<>
|
<>
|
||||||
{
|
{strings.guesser.search[selected === null ? "skip" : "guess"]}
|
||||||
strings.website.tools.guess.search[
|
|
||||||
selected === null ? "skip" : "guess"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
{selected === null ? <ArrowRightIcon /> : <PaperPlaneIcon />}
|
{selected === null ? <ArrowRightIcon /> : <PaperPlaneIcon />}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{strings.website.tools.guess.search.next}
|
{strings.guesser.search.next}
|
||||||
<ArrowRightIcon />
|
<ArrowRightIcon />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
import { AstroSeo } from "@astrolib/seo";
|
import { AstroSeo } from "@astrolib/seo";
|
||||||
|
import { api } from "../api/dynamic";
|
||||||
import type { Tool } from "../constants/tools";
|
import type { Tool } from "../constants/tools";
|
||||||
import { getStrings } from "../core/i18n/getStrings";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tool: Tool;
|
tool: Tool;
|
||||||
@@ -9,7 +9,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { locale, tool } = Astro.props;
|
const { locale, tool } = Astro.props;
|
||||||
const strings = getStrings(locale);
|
const strings = await api.strings(locale);
|
||||||
const toolStrings =
|
const toolStrings =
|
||||||
strings.website.tools[
|
strings.website.tools[
|
||||||
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
|
(tool.strings ?? tool.id) as keyof typeof strings.website.tools
|
||||||
|
|||||||
@@ -5,13 +5,10 @@ import { GuessBackground } from "../../../../components/GuessBackground";
|
|||||||
import { Guesser } from "../../../../components/Guesser";
|
import { Guesser } from "../../../../components/Guesser";
|
||||||
import { GuessRenderer } from "../../../../components/GuessRenderer";
|
import { GuessRenderer } from "../../../../components/GuessRenderer";
|
||||||
import { GuessRendererLoader } from "../../../../components/GuessRendererLoader";
|
import { GuessRendererLoader } from "../../../../components/GuessRendererLoader";
|
||||||
import { PageWrapper } from "../../../../components/PageWrapper";
|
import { withErrorWrapper } from "../../../../hocs/withErrorWrapper";
|
||||||
import {
|
import { withLocale } from "../../../../hocs/withLocale";
|
||||||
type LocaleAcceptorProps,
|
import { DuelModule, useDuel } from "../../../../hooks/useDuel";
|
||||||
LocaleProvider,
|
import { useUnwrapper } from "../../../../hooks/useUnwrapper";
|
||||||
useLocale,
|
|
||||||
} from "../../../../hooks/useLocale";
|
|
||||||
import { Duel } from "../../../../stores/duel";
|
|
||||||
import { Guess, GuessState } from "../../../../stores/guess";
|
import { Guess, GuessState } from "../../../../stores/guess";
|
||||||
import { Tankopedia } from "../../../../stores/tankopedia";
|
import { Tankopedia } from "../../../../stores/tankopedia";
|
||||||
import type { MaybeSkeletonComponentProps } from "../../../../types/maybeSkeletonComponentProps";
|
import type { MaybeSkeletonComponentProps } from "../../../../types/maybeSkeletonComponentProps";
|
||||||
@@ -23,42 +20,34 @@ const [tankDefinitions, modelDefinitions] = await Promise.all([
|
|||||||
|
|
||||||
const ids = Object.keys(tankDefinitions.tanks);
|
const ids = Object.keys(tankDefinitions.tanks);
|
||||||
|
|
||||||
export function Page({
|
export const Page = withLocale(
|
||||||
locale,
|
withErrorWrapper(({ skeleton }: MaybeSkeletonComponentProps) => {
|
||||||
skeleton,
|
const id = Number(ids[Math.floor(Math.random() * ids.length)]);
|
||||||
}: LocaleAcceptorProps & MaybeSkeletonComponentProps) {
|
|
||||||
const id = Number(ids[Math.floor(Math.random() * ids.length)]);
|
|
||||||
const tank = tankDefinitions.tanks[id];
|
|
||||||
|
|
||||||
Guess.useInitialization(tank);
|
Guess.useInitialization(id);
|
||||||
|
|
||||||
return (
|
return <Container skeleton={skeleton} />;
|
||||||
<LocaleProvider locale={locale}>
|
}),
|
||||||
<Container skeleton={skeleton} />
|
);
|
||||||
</LocaleProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Container({ skeleton }: MaybeSkeletonComponentProps) {
|
function Container({ skeleton }: MaybeSkeletonComponentProps) {
|
||||||
const tank = Guess.use((state) => state.tank);
|
const id = Guess.use((state) => state.tank);
|
||||||
const model = modelDefinitions.models[tank.id];
|
const tank = tankDefinitions.tanks[id];
|
||||||
|
|
||||||
Tankopedia.useInitialization(model);
|
Tankopedia.useInitialization(tank);
|
||||||
Duel.useInitialization({ tank, model });
|
|
||||||
|
|
||||||
return (
|
return <Content skeleton={skeleton} />;
|
||||||
<PageWrapper p="0" maxWidth="unset" color="cyan">
|
|
||||||
<Content skeleton={skeleton} />
|
|
||||||
</PageWrapper>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Content({ skeleton }: MaybeSkeletonComponentProps) {
|
function Content({ skeleton }: MaybeSkeletonComponentProps) {
|
||||||
const { unwrap } = useLocale();
|
const tank = useDuel("protagonist", DuelModule.Tank);
|
||||||
const tank = Guess.use((state) => state.tank);
|
|
||||||
|
const unwrap = useUnwrapper();
|
||||||
|
|
||||||
|
const name = unwrap(tank.name!);
|
||||||
|
|
||||||
const guessState = Guess.use((state) => state.guessState);
|
const guessState = Guess.use((state) => state.guessState);
|
||||||
const isRevealed = guessState !== GuessState.NotGuessed;
|
const isRevealed = guessState !== GuessState.NotGuessed;
|
||||||
const name = unwrap(tank.name!);
|
|
||||||
const fontSize = `min(48vh, ${55 / name.length}vw)`;
|
const fontSize = `min(48vh, ${55 / name.length}vw)`;
|
||||||
const transitionDuration = isRevealed ? "2s" : undefined;
|
const transitionDuration = isRevealed ? "2s" : undefined;
|
||||||
const tiers = Guess.use((state) => state.tiers);
|
const tiers = Guess.use((state) => state.tiers);
|
||||||
@@ -78,10 +67,9 @@ function Content({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
const id = Number(
|
const id = Number(
|
||||||
filteredIds[Math.floor(Math.random() * filteredIds.length)],
|
filteredIds[Math.floor(Math.random() * filteredIds.length)],
|
||||||
);
|
);
|
||||||
const newTank = tankDefinitions.tanks[id];
|
|
||||||
|
|
||||||
Guess.mutate((draft) => {
|
Guess.mutate((draft) => {
|
||||||
draft.tank = newTank;
|
draft.tank = id;
|
||||||
draft.guessState = GuessState.NotGuessed;
|
draft.guessState = GuessState.NotGuessed;
|
||||||
draft.helpingReveal = false;
|
draft.helpingReveal = false;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
---
|
---
|
||||||
import ToolOpenGraph from "../../../../components/ToolOpenGraph.astro";
|
|
||||||
import { tools } from "../../../../constants/tools";
|
|
||||||
import BaseLayout from "../../../../layouts/BaseLayout.astro";
|
import BaseLayout from "../../../../layouts/BaseLayout.astro";
|
||||||
import { Page } from "./_index";
|
import { Page } from "./_index";
|
||||||
|
|
||||||
@@ -9,9 +7,7 @@ export { getStaticPaths } from "../index.astro";
|
|||||||
const { locale } = Astro.props;
|
const { locale } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<ToolOpenGraph {locale} tool={tools.guess} />
|
<BaseLayout accent="blue" {locale}>
|
||||||
|
|
||||||
<BaseLayout {locale} noFooter>
|
|
||||||
<Page {locale} client:only="react">
|
<Page {locale} client:only="react">
|
||||||
<Page {locale} skeleton slot="fallback" />
|
<Page {locale} skeleton slot="fallback" />
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import type { TankDefinition } from "@blitzkit/core";
|
import { Soapstone } from "soapstone";
|
||||||
import { Varuna } from "varuna";
|
|
||||||
import { awaitableTiers } from "../core/awaitables/tiers";
|
import { awaitableTiers } from "../core/awaitables/tiers";
|
||||||
|
|
||||||
const tiers = await awaitableTiers;
|
const tiers = await awaitableTiers;
|
||||||
|
|
||||||
export enum GuessState {
|
export enum GuessState {
|
||||||
Correct,
|
Correct = "correct",
|
||||||
Incorrect,
|
Incorrect = "incorrect",
|
||||||
NotGuessed,
|
NotGuessed = "not-guessed",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Guess {
|
export interface Guess {
|
||||||
tank: TankDefinition;
|
tank: number;
|
||||||
guessState: GuessState;
|
guessState: GuessState;
|
||||||
totalGuesses: number;
|
totalGuesses: number;
|
||||||
correctGuesses: number;
|
correctGuesses: number;
|
||||||
@@ -20,7 +19,7 @@ export interface Guess {
|
|||||||
tiers: number[];
|
tiers: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Guess = new Soapstone<Guess, [TankDefinition]>((tank) => ({
|
export const Guess = new Soapstone<Guess, [number]>((tank) => ({
|
||||||
tank,
|
tank,
|
||||||
guessState: GuessState.NotGuessed,
|
guessState: GuessState.NotGuessed,
|
||||||
totalGuesses: 0,
|
totalGuesses: 0,
|
||||||
|
|||||||
Reference in new issue
Block a user