Unofficial Formula 1 race strategy analysis: true pace from clean laps, tyre degradation, pit cycles and a measured Chaos Index, with the laps excluded and a confidence label on every estimate. Season
翻譯準備中
運動與健身Python · TypeScriptGitHub @MarcGuitart上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Pit Wall Engineer is a motorsport analytics platform combining Formula 1 telemetry processing, data visualisation and AI reasoning to replicate the workflow of a race engineer. It analyses historical F1 sessions (2023-2025), extracting insights from telemetry, strategy and race data through an AI engineering assistant.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗pitwallengineer.com · Docs: free, PRO and live mode · Leer en español
Pit Wall Engineer turns raw Formula 1 timing data into the analysis a race engineer would run: true pace, tyre degradation, pit impact, race phases, chaos, weather crossovers and lap telemetry.
During a session, Live mode puts the same lens on the feed as it arrives: timing, track map, car data, tyres, strategy, race control and team radio.
Every number carries its confidence and the size of the sample behind it. A reading that cannot be judged yet is labelled as such, never rounded into certainty.
A ranking built on four laps is not a ranking built on forty. The product treats that as a design rule, not a footnote.
| Module | Strategic question |
|---|---|
| True Pace | Who was actually fast once pit laps, safety car laps and outliers are removed? |
| Tyre degradation | Where did each stint start to fall off, and how steep was it? |
| Pit impact | Did the stop gain or lose positions, and was the undercut real? |
| Race phases | What was the race doing on each lap: sorting, pit window, safety car reset, final push? |
| Chaos Index | How disordered was the race, and on which lap did it peak? |
| DRS trains | When were cars stuck in a group, and for how long? |
| Weather crossovers | Who was early, on time or late when the track changed? |
| Clean air value | What was running free worth against running in traffic? |
| Lap charts | How did lap times and gaps evolve, lap by lap? |
| Telemetry replay | How did the drivers differ through speed, throttle, brake, gear and g on one lap? |
| Race control and radio | What did the stewards and the pit wall say, and when? |
| Recon Lap | What does this circuit ask of a car: where are the braking zones, how much speed is lost, in which gear, over how much height? |
| AI race engineer | What does this specific race say about a question I have? |
A session view with eight tabs: Timing, Track & car, Strategy, Predictions (only when the live server sends a projection), Race control & radio, Lap charts, Engineer AI and Feed.
Practice and qualifying sessions get their own profile: best laps, sector colours, long runs and session status.
The telemetry tab replays one lap per driver, fastest clean or representative, with speed, throttle, brake, gear and g forces against the circuit map.
/recon/<circuit> previews a circuit before its Grand Prix from the previous season's pole lap: the line the car took in 3D with its recorded height, as a tour of its braking zones, one at a time. The arrow keys or the buttons move to the previous or next zone with the camera still on it, and a panel shows what the lap's car data measured there: entry speed, minimum speed, braking distance, time on the brakes, gear at the minimum and height change. It is labelled approximate, with the data's sampling rate and the reference session. The whole lap plays only when asked, never by itself. A minimap and a height profile show where the zone sits.
data/circuit_lengths.json, the same table the lap telemetry uses.Captured from a published historical race by scripts/readme_shots.py. The Recon Lap shot is Interlagos, braking zone 1.
| Race analysis | Lap telemetry | Chaos Index and key decisions |
São Paulo 2024 race, captured from the live site. A Live mode capture follows during a race weekend.
OpenF1 (REST + MQTT)
|
|-- Analysis API (FastAPI, Render)
| async OpenF1 client (httpx, semaphore, retry)
| per-session JSON cache, immutable for past races
| RaceTimeline (one canonical object shared by every service)
| services: pace, tyre, pit, chaos, drs, weather, crossover,
| race phase, clean air, decisions, notes, DNA
| FastF1 telemetry from cache (fallback for the telemetry tab)
| AI chat: Ollama locally, Groq in production
|
|-- Recorder (Render, persistent disk)
| holds the MQTT subscription, writes the capture,
| archives finished captures to Cloudflare R2
|
|-- Live server (Render)
| second MQTT subscription, one snapshot, SSE to browsers
|
|-- GitHub Actions
| publish-race: publishes each finished race into backend/cache/
| telemetry-openf1: builds the race's lap telemetry and uploads it to R2
|
Cloudflare R2
live capture archive; lap telemetry files behind a public domain
|
Frontend (Next.js 14 on Netlify)
historical analysis, Live mode, Recon Lap, docs, access settings
publish-race commits each finished race into backend/cache/ and then queues telemetry-openf1 for it, which writes to R2 without a commit or a deploy. A commit to main is a deploy, which is why the Render blueprint uses build filters. See docs/DEPLOY.md and docs/telemetry-openf1.md.| Seasons | Includes | |
|---|---|---|
| Free | 2023 and 2024 | Full analysis, every session type, no account |
| PRO | 2025 onwards and the current season | The above plus Live mode, EUR 2.99 per month |
PRO_PROMO_CODES (code and end instant) can be redeemed by anyone, in any case, until it ends. A banner shows the code with a countdown and a field to redeem it. A redeemed code gives PRO for PRO_PROMO_TOKEN_TTL_DAYS days, and keeps working after the code itself ends. The code lives in the API's environment, never in this repo.OPEN_ACCESS_UNTIL on the API and the live server opens every PRO season and Live mode to everyone until that instant. Past it, everything is as before without a deploy.Details at pitwallengineer.com/docs.
Requirements: Python 3.11, Node.js 18 or later. Ollama with llama3.1:8b is optional and only used by the AI chat.
# Backend
cd backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
uvicorn app.main:app --reload # http://localhost:8000
# Frontend
cd frontend
cp .env.local.example .env.local
npm install
npm run dev # http://localhost:3000
Tests:
cd backend && pip install -r requirements-dev.txt && pytest
cd frontend && npm test
cd backend
pip install -r requirements-live.txt
python scripts/live_server.py --replay 9636 --replay-speed 0.02
# or replay a capture recorded by the recorder:
python scripts/live_server.py --replay-capture <capture dir> --speed 60
cd ../frontend
NEXT_PUBLIC_LIVE_URL=http://localhost:8099 npm run dev
cd backend
python scripts/openf1_telemetry.py --sessions <session_key> --out telemetry-out
# FastF1 fallback cache, as before:
python scripts/precompute_telemetry.py --sessions <session_key> --drivers VER,NOR,LEC,PIA,RUS
Point NEXT_PUBLIC_TELEMETRY_URL at a server for telemetry-out to read the files locally; leave it empty to use the API.
cd frontend
python3 scripts/recon/build_recon.py Interlagos --for-year 2026 # writes public/recon/interlagos.json
Both generators read OpenF1 with OPENF1_USERNAME and OPENF1_PASSWORD when set, anonymously otherwise.
Names only. Real values belong in the host dashboards, never in the repo. Templates: backend/.env.example and frontend/.env.local.example.
Analysis API
| Variable | Purpose |
|---|---|
OPENF1_BASE_URL | OpenF1 REST base URL |
OPENF1_USERNAME, OPENF1_PASSWORD | OpenF1 account, exchanged for a renewing bearer token |
OPENF1_API_TOKEN | Legacy static token, ignored when username and password are set |
CACHE_DIR | Where per-session JSON is stored |
CORS_ORIGINS | Allowed browser origins |
ENVIRONMENT | development or production |
OLLAMA_BASE_URL, OLLAMA_MODEL | Local AI chat |
GROQ_API_KEY, GROQ_MODEL, GROQ_REASONING_EFFORT | Production AI chat |
FREE_SEASONS | Seasons open to everyone |
PRO_ACCESS_CODES, PRO_TOKEN_SECRET, PRO_TOKEN_TTL_DAYS | PRO gate |
PRO_PROMO_CODES, PRO_PROMO_TOKEN_TTL_DAYS | Public promo codes as CODE|ISO 8601 instant with its zone, and how long a redeemed one lasts |
OPEN_ACCESS_UNTIL | Open week: an ISO 8601 instant with its time zone |
INTERNAL_BUILD_SECRET | Lets the publication Action compute PRO seasons |
PAYMENTS_ENABLED | Subscriptions on or off |
STRIPE_SECRET_KEY, STRIPE_PRICE_ID, STRIPE_WEBHOOK_SECRET | Stripe Checkout and webhooks |
PAYMENTS_RETURN_URL, PAYMENTS_REVOKED_SUBS | Return address and revoked subscriptions |
RESEND_API_KEY, RESEND_FROM | Restore access emails |
TELEGRAM_BOT_TOKEN, TELEGRAM_PRO_CHAT_ID, TELEGRAM_WEBHOOK_SECRET | PRO channel |
Recorder and live server
| Variable | Purpose |
|---|---|
CAPTURE_BUCKET, CAPTURE_ENDPOINT_URL, CAPTURE_REGION | S3-compatible archive (Cloudflare R2) |
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | Credentials for that bucket |
LIVE_ALLOWED_ORIGINS | Origins allowed to open the live stream |
PRO_ACCESS_CODES, PRO_PROMO_CODES, PRO_TOKEN_SECRET | The same values as the API, so its tokens open Live mode |
OPEN_ACCESS_UNTIL | Open week, as on the API |
TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID | Operational notifications |
Frontend (read at build time)
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_API_URL | Analysis API |
NEXT_PUBLIC_LIVE_URL | Live server |
NEXT_PUBLIC_TELEMETRY_URL | Public base of the lap telemetry files on R2; empty means the API only |
NEXT_PUBLIC_PAYMENTS_ENABLED | Subscriptions shown or not |
NEXT_PUBLIC_PW_BUILD | Build label |
GitHub Actions
| Name | Purpose |
|---|---|
OPENF1_USERNAME, OPENF1_PASSWORD | Publication and lap telemetry |
INTERNAL_BUILD_SECRET | Publication of PRO seasons |
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY | Upload of lap telemetry (a token scoped to one bucket) |
R2_BUCKET | Repository variable, the telemetry bucket |
TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID | Publication reports |
Session data, car data and location come from OpenF1; the telemetry fallback from FastF1. Historical data starts in 2023. Official lap lengths come from each Grand Prix's page on formula1.com, with the source kept per row. Team radio clips are linked from the official archive and are never copied or stored here.
MIT, see LICENSE. Fonts are under the SIL Open Font License, with their licences beside them.
Unofficial project. Not affiliated with Formula 1, the FIA or any team. F1, FORMULA 1 and related marks are trademarks of Formula One Licensing B.V.