Files
x0gp/server/web/README.md
T
x0gp 978d36c505 feat(server): initial implementation
This commit captures the full server code accumulated across
several development sessions. It includes the following layers,
applied in roughly this order during development:

1. Base infrastructure
   - cmd/poc-server HTTP+WebSocket server, /health, /stats
   - internal/transport wire types (Envelope + all message types)
   - internal/catalog, internal/realtime, internal/stats
   - internal/storage/postgres with migrations 001-004
   - .env, .env.example, docker-compose, Dockerfile, scripts/

2. Swagger documentation
   - go get github.com/swaggo/http-swagger
   - swag init produces docs/docs.go
   - /swagger/index.html UI, /swagger/doc.json spec
   - annotations on health/stats/ws and catalog handlers

3. Races API
   - internal/races/{store,service,keyset,types}.go
   - migration 005_races.sql: finished_races, race_plans, race_queue
   - GET /api/races with keyset pagination, status filter
   - GET /api/races/upcoming
   - POST /api/races/queue/join, GET, DELETE
   - POST/GET /api/races/plans, DELETE /{id}
   - lobby.RaceMeta simplification (no host_id/host_name)

4. Races seeder
   - internal/races/seed with deterministic generator
   - --seed-races / --reset CLI flags in main.go
   - 30 finished + 5 live + 5 plans + 4 queue entries

5. Drivers and clans
   - internal/drivers, internal/clans (CRUD, validation)
   - migration 008_drivers_clans.sql
   - /api/clans and /api/drivers endpoints
   - 3-letter uppercase nickname/tag validation
   - lobby.DriverMeta: Nickname, AvatarURL, ClanID, ClanTag

6. Podium
   - internal/transport.RacePodiumEntry
   - lobby.SetDriverProfile for in-memory metadata sync
   - migration 007_podium.sql (podium JSONB column)
   - seeder populates top-3 per finished race

7. Live races persistence
   - migration 009_live_persistence.sql: live_races,
     live_race_drivers, lobby_drivers
   - internal/races/live_store.go: LiveStore with write-side
     mirror for lobby.Service mutations
   - Service.collectLive and Upcoming read from Postgres
   - main.go RestoreFromDB rehydrates lobby on startup

8. Unify live + finished into one races table
   - migration 010_unify_races.sql: rename finished_races to
     races, expand status CHECK, merge live rows
   - PgStore now hosts both write paths; LiveStore is a
     thin facade implementing lobby.Persistence
   - seeder resetAll drops only finished/cancelled rows and
     race_plans / race_queue / lobby_drivers

Each layer is consistent on its own; cross-layer changes are
visible in the file history. A future refactor may split this
commit into the per-stage boundaries listed above.
2026-06-22 22:01:09 +04:00

83 lines
3.6 KiB
Markdown
Raw 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.
# x0gp · PoC web client
Минимальный vanilla JS клиент для проверки PoC-сервера из этой же папки.
Без сборки, без зависимостей — открывается в браузере.
## Запуск
Вариант А — открыть файл напрямую:
```bash
# Windows
start web/index.html
# Linux
xdg-open web/index.html
# macOS
open web/index.html
```
> Некоторые браузеры не разрешают `WebSocket` к чужим origin со страницы,
> открытой по `file://`. Если что — поднимите мини-сервер (вариант Б).
Вариант Б — раздать через тот же poc-server:
В `cmd/poc-server/main.go` есть TODO — добавить `http.FileServer` для `web/`.
После этого клиент будет доступен по `http://localhost:8080/`.
Вариант В`python -m http.server`:
```bash
cd server/web
python -m http.server 5173
# открыть http://localhost:5173/
```
## Подключение к серверу
1. Запустите `poc-server` (см. корневой `server/README.md`).
2. В UI клиента проверьте `WS URL` — по умолчанию `ws://localhost:8080/ws`.
3. Укажите `driver_id` (например `driver-1`).
4. **Connect****Join race**.
5. Управление:
- `W` / `↑` — газ
- `S` / `↓` — тормоз
- `A` / `←` — руль влево
- `D` / `→` — руль вправо
- `Space` — ручник
6. На canvas появится ваша машинка (синяя) и машинки других подключённых
драйверов (оранжевые).
## Что смотреть
- **tick Hz** в верхней панели — частота приходящих `race_snapshot`.
Должно держаться ~30 Hz.
- **rtt** — round-trip ping/pong, в PoC без сети это 0–2 ms.
- **seq** — растёт с каждым отправленным сообщением.
- **Телеметрия** — speed/heading/lap/sector вашей машинки.
- **Лог** — все входящие/исходящие сообщения (кроме ping/pong).
## Что PoC делает
- Открывает WebSocket, шлёт `client_hello`.
- По кнопке— `join_race` / `leave_race`.
- Каждые 33 ms (≈30 Hz) шлёт `input_state` (throttle/brake/steer/handbrake).
- Каждые 1000 ms шлёт `ping` для измерения RTT.
- Получает `race_snapshot` и рисует все машинки на канвасе.
- Получает `input_ack`, `race_event`, `correction`, `error` и логирует их.
## Что PoC НЕ делает
- Нет предиктивного сглаживания (interpolation/extrapolation) — увидите
«дёрганье», это нормально для PoC.
- Нет клиент-сайд предикции — добавим, когда появится настоящая модель физики.
- Нет тач-управления для мобильных — клавиатура только.
- Нет авторизации, биллинга, чата — это всё вне PoC.
## Что дальше
- Когда `proto/` будет сгенерирован в Go и JS — заменим JSON на protobuf.
- Подключим `gRPC-Web` или бинарный WS-фрейминг.
- Добавим предиктивный слой и интерполяцию.
- Добавим мобильный layout (touch steering + pedals).