feat: improve opening trainer flow and add deviation dialog
- Add tutor message guardrail to prevent rapid-fire messages - Track last message by move index - Wait for both player and opponent moves before speaking - Speak immediately when player deviates from theory - Add deviation dialog with three options: - Continue Playing (Start Game) - transitions to game mode - Undo & Return to Opening - returns to theory - Explore This Variation - continues off-book practice - Implement smooth game mode transition: - Pass opening context from trainer to game - Tutor welcomes player with context about their study - Computer makes first move if needed in starting position - Fix generate-test-fixtures script: - Add safety check to prevent overwriting real data - Restore full opening database (12,379 openings) - Rebuild move index (12,377 sequences) - Add clear warnings about test fixtures - Update ChessGame to accept openingContext prop - Update Tutor to display contextual greeting in game mode 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,13 @@ export default function Home() {
|
||||
initialPersonality: Personality;
|
||||
initialColor: 'white' | 'black';
|
||||
initialStockfishDepth?: number;
|
||||
openingContext?: {
|
||||
openingName: string;
|
||||
openingEco: string;
|
||||
movesCompleted: number;
|
||||
wikipediaSummary?: string;
|
||||
contextMessage: string;
|
||||
};
|
||||
} | null>(null);
|
||||
|
||||
const [savedGames, setSavedGames] = useState<SavedGame[]>([]);
|
||||
@@ -48,18 +55,31 @@ export default function Home() {
|
||||
|
||||
const personality = PERSONALITIES.find(p => p.id === pendingGame.personalityId) || PERSONALITIES[0];
|
||||
|
||||
// Check for opening context (from opening trainer)
|
||||
const openingContextRaw = localStorage.getItem("chess_tutor_opening_context");
|
||||
let openingContext;
|
||||
if (openingContextRaw) {
|
||||
try {
|
||||
openingContext = JSON.parse(openingContextRaw);
|
||||
} catch (err) {
|
||||
console.error("Failed to parse opening context", err);
|
||||
}
|
||||
}
|
||||
|
||||
setGameProps({
|
||||
gameId: crypto.randomUUID ? crypto.randomUUID() : `game-${Date.now()}`,
|
||||
initialFen: pendingGame.fen,
|
||||
initialPersonality: personality,
|
||||
initialColor: pendingGame.color,
|
||||
initialStockfishDepth: pendingGame.stockfishDepth,
|
||||
openingContext,
|
||||
});
|
||||
setView('game');
|
||||
} catch (err) {
|
||||
console.error("Failed to load pending game", err);
|
||||
} finally {
|
||||
localStorage.removeItem("chess_tutor_pending_game");
|
||||
localStorage.removeItem("chess_tutor_opening_context");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +147,7 @@ export default function Home() {
|
||||
initialPersonality={gameProps.initialPersonality}
|
||||
initialColor={gameProps.initialColor}
|
||||
initialStockfishDepth={gameProps.initialStockfishDepth}
|
||||
openingContext={gameProps.openingContext}
|
||||
onBack={handleBackToMenu}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user