react-chess-replay-trainer 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -32,6 +32,8 @@ export interface ReplayTrainerState {
|
|
|
32
32
|
correctMoveSquare: string | null;
|
|
33
33
|
/** FEN shown on the board (includes a pending correct-move ply). */
|
|
34
34
|
displayFen: string;
|
|
35
|
+
/** UCI of the move that produced the current board position. */
|
|
36
|
+
lastMoveUci: string | null;
|
|
35
37
|
canPrev: boolean;
|
|
36
38
|
canNext: boolean;
|
|
37
39
|
goFirst: () => void;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
|
3
|
-
import { useCorrectMoveFeedback, createExpectedMoveDropHandler, fenAfterUci, ThemeProvider, ChessboardDnDProvider, HighlightChessboard, PlyNavigation, AnalysisErrorBoundary, AnalysisBoard } from 'react-chess-core';
|
|
3
|
+
import { useCorrectMoveFeedback, lastMoveUciAtPly, createExpectedMoveDropHandler, fenAfterUci, ThemeProvider, ChessboardDnDProvider, HighlightChessboard, PlyNavigation, AnalysisErrorBoundary, AnalysisBoard } from 'react-chess-core';
|
|
4
4
|
export { AnalysisBoard, AnalysisBoardCore, AnalysisErrorBoundary, DEFAULT_ANALYSIS_LAYOUT, DefaultPlyNavigation, PlyNavigation, MISS_MOVE_ANIMATION_MS as REPLAY_MISS_MOVE_ANIMATION_MS, MISS_REFUTATION_MAX_WAIT_MS as REPLAY_MISS_REFUTATION_MAX_WAIT_MS, MISS_REFUTATION_PAUSE_MS as REPLAY_MISS_REFUTATION_PAUSE_MS, MISS_WRONG_PAUSE_MS as REPLAY_MISS_WRONG_PAUSE_MS, REFUTATION_EVAL_GAP_CP as REPLAY_REFUTATION_EVAL_GAP_CP, REFUTATION_EVAL_GAP_PAWNS as REPLAY_REFUTATION_EVAL_GAP_PAWNS, defaultRenderPlyNavigation, fenAfterUci, getMissDisplay as getReplayMissDisplay, refutationEvalGapCp, refutationFromEvaluation, refutationEngineOptions as replayRefutationEngineOptions, uciFromDrop, useMissBoard as useReplayMissBoard, useMissSequence as useReplayMissSequence, useMissRefutation as useReplayRefutation } from 'react-chess-core';
|
|
5
5
|
import { Chess } from 'chess.js';
|
|
6
6
|
|
|
@@ -136,6 +136,13 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
136
136
|
const totalPly = movesUci.length;
|
|
137
137
|
const fen = useMemo(() => fenAtPly(movesUci, plyIndex), [movesUci, plyIndex]);
|
|
138
138
|
const displayFen = feedbackFen !== null && feedbackFen !== void 0 ? feedbackFen : fen;
|
|
139
|
+
const lastMoveUci = useMemo(() => {
|
|
140
|
+
var _a;
|
|
141
|
+
if (feedbackFen) {
|
|
142
|
+
return (_a = movesUci[plyIndex]) !== null && _a !== void 0 ? _a : null;
|
|
143
|
+
}
|
|
144
|
+
return lastMoveUciAtPly(movesUci, plyIndex);
|
|
145
|
+
}, [feedbackFen, movesUci, plyIndex]);
|
|
139
146
|
const complete = plyIndex >= totalPly && totalPly > 0;
|
|
140
147
|
const sideToMove$1 = sideToMove(fen);
|
|
141
148
|
const isUserTurn = isTrainSideToMove(trainColor, sideToMove$1);
|
|
@@ -309,6 +316,7 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
309
316
|
expectedUci,
|
|
310
317
|
correctMoveSquare,
|
|
311
318
|
displayFen,
|
|
319
|
+
lastMoveUci,
|
|
312
320
|
canPrev: plyIndex > 0,
|
|
313
321
|
canNext: plyIndex < totalPly,
|
|
314
322
|
goFirst,
|
|
@@ -464,7 +472,7 @@ const ReplayTrainer = ({ gameId, fetchGame, startFen, onMiss, onComplete, onExit
|
|
|
464
472
|
if (state.trainColor === 'black')
|
|
465
473
|
return piece[0] === 'b';
|
|
466
474
|
return piece[0] === state.sideToMove;
|
|
467
|
-
}, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsx(PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxs(Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
|
|
475
|
+
}, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, lastMoveUci: state.lastMoveUci, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsx(PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxs(Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
|
|
468
476
|
? ` · ${state.sideToMove === 'b' ? 'Black' : 'White'} to move`
|
|
469
477
|
: state.isUserTurn
|
|
470
478
|
? ' · Your move'
|
package/dist/index.js
CHANGED
|
@@ -137,6 +137,13 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
137
137
|
const totalPly = movesUci.length;
|
|
138
138
|
const fen = react.useMemo(() => fenAtPly(movesUci, plyIndex), [movesUci, plyIndex]);
|
|
139
139
|
const displayFen = feedbackFen !== null && feedbackFen !== void 0 ? feedbackFen : fen;
|
|
140
|
+
const lastMoveUci = react.useMemo(() => {
|
|
141
|
+
var _a;
|
|
142
|
+
if (feedbackFen) {
|
|
143
|
+
return (_a = movesUci[plyIndex]) !== null && _a !== void 0 ? _a : null;
|
|
144
|
+
}
|
|
145
|
+
return reactChessCore.lastMoveUciAtPly(movesUci, plyIndex);
|
|
146
|
+
}, [feedbackFen, movesUci, plyIndex]);
|
|
140
147
|
const complete = plyIndex >= totalPly && totalPly > 0;
|
|
141
148
|
const sideToMove$1 = sideToMove(fen);
|
|
142
149
|
const isUserTurn = isTrainSideToMove(trainColor, sideToMove$1);
|
|
@@ -310,6 +317,7 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
310
317
|
expectedUci,
|
|
311
318
|
correctMoveSquare,
|
|
312
319
|
displayFen,
|
|
320
|
+
lastMoveUci,
|
|
313
321
|
canPrev: plyIndex > 0,
|
|
314
322
|
canNext: plyIndex < totalPly,
|
|
315
323
|
goFirst,
|
|
@@ -465,7 +473,7 @@ const ReplayTrainer = ({ gameId, fetchGame, startFen, onMiss, onComplete, onExit
|
|
|
465
473
|
if (state.trainColor === 'black')
|
|
466
474
|
return piece[0] === 'b';
|
|
467
475
|
return piece[0] === state.sideToMove;
|
|
468
|
-
}, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxRuntime.jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsxRuntime.jsx(reactChessCore.PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsxRuntime.jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxRuntime.jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
|
|
476
|
+
}, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, lastMoveUci: state.lastMoveUci, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxRuntime.jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsxRuntime.jsx(reactChessCore.PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsxRuntime.jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxRuntime.jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
|
|
469
477
|
? ` · ${state.sideToMove === 'b' ? 'Black' : 'White'} to move`
|
|
470
478
|
: state.isUserTurn
|
|
471
479
|
? ' · Your move'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-chess-replay-trainer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "React component for browsing a chess game and drilling its moves, reporting misses (uses react-chess-core for board and analysis)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Robert Blackwell",
|