@@ -375,7 +375,7 @@ const CustomTooltip: React.FC<{
375375 : 'text-yellow-400'
376376 } `}
377377 >
378- { data . classification } { data . isPlayerMove ? '(You)' : '(Maia)' }
378+ { data . classification }
379379 </ p >
380380 ) }
381381 </ div >
@@ -390,13 +390,20 @@ const EvaluationChart: React.FC<{
390390 onHoverMove ?: ( moveIndex : number ) => void
391391 playerColor : 'white' | 'black'
392392 drill : DrillPerformanceData [ 'drill' ]
393+ gameNodesMap : Map < string , GameNode >
394+ getChartClassification : (
395+ analysis : MoveAnalysis ,
396+ gameNodesMap : Map < string , GameNode > ,
397+ ) => 'excellent' | 'good' | 'inaccuracy' | 'mistake' | 'blunder'
393398} > = ( {
394399 evaluationChart,
395400 moveAnalyses,
396401 currentMoveIndex = - 1 ,
397402 onHoverMove,
398403 playerColor,
399404 drill,
405+ gameNodesMap,
406+ getChartClassification,
400407} ) => {
401408 if ( evaluationChart . length === 0 ) {
402409 return (
@@ -406,11 +413,6 @@ const EvaluationChart: React.FC<{
406413 )
407414 }
408415
409- // Helper function to get move classification (use analysis data for compatibility)
410- const getChartClassification = ( analysis : MoveAnalysis ) : string => {
411- return analysis . classification || ''
412- }
413-
414416 // Generate move numbers for chartData - create pairs first then extract chart data
415417 const movePairs = ( ( ) => {
416418 const pairs : Array < {
@@ -486,7 +488,7 @@ const EvaluationChart: React.FC<{
486488 }
487489
488490 const dynamicClassification = moveAnalysis
489- ? getChartClassification ( moveAnalysis )
491+ ? getChartClassification ( moveAnalysis , gameNodesMap )
490492 : ''
491493
492494 // Get Stockfish depth by finding the corresponding game node
@@ -658,6 +660,11 @@ const DesktopLayout: React.FC<{
658660 gameTree : GameTree
659661 playerMoveCount : number
660662 treeController : ReturnType < typeof useTreeController >
663+ gameNodesMap : Map < string , GameNode >
664+ getChartClassification : (
665+ analysis : MoveAnalysis ,
666+ gameNodesMap : Map < string , GameNode > ,
667+ ) => 'excellent' | 'good' | 'inaccuracy' | 'mistake' | 'blunder'
661668} > = ( {
662669 drill,
663670 filteredEvaluationChart,
@@ -669,6 +676,8 @@ const DesktopLayout: React.FC<{
669676 gameTree,
670677 playerMoveCount,
671678 treeController,
679+ gameNodesMap,
680+ getChartClassification,
672681} ) => (
673682 < div className = "relative flex h-[90vh] max-h-[800px] w-[95vw] max-w-[1200px] flex-col overflow-hidden rounded-lg bg-background-1 shadow-2xl" >
674683 { /* Header */ }
@@ -753,6 +762,8 @@ const DesktopLayout: React.FC<{
753762 } }
754763 playerColor = { drill . selection . playerColor }
755764 drill = { drill }
765+ gameNodesMap = { gameNodesMap }
766+ getChartClassification = { getChartClassification }
756767 />
757768
758769 { /* Critical Decisions Section */ }
@@ -765,15 +776,44 @@ const DesktopLayout: React.FC<{
765776 </ div >
766777 < div className = "flex flex-col gap-2 px-3 pb-3" >
767778 { ( ( ) => {
768- // Get critical moves (blunders, excellent moves, inaccuracies)
769- const criticalMoves = performanceData . moveAnalyses
770- . filter ( ( move ) => move . isPlayerMove )
771- . filter (
772- ( move ) =>
773- move . classification === 'blunder' ||
774- move . classification === 'excellent' ||
775- move . classification === 'inaccuracy' ,
776- )
779+ // Get critical moves directly from game tree (like MovesContainer)
780+ const mainLineNodes = gameTree . getMainLine ( ) . slice ( 1 ) // Skip root
781+ const criticalMoves = mainLineNodes
782+ . filter ( ( node , index ) => {
783+ // Determine if this is a player move
784+ const chess = new Chess ( node . fen )
785+ const isPlayerMove =
786+ drill . selection . playerColor === 'white'
787+ ? chess . turn ( ) === 'b' // If black to move, white just played
788+ : chess . turn ( ) === 'w' // If white to move, black just played
789+ return isPlayerMove
790+ } )
791+ . filter ( ( node ) => {
792+ // Filter for critical moves (same logic as MovesContainer)
793+ return node . blunder || node . inaccuracy || node . excellentMove
794+ } )
795+ . map ( ( node ) => {
796+ // Convert to MoveAnalysis format for display
797+ let classification : 'blunder' | 'inaccuracy' | 'excellent' =
798+ 'excellent'
799+ if ( node . blunder ) {
800+ classification = 'blunder'
801+ } else if ( node . inaccuracy ) {
802+ classification = 'inaccuracy'
803+ }
804+
805+ return {
806+ move : node . move || '' ,
807+ san : node . san || '' ,
808+ fen : node . fen ,
809+ fenBeforeMove : node . parent ?. fen ,
810+ moveNumber : node . moveNumber ,
811+ isPlayerMove : true ,
812+ evaluation : 0 , // Will be filled if needed
813+ classification,
814+ evaluationLoss : 0 ,
815+ }
816+ } )
777817 . sort ( ( a , b ) => {
778818 // Sort by move number (chronological order)
779819 return a . moveNumber - b . moveNumber
@@ -919,6 +959,11 @@ const MobileLayout: React.FC<{
919959 gameTree : GameTree
920960 playerMoveCount : number
921961 treeController : ReturnType < typeof useTreeController >
962+ gameNodesMap : Map < string , GameNode >
963+ getChartClassification : (
964+ analysis : MoveAnalysis ,
965+ gameNodesMap : Map < string , GameNode > ,
966+ ) => 'excellent' | 'good' | 'inaccuracy' | 'mistake' | 'blunder'
922967} > = ( {
923968 drill,
924969 filteredEvaluationChart,
@@ -932,6 +977,8 @@ const MobileLayout: React.FC<{
932977 gameTree,
933978 playerMoveCount,
934979 treeController,
980+ gameNodesMap,
981+ getChartClassification,
935982} ) => (
936983 < div className = "relative flex h-[95vh] w-[95vw] flex-col overflow-hidden rounded-lg bg-background-1 shadow-2xl" >
937984 { /* Header */ }
@@ -1046,6 +1093,8 @@ const MobileLayout: React.FC<{
10461093 } }
10471094 playerColor = { drill . selection . playerColor }
10481095 drill = { drill }
1096+ gameNodesMap = { gameNodesMap }
1097+ getChartClassification = { getChartClassification }
10491098 />
10501099 </ div >
10511100 ) }
@@ -1156,6 +1205,43 @@ export const DrillPerformanceModal: React.FC<Props> = ({
11561205 drill . selection . playerColor ,
11571206 )
11581207
1208+ // Create a map of FEN -> GameNode for consistent classification
1209+ const gameNodesMap = useMemo ( ( ) => {
1210+ const map = new Map < string , GameNode > ( )
1211+ const collectNodes = ( node : GameNode ) : void => {
1212+ map . set ( node . fen , node )
1213+ node . children . forEach ( collectNodes )
1214+ }
1215+ collectNodes ( gameTree . getRoot ( ) )
1216+ return map
1217+ } , [ gameTree ] )
1218+
1219+ // Helper function to get move classification from GameNode (same as MovesContainer)
1220+ const getChartClassification = useCallback (
1221+ (
1222+ analysis : MoveAnalysis ,
1223+ gameNodesMap : Map < string , GameNode > ,
1224+ ) : 'excellent' | 'good' | 'inaccuracy' | 'mistake' | 'blunder' => {
1225+ // Get the GameNode for the position after the move
1226+ const moveNode = gameNodesMap . get ( analysis . fen )
1227+ if ( ! moveNode ) {
1228+ return analysis . classification || 'good'
1229+ }
1230+
1231+ // Use the same logic as MovesContainer
1232+ if ( moveNode . blunder ) {
1233+ return 'blunder'
1234+ } else if ( moveNode . inaccuracy ) {
1235+ return 'inaccuracy'
1236+ } else if ( moveNode . excellentMove ) {
1237+ return 'excellent'
1238+ }
1239+
1240+ return 'good'
1241+ } ,
1242+ [ ] ,
1243+ )
1244+
11591245 // Count player moves from move analyses for display purposes
11601246 const playerMoveCount = useMemo ( ( ) => {
11611247 return moveAnalyses . filter ( ( move ) => move . isPlayerMove ) . length
@@ -1196,6 +1282,8 @@ export const DrillPerformanceModal: React.FC<Props> = ({
11961282 gameTree = { gameTree }
11971283 playerMoveCount = { playerMoveCount }
11981284 treeController = { treeController }
1285+ gameNodesMap = { gameNodesMap }
1286+ getChartClassification = { getChartClassification }
11991287 />
12001288 ) : (
12011289 < DesktopLayout
@@ -1209,6 +1297,8 @@ export const DrillPerformanceModal: React.FC<Props> = ({
12091297 gameTree = { gameTree }
12101298 playerMoveCount = { playerMoveCount }
12111299 treeController = { treeController }
1300+ gameNodesMap = { gameNodesMap }
1301+ getChartClassification = { getChartClassification }
12121302 />
12131303 ) }
12141304 </ ModalContainer >
0 commit comments