@@ -16,6 +16,15 @@ import {
16
16
useLocalStorage ,
17
17
} from '..'
18
18
19
+ const COLORS = {
20
+ good : [ '#238b45' , '#41ab5d' , '#74c476' , '#a1d99b' , '#c7e9c0' ] ,
21
+ ok : [ '#ec7014' , '#feb24c' , '#fed976' , '#ffeda0' , '#ffffcc' ] . reverse ( ) ,
22
+ blunder : [ '#cb181d' , '#ef3b2c' , '#fb6a4a' , '#fc9272' , '#fcbba1' ] . reverse ( ) ,
23
+ }
24
+
25
+ // Constants for move classification based on winrate
26
+ const BLUNDER_THRESHOLD = 0.1 // 10% winrate drop
27
+ const INACCURACY_THRESHOLD = 0.05 // 5% winrate drop
19
28
const MAIA_MODELS = [
20
29
'maia_kdd_1100' ,
21
30
'maia_kdd_1200' ,
@@ -28,22 +37,6 @@ const MAIA_MODELS = [
28
37
'maia_kdd_1900' ,
29
38
]
30
39
31
- // const MAIA_COLORS = ['#fe7f6d', '#f08a4c', '#ecaa4f', '#eccd4f']
32
- const STOCKFISH_COLORS = [
33
- '#1a9850' ,
34
- '#91cf60' ,
35
- '#d9ef8b' ,
36
- '#fee08b' ,
37
- '#fc8d59' ,
38
- '#d73027' ,
39
- ]
40
-
41
- const COLORS = {
42
- good : [ '#238b45' , '#41ab5d' , '#74c476' , '#a1d99b' , '#c7e9c0' ] ,
43
- ok : [ '#ec7014' , '#feb24c' , '#fed976' , '#ffeda0' , '#ffffcc' ] . reverse ( ) ,
44
- blunder : [ '#cb181d' , '#ef3b2c' , '#fb6a4a' , '#fc9272' , '#fcbba1' ] . reverse ( ) ,
45
- }
46
-
47
40
export const useAnalysisController = ( game : AnalyzedGame ) => {
48
41
const controller = useAnalysisGameController (
49
42
game . tree as GameTree ,
@@ -67,7 +60,6 @@ export const useAnalysisController = (game: AnalyzedGame) => {
67
60
MAIA_MODELS [ 0 ] ,
68
61
)
69
62
70
- // Ensure the selected model is valid for the current context
71
63
useEffect ( ( ) => {
72
64
if ( ! MAIA_MODELS . includes ( currentMaiaModel ) ) {
73
65
setCurrentMaiaModel ( MAIA_MODELS [ 0 ] )
@@ -268,20 +260,40 @@ export const useAnalysisController = (game: AnalyzedGame) => {
268
260
okMoves : { probability : 0 , moves : [ ] } ,
269
261
goodMoves : { probability : 0 , moves : [ ] } ,
270
262
}
271
- for ( const [ move , prob ] of Object . entries ( maia . policy ) ) {
272
- const loss = stockfish . cp_relative_vec [ move ]
273
- if ( loss === undefined ) continue
274
- const probability = prob * 100
275
-
276
- if ( loss >= - 50 ) {
277
- goodMoveProbability += probability
278
- goodMoveChanceInfo . push ( { move, probability } )
279
- } else if ( loss >= - 150 ) {
280
- okMoveProbability += probability
281
- okMoveChanceInfo . push ( { move, probability } )
282
- } else {
283
- blunderMoveProbability += probability
284
- blunderMoveChanceInfo . push ( { move, probability } )
263
+
264
+ if ( stockfish . winrate_loss_vec ) {
265
+ for ( const [ move , prob ] of Object . entries ( maia . policy ) ) {
266
+ const winrate_loss = stockfish . winrate_loss_vec [ move ]
267
+ if ( winrate_loss === undefined ) continue
268
+ const probability = prob * 100
269
+
270
+ if ( winrate_loss >= - INACCURACY_THRESHOLD ) {
271
+ goodMoveProbability += probability
272
+ goodMoveChanceInfo . push ( { move, probability } )
273
+ } else if ( winrate_loss >= - BLUNDER_THRESHOLD ) {
274
+ okMoveProbability += probability
275
+ okMoveChanceInfo . push ( { move, probability } )
276
+ } else {
277
+ blunderMoveProbability += probability
278
+ blunderMoveChanceInfo . push ( { move, probability } )
279
+ }
280
+ }
281
+ } else {
282
+ for ( const [ move , prob ] of Object . entries ( maia . policy ) ) {
283
+ const loss = stockfish . cp_relative_vec [ move ]
284
+ if ( loss === undefined ) continue
285
+ const probability = prob * 100
286
+
287
+ if ( loss >= - 50 ) {
288
+ goodMoveProbability += probability
289
+ goodMoveChanceInfo . push ( { move, probability } )
290
+ } else if ( loss >= - 150 ) {
291
+ okMoveProbability += probability
292
+ okMoveChanceInfo . push ( { move, probability } )
293
+ } else {
294
+ blunderMoveProbability += probability
295
+ blunderMoveChanceInfo . push ( { move, probability } )
296
+ }
285
297
}
286
298
}
287
299
@@ -350,10 +362,21 @@ export const useAnalysisController = (game: AnalyzedGame) => {
350
362
351
363
const moveRecommendations = useMemo ( ( ) => {
352
364
if ( ! moveEvaluation ) return { }
365
+
366
+ const isBlackTurn = controller . currentNode ?. turn === 'b'
367
+
353
368
const recommendations : {
354
369
maia ?: { move : string ; prob : number } [ ]
355
- stockfish ?: { move : string ; cp : number } [ ]
356
- } = { }
370
+ stockfish ?: {
371
+ move : string
372
+ cp : number
373
+ winrate ?: number
374
+ winrate_loss ?: number
375
+ } [ ]
376
+ isBlackTurn ?: boolean
377
+ } = {
378
+ isBlackTurn,
379
+ }
357
380
358
381
if ( moveEvaluation ?. maia ) {
359
382
const policy = moveEvaluation . maia . policy
@@ -367,16 +390,21 @@ export const useAnalysisController = (game: AnalyzedGame) => {
367
390
368
391
if ( moveEvaluation ?. stockfish ) {
369
392
const cp_vec = moveEvaluation . stockfish . cp_vec
393
+ const winrate_vec = moveEvaluation . stockfish . winrate_vec || { }
394
+ const winrate_loss_vec = moveEvaluation . stockfish . winrate_loss_vec || { }
395
+
370
396
const stockfish = Object . entries ( cp_vec ) . map ( ( [ move , cp ] ) => ( {
371
397
move,
372
398
cp,
399
+ winrate : winrate_vec [ move ] || 0 ,
400
+ winrate_loss : winrate_loss_vec [ move ] || 0 ,
373
401
} ) )
374
402
375
403
recommendations . stockfish = stockfish
376
404
}
377
405
378
406
return recommendations
379
- } , [ moveEvaluation ] )
407
+ } , [ moveEvaluation , controller . currentNode ] )
380
408
381
409
const moveMap = useMemo ( ( ) => {
382
410
if ( ! moveEvaluation ?. maia || ! moveEvaluation ?. stockfish ) {
@@ -387,8 +415,13 @@ export const useAnalysisController = (game: AnalyzedGame) => {
387
415
Object . entries ( moveEvaluation . maia . policy ) . slice ( 0 , 3 ) ,
388
416
)
389
417
418
+ // Get the Stockfish moves in their sorted order (best to worst for the current player)
390
419
const stockfishMoves = Object . entries ( moveEvaluation . stockfish . cp_vec )
420
+
421
+ // Top moves are the first 3 in the sorted order
391
422
const topStockfish = Object . fromEntries ( stockfishMoves . slice ( 0 , 3 ) )
423
+
424
+ // Worst moves are the last 2 in the sorted order
392
425
const worstStockfish = Object . fromEntries ( stockfishMoves . slice ( - 2 ) )
393
426
394
427
const moves = Array . from (
0 commit comments