Skip to content

Commit

Permalink
feat: add capability to analyze play, hand, and brain games on analyz…
Browse files Browse the repository at this point in the history
…e page
  • Loading branch information
kevinjosethomas committed Nov 23, 2024
1 parent 934fb2b commit b8b5c10
Show file tree
Hide file tree
Showing 11 changed files with 489 additions and 121 deletions.
100 changes: 100 additions & 0 deletions src/api/analysis/analysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,103 @@ export const getAnalyzedLichessGame = async (
pgn,
} as AnalyzedGame
}

export const getAnalyzedUserGame = async (
id: string,
game_type: 'play' | 'hand' | 'brain',
maia_model = 'maia_kdd_1500',
) => {
const res = await fetch(
buildUrl(
`analysis/user/analyze_user_maia_game/${id}?` +
new URLSearchParams({
game_type,
maia_model,
}),
),
{
method: 'GET',
headers: {
'Content-Type': 'text/plain',
},
},
)

if (res.status === 401) {
throw new Error('Unauthorized')
}

const data = await res.json()

const termination = {
...data['termination'],
condition: 'Normal',
}

const gameType = 'blitz'
const blackPlayer = data['black_player']
const whitePlayer = data['white_player']

const maiaEvaluations: { [model: string]: MoveMap[] } = {}
const positionEvaluations: { [model: string]: PositionEvaluation[] } = {}
const availableMoves: AvailableMoves[] = []

for (const model of data['maia_versions']) {
maiaEvaluations[model] = data['maia_evals'][model]
positionEvaluations[model] = Object.keys(data['maia_evals'][model]).map(
() => ({
trickiness: 1,
performance: 1,
}),
)
}

for (const position of data['move_maps']) {
const moves: AvailableMoves = {}
for (const move of position) {
const fromTo = move.move.join('')
const san = move['move_san']
const { check, fen } = move

moves[fromTo] = {
board: fen,
check,
san,
lastMove: move.move,
}
}
availableMoves.push(moves)
}

const gameStates = data['game_states']

const moves = gameStates.map((gameState: any) => {
const {
last_move: lastMove,
fen,
check,
last_move_san: san,
evaluations: maia_values,
} = gameState

return {
board: fen,
lastMove,
san,
check,
maia_values,
}
})

return {
id,
blackPlayer,
whitePlayer,
moves,
maiaEvaluations,
availableMoves,
gameType,
termination,
positionEvaluations,
} as AnalyzedGame
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { motion } from 'framer-motion'

import Tournament from './Tournament'
import { AnalysisListContext, GameControllerContext } from 'src/contexts'
import UserGameList from './UserGameList'

interface AnalysisGameListProps {
currentId: string[] | null
Expand All @@ -25,19 +26,33 @@ interface AnalysisGameListProps {
setCurrentMove: Dispatch<SetStateAction<number>>,
currentMaiaModel: string,
) => Promise<void>
loadNewUserGames: (
id: string,
type: 'play' | 'hand' | 'brain',
setCurrentMove: Dispatch<SetStateAction<number>>,
currentMaiaModel: string,
) => Promise<void>
}

const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
currentId,
currentMaiaModel,
loadNewTournamentGame,
loadNewLichessGames,
loadNewUserGames,
}) => {
const [selected, setSelected] = useState<'tournament' | 'lichess'>('lichess')
const [selected, setSelected] = useState<
'tournament' | 'pgn' | 'play' | 'hand' | 'brain'
>('pgn')

const controller = useContext(GameControllerContext)
const { analysisTournamentList, analysisLichessList } =
useContext(AnalysisListContext)
const {
analysisPlayList,
analysisHandList,
analysisBrainList,
analysisLichessList,
analysisTournamentList,
} = useContext(AnalysisListContext)
const listKeys = useMemo(() => {
return analysisTournamentList
? Array.from(analysisTournamentList.keys()).sort((a, b) =>
Expand Down Expand Up @@ -85,11 +100,11 @@ const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
<div className="flex flex-col items-start justify-start overflow-hidden rounded bg-background-1">
<div className="flex min-h-12 w-full items-center justify-center overflow-hidden bg-background-2">
<button
onClick={() => setSelected('lichess')}
className={`relative z-10 flex h-full w-full items-center justify-center py-2 pb-3 transition duration-300 hover:bg-background-3 ${selected === 'lichess' && 'bg-background-5'}`}
onClick={() => setSelected('pgn')}
className={`relative z-10 flex h-full w-full items-center justify-center py-2 pb-3 transition duration-300 hover:bg-background-3 ${['pgn', 'hand', 'brain', 'play'].includes(selected) && 'bg-background-5'}`}
>
<p className="z-10 font-medium text-primary">Your Games</p>
{selected === 'lichess' && (
{['pgn', 'hand', 'brain', 'play'].includes(selected) && (
<motion.div
layoutId="selected-highlight"
className="absolute bottom-0 left-0 h-1 w-full rounded bg-primary"
Expand Down Expand Up @@ -130,47 +145,20 @@ const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
))}
</div>
) : (
<div className="flex h-full w-full flex-col justify-start overflow-y-scroll">
{analysisLichessList.map((game, index) => {
const selected =
currentId && currentId[1] === 'lichess'
? currentId[0] === game.id
: false

return (
<button
key={index}
onClick={async () => {
setLoadingIndex(index)
await loadNewLichessGames(
game.id,
game.pgn,
controller.setCurrentIndex,
currentMaiaModel,
)
setLoadingIndex(null)
}}
className={`group flex w-full cursor-pointer items-center gap-2 ${selected ? 'bg-background-2 font-bold' : 'hover:bg-background-2'}`}
>
<div
className={`flex h-full w-10 items-center justify-center ${selected ? 'bg-background-3' : 'bg-background-2 group-hover:bg-background-3'}`}
>
{loadingIndex === index ? (
<div className="spinner" />
) : (
<p className="text-muted">{index + 1}</p>
)}
</div>
<div className="flex flex-1 items-center justify-between py-1">
<p className="text-primary">
{game.white} vs. {game.black}
</p>
<p className="text-muted">{game.result}</p>
</div>
</button>
)
})}
</div>
<UserGameList
currentId={currentId}
selected={selected}
setSelected={setSelected}
playGames={analysisPlayList}
handGames={analysisHandList}
brainGames={analysisBrainList}
lichessGames={analysisLichessList}
setCurrentIndex={controller.setCurrentIndex}
currentMaiaModel={currentMaiaModel}
loadNewUserGames={loadNewUserGames}
loadNewLichessGames={loadNewLichessGames}
setLoadingIndex={setLoadingIndex}
/>
)}
</div>
) : null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Dispatch, SetStateAction } from 'react'

import {
PlusIcon,
MinusIcon,
Expand Down Expand Up @@ -67,7 +68,7 @@ export default function Tournament({
>
{games?.map((game, j) => {
const selected =
currentId && currentId[1] != 'lichess'
currentId && currentId[1] == 'tournament'
? sectionId == currentId[0] &&
game.game_index == Number.parseInt(currentId[1])
: false
Expand Down
Loading

0 comments on commit b8b5c10

Please sign in to comment.