@@ -466,17 +466,19 @@ export const useOpeningDrillController = (
466466 playerMoveCount : completedDrill . totalMoves ,
467467 }
468468
469+ // Important: Set the loaded game state first before setting controller position
470+ // This ensures the useEffect hooks see the correct moves.length > 0 state
469471 setCurrentDrillGame ( loadedGame )
470472 setAnalysisEnabled ( true ) // Auto-enable analysis when loading a completed drill
471473 setContinueAnalyzingMode ( true ) // Allow moves beyond target count
472- setWaitingForMaiaResponse ( false )
474+ setWaitingForMaiaResponse ( false ) // Ensure we're not waiting for Maia
473475
474- // Set the controller to the final position after a brief delay
476+ // Set the controller to the final position after ensuring game state is set
475477 setTimeout ( ( ) => {
476478 if ( finalNode ) {
477479 controller . setCurrentNode ( finalNode )
478480 }
479- } , 100 )
481+ } , 50 ) // Shorter delay to ensure state is synchronized
480482 } ,
481483 [ controller , currentDrillGame ] ,
482484 )
@@ -550,6 +552,41 @@ export const useOpeningDrillController = (
550552 }
551553 } , [ completedDrills , configuration . drillCount ] )
552554
555+ // Helper function to update a completed drill with new moves
556+ const updateCompletedDrill = useCallback (
557+ ( updatedGame : OpeningDrillGame ) => {
558+ // Check if this is a loaded completed drill (ID ends with '-replay')
559+ if ( updatedGame . id . endsWith ( '-replay' ) ) {
560+ const originalId = updatedGame . id . replace ( '-replay' , '' )
561+
562+ setCompletedDrills ( ( prev ) =>
563+ prev . map ( ( completedDrill ) => {
564+ if ( completedDrill . selection . id === originalId ) {
565+ // Update the completed drill with new moves and final position
566+ const finalNode = controller . currentNode
567+ return {
568+ ...completedDrill ,
569+ allMoves : updatedGame . moves ,
570+ playerMoves : updatedGame . moves . filter ( ( _ , index ) => {
571+ // Only count player moves (assuming alternating turns)
572+ const isPlayerMove =
573+ completedDrill . selection . playerColor === 'white'
574+ ? index % 2 === 0
575+ : index % 2 === 1
576+ return isPlayerMove
577+ } ) ,
578+ totalMoves : updatedGame . playerMoveCount ,
579+ finalNode : finalNode || completedDrill . finalNode ,
580+ }
581+ }
582+ return completedDrill
583+ } ) ,
584+ )
585+ }
586+ } ,
587+ [ controller ] ,
588+ )
589+
553590 // Make a move for the player - enhanced to support variations and completion checking
554591 const makePlayerMove = useCallback (
555592 async ( moveUci : string , fromNode ?: GameNode ) => {
@@ -639,6 +676,9 @@ export const useOpeningDrillController = (
639676
640677 setCurrentDrillGame ( updatedGame )
641678
679+ // Update completed drill if this is a loaded completed drill
680+ updateCompletedDrill ( updatedGame )
681+
642682 // Set flag to indicate we're waiting for Maia's response (after player move, it becomes Maia's turn)
643683 setWaitingForMaiaResponse ( true )
644684
@@ -665,6 +705,7 @@ export const useOpeningDrillController = (
665705 currentDrill ,
666706 completeDrill ,
667707 continueAnalyzingMode ,
708+ updateCompletedDrill ,
668709 ] ,
669710 )
670711
@@ -758,6 +799,9 @@ export const useOpeningDrillController = (
758799
759800 setCurrentDrillGame ( updatedGame )
760801
802+ // Update completed drill if this is a loaded completed drill
803+ updateCompletedDrill ( updatedGame )
804+
761805 // Clear the waiting flag since Maia has responded
762806 setWaitingForMaiaResponse ( false )
763807 }
@@ -766,7 +810,13 @@ export const useOpeningDrillController = (
766810 console . error ( 'Error making Maia move:' , error )
767811 }
768812 } ,
769- [ currentDrillGame , controller , currentDrill , playSound ] ,
813+ [
814+ currentDrillGame ,
815+ controller ,
816+ currentDrill ,
817+ playSound ,
818+ updateCompletedDrill ,
819+ ] ,
770820 )
771821
772822 // Store makeMaiaMove in a ref to avoid circular dependencies
@@ -779,18 +829,25 @@ export const useOpeningDrillController = (
779829 currentDrillGame &&
780830 controller . currentNode &&
781831 ! isPlayerTurn &&
782- currentDrillGame . moves . length === 0 &&
832+ currentDrillGame . moves . length === 0 && // Only for fresh drills, not loaded ones
783833 currentDrillGame . openingEndNode &&
784834 controller . currentNode === currentDrillGame . openingEndNode &&
785- ! isDrillComplete
835+ ! isDrillComplete &&
836+ ! continueAnalyzingMode // Don't trigger when in analysis mode (like when loading completed drills)
786837 ) {
787838 // It's Maia's turn to move first from the opening position
788839 setWaitingForMaiaResponse ( true )
789840 setTimeout ( ( ) => {
790841 makeMaiaMoveRef . current ( controller . currentNode )
791842 } , 1000 )
792843 }
793- } , [ currentDrillGame , controller . currentNode , isPlayerTurn , isDrillComplete ] )
844+ } , [
845+ currentDrillGame ,
846+ controller . currentNode ,
847+ isPlayerTurn ,
848+ isDrillComplete ,
849+ continueAnalyzingMode ,
850+ ] )
794851
795852 // Handle Maia's response after player moves - only when we're actually waiting for a response
796853 useEffect ( ( ) => {
0 commit comments