Skip to main content

Utilities for MyLaps Event Results API.

Project description

speedhive-tools

A Python client, SQLite persistence layer, and CLI for scraping and analyzing MyLaps Speedhive race results. It powers the speedhive-tools-ui dashboard, but works standalone as a library or command-line tool.

Install:

pip install speedhive-tools

or, for local development:

git clone https://github.com/ncrosty58/speedhive-tools.git
cd speedhive-tools
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

How it fits together

SpeedhiveClient  --scrapes-->  SpeedhiveStorage (SQLite)  --queries-->  reports / exports
     |                                |
     +------ workflows/ orchestrate both -----+
  • SpeedhiveClient (speedhive.wrapper) talks to the Speedhive HTTP API.
  • SpeedhiveStorage (speedhive.storage) is the single SQLite persistence and query layer — every event, session, result, lap, and announcement gets cached here, and every read (including derived data like parsed track records) goes through it.
  • Workflows (speedhive.workflows) orchestrate the two: refresh_org_cache pulls from the client and writes to storage; the track_records workflow reads from storage, diffs against a curated file store, and writes candidate records for human review.
  • Exporters / analyzers are thin, mostly-CLI-facing layers that read from an already-populated SpeedhiveStorage and produce NDJSON, reports, or driver-lap extracts.

A SpeedhiveStorage instance is cheap to construct but not free — its constructor opens a connection and runs schema DDL. Library functions that need one take it as a parameter rather than a raw path, so callers doing multi-step work (sync, then scan, then export) build it once and pass it through instead of reopening it at every step.

src/speedhive/
├── client.py                    # Low-level HTTP client
├── wrapper.py                   # SpeedhiveClient — high-level API wrapper
├── storage.py                   # SpeedhiveStorage — SQLite cache + queries
├── ndjson.py                    # Streaming NDJSON helpers
├── generated/                   # Auto-generated OpenAPI models/endpoints
├── utils/                       # Lap-time parsing, outlier detection, text parsing
├── analyzers/                   # analyze_consistency, analyze_driver_laps (CLI)
├── exporters/                   # export_db_dump, export_lap_records, export_track_records, ...
├── workflows/
│   ├── refresh_org_cache.py     # Sync one org from the API into storage
│   ├── import_sqlite_dump.py    # Load an offline NDJSON dump into storage
│   └── track_records/
│       ├── extract.py           # extract_records_from_api — API-side scraping (no storage)
│       └── curation.py          # sync/diff orchestration against a curated NDJSON store
├── stores/                      # File-backed stores (curated/rejected/pending track records)
└── cli/main.py                  # `speedhive` command-line entry point

Programmatic usage

Scrape live from the API

from speedhive.wrapper import SpeedhiveClient

client = SpeedhiveClient.create()
org = client.get_organization(30476)
events = client.iter_events(30476)          # generator over all events
sessions = client.get_sessions(event_id=12345)
laps = client.get_laps(session_id=67890)

Sync an org into a local SQLite cache

SpeedhiveStorage is constructed once and threaded through every call that touches it:

from speedhive.storage import SpeedhiveStorage
from speedhive.wrapper import SpeedhiveClient
from speedhive.workflows.refresh_org_cache import refresh_org_cache

client = SpeedhiveClient.create()
storage = SpeedhiveStorage("speedhive.db")

refresh_org_cache(
    client=client,
    storage=storage,
    org_id=30476,
    mode="incremental",          # or "full" to re-scrape everything
    recent_backfill_events=3,    # also re-check the N most recent events
)

Query the cache

Reads — including derived queries like parsed track records — are methods on SpeedhiveStorage itself:

org = storage.get_organization(30476).payload
laps = storage.get_laps(session_id=67890).payload
status = storage.get_org_status(30476)                 # freshness/staleness info
records = storage.get_track_records(30476, classification="Karting")

Track-record curation workflow

Speedhive announcers flag new track/class records in session announcements. The track_records workflow extracts those, normalizes classification codes against a per-org alias map, diffs them against a curated NDJSON file, and writes only new/changed candidates out for human review — nothing is written to the curated file automatically.

from speedhive.workflows.track_records import curation

# Refresh storage if the cache looks stale, then scan for new record candidates
outcome = curation.refresh_and_scan(
    org_id=30476,
    client=client,
    storage=storage,
    track_records_root="./web_data/track_records",
)

# Or just diff against an already-synced cache, no API calls:
scan = curation.run_sync_and_diff(30476, storage, "./web_data/track_records")

Offline dumps

Export a synced org to portable NDJSON, or load one back into a fresh cache:

from speedhive.exporters.export_db_dump import export_db_dump
from speedhive.workflows.import_sqlite_dump import import_dump_to_storage

export_db_dump(storage, org_id=30476, output_dir="./snapshots/30476")
import_dump_to_storage(org=30476, dump_dir="./snapshots", storage=storage)

Command-line interface

Installing the package registers a speedhive executable.

Command Purpose
sync-org --org ID [--mode full|incremental] Scrape an org from the API into the SQLite cache
report-consistency --org ID [--driver NAME] Rank drivers by lap-time consistency (CV), optionally look up one driver's percentile
extract-driver-laps --org ID --driver NAME Fuzzy-match a driver and dump their race laps + stats to JSON
export-track-records --org ID [--classification C] Export parsed track/class records from the cache to NDJSON
export-lap-records --org ID Export raw lap rows per session to NDJSON
export-db-dump --org ID --output-dir DIR Export a full offline NDJSON dump of an org
import-dump --org ID --dump-dir DIR Load an offline NDJSON dump into the SQLite cache
export-dump --org ID --output DIR Full raw dump export (events/sessions/results/laps/announcements)
scan-track-records --org ID Diff the curated track-record store against an already-synced cache
refresh-track-records --org ID [--force] Refresh the cache if stale, then scan for track-record candidates
export-curated-track-records --org ID Export the human-approved curated record list to NDJSON
import-curated-track-records --org ID --input FILE Merge or replace the curated record list from NDJSON

All commands accept --db-path (defaults to $SPEEDHIVE_DB_PATH or ./web_data/speedhive.db). Run speedhive <command> --help for full options.

speedhive sync-org --org 30476 --mode incremental --recent-backfill-events 5
speedhive report-consistency --org 30476 --min-laps 15 --top 20 --ignore-outliers
speedhive refresh-track-records --org 30476

Configuration

Variable Purpose
SPEEDHIVE_DB_PATH Default SQLite cache path used by CLI commands
TRACK_RECORDS_STALE_HOURS How old the cache can be before get_cache_status reports needs_sync (default 20)
GOTIFY_URL, GOTIFY_APP_TOKEN Optional push notification when new track-record candidates are found

Testing

pip install -e ".[dev]"
pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

speedhive_tools-0.9.5.tar.gz (112.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

speedhive_tools-0.9.5-py3-none-any.whl (214.9 kB view details)

Uploaded Python 3

File details

Details for the file speedhive_tools-0.9.5.tar.gz.

File metadata

  • Download URL: speedhive_tools-0.9.5.tar.gz
  • Upload date:
  • Size: 112.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for speedhive_tools-0.9.5.tar.gz
Algorithm Hash digest
SHA256 cd417766188041b5a1cae5d5d85fe606752a539afbfb6b0ae7f54aaab010deca
MD5 e0da60e8b3ba0313059b0db9559de6ba
BLAKE2b-256 7609bc93872fd04098a9a27f22014d0b8a93211eeb77f3b212a0dd84e4b3753e

See more details on using hashes here.

File details

Details for the file speedhive_tools-0.9.5-py3-none-any.whl.

File metadata

  • Download URL: speedhive_tools-0.9.5-py3-none-any.whl
  • Upload date:
  • Size: 214.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for speedhive_tools-0.9.5-py3-none-any.whl
Algorithm Hash digest
SHA256 5271c8fcd77dddc2990897ed53675b012462c433550f463be9cd39c7fb974d66
MD5 641bb333135498b6a3a9f71930975a28
BLAKE2b-256 e3d3a5e929b71797999adfa01064476c63382639cb220d6bfcbfa0be00680f27

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page