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,17 @@
from app.schemas.question import QuestionCreate, QuestionUpdate, QuestionResponse
from app.schemas.game import (
RoomCreate,
RoomJoin,
PlayerInfo,
GameState,
AnswerSubmit,
StealAttempt
)
from app.schemas.admin import AdminCreate, AdminLogin, Token
__all__ = [
"QuestionCreate", "QuestionUpdate", "QuestionResponse",
"RoomCreate", "RoomJoin", "PlayerInfo", "GameState",
"AnswerSubmit", "StealAttempt",
"AdminCreate", "AdminLogin", "Token"
]

View File

@@ -0,0 +1,31 @@
from pydantic import BaseModel
from datetime import datetime
class AdminBase(BaseModel):
username: str
class AdminCreate(AdminBase):
password: str
class AdminLogin(AdminBase):
password: str
class AdminResponse(AdminBase):
id: int
created_at: datetime
class Config:
from_attributes = True
class Token(BaseModel):
access_token: str
token_type: str = "bearer"
class TokenData(BaseModel):
username: str | None = None

View File

@@ -0,0 +1,70 @@
from pydantic import BaseModel
from typing import Optional, List, Dict
from datetime import datetime
class PlayerInfo(BaseModel):
name: str
team: str # 'A' or 'B'
position: int
socket_id: Optional[str] = None
class RoomCreate(BaseModel):
player_name: str
class RoomJoin(BaseModel):
room_code: str
player_name: str
team: str # 'A' or 'B'
class TeamState(BaseModel):
players: List[PlayerInfo]
score: int
current_player_index: int
class QuestionState(BaseModel):
id: int
category_id: int
difficulty: int
points: int
answered: bool = False
class GameState(BaseModel):
room_code: str
status: str # waiting, playing, finished
team_a: TeamState
team_b: TeamState
current_team: Optional[str] = None
current_question: Optional[int] = None
can_steal: bool = False
board: Dict[int, List[QuestionState]] # category_id -> questions
timer_end: Optional[datetime] = None
class AnswerSubmit(BaseModel):
question_id: int
answer: str
class StealAttempt(BaseModel):
question_id: int
attempt: bool # True = try to steal, False = pass
answer: Optional[str] = None
class ChatMessage(BaseModel):
player_name: str
team: str
message: str
timestamp: datetime
class EmojiReaction(BaseModel):
player_name: str
team: str
emoji: str # One of: 👏 😮 😂 🔥 💀 🎉 😭 🤔

View File

@@ -0,0 +1,61 @@
from pydantic import BaseModel
from typing import Optional, List
from datetime import date, datetime
class QuestionBase(BaseModel):
question_text: str
correct_answer: str
alt_answers: List[str] = []
difficulty: int
fun_fact: Optional[str] = None
class QuestionCreate(QuestionBase):
category_id: int
class QuestionUpdate(BaseModel):
question_text: Optional[str] = None
correct_answer: Optional[str] = None
alt_answers: Optional[List[str]] = None
difficulty: Optional[int] = None
fun_fact: Optional[str] = None
status: Optional[str] = None
date_active: Optional[date] = None
class QuestionResponse(QuestionBase):
id: int
category_id: int
points: int
time_seconds: int
date_active: Optional[date]
status: str
created_at: datetime
class Config:
from_attributes = True
class QuestionForGame(BaseModel):
id: int
category_id: int
question_text: str
difficulty: int
points: int
time_seconds: int
class Config:
from_attributes = True
class AIGenerateRequest(BaseModel):
category_id: int
difficulty: int
count: int = 5
class AIValidateRequest(BaseModel):
question_id: int
player_answer: str