From 45fa9d2f057728d9e6ee8a2a4ca9c443b436efc2 Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Mon, 18 Nov 2024 19:33:31 -0800 Subject: [PATCH 1/3] feat: add play, hand, brain games to profile page --- src/api/analysis/analysis.ts | 12 ++ src/components/UserProfile/GameList.tsx | 154 +++++++++++++++++---- src/components/UserProfile/UserProfile.tsx | 2 +- src/types/analysis/index.ts | 6 + 4 files changed, 146 insertions(+), 28 deletions(-) diff --git a/src/api/analysis/analysis.ts b/src/api/analysis/analysis.ts index e3efc67..e2b99f1 100644 --- a/src/api/analysis/analysis.ts +++ b/src/api/analysis/analysis.ts @@ -49,6 +49,18 @@ export const getAnalysisList = async (): Promise< return data } +export const getAnalysisGameList = async (type = 'play', page = 1) => { + const res = await fetch(buildUrl(`analysis/user/list/${type}/${page}`)) + + if (res.status === 401) { + throw new Error('Unauthorized') + } + + const data = await res.json() + + return data +} + export const getLichessGames = async ( username: string, onMessage: (data: any) => void, diff --git a/src/components/UserProfile/GameList.tsx b/src/components/UserProfile/GameList.tsx index 07b6803..6c1b325 100644 --- a/src/components/UserProfile/GameList.tsx +++ b/src/components/UserProfile/GameList.tsx @@ -1,32 +1,64 @@ +import { motion } from 'framer-motion' import { AuthContext } from 'src/contexts' import React, { useState, useEffect, useContext } from 'react' -import { getLichessGames } from 'src/api' -import { AnalysisLichessGame } from 'src/types' +import { getLichessGames, getAnalysisGameList } from 'src/api' +import { AnalysisLichessGame, AnalysisWebGame } from 'src/types' export default function GameList() { const { user } = useContext(AuthContext) - const [games, setGames] = useState([]) + const [selected, setSelected] = useState< + 'play' | 'hand' | 'brain' | 'lichess' + >('play') + const [games, setGames] = useState([]) + const [playGames, setPlayGames] = useState([]) + const [handGames, setHandGames] = useState([]) + const [brainGames, setBrainGames] = useState([]) + + useEffect(() => { + if (user?.lichessId) { + const playRequest = getAnalysisGameList('play', 1) + const handRequest = getAnalysisGameList('hand', 1) + const brainRequest = getAnalysisGameList('brain', 1) + + Promise.all([playRequest, handRequest, brainRequest]).then((data) => { + const [play, hand, brain] = data + + const parse = (game: { + game_id: string + maia_name: string + result: string + player_color: 'white' | 'black' + }) => { + const raw = game.maia_name.replace('_kdd_', ' ') + const maia = raw.charAt(0).toUpperCase() + raw.slice(1) + + return { + id: game.game_id, + label: + game.player_color === 'white' + ? `You vs. ${maia}` + : `${maia} vs. You`, + result: game.result, + } + } + + setPlayGames(play.games.map(parse)) + setHandGames(hand.games.map(parse)) + setBrainGames(brain.games.map(parse)) + }) + } + }, [user?.lichessId]) useEffect(() => { if (user?.lichessId) { getLichessGames(user?.lichessId, (data) => { - const playerColor = - data.players.white.user?.id == user?.lichessId ? 'white' : 'black' const result = data.pgn.match(/\[Result\s+"(.+?)"\]/)[1] || '?' const game = { id: data.id, - white: - playerColor == 'white' - ? 'You' - : data.players.white.user?.id || 'Anonymous', - black: - playerColor == 'black' - ? 'You' - : data.players.black.user?.id || 'Anonymous', + label: `${data.players.white.user?.id || 'Unknown'} vs. ${data.players.black.user?.id || 'Unknown'}`, result: result, - pgn: data.pgn, } setGames((x) => [...x, game]) @@ -35,26 +67,56 @@ export default function GameList() { }, [user?.lichessId]) return ( -
-
-

YOUR GAMES

+
+
+

Your Games

- -
- {games.map((game, index) => ( +
+
+
+
+
+
+
+ {(selected === 'play' + ? playGames + : selected === 'hand' + ? handGames + : selected === 'brain' + ? brainGames + : games + ).map((game, index) => ( - ) } + +function Header({ + name, + label, + selected, + setSelected, +}: { + label: string + name: 'play' | 'hand' | 'brain' | 'lichess' + selected: 'play' | 'hand' | 'brain' | 'lichess' + setSelected: (name: 'play' | 'hand' | 'brain' | 'lichess') => void +}) { + return ( + + ) +} diff --git a/src/components/UserProfile/UserProfile.tsx b/src/components/UserProfile/UserProfile.tsx index 93bbae2..596c0e9 100644 --- a/src/components/UserProfile/UserProfile.tsx +++ b/src/components/UserProfile/UserProfile.tsx @@ -80,7 +80,7 @@ const UserProfile: React.FC = () => {
{UserIcon}

{user?.displayName}

-
+
From 934fb2b42d3c22913ed0ac9b9f8c2d001a41c8fa Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Wed, 20 Nov 2024 10:56:13 -0800 Subject: [PATCH 2/3] style: modify profile page --- .../ProfileColumn/ProfileColumn.tsx | 20 +++++++++---------- src/components/UserProfile/GameList.tsx | 6 +++--- src/components/UserProfile/UserProfile.tsx | 10 +++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/components/ProfileColumn/ProfileColumn.tsx b/src/components/ProfileColumn/ProfileColumn.tsx index 96bdff9..23a11c3 100644 --- a/src/components/ProfileColumn/ProfileColumn.tsx +++ b/src/components/ProfileColumn/ProfileColumn.tsx @@ -18,12 +18,12 @@ export const ProfileColumn: React.FC = ({ icon, name, data }: Props) => { const losses = data.losses ?? data.games - data.wins - (data?.draws || 0) return ( -
-
-
{icon}
+
+
+
{icon}

{name}

-
+

Rating

@@ -45,7 +45,7 @@ export const ProfileColumn: React.FC = ({ icon, name, data }: Props) => {
-
+

Wins: {wins}{' '} @@ -55,7 +55,7 @@ export const ProfileColumn: React.FC = ({ icon, name, data }: Props) => {

{draws > 0 ? (
-
+

Draws: {draws}{' '} @@ -67,7 +67,7 @@ export const ProfileColumn: React.FC = ({ icon, name, data }: Props) => { <> )}

-
+

Losses: {losses}{' '} @@ -79,20 +79,20 @@ export const ProfileColumn: React.FC = ({ icon, name, data }: Props) => {

{wins > 0 && (
)} {draws > 0 && (
)} {losses > 0 && (
)} diff --git a/src/components/UserProfile/GameList.tsx b/src/components/UserProfile/GameList.tsx index 6c1b325..255c613 100644 --- a/src/components/UserProfile/GameList.tsx +++ b/src/components/UserProfile/GameList.tsx @@ -2,8 +2,8 @@ import { motion } from 'framer-motion' import { AuthContext } from 'src/contexts' import React, { useState, useEffect, useContext } from 'react' +import { AnalysisWebGame } from 'src/types' import { getLichessGames, getAnalysisGameList } from 'src/api' -import { AnalysisLichessGame, AnalysisWebGame } from 'src/types' export default function GameList() { const { user } = useContext(AuthContext) @@ -97,7 +97,7 @@ export default function GameList() { setSelected={setSelected} />
-
+
{(selected === 'play' ? playGames : selected === 'hand' @@ -108,7 +108,7 @@ export default function GameList() { ).map((game, index) => (
diff --git a/src/components/UserProfile/UserProfile.tsx b/src/components/UserProfile/UserProfile.tsx index 596c0e9..1705f96 100644 --- a/src/components/UserProfile/UserProfile.tsx +++ b/src/components/UserProfile/UserProfile.tsx @@ -85,7 +85,7 @@ const UserProfile: React.FC = () => {
} - name="REGULAR" + name="Regular" data={{ rating: stats.regularRating, highest: stats.regularMax, @@ -97,7 +97,7 @@ const UserProfile: React.FC = () => { /> } - name="HAND" + name="Hand" data={{ rating: stats.handRating, highest: stats.handMax, @@ -109,7 +109,7 @@ const UserProfile: React.FC = () => { /> } - name="BRAIN" + name="Brain" data={{ rating: stats.brainRating, highest: stats.brainMax, @@ -121,7 +121,7 @@ const UserProfile: React.FC = () => { /> } - name="TRAIN" + name="Train" data={{ rating: stats.trainRating, highest: stats.trainMax, @@ -132,7 +132,7 @@ const UserProfile: React.FC = () => { /> } - name="BOT/NOT" + name="Bot / Not" data={{ rating: stats.botNotRating, highest: stats.botNotMax, From b8b5c10c0579f48d4093f0e4bd2cf607c0ed81b0 Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Fri, 22 Nov 2024 18:37:51 -0800 Subject: [PATCH 3/3] feat: add capability to analyze play, hand, and brain games on analyze page --- src/api/analysis/analysis.ts | 100 +++++++++++ .../AnalysisGameList.tsx | 82 ++++----- .../Tournament.tsx | 3 +- src/components/Analysis/UserGameList.tsx | 164 ++++++++++++++++++ src/components/UserProfile/GameList.tsx | 69 ++++---- src/components/UserProfile/UserProfile.tsx | 2 +- .../AnalysisListContext.tsx | 10 +- .../useAnalysisController.ts | 2 +- src/pages/analysis/[...id].tsx | 87 ++++++++-- .../AnalysisListContextProvider.tsx | 87 ++++++++-- src/types/analysis/index.ts | 4 +- 11 files changed, 489 insertions(+), 121 deletions(-) rename src/components/{AnalysisGameList => Analysis}/AnalysisGameList.tsx (68%) rename src/components/{AnalysisGameList => Analysis}/Tournament.tsx (98%) create mode 100644 src/components/Analysis/UserGameList.tsx diff --git a/src/api/analysis/analysis.ts b/src/api/analysis/analysis.ts index e2b99f1..61da8cf 100644 --- a/src/api/analysis/analysis.ts +++ b/src/api/analysis/analysis.ts @@ -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 +} diff --git a/src/components/AnalysisGameList/AnalysisGameList.tsx b/src/components/Analysis/AnalysisGameList.tsx similarity index 68% rename from src/components/AnalysisGameList/AnalysisGameList.tsx rename to src/components/Analysis/AnalysisGameList.tsx index 7f4989a..63e6d25 100644 --- a/src/components/AnalysisGameList/AnalysisGameList.tsx +++ b/src/components/Analysis/AnalysisGameList.tsx @@ -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 @@ -25,6 +26,12 @@ interface AnalysisGameListProps { setCurrentMove: Dispatch>, currentMaiaModel: string, ) => Promise + loadNewUserGames: ( + id: string, + type: 'play' | 'hand' | 'brain', + setCurrentMove: Dispatch>, + currentMaiaModel: string, + ) => Promise } const AnalysisGameList: React.FC = ({ @@ -32,12 +39,20 @@ const AnalysisGameList: React.FC = ({ 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) => @@ -85,11 +100,11 @@ const AnalysisGameList: React.FC = ({
) : ( -
- {analysisLichessList.map((game, index) => { - const selected = - currentId && currentId[1] === 'lichess' - ? currentId[0] === game.id - : false - - return ( - - ) - })} -
+ )}
) : null diff --git a/src/components/AnalysisGameList/Tournament.tsx b/src/components/Analysis/Tournament.tsx similarity index 98% rename from src/components/AnalysisGameList/Tournament.tsx rename to src/components/Analysis/Tournament.tsx index 0944373..4bb8516 100644 --- a/src/components/AnalysisGameList/Tournament.tsx +++ b/src/components/Analysis/Tournament.tsx @@ -1,4 +1,5 @@ import { Dispatch, SetStateAction } from 'react' + import { PlusIcon, MinusIcon, @@ -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 diff --git a/src/components/Analysis/UserGameList.tsx b/src/components/Analysis/UserGameList.tsx new file mode 100644 index 0000000..b4dadfb --- /dev/null +++ b/src/components/Analysis/UserGameList.tsx @@ -0,0 +1,164 @@ +import { motion } from 'framer-motion' +import { SetStateAction, Dispatch } from 'react' + +import { AnalysisWebGame } from 'src/types' + +interface Props { + currentId: string[] | null + playGames: AnalysisWebGame[] + handGames: AnalysisWebGame[] + brainGames: AnalysisWebGame[] + lichessGames: AnalysisWebGame[] + selected: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn' + setSelected: (name: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn') => void + setCurrentIndex: Dispatch> + setLoadingIndex: (index: number | null) => void + loadNewLichessGames: ( + id: string, + pgn: string, + setCurrentMove: Dispatch>, + currentMaiaModel: string, + ) => void + loadNewUserGames: ( + id: string, + type: 'play' | 'hand' | 'brain', + setCurrentMove: Dispatch>, + currentMaiaModel: string, + ) => void + currentMaiaModel: string +} + +export default function UserGameList({ + currentId, + selected, + setSelected, + playGames, + handGames, + brainGames, + lichessGames, + setLoadingIndex, + setCurrentIndex, + loadNewLichessGames, + loadNewUserGames, + currentMaiaModel, +}: Props) { + return ( +
+
+
+
+
+
+
+
+ {(selected === 'play' + ? playGames + : selected === 'hand' + ? handGames + : selected === 'brain' + ? brainGames + : lichessGames + ).map((game, index) => { + const selectedGame = currentId && currentId[0] === game.id + return ( + + ) + })} +
+
+ ) +} + +function Header({ + name, + label, + selected, + setSelected, +}: { + label: string + name: 'play' | 'hand' | 'brain' | 'pgn' + selected: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn' + setSelected: (name: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn') => void +}) { + return ( + + ) +} diff --git a/src/components/UserProfile/GameList.tsx b/src/components/UserProfile/GameList.tsx index 255c613..3426d4c 100644 --- a/src/components/UserProfile/GameList.tsx +++ b/src/components/UserProfile/GameList.tsx @@ -7,14 +7,31 @@ import { getLichessGames, getAnalysisGameList } from 'src/api' export default function GameList() { const { user } = useContext(AuthContext) - const [selected, setSelected] = useState< - 'play' | 'hand' | 'brain' | 'lichess' - >('play') + const [selected, setSelected] = useState<'play' | 'hand' | 'brain' | 'pgn'>( + 'play', + ) const [games, setGames] = useState([]) const [playGames, setPlayGames] = useState([]) const [handGames, setHandGames] = useState([]) const [brainGames, setBrainGames] = useState([]) + useEffect(() => { + if (user?.lichessId) { + getLichessGames(user?.lichessId, (data) => { + const result = data.pgn.match(/\[Result\s+"(.+?)"\]/)[1] || '?' + + const game: AnalysisWebGame = { + id: data.id, + label: `${data.players.white.user?.id || 'Unknown'} vs. ${data.players.black.user?.id || 'Unknown'}`, + result: result, + type: 'pgn', + } + + setGames((x) => [...x, game]) + }) + } + }, [user?.lichessId]) + useEffect(() => { if (user?.lichessId) { const playRequest = getAnalysisGameList('play', 1) @@ -24,12 +41,15 @@ export default function GameList() { Promise.all([playRequest, handRequest, brainRequest]).then((data) => { const [play, hand, brain] = data - const parse = (game: { - game_id: string - maia_name: string - result: string - player_color: 'white' | 'black' - }) => { + const parse = ( + game: { + game_id: string + maia_name: string + result: string + player_color: 'white' | 'black' + }, + type: string, + ) => { const raw = game.maia_name.replace('_kdd_', ' ') const maia = raw.charAt(0).toUpperCase() + raw.slice(1) @@ -40,28 +60,13 @@ export default function GameList() { ? `You vs. ${maia}` : `${maia} vs. You`, result: game.result, + type, } } - setPlayGames(play.games.map(parse)) - setHandGames(hand.games.map(parse)) - setBrainGames(brain.games.map(parse)) - }) - } - }, [user?.lichessId]) - - useEffect(() => { - if (user?.lichessId) { - getLichessGames(user?.lichessId, (data) => { - const result = data.pgn.match(/\[Result\s+"(.+?)"\]/)[1] || '?' - - const game = { - id: data.id, - label: `${data.players.white.user?.id || 'Unknown'} vs. ${data.players.black.user?.id || 'Unknown'}`, - result: result, - } - - setGames((x) => [...x, game]) + setPlayGames(play.games.map((game: never) => parse(game, 'play'))) + setHandGames(hand.games.map((game: never) => parse(game, 'hand'))) + setBrainGames(brain.games.map((game: never) => parse(game, 'brain'))) }) } }, [user?.lichessId]) @@ -92,7 +97,7 @@ export default function GameList() { />
@@ -132,9 +137,9 @@ function Header({ setSelected, }: { label: string - name: 'play' | 'hand' | 'brain' | 'lichess' - selected: 'play' | 'hand' | 'brain' | 'lichess' - setSelected: (name: 'play' | 'hand' | 'brain' | 'lichess') => void + name: 'play' | 'hand' | 'brain' | 'pgn' + selected: 'play' | 'hand' | 'brain' | 'pgn' + setSelected: (name: 'play' | 'hand' | 'brain' | 'pgn') => void }) { return (
@@ -612,6 +664,7 @@ const Analysis: React.FC = ({ currentMaiaModel={currentMaiaModel} loadNewTournamentGame={getAndSetTournamentGame} loadNewLichessGames={getAndSetLichessGames} + loadNewUserGames={getAndSetUserGames} />
diff --git a/src/providers/AnalysisListContextProvider/AnalysisListContextProvider.tsx b/src/providers/AnalysisListContextProvider/AnalysisListContextProvider.tsx index c732011..48404e5 100644 --- a/src/providers/AnalysisListContextProvider/AnalysisListContextProvider.tsx +++ b/src/providers/AnalysisListContextProvider/AnalysisListContextProvider.tsx @@ -1,9 +1,9 @@ +import { useRouter } from 'next/router' import { ReactNode, useContext, useEffect, useState } from 'react' +import { AnalysisWebGame, AnalysisTournamentGame } from 'src/types' import { AuthContext, AnalysisListContext } from 'src/contexts' -import { getAnalysisList, getLichessGames } from 'src/api' -import { AnalysisLichessGame, AnalysisTournamentGame } from 'src/types' -import { useRouter } from 'next/router' +import { getAnalysisList, getLichessGames, getAnalysisGameList } from 'src/api' export const AnalysisListContextProvider: React.FC<{ children: ReactNode }> = ({ children, @@ -18,8 +18,17 @@ export const AnalysisListContextProvider: React.FC<{ children: ReactNode }> = ({ AnalysisTournamentGame[] > | null>(null) const [analysisLichessList, setAnalysisLichessList] = useState< - AnalysisLichessGame[] + AnalysisWebGame[] >([]) + const [analysisPlayList, setAnalysisPlayList] = useState( + [], + ) + const [analysisHandList, setAnalysisHandList] = useState( + [], + ) + const [analysisBrainList, setAnalysisBrainList] = useState( + [], + ) useEffect(() => { async function getAndSetData() { @@ -41,23 +50,12 @@ export const AnalysisListContextProvider: React.FC<{ children: ReactNode }> = ({ useEffect(() => { if (user?.lichessId) { getLichessGames(user?.lichessId, (data) => { - const playerColor = - data.players.white.user?.id == user?.lichessId ? 'white' : 'black' - const result = data.pgn.match(/\[Result\s+"(.+?)"\]/)[1] || '?' - const game = { + const game: AnalysisWebGame = { id: data.id, - white: - playerColor === 'white' - ? 'You' - : data.players.white.user?.id || 'Anonymous', - whiteRating: data.players.white.rating, - black: - playerColor === 'black' - ? 'You' - : data.players.black.user?.id || 'Anonymous', - blackRating: data.players.black.rating, + type: 'pgn', + label: `${data.players.white.user?.id || 'Unknown'} vs. ${data.players.black.user?.id || 'Unknown'}`, result: result, pgn: data.pgn, } @@ -67,9 +65,60 @@ export const AnalysisListContextProvider: React.FC<{ children: ReactNode }> = ({ } }, [user?.lichessId]) + useEffect(() => { + if (user?.lichessId) { + const playRequest = getAnalysisGameList('play', 1) + const handRequest = getAnalysisGameList('hand', 1) + const brainRequest = getAnalysisGameList('brain', 1) + + Promise.all([playRequest, handRequest, brainRequest]).then((data) => { + const [play, hand, brain] = data + + const parse = ( + game: { + game_id: string + maia_name: string + result: string + player_color: 'white' | 'black' + }, + type: string, + ) => { + const raw = game.maia_name.replace('_kdd_', ' ') + const maia = raw.charAt(0).toUpperCase() + raw.slice(1) + + return { + id: game.game_id, + label: + game.player_color === 'white' + ? `You vs. ${maia}` + : `${maia} vs. You`, + result: game.result, + type, + } + } + + setAnalysisPlayList( + play.games.map((game: never) => parse(game, 'play')), + ) + setAnalysisHandList( + hand.games.map((game: never) => parse(game, 'hand')), + ) + setAnalysisBrainList( + brain.games.map((game: never) => parse(game, 'brain')), + ) + }) + } + }, [user?.lichessId]) + return ( {children} diff --git a/src/types/analysis/index.ts b/src/types/analysis/index.ts index f1cf455..35b2cd7 100644 --- a/src/types/analysis/index.ts +++ b/src/types/analysis/index.ts @@ -1,7 +1,7 @@ import { Game } from '../base' import { AvailableMoves } from '../training' -type EvaluationType = 'tournament' | 'pgn' +type EvaluationType = 'tournament' | 'pgn' | 'play' | 'hand' | 'brain' type StockfishEvaluations = T extends 'tournament' ? MoveMap[] @@ -28,8 +28,10 @@ export interface AnalysisLichessGame { export interface AnalysisWebGame { id: string + type: 'tournament' | 'pgn' | 'play' | 'hand' | 'brain' label: string result: string + pgn?: string } export interface AnalyzedGame extends Game {