Skip to content

Commit 4ddc76e

Browse files
feat: add functionality to update completed drills with new moves and synchronize game state
1 parent 7887b0b commit 4ddc76e

1 file changed

Lines changed: 64 additions & 7 deletions

File tree

src/hooks/useOpeningDrillController/useOpeningDrillController.ts

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)