124 lines
5.5 KiB
Markdown
124 lines
5.5 KiB
Markdown
# 🌙 Уютная викторина — Calm Family Quiz
|
|
|
|
Спокойная семейная игра-викторина в стиле «Своей игры», созданная для уютного
|
|
вечера перед сном. Все смотрят на одно табло, ведущий управляет игрой, команда
|
|
отвечает вместе — без таймеров, давления и спешки.
|
|
|
|
## 🚀 Запуск
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
Откройте адрес из консоли (обычно `http://localhost:5173`).
|
|
|
|
### Прочее
|
|
|
|
```bash
|
|
npm run build # production-сборка
|
|
npm run preview # предпросмотр сборки
|
|
npm run check # проверка типов (svelte-check)
|
|
```
|
|
|
|
## 🎮 Как играть
|
|
|
|
1. **Выбор набора** — выберите тему вопросов.
|
|
2. **Табло** — категории и карточки очков (100 / 200 / 300 / 500 / 1000).
|
|
Чем дороже карточка, тем сложнее вопрос.
|
|
3. Ведущий открывает вопрос, затем «Показать ответ», и решает:
|
|
- **Засчитать +N** — команде идут очки;
|
|
- **Не засчитывать** — без очков, но вопрос закрыт.
|
|
- Штрафов и минусов нет.
|
|
4. Для творческих вопросов (type `creative`) кнопка мягче:
|
|
«Засчитать творческий ответ +N».
|
|
5. Сыгранный вопрос затемняется и больше не выбирается.
|
|
6. Когда сыграны все вопросы — экран результата с мягкой финальной фразой.
|
|
|
|
Прогресс сохраняется автоматически — после перезагрузки игра продолжится с того же места.
|
|
|
|
## 🧩 Добавление нового набора вопросов
|
|
|
|
Архитектура задумана так, чтобы наборы добавлялись без правок UI.
|
|
|
|
1. Создайте файл `src/lib/question-sets/<name>.ts`:
|
|
|
|
```ts
|
|
import type { QuestionSet } from '$lib/types';
|
|
|
|
export const mySet: QuestionSet = {
|
|
id: 'my-set', // уникальный
|
|
title: 'Моя тема',
|
|
description: 'Короткое описание',
|
|
ageRange: '6+ лет',
|
|
categories: [
|
|
{
|
|
id: 'cat-1', // уникально в пределах набора
|
|
title: 'Категория',
|
|
questions: [
|
|
{ id: 'q1', points: 100, question: '...', answer: '...', type: 'strict' },
|
|
{ id: 'q2', points: 200, question: '...', answer: '...', type: 'strict' },
|
|
{ id: 'q3', points: 300, question: '...', answer: '...', type: 'strict' },
|
|
{ id: 'q4', points: 500, question: '...', answer: '...', type: 'creative' },
|
|
{ id: 'q5', points: 1000, question: '...', answer: '...', type: 'strict' }
|
|
// ровно 5 вопросов с очками 100/200/300/500/1000
|
|
]
|
|
}
|
|
// …остальные категории
|
|
]
|
|
};
|
|
```
|
|
|
|
2. Зарегистрируйте набор в `src/lib/question-sets/index.ts`:
|
|
|
|
```ts
|
|
import { mySet } from './my-set';
|
|
export const questionSets = [animalsSet, cozySet, mySet];
|
|
```
|
|
|
|
Готово — набор автоматически появится на экране выбора.
|
|
|
|
## 🏗️ Архитектура
|
|
|
|
Код аккуратно разделён по слоям:
|
|
|
|
```
|
|
src/
|
|
├─ lib/
|
|
│ ├─ types.ts # Доменные типы (Question, Category, QuestionSet, GameState)
|
|
│ ├─ question-sets/ # ДАННЫЕ (отделены от UI)
|
|
│ │ ├─ animals.ts # набор-заглушка
|
|
│ │ ├─ cozy.ts # набор-заглушка
|
|
│ │ └─ index.ts # реестр наборов + хелперы поиска
|
|
│ ├─ stores/
|
|
│ │ └─ game.ts # СОСТОЯНИЕ игры (Svelte store + localStorage)
|
|
│ └─ components/ # UI-компоненты
|
|
│ ├─ QuestionSetSelector.svelte
|
|
│ ├─ GameBoard.svelte
|
|
│ ├─ QuestionCard.svelte
|
|
│ ├─ ScorePanel.svelte
|
|
│ ├─ QuestionModal.svelte
|
|
│ ├─ HostControls.svelte
|
|
│ ├─ GameResult.svelte
|
|
│ └─ ConfirmDialog.svelte
|
|
└─ routes/
|
|
├─ +layout.svelte # подключение глобальных стилей
|
|
├─ +layout.ts # CSR-only (localStorage)
|
|
└─ +page.svelte # оркестрация экранов
|
|
```
|
|
|
|
**Принципы:**
|
|
- Данные вопросов полностью отделены от состояния и UI.
|
|
- Состояние игры живёт в Svelte store с автосохранением в `localStorage`
|
|
и восстанавливается после перезагрузки.
|
|
- Очки берутся из данных вопроса — ничего не хардкодится в UI.
|
|
- Никакого бэкенда, БД, авторизации, мультиплеера или редактора в MVP.
|
|
|
|
## 🎨 Стек
|
|
|
|
- **SvelteKit + TypeScript**
|
|
- **Tailwind CSS v4** (через `@tailwindcss/vite`)
|
|
- Без тяжёлых UI-библиотек — только лёгкие зависимости.
|
|
|
|
Лицензия: личный/семейный проект.
|