diff --git a/src/components/game/variant-header.tsx b/src/components/game/variant-header.tsx
index 85cb3c5..a45068d 100644
--- a/src/components/game/variant-header.tsx
+++ b/src/components/game/variant-header.tsx
@@ -1,37 +1,47 @@
-import { useBoardSubset } from "@/lib/hooks";
+import { groupByValue } from "@/lib/game";
+import { useBoardSubset, useSessionSubset } from "@/lib/hooks";
import { cva } from "class-variance-authority";
+import { useMemo } from "react";
-const variantHeader = cva("flex gap-2 text-sm text-main font-bold", {
+const variantHeader = cva("flex gap-2 text-sm font-bold", {
variants: {
orientation: {
horizontal: "",
vertical: "flex-col items-center",
},
+ result: {
+ correct: "text-lime-400",
+ almost: "text-amber-300",
+ inProgress: "text-main",
+ },
},
});
type Props = {
+ orientation: "horizontal" | "vertical";
+ index: number;
variant: number;
};
-type RowProps = {
- row: number;
-} & Props;
+export function VariantHeader({ orientation, index, variant }: Props) {
+ const dir = orientation === "horizontal" ? "row" : "col";
+ const boardRow = useBoardSubset(dir, index);
+ const boardHints = groupByValue(boardRow, variant);
+ const sessionRow = useSessionSubset(dir, index);
+ const sessionHints = groupByValue(sessionRow, variant);
+ // TODO This re-renders way too much because of the selectAtom
-type ColProps = {
- col: number;
-} & Props;
+ const result =
+ sessionRow.toString() === boardRow.toString()
+ ? "correct"
+ : sessionHints.toString() === boardHints.toString() &&
+ sessionRow.filter((i) => i > -1).length === boardRow.length
+ ? "almost"
+ : "inProgress";
-export function VariantHeader({ variant, ...props }: RowProps | ColProps) {
- const orientation = "row" in props ? "horizontal" : "vertical";
- const block = useBoardSubset(
- "row" in props ? "row" : "col",
- "row" in props ? props.row : props.col,
- variant,
- );
return (
-
- {block.map((count, i) => (
+
+ {boardHints.map((count, i) => (
{count}
))}
diff --git a/src/components/game/variant-hints.tsx b/src/components/game/variant-hints.tsx
index 27c3e99..d5e7f36 100644
--- a/src/components/game/variant-hints.tsx
+++ b/src/components/game/variant-hints.tsx
@@ -22,21 +22,10 @@ interface Props {
blocks: number[][];
}
-function headerProps
(orientation: T) {
- return (index: number) => {
- return {
- [orientation]: index,
- } as Record;
- };
-}
-
export function VariantHints({ variant, position, blocks }: Props) {
const orientation = ["top", "bottom"].includes(position)
? "horizontal"
: "vertical";
- const propsFactory = headerProps(
- orientation === "horizontal" ? "col" : "row",
- );
return (
{blocks.map((_, i) => (
@@ -49,7 +38,14 @@ export function VariantHints({ variant, position, blocks }: Props) {
position === "top" ? "justify-end" : "",
].join(" ")}
>
-
+
))}
diff --git a/src/lib/hooks.ts b/src/lib/hooks.ts
index 611618d..7094fae 100644
--- a/src/lib/hooks.ts
+++ b/src/lib/hooks.ts
@@ -1,22 +1,22 @@
import { useAtom, useAtomValue } from "jotai";
import { useMemo } from "react";
import {
- _boardAtom,
boardAtom,
boardMatrixAtom,
gameResultAtom,
- getGuessAtomAt,
- getVariantAtomAt,
heightAtom,
preferencesAtom,
+ selectBoardSubset,
+ selectGuessAt,
+ selectSessionSubset,
+ selectVariantAt,
sessionMatrixAtom,
variantsAtom,
widthAtom,
} from "./state";
-import { groupByValue, groupIntoCols, groupIntoRows } from "./game";
export function useGuessAt(index: number) {
- const atomCell = useMemo(() => getGuessAtomAt(index), [index]);
+ const atomCell = useMemo(() => selectGuessAt(index), [index]);
const [cell] = useAtom(atomCell);
return cell;
}
@@ -26,7 +26,7 @@ export function useVariants() {
}
export function useVariantAt(index: number) {
- const variantAtom = useMemo(() => getVariantAtomAt(index), [index]);
+ const variantAtom = useMemo(() => selectVariantAt(index), [index]);
return useAtomValue(variantAtom);
}
@@ -52,19 +52,14 @@ export function useGameResult() {
return useAtomValue(gameResultAtom);
}
-export function useBoardSubset(
- orientation: "row" | "col",
- index: number,
- variant: number,
-) {
- const [width] = useBoardDimensions();
- const board = useBoard();
+export function useBoardSubset(dir: "row" | "col", index: number) {
+ const subset = useMemo(() => selectBoardSubset(dir, index), [dir, index]);
+ return useAtomValue(subset);
+}
- if (orientation === "row") {
- return groupByValue(groupIntoRows(board, width)[index]!, variant);
- } else {
- return groupByValue(groupIntoCols(board, width)[index]!, variant);
- }
+export function useSessionSubset(dir: "row" | "col", index: number) {
+ const subset = useMemo(() => selectSessionSubset(dir, index), [dir, index]);
+ return useAtomValue(subset);
}
export function usePreferences() {
diff --git a/src/lib/state.ts b/src/lib/state.ts
index 2da68d0..8f5f73a 100644
--- a/src/lib/state.ts
+++ b/src/lib/state.ts
@@ -103,7 +103,45 @@ export const preferencesAtom = atom(
},
);
-export const getGuessAtomAt = (index: number) =>
+export const selectBoardSubset = (dir: "row" | "col", index: number) =>
+ selectAtom(boardMatrixAtom, (board) => {
+ if (dir === "row") {
+ const row = board[index];
+ if (typeof row === "undefined") {
+ throw new Error(`No board ${dir} at index ${index}`);
+ }
+ return row;
+ } else {
+ return board.map((row) => {
+ const col = row[index];
+ if (typeof col === "undefined") {
+ throw new Error(`No board ${dir} at index ${index}`);
+ }
+ return col;
+ });
+ }
+ });
+
+export const selectSessionSubset = (dir: "row" | "col", index: number) =>
+ selectAtom(sessionMatrixAtom, (session) => {
+ if (dir === "row") {
+ const row = session[index];
+ if (typeof row === "undefined") {
+ throw new Error(`No session ${dir} at index ${index}`);
+ }
+ return row;
+ } else {
+ return session.map((row) => {
+ const col = row[index];
+ if (typeof col === "undefined") {
+ throw new Error(`No session ${dir} at index ${index}`);
+ }
+ return col;
+ });
+ }
+ });
+
+export const selectGuessAt = (index: number) =>
selectAtom(sessionAtom, (cells) => {
const cellAtom = cells[index];
if (typeof cellAtom === "undefined") {
@@ -112,7 +150,7 @@ export const getGuessAtomAt = (index: number) =>
return cellAtom;
});
-export function getVariantAtomAt(index: number) {
+export function selectVariantAt(index: number) {
return selectAtom(variantsAtom, (variants) => {
const variant = variants[index];
if (typeof variant === "undefined") {