Pursuit Maps

Data & APIs

TrackMania Pursuit maps pipeline — fetches maps from ManiaPlanet Feedback (star ratings, vote counts), enriches with ManiaExchange data, syncs to Google Sheets via GAS Web App. Daily automated pipeline with vote tracking.

Install

openclaw skills install pursuit-maps

Pursuit Maps Pipeline

Automated pipeline: ManiaPlanet Feedback + ManiaExchange → Google Sheets.

Quick Reference

Main script: pipeline/pipeline.py in repo tomekdot/pursuit-maps

python3 pipeline/pipeline.py                    # full pipeline
python3 pipeline/pipeline.py --action sync      # fetch + push new maps + auto-sort
python3 pipeline/pipeline.py --action votes     # update vote columns only
python3 pipeline/pipeline.py --action sort      # sort sheet by Uploaded At
python3 pipeline/pipeline.py --action report    # vote change report
python3 pipeline/pipeline.py --action validate  # data quality checks

GAS Web App: pipeline/gas-webapp/PursuitMaps.gs — deploy once in Sheet (Extensions → Apps Script → Deploy as Web App). Accepts HTTP POST from pipeline.

Repo Structure

pursuit-maps/
├── pipeline/pipeline.py      ← Main entry point (all actions)
├── pipeline/gas_runner.py    ← HTTP client for GAS
├── pipeline/gas-webapp/      ← GAS script (deploy in Sheet)
├── data/                     ← Cache, history, reports
├── docs/                     ← Setup guides
├── scripts/legacy/           ← Old scripts (reference)
└── .github/workflows/pipeline.yml  ← Daily 5:00 UTC

Sheet Columns

ColNameSource
A#Auto
BMap nameFeedback
CAuthor loginManiaExchange
DEnvironmentManiaExchange
EUploaded atManiaExchange (ISO 8601 → normalized to YYYY-MM-DD HH:MM:SS)
FUIDFeedback
GTrackMania\MapTypeManiaExchange
HNotesManual
IYN RatingFeedback YES/NO section
JYN VotesFeedback YES/NO section
K5-Star AvgFeedback 5 STARS section
L5-Star TotalFeedback 5 STARS section

Sorting

Sheet is auto-sorted by Uploaded At (column E) descending after every sync (newest maps on top).

  • Column E is formatted as Date (yyyy-mm-dd hh:mm:ss) so Sheets treats it as proper date
  • Manual sort: python3 pipeline/pipeline.py --action sort or POST {"action":"sort"} to GAS
  • Sort function handles both Date objects and string dates from MX API

Key API Endpoints

  • Feedback page: feedback.prod.live.maniaplanet.com/votes/display/106
  • MX API: tm.mania.exchange/api/maps/get_map_info/id/{UID} (V1, accepts UID)
  • Sheet read: gviz API (no auth for public sheets)
  • Sheet write: GAS Web App (deployed once per user)

Parsing Notes

Feed page has TWO separate star rating sections per map card:

  1. YES/NO section: <h6>YES/NO</h6> → gold span → rating (count)
  2. 5 STARS section: <h6>5 STARS</h6> → gold span → rating (count)

Parse independently. ~80% of maps have 5-Star data but no YES/NO votes.

Split HTML at each <img src="...maps/..."> to isolate per-map cards.

Stats

  • 249 maps total
  • ~75% indexed on ManiaExchange
  • 248 thumbnails available (1 HTTP 403)
  • 4 environments: Valley, Canyon, Stadium, Lagoon
  • 3 map types: PursuitArena (~80%), GoalHuntArena (~15%), HuntersArena (~5%)