Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
06d59bd
feat: migrate play page to use tree structure
kevinjosethomas Jun 14, 2025
8dadd0f
feat: migrate h&b to use tree structure
kevinjosethomas Jun 14, 2025
08120de
feat: migrate train page to use new train controller
kevinjosethomas Jun 14, 2025
688da4a
feat: migrate turing to use tree data structure
kevinjosethomas Jun 14, 2025
8ff2bcb
feat: consolidate components + clean up training page
kevinjosethomas Jun 14, 2025
5dee7d7
feat: clean up board controller
kevinjosethomas Jun 14, 2025
1e94e9e
feat: modularize + clean up
kevinjosethomas Jun 16, 2025
281c022
feat: condense move container components + condense controllers
kevinjosethomas Jun 16, 2025
fef0ddd
chore: remove legacy components
kevinjosethomas Jun 16, 2025
dae5d07
chore: refactor components + clean up types
kevinjosethomas Jun 16, 2025
20321b6
feat: clean up play controller adding new moves
kevinjosethomas Jun 17, 2025
a231a8b
feat: migrate turing to use tree datastructure + clean up type incons…
kevinjosethomas Jun 17, 2025
a32281d
feat: remove legacy analysis page featureset
kevinjosethomas Jun 17, 2025
2c6ca3f
feat: cleanup analysis controllers + linter errors
kevinjosethomas Jun 17, 2025
45507d3
feat: clean up play page conventions
kevinjosethomas Jun 19, 2025
e16b396
feat: migrate train page to tree structure + handle all cases
kevinjosethomas Jun 19, 2025
80a0564
refactor: playcontroller use treecontroller
kevinjosethomas Jun 19, 2025
67c25e1
chore: fix build + lint errors
kevinjosethomas Jun 19, 2025
85fceab
feat: add first iteration of analysis in puzzle page
kevinjosethomas Jun 19, 2025
ff0d907
chore: clean up + modularize code
kevinjosethomas Jun 19, 2025
be75bee
fix: orientation bug + clean up code
kevinjosethomas Jun 19, 2025
f7f7a1e
feat: add download model modal blocker to train page
kevinjosethomas Jun 19, 2025
9914369
fix: build errors
kevinjosethomas Jun 19, 2025
983b5c4
docs: update feedback
kevinjosethomas Jun 19, 2025
49c4f3a
fix: remove redundant dependency
kevinjosethomas Jun 19, 2025
9d82879
Apply suggestions from cocdcdfde reviewf
kevinjosethomas Jun 19, 2025
b402f5d
fix: lint errors
kevinjosethomas Jun 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 0 additions & 301 deletions src/api/analysis/analysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
GameNode,
AnalyzedGame,
MaiaEvaluation,
LegacyAnalyzedGame,
PositionEvaluation,
StockfishEvaluation,
AnalysisTournamentGame,
Expand Down Expand Up @@ -113,306 +112,6 @@ export const getLichessGamePGN = async (id: string) => {
return res.text()
}

export const getLegacyAnalyzedTournamentGame = async (
gameId = ['FkgYSri1'],
) => {
const res = await fetch(
buildUrl(`analysis/analysis_list/${gameId.join('/')}`),
)

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

const data = await res.json()
const id = data['id']
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 stockfishEvaluations: MoveMap[] = data['stockfish_evals']

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,
stockfishEvaluations,
availableMoves,
gameType,
termination,
positionEvaluations,
} as any as LegacyAnalyzedGame
}

export const getLegacyAnalyzedLichessGame = async (
id: string,
pgn: string,
maia_model = 'maia_kdd_1500',
) => {
const res = await fetch(
buildUrl(
'analysis/analyze_user_game?' +
new URLSearchParams({
maia_model,
}),
),
{
method: 'POST',
body: pgn,
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,
pgn,
} as LegacyAnalyzedGame
}

export const getLegacyAnalyzedUserGame = 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 maiaPattern = /maia_kdd_1\d00/

if (blackPlayer.name && maiaPattern.test(blackPlayer.name)) {
blackPlayer.name = blackPlayer.name.replace('maia_kdd_', 'Maia ')
}

if (whitePlayer.name && maiaPattern.test(whitePlayer.name)) {
whitePlayer.name = whitePlayer.name.replace('maia_kdd_', 'Maia ')
}

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 LegacyAnalyzedGame
}

function convertMoveMapToStockfishEval(
moveMap: MoveMap,
turn: 'w' | 'b',
Expand Down
24 changes: 23 additions & 1 deletion src/api/train/train.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { MoveMap } from 'src/types'
import { Chess } from 'chess.ts'
import { MoveMap, GameTree } from 'src/types'
import { AvailableMoves, TrainingGame } from 'src/types/training'
import { buildUrl } from '../utils'

Expand Down Expand Up @@ -46,10 +47,30 @@ export const getTrainingGame = async () => {
lastMove,
movePlayed: move,
san,
uci: lastMove ? lastMove.join('') : undefined,
check,
}
})

// Build game tree from moves
Comment thread
kevinjosethomas marked this conversation as resolved.
if (moves.length === 0) {
throw new Error('Moves array is empty. Cannot initialize GameTree.')
}
const gameTree = new GameTree(moves[0].board)
let currentNode = gameTree.getRoot()

for (let i = 1; i < moves.length; i++) {
const move = moves[i]
if (move.uci && move.san) {
currentNode = gameTree.addMainMove(
currentNode,
move.board,
move.uci,
move.san,
)
}
}

const moveMap = data['target_move_map']

const stockfishEvaluation: MoveMap = {}
Expand Down Expand Up @@ -84,6 +105,7 @@ export const getTrainingGame = async () => {
whitePlayer,
blackPlayer,
moves,
tree: gameTree,
maiaEvaluation,
stockfishEvaluation,
gameType,
Expand Down
Loading