| name | track-round |
| description | Flight Arc「抓取一輪」FR24 資料工作流:fetch-flights → fetch-tracks → split-tracks → 同步文件 → 上傳 S3。當使用者說「抓下一輪」「抓軌跡」「fetch tracks」「抓 XX 機場的資料」「接續抓取」「補抓軌跡」「跑一輪抓取」時觸發。 |
| user_invocable | true |
/track-round — 抓取一輪 SOP
FR24 Essential 方案限制:300 筆/次、30 次/分鐘、666,000 credits/月。
🌐 Top-1000 P2 長期模式(2/18 全球網,跨數月)
若這次是在推進「全球前 1000 大機場 2/18 軌跡」戰役(65,421 條 ≈ 2.62M credits ≈ 4 個月),走這個特化迴圈:跳過 Step 1(1000 座時刻表已全掃完)、日期固定 2026-02-18、按 rank 分批、--max-credits 封頂。每個 session:
npx tsx scripts/campaign-status.ts
caffeinate -dims npx tsx scripts/fetch-tracks.ts --airports-file scripts/top1000-airports.json \
--rank <目前批次> --from-time 2026-02-17T16:00:00Z --to-time 2026-02-18T16:00:00Z \
--max-credits <算好的值> 2>&1 | tee scripts/_p2-batch.log
- 額度追蹤:
fetch-tracks 每次跑完自動 append 一行到 scripts/fetch-sessions.ndjson(含 SIGINT / circuit breaker)。月額度重置後,從 FR24 dashboard 讀實際餘額,更新 campaign-top1000.json 的 budget.manual_remaining / manual_remaining_as_of。
- 進度真相永遠現算:文件過期不影響,
campaign-status.ts 掃 scripts/flights vs track-done 得出。
- 細節與批次表 →
docs/backlog/data-fetching-status.md 最上方「🔖 下次接續」。
Step 0: 先讀狀態(必做)
讀 docs/backlog/data-fetching-status.md:
- 開頭「🔖 下次接續(接力點)」→ 有未完成項就先接續,不要開新目標
- 「🎯 目前目標清單」→ 確認這輪要抓哪些機場、預估額度
若接力點只差軌跡(時刻表已抓),直接跳 Step 2。
Step 1: fetch-flights(抓時刻表)
npx tsx scripts/fetch-flights.ts \
--from 2026-02-17 --to 2026-03-02 \
--airports VTBS,VTBD
- 額度:~38.7 credits / page(每 page 300 筆)
- 14 天上限:單次查詢範圍不可超過 14 天,更長要分段(如 2/26
3/11 + 3/123/28)
- 參數:
--from / --to — 日期範圍(YYYY-MM-DD 或 ISO)。⚠️ 是 --from/--to,不是 --from-time/--to-time(那是 fetch-tracks 的);誤用會 fallback 成「今天往前 3 天」
--airports A,B,C — 覆蓋預設(預設 = 台灣 22 座)
--airports-file path — 讀 JSON 清單(如 scripts/top1000-airports.json)
--direction outbound|inbound|both — 預設 outbound(單向、零重複命中)
--batch-size N — 跑 N 座機場後自動停(0 = 不停)
--range A-B — 只跑清單中第 A~B 座(1-based 含頭含尾)
- 輸出(皆 gitignored):新格式
scripts/flights/{ICAO}/{YYYY-MM-DD}.json 優先;legacy scripts/flight-list.json fallback
- ⚠️ 主動查詢的班次遠多於被動觸及(如浦東被動 330 vs 主動 1,488)→ Track 額度要用 Step 1 的實際結果估算
Step 2: fetch-tracks(抓軌跡)
npx tsx scripts/fetch-tracks.ts --airports KSEA,ZBAA --dry-run
npx tsx scripts/fetch-tracks.ts \
--airports KSEA,ZBAA,ZBAD \
--from-time 2026-02-17T16:00:00Z --to-time 2026-02-18T16:00:00Z
Step 3: split-tracks(重建 region + manifest)
NODE_OPTIONS="--max-old-space-size=12288" npx tsx scripts/split-tracks.ts
npx tsx scripts/split-tracks.ts --manifest-only
- 掃
airports/*.jsonl 做 dedupe + 產生 regions/*.jsonl + manifest.json
--manifest-only 不重寫 region 檔(regions 沿用既有值);有新增 region 機場時要跑完整版
- ⚠️ 產出新 region 時:
scripts/pull-from-s3.sh 的 for R in ... 是 hardcode 清單,必須同步加上新 region,否則 Zeabur 拉不到(UK、CN 都曾漏加)
- 重建 manifest 後跑
npx tsx scripts/build-airport-points.ts 更新 public/airport-points.geojson(機場 metadata,Location 面板 + Atlas 星圖共用;讀 manifest.json,須在 split 之後)
Step 3.5: 新機場 UI 三層同步(僅當這輪有「新」主動機場)
新機場群要在 UI 完整顯示,資料 / UI / 邊界三層缺一不可,缺了會像「沒抓到」:
- 資料層:Step 1-3 已完成(
public/tracks/airports/*.jsonl)
- UI 層:
src/map/cameraPresets.ts 加 AIRPORT_INFO + CAMERA_PRESETS(缺了機場 dropdown 不顯示);新地區記得更新 overview preset
- 邊界層:
npx tsx scripts/fetch-airport-boundaries.ts --icao A,B,C 更新 public/airports.geojson(找不到 aerodrome polygon 會自動 fallback 成 runway-buffer 矩形;腳本走 curl,勿改回 Node fetch — 對 Overpass 會 ETIMEDOUT)
改完跑 npm run typecheck 再 commit。
Step 4: 同步文件(必做,三處)
數字一律以重建後的 public/tracks/manifest.json 為準:
- README.md「軌跡資料量(Track Coverage)」表 — region 軌跡數、總筆數(
wc -l scripts/track-done.ndjson)、機場 JSONL 數、Top 15 機場、最後更新日
docs/backlog/data-fetching-status.md — 更新狀態欄、把完成項從接力點/目標清單移到「最近完成」、記新接力點
- 記憶
project_fetch_resume_point.md — 若這輪沒抓完,記下接力指令
Step 5: 上傳 S3 + Zeabur 拉取
npm run s3:upload
sh /app/scripts/pull-from-s3.sh
軌跡資料不進 git,S3 路徑 migu-gis-data-collector/flight-arc/。
重要觀念
- 主動 ≠ 有完整資料:被動機場 JSONL 只涵蓋「連到主動機場的航線」;要看完整主場流量必須對它跑 fetch-flights
- 軌跡雙寫:每筆軌跡 append 到 dep + dest 兩個 ICAO.jsonl
- 台北時間整天 = UTC
前一天T16:00:00Z ~ 當天T16:00:00Z