# 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
