Skip to content

Commit

Permalink
feat: add hover/click options to blunder meter and move recommendatio…
Browse files Browse the repository at this point in the history
…ns + fix export game
  • Loading branch information
kevinjosethomas committed Feb 10, 2025
1 parent 61a74bd commit 2572884
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 31 deletions.
38 changes: 29 additions & 9 deletions src/components/Analysis/BlunderMeter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import { BlunderMeterResult, ColorSanMapping } from 'src/types'
interface Props {
data: BlunderMeterResult
colorSanMapping: ColorSanMapping
hover: (move?: string) => void
makeMove: (move: string) => void
}

export const BlunderMeter: React.FC<Props> = ({
data,
hover,
makeMove,
colorSanMapping,
}: Props) => {
return (
Expand All @@ -19,27 +23,33 @@ export const BlunderMeter: React.FC<Props> = ({
<div className="flex h-full w-full flex-col overflow-hidden">
<div className="flex h-full w-full select-none flex-col overflow-hidden rounded">
<Meter
hover={hover}
makeMove={makeMove}
title="Good Moves"
textColor="text-green-600"
moves={data.goodMoves.moves}
bgColor="bg-green-600 rounded-t"
probability={data.goodMoves.probability}
moves={data.goodMoves.moves}
colorSanMapping={colorSanMapping}
/>
<Meter
hover={hover}
title="OK Moves"
textColor="text-yellow-500"
makeMove={makeMove}
moves={data.okMoves.moves}
bgColor="bg-yellow-500"
textColor="text-yellow-500"
probability={data.okMoves.probability}
moves={data.okMoves.moves}
colorSanMapping={colorSanMapping}
/>
<Meter
hover={hover}
title="Blunder Moves"
makeMove={makeMove}
textColor="text-red-600"
bgColor="bg-red-600 rounded-b"
probability={data.blunderMoves.probability}
moves={data.blunderMoves.moves}
probability={data.blunderMoves.probability}
colorSanMapping={colorSanMapping}
/>
</div>
Expand All @@ -48,19 +58,23 @@ export const BlunderMeter: React.FC<Props> = ({
)
}
function Meter({
probability,
moves,
textColor,
bgColor,
title,
hover,
makeMove,
textColor,
probability,
colorSanMapping,
}: {
title: string
textColor: string
bgColor: string
probability: number
moves: { move: string; probability: number }[]
hover: (move?: string) => void
makeMove: (move: string) => void
colorSanMapping: ColorSanMapping
moves: { move: string; probability: number }[]
}) {
return (
<motion.div
Expand Down Expand Up @@ -89,10 +103,16 @@ function Meter({
.slice(0, 6)
.filter((move) => move.probability >= 2)
.map((move) => (
<span key={move.move} className="hover:underline">
<button
key={move.move}
className="text-left hover:underline"
onMouseLeave={() => hover()}
onMouseEnter={() => hover(move.move)}
onClick={() => makeMove(move.move)}
>
{colorSanMapping[move.move]?.san || move.move} (
{Math.round(move.probability)}%){' '}
</span>
</button>
))}
</div>
</div>
Expand Down
25 changes: 17 additions & 8 deletions src/components/Analysis/Highlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@ interface Props {
maia?: { move: string; prob: number }[]
stockfish?: { move: string; cp: number }[]
}

hover: (move?: string) => void
makeMove: (move: string) => void
movesByRating: { [key: string]: number }[] | undefined
}

export const Highlight: React.FC<Props> = ({
currentMaiaModel,
recommendations,
hover,
makeMove,
movesByRating,
moveEvaluation,
colorSanMapping,
movesByRating,
recommendations,
currentMaiaModel,
}: Props) => {
return (
<div className="flex h-full w-full items-start overflow-hidden rounded border-[0.5px] border-white/40 bg-background-1">
Expand Down Expand Up @@ -58,32 +61,38 @@ export const Highlight: React.FC<Props> = ({
<div className="grid grid-rows-2 items-center justify-center p-3">
{recommendations.maia?.map(({ move, prob }, index) => {
return (
<div
<button
key={index}
className="grid cursor-default grid-cols-2 gap-3 hover:underline"
style={{
color: colorSanMapping[move]?.color ?? '#fff',
}}
onMouseLeave={() => hover()}
onMouseEnter={() => hover(move)}
onClick={() => makeMove(move)}
>
<p className="text-right font-mono text-sm">
{(Math.round(prob * 1000) / 10).toFixed(1)}%
</p>
<p className="text-left font-mono text-sm">
{colorSanMapping[move]?.san ?? move}
</p>
</div>
</button>
)
})}
</div>
<div className="grid grid-rows-2 flex-col items-center justify-center p-3">
{recommendations.stockfish?.map(({ move, cp }, index) => {
return (
<div
<button
key={index}
className="grid cursor-default grid-cols-2 gap-3 hover:underline"
style={{
color: colorSanMapping[move]?.color ?? '#fff',
}}
onMouseLeave={() => hover()}
onMouseEnter={() => hover(move)}
onClick={() => makeMove(move)}
>
<p className="w-[42px] text-right font-mono text-sm">
{cp > 0 ? '+' : null}
Expand All @@ -92,7 +101,7 @@ export const Highlight: React.FC<Props> = ({
<p className="font-mono text-sm">
{colorSanMapping[move]?.san ?? move}
</p>
</div>
</button>
)
})}
</div>
Expand Down
1 change: 0 additions & 1 deletion src/components/Board/AnalysisGameBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ export const AnalysisGameBoard: React.FC<Props> = ({
if (setCurrentSquare) setCurrentSquare(null)

const chess = new Chess(currentNode.fen)

const moveAttempt = chess.move({ from: from, to: to })

if (moveAttempt) {
Expand Down
17 changes: 8 additions & 9 deletions src/components/Misc/ExportGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ export const ExportGame: React.FC<Props> = ({
}

return (
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-0.5">
<div className="flex items-center justify-between">
<div className="flex w-full flex-col gap-2">
<div className="flex w-full flex-col gap-0.5">
<div className="flex w-full items-center justify-between">
<p className="select-none text-sm font-semibold tracking-wider text-secondary">
FEN
</p>
Expand All @@ -82,16 +82,16 @@ export const ExportGame: React.FC<Props> = ({
role="button"
tabIndex={0}
onClick={() => copy(fen)}
className="border-1 group flex cursor-pointer overflow-x-hidden rounded border border-white/5 bg-background-1/50 px-3 py-2"
className="border-1 group flex w-full cursor-pointer overflow-x-hidden rounded border border-white/5 bg-background-1/50 px-3 py-2"
>
<p className="whitespace-nowrap text-xs text-secondary group-hover:text-secondary/80">
{fen}
</p>
</div>
</div>
<div className="flex flex-col gap-0.5">
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="flex w-full flex-col gap-0.5">
<div className="flex w-full items-center justify-between">
<div className="flex w-full items-center">
<p className="select-none text-sm font-semibold tracking-wider text-secondary">
PGN
</p>
Expand All @@ -106,7 +106,6 @@ export const ExportGame: React.FC<Props> = ({
</p>
</div>
</div>

<i
tabIndex={0}
role="button"
Expand All @@ -120,7 +119,7 @@ export const ExportGame: React.FC<Props> = ({
role="button"
tabIndex={0}
onClick={() => copy(pgn)}
className="border-1 group flex max-h-32 cursor-pointer overflow-x-hidden overflow-y-scroll rounded border border-white/5 bg-background-1/50 p-3"
className="group flex max-h-32 w-full cursor-pointer overflow-x-hidden overflow-y-scroll rounded border border-white/5 bg-background-1/50 p-3"
>
<p className="whitespace-pre-wrap text-xs text-secondary group-hover:text-secondary/80">
{pgn}
Expand Down
60 changes: 56 additions & 4 deletions src/pages/analysis/[...id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ import {
AnalysisGameList,
AnalysisGameBoard,
DownloadModelModal,
MoveRecommendations,
ContinueAgainstMaia,
AuthenticatedWrapper,
AnalysisMovesContainer,
AnalysisBoardController,
} from 'src/components'
import Head from 'next/head'
import type { NextPage } from 'next'
import toast from 'react-hot-toast'
import type { NextPage } from 'next'
import { useRouter } from 'next/router'
import type { Key } from 'chessground/types'
import { Chess, PieceSymbol } from 'chess.ts'
import { useAnalysisController } from 'src/hooks'
import { AnimatePresence, animateValue, motion } from 'framer-motion'
import { AnimatePresence, motion } from 'framer-motion'
import type { DrawBrushes, DrawShape } from 'chessground/draw'
import { ConfigureAnalysis } from 'src/components/Analysis/ConfigureAnalysis'

Expand Down Expand Up @@ -316,6 +316,54 @@ const Analysis: React.FC<Props> = ({
setArrows(arr)
}, [moveEvaluation, controller.currentNode, controller.orientation])

const hover = (move?: string) => {
if (move) {
setHoverArrow({
orig: move.slice(0, 2) as Key,
dest: move.slice(2, 4) as Key,
brush: 'green',
modifiers: {
lineWidth: 10,
},
})
} else {
setHoverArrow(null)
}
}

const makeMove = (move: string) => {
if (!controller.currentNode || !analyzedGame.tree) return

const chess = new Chess(controller.currentNode.fen)
const moveAttempt = chess.move({
from: move.slice(0, 2),
to: move.slice(2, 4),
promotion: move[4] ? (move[4] as PieceSymbol) : undefined,
})

if (moveAttempt) {
const newFen = chess.fen()

const moveString =
moveAttempt.from +
moveAttempt.to +
(moveAttempt.promotion ? moveAttempt.promotion : '')
const san = moveAttempt.san

if (controller.currentNode.mainChild?.move === moveString) {
controller.goToNode(controller.currentNode.mainChild)
} else {
const newVariation = analyzedGame.tree.addVariation(
controller.currentNode,
newFen,
moveString,
san,
)
controller.goToNode(newVariation)
}
}
}

const Player = ({
name,
rating,
Expand Down Expand Up @@ -489,7 +537,7 @@ const Analysis: React.FC<Props> = ({
MAIA_MODELS={MAIA_MODELS}
/>
) : screen.id === 'export' ? (
<div className="flex flex-col p-4">
<div className="flex w-full flex-col p-4">
<ExportGame
game={analyzedGame as unknown as PlayedGame}
whitePlayer={analyzedGame.whitePlayer.name}
Expand All @@ -507,6 +555,8 @@ const Analysis: React.FC<Props> = ({
>
<div className="flex h-[calc((55vh+4.5rem)/2)]">
<Highlight
hover={hover}
makeMove={makeMove}
currentMaiaModel={currentMaiaModel}
recommendations={moveRecommendations}
moveEvaluation={
Expand All @@ -528,6 +578,8 @@ const Analysis: React.FC<Props> = ({
/>
</div>
<BlunderMeter
hover={hover}
makeMove={makeMove}
data={blunderMeter}
colorSanMapping={colorSanMapping}
/>
Expand Down

0 comments on commit 2572884

Please sign in to comment.