Crowd-sourced live scoring (bstats core)
Turning many parents' phones into one trustworthy box score, with live consensus, a disputed-play queue, and an AI review pass.
// Architecture
Problem
Youth basketball rarely has a stat crew. Parents and coaches want real numbers, so let everyone in the stands score from their phone at once, and turn that noisy, overlapping input into one record people can trust.
Constraints
- Every scorer is unreliable on their own: they miss plays, credit the wrong player, or tap late.
- Gym Wi-Fi is bad. Phones drop off and reconnect mid-game, and nothing they entered can be lost.
- It has to work one-thumbed, courtside, while the game is still moving.
- The final numbers have to be explainable, which means no input is silently discarded.
Approach
Basketball makes this tractable: events are discrete, belong to one player, and are anchored to the game clock. The server holds the live game in memory and is the only authority. Taps from different scorers are matched by action, player, and clock window. With three or more scorers online, the majority wins and the minority becomes a recorded duplicate. Clock corrections resolve to the median. Anything that can’t be settled lands in a disputed-play queue, and an AI pass works through that queue after the game, with its confidence and reasoning stored alongside each call. Raw inputs are kept forever, offline taps are queued and replayed on reconnect, and a server restart rebuilds the game from the event log.
What it demonstrates for clients
This is the same pattern as business data processing: many unreliable inputs → one validated record. Swap scorers for data sources or extraction runs and the engineering is the same. You need explicit matching rules, a policy for disagreement, a review queue instead of silent guesses, and a full audit trail of why each value is what it is.
// Stack
- Go
- WebSockets
- SQLite
- SolidJS
- Consensus