electro-sb's picture
Containerization and frontend backend communication issue fixed
d086f83
import axios from 'axios';
// In development, the API URL is '/api', but in production, it's just '/'
const API_URL = '';
// Define types based on the backend API
export interface NewGameOptions {
player_color: 'white' | 'black';
difficulty: 'beginner' | 'easy' | 'medium' | 'hard' | 'expert' | 'master';
time_limit: number;
use_opening_book: boolean;
enable_analysis: boolean;
}
export interface MoveRequest {
move: string;
}
// Promotion-related types
export type PromotionPiece = 'queen' | 'rook' | 'bishop' | 'knight';
export interface PromotionMove {
from: string; // e.g., "e7"
to: string; // e.g., "e8"
piece?: PromotionPiece; // promotion piece selection
required: boolean; // true if promotion piece selection is required
}
export interface PromotionRequirement {
from: string;
to: string;
available_pieces: PromotionPiece[];
}
export interface PromotionRequest {
move: string;
promotion_piece: PromotionPiece;
}
export interface GameState {
fen: string;
turn: 'white' | 'black';
game_state: string;
legal_moves: string[];
in_check: boolean;
move_count: number;
}
export interface GameResponse {
status: string;
message?: string;
board_state: GameState;
player_color?: 'white' | 'black';
player_move?: string;
ai_move?: string;
analysis?: any;
result?: string;
winner?: string;
reason?: string;
// Promotion support
promotion_required?: PromotionRequirement;
}
export interface HintResponse {
status: string;
hint: string;
explanation: string;
board_state: GameState;
}
// API functions
export const startNewGame = async (options: NewGameOptions): Promise<GameResponse> => {
const response = await axios.post(`${API_URL}/game/new`, options);
return response.data;
};
export const makeMove = async (move: string, promotionPiece?: PromotionPiece): Promise<GameResponse> => {
try {
// If promotion piece is specified, append it to the move in UCI notation
const moveWithPromotion = promotionPiece ? createPromotionMove(move.substring(0, 2), move.substring(2, 4), promotionPiece) : move;
const response = await axios.post(`${API_URL}/game/move`, { move: moveWithPromotion });
return response.data;
} catch (error) {
// Handle promotion-required errors specifically
if (axios.isAxiosError(error) && error.response?.status === 400) {
const errorData = error.response.data;
// Check if this is a promotion-required error
if (errorData.status === 'promotion_required' || errorData.promotion_details) {
return {
status: 'promotion_required',
message: errorData.message || 'Pawn promotion requires piece selection',
board_state: errorData.board_state || {} as GameState,
promotion_required: {
from: errorData.promotion_details?.from || move.substring(0, 2),
to: errorData.promotion_details?.to || move.substring(2, 4),
available_pieces: errorData.promotion_details?.available_pieces || ['queen', 'rook', 'bishop', 'knight']
}
};
}
}
// Re-throw other errors
throw error;
}
};
export const getGameState = async (): Promise<GameResponse> => {
const response = await axios.get(`${API_URL}/game/state`);
return response.data;
};
export const getHint = async (): Promise<HintResponse> => {
const response = await axios.post(`${API_URL}/game/hint`);
return response.data;
};
export const undoMove = async (count: number = 2): Promise<GameResponse> => {
const response = await axios.post(`${API_URL}/game/undo`, { count });
return response.data;
};
export const resignGame = async (): Promise<GameResponse> => {
const response = await axios.post(`${API_URL}/game/resign`);
return response.data;
};
// Utility functions for promotion handling
export const isPromotionRequired = (response: GameResponse): boolean => {
return response.status === 'promotion_required' && !!response.promotion_required;
};
export const getPromotionRequirement = (response: GameResponse): PromotionRequirement | null => {
return response.promotion_required || null;
};
export const createPromotionMove = (from: string, to: string, piece: PromotionPiece): string => {
// Map promotion pieces to UCI notation
const pieceMap: Record<PromotionPiece, string> = {
'queen': 'q',
'rook': 'r',
'bishop': 'b',
'knight': 'n' // Knight uses 'n' in UCI notation, not 'k'
};
return `${from}${to}${pieceMap[piece]}`;
};