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.
 
 
 
 
 

16 KiB

Kuldvillak/Jeopardy Game Platform - Technical Documentation

Table of Contents


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:

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)

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)

: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:

<script>
    import * as m from "$lib/paraglide/messages";
</script>

{m.kv_play_daily_double()}

Development

# 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