18 KiB
PEAK HOUR — GDD (компактная сводка v1.2)
Статус: компактная сводка правил и чисел из постановки задачи + решений
DECISIONS.md(ссылки Dxx). Версия v1.2 (25.10.2026) добавляет решения D18–D25 и не отменяет D01–D17, если ниже не сказано иное. Godot 4.7.2 → HTML5 (Web, no threads), RU-only, окно 1920×1080, логический viewport 1280×720 (canvas_items/keep/fractional), 4 человека, джем FEIS, дедлайн 26.10.2026 23:59 Minsk.
1–2. Обзор и платформа
Менеджер приёма/отправки файлов: дежурный узла обрабатывает пакеты,
запросы клиентов, канал и атаки в течение одной смены. Ограничения:
окно 1920×1080, логический viewport 1280×720 (canvas_items, keep,
fractional), nearest, RU-only, Web no-threads (без Thread/блокирующего IO),
шрифт Handjet (D15). UI v2 — «Kaleidos»: тёплая бумага, 1 px контуры,
мягкие тени и бирюзовый акцент (D18).
3. Структура смены
Забег конечный, 9 игровых часов: Prep (подготовка) → Hour → итоги часа; после 9-го — победа и итоги забега. Досрочное поражение —
SLA ≤ 0 (сразу итоги забега). «Конец забега по складу» — страховочный
механизм (см. §16), тоже итоги забега. Магазин открывается с часа 2
(в подготовке после часа 1) и скрыт во время часа (D23).
4. Файлы и типы
4 типа файлов: текст (text), звук (sound), фото (photo), видео
(video). Каждый с полями name_ru, ext, icon, recv_time, send_time, recv_fee, base_pay, weight, minigame_coeff, sla_loss — значения в
data/balance.json.
Перед отправкой запроса качество определяется заглушкой quality = 1.0;
кнопка «Переделать» не даёт бонусов (D17). «Самый сложный тип» заменён
средним коэффициентом (см. выбор мини-игры, п. 8.4/10). Потеря пакета
бьёт по SLA по типу: text 2, sound 4, photo 8, video 16 (D19).
5. Папки и секции
Файлы лежат в папках (список папок по умолчанию — names_ru.json),
папки сгруппированы в секции; секции докупаются в магазине (D13).
Обычные файлы удаляются только в подготовке (долгое удержание/ПКМ);
зловредные — в любой фазе (D02). «Уничтожить содержимое» папки реально
удаляет файлы после подтверждения и снимает 5 SLA; пустая папка — без штрафа
(D26).
6. Буфер приёма
Буфер = 4 + 2×уровня апгрейда буфера, максимум 8 (D05). Пакет тянут по таймеру в папку; таймеры пакетов в буфере идут только когда нет модалок (D03).
7. Запросы
Карточка запроса показывает имя требуемого файла (до 12 симв.) и
папку, а не только иконку типа; required — конкретные id (D01).
Файл может числиться в required нескольких запросов, но attached —
только одном; второй запрос видит его серым; при failed файла все
запросы, где он required, отменяются со штрафом (D06).
В окне «Отправка» максимум 4 видимых карточки; 5-й и далее — скролл,
карточки высотой 56 px (D05).
8. Meter/фазы и таймеры
Все фазы (приём, отправка, соединение, мини-игра, атаки) — на едином
Clock/HourDirector.tick(delta); пауза флагами (см. IMPLEMENTATION.md).
Полный буфер останавливает спавн приёма; открытые модалки/панели —
останавливают спавн приёма и таймеры пакетов, но таймер активного
запроса продолжается (D03). delta = min(delta, 0.1), авто-пауза при
потере фокуса окна, макс FPS 60 (D11).
Таймеры пакетов/запросов с grace первых часов: h1 1.5, h2 1.35,
h3 1.2, h4+ 1.0; формула (base − 0.5×(h−1))×grace + 4×timer_level
(D20). Итоговые значения:
| Час | Пакет, с | Запрос, с |
|---|---|---|
| 1 | 30 | 45 |
| 2 | 26.325 | 39.825 |
| 3 | 22.8 | 34.8 |
| 4 | 18.5 | 28.5 |
| 5–9 | 18 → 16 | 28 → 26 |
8.4. Мини-игры запросов (правило выбора)
coeff = {text:1.0, sound:2.0, photo:3.0, video:4.0}
difficulty = sum(coeff(required)) / n # средний коэффициент
пороги: <1.5 → text, <2.5 → sound, <3.5 → photo, иначе → video
MiniGame.start(type, difficulty)
9. Канал
Один общий ресурс для отправок. Фон и занятые слоты канал не грузят:
idle load = 0, в нагрузку входят только активные передачи (loading/
sending). Формула (D21):
load = Σ weight(active_transfers)
factor = max(1.0, load / CHANNEL_CAPACITY)
CHANNEL_CAPACITY = 80 + 25×channel_level
actual_time = base_time × factor
Апгрейд «Канал +25» (магазин, ×4, D13/D21) увеличивает capacity.
Полные параметры — data/balance.json → channel.
10. Мини-игры (детали)
Мини-игра — модалка; тип определяется правилом п. 8.4 (коэффициенты
text 1.0 / sound 2.0 / photo 3.0 / video 4.0, средняя difficulty,
пороги <1.5/<2.5/<3.5/иначе). MiniGame.start(type, difficulty).
Типы: text — h1, sound — h2, photo/video — h3+; продвинутые мини-игры —
мета complete_run, контента пока нет (D23). Esc в мини-игре — no-op (D10).
11. Полоска соединения
W = clamp(0.30 − 0.005×(hour−1) − 0.005×successes + 0.05×zone_upgrade_level, 0.18, 0.36);
скорости палочек 440/340/280 px/с; окна попадания ~130–200 мс;
апгрейд зоны учтён в формуле с кап 0.36 (D04). W — единственный
источник правды по зоне; других формул зоны нет (D05).
Esc в панели соединения — отмена: слот освобождается, запрос остаётся (D10).
Промах закрывает полоску: автоповтора нет, нужно снова нажать
«Соединиться». connected выставляется только после успешного прохождения
полоски (D22).
12. SLA и штрафы
Старт забега: SLA 128 / 200 (D19). Прирост: приём +0.5, отправка +1, отражённая атака +1 (D12). Потеря пакета — по типу: text 2, sound 4, photo 8, video 16 (D19). Отдельная таблица штрафов атак (D07): мусор −5, DDoS −15, фишинг −10, шифровальщик −10. Таймаут и подобные штрафы масштабируются: −(10 + 2×hour) (D12).
13. Экономика
Ожидаемый доход/час ≈ 500 / 800 / 1200 / 1800 / 2200 для часов 1 / 2 / 3 / 5 / 9 (D12). Цены магазина подняты так, что полный выкуп реалистичен к часу 8–9. Таблица сложности останавливается на часе 8; дальше те же значения +5 % к скорости спавна каждые 2 часа (D12).
14. Магазин
10 позиций (D13 + D19): 3-й слот (250), 4-й слот (450), буфер +2
(200, ×2), таймер пакетов +4 с (350, ×3), зона +5 % (300, ×3), канал +25
(250, ×4), секция (300, ×5), поиск (250), щит (400), SLA +24 (300, ×3).
Сканер и автосортировка — резерв (в прототип не входят). Открытия (D23):
магазин — с часа 2; поиск — мета survive_hour_3; щит — мета
survive_hour_5; в час магазин скрыт. Крестика у магазина нет: закрытие —
«Закрыть» или Esc.
15. Save
Сохранение между часами (SaveManager, без секретов, локально). В Web —
IndexedDB (user://save.json). Мета-открытия (meta_unlocks) сохраняются
между забегами: survive_hour_3 → поиск, survive_hour_5 → щит,
complete_run → продвинутые мини-игры (D23). Награды выдаются постепенно:
после 3-го, 5-го и 9-го часа; Game.run_meta_awards копит открытия забега,
итоги показывают «ОТКРЫТО: …».
16. Окончание забега
Победа — отработаны все 9 часов, затем итоги забега. Поражение — SLA ≤ 0 (смена не отработана), экран итогов. Переполнение склада за 9 часов недостижимо; механизм «конец забега по складу» остаётся как страховка (не основной конец): поражение, но пройденные 30+ часов засчитываются — отметка в итоговом отчёте (D02).
17. Состояния
Флаги, а не enum (D09):
FileItem.location∈ registry/folder/attached/locked/malicious/failed,attached_request,malicious_kind,lock_until;Request.slot_reserved,Request.connected,Request.minigame_active. Таблица переходов по таймерам (потеря таймера в приёме/соединении/мини-игре) —docs/IMPLEMENTATION.md.
18. Esc и паузирование (D10)
Час — пауза; мини-игра — no-op; панель соединения — отмена (слот
свободен, запрос остаётся); закрытие модалок — кнопкой/таймаутом. Магазин
закрывается «Закрыть» или Esc, без крестика (D24). Esc на итогах забега
ведёт в главное меню (D26).
19. Тексты UI
Все строки игрока берутся из data/strings_ru.json, ключи btn.*,
msg.*, ui.*, shop.*, attack.* (+ итаковые/панные/подсказки).
Нет оскорблений, русский язык, никакого мата.
20. Tells и читаемость
Видимые теллы (D08): пакет показывает расширение; шифровальщик —
красный квадрат 4×4; фишинг — client_id в формате id_XXXX с неверным
символом (например id_7F3К, кириллическая К) и серым аватаром.
locked/malicious файл остаётся кликабельным (уничтожение).
21. Арт и шрифты
- Основной шрифт — Handjet (OFL 1.1, полная кириллица; вариативный
wght 100–900, ELGR 1–2, ELSH 0–16; средняя ширина ≈0.36 em). (D15) - Press Start 2P — ТОЛЬКО крупные заголовки/логотип (слишком широкий: 17 символов не влезают в карточку 132 px).
- Pixelify Sans — удалён из темы (неполная кириллица: нет
О,П). - Допустимые кегли: 10 / 12 / 16 / 24 (Handjet узкий, 10 разрешён).
- UI v2 «Kaleidos»: тёплая бумага
#E9E6DD, 1 px контуры, мягкие тени#00000018, скругления 3–4 px, бирюзовый акцент#2F7F8F; меньше декоративных подписей. «Спокойный фон» — плоскаяPAPERбез dither (D18, D24, D26). - Маскот БАЙТ ведёт короткий туториал первого часа (D24).
- VHS-эффект только на главном меню: процедурный слой
scripts/ui/vhs_overlay.gd(extends RefCounted), рисуется вMainMenu._drawдо текста; скан-линии 2 физ. px, слабая хроматика, зерно, виньетка, полоса. Без shader/screen texture, ввод не блокирует, текст резкий. Чекбокс «VHS-эффект» в настройках, HEADLESS не рендерит. Игровой UI без CRT; это не полноэкранный CRT (D14, D27). - Фон: тёплый бумажный дизеринг и светлые панели, без полноэкранного fbm; CRT убрать (D14, D18).
22. Аудио
18 SFX (интерфейс, приём/отправка, соединение, мини-игры, атаки, экономика,
итоги) + фоновый hum.wav (loop-friendly, 3 с); регулируемая громкость.
Ambient машинного зала — 4 WAV (audio/amb, PSU/fan/room/seek), генератор
audio/generate_ambient.py, autoload Ambient стартует после первого жеста
(web autoplay), поддерживает mute/паузу/громкость музыки (D28).
23. Порядок разработки
P0 (D16, уточнено D23): данные/реестр → слоты → приём/отправка → UI.
Типы: text h1, sound h2, photo/video h3+. Час 1 — без атак; junk/ddos —
h2, phishing — h3, ransomware — h4 (difficulty.attacks = 0,1,1,2,2,3,3,4,4).
Магазин — h2. Дальше: UI v2 «Kaleidos», прогрессивная мета, маскот-туториал,
полировка, Web-сборка.
24. Приёмка (definition of done)
Полный забег из 9 часов, 4 типа файлов, 4 атаки, 10 позиций магазина, правило выбора мини-игры и формула зоны исчерпываются через data, RU-тексты, save/load и мета-открытия, HTML5-сборка работает на itch.io.
25. v1.2 — delta (D18–D28)
- D18 — UI v2 «Kaleidos»: тёплая бумага, 1 px контуры, мягкие тени, скругления, бирюзовый акцент; окно 1920×1080, логический viewport 1280×720, fractional scale; меньше декоративного шума.
- D19 — SLA/экономика: старт 128/200; потеря пакета
text 2 / sound 4 / photo 8 / video 16; в магазине 10-я позицияSLA +24(300, ×3). - D20 — таймеры: grace
h1 1.5 / h2 1.35 / h3 1.2 / h4+ 1.0;(base − 0.5×(h−1))×grace + 4×timer_level; итоговая таблица — §8. - D21 — канал:
load = Σ weightтолько активных передач; idle 0 %;capacity = 80 + 25×level; фон и слоты не грузят. - D22 — TCP: промах закрывает полоску, автоповтора нет; повторное
«Соединиться»;
connectedтолько после успеха. - D23 — открытия/мета: магазин с часа 2; поиск/щит/
complete_run— после 3/5/9 часов;run_meta_awards+ «ОТКРЫТО» в итогах; типы text h1, sound h2, photo/video h3+; час 1 без атак, junk/ddos h2, phishing h3, ransomware h4;minigame_advanced— резерв без контента. - D24 — UX: уникальные имена папок, удаление пустых папок, автообновление, attached-галочки, магазин после часа без крестика, настройки на главном экране, маскот БАЙТ, спокойный фон = плоская бумага, реальное уничтожение содержимого (−5 SLA), Esc на итогах → меню.
- D25 — проверки/ревью:
scripts/run_all_tests.sh— 21 набор + parse-check, 22/22 PASS; MR-ревью OpenCodeoracle(opencode-go/deepseek-v4.1-flash, 74–90 с на dry-run). - D26 — фиксы аудита: calm-фон без серого
#C0C0C0, Esc на итогах → меню без soft-lock, реальное уничтожение папки, прогрессивная мета, час 1 без атак, честный резервminigame_advanced. - D27 — VHS главного меню: процедурный
vhs_overlay.gd(extends RefCounted) вMainMenu._draw; скан-линии, хроматика, зерно, виньетка, полоса. Без shader/screen texture, ввод не блокирует, текст резкий; только меню, чекбокс, HEADLESS без рендера. Не CRT на весь UI. - D28 — ambient machine room: 4 WAV в
audio/amb, генераторgenerate_ambient.py, autoload после первого жеста, mute/пауза/громкость; тестtest_ambient— 74/0.