Kuldvillak MVP ei forki, Randel, fork you Randel Mandre SASS license peal
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

541 lines
16 KiB

# Kuldvillak/Jeopardy Game Platform - Technical Documentation
## Table of Contents
- [Overview](#overview)
- [Tech Stack](#tech-stack)
- [Architecture](#architecture)
- [Directory Structure](#directory-structure)
- [Game Flow](#game-flow)
- [State Management](#state-management)
- [Components](#components)
- [Data Types](#data-types)
- [Features](#features)
- [Multi-Window Sync](#multi-window-sync)
---
## Overview
**Ultimate Gaming** is a web-based platform for hosting trivia game shows, currently featuring **Kuldvillak** - a Jeopardy-style quiz game. The platform supports:
- Full game editor with customizable settings
- Dual-screen setup (Moderator + Projector views)
- Real-time cross-tab synchronization
- Theme customization
- Internationalization (Estonian/English)
- Audio management
- Persistent game storage
---
## Tech Stack
| Technology | Version | Purpose |
|------------|---------|---------|
| **SvelteKit** | 2.48.5 | Full-stack framework |
| **Svelte 5** | 5.43.8 | UI with Runes reactivity |
| **TailwindCSS** | 4.1.17 | Utility-first styling |
| **TypeScript** | 5.9.3 | Type safety |
| **Paraglide** | 2.5.0 | i18n (internationalization) |
| **Vite** | 7.2.2 | Build tool |
---
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Ultimate Gaming │
├─────────────────────────────────────────────────────────────┤
│ Routes │
│ ├── / (Home - Game Selection) │
│ ├── /kuldvillak (Game Menu) │
│ ├── /kuldvillak/edit (Game Editor) │
│ └── /kuldvillak/play (Game Play) │
│ ├── ModeratorView (Controls) │
│ └── ProjectorView (Display) │
├─────────────────────────────────────────────────────────────┤
│ State Management (Svelte 5 Runes) │
│ ├── gameSession.svelte.ts (Live game state + BroadcastAPI) │
│ ├── kuldvillak.svelte.ts (Game store - editor) │
│ ├── theme.svelte.ts (Color theming) │
│ ├── audio.svelte.ts (Music/SFX volumes) │
│ └── persistence.ts (localStorage utilities) │
├─────────────────────────────────────────────────────────────┤
│ Components │
│ ├── Shared (Settings, ColorPicker, Toast, etc.) │
│ └── Kuldvillak UI (Buttons, Cards, Logo, etc.) │
└─────────────────────────────────────────────────────────────┘
```
---
## Directory Structure
```
src/
├── lib/
│ ├── assets/ # Static assets (favicon)
│ ├── components/
│ │ ├── kuldvillak/
│ │ │ └── ui/ # Game-specific UI components
│ │ │ ├── KvButtonPrimary.svelte
│ │ │ ├── KvButtonSecondary.svelte
│ │ │ ├── KvEditCard.svelte
│ │ │ ├── KvGameLogo.svelte
│ │ │ ├── KvNumberInput.svelte
│ │ │ ├── KvPlayerCard.svelte
│ │ │ └── KvProjectorCard.svelte
│ │ ├── ColorPicker.svelte
│ │ ├── ConfirmDialog.svelte
│ │ ├── LanguageSwitcher.svelte
│ │ ├── Settings.svelte
│ │ ├── Slider.svelte
│ │ └── Toast.svelte
│ ├── paraglide/ # Generated i18n code
│ ├── stores/
│ │ ├── audio.svelte.ts
│ │ ├── gameSession.svelte.ts
│ │ ├── kuldvillak.svelte.ts
│ │ ├── persistence.ts
│ │ └── theme.svelte.ts
│ ├── types/
│ │ └── kuldvillak.ts # TypeScript interfaces
│ └── index.ts # Library exports
├── routes/
│ ├── kuldvillak/
│ │ ├── edit/
│ │ │ └── +page.svelte # Game editor
│ │ ├── play/
│ │ │ ├── +page.svelte # Route handler
│ │ │ ├── ModeratorView.svelte
│ │ │ └── ProjectorView.svelte
│ │ ├── +layout.svelte
│ │ └── +page.svelte # Game menu
│ ├── +error.svelte
│ ├── +layout.svelte # Root layout
│ ├── +page.svelte # Home page
│ └── layout.css # Global styles + Tailwind
├── app.html
├── app.d.ts
├── hooks.server.ts
└── hooks.ts
```
---
## Game Flow
### 1. Game Creation (Editor)
```
/kuldvillak/edit
├── Configure Settings
│ ├── Number of rounds (1-2)
│ ├── Timer durations
│ ├── Point values (preset or custom)
│ ├── Daily doubles per round
│ └── Enable/disable final round
├── Add Teams (2-6 players)
├── Fill Categories & Questions
│ ├── 6 categories per round
│ ├── 5 questions per category
│ └── Mark daily doubles
├── Final Round Question (optional)
└── Start Game → Opens Moderator + Projector views
```
### 2. Game Phases
```
┌─────────────┐
│ intro │ ← Kuldvillak logo screen
└──────┬──────┘
┌──────▼──────────────┐
│ intro-categories │ ← Category reveal animation
└──────┬──────────────┘
┌──────▼──────┐
│ board │ ← Question selection grid
└──────┬──────┘
┌──────▼──────────────┐
│ daily-double (if) │ ← Wager selection
└──────┬──────────────┘
┌──────▼──────┐
│ question │ ← Display question, teams answer
└──────┬──────┘
├── Correct → Award points
├── Wrong → Deduct points, next team
└── Skip → Reveal answer
└──────► Back to board
│ (After all questions)
┌──────▼────────────────┐
│ final-intro │ ← Final round logo
├───────────────────────┤
│ final-category │ ← Reveal final category
├───────────────────────┤
│ final-question │ ← Teams write answers + wagers
├───────────────────────┤
│ final-scores │ ← Final standings
└───────────────────────┘
┌──────▼──────┐
│ finished │
└─────────────┘
```
### 3. Question Flow
```
Question Selected
├── Is Daily Double?
│ │
│ ├── YES → Select team → Enter wager → Show question
│ └── NO → Show question directly
Display Question
├── Timer starts
├── Team clicks to answer
│ │
│ ├── Timer pauses
│ │
│ ├── Moderator marks Correct/Wrong
│ │ │
│ │ ├── Correct → +points → Show answer → Return to board
│ │ └── Wrong → -points → Continue (others can try)
│ │
│ └── All teams wrong → Auto-reveal answer
└── Timer expires → Auto-reveal answer
```
---
## State Management
### GameSessionStore (`gameSession.svelte.ts`)
The heart of the game - manages live game state with cross-tab synchronization.
**Key Features:**
- Uses `BroadcastChannel` API for real-time sync between Moderator and Projector
- Persists to `localStorage` for session recovery
- Single internal timer managed by moderator view
**State Interface:**
```typescript
interface GameSessionState {
// Game data
name: string;
settings: GameSettings;
teams: Team[];
rounds: Round[];
finalRound: FinalRound | null;
// Game phase
phase: GamePhase;
currentRoundIndex: number;
activeTeamId: string | null;
// Animation state
introCategoryIndex: number;
categoriesIntroduced: boolean;
boardRevealed: boolean;
// Question state
currentQuestion: { roundIndex, categoryIndex, questionIndex } | null;
showAnswer: boolean;
wrongTeamIds: string[];
lastAnsweredTeamId: string | null;
lastAnswerCorrect: boolean | null;
// Daily Double
dailyDoubleWager: number | null;
// Final Round
finalCategoryRevealed: boolean;
finalWagers: Record<string, number>;
finalAnswers: Record<string, string>;
finalRevealed: string[];
// Timer
timerRunning: boolean;
timerSeconds: number;
timerMax: number;
timeoutCountdown: number | null;
revealCountdown: number | null;
skippingQuestion: boolean;
// Tracking
questionsAnswered: number;
currentQuestionNumber: number;
questionResults: QuestionResult[];
}
```
### ThemeStore (`theme.svelte.ts`)
Manages color theming with cross-window sync.
**CSS Variables controlled:**
- `--kv-blue` (primary)
- `--kv-yellow` (secondary)
- `--kv-text`
- `--kv-background`
### AudioStore (`audio.svelte.ts`)
Manages background music and sound effects volumes.
---
## Components
### Shared Components
| Component | Purpose |
|-----------|---------|
| `Settings.svelte` | Modal with audio, language, and color settings |
| `ColorPicker.svelte` | Full HSL color picker with swatches |
| `ConfirmDialog.svelte` | Confirmation modal |
| `Toast.svelte` | Notification messages |
| `Slider.svelte` | Volume control slider |
| `LanguageSwitcher.svelte` | ET/EN language toggle |
### Kuldvillak UI Components
| Component | Purpose |
|-----------|---------|
| `KvButtonPrimary.svelte` | Yellow primary action button |
| `KvButtonSecondary.svelte` | Blue secondary action button |
| `KvEditCard.svelte` | Team card for moderator (score adjust, correct/wrong) |
| `KvPlayerCard.svelte` | Basic player display card |
| `KvProjectorCard.svelte` | Player card for projector view |
| `KvNumberInput.svelte` | Styled number input with +/- buttons |
| `KvGameLogo.svelte` | SVG logo component with variants |
---
## Data Types
### Core Types (`types/kuldvillak.ts`)
```typescript
interface Question {
id: string;
question: string;
answer: string;
points: number;
isDailyDouble: boolean;
isRevealed: boolean;
imageUrl?: string;
}
interface Category {
id: string;
name: string;
questions: Question[];
}
interface Round {
id: string;
name: string;
categories: Category[];
pointMultiplier: number;
}
interface Team {
id: string;
name: string;
score: number;
}
interface GameSettings {
numberOfRounds: 1 | 2;
pointValuePreset: 'round1' | 'round2' | 'custom' | 'multiplier';
pointValues: number[];
basePointValue: number;
categoriesPerRound: number; // Default: 6
questionsPerCategory: number; // Default: 5
dailyDoublesPerRound: number[];
enableFinalRound: boolean;
enableSoundEffects: boolean;
allowNegativeScores: boolean;
maxTeams: number; // Max: 6
defaultTimerSeconds: number;
answerRevealSeconds: number;
}
type GamePhase =
| 'intro' // Logo screen
| 'intro-categories' // Category reveal
| 'lobby'
| 'board' // Question grid
| 'question'
| 'answer'
| 'daily-double'
| 'final-intro'
| 'final-category'
| 'final-wagers'
| 'final-question'
| 'final-reveal'
| 'final-scores'
| 'finished';
```
---
## Features
### 1. Game Editor
- Auto-save to localStorage
- Import/Export JSON game files
- Visual daily double indicators
- Point value presets or custom
- Final round configuration
### 2. Moderator View
- Full game control
- Score adjustments
- Timer control (start/stop/reset)
- Question skip functionality
- Open projector window button
### 3. Projector View
- Full-screen presentation
- Animated category introductions
- Staggered board reveal animation
- Question expand animation
- Team score display during questions
- Final scores display
### 4. Animations (ProjectorView)
- **Category Intro**: 500ms fade-in → 1500ms shown → 500ms push-out
- **Board Reveal**: Staggered 50ms per cell
- **Question Expand**: From grid cell position to fullscreen
### 5. Cross-Tab Sync
- Real-time state sync via BroadcastChannel
- localStorage persistence for recovery
- Single timer owner (moderator)
---
## Multi-Window Sync
```
┌─────────────────┐ BroadcastChannel ┌─────────────────┐
│ Moderator Tab │ ◄─────────────────────────────► │ Projector Tab │
│ │ │ │
│ - Controls │ STATE_UPDATE │ - Display │
│ - Timer owner │ ─────────────────────────────────►│ - Animations │
│ - Score adjust │ │ - Read-only │
└────────┬────────┘ └─────────────────┘
│ localStorage
┌─────────────────┐
│ Session Store │
│ (persistence) │
└─────────────────┘
```
---
## Styling
### Design Tokens (CSS Variables)
```css
:root {
/* Colors */
--kv-blue: #003B9B; /* Primary */
--kv-yellow: #FFAB00; /* Secondary/Accent */
--kv-text: #FFFFFF;
--kv-background: #000000;
--kv-green: #009900; /* Correct */
--kv-red: #FF3333; /* Wrong */
/* Fonts */
--kv-font-title: 'Swiss 921';
--kv-font-body: 'Swiss 921';
--kv-font-price: 'Bebas Neue';
--kv-font-question: 'ITC Korinna';
/* Shadows */
--kv-shadow-text: 6px 6px 4px rgba(0,0,0,0.5);
--kv-shadow-price: 8px 8px 4px rgba(0,0,0,0.5);
--kv-shadow-button: 0 4px 4px rgba(0,0,0,0.25), 8px 8px 4px rgba(0,0,0,0.5);
}
```
### Tailwind Theme Extensions
Custom Tailwind classes prefixed with `kv-`:
- Colors: `bg-kv-blue`, `text-kv-yellow`, etc.
- Fonts: `font-kv-body`, `font-kv-price`, etc.
---
## i18n (Internationalization)
Using **Paraglide** for type-safe translations.
**Supported Languages:**
- Estonian (et) - Primary
- English (en)
**Message Files:**
- `messages/et.json`
- `messages/en.json`
**Usage:**
```svelte
<script>
import * as m from "$lib/paraglide/messages";
</script>
{m.kv_play_daily_double()}
```
---
## Development
```bash
# Install dependencies
npm install
# Start dev server
npm run dev
# Build for production
npm run build
# Type check
npm run check
```
---
## Future Considerations
1. **Database Backend**: Replace localStorage with proper database for persistence
2. **WebSocket**: Real-time sync without BroadcastChannel limitations
3. **Sound Effects**: Implement actual SFX playback
4. **More Game Modes**: "Rooside Sõda" (Family Feud) placeholder exists
5. **User Accounts**: Save games to cloud
6. **Mobile Buzzer**: Player buzzer app for team selection