feat: Initial project structure for WebTriviasMulti

- Backend: FastAPI + Python-SocketIO + SQLAlchemy
  - Models for categories, questions, game sessions, events
  - AI services for answer validation and question generation (Claude)
  - Room management with Redis
  - Game logic with stealing mechanics
  - Admin API for question management

- Frontend: React + Vite + TypeScript + Tailwind
  - 5 visual themes (DRRR, Retro, Minimal, RGB, Anime 90s)
  - Real-time game with Socket.IO
  - Achievement system
  - Replay functionality
  - Sound effects per theme

- Docker Compose for deployment
- Design documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-26 07:50:48 +00:00
commit 43021b9c3c
57 changed files with 5446 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
import { create } from 'zustand'
import type { GameRoom, Player, Question, ChatMessage, Achievement } from '../types'
interface GameState {
// Room state
room: GameRoom | null
setRoom: (room: GameRoom | null) => void
// Player info
playerName: string
setPlayerName: (name: string) => void
// Current question
currentQuestion: Question | null
setCurrentQuestion: (question: Question | null) => void
// Timer
timerEnd: Date | null
setTimerEnd: (end: Date | null) => void
// Chat messages
messages: ChatMessage[]
addMessage: (message: ChatMessage) => void
clearMessages: () => void
// Achievements
achievements: Achievement[]
setAchievements: (achievements: Achievement[]) => void
unlockAchievement: (id: number) => void
// Game stats (for achievements tracking)
stats: {
correctStreak: number
stealsAttempted: number
stealsSuccessful: number
categoryCorrect: Record<number, number>
fastAnswers: number
maxDeficit: number
}
updateStats: (updates: Partial<GameState['stats']>) => void
resetStats: () => void
// UI state
showStealPrompt: boolean
setShowStealPrompt: (show: boolean) => void
// Reset
resetGame: () => void
}
const initialStats = {
correctStreak: 0,
stealsAttempted: 0,
stealsSuccessful: 0,
categoryCorrect: {},
fastAnswers: 0,
maxDeficit: 0,
}
export const useGameStore = create<GameState>((set) => ({
room: null,
setRoom: (room) => set({ room }),
playerName: '',
setPlayerName: (playerName) => set({ playerName }),
currentQuestion: null,
setCurrentQuestion: (currentQuestion) => set({ currentQuestion }),
timerEnd: null,
setTimerEnd: (timerEnd) => set({ timerEnd }),
messages: [],
addMessage: (message) =>
set((state) => ({ messages: [...state.messages, message].slice(-100) })),
clearMessages: () => set({ messages: [] }),
achievements: [],
setAchievements: (achievements) => set({ achievements }),
unlockAchievement: (id) =>
set((state) => ({
achievements: state.achievements.map((a) =>
a.id === id ? { ...a, unlocked: true, unlockedAt: new Date().toISOString() } : a
),
})),
stats: initialStats,
updateStats: (updates) =>
set((state) => ({ stats: { ...state.stats, ...updates } })),
resetStats: () => set({ stats: initialStats }),
showStealPrompt: false,
setShowStealPrompt: (showStealPrompt) => set({ showStealPrompt }),
resetGame: () =>
set({
room: null,
currentQuestion: null,
timerEnd: null,
messages: [],
stats: initialStats,
showStealPrompt: false,
}),
}))