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

10 KiB
Raw Permalink Blame History

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

{
  "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

{
  "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

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 (минимум)

{
  "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 может запускать)

# Из корня проекта
godot --headless --script scripts/data/build_catalog.gd --seed 42
# → генерирует assets/data/skins.json (15k записей)
# → проверяет соответствие якорям ±10%
# → выходит с кодом 0 если ок, 1 если рассогласование

В .forgejo/workflows/build.yml (когда дойдём)

Добавить step:

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