Skip to content

Commit 27717b5

Browse files
Merge pull request #9 from CSSLab/migrate-tree
Migrate to Tree-Based Game Structure (Maia2) Across Core Pages
2 parents ec26156 + b402f5d commit 27717b5

72 files changed

Lines changed: 3087 additions & 4354 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/api/analysis/analysis.ts

Lines changed: 0 additions & 301 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
GameNode,
77
AnalyzedGame,
88
MaiaEvaluation,
9-
LegacyAnalyzedGame,
109
PositionEvaluation,
1110
StockfishEvaluation,
1211
AnalysisTournamentGame,
@@ -113,306 +112,6 @@ export const getLichessGamePGN = async (id: string) => {
113112
return res.text()
114113
}
115114

116-
export const getLegacyAnalyzedTournamentGame = async (
117-
gameId = ['FkgYSri1'],
118-
) => {
119-
const res = await fetch(
120-
buildUrl(`analysis/analysis_list/${gameId.join('/')}`),
121-
)
122-
123-
if (res.status === 401) {
124-
throw new Error('Unauthorized')
125-
}
126-
127-
const data = await res.json()
128-
const id = data['id']
129-
const termination = {
130-
...data['termination'],
131-
condition: 'Normal',
132-
}
133-
134-
const gameType = 'blitz'
135-
const blackPlayer = data['black_player']
136-
const whitePlayer = data['white_player']
137-
138-
const maiaEvaluations: { [model: string]: MoveMap[] } = {}
139-
const stockfishEvaluations: MoveMap[] = data['stockfish_evals']
140-
141-
const positionEvaluations: { [model: string]: PositionEvaluation[] } = {}
142-
const availableMoves: AvailableMoves[] = []
143-
144-
for (const model of data['maia_versions']) {
145-
maiaEvaluations[model] = data['maia_evals'][model]
146-
positionEvaluations[model] = Object.keys(data['maia_evals'][model]).map(
147-
() => ({
148-
trickiness: 1,
149-
performance: 1,
150-
}),
151-
)
152-
}
153-
154-
for (const position of data['move_maps']) {
155-
const moves: AvailableMoves = {}
156-
for (const move of position) {
157-
const fromTo = move.move.join('')
158-
const san = move['move_san']
159-
const { check, fen } = move
160-
161-
moves[fromTo] = {
162-
board: fen,
163-
check,
164-
san,
165-
lastMove: move.move,
166-
}
167-
}
168-
availableMoves.push(moves)
169-
}
170-
171-
const gameStates = data['game_states']
172-
173-
const moves = gameStates.map((gameState: any) => {
174-
const {
175-
last_move: lastMove,
176-
fen,
177-
check,
178-
last_move_san: san,
179-
evaluations: maia_values,
180-
} = gameState
181-
182-
return {
183-
board: fen,
184-
lastMove,
185-
san,
186-
check,
187-
maia_values,
188-
}
189-
})
190-
191-
return {
192-
id,
193-
blackPlayer,
194-
whitePlayer,
195-
moves,
196-
maiaEvaluations,
197-
stockfishEvaluations,
198-
availableMoves,
199-
gameType,
200-
termination,
201-
positionEvaluations,
202-
} as any as LegacyAnalyzedGame
203-
}
204-
205-
export const getLegacyAnalyzedLichessGame = async (
206-
id: string,
207-
pgn: string,
208-
maia_model = 'maia_kdd_1500',
209-
) => {
210-
const res = await fetch(
211-
buildUrl(
212-
'analysis/analyze_user_game?' +
213-
new URLSearchParams({
214-
maia_model,
215-
}),
216-
),
217-
{
218-
method: 'POST',
219-
body: pgn,
220-
headers: {
221-
'Content-Type': 'text/plain',
222-
},
223-
},
224-
)
225-
226-
if (res.status === 401) {
227-
throw new Error('Unauthorized')
228-
}
229-
230-
const data = await res.json()
231-
232-
const termination = {
233-
...data['termination'],
234-
condition: 'Normal',
235-
}
236-
237-
const gameType = 'blitz'
238-
const blackPlayer = data['black_player']
239-
const whitePlayer = data['white_player']
240-
241-
const maiaEvaluations: { [model: string]: MoveMap[] } = {}
242-
const positionEvaluations: { [model: string]: PositionEvaluation[] } = {}
243-
const availableMoves: AvailableMoves[] = []
244-
245-
for (const model of data['maia_versions']) {
246-
maiaEvaluations[model] = data['maia_evals'][model]
247-
positionEvaluations[model] = Object.keys(data['maia_evals'][model]).map(
248-
() => ({
249-
trickiness: 1,
250-
performance: 1,
251-
}),
252-
)
253-
}
254-
255-
for (const position of data['move_maps']) {
256-
const moves: AvailableMoves = {}
257-
for (const move of position) {
258-
const fromTo = move.move.join('')
259-
const san = move['move_san']
260-
const { check, fen } = move
261-
262-
moves[fromTo] = {
263-
board: fen,
264-
check,
265-
san,
266-
lastMove: move.move,
267-
}
268-
}
269-
availableMoves.push(moves)
270-
}
271-
272-
const gameStates = data['game_states']
273-
274-
const moves = gameStates.map((gameState: any) => {
275-
const {
276-
last_move: lastMove,
277-
fen,
278-
check,
279-
last_move_san: san,
280-
evaluations: maia_values,
281-
} = gameState
282-
283-
return {
284-
board: fen,
285-
lastMove,
286-
san,
287-
check,
288-
maia_values,
289-
}
290-
})
291-
292-
return {
293-
id,
294-
blackPlayer,
295-
whitePlayer,
296-
moves,
297-
maiaEvaluations,
298-
availableMoves,
299-
gameType,
300-
termination,
301-
positionEvaluations,
302-
pgn,
303-
} as LegacyAnalyzedGame
304-
}
305-
306-
export const getLegacyAnalyzedUserGame = async (
307-
id: string,
308-
game_type: 'play' | 'hand' | 'brain',
309-
maia_model = 'maia_kdd_1500',
310-
) => {
311-
const res = await fetch(
312-
buildUrl(
313-
`analysis/user/analyze_user_maia_game/${id}?` +
314-
new URLSearchParams({
315-
game_type,
316-
maia_model,
317-
}),
318-
),
319-
{
320-
method: 'GET',
321-
headers: {
322-
'Content-Type': 'text/plain',
323-
},
324-
},
325-
)
326-
327-
if (res.status === 401) {
328-
throw new Error('Unauthorized')
329-
}
330-
331-
const data = await res.json()
332-
333-
const termination = {
334-
...data['termination'],
335-
condition: 'Normal',
336-
}
337-
338-
const gameType = 'blitz'
339-
const blackPlayer = data['black_player']
340-
const whitePlayer = data['white_player']
341-
342-
const maiaPattern = /maia_kdd_1\d00/
343-
344-
if (blackPlayer.name && maiaPattern.test(blackPlayer.name)) {
345-
blackPlayer.name = blackPlayer.name.replace('maia_kdd_', 'Maia ')
346-
}
347-
348-
if (whitePlayer.name && maiaPattern.test(whitePlayer.name)) {
349-
whitePlayer.name = whitePlayer.name.replace('maia_kdd_', 'Maia ')
350-
}
351-
352-
const maiaEvaluations: { [model: string]: MoveMap[] } = {}
353-
const positionEvaluations: { [model: string]: PositionEvaluation[] } = {}
354-
const availableMoves: AvailableMoves[] = []
355-
356-
for (const model of data['maia_versions']) {
357-
maiaEvaluations[model] = data['maia_evals'][model]
358-
positionEvaluations[model] = Object.keys(data['maia_evals'][model]).map(
359-
() => ({
360-
trickiness: 1,
361-
performance: 1,
362-
}),
363-
)
364-
}
365-
366-
for (const position of data['move_maps']) {
367-
const moves: AvailableMoves = {}
368-
for (const move of position) {
369-
const fromTo = move.move.join('')
370-
const san = move['move_san']
371-
const { check, fen } = move
372-
373-
moves[fromTo] = {
374-
board: fen,
375-
check,
376-
san,
377-
lastMove: move.move,
378-
}
379-
}
380-
availableMoves.push(moves)
381-
}
382-
383-
const gameStates = data['game_states']
384-
385-
const moves = gameStates.map((gameState: any) => {
386-
const {
387-
last_move: lastMove,
388-
fen,
389-
check,
390-
last_move_san: san,
391-
evaluations: maia_values,
392-
} = gameState
393-
394-
return {
395-
board: fen,
396-
lastMove,
397-
san,
398-
check,
399-
maia_values,
400-
}
401-
})
402-
403-
return {
404-
id,
405-
blackPlayer,
406-
whitePlayer,
407-
moves,
408-
maiaEvaluations,
409-
availableMoves,
410-
gameType,
411-
termination,
412-
positionEvaluations,
413-
} as LegacyAnalyzedGame
414-
}
415-
416115
function convertMoveMapToStockfishEval(
417116
moveMap: MoveMap,
418117
turn: 'w' | 'b',

src/api/train/train.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
import { MoveMap } from 'src/types'
2+
import { Chess } from 'chess.ts'
3+
import { MoveMap, GameTree } from 'src/types'
34
import { AvailableMoves, TrainingGame } from 'src/types/training'
45
import { buildUrl } from '../utils'
56

@@ -46,10 +47,30 @@ export const getTrainingGame = async () => {
4647
lastMove,
4748
movePlayed: move,
4849
san,
50+
uci: lastMove ? lastMove.join('') : undefined,
4951
check,
5052
}
5153
})
5254

55+
// Build game tree from moves
56+
if (moves.length === 0) {
57+
throw new Error('Moves array is empty. Cannot initialize GameTree.')
58+
}
59+
const gameTree = new GameTree(moves[0].board)
60+
let currentNode = gameTree.getRoot()
61+
62+
for (let i = 1; i < moves.length; i++) {
63+
const move = moves[i]
64+
if (move.uci && move.san) {
65+
currentNode = gameTree.addMainMove(
66+
currentNode,
67+
move.board,
68+
move.uci,
69+
move.san,
70+
)
71+
}
72+
}
73+
5374
const moveMap = data['target_move_map']
5475

5576
const stockfishEvaluation: MoveMap = {}
@@ -84,6 +105,7 @@ export const getTrainingGame = async () => {
84105
whitePlayer,
85106
blackPlayer,
86107
moves,
108+
tree: gameTree,
87109
maiaEvaluation,
88110
stockfishEvaluation,
89111
gameType,

0 commit comments

Comments
 (0)