mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-07 11:54:59 -04:00
Update operator documentation
This commit is contained in:
252
README.md
252
README.md
@@ -1,92 +1,224 @@
|
||||
# 🏎️ box-box
|
||||
# box-box
|
||||
|
||||

|
||||
> "Box, box. Box, box." — Every F1 race engineer, ever.
|
||||
|
||||
> "Box, box. Box, box." — Every F1 Race Engineer, ever.
|
||||
**box-box** is a Formula 1 dashboard in Go with two surfaces:
|
||||
|
||||
**⚠️ Disclaimer: This project is currently in a pre-beta state.** Features may be incomplete, and you might encounter bugs as we fine-tune the engine.
|
||||
- **Web UI (primary)** — React + TypeScript SPA for Race Hub analytics, local data coverage, and live timing.
|
||||
- **TUI (preserved)** — Bubble Tea terminal app with standings, calendar, driver profiles, official live timing, track map, battles, pit window, and replay.
|
||||
|
||||
**box-box** is a high-performance Formula 1 Terminal User Interface (TUI) built for fans who live in the command line. Get real-time standings, race calendars, and deep-dive driver stats without ever leaving your terminal.
|
||||
Historical Web data is **local-first** in a SQLite domain database (ingested from OpenF1). **Live timing** uses the official F1 SignalR feed via the Go server; the React app reads `/api/v1/live/*`, not OpenF1 directly.
|
||||
|
||||

|
||||

|
||||
For architecture, phase history, and design rationale, see [documentations/refactor/README.md](documentations/refactor/README.md).
|
||||
|
||||
## ✨ Features
|
||||
## How it fits together
|
||||
|
||||
- 🏆 **Live Standings**: Keep track of the Driver and Constructor Championships.
|
||||
- 📅 **Race Calendar**: The full 2025 schedule at your fingertips.
|
||||
- 🏎️ **Race Details**: Deep dive into session results, starting grids, and lap data.
|
||||
- 👤 **Driver Profiles**: Detailed stats for every driver on the grid.
|
||||
- 🔴 **Official Live Timing**: Real-time F1 timing tower via the official SignalR feed — gaps, intervals, tyre age, sector times, DRS, and track status.
|
||||
- ⚔️ **Battle Tracker**: Auto-detects on-track duels within DRS range with gap sparklines and tyre strategy comparison.
|
||||
- 🔧 **Pit Window Calculator**: Predicts rejoin position if a driver pits now, using per-circuit pit loss times.
|
||||
- ⏪ **Race Replay**: Lap-by-lap scrubber for completed races — relive the whole field's evolution with pit annotations and race control messages.
|
||||
- 🗺️ **ASCII Track Map**: Live car positions on a terminal-rendered track outline, team-coloured.
|
||||
- 🔌 **Offline-ish**: Fast, lightweight, and powered by the wonderful [OpenF1 API](https://openf1.org).
|
||||
| Layer | Role |
|
||||
| --- | --- |
|
||||
| **OpenF1 REST** | Backfill and ingestion source; optional paid tier via `OPENF1_API_KEY`. Also powers the TUI’s on-demand reads and HTTP cache. |
|
||||
| **Domain SQLite** (`boxbox.db`) | Local store for meetings, sessions, Race Hub datasets, and navigation APIs used by the Web UI. |
|
||||
| **HTTP cache SQLite** (`cache.db`) | TTL cache for OpenF1 responses (TUI and legacy paths). Separate from the domain DB. |
|
||||
| **Official F1 SignalR** | Live timing bridge in `internal/live`, exposed to Web (SSE) and TUI. |
|
||||
| **Go server** | `cmd/main.go` — TUI, `--web` API + static SPA, or CLI ingestion. |
|
||||
| **React frontend** | `frontend/` — production build served from `frontend/dist` when present. |
|
||||
|
||||
## 🚀 Quick Start
|
||||
The Web UI should call **local-first Go APIs** (`/api/v1/...`). Do not add direct OpenF1 reads in the frontend.
|
||||
|
||||
### Prerequisites
|
||||
## Prerequisites
|
||||
|
||||
- [Go](https://go.dev/doc/install) 1.21 or higher.
|
||||
- [Go](https://go.dev/doc/install) (see `go.mod` for the module version)
|
||||
- [Node.js](https://nodejs.org/) 18+ and npm (Web UI dev, unit tests, Playwright)
|
||||
- Internet for ingestion and TUI OpenF1 calls
|
||||
- For E2E / visual tests: `npx playwright install` (Chromium) after `npm install` at the repo root
|
||||
|
||||
### Installation
|
||||
## Install
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/AmanTahiliani/box-box.git
|
||||
cd box-box
|
||||
|
||||
# Build and run
|
||||
go run cmd/main.go
|
||||
npm install # Playwright and repo-level test scripts
|
||||
npm install --prefix frontend # Vite + React app
|
||||
```
|
||||
|
||||
## 🎮 Controls
|
||||
## Build
|
||||
|
||||
```bash
|
||||
go build -o box-box ./cmd/main.go
|
||||
npm run build --prefix frontend # writes frontend/dist (gitignored)
|
||||
```
|
||||
|
||||
## Run — TUI (default)
|
||||
|
||||
```bash
|
||||
go run ./cmd/main.go
|
||||
# or: ./box-box
|
||||
```
|
||||
|
||||
Logs go to `box-box.log` in the project directory so the terminal stays clean.
|
||||
|
||||
### TUI keybindings
|
||||
|
||||
| Key | Action |
|
||||
| --- | --- |
|
||||
| `1` | Switch to **Home** |
|
||||
| `2` | Switch to **Standings** |
|
||||
| `3` | Switch to **Calendar** |
|
||||
| `4` | Switch to **Race Details** |
|
||||
| `5` | Switch to **Drivers** |
|
||||
| `6` | Switch to **Live Timing** |
|
||||
| `7` | Switch to **Track Map** |
|
||||
| `tab` / `shift+tab` | Next / Previous tab |
|
||||
| `j`/`↓` | Navigate down |
|
||||
| `k`/`↑` | Navigate up |
|
||||
| `enter` | Select/Inspect item |
|
||||
| `b` / `esc` | Go back / collapse |
|
||||
| `s` | Toggle sector times (Live tab) |
|
||||
| `b` | Toggle Battle Tracker (Live tab) |
|
||||
| `p` | Toggle Pit Window Calculator (Live tab) |
|
||||
| `r` | Enter Race Replay (Race Detail tab, Race sessions) |
|
||||
| `←`/`h` · `→`/`l` | Scrub laps in Replay |
|
||||
| `1`–`7` | Home, Standings, Calendar, Race Detail, Drivers, Live, Track Map |
|
||||
| `tab` / `shift+tab` | Next / previous tab |
|
||||
| `j`/`k`, `enter`, `b`/`esc` | Navigate, select, back |
|
||||
| `s`, `b`, `p` | Live: sectors, battles, pit window |
|
||||
| `r` | Race replay (Race Detail, race sessions) |
|
||||
| `y` | Cycle season year |
|
||||
| `q` / `ctrl+c` | Exit |
|
||||
| `q` / `ctrl+c` | Quit |
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
## Run — Web (Go serves API + built React)
|
||||
|
||||
- **[Bubble Tea](https://github.com/charmbracelet/bubbletea)**: The TUI engine.
|
||||
- **[Lipgloss](https://github.com/charmbracelet/lipgloss)**: For that sleek F1 styling.
|
||||
- **[Bubbles](https://github.com/charmbracelet/bubbles)**: Common TUI components.
|
||||
- **[OpenF1 API](https://api.openf1.org)**: The data source (Free, no API key needed).
|
||||
|
||||
## 🚥 Development
|
||||
|
||||
Want to tinker under the hood?
|
||||
Build the frontend first, then start web mode. Go walks up from the cwd to find `frontend/dist/index.html`; if missing, it serves embedded legacy assets.
|
||||
|
||||
```bash
|
||||
# Run tests
|
||||
go test ./...
|
||||
|
||||
# View API integration tests (requires internet)
|
||||
go test -v ./internal/api
|
||||
npm run build --prefix frontend
|
||||
go run ./cmd/main.go --web
|
||||
# → http://localhost:8080
|
||||
```
|
||||
|
||||
## 📜 License
|
||||
Use a specific domain database or port:
|
||||
|
||||
```bash
|
||||
go run ./cmd/main.go --web --db ~/.local/share/box-box/boxbox.db --port 8080
|
||||
```
|
||||
|
||||
## Run — Web dev (Vite + Go API)
|
||||
|
||||
Vite proxies `/api` to the Go server. Set `BOXBOX_API_PORT` to match the Go `--port`.
|
||||
|
||||
**Terminal 1 — API (seeded DB is enough for UI work without ingesting):**
|
||||
|
||||
```bash
|
||||
go run ./scripts/seed-e2e-db/main.go --db /tmp/boxbox-dev.db
|
||||
BOXBOX_DISABLE_LIVE=1 go run ./cmd/main.go --web --db /tmp/boxbox-dev.db --port 18080
|
||||
```
|
||||
|
||||
**Terminal 2 — frontend:**
|
||||
|
||||
```bash
|
||||
BOXBOX_API_PORT=18080 npm run dev --prefix frontend
|
||||
# default Vite port 5173 → http://localhost:5173
|
||||
```
|
||||
|
||||
`BOXBOX_DISABLE_LIVE=1` skips starting the SignalR bridge (used in CI and local UI work).
|
||||
|
||||
## Web routes
|
||||
|
||||
| Route | Purpose |
|
||||
| --- | --- |
|
||||
| `/` | **Command Center** — local season/weekend coverage, focus weekend, quick links to Live / Race Hub / Data Library |
|
||||
| `/race-hub?session_key=<key>` | **Race Hub** — classification, grid, strategy, positions, laps, race control, weather (from local DB) |
|
||||
| `/data-library` | **Data Library** — ingestion coverage and suggested CLI commands |
|
||||
| `/live` | **Live Timing** — timing tower and race control via SSE when a session is live |
|
||||
|
||||
Example after seeding: `http://localhost:5173/race-hub?session_key=9472`
|
||||
|
||||
## Ingest historical data (OpenF1 → domain DB)
|
||||
|
||||
Ingestion is a **CLI mode** on the same binary. Only one of `--ingest-year`, `--ingest-meeting`, or `--ingest-session` may be set per run.
|
||||
|
||||
```bash
|
||||
# Season: discover and store meeting metadata (2023+)
|
||||
go run ./cmd/main.go --ingest-year 2025
|
||||
|
||||
# Full race weekend: all sessions + Race Hub datasets
|
||||
go run ./cmd/main.go --ingest-meeting 1229
|
||||
|
||||
# Single session only
|
||||
go run ./cmd/main.go --ingest-session 9472
|
||||
|
||||
# Preview without writing
|
||||
go run ./cmd/main.go --dry-run --ingest-meeting 1229
|
||||
|
||||
# Custom DB path (default: ~/.local/share/box-box/boxbox.db)
|
||||
go run ./cmd/main.go --ingest-meeting 1229 --db /tmp/boxbox.db
|
||||
```
|
||||
|
||||
Use **`--ingest-meeting`** for a complete weekend. **`--ingest-year`** lists meetings for the season; ingest meetings individually or by weekend as needed. Optional analytics fetches may partially fail without aborting the whole run.
|
||||
|
||||
## `OPENF1_API_KEY`
|
||||
|
||||
```bash
|
||||
export OPENF1_API_KEY=your_key_here
|
||||
go run ./cmd/main.go --web
|
||||
```
|
||||
|
||||
Without a key, the free OpenF1 tier is used. A key may be required for paid-tier behavior (e.g. live session access during API lockouts). Ingestion and TUI calls use the same client.
|
||||
|
||||
## Local files
|
||||
|
||||
| Path | Purpose |
|
||||
| --- | --- |
|
||||
| `~/.local/share/box-box/boxbox.db` | Domain database (default `--db`) |
|
||||
| `~/.cache/box-box/cache.db` | OpenF1 HTTP response cache (TUI / client) |
|
||||
| `box-box.log` | TUI application log (project root) |
|
||||
| `frontend/dist/` | Production React build (**gitignored** — build locally, do not commit) |
|
||||
| `.playwright/*.db` | Seeded DBs for automated tests |
|
||||
|
||||
Web mode logs to **stderr**.
|
||||
|
||||
## Tests and QA
|
||||
|
||||
### Go (targeted packages)
|
||||
|
||||
```bash
|
||||
go test ./internal/live ./internal/models ./internal/store ./internal/ingest ./internal/query ./internal/web
|
||||
```
|
||||
|
||||
All packages: `go test ./...`
|
||||
|
||||
OpenF1 integration tests (network, rate-limit aware): `go test -v ./internal/api`
|
||||
|
||||
### Frontend unit tests and build
|
||||
|
||||
```bash
|
||||
npm --prefix frontend test -- --run
|
||||
npm --prefix frontend run build
|
||||
```
|
||||
|
||||
### E2E (Vite dev proxy + seeded API)
|
||||
|
||||
Starts seeded Go on port `18080` and Vite on `15173` (see `playwright.config.ts`).
|
||||
|
||||
```bash
|
||||
npx playwright install # first time only
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
### E2E production (Go serves `frontend/dist`)
|
||||
|
||||
```bash
|
||||
npm run test:e2e:prod
|
||||
```
|
||||
|
||||
### Visual regression (screenshots)
|
||||
|
||||
```bash
|
||||
npm run test:visual # dev proxy stack
|
||||
npm run test:visual:prod # production serving (canonical baselines)
|
||||
|
||||
# after intentional UI changes
|
||||
npm run test:visual:update
|
||||
npm run test:visual:prod:update
|
||||
```
|
||||
|
||||
Snapshots live under `tests/visual/__snapshots__/`.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- **Live timing** only works when F1 is broadcasting timing data; there is no guaranteed live session for local dev.
|
||||
- **E2E / visual tests** use `BOXBOX_DISABLE_LIVE=1` and seeded SQLite — they do not exercise full SignalR live behavior.
|
||||
- **`frontend/dist`** is generated output; build before production web mode or `test:e2e:prod`.
|
||||
- **TUI historical views** still use OpenF1 on demand with the HTTP cache; the Web UI’s local-first model does not fully replace the TUI yet.
|
||||
- **`--ingest-year`** stores season meetings, not full session datasets — use `--ingest-meeting` or `--ingest-session` for Race Hub data.
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Aman Tahiliani](https://github.com/AmanTahiliani)
|
||||
|
||||
---
|
||||
*Disclaimer: This project is unofficial and not associated with Formula 1 or the FIA in any way.*
|
||||
|
||||
*Unofficial project; not associated with Formula 1 or the FIA.*
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# box-box Refactor Brief
|
||||
|
||||
## Operator guide
|
||||
|
||||
For day-to-day build, run, ingest, test, and Web route commands, use the
|
||||
top-level [README.md](../../README.md). This directory is for architecture,
|
||||
phasing, and research — not the first stop for new contributors.
|
||||
|
||||
## Purpose
|
||||
|
||||
This directory captures the planning baseline for the next major evolution of
|
||||
|
||||
Reference in New Issue
Block a user