61 lines
1.4 KiB
TypeScript
61 lines
1.4 KiB
TypeScript
import type { Chess } from 'chess.js';
|
|
import type { WebSocket } from 'ws';
|
|
import type {
|
|
Announcement,
|
|
Color,
|
|
EndReason,
|
|
GameId,
|
|
GameStatus,
|
|
Mode,
|
|
PieceType,
|
|
PlayerToken,
|
|
PromotionType,
|
|
Square,
|
|
} from '@blind-chess/shared';
|
|
|
|
export interface MoveRecord {
|
|
ply: number;
|
|
by: Color;
|
|
from: Square;
|
|
to: Square;
|
|
san: string;
|
|
capturedPieceType?: PieceType;
|
|
promotion?: PromotionType;
|
|
flags: { castle?: 'k' | 'q'; enPassant?: boolean; check?: boolean; mate?: boolean };
|
|
at: number;
|
|
}
|
|
|
|
export interface PlayerSlot {
|
|
token: PlayerToken;
|
|
socket: WebSocket | null;
|
|
joinedAt: number;
|
|
rateBucket: { tokens: number; last: number };
|
|
}
|
|
|
|
export interface Game {
|
|
id: GameId;
|
|
mode: Mode;
|
|
highlightingEnabled: boolean;
|
|
status: GameStatus;
|
|
createdAt: number;
|
|
finishedAt?: number;
|
|
endReason?: EndReason;
|
|
winner?: Color | null;
|
|
|
|
chess: Chess;
|
|
moveHistory: MoveRecord[];
|
|
announcements: Announcement[];
|
|
|
|
players: { w: PlayerSlot | null; b: PlayerSlot | null };
|
|
|
|
armed: { color: Color; from: Square } | null;
|
|
drawOffer: { from: Color; at: number } | null;
|
|
disconnectAt: { w?: number; b?: number };
|
|
lastBroadcastIdx: { w: number; b: number };
|
|
aiOpponent?: { color: Color; brain: 'casual' | 'recon' };
|
|
}
|
|
|
|
export const RATE_LIMIT = { capacity: 20, refillPerSec: 10 };
|
|
export const GRACE_MS = 5 * 60 * 1000;
|
|
export const PRUNE_AFTER_FINISHED_MS = 30 * 60 * 1000;
|