Skip to content

Commit

Permalink
Release (v3) (#6)
Browse files Browse the repository at this point in the history
Co-authored-by: ぎがへるつ <[email protected]>
Co-authored-by: KtaK721 <[email protected]>
Co-authored-by: GIGAHERTZ00 <[email protected]>
Co-authored-by: KtaK <[email protected]>
  • Loading branch information
5 people authored Oct 15, 2024
1 parent c6617f7 commit a01cca9
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 19 deletions.
1 change: 1 addition & 0 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"typescript-remix-routes-plugin": "^1.0.1",
"vite": "^5.4.8",
"vite-env-only": "^3.0.3",
"vite-plugin-env-compatible": "^2.0.1",
"vite-tsconfig-paths": "^4.3.2",
"wrangler": "^3.79.0"
}
Expand Down
5 changes: 2 additions & 3 deletions apps/frontend/src/app/components/board/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ export const Board = ({ board, width, height, zoomLevel, marks, scrollGroup }: P
<Fragment key={virtualRow.key}>
{columnVirtualizer.getVirtualItems().map((virtualColumn) => {
const cell = board[virtualRow.index][virtualColumn.index] as "0" | "1" | "2" | "3";
const borderColor = shouldMark(marks, virtualColumn.index, virtualRow.index)
? "var(--orange-8)"
: "var(--mauve-2)";
const borderColor =
marks && shouldMark(marks, virtualColumn.index, virtualRow.index) ? "var(--orange-8)" : "var(--mauve-2)";

return (
<BoardCell
Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/src/app/components/board/Cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const isCell = (cell: string): cell is "0" | "1" | "2" | "3" => ["0", "1"

type Props = {
cell: "0" | "1" | "2" | "3";
size: string;
size?: string;
borderColor?: string;
style?: CSSProperties;
};
Expand Down
6 changes: 5 additions & 1 deletion apps/frontend/src/app/components/replay/InputFileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ export const InputFileCard = ({ onSetReplayInfo }: Props) => {
onChange={(files) => (files ? setFile(files[0]) : setFile(null))}
/>
</FormControl>
{error && <Text color="red">{error}</Text>}
{error && (
<Text color="red" whiteSpace="no-wrap" textOverflow="ellipsis">
{error}
</Text>
)}
</CardBody>
</Card>
);
Expand Down
22 changes: 19 additions & 3 deletions apps/frontend/src/app/components/replay/TimelineCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
Checkbox,
HStack,
Heading,
Input,
InputGroup,
InputLeftElement,
InputRightElement,
Expand All @@ -18,7 +17,7 @@ import {
VStack,
useBoolean,
} from "@yamada-ui/react";
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";

const clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);

Expand All @@ -28,6 +27,7 @@ type Props = Readonly<{
onChangeTurn: (turn: number) => void;
showDebugOverlay: boolean;
onChangeDebugOverlay: (showDebugOverlay: boolean) => void;
onChangeInterval: (interval: number) => void;
}>;

export const TimelineCard = ({
Expand All @@ -36,14 +36,24 @@ export const TimelineCard = ({
onChangeTurn,
showDebugOverlay,
onChangeDebugOverlay,
onChangeInterval,
}: Props) => {
const [isPlaying, { off: pause, toggle: togglePlaying }] = useBoolean(false);
const [rawInterval, setRawInterval] = useState<string>("");
const interval = rawInterval === "" ? null : Number(rawInterval);
const oldInterval = useRef(interval);

useEffect(() => {
if (interval !== oldInterval.current) {
oldInterval.current = interval;

onChangeInterval(interval ?? 0);
}
}, [interval, onChangeInterval]);

const turns = actualTurns - 1; // turn starts from 0

if (currentTurn === turns - 1) pause();
if (currentTurn === turns && isPlaying) pause();

useEffect(() => {
if (isPlaying && interval !== null) {
Expand Down Expand Up @@ -92,8 +102,14 @@ export const TimelineCard = ({
</InputRightElement>
</InputGroup>
<ButtonGroup isAttached isDisabled={turns <= 0} variant="outline" gap="sm">
<Button onClick={() => onChangeTurn(clamp(currentTurn - 1, 0, turns))} isDisabled={currentTurn === 0}>
-1
</Button>
<Button onClick={() => onChangeTurn(clamp(currentTurn - 10, 0, turns))}>-10</Button>
<Button onClick={() => onChangeTurn(clamp(currentTurn + 10, 0, turns))}>+10</Button>
<Button onClick={() => onChangeTurn(clamp(currentTurn + 1, 0, turns))} isDisabled={currentTurn === turns}>
+1
</Button>
</ButtonGroup>
<Checkbox isChecked={showDebugOverlay} onChange={() => onChangeDebugOverlay(!showDebugOverlay)}>
Debug overlay
Expand Down
23 changes: 23 additions & 0 deletions apps/frontend/src/app/routes/mock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
Grid,
HStack,
Heading,
InputGroup,
InputRightElement,
NumberInput,
Select,
Switch,
Expand Down Expand Up @@ -59,6 +61,8 @@ export default function Page() {
const height = randomHeight || Number.isNaN(rawHeight) ? 0 : Number(rawHeight);
const [genKindStart, setGenKindStart] = useState<GenerationKindStart>("all-random");
const [genKindGoal, setGenKindGoal] = useState<GenerationKindGoal>("all-random");
const [rawWaitDuration, setRawWaitDuration] = useState("5");
const waitDuration = Number.isNaN(rawWaitDuration) ? 0 : Number(rawWaitDuration);
const notice = useNotice();

return (
Expand All @@ -79,6 +83,7 @@ export default function Page() {
height,
genKindStart,
genKindGoal,
waitDuration,
}),
});

Expand Down Expand Up @@ -169,6 +174,24 @@ export default function Page() {
/>
</FormControl>
</VStack>
<VStack>
<FormControl label="Wait Duration">
<InputGroup>
<NumberInput
placeholder="10"
fontFeatureSettings="'tnum'"
min={0}
value={rawWaitDuration}
onChange={setRawWaitDuration}
required
/>

<InputRightElement mr={4}>
<p>s</p>
</InputRightElement>
</InputGroup>
</FormControl>
</VStack>
</HStack>
<HStack gap="md">
<Button colorScheme="primary" type="submit">
Expand Down
60 changes: 50 additions & 10 deletions apps/frontend/src/app/routes/replay.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { easyKatanuki } from "@data-maki/algorithm";
import type { Board as BoardSchema, ReplayInfo } from "@data-maki/schemas";
import { Box, Checkbox, Flex, Grid, HStack, Heading, SimpleGrid, Spacer, Text, useBoolean } from "@yamada-ui/react";
import { useMemo, useState } from "react";
import { type CSSProperties, useMemo, useState } from "react";
import { ScrollSync } from "scroll-sync-react";
import { useDebounce } from "use-debounce";
import { Board } from "../components/board/Board";
import { BoardCell } from "../components/board/Cell";
import { StartGoalBoard } from "../components/board/StartGoalBoard";
import { ZoomLevelSlider } from "../components/board/ZoomLevelSlider";
Expand All @@ -13,7 +14,12 @@ import { TimelineCard } from "../components/replay/TimelineCard";

export default function Page() {
const [rawTurn, setTurn] = useState(0);
const [turn] = useDebounce(rawTurn, 400);
const [interval, setIntervalState] = useState(400);

const [turn] = useDebounce(rawTurn, Math.min(interval, 400), {
leading: true /* Need this to prevent delayed updates when playing */,
});

const [replayInfo, setReplayInfo] = useState<ReplayInfo | null>(null);
const [showDebugOverlay, setDebugOverlay] = useState(true);
const [hideCellNumber, { toggle: toggleHideCellNumber }] = useBoolean(false);
Expand All @@ -23,12 +29,18 @@ export default function Page() {
const [turns, boards] = useMemo(() => {
if (!replayInfo) return [0, []];

const boards: string[][] = [replayInfo.problem.board.start];
const boards: string[][] = [structuredClone(replayInfo.problem.board.start)];

for (const op of replayInfo.answer.ops) {
boards.push(easyKatanuki(replayInfo.problem, op));
const afterBoard = easyKatanuki(replayInfo.problem, op);

replayInfo.problem.board.start = afterBoard;

boards.push(afterBoard);
}

replayInfo.problem.board.start = boards[0];

return [replayInfo.answer.n + 1, boards] as const;
}, [replayInfo]);

Expand All @@ -44,7 +56,7 @@ export default function Page() {
}
: null;

const extraOpInfo = showDebugOverlay ? replayInfo?.extraInfo[turn] : undefined;
const extraOpInfo = replayInfo?.extraInfo[turn];
const delta =
extraOpInfo?.delta ??
replayInfo?.extraInfo
Expand All @@ -67,15 +79,26 @@ export default function Page() {
onChangeTurn={setTurn}
showDebugOverlay={showDebugOverlay}
onChangeDebugOverlay={setDebugOverlay}
onChangeInterval={setIntervalState}
/>
</Grid>
<Box as="section" minH="100vh">
<Box
as="section"
minH="100vh"
style={
{
"--cell-color": hideCellNumber ? "transparent" : "var(--mauve-10)",
// color: `var(--${colors[cell]}-8)`,
// color: `var(--mauve-10)`,
} as CSSProperties
}
>
<Heading as="h2" size="lg" fontWeight="medium" lineHeight={1.2}>
Board
</Heading>
{board && extraOpInfo ? (
{(board && extraOpInfo) || turn === turns - 1 ? (
<>
<section>
<Box as="section" my={4}>
<Heading as="h3" size="md" fontWeight="regular" lineHeight={1}>
Delta
</Heading>
Expand All @@ -99,7 +122,7 @@ export default function Page() {
</HStack>
</Flex>
) : null}
</section>
</Box>
<Grid templateColumns="1fr 1fr" w="100%" placeItems="start" gap={4}>
<Heading as="h3" size="md" fontWeight="regular" lineHeight={1}>
Start
Expand All @@ -109,7 +132,24 @@ export default function Page() {
</Heading>
</Grid>
<ScrollSync>
<StartGoalBoard board={board} zoomLevel={zoomLevel} syncScroll={syncScroll} extraInfo={extraOpInfo} />
{turn === turns - 1 ? (
<Grid templateColumns="1fr 1fr" w="100%" placeItems="start" gap={4}>
<Box />
<Board
board={replayInfo?.problem.board.goal}
width={replayInfo?.problem.board.width}
height={replayInfo?.problem.board.height}
zoomLevel={zoomLevel}
/>
</Grid>
) : (
<StartGoalBoard
board={board}
zoomLevel={zoomLevel}
syncScroll={syncScroll}
extraInfo={showDebugOverlay ? extraOpInfo : undefined}
/>
)}
</ScrollSync>
<Grid as="section" templateColumns="auto 1fr auto" w="100%" mb={4}>
<SimpleGrid columns={2} gap="md">
Expand Down
3 changes: 3 additions & 0 deletions apps/frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { flatRoutes } from "remix-flat-routes";
import { remixRoutes } from "remix-routes/vite";
import { defineConfig } from "vite";
import { denyImports, envOnlyMacros } from "vite-env-only";
import env from "vite-plugin-env-compatible";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
build: {
minify: true,
sourcemap: true,
},
envPrefix: "SOLVER_",
plugins: [
cloudflareDevProxyVitePlugin(),
remix({
Expand Down Expand Up @@ -43,6 +45,7 @@ export default defineConfig({
typia({
log: false,
}),
env({ prefix: "SOLVER", mountedPath: "process.env" }),
],
ssr: {
resolve: {
Expand Down
1 change: 1 addition & 0 deletions apps/mock-server/src/gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export type GenerationSettings = {
height: number;
genKindStart: GenerationKindStart;
genKindGoal: GenerationKindGoal;
waitDuration?: number;
};

export const getBoardArrayFromNumbers = (numbers: number[], width: number): string[] => {
Expand Down
22 changes: 22 additions & 0 deletions apps/mock-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const generationSettings: GenerationSettings = {
height: 0,
genKindStart: "all-random",
genKindGoal: "all-random",
waitDuration: 5,
};

const app = new Hono();
Expand Down Expand Up @@ -55,7 +56,11 @@ app.use(async (c, next) => {
await next();
});

let lockedDown = true;

app.get("/problem", (c) => {
if (lockedDown) return new Response('"AccessTimeError"', { status: 403 });

const [id, problem] = generateProblem(generationSettings);

c.header("X-Data-Maki-Problem-ID", id.toString());
Expand All @@ -71,6 +76,14 @@ app.post("/answer", async (c) => {
return c.json({ error: "Invalid answer format", details: validation.errors }, 400);
}

if (generationSettings.waitDuration && generationSettings.waitDuration > 0) {
lockedDown = true;

setTimeout(() => {
lockedDown = false;
}, generationSettings.waitDuration * 1000);
}

const revision = microtime.now();

return c.json({ revision });
Expand All @@ -85,10 +98,19 @@ app.post("/settings", async (c) => {
generationSettings.height = settings.height;
generationSettings.genKindStart = settings.genKindStart;
generationSettings.genKindGoal = settings.genKindGoal;
generationSettings.waitDuration = settings.waitDuration;

return new Response(null, { status: 204 });
});

if (generationSettings.waitDuration && generationSettings.waitDuration > 0) {
lockedDown = true;

setTimeout(() => {
lockedDown = false;
}, generationSettings.waitDuration * 1000);
}

export default {
port: PORT,
hostname: HOST,
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/schemas/src/replay-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type CellsMark = CellsMarkLine | CellsMarkPoint;
export interface ExtraOpInfo {
currentMark: CellsMark;
goalMark: CellsMark;
delta?: (Array<number & tags.Type<"uint32">> & tags.MinItems<4> & tags.MaxItems<4>) | null;
delta?: (Array<number & tags.Type<"int32">> & tags.MinItems<4> & tags.MaxItems<4>) | null;
}

export interface ReplayInfo {
Expand Down

0 comments on commit a01cca9

Please sign in to comment.