MARKWU

FRC Scouting App

Real‑time match collection. Offline‑first reliability. Instant analytics that actually drive pick lists.

Teams
80+
Matches Logged
1,500+
Offline Sessions
500+
Median Sync
<2s
Placeholder for demo preview
Match input placeholder
Analytics placeholder
Offline cache placeholder
Background

Overview

Offline‑first PWA for field data collection. Deterministic sync. On‑device analytics for pick lists and drive‑team briefs.

Stack: React + TypeScript + Tailwind, FastAPI, SQLite/Postgres, WebSocket + HTTP, IndexedDB (Dexie).

Match Input (Tap‑Zone UI)This frame is intentionally empty. The demo mounts its own simulation (DB, HTTP, WS) when implemented.

Match input

± tap‑zones for atomic ops per metric (Auto/Teleop/End). Writes to local op‑queue (IndexedDB). Optimistic UI. Batch push on sync.

  • Own demo sim: IndexedDB + mock HTTP batch endpoint.
  • Idempotent keys: (event, match, team, phase, metric).
  • Accessibility: large hit targets; no-scroll, full-screen.

Team analytics

Using various algorithms to analyze data, give strategy suggestions, and alliance simulation.

  • AI: Using KMeans and random forest regressor to classify and predict match outcome.
  • Heuristic: Using Theil-Sen estimator and score calculators to predict match scores.
  • Elo: Using Bayesian inference and featured Elo to classify and rank robot.
Team Analytics (Charts + Table)This frame is intentionally empty. The demo mounts its own simulation (DB, HTTP, WS) when implemented.
Sync Visualizer (Queue → Batch → Transport → Upsert → Delta)This frame is intentionally empty. The demo mounts its own simulation (DB, HTTP, WS) when implemented.

Sync architecture

Uses HTTPS polling for live sync, DexieDB(IndexedDB) for offline scouting.

  • HTTPS Polling: more stable than websocket at worse internet.
  • live update: scouting data is uploaded live so admins get real time scouting data and basic analytics.
  • DexieDB & PWA: allows scouting with no internet, and data syncs on reconnect.

Architecture

Client: React/TS, Tailwind, PWA. Storage: IndexedDB (Dexie). Transport: HTTP + WebSocket. Server: FastAPI, SQLite (dev) / Postgres (prod), Alembic migrations.

Storage

Client op‑queue + cache in IndexedDB; server tables keyed on (event, match, team, phase, metric) for idempotence.

Sync

Batch push with ULIDs; delta feed by cursor; retry with exponential backoff and jitter; live updates via WS.

Auth

JWT session cookies; role‑based access; kiosk API keys; edge allowlist + rate limiting.

Data model

Minimal event‑sourced ops schema. Derived metrics computed server‑side; clients render aggregated series.

TypeScript (client)
export type Phase = "pre" | "auto" | "teleop" | "end";
export interface MatchEvent {
  id: string;            // ulid
  eventKey: string;      // e.g. 2025marea
  matchKey: string;      // qm12, qf2m1, etc.
  team: number;          // 0000–9999
  phase: Phase;
  metric: string;        // e.g. coral.L3, algae.removed
  delta: number;         // +1/-1 atomic op
  ts: number;            // ms epoch
}
SQL (server)
CREATE TABLE ops
                                                      (
                                                          ulid      TEXT PRIMARY KEY,
                                                          event_key TEXT    NOT NULL,
                                                          match_key TEXT    NOT NULL,
                                                          team      INTEGER NOT NULL,
                                                          phase     TEXT    NOT NULL,
                                                          metric    TEXT    NOT NULL,
                                                          delta     INTEGER NOT NULL,
                                                          ts        BIGINT  NOT NULL
                                                      );
                    CREATE INDEX ops_event_cursor ON ops (event_key, ts);

API

MethodPathDescription
POST/ops/batchPush queued ops (idempotent)
GET/ops/delta?since=ULIDStream new ops since cursor
GET/teams/:team/summaryComputed metrics per team
GET/event/:key/export.csvCSV export (offline review)