Skip to content

Commit daa12d5

Browse files
fix: game selection and redirect criteria
1 parent 51d6274 commit daa12d5

File tree

8 files changed

+255
-51
lines changed

8 files changed

+255
-51
lines changed

src/components/Analysis/AnalysisGameList.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,25 @@ import { AnalysisListContext, GameControllerContext } from 'src/contexts'
1414

1515
interface AnalysisGameListProps {
1616
currentId: string[] | null
17-
currentMaiaModel: string
17+
1818
loadNewTournamentGame: (
1919
newId: string[],
20-
setCurrentMove: Dispatch<SetStateAction<number>>,
20+
setCurrentMove?: Dispatch<SetStateAction<number>>,
2121
) => Promise<void>
2222
loadNewLichessGames: (
2323
id: string,
2424
pgn: string,
25-
setCurrentMove: Dispatch<SetStateAction<number>>,
26-
currentMaiaModel: string,
25+
setCurrentMove?: Dispatch<SetStateAction<number>>,
2726
) => Promise<void>
2827
loadNewUserGames: (
2928
id: string,
3029
type: 'play' | 'hand' | 'brain',
31-
setCurrentMove: Dispatch<SetStateAction<number>>,
32-
currentMaiaModel: string,
30+
setCurrentMove?: Dispatch<SetStateAction<number>>,
3331
) => Promise<void>
3432
}
3533

3634
export const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
3735
currentId,
38-
currentMaiaModel,
3936
loadNewTournamentGame,
4037
loadNewLichessGames,
4138
loadNewUserGames,
@@ -159,14 +156,12 @@ export const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
159156
game.id,
160157
game.pgn as string,
161158
controller.setCurrentIndex,
162-
currentMaiaModel,
163159
)
164160
} else {
165161
await loadNewUserGames(
166162
game.id,
167163
game.type as 'play' | 'hand' | 'brain',
168164
controller.setCurrentIndex,
169-
currentMaiaModel,
170165
)
171166
}
172167
setLoadingIndex(null)
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
import React, {
2+
useRef,
3+
useMemo,
4+
Dispatch,
5+
useState,
6+
useEffect,
7+
useContext,
8+
SetStateAction,
9+
} from 'react'
10+
import { motion } from 'framer-motion'
11+
12+
import { Tournament } from 'src/components'
13+
import { AnalysisListContext } from 'src/contexts'
14+
15+
interface AnalysisGameListProps {
16+
currentId: string[] | null
17+
loadNewTournamentGame: (
18+
newId: string[],
19+
setCurrentMove?: Dispatch<SetStateAction<number>>,
20+
) => Promise<void>
21+
loadNewLichessGames: (
22+
id: string,
23+
pgn: string,
24+
setCurrentMove?: Dispatch<SetStateAction<number>>,
25+
) => Promise<void>
26+
loadNewUserGames: (
27+
id: string,
28+
type: 'play' | 'hand' | 'brain',
29+
setCurrentMove?: Dispatch<SetStateAction<number>>,
30+
) => Promise<void>
31+
}
32+
33+
export const ClientAnalysisGameList: React.FC<AnalysisGameListProps> = ({
34+
currentId,
35+
loadNewTournamentGame,
36+
loadNewLichessGames,
37+
loadNewUserGames,
38+
}) => {
39+
const {
40+
analysisPlayList,
41+
analysisHandList,
42+
analysisBrainList,
43+
analysisLichessList,
44+
analysisTournamentList,
45+
} = useContext(AnalysisListContext)
46+
47+
const listKeys = useMemo(() => {
48+
return analysisTournamentList
49+
? Array.from(analysisTournamentList.keys()).sort(
50+
(a, b) =>
51+
b?.split('---')?.[1]?.localeCompare(a?.split('---')?.[1] ?? '') ??
52+
0,
53+
)
54+
: []
55+
}, [analysisTournamentList])
56+
57+
const initialOpenIndex = useMemo(() => {
58+
if (analysisTournamentList && currentId) {
59+
return listKeys.map((m) => m?.split('---')?.[0]).indexOf(currentId[0])
60+
} else {
61+
return null
62+
}
63+
}, [analysisTournamentList, currentId, listKeys])
64+
65+
const [selected, setSelected] = useState<
66+
'tournament' | 'pgn' | 'play' | 'hand' | 'brain'
67+
>('pgn')
68+
const [loadingIndex, setLoadingIndex] = useState<number | null>(null)
69+
const [openIndex, setOpenIndex] = useState<number | null>(initialOpenIndex)
70+
71+
const openElement = useRef<HTMLDivElement>(null)
72+
const selectedGameElement = useRef<HTMLButtonElement>(null)
73+
74+
useEffect(() => {
75+
setLoadingIndex(null)
76+
}, [selected])
77+
78+
return analysisTournamentList ? (
79+
<div className="flex flex-col items-start justify-start overflow-hidden rounded bg-background-1">
80+
<div className="flex w-full flex-col">
81+
<div className="grid select-none grid-cols-5 border-b-2 border-white border-opacity-10">
82+
<Header
83+
label="Play"
84+
name="play"
85+
selected={selected}
86+
setSelected={setSelected}
87+
/>
88+
<Header
89+
label="Hand"
90+
name="hand"
91+
selected={selected}
92+
setSelected={setSelected}
93+
/>
94+
<Header
95+
label="Brain"
96+
name="brain"
97+
selected={selected}
98+
setSelected={setSelected}
99+
/>
100+
<Header
101+
label="Lichess"
102+
name="pgn"
103+
selected={selected}
104+
setSelected={setSelected}
105+
/>
106+
<Header
107+
label="WC Matches"
108+
name="tournament"
109+
selected={selected}
110+
setSelected={setSelected}
111+
/>
112+
</div>
113+
<div className="red-scrollbar flex max-h-64 flex-col overflow-y-scroll md:max-h-[60vh]">
114+
{selected === 'tournament' ? (
115+
<>
116+
{listKeys.map((id, i) => (
117+
<Tournament
118+
key={i}
119+
id={id}
120+
index={i}
121+
openIndex={openIndex}
122+
currentId={currentId}
123+
openElement={openElement as React.RefObject<HTMLDivElement>}
124+
setOpenIndex={setOpenIndex}
125+
loadingIndex={loadingIndex}
126+
setLoadingIndex={setLoadingIndex}
127+
selectedGameElement={
128+
selectedGameElement as React.RefObject<HTMLButtonElement>
129+
}
130+
loadNewTournamentGame={loadNewTournamentGame}
131+
analysisTournamentList={analysisTournamentList}
132+
/>
133+
))}
134+
</>
135+
) : (
136+
<>
137+
{(selected === 'play'
138+
? analysisPlayList
139+
: selected === 'hand'
140+
? analysisHandList
141+
: selected === 'brain'
142+
? analysisBrainList
143+
: analysisLichessList
144+
).map((game, index) => {
145+
const selectedGame = currentId && currentId[0] === game.id
146+
return (
147+
<button
148+
key={index}
149+
onClick={async () => {
150+
setLoadingIndex(index)
151+
if (game.type === 'pgn') {
152+
await loadNewLichessGames(game.id, game.pgn as string)
153+
} else {
154+
await loadNewUserGames(
155+
game.id,
156+
game.type as 'play' | 'hand' | 'brain',
157+
)
158+
}
159+
setLoadingIndex(null)
160+
}}
161+
className={`group flex w-full cursor-pointer items-center gap-2 pr-2 ${selectedGame ? 'bg-background-2 font-bold' : index % 2 === 0 ? 'bg-background-1/30 hover:bg-background-2' : 'bg-background-1/10 hover:bg-background-2'}`}
162+
>
163+
<div
164+
className={`flex h-full w-10 items-center justify-center py-1 ${selectedGame ? 'bg-background-3' : 'bg-background-2 group-hover:bg-white/5'}`}
165+
>
166+
<p className="text-secondary">{index + 1}</p>
167+
</div>
168+
<div className="flex flex-1 items-center justify-between overflow-hidden py-1">
169+
<p className="overflow-hidden text-ellipsis whitespace-nowrap text-primary">
170+
{game.label}
171+
</p>
172+
<p className="whitespace-nowrap text-secondary">
173+
{game.result}
174+
</p>
175+
</div>
176+
</button>
177+
)
178+
})}
179+
</>
180+
)}
181+
</div>
182+
</div>
183+
</div>
184+
) : null
185+
}
186+
187+
function Header({
188+
name,
189+
label,
190+
selected,
191+
setSelected,
192+
}: {
193+
label: string
194+
name: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn'
195+
selected: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn'
196+
setSelected: (name: 'tournament' | 'play' | 'hand' | 'brain' | 'pgn') => void
197+
}) {
198+
return (
199+
<button
200+
onClick={() => setSelected(name)}
201+
className={`relative flex items-center justify-center py-0.5 ${selected === name ? 'bg-human-4/30' : 'bg-background-1/80 hover:bg-background-2'} transition duration-200`}
202+
>
203+
<div className="flex items-center justify-start gap-1">
204+
<p
205+
className={`text-sm transition duration-200 ${selected === name ? 'text-human-2' : 'text-primary'}`}
206+
>
207+
{label}
208+
</p>
209+
<i
210+
className={`material-symbols-outlined text-base transition duration-200 ${selected === name ? 'text-human-2/80' : 'text-primary/80'}`}
211+
>
212+
keyboard_arrow_down
213+
</i>
214+
</div>
215+
{selected === name && (
216+
<motion.div
217+
layoutId="underline"
218+
className="absolute -bottom-0.5 h-0.5 w-full bg-human-2/80"
219+
></motion.div>
220+
)}
221+
</button>
222+
)
223+
}

src/components/Analysis/Tournament.tsx

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ import {
77
CaretDownIcon,
88
} from 'src/components/Icons/icons'
99
import { AnalysisTournamentGame } from 'src/types'
10+
type Props = {
11+
id: string
12+
index: number
13+
currentId: string[] | null
14+
openIndex: number | null
15+
setOpenIndex: (index: number | null) => void
16+
loadingIndex: number | null
17+
setLoadingIndex: (index: number | null) => void
18+
openElement: React.RefObject<HTMLDivElement>
19+
selectedGameElement: React.RefObject<HTMLButtonElement>
20+
analysisTournamentList: Map<string, AnalysisTournamentGame[]>
21+
loadNewTournamentGame: (
22+
id: string[],
23+
setCurrentMove?: Dispatch<SetStateAction<number>>,
24+
) => Promise<void>
25+
setCurrentMove?: Dispatch<SetStateAction<number>>
26+
}
1027

1128
export const Tournament = ({
1229
id,
@@ -21,23 +38,7 @@ export const Tournament = ({
2138
analysisTournamentList,
2239
loadNewTournamentGame,
2340
setCurrentMove,
24-
}: {
25-
id: string
26-
index: number
27-
currentId: string[] | null
28-
openIndex: number | null
29-
setOpenIndex: (index: number | null) => void
30-
loadingIndex: number | null
31-
setLoadingIndex: (index: number | null) => void
32-
openElement: React.RefObject<HTMLDivElement>
33-
selectedGameElement: React.RefObject<HTMLButtonElement>
34-
analysisTournamentList: Map<string, AnalysisTournamentGame[]>
35-
loadNewTournamentGame: (
36-
id: string[],
37-
setCurrentMove: Dispatch<SetStateAction<number>>,
38-
) => Promise<void>
39-
setCurrentMove: Dispatch<SetStateAction<number>>
40-
}) => {
41+
}: Props) => {
4142
const games = analysisTournamentList.get(id)
4243
const [sectionId, title] = id.split('---')
4344
const opened = openIndex == index

src/components/Analysis/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from './PositionEvaluationContainer'
1212
export * from './VerticalEvaluationBar'
1313
export * from './MoveRecommendations'
1414
export * from './MovesByRating'
15+
export * from './ClientAnalysisGameList'

src/components/Board/ClientGameBoard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { Chess } from 'chess.ts'
33
import { defaults } from 'chessground/state'
44
import type { Key } from 'chessground/types'
55
import Chessground from '@react-chess/chessground'
6-
import type { DrawBrushes, DrawShape } from 'chessground/draw'
76
import { ClientBaseGame, Check, GameNode, Color } from 'src/types'
7+
import type { DrawBrushes, DrawShape } from 'chessground/draw'
88
import {
99
useMemo,
1010
Dispatch,
@@ -53,7 +53,7 @@ export const ClientGameBoard: React.FC<Props> = ({
5353
if (setCurrentMove) setCurrentMove([from, to])
5454
if (setCurrentSquare) setCurrentSquare(null)
5555

56-
const chess = new Chess(currentNode.fen) // Use currentNode.fen
56+
const chess = new Chess(currentNode.fen)
5757

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

src/components/Board/ClientMovesContainer.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
/* eslint-disable jsx-a11y/click-events-have-key-events */
33
import { Tooltip } from 'react-tooltip'
44
import { useContext, useMemo } from 'react'
5-
6-
import { CheckIcon } from '../Icons/icons'
7-
import { GameNode, AnalyzedGame, Termination, ClientBaseGame } from 'src/types'
85
import { ClientGameControllerContext, WindowSizeContext } from 'src/contexts'
6+
import { GameNode, AnalyzedGame, Termination, ClientBaseGame } from 'src/types'
97

108
interface Props {
119
game: ClientBaseGame | AnalyzedGame

src/pages/analysis/[...id].tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,11 @@ interface Props {
203203
id: string,
204204
pgn: string,
205205
setCurrentMove?: Dispatch<SetStateAction<number>>,
206-
currentMaiaModel?: string,
207206
) => Promise<void>
208207
getAndSetUserGames: (
209208
id: string,
210209
type: 'play' | 'hand' | 'brain',
211-
setCurrentMove: Dispatch<SetStateAction<number>>,
212-
currentMaiaModel: string,
210+
setCurrentMove?: Dispatch<SetStateAction<number>>,
213211
) => Promise<void>
214212
analyzedGame: AnalyzedGame
215213
initialIndex: number
@@ -469,7 +467,6 @@ const Analysis: React.FC<Props> = ({
469467
{screen.id === 'select' ? (
470468
<AnalysisGameList
471469
currentId={currentId}
472-
currentMaiaModel={currentMaiaModel}
473470
loadNewTournamentGame={getAndSetTournamentGame}
474471
loadNewLichessGames={getAndSetLichessGames}
475472
loadNewUserGames={getAndSetUserGames}

0 commit comments

Comments
 (0)