farming-simulator/canon/DATA_PIPELINE.md
Dmitrii Bykov 15260532b6
All checks were successful
Godot CI / Import + smoke test (push) Successful in 30s
canon: COLLECTIONS_TIMELINE + CS2_TRANSITION + DATA_PIPELINE
3 новых файла отвечают на 'полный каталог рынка':

I. COLLECTIONS_TIMELINE.md - лимитизация ~50 коллекций по статусам:
- Active/Legacy/Rare/Retired/Contraband/Event-only
- 50+ кейсов 2013-2026 с релиз-датами и ценами 2020/2026 (древние Bravo/Hydra → CapyFarm → кампания Fracture/Broken Fang → эпилог Anubis/Kilowatt/Harlequin 2026)
- 15 non-case коллекций (Cobblestone retired, Train вернулся CS2 2025)
- 4 экспоната лимитизации: M4A4 Howl Contraband (изъят 23.06.2014 за 7 нед), Dragon Lore (Cobble retired 2018), Hydra Case 6 мес дроп, EMS Katowice 2014 Holo $100k+
- Триггеры: drop pool removal/map removed/operation ends/plagiarism/CS2 transition/Care Package rotation янв 2026

II. CS2_TRANSITION.md - точно 27.09.2023:
- Source 2 движок, новые viewmodels, smoke physics
- Map pool: Train убран 2017, вернулся апр 2025 CS2
- Premier mode заменил Wingman+Competitive, CS Rating numerical
- Trust Factor 2.0 + Prime интегрированы → multi-HWID = плохие матчи
- Перенос инвентаря: 100% автомат, float теперь виден в Inspect сразу
- Влияние на рынок: первые 2 недели ±30-50% паника, AWP Dragon Lore $3500→$5000 за день
- Влияние на панели: FSM/DM обновили 1-2 мес, CapyFarm закрылась
- Влияние на тиры фермеров: тир 4 (industrial) пострадал больше всех (Care Package требует play на каждом акке)
- Канон-сцена: 27.09.2023 в TG чате 'Свои' паника, octofarm пост 'не паникуем'

III. DATA_PIPELINE.md - техническое решение НЕ делать 10к ручных записей:
- 3-слойная архитектура: 150 якорей (из HISTORICAL_STEAM_ITEMS.md) + процедурный генератор (15-25к записей) + опц реалтайм Steam Market API скрейпинг
- JSON-структуры skins.json/cases.json/collections_timeline.json
- Скрипт skins_generator.gd в Godot (формула base × wear × status × time × jitter)
- MVP для пролога: 15-20 скинов в skins_prolog.json вручную
- Полный каталог — для эпохи 1 (9 класс)
- Build через godot --headless --script build_catalog.gd, в Forgejo CI
- Размер dataset: 25k записей ~10-15МБ JSON, приемлемо для Steam-инди
2026-05-24 16:51:37 +03:00

275 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DATA_PIPELINE.md — Техническое решение каталога предметов
> **Проблема:** ~10 000 скинов CS:GO × 5 wear × 10+ лет = миллионы записей цен. Вручную невозможно.
>
> **Решение:** 3-слойная архитектура. Якоря вручную + процедурка + опц. скрейпинг.
---
## I. АРХИТЕКТУРА — 3 СЛОЯ
### Слой 1: ЯКОРЯ (вручную, 100-150 шт)
**Источник:** `canon/HISTORICAL_STEAM_ITEMS.md` от research-агента (4800 слов).
**Что покрыто:**
- 30 iconic скинов с реальными ценами по wear/year (Dragon Lore, Howl, Fire Serpent, etc.)
- 50 кейсов с датами выхода и ценами по кварталам
- 13 Australium weapons с ценами 2020-2024
- 15+ Unusual TF2 effects с типовыми ценами
- PUBG sezony S7-S25 с pass-ценами
- Все CS:GO Operations с pass-ценами и дроп-листами
**Используется как:** **ground truth** для калибровки процедурного слоя.
### Слой 2: ПРОЦЕДУРНЫЙ ГЕНЕРАТОР (формула, генерирует тысячи)
**Источник:** `canon/STEAM_ITEMS.md` секция VII (формула ценообразования) + `canon/COLLECTIONS_TIMELINE.md` (статус коллекций по датам).
**Алгоритм:**
```
для каждого скина в каталоге:
base = base_price[rarity_tier] # из COLLECTIONS_TIMELINE
status = collection_status_on_date # active/legacy/retired/contraband
для каждого wear FN/MW/FT/WW/BS:
price = base
× wear_multiplier[wear] # 0.3-4.0 по STEAM_ITEMS.md
× status_multiplier[status] # 1.0-30.0 (retired = expensive)
× time_curve(date, release) # 0.2-5.0
× stattrak_or_souvenir # 1.0-3.0
× pattern_jitter() # 0.85-1.15
если skin in ANCHORS (якорь из слоя 1):
скорректировать формулу чтобы совпадало с якорем ±10%
```
**Что генерируется:** 3000-5000 уникальных скинов × 5 wear = 15-25 тыс записей.
**Хранится как:** `assets/data/skins.json` — генерируется один раз при build-е.
### Слой 3: РЕАЛТАЙМ-СКРЕЙПИНГ (опционально, для энтузиастов)
**Источник:** Steam Market public API.
**Endpoint:** `https://steamcommunity.com/market/priceoverview/?currency=5&appid=730&market_hash_name=<skin>` (currency=5 = RUB)
**Что даёт:** реальная цена на сегодня для любого скина.
**Использование в игре:**
- В пред-альфа: НЕ используется (offline-only)
- В будущей версии: опциональная "live-pricing" механика для игроков с интернетом
**Скорость:** Steam ограничивает ~20 req/sec → 30к скинов = 25 минут на полный апдейт.
---
## II. JSON-СТРУКТУРА
### Файл `assets/data/skins.json`
```json
{
"version": "1.0.0",
"generated_at": "2026-05-24T15:00:00Z",
"base_date": "2020-08-21",
"skins": [
{
"id": "awp_dragon_lore",
"weapon": "AWP",
"name": "Dragon Lore",
"collection": "The Cobblestone Collection",
"rarity": "covert",
"category": "rifle_sniper",
"released": "2014-07-01",
"collection_status_timeline": [
{"from": "2014-07-01", "status": "active"},
{"from": "2018-04-01", "status": "rare"},
{"from": "2023-09-27", "status": "legacy_cs2"}
],
"base_price_rub_2020": 90000,
"wear_multipliers": {
"FN": 2.5,
"MW": 1.7,
"FT": 1.0,
"WW": 0.7,
"BS": 0.5
},
"stattrak_available": true,
"souvenir_available": true,
"souvenir_multiplier": 3.0,
"low_float_supported": true,
"is_anchor": true
}
]
}
```
### Файл `assets/data/cases.json`
```json
{
"cases": [
{
"id": "fracture_case",
"name": "Fracture Case",
"released": "2020-08-06",
"collection_status_timeline": [
{"from": "2020-08-06", "status": "active"},
{"from": "2023-09-27", "status": "legacy_cs2"}
],
"key_cost_rub_2020": 190,
"drop_weights": {
"mil_spec": 0.7992,
"restricted": 0.1598,
"classified": 0.0320,
"covert": 0.0064,
"knife": 0.0026
},
"knife_pool": ["bayonet", "karambit", "m9_bayonet", "..."]
}
]
}
```
### Файл `assets/data/collections_timeline.json`
Структурированный экспорт `canon/COLLECTIONS_TIMELINE.md` в JSON.
### Файл `assets/data/cs2_transition.json`
События 27.09.2023: смена UI, market shock, panel updates.
---
## III. ГЕНЕРАТОР В GODOT
### Скрипт `scripts/data/skins_generator.gd`
```gdscript
extends Node
const ANCHORS_JSON = "res://assets/data/anchors.json" # из HISTORICAL_STEAM_ITEMS.md
const COLLECTIONS_JSON = "res://assets/data/collections_timeline.json"
func generate_full_catalog(seed_value: int) -> Array:
var rng = RandomNumberGenerator.new()
rng.seed = seed_value
var anchors = _load_anchors()
var collections = _load_collections()
var catalog = []
for collection in collections:
for skin_template in _generate_skins_for_collection(collection, rng):
for wear in ["FN", "MW", "FT", "WW", "BS"]:
var entry = _build_entry(skin_template, wear, collection, rng)
catalog.append(entry)
return catalog
func get_price(skin_id: String, wear: String, on_date: String) -> int:
# Расчёт цены любого скина на любую дату
var skin = _find_skin(skin_id)
var collection_status = _status_on_date(skin.collection, on_date)
var time_curve = _time_curve(skin.released, on_date)
return skin.base_price \
* skin.wear_multipliers[wear] \
* _status_multiplier(collection_status) \
* time_curve \
* _daily_jitter(on_date, skin_id)
```
### Скрипт `scripts/data/market_simulator.gd`
- Симулирует ежедневные флуктуации ±5-15%
- Среда -10% (канон-механика)
- 5.12.2023 крах -10-20%
- 24.02.2022 курс-скачок +30-50% в RUB
- CS2 transition 27.09.2023 спайк ±30-50%
---
## IV. УПРОЩЁННАЯ ВЕРСИЯ ДЛЯ MVP (пролога)
### Что нужно в Акте 1-13 пролога
- **Australium Wrench** (1 скин) — захардкоден в коде
- **Кейс кесе го Prime** (после покупки игры) — выпадает что-то от Fracture Case (свежий на 21.08.2020). 5-7 возможных скинов рандомно.
- **Кейс Пабаджи** — Survivor Crate, 5-7 косметик из реала
**ИТОГО для пролога:** ~15-20 скинов в JSON, не тысячи. Полный генератор — для основной игры.
### Файл `assets/data/skins_prolog.json` (минимум)
```json
{
"australium_wrench": { ... },
"fracture_case_skins": [
"ak47_legion_of_anubis",
"m4a4_tooth_fairy",
"ump45_gold_bismuth",
"..."
],
"pubg_survivor_crate_items": [
"trench_coat",
"leather_jacket",
"..."
]
}
```
---
## V. PIPELINE BUILD
### CLI команда (Forgejo Actions может запускать)
```bash
# Из корня проекта
godot --headless --script scripts/data/build_catalog.gd --seed 42
# → генерирует assets/data/skins.json (15k записей)
# → проверяет соответствие якорям ±10%
# → выходит с кодом 0 если ок, 1 если рассогласование
```
### В `.forgejo/workflows/build.yml` (когда дойдём)
Добавить step:
```yaml
- name: Build catalog
run: godot --headless --script scripts/data/build_catalog.gd --seed 42
```
---
## VI. КОГДА ЧТО ДЕЛАТЬ
| Этап | Что |
|---|---|
| **Сейчас (Акт 1 пролога)** | Не нужен полный каталог. 15-20 скинов руками в `skins_prolog.json`. |
| **Акт 12-13 пролога (3 фарм-акка)** | Добавить 10-20 базовых скинов кесе го/Пабаджи |
| **Эпоха 1 (9 класс)** | Полный каталог: ~3000 скинов через генератор. Реализация `skins_generator.gd`. |
| **Эпоха 3 (10 класс, окт 2021)** | Добавить Riptide коллекции |
| **Эпилог (CS2 transition)** | State-machine "era": до/после 27.09.2023 |
| **Финальный релиз** | Опц. реалтайм-скрейпинг для энтузиастов |
---
## VII. РАЗМЕР DATASET
| Слой | Записей | Размер JSON |
|---|---|---|
| Anchors (вручную) | 150 | ~50 КБ |
| Процедурный CS:GO/CS2 | 15 000 | ~5-8 МБ |
| TF2 (Mannco + Australium + Unusual) | 8 000 | ~3-5 МБ |
| PUBG | 2 000 | ~1 МБ |
| **ИТОГО** | **25 000** | **~10-15 МБ** |
**Размер билда:** +15МБ — приемлемо (Godot project = 50 МБ базы, итого ~65МБ — без проблем для Steam $5 игры).
---
## VIII. ТРЕНИНГ-СЛОЙ (опционально, для будущего)
ML-модель которая обучается на anchors + Steam Market API данных за месяц → может предсказывать цены любого скина с точностью ±10-15%. Запускается в фоне игры, обновляет dataset.
**Не нужно для пролога.** Опция для долгосрочного развития.
---
## TBD
- Конкретный JSON-формат якорей (выкатим при первой генерации)
- Карта rarity → base_price (5-7 уровней)
- Какие именно 30 iconic скинов кодируем как якоря (взять из HISTORICAL_STEAM_ITEMS.md)
- Логика state-machine "CS-era" (до/после 27.09.2023)