Skip to content

Commit

Permalink
clock refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscoBSalgueiro committed Dec 7, 2024
1 parent f07a134 commit d439bd8
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 129 deletions.
94 changes: 13 additions & 81 deletions src/components/boards/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,13 @@ import {
import { keyMapAtom } from "@/state/keybinds";
import { chessboard } from "@/styles/Chessboard.css";
import { ANNOTATION_INFO, isBasicAnnotation } from "@/utils/annotation";
import {
type TimeControlField,
getMaterialDiff,
getVariationLine,
parseTimeControl,
} from "@/utils/chess";
import { getMaterialDiff, getVariationLine } from "@/utils/chess";
import {
chessopsError,
forceEnPassant,
positionFromFen,
} from "@/utils/chessops";
import { type TimeControlField, getClockInfo } from "@/utils/clock";
import { getNodeAtPath } from "@/utils/treeReducer";
import {
ActionIcon,
Expand Down Expand Up @@ -107,8 +103,6 @@ interface ChessboardProps {
canTakeBack?: boolean;
whiteTime?: number;
blackTime?: number;
whiteTc?: TimeControlField;
blackTc?: TimeControlField;
practicing?: boolean;
}

Expand All @@ -125,8 +119,6 @@ function Board({
canTakeBack,
whiteTime,
blackTime,
whiteTc,
blackTc,
practicing,
}: ChessboardProps) {
const { t } = useTranslation();
Expand Down Expand Up @@ -331,6 +323,13 @@ function Board({
shapes = shapes.concat(currentNode.shapes);
}

const hasClock =
whiteTime !== undefined ||
blackTime !== undefined ||
headers.time_control !== undefined ||
headers.white_time_control !== undefined ||
headers.black_time_control !== undefined;

function changeTabType() {
setCurrentTab((t) => {
return {
Expand Down Expand Up @@ -494,73 +493,6 @@ function Board({
const lightColor = theme.colors[color][6];
const darkColor = theme.colors[color][8];

const timeControl = headers.time_control
? parseTimeControl(headers.time_control)
: null;
let { whiteSeconds, blackSeconds } = match(pos?.turn)
.with("white", () => ({
whiteSeconds: getNodeAtPath(root, position.slice(0, -1))?.clock,
blackSeconds: currentNode.clock,
}))
.with("black", () => ({
whiteSeconds: currentNode.clock,
blackSeconds: getNodeAtPath(root, position.slice(0, -1))?.clock,
}))
.otherwise(() => {
return {
whiteSeconds: undefined,
blackSeconds: undefined,
};
});
if (position.length <= 1 && timeControl) {
if (timeControl.length > 0) {
const seconds = timeControl[0].seconds / 1000;
if (!whiteSeconds) {
whiteSeconds = seconds;
}
if (!blackSeconds) {
blackSeconds = seconds;
}
}
}
if (whiteTime) {
whiteSeconds = whiteTime / 1000;
}
if (blackTime) {
blackSeconds = blackTime / 1000;
}

function calculateProgress(clock?: number, tc?: TimeControlField) {
if (!clock) {
return 0;
}
if (tc) {
return clock / (tc.seconds / 1000);
}
if (timeControl) {
return clock / (timeControl[0].seconds / 1000);
}
if (root.children.length > 0 && root.children[0].clock) {
return clock / root.children[0].clock;
}
return 0;
}

const hasClock =
whiteTime !== undefined ||
blackTime !== undefined ||
headers.time_control !== undefined ||
whiteTc !== undefined ||
blackTc !== undefined;

const topClock = orientation === "black" ? whiteSeconds : blackSeconds;
const topTc = orientation === "black" ? whiteTc : blackTc;
const topProgress = calculateProgress(topClock, topTc);

const bottomClock = orientation === "black" ? blackSeconds : whiteSeconds;
const bottomTc = orientation === "black" ? blackTc : whiteTc;
const bottomProgress = calculateProgress(bottomClock, bottomTc);

const [enableBoardScroll] = useAtom(enableBoardScrollAtom);
const [snapArrows] = useAtom(snapArrowsAtom);

Expand Down Expand Up @@ -620,10 +552,10 @@ function Board({
<Group ml="2.5rem" h="2.125rem">
{hasClock && (
<Clock
clock={topClock}
color={orientation === "black" ? "white" : "black"}
progress={topProgress}
turn={turn}
whiteTime={whiteTime}
blackTime={blackTime}
/>
)}
<ShowMaterial
Expand Down Expand Up @@ -793,10 +725,10 @@ function Board({
<Group ml="2.5rem">
{hasClock && (
<Clock
clock={bottomClock}
color={orientation}
progress={bottomProgress}
turn={turn}
whiteTime={whiteTime}
blackTime={blackTime}
/>
)}
<ShowMaterial
Expand Down
36 changes: 27 additions & 9 deletions src/components/boards/BoardGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
enginesAtom,
tabsAtom,
} from "@/state/atoms";
import { type TimeControlField, getMainLine } from "@/utils/chess";
import { getMainLine } from "@/utils/chess";
import { positionFromFen } from "@/utils/chessops";
import type { TimeControlField } from "@/utils/clock";
import type { LocalEngine } from "@/utils/engines";
import { type GameHeaders, treeIteratorMainLine } from "@/utils/treeReducer";
import {
Expand Down Expand Up @@ -517,12 +518,31 @@ function BoardGame() {
time_control: undefined,
};

if (sameTimeControl && players.white.timeControl) {
newHeaders.time_control = `${players.white.timeControl.seconds / 1000}`;
if (players.white.timeControl.increment) {
newHeaders.time_control += `+${
players.white.timeControl.increment / 1000
}`;
if (players.white.timeControl || players.black.timeControl) {
if (sameTimeControl && players.white.timeControl) {
newHeaders.time_control = `${players.white.timeControl.seconds / 1000}`;
if (players.white.timeControl.increment) {
newHeaders.time_control += `+${
players.white.timeControl.increment / 1000
}`;
}
} else {
if (players.white.timeControl) {
newHeaders.white_time_control = `${players.white.timeControl.seconds / 1000}`;
if (players.white.timeControl.increment) {
newHeaders.white_time_control += `+${
players.white.timeControl.increment / 1000
}`;
}
}
if (players.black.timeControl) {
newHeaders.black_time_control = `${players.black.timeControl.seconds / 1000}`;
if (players.black.timeControl.increment) {
newHeaders.black_time_control += `+${
players.black.timeControl.increment / 1000
}`;
}
}
}
}

Expand Down Expand Up @@ -597,8 +617,6 @@ function BoardGame() {
blackTime={
gameState === "playing" ? (blackTime ?? undefined) : undefined
}
whiteTc={players.white.timeControl}
blackTc={players.black.timeControl}
/>
</Portal>
<Portal target="#topRight" style={{ height: "100%", overflow: "hidden" }}>
Expand Down
40 changes: 36 additions & 4 deletions src/components/boards/Clock.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
import { positionFromFen } from "@/utils/chessops";
import { getClockInfo } from "@/utils/clock";
import { Paper, Progress, Text } from "@mantine/core";
import { useContext } from "react";
import { match } from "ts-pattern";
import { useStore } from "zustand";
import { TreeStateContext } from "../common/TreeStateContext";
import * as classes from "./Clock.css";

function Clock({
color,
turn,
progress,
clock,
whiteTime,
blackTime,
}: {
color: "white" | "black";
turn: "white" | "black";
progress: number;
clock: number | undefined;
whiteTime?: number;
blackTime?: number;
}) {
const store = useContext(TreeStateContext)!;
const root = useStore(store, (s) => s.root);
const position = useStore(store, (s) => s.position);
const headers = useStore(store, (s) => s.headers);
const currentNode = useStore(store, (s) => s.currentNode());
const [pos, error] = positionFromFen(currentNode.fen);

const { white, black } = getClockInfo({
headers,
root,
currentClock: currentNode.clock,
position,
pos,
whiteTime,
blackTime,
});

const clock = match(color)
.with("white", () => white.value)
.with("black", () => black.value)
.otherwise(() => undefined);
const progress = match(color)
.with("white", () => white.progress)
.with("black", () => black.progress)
.otherwise(() => 0);

return (
<Paper
className={color === "black" ? classes.blackClock : classes.whiteClock}
Expand Down
4 changes: 2 additions & 2 deletions src/components/boards/EvalListener.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
enginesAtom,
tabEngineSettingsFamily,
} from "@/state/atoms";
import { getVariationLine } from "@/utils/chess";
import { getBestMoves as chessdbGetBestMoves } from "@/utils/chessdb/api";
import { positionFromFen, swapMove } from "@/utils/chessops";
import {
Expand All @@ -24,9 +25,8 @@ import { useAtom, useAtomValue } from "jotai";
import { startTransition, useContext, useEffect, useMemo } from "react";
import { match } from "ts-pattern";
import { useStore } from "zustand";
import { TreeStateContext } from "../common/TreeStateContext";
import { getVariationLine } from "@/utils/chess";
import { useShallow } from "zustand/react/shallow";
import { TreeStateContext } from "../common/TreeStateContext";

function EvalListener() {
const [engines] = useAtom(enginesAtom);
Expand Down
39 changes: 6 additions & 33 deletions src/utils/chess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ function headersToPGN(game: GameHeaders): string {
if (game.time_control) {
headers += `[TimeControl "${game.time_control}"]\n`;
}
if (game.white_time_control) {
headers += `[WhiteTimeControl "${game.white_time_control}"]\n`;
}
if (game.black_time_control) {
headers += `[BlackTimeControl "${game.black_time_control}"]\n`;
}
if (game.eco) {
headers += `[ECO "${game.eco}"]\n`;
}
Expand Down Expand Up @@ -550,39 +556,6 @@ function getPgnHeaders(tokens: Token[]): GameHeaders {
return headers;
}

export type TimeControlField = {
seconds: number;
increment?: number;
moves?: number;
};

export type TimeControl = TimeControlField[];

export function parseTimeControl(timeControl: string): TimeControl {
const fields = timeControl.split(":");
const timeControlFields: TimeControl = [];
for (const field of fields) {
const match = field.match(/(?:(\d+)\/)?(\d+)(?:\+(\d+))?/);
if (!match) {
continue;
}
const moves = match[1];
const seconds = match[2];
const increment = match[3];
const timeControlField: TimeControlField = {
seconds: Number.parseInt(seconds) * 1000,
};
if (increment) {
timeControlField.increment = Number.parseInt(increment) * 1000;
}
if (moves) {
timeControlField.moves = Number.parseInt(moves);
}
timeControlFields.push(timeControlField);
}
return timeControlFields;
}

type ColorMap<T> = {
[key in Color]: T;
};
Expand Down
Loading

0 comments on commit d439bd8

Please sign in to comment.