LLM Wiki: Whiteout Survival Analytics
Последнее обновление: 2026-05-15
Этот файл хранит устойчивый контекст проекта для будущей разработки с LLM. Перед значимой доработкой нужно читать этот файл. Если в ходе работы фиксируется новая функция, бизнес-правило, техническое решение или изменение модели данных, этот файл нужно обновить в той же итерации.
Как Использовать Эту Wiki
- Использовать
docs/LLM_WIKI.mdкак основной источник проектного контекста. - Не хранить здесь временные debug-логи и одноразовые наблюдения.
- Фиксировать только то, что важно для следующих итераций разработки.
- Если решение устарело, обновлять существующий раздел, а не оставлять противоречивые записи.
- В описаниях использовать точные имена файлов, API, таблиц, views и полей.
Бизнес-Контекст
Назначение Проекта
Whiteout Survival Analytics — локальный веб-сервис для анализа платных паков в игре Whiteout Survival.
Проект нужен, чтобы игрок мог понять, какие внутриигровые предложения дают лучшую ценность за реальные деньги. Основная метрика — сколько полезности, выраженной в алмазах, игрок получает за один рубль.
Целевая Польза
Сервис должен помогать:
- сравнивать платные паки между собой;
- видеть лучшие предложения по
алм/₽; - понимать, из каких предметов складывается ценность пака;
- замечать паки с неполным расчетом;
- видеть, какие предметы пока не имеют подтвержденной ценности;
- принимать решение о покупке на основе расчетов, а не баннерных процентов игры.
Основные Пользовательские Сценарии
- Игрок открывает дашборд и быстро видит лучшие паки.
- Игрок переходит в рейтинг и фильтрует паки по цене, типу или приоритету.
- Игрок открывает карточку пака и проверяет состав наград.
- Игрок смотрит, какие категории предметов дают основной вклад в value.
- Игрок открывает раздел проблем данных и видит, какие предметы требуют оценки.
- Игрок добавляет новые данные в базу/definitions, после чего сервис пересчитывает рейтинг.
Бизнес-Метрика
Главная метрика:
diamonds_per_rub/алм/₽
Смысл метрики:
- все предметы переводятся в условную полезность в алмазах;
- общая полезность пака делится на цену в рублях;
- чем выше значение, тем выгоднее пак.
Шкала Приоритетов
Паки распределяются по приоритетам:
S+:diamonds_per_rub >= 200S:diamonds_per_rub >= 120A:diamonds_per_rub >= 100B:diamonds_per_rub >= 80C:diamonds_per_rub >= 50D: ниже50
Эта шкала используется как пользовательская подсказка для быстрого принятия решения. Она не заменяет детальный просмотр состава пака.
Неполные Расчеты
Если в паке есть предметы без подтвержденной ценности:
has_missingстановитсяtrue;total_valueсчитается как нижняя оценка;- реальная ценность пака может быть выше;
- такой пак должен быть явно помечен в интерфейсе.
Текущая бизнес-логика: лучше показать нижнюю оценку и флаг проблемы, чем скрыть пак полностью.
Источники Доверия
Для расчетов важны источники и доказательства:
- скриншоты паков;
- скриншоты магазинов/цен;
- каталог предметов Whiteout Survival Wiki для расширения справочника items;
- SQL-миграции с основаниями value;
- JSON-описания паков;
- комментарии к расчетам.
Скриншоты и заметки считаются частью доказательной базы. Если добавляются write-функции, нужно сохранять аудит изменения value.
Текущее Состояние Данных
Проверенное состояние API на 2026-05-15:
- паков:
29 - неизвестных value-ключей:
13 - предметов в
items:431 - предметов, импортированных только из Wiki с временным английским названием:
396 - активный источник:
postgres
Текущие неизвестные предметы показываются в разделе Проблемы данных.
Продуктовые Принципы
- Интерфейс должен быть аналитическим, плотным и табличным.
- Главный экран должен быть рабочим приложением, а не лендингом.
- Баннерные проценты игры не являются главным источником истины.
- Нужно явно показывать, когда расчет неполный.
- Пользователь должен быстро понять, почему один пак лучше другого.
- История value-предположений должна быть проверяемой.
Разработческий Контекст
Текущий Стек
- Frontend: React.
- Full-stack framework: Next.js App Router.
- Backend: Next.js route handlers.
- Database: PostgreSQL 16 через Docker Compose.
- Package manager: npm.
Текущие версии:
- Next.js:
^16.2.0, установленная версия наблюдалась как16.2.6. - React:
^19.2.0. - npm:
11.14.1, установлен локально в~/.local/bin/npm.
Локальные URL
Development server:
http://127.0.0.1:3000
Основной API:
GET /api/analytics
API для изображений:
GET /api/media/[...path]
Страница wiki на сайте:
/wiki
Страница просмотра Postgres:
/database
Страница каталога предметов:
/items
Карта Репозитория
Ключевые файлы и директории:
app/— Next.js App Router страницы и route handlers.app/page.jsx— серверная страница, загружает initial data.app/layout.jsx— корневой layout.app/api/analytics/route.js— JSON API аналитики.app/api/media/[...path]/route.js— безопасная отдача локальных изображений.app/database/page.jsx— отдельная страница просмотра таблиц и views Postgres.app/items/page.jsx— отдельная страница каталога предметов из Postgres.app/wiki/page.jsx— отдельная страница сайта с LLM Wiki.app/globals.css— стили приложения, адаптированные из макета.components/AnalyticsApp.jsx— основной интерактивный React UI.components/DatabaseBrowser.jsx— client-side вкладки и таблицы для просмотра Postgres.components/ItemsCatalog.jsx— client-side фильтры и таблица каталога предметов.components/WikiPage.jsx— server-rendered представлениеdocs/LLM_WIKI.md.lib/databaseBrowser.js— server-side чтение всехBASE TABLEиVIEWизpublic.lib/data.js— серверная загрузка, нормализация и fallback данных.lib/itemsCatalog.js— server-side чтениеitemsс value и usage-контекстом для/items.lib/postgres.js— общий Postgres pool factory и безопасное экранирование identifiers.lib/wiki.js— чтение Markdown-файла wiki для страницы/wiki.db/001_schema.sql— схема Postgres и основные views.db/*.sql— seed/value migrations.db/011_items_wiki_fields.sql— metadata-поля для предметов, импортированных или сопоставленных с Whiteout Survival Wiki.db/012_items_local_icons.sql— локальные иконки предметов, вырезанные из пользовательских скриншотов и подключенные черезitems.local_icon_url.db/013_essence_stones_value_from_vip_shop.sql— value дляessence_stonesпо VIP-магазину:1500алмазов за 1 камень эссенции.db/014_hero_items_ru_from_screenshots.sql— русские названия, описания, редкость и screenshot-source для Hero Items из пользовательских скриншотовIMG_6139–IMG_6147.db/015_speedup_atomic_durations.sql— нормализация ускорений в weekly speedup card до атомарной длительности предмета и регистрацияIMG_6148как справочника длительностей.db/016_speedup_duration_items.sql— ввод duration-items для ускорений: отдельные предметы по типу и длительности (speedup_general_1h,speedup_general_5mи т.д.) и миграцияpack_itemsна эти предметы.db/018_personalized_hero_widget_chest_temporary_value.sql— добавляетitem_values.value_qualityи временную оценку дляpersonalized_hero_widget_chest.db/021_mark_zero_value_analytics_items_needs_review.sql— правило качества: предметы, которые используются вpack_items, но не имеют активного value или имеют value0, получаютitems.recognition_status = needs_review.scripts/import_wiki_items.mjs— импорт каталога предметов сhttps://www.whiteoutsurvival.wiki/items/в Postgres.public/item-icons/— локальные изображения предметов, которые не имеют точного Wiki-сопоставления.packs/definitions/*.json— JSON-описания состава паков.packs/— скриншоты паков.screenshots/— дополнительные скриншоты и доказательства value.exports/pack_summary.csv— экспорт сводки и файловый fallback.docker-compose.yml— локальный Postgres.INSTALL.md— установка и эксплуатационные заметки.docs/LLM_WIKI.md— этот файл.
Поток Данных
Frontend не является источником истины.
Порядок работы:
app/page.jsxвызываетgetAnalyticsData()изlib/data.js.lib/data.jsсначала пытается прочитать Postgres.- Если Postgres доступен, данные берутся из
v_pack_summary,v_pack_item_values,packs,screenshotsиv_active_item_values. - Если Postgres недоступен, backend переключается на файловый fallback:
exports/pack_summary.csv,packs/definitions/*.jsonиdb/*.sql. - Frontend получает нормализованный JSON и выполняет только операции отображения.
Что Считается На Backend/Postgres
Канонические расчеты должны оставаться на backend/Postgres:
- общая ценность пака;
diamonds_per_rub;- признак неполного расчета;
- активные item values;
- total quantity предметов в паках;
- каноническая metadata паков и предметов.
Что Допустимо Считать На Frontend
Frontend может считать только UI-агрегации:
- фильтрация;
- сортировка;
- поиск;
- top-5 для отображения;
- среднее
diamonds_per_rubдля dashboard-контекста; - распределение по приоритетам;
- bars вклада категорий в деталке пака.
Frontend не должен дублировать формулы value как источник истины.
Текущий API Shape
GET /api/analytics возвращает:
{
packs: [
{
id,
name,
price,
currency,
date,
limit,
validity_days,
status,
priority,
banner,
total_value,
dia_per_rub,
has_missing,
comment,
tag,
source,
screenshot_path,
purchase_count,
instant,
daily,
lines
}
],
unknowns: [
{
key,
name,
category,
occurrences,
total_qty,
visual,
packs
}
],
lastImport,
source: {
kind,
label,
summaryPath,
definitionsPath
}
}Модель Базы Данных
Канонические таблицы:
screenshots— источники и metadata скриншотов.items— каталог предметов. Для интеграции с Whiteout Survival Wiki дополнительно используются поляname_en,wiki_slug,wiki_url,wiki_icon_url,wiki_category,wiki_imported_at. Для иконок из локальных скриншотов используетсяlocal_icon_url; UI беретlocal_icon_urlпервым, затемwiki_icon_url.item_values— value единицы предмета в алмазах. Полеvalue_qualityфиксирует качество оценки:unknown,temporary,derived,confirmed. Временные гипотезы не считать окончательными справочными ценами.- Для предметов из аналитики (
pack_items) статусconfirmedдопустим только когда у предмета есть ненулевой активный value. Если value отсутствует, неизвестен или равен0, ставитьitems.recognition_status = needs_review, даже если Wiki-сопоставление уже найдено. price_observations— наблюдения цен в магазинах.packs— metadata платных паков.pack_items— состав паков.
Канонические views:
v_active_item_values— последнее активное value по каждому предмету.v_pack_item_values— item-level contribution в рамках пака.v_pack_summary— pack-level summary.
UI Views
Сейчас приложение использует client-side route state, а не URL routes.
Текущие views:
dashboard— KPI, топ паков, распределение приоритетов, preview проблем данных.ranking— таблица рейтинга с сортировкой и фильтрами.detail— деталка пака: состав, metadata, скриншот, вклад категорий.missing— неизвестные предметы/value issues.source— статус источника данных и refresh control./database— отдельная URL-страница с вкладками по таблицам и views Postgres./items— отдельная URL-страница каталога предметов изitemsс фильтрами, wiki-иконками,name_ru/name_en, статусом, активным value и использованием в паках./wiki— отдельная URL-страница с содержимымdocs/LLM_WIKI.md.- В левом сайдбаре всех основных страниц показывается контактный блок: Telegram
@FlashSWкак ссылка наhttps://t.me/FlashSW; игровой контакт — сервер 43, никFlashbang. - Главная страница
/по умолчанию открываетДашборд; рейтинг доступен через/?view=ranking. Сайдбары URL-страниц должны показывать оба пункта:ДашбордиРейтинг паков; в dev-режиме такжеПроблемы данных(/?view=missing) иИсточник(/?view=source).Wiki проектанаходится в категорииДокументация, а не вДанные. - В production (
NODE_ENV=production) скрываются внутренние QA/служебные элементы: пунктыПроблемы данных,Источник,База данных, блок дашбордаТребуют внимания; прямой route/databaseвозвращаетnotFound().
Текущие Технические Решения
- Next.js используется как full-stack framework.
- Postgres — preferred source of truth.
- Файловый fallback намеренно сохранен для локальной работы без базы.
- Скриншоты отдаются через
/api/media/..., а не прямыми абсолютными путями. - Макет из
/Users/andrey/Downloads/whiteout survival.zipиспользован как визуальная и продуктовая основа. components/AnalyticsApp.jsxпока является крупным компонентом; при росте UI его стоит разнести на модули.- Wiki проекта доступна на сайте по
/wikiи server-side читает тот же файлdocs/LLM_WIKI.md; не дублировать содержимое wiki вручную в React-компонентах. - Просмотр базы доступен по
/database: страница читает всеBASE TABLEиVIEWиз схемыpublic, отображает каждый объект отдельной вкладкой и не выполняет write-действий. - Каталог предметов доступен по
/items: страница читает Postgres на сервере, а на frontend выполняет только поиск и UI-фильтрацию по категории, статусу и срезуВсе / Аналитика / Только Wiki. - В деталке пака строки состава используют
icon_urlизitems.wiki_icon_urlвместо текстовых сокращений категорий. Если иконки нет, UI оставляет прежний fallback с короткой подписью. - Раздел
Проблемы данныхтакже используетicon_urlиз неизвестных строк предметов. Если у предмета нетlocal_icon_urlилиwiki_icon_url, остается fallback?. - Каталог предметов можно расширять из Whiteout Survival Wiki через
scripts/import_wiki_items.mjs. Существующие предметы, которые уже участвуют в аналитике, не переименовываются: их русскоеname_ruсохраняется, а английское название и ссылка на Wiki пишутся в metadata-поля. Новые предметы, которых нет в текущей аналитике, добавляются с временным английскимname_ruи статусомwiki_imported_en. - Сопоставление Wiki
Gemsзакреплено за аналитическим предметомdiamonds(Алмазы). Не создавать отдельныйwiki_gems. - В категории Wiki
Hero Itemsзакреплены соответствия:Mythic General Hero Shard→hero_shard_universal_mythic,Mythic Exploration Skill Manual→skill_combat_manual_orange(Учебник боя оранжевый),Mythic Expedition Skill Manual→skill_development_manual_orange(Учебник развития оранжевый). Не сопоставлять Epic/Rare manuals и shards с мифическими/оранжевыми предметами. - Для Hero Items русские игровые названия подтверждены скриншотами:
Rare/Epic/Mythic Expedition Skill Manual→Редкий/Великий/Мифический инструктаж экспедиции,Rare/Epic/Mythic Exploration Skill Manual→Редкое/Великое/Мифическое руководство по освоению,Rare/Epic/Mythic General Hero Shard→Редкий/Великий/Мифический общий фрагмент героя. Сохранять этиname_ruпри повторных Wiki-импортах. - Сопоставление Wiki
Chief Staminaзакреплено заstamina_can_10(Банка выносливости (10)). Не создавать отдельныйwiki_chief_stamina. - Сопоставление Wiki
Lv.2 Custom Ressource Chestзакреплено заresource_box_personal_lv2(Персональный ящик с ресурсами ур. 2). Не создавать отдельныйwiki_lv_2_custom_ressource_chest. - Дополнительные сопоставления Wiki для предметов, используемых в паках:
Gold key→golden_key,Enhancement XP Component→gear_exp_component_100,Lucky Hero Gear Chest→weekly_gear_chest,Custom Mythic Hero Gear Chest→personalized_hero_widget_chest,Hardened Alloy→governor_gear_alloy,Design Plans→governor_gear_scroll,Charm Guide→talisman_manual,Charm Design→governor_talisman_scroll,Mystery Badge→secret_token(Тайный жетон),Blacksmith Stone→essence_stones. Не создавать отдельный предметblacksmith_stone: это ошибочное распознавание камней эссенции. personalized_hero_widget_chest(Персонализированный ящик с подделкой героя, WikiCustom Mythic Hero Gear Chest) имеет временный value3000алмазов за 1 шт. Формула: 5 таких ящиков стоят в 2 раза дороже 5 камней эссенции, значит 1 ящик =2 × essence_stones = 3000. Вitem_values.value_qualityэто значение помечено какtemporary; при появлении прямого магазина/скрина заменить подтвержденным value. В UI временные value показываются warning-цветом: в каталоге/itemsбейджвременно, в деталке пака подписьалм/ед.окрашена и имеет значок?с tooltip-обоснованием расчета.- Для ускорений каноническая модель разделена на две сущности. Базовые
speedup_general_min,speedup_construction_min,speedup_research_min,speedup_training_minхранят value одной минуты и не должны использоваться как строки состава новых паков. Вpack_itemsиспользуются duration-items:speedup_*_1m,speedup_*_5m,speedup_*_1h, а для общих ускорений такжеspeedup_general_3hиspeedup_general_8h. Ихvalue_per_unit_diamondsуже равен стоимости одной карточки ускорения нужной длительности, напримерspeedup_general_5m = 5 × speedup_general_min,speedup_general_1h = 60 × speedup_general_min. - После перехода на duration-items поле
pack_items.quantity_per_claimдля ускорений означает количество карточек ускорения, а не минуты. Длительность берется изitem_id. Например строкаspeedup_general_1hсquantity_per_claim = 20означает 20 предметов по 1 часу; строкаspeedup_general_5mсquantity_per_claim = 480означает 480 предметов по 5 минут. Не сворачивать такие строки обратно в один минутный предмет, иначе UI снова будет показывать13 алм/ед.вместо value одной карточки ускорения. - Для обобщенных speedup-предметов нет точного Wiki-сопоставления. Их иконки рисуются в UI как одна стрелка с фоном по длительности и маленьким маркером типа: общее, строительство, исследование, тренировка. Цвет фона:
1m— серый,5m— зеленый,1h— синий,3h— фиолетовый,8h— оранжевый. Компонент находится вcomponents/SpeedupIcon.jsxи переиспользуется в деталке пака, каталоге/itemsи новых местах, где нужно показать предмет ускорения. Нижнее число на игровых иконках является количеством предметов и не должно попадать в иконку. После подключения speedup-иконок228из250строк состава паков имеют изображение. Без уверенного сопоставления остаются синие/рассветные supply chest; не склеивать их с похожими Wiki-предметами без визуального подтверждения. essence_stones(Камни эссенции) имеет подтвержденный value1500алмазов за 1 шт. Источник: VIP-магазин, зафиксировано 2026-05-15.
Локальные Особенности Окружения
На машине был Node из Codex.app, но не было npm в PATH.
Установлено:
- npm path:
~/.local/bin/npm - npx path:
~/.local/bin/npx - npm version:
11.14.1
В ~/.zshrc добавлен ~/.local/bin.
У Node из Codex.app есть проблема с загрузкой native SWC на macOS из-за code-signing. Поэтому локальные scripts используют Webpack + wasm SWC:
{
"dev": "NEXT_TEST_WASM_DIR=./node_modules/@next/swc-wasm-nodejs next dev --webpack",
"build": "NEXT_TEST_WASM_DIR=./node_modules/@next/swc-wasm-nodejs next build --webpack"
}Не удалять этот workaround без проверки native SWC в текущем окружении.
Команды
Установка зависимостей:
npm installЗапуск dev-сервера:
npm run dev -- --hostname 127.0.0.1 --port 3000Сборка:
npm run buildПроверка API:
curl -sS http://127.0.0.1:3000/api/analyticsPostgres helpers:
./scripts/db.sh start
./scripts/db.sh summary
./scripts/db.sh export-packs
./scripts/db.sh psql
./scripts/db.sh stopИмпорт предметов из Whiteout Survival Wiki:
node scripts/import_wiki_items.mjsПравила Для Будущей Разработки
- Перед изменениями читать
docs/LLM_WIKI.md. - При добавлении новой фичи обновлять эту wiki.
- При изменении data flow, API или schema обновлять соответствующие разделы.
- Если добавляются write-действия, продумать audit trail.
- Не переносить канонические value-формулы на frontend.
- Для новых расчетов сначала определить, где источник истины: Postgres, backend или UI-only aggregation.
Ближайший Backlog
Потенциальные следующие задачи:
- Перевести client-side route state на URL routes для shareable detail pages.
- Добавить CSV export из таблицы рейтинга.
- Добавить CRUD для pack definitions и item values.
- Добавить admin action: отметить value предмета как
0с audit note. - Добавить сравнение Postgres-данных и file fallback.
- Добавить authentication перед write-действиями.
- Добавить тесты для
lib/data.js. - Добавить loading/error states для refresh API.
- Разбить
components/AnalyticsApp.jsxна более мелкие компоненты.
Принципы Реализации
- Postgres остается каноническим источником расчетов.
- Fallback-режим должен быть детерминированным и заметным пользователю.
- UI должен быть плотным, аналитическим и удобным для сравнения.
- Скриншоты и source notes являются доказательной базой.
- Любое изменение value должно быть проверяемым.