kaboot/types.ts
2026-01-14 09:07:20 -07:00

165 lines
No EOL
4.2 KiB
TypeScript

export type GameState =
| 'LANDING'
| 'CREATING'
| 'GENERATING'
| 'EDITING'
| 'LOBBY'
| 'COUNTDOWN'
| 'QUESTION'
| 'REVEAL'
| 'SCOREBOARD'
| 'PODIUM'
| 'DISCONNECTED'
| 'WAITING_TO_REJOIN'
| 'HOST_RECONNECTED';
export type GameRole = 'HOST' | 'CLIENT';
export interface AnswerOption {
text: string;
isCorrect: boolean;
shape: 'triangle' | 'diamond' | 'circle' | 'square';
color: 'red' | 'blue' | 'yellow' | 'green';
reason?: string; // Explanation for why this answer is correct or incorrect
}
export interface Question {
id: string;
text: string;
options: AnswerOption[];
timeLimit: number; // in seconds
}
export interface GameConfig {
shuffleQuestions: boolean;
shuffleAnswers: boolean;
hostParticipates: boolean;
streakBonusEnabled: boolean;
streakThreshold: number;
streakMultiplier: number;
comebackBonusEnabled: boolean;
comebackBonusPoints: number;
penaltyForWrongAnswer: boolean;
penaltyPercent: number;
firstCorrectBonusEnabled: boolean;
firstCorrectBonusPoints: number;
}
export const DEFAULT_GAME_CONFIG: GameConfig = {
shuffleQuestions: false,
shuffleAnswers: false,
hostParticipates: true,
streakBonusEnabled: false,
streakThreshold: 3,
streakMultiplier: 1.1,
comebackBonusEnabled: false,
comebackBonusPoints: 50,
penaltyForWrongAnswer: false,
penaltyPercent: 25,
firstCorrectBonusEnabled: false,
firstCorrectBonusPoints: 50,
};
export interface Quiz {
title: string;
questions: Question[];
config?: GameConfig;
}
export type QuizSource = 'manual' | 'ai_generated';
export interface SavedQuiz extends Quiz {
id: string;
source: QuizSource;
aiTopic?: string;
createdAt: string;
updatedAt: string;
config?: GameConfig;
}
export interface QuizListItem {
id: string;
title: string;
source: QuizSource;
aiTopic?: string;
questionCount: number;
createdAt: string;
updatedAt: string;
}
export interface ProcessedDocument {
type: 'native' | 'text';
content: string | Buffer;
mimeType?: string;
}
export interface GenerateQuizOptions {
topic?: string;
questionCount?: number;
documents?: ProcessedDocument[];
}
export interface PointsBreakdown {
basePoints: number;
streakBonus: number;
comebackBonus: number;
firstCorrectBonus: number;
penalty: number;
total: number;
}
export interface Player {
id: string;
name: string;
score: number;
previousScore: number;
streak: number;
lastAnswerCorrect: boolean | null;
selectedShape: 'triangle' | 'diamond' | 'circle' | 'square' | null;
pointsBreakdown: PointsBreakdown | null;
isBot: boolean;
avatarSeed: number;
color: string;
}
// Network Types
export type NetworkMessage =
| { type: 'JOIN'; payload: { name: string; reconnect?: boolean; previousId?: string } }
| { type: 'WELCOME'; payload: {
playerId: string;
quizTitle: string;
players: Player[];
gameState?: GameState;
score?: number;
streak?: number;
hasAnswered?: boolean;
lastAnswerCorrect?: boolean | null;
lastPointsEarned?: number;
selectedShape?: 'triangle' | 'diamond' | 'circle' | 'square' | null;
currentQuestionIndex?: number;
totalQuestions?: number;
questionText?: string;
options?: AnswerOption[];
correctShape?: string;
timeLeft?: number;
} }
| { type: 'PLAYER_JOINED'; payload: { player: Player } }
| { type: 'GAME_START'; payload: {} }
| { type: 'START_COUNTDOWN'; payload: { duration: number } }
| {
type: 'QUESTION_START';
payload: {
totalQuestions: number;
currentQuestionIndex: number;
timeLimit: number;
correctShape: string;
questionText: string;
options: AnswerOption[];
}
}
| { type: 'ANSWER'; payload: { playerId: string; isCorrect: boolean; selectedShape: 'triangle' | 'diamond' | 'circle' | 'square' } }
| { type: 'RESULT'; payload: { isCorrect: boolean; scoreAdded: number; newScore: number; breakdown: PointsBreakdown } }
| { type: 'TIME_SYNC'; payload: { timeLeft: number } }
| { type: 'TIME_UP'; payload: {} }
| { type: 'SHOW_SCOREBOARD'; payload: { players: Player[] } }
| { type: 'GAME_OVER'; payload: { players: Player[] } };