mirror of
https://github.com/Horizontal42/f1-telemetry.git
synced 2026-11-11 01:52:08 +03:00
update docs: new folder structure, session rename, prompts, lang flag
This commit is contained in:
parent
35dc9df1de
commit
925109d0ec
4 changed files with 68 additions and 50 deletions
|
|
@ -13,14 +13,14 @@ telemetry/
|
|||
segments.py Lap -> corners & straights. Zone detection + numbering.
|
||||
corner_metrics.py Per-zone number crunching: braking point, lock/spin, coast, temps.
|
||||
resample.py Adaptive distance grid + channel interpolation for the trace.
|
||||
report_common.py Header block, legend strings, md_table, token_estimate, atomic write.
|
||||
report_common.py Header block, legend strings, md_table, token_estimate, load_prompt, atomic write.
|
||||
report_technique.py Driving report (corners, straights, cost, trace).
|
||||
report_setup.py Car report (setup, balance, tyres, brakes, suspension, phases).
|
||||
report_compare.py Two+ laps side by side, per-corner and cumulative delta.
|
||||
report_race.py A folder of laps: lap times, stints, wear, thermals, ERS.
|
||||
rename.py Insert lap number into filenames; skip already-processed.
|
||||
gui.py tkinter window; runs generation/rename on a worker thread.
|
||||
prompts/ Russian LLM prompts, one per report mode.
|
||||
report_race.py A folder of laps: lap times (with position), stints, wear, thermals, ERS.
|
||||
rename.py Insert session type + lap number (e.g. P1_L7) into filenames; skip processed.
|
||||
gui.py tkinter window; per-mode browse memory; runs generation/rename on a worker thread.
|
||||
prompts/ LLM analysis prompts, ru/ and en/ subdirectories, one file per mode. Auto-appended to every report.
|
||||
tests/ pytest suite + fixture laps.
|
||||
```
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ tests/ pytest suite + fixture laps.
|
|||
2. **`parser.load_lap`** reads the file as UTF-8 and splits it into four meta blocks (session, track, setup) plus the 108-channel telemetry table. Channel names are normalised by stripping the ` [unit]` suffix. Every column that is entirely zero is dropped — the game writes many dead channels (see Gotchas).
|
||||
3. **`segments.detect_corners`** walks the samples, marks each as "cornering" when `|Steer| > STEER_ON` or `Brake > BRAKE_ON`, merges adjacent zones closer than `MERGE_GAP_M`, drops zones shorter than `MIN_LEN_M`, and numbers what's left T1..Tn by distance. For each zone it calls **`corner_metrics.corner_from_zone`**, which extracts the braking point, apex, gear, full-throttle point, peak brake/gLat, relative lock%/spin%, coast distance, and rear tyre temperature peak. `straights` fills the gaps between corners.
|
||||
4. **`resample.adaptive_points`** builds a distance grid that is dense inside (and on approach to) corners and sparse on straights — the step sizes default to the lap's own median sample spacing via `auto_steps`, so denser raw telemetry yields a denser trace. **`sample_at`** interpolates each channel onto that grid (nearest-sample for discrete channels like Gear/DRS).
|
||||
5. The **`report_<mode>.generate`** function assembles Markdown from `report_common` helpers (`header_block`, `md_table`, `legend`) and the data above, then calls **`report_common.write_report`**, which writes atomically (temp file + `os.replace`) and returns `(abs_path, tokens)`.
|
||||
5. The **`report_<mode>.generate(…, lang)`** function assembles Markdown from `report_common` helpers (`header_block`, `md_table`, `legend`) and the data above. It then calls **`load_prompt(mode, lang)`** to read the matching prompt from `prompts/<lang>/<mode>.md` and appends it after a `---` separator. Finally **`write_report`** writes atomically (temp file + `os.replace`) and returns `(abs_path, tokens)`.
|
||||
6. **`__main__`** prints that path and `~N tokens (budget 60k)`. The **GUI** shows the same tuple in its log instead of printing.
|
||||
|
||||
## Adding things
|
||||
|
|
@ -53,6 +53,6 @@ tests/ pytest suite + fixture laps.
|
|||
|
||||
**The setup row has a trailing comma** (an empty `FuelLoad` tail field in some exports). The parser drops trailing empties so the setup dict has no blank-string key.
|
||||
|
||||
**Rename idempotency hinges on the `L<digits>` token.** `lap_token_present` is the single source of truth for "already processed". Changing the token format means changing both `insert_lap_token` and `lap_token_present` together, or rename stops being safe to re-run.
|
||||
**Rename idempotency hinges on TWO tokens.** A file is considered processed only when both a session token (`P1`, `Q2`, `R`, …, matched by `_SESSION_PAT`) and a lap token (`L<digits>`) are present in the stem. Both `session_token_present` and `lap_token_present` are the joint source of truth — changing either token format means updating both the insert and the presence-check functions together.
|
||||
|
||||
**Reports go next to the input, not next to the program.** `report_path` derives the `reports/` directory from the *input CSV's* folder; `race` mode computes it from the race folder's parent. Moving the tool does not move where reports land.
|
||||
**Reports go next to the input, not next to the program.** `report_path` derives the `reports/` directory from the *input CSV's* folder. `race` mode puts the report inside the race session folder (`<race_dir>/reports/`). Moving the tool does not move where reports land.
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ telemetry/
|
|||
segments.py Lap -> повороты и прямые. Детекция зон + нумерация.
|
||||
corner_metrics.py Подсчёт по зоне: точка торможения, lock/spin, накат, температуры.
|
||||
resample.py Адаптивная сетка по дистанции + интерполяция каналов для трассы.
|
||||
report_common.py Шапка, строки легенды, md_table, token_estimate, атомарная запись.
|
||||
report_common.py Шапка, строки легенды, md_table, token_estimate, load_prompt, атомарная запись.
|
||||
report_technique.py Отчёт о пилотировании (повороты, прямые, расход, трасса).
|
||||
report_setup.py Отчёт о машине (сетап, баланс, шины, тормоза, подвеска, фазы).
|
||||
report_compare.py Два+ круга рядом, дельта по поворотам и накопленная.
|
||||
report_race.py Папка кругов: лаптаймы, стинты, износ, тепло, ERS.
|
||||
rename.py Вставка номера круга в имена файлов; пропуск обработанных.
|
||||
gui.py Окно tkinter; генерация/переименование в рабочем потоке.
|
||||
prompts/ Русские промпты для LLM, по одному на режим.
|
||||
report_race.py Папка кругов: лаптаймы (с позицией), стинты, износ, тепло, ERS.
|
||||
rename.py Вставка типа сессии + номера круга (P1_L7); пропуск обработанных.
|
||||
gui.py Окно tkinter; память последней папки по режиму; генерация/переименование в потоке.
|
||||
prompts/ Промпты LLM, подпапки ru/ и en/, по одному файлу на режим. Добавляются в конец каждого отчёта.
|
||||
tests/ Набор pytest + фикстуры-круги.
|
||||
```
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ tests/ Набор pytest + фикстуры-круги.
|
|||
2. **`parser.load_lap`** читает файл как UTF-8 и делит на четыре мета-блока (session, track, setup) плюс таблицу телеметрии на 108 каналов. Имена каналов нормализуются срезанием суффикса ` [unit]`. Каждая колонка, целиком состоящая из нулей, отбрасывается — игра пишет много мёртвых каналов (см. «Подводные камни»).
|
||||
3. **`segments.detect_corners`** проходит по сэмплам, помечает сэмпл как «в повороте», если `|Steer| > STEER_ON` или `Brake > BRAKE_ON`, сливает соседние зоны с зазором меньше `MERGE_GAP_M`, отбрасывает зоны короче `MIN_LEN_M` и нумерует оставшиеся T1..Tn по дистанции. Для каждой зоны вызывается **`corner_metrics.corner_from_zone`**, которая извлекает точку торможения, апекс, передачу, точку полного газа, пик тормоза/gLat, относительные lock%/spin%, дистанцию наката и пик температуры задней шины. `straights` заполняет промежутки между поворотами.
|
||||
4. **`resample.adaptive_points`** строит сетку по дистанции — плотную внутри поворотов (и на подходе) и редкую на прямых; шаги по умолчанию берутся из медианного интервала сэмплов круга через `auto_steps`, так что более плотная сырая телеметрия даёт более плотную трассу. **`sample_at`** интерполирует каждый канал на эту сетку (ближайший сэмпл для дискретных вроде Gear/DRS).
|
||||
5. Функция **`report_<режим>.generate`** собирает Markdown из помощников `report_common` (`header_block`, `md_table`, `legend`) и данных выше, затем вызывает **`report_common.write_report`**, которая пишет атомарно (временный файл + `os.replace`) и возвращает `(abs_path, tokens)`.
|
||||
5. Функция **`report_<режим>.generate(…, lang)`** собирает Markdown из помощников `report_common` (`header_block`, `md_table`, `legend`) и данных выше. Затем вызывает **`load_prompt(mode, lang)`**, которая читает промпт из `prompts/<lang>/<mode>.md` и добавляет его после разделителя `---`. Финальный текст пишется через **`write_report`** атомарно (временный файл + `os.replace`), возвращается `(abs_path, tokens)`.
|
||||
6. **`__main__`** печатает путь и `~N tokens (budget 60k)`. **GUI** показывает тот же кортеж в логе вместо печати.
|
||||
|
||||
## Как добавлять
|
||||
|
|
@ -53,6 +53,6 @@ tests/ Набор pytest + фикстуры-круги.
|
|||
|
||||
**Строка сетапа заканчивается лишней запятой** (пустой хвост `FuelLoad` в части экспортов). Парсер отбрасывает пустые хвостовые поля, чтобы в словаре сетапа не было ключа с пустой строкой.
|
||||
|
||||
**Идемпотентность rename держится на токене `L<цифры>`.** `lap_token_present` — единственный источник истины для «уже обработан». Смена формата токена требует менять `insert_lap_token` и `lap_token_present` вместе, иначе rename перестаёт быть безопасным для повторного запуска.
|
||||
**Идемпотентность rename держится на ДВУХ токенах.** Файл считается обработанным только при наличии обоих: токена типа сессии (`P1`, `Q2`, `R`, … — совпадение по `_SESSION_PAT`) и токена `L<цифры>`. `session_token_present` и `lap_token_present` — совместный источник истины. Смена формата любого токена требует обновить и функцию вставки, и функцию проверки одновременно.
|
||||
|
||||
**Отчёты выходят рядом с входом, а не рядом с программой.** `report_path` выводит папку `reports/` из папки *входного CSV*; режим `race` считает её от родителя папки гонки. Перемещение инструмента не меняет, куда попадают отчёты.
|
||||
**Отчёты выходят рядом с входом, а не рядом с программой.** `report_path` выводит папку `reports/` из папки *входного CSV*. Режим `race` кладёт отчёт внутрь папки сессии (`<race_dir>/reports/`). Перемещение инструмента не меняет, куда попадают отчёты.
|
||||
|
|
|
|||
43
README.md
43
README.md
|
|
@ -6,8 +6,8 @@ Turns raw F1 22 lap telemetry into compact Markdown reports you can paste into a
|
|||
|
||||
```bash
|
||||
# from the tool/ folder
|
||||
python -m telemetry technique ../zandvoort_P_L7_74.074_ferrari.csv
|
||||
# -> ../reports/zandvoort_P_L7_74.074_ferrari_technique.md (~34k tokens)
|
||||
python -m telemetry technique "races/Zandvoort/Practice/zandvoort_P1_L7_74.074_ferrari.csv"
|
||||
# -> races/Zandvoort/Practice/reports/zandvoort_P1_L7_74.074_ferrari_technique.md (~35k tokens)
|
||||
```
|
||||
|
||||
Or just double-click `run-gui.bat` and click **Generate report**.
|
||||
|
|
@ -29,21 +29,27 @@ Five modes. Four produce reports, one renames files.
|
|||
| `setup` | one lap | **what** is set — balance (US/OS), tyre temps, brakes, suspension rake & roll |
|
||||
| `compare` | two+ laps | **where** one lap is faster — per-corner and cumulative delta |
|
||||
| `race` | a folder of laps | the whole race — pace, stint degradation, tyre wear, ERS per lap |
|
||||
| `rename` | files/folder | insert the lap number into each filename (`..._74.074_...` → `..._L7_74.074_...`) |
|
||||
| `rename` | files/folder | insert session type and lap number into each filename (`..._74.074_...` → `..._P1_L7_74.074_...`) |
|
||||
|
||||
Reports include a legend explaining every column, so the LLM understands the data without extra prompting. Ready-made analysis prompts live in [`prompts/`](prompts/) — one per mode.
|
||||
Reports include a legend explaining every column and have the analysis prompt auto-appended at the end — just drop the file into an LLM. Prompts come in RU and EN; pick with `--lang en` on the CLI or the language radio in the GUI.
|
||||
|
||||
### Folder layout
|
||||
|
||||
The program lives in `tool/`; your telemetry sits one level up, output lands next to it:
|
||||
|
||||
```
|
||||
Telemetry/
|
||||
zandvoort_P_L7_74.074_ferrari.csv <- raw laps here
|
||||
races/
|
||||
Zandvoort_Race_2026/ <- one folder per race (for `race` mode)
|
||||
reports/ <- generated reports land here
|
||||
tool/ <- this repository
|
||||
Zandvoort/
|
||||
Practice/ <- CSVs go here after renaming
|
||||
zandvoort_P1_L7_74.074_ferrari.csv
|
||||
reports/ <- technique/setup/compare reports land here
|
||||
Qualifying/
|
||||
zandvoort_Q1_L3_74.897_ferrari.csv
|
||||
reports/
|
||||
Race/
|
||||
zandvoort_R_L7_74.152_ferrari.csv
|
||||
reports/
|
||||
Race_race.md <- race mode report
|
||||
tool/ <- this repository
|
||||
telemetry/
|
||||
prompts/
|
||||
run-gui.bat
|
||||
|
|
@ -51,16 +57,19 @@ Telemetry/
|
|||
|
||||
## Handy things
|
||||
|
||||
**GUI** — double-click `run-gui.bat` (or `run-gui.pyw` for no console window, or run `python -m telemetry gui`). Pick a mode, browse to the file/folder, click Generate. The **Rename unprocessed** button adds lap numbers to files that don't have them yet and leaves the rest alone.
|
||||
**GUI** — double-click `run-gui.bat` (or `run-gui.pyw` for no console window, or run `python -m telemetry gui`). Pick a mode and language (RU/EN), browse to the file/folder, click Generate. The file browser remembers the last used directory per mode. The **Rename unprocessed** button adds the session type and lap number to files that don't have them yet and leaves the rest alone.
|
||||
|
||||
**CLI** — from the `tool/` folder:
|
||||
|
||||
```bash
|
||||
python -m telemetry technique ../lap.csv
|
||||
python -m telemetry setup ../lap.csv
|
||||
python -m telemetry compare ../lap_a.csv ../lap_b.csv
|
||||
python -m telemetry race ../races/Zandvoort_Race_2026
|
||||
python -m telemetry rename ../races/Zandvoort_Race_2026 # or individual files
|
||||
python -m telemetry technique races/Zandvoort/Practice/lap.csv
|
||||
python -m telemetry setup races/Zandvoort/Practice/lap.csv
|
||||
python -m telemetry compare races/Zandvoort/Practice/lap_a.csv races/Zandvoort/Practice/lap_b.csv
|
||||
python -m telemetry race races/Zandvoort/Race
|
||||
python -m telemetry rename races/Zandvoort/Practice # or individual files
|
||||
|
||||
# choose prompt language (default: ru)
|
||||
python -m telemetry technique races/Zandvoort/Practice/lap.csv --lang en
|
||||
```
|
||||
|
||||
Every report run prints the output path and a token estimate:
|
||||
|
|
@ -70,7 +79,7 @@ C:\...\Telemetry\reports\lap_technique.md
|
|||
~33834 tokens (budget 60k)
|
||||
```
|
||||
|
||||
**Rename only touches unprocessed files.** A file is "processed" once its name contains an `L<number>` token, so re-running rename is safe and idempotent.
|
||||
**Rename only touches unprocessed files.** A file is "processed" once its name contains both a session token (`P1`, `Q2`, `R`, …) and an `L<number>` token. Re-running rename on the same folder is safe.
|
||||
|
||||
## Input format
|
||||
|
||||
|
|
|
|||
43
README.ru.md
43
README.ru.md
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
```bash
|
||||
# из папки tool/
|
||||
python -m telemetry technique ../zandvoort_P_L7_74.074_ferrari.csv
|
||||
# -> ../reports/zandvoort_P_L7_74.074_ferrari_technique.md (~34k токенов)
|
||||
python -m telemetry technique "races/Zandvoort/Практика/zandvoort_P1_L7_74.074_ferrari.csv"
|
||||
# -> races/Zandvoort/Практика/reports/zandvoort_P1_L7_74.074_ferrari_technique.md (~35k токенов)
|
||||
```
|
||||
|
||||
Или просто двойной клик по `run-gui.bat` и кнопка **Generate report**.
|
||||
|
|
@ -29,21 +29,27 @@ python -m telemetry technique ../zandvoort_P_L7_74.074_ferrari.csv
|
|||
| `setup` | один круг | **что** настроено — баланс (US/OS), температуры шин, тормоза, rake и крен подвески |
|
||||
| `compare` | два+ круга | **где** один круг быстрее — дельта по поворотам и накопленная |
|
||||
| `race` | папка кругов | вся гонка — темп, деградация в стинтах, износ резины, ERS по кругам |
|
||||
| `rename` | файлы/папка | вставить номер круга в имя файла (`..._74.074_...` → `..._L7_74.074_...`) |
|
||||
| `rename` | файлы/папка | вставить тип сессии и номер круга в имя файла (`..._74.074_...` → `..._P1_L7_74.074_...`) |
|
||||
|
||||
Отчёты содержат легенду с пояснением каждой колонки — LLM понимает данные без дополнительных подсказок. Готовые промпты для анализа лежат в [`prompts/`](prompts/) — по одному на режим.
|
||||
Отчёты содержат легенду с пояснением каждой колонки, а промпт анализа добавляется в конец файла автоматически — достаточно скинуть файл в LLM. Промпты доступны на RU и EN; выбирается флагом `--lang en` в CLI или переключателем языка в GUI.
|
||||
|
||||
### Структура папок
|
||||
|
||||
Программа живёт в `tool/`; телеметрия — на уровень выше, отчёты выходят рядом с ней:
|
||||
|
||||
```
|
||||
Telemetry/
|
||||
zandvoort_P_L7_74.074_ferrari.csv <- сырые круги здесь
|
||||
races/
|
||||
Zandvoort_Race_2026/ <- по папке на гонку (для режима `race`)
|
||||
reports/ <- сюда выходят отчёты
|
||||
tool/ <- этот репозиторий
|
||||
Zandvoort/
|
||||
Практика/ <- CSV-файлы после переименования
|
||||
zandvoort_P1_L7_74.074_ferrari.csv
|
||||
reports/ <- отчёты technique/setup/compare
|
||||
Квалификация/
|
||||
zandvoort_Q1_L3_74.897_ferrari.csv
|
||||
reports/
|
||||
Гонка/
|
||||
zandvoort_R_L7_74.152_ferrari.csv
|
||||
reports/
|
||||
Гонка_race.md <- отчёт режима race
|
||||
tool/ <- этот репозиторий
|
||||
telemetry/
|
||||
prompts/
|
||||
run-gui.bat
|
||||
|
|
@ -51,16 +57,19 @@ Telemetry/
|
|||
|
||||
## Полезное
|
||||
|
||||
**GUI** — двойной клик по `run-gui.bat` (или `run-gui.pyw` без окна консоли, либо `python -m telemetry gui`). Выбери режим, укажи файл/папку, нажми Generate. Кнопка **Rename unprocessed** добавляет номера круга к файлам, у которых их ещё нет, и не трогает остальные.
|
||||
**GUI** — двойной клик по `run-gui.bat` (или `run-gui.pyw` без окна консоли, либо `python -m telemetry gui`). Выбери режим и язык промпта (RU/EN), укажи файл/папку, нажми Generate. Диалог открывается в последней использованной папке для каждого режима отдельно. Кнопка **Rename unprocessed** добавляет тип сессии и номер круга к файлам, у которых их ещё нет, и не трогает остальные.
|
||||
|
||||
**CLI** — из папки `tool/`:
|
||||
|
||||
```bash
|
||||
python -m telemetry technique ../lap.csv
|
||||
python -m telemetry setup ../lap.csv
|
||||
python -m telemetry compare ../lap_a.csv ../lap_b.csv
|
||||
python -m telemetry race ../races/Zandvoort_Race_2026
|
||||
python -m telemetry rename ../races/Zandvoort_Race_2026 # или отдельные файлы
|
||||
python -m telemetry technique races/Zandvoort/Практика/lap.csv
|
||||
python -m telemetry setup races/Zandvoort/Практика/lap.csv
|
||||
python -m telemetry compare races/Zandvoort/Практика/lap_a.csv races/Zandvoort/Практика/lap_b.csv
|
||||
python -m telemetry race races/Zandvoort/Гонка
|
||||
python -m telemetry rename races/Zandvoort/Практика # или отдельные файлы
|
||||
|
||||
# выбор языка промпта (по умолчанию: ru)
|
||||
python -m telemetry technique races/Zandvoort/Практика/lap.csv --lang en
|
||||
```
|
||||
|
||||
Каждый прогон печатает путь к отчёту и оценку токенов:
|
||||
|
|
@ -70,7 +79,7 @@ C:\...\Telemetry\reports\lap_technique.md
|
|||
~33834 tokens (budget 60k)
|
||||
```
|
||||
|
||||
**Rename трогает только необработанные файлы.** Файл считается обработанным, как только в имени появляется токен `L<номер>` — поэтому повторный запуск безопасен и идемпотентен.
|
||||
**Rename трогает только необработанные файлы.** Файл считается обработанным, когда в имени есть оба токена: тип сессии (`P1`, `Q2`, `R`, …) и `L<номер>`. Повторный запуск безопасен.
|
||||
|
||||
## Входной формат
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue