fix: NCWF-4 Token Issues (#8)

Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de>
Co-authored-by: shahdlala66 <shahd.lala66@gmail.com>
Reviewed-on: #8
This commit was merged in pull request #8.
This commit is contained in:
2026-06-02 21:55:55 +02:00
parent 873bfe3bae
commit 95eff42dfe
37 changed files with 2522 additions and 573 deletions
+85 -3
View File
@@ -23,6 +23,11 @@ export class GameFacade implements OnDestroy {
gameCompletionMessage = '';
isGameFinished = false;
isPromotionDialogOpen = false;
resignConfirmPending = false;
private fenHistory: string[] = [];
private sessionStartPly = 0;
viewingPly: number | null = null;
private boardSelection: BoardSelection = {
selectedSquare: null,
@@ -52,6 +57,46 @@ export class GameFacade implements OnDestroy {
return this.boardSelection.highlightedSquares;
}
get displayFen(): string {
if (this.viewingPly !== null) {
const historyIndex = this.viewingPly - this.sessionStartPly;
return this.fenHistory[historyIndex] ?? this.game?.state.fen ?? '';
}
return this.game?.state.fen ?? '';
}
get isReviewing(): boolean {
return this.viewingPly !== null;
}
navigateToPly(ply: number): void {
const historyIndex = ply - this.sessionStartPly;
if (historyIndex < 0 || historyIndex >= this.fenHistory.length) return;
this.viewingPly = ply;
this.boardSelection = this.boardSelectionService.clearSelection();
}
navigateHistory(direction: 'first' | 'prev' | 'next' | 'last'): void {
const totalPly = this.sessionStartPly + this.fenHistory.length - 1;
const current = this.viewingPly ?? totalPly;
let next: number;
switch (direction) {
case 'first': next = this.sessionStartPly; break;
case 'prev': next = Math.max(this.sessionStartPly, current - 1); break;
case 'next': next = Math.min(totalPly, current + 1); break;
case 'last':
default: next = totalPly; break;
}
if (next === totalPly) {
this.viewingPly = null;
} else {
this.viewingPly = next;
}
this.boardSelection = this.boardSelectionService.clearSelection();
}
ngOnDestroy(): void {
this.streamService.cleanup();
this.botMoveService.cleanup();
@@ -63,7 +108,7 @@ export class GameFacade implements OnDestroy {
}
onBoardSquareSelected(square: string): void {
if (!this.state) {
if (!this.state || this.viewingPly !== null) {
return;
}
@@ -123,6 +168,8 @@ export class GameFacade implements OnDestroy {
if (this.game) {
this.game = { ...this.game, state };
this.clockSyncedAt = Date.now();
this.pushFen(state.fen);
this.viewingPly = null;
this.updateGameCompletion();
}
this.moveInput = '';
@@ -171,6 +218,26 @@ export class GameFacade implements OnDestroy {
this.pendingPromotionMoves = [];
}
requestResign(): void {
this.resignConfirmPending = true;
}
cancelResign(): void {
this.resignConfirmPending = false;
}
confirmResign(): void {
this.resignConfirmPending = false;
this.gameApi
.resignGame(this.gameId)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
error: (error) => {
this.errorMessage = getErrorMessage(error, 'Could not resign.');
}
});
}
importFen(): void {
this.errorMessage = '';
this.importService.importFen(
@@ -204,6 +271,8 @@ export class GameFacade implements OnDestroy {
this.errorMessage = '';
this.boardSelection = this.boardSelectionService.clearSelection();
this.streamService.cleanup();
this.fenHistory = [];
this.viewingPly = null;
this.gameApi
.getGame(this.gameId)
@@ -213,6 +282,8 @@ export class GameFacade implements OnDestroy {
this.game = game;
this.clockSyncedAt = Date.now();
this.loading = false;
this.sessionStartPly = game.state.moves.length;
this.fenHistory = [game.state.fen];
this.updateGameCompletion();
this.gameHistory.recordGame(this.gameId);
this.startStreaming();
@@ -237,7 +308,10 @@ export class GameFacade implements OnDestroy {
if (event.type === 'gameFull') {
this.game = event.game;
this.clockSyncedAt = Date.now();
this.boardSelection = this.boardSelectionService.clearSelection();
this.pushFen(event.game.state.fen);
if (this.viewingPly === null) {
this.boardSelection = this.boardSelectionService.clearSelection();
}
this.updateGameCompletion();
this.tryMakeBotMove();
return;
@@ -247,8 +321,9 @@ export class GameFacade implements OnDestroy {
const moveCountBefore = this.game.state.moves.length;
this.game = { ...this.game, state: event.state };
this.clockSyncedAt = Date.now();
this.pushFen(event.state.fen);
this.updateGameCompletion();
if (event.state.moves.length !== moveCountBefore) {
if (event.state.moves.length !== moveCountBefore && this.viewingPly === null) {
this.boardSelection = this.boardSelectionService.clearSelection();
this.tryMakeBotMove();
}
@@ -260,6 +335,13 @@ export class GameFacade implements OnDestroy {
}
}
private pushFen(fen: string): void {
const last = this.fenHistory[this.fenHistory.length - 1];
if (last !== fen) {
this.fenHistory.push(fen);
}
}
private tryMakeBotMove(): void {
this.botMoveService.tryMakeBotMove(
this.gameId,