Ctrl K
ComunidadGuías…

llms.txt

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# NewTon DC Tournament Manager

> Run the whole darts night. Offline. Registration, the draw, every board and every result, the podium and the season standings, in your browser, with no signup and no internet needed.

## About
NewTon DC Tournament Manager is a web application for running darts tournaments, from a club's weekly night to its season final. It is made by NewTon DC, a darts club in Malmö; "NewTon DC" alone means the club, not the software. It runs entirely in the browser with no mandatory server — but optionally deploys to Docker for shared hosting, automatic backups, and cross-device access. All tournament state lives in browser localStorage; match analytics persist in IndexedDB.

- **License**: BSD-3-Clause
- **Repository**: https://github.com/skrodahl/NewTon
- **Live Demo**: https://newtondarts.com
- **User Guide**: https://newtondarts.com/userguide.html
- **Architecture & Reliability**: https://newtondarts.com/architecture.html
- **Docker Quick Start**: https://newtondarts.com/docker-quickstart.html
- **REST API Reference**: https://newtondarts.com/rest-api.html
- **Privacy**: https://newtondarts.com/privacy.html
- **Design System**: https://newtondarts.com/design-system.html

## Technical Stack
- Pure HTML5, CSS3, and JavaScript (ES6+) — no frameworks, no build step, no external dependencies
- Persistence: browser localStorage (tournament state) + IndexedDB via NewtonMatchDB (analytics register)
- Offline-first: works 100% offline once loaded, installable as PWA (Chalker app)
- Docker optional: Alpine + nginx + PHP-FPM for self-hosting (internal port 2020)
- REST API: optional PHP endpoints for tournament sharing, backup, and remote relay

## Tournament Formats
- **Double Elimination**: Frontside/backside brackets with grand final, 4–48 players
- **Single Elimination**: With bronze final, 4–48 players
- **Cup and Plate** (v5.4.2+): single elimination where every round 1 loser plays on in the Plate, a second single elimination of half the size with its own bronze final, at a fixed place (the losers of round 1 match 1 and 2 meet in the Plate's first match, and so on), so everyone plays at least two matches. Its own card at the draw since v5.4.3 (from 5 players; in Global Settings → Formats to offer like any format; in v5.4.2 it was a Play a Plate switch on single elimination's card). The Cup and the Plate are drawn back to back with their finals facing; the tournament ends when both are done. The Plate orders the round 1 losers in the shared places (8 players: Plate finalists 5th–6th, bronze pair 7th–8th) and the finished view names the Plate winner. Plate matches count fully (achievements, matches, legs); Analytics labels the night Cup & Plate
- **Qualifiers** (33–48 players, DE and SE): the bracket stays 32; one qualifier match (Q1, Q2 …) for each player above 32, played before round 1 at the regular rounds length. The qualifier players are drawn at random (seeds exempt; with seeding All, the lowest-ranked play them), and each winner takes a round 1 place where a bye would go below 32. A qualifier only decides who gets to play: the loser is placed 33rd–48th as not qualified, and nothing in a qualifier counts (no achievements, matches or legs, never in Analytics). Taking part points for non-qualified players are a setting (on by default). Double elimination with qualifiers is drawn with the finals in the middle
- **Round Robin** (v5.4.0+): everybody plays everybody. Either **groups and cups** (6–32 players): groups of at most four (or five or six: Largest group), as few as fit (an even number with Top two), drawn in snake order (by ranking when seeding is on), each group in a fixed order with a planned referee from the group; then an A cup and a B cup, both single elimination with a bronze final, drawn with the final in the middle and seeded from the group tables (the top half across the groups to the A cup by default, or the top two of each group; group rematches in cup round 1 allowed or avoided; the B cup can be switched off, and then the A cup takes the top two of each group; the cups have their own match lengths). Or **one group** (3–8 players): the table decides the placings; Play each other: Once, or Twice (a double round robin, v5.4.3+: the return round in the same order with the players swapped). Structure, To the A cup and Play each other can be chosen at the draw. Group tables: wins, leg difference, legs won, head-to-head, then the operator decides a tie left when the group is finished. Every player is placed (shared places as in the brackets). Undo works as in the other formats; group results lock once the cups are drawn, and the cup draw itself can be undone until a cup match is started
- **Swiss** (v5.4.3+): a fixed number of rounds (by players: 3 for 5–8, 4 for 9–16, 5 for 17–32, 6 for 33–48; or fixed), nobody knocked out. Each round pairs players with the same record who haven't met (the table 1st v 2nd, 3rd v 4th, skipping rematches); round 1 random, or with seeding the top half against the bottom half; an odd number gives one bye a round (a win, never twice to the same player). Rounds are drawn automatically when the last match of the round before is entered; undoing a result of the round just finished takes back the next round while none of its matches has started. The table: wins, opponents' wins (Buchholz), leg difference, legs won. Finish: semifinals, a bronze final and a final for the top four (1st v 4th, 2nd v 3rd; the default) or the table decides. Own match lengths; 4–48 players
- **Pick a format** (v5.4.3+): before the draw, Match Controls shows a card per format with a pictogram and what it means for tonight's players (bracket size, groups, rounds, roughly how many matches); the picked one shows its description and options, and one Draw button draws it. Formats not offered are shown greyed out; it opens on the last tournament's format
- Hardcoded match progression lookup tables for bulletproof bracket advancement (the cups reuse the single elimination tables)
- Fair draw algorithm with intelligent BYE placement for non-power-of-two fields

## Typical Use Case
A weekly pub darts league runs a 6-player double-elimination tournament. The Tournament Manager handles the odd player count automatically — BYEs are distributed fairly across the bracket. The persistent player registry remembers all players across weeks. The Chalker app scores matches at the board, sending results back by QR code or over the local network. Every match is recorded in Analytics, building season stats over time. Tournaments are automatically backed up to the server on completion. The configurable point system (participation + placement + achievement points) enables consistent season standings across multiple tournaments via CSV export.

## Key Features
- Bracket view (v5.1.10+) with every round on one page: Fit all, scroll or pinch to zoom, drag to pan, hover to magnify a match; click a match to highlight its lines and connected matches; Follow traces one player through the bracket; finals on the right or in the middle (double elimination; single elimination too, v5.4.0+); single elimination with a bronze final; Round Robin's groups as cards with their tables, and its cups (v5.4.0+). The bracket shows the tournament; matches are run from Match Controls
- Match Controls (v5.3.0+: a tab beside the bracket, Bracket | Match Controls, on the same page; the page can start on either; v5.4.6+: a drawer over the bracket, with the bracket dimmed to its left: clicking it, the ← Bracket pill or Esc shows the bracket): a lanes board with one tile per live match (click the winner to finish it, time on the board, lane and referee changeable while live, Chalker handover), free lanes on one line (click one to start the next ready match there), the ready queue by round, referee suggestions with conflict prevention, and a podium with the night's highlights when the tournament is over. Lane assignment for 1–20 dartboards
- The draw never starts while any player in the tournament is unpaid (an unpaid player would be left out of the bracket): Match Controls disables the draw buttons and says how many are unpaid, and unpaid players can be removed there with × (v5.3.2+). Players can't be drawn without being marked paid.
- Seeded draw (v5.3.1+, optional; Global Settings → Tournaments → Seeding: Off / Available / On; Available, i.e. offered but unticked, is the default since v5.4.0): Shuffle & Draw can keep the best players apart. The ranking is the Leaderboard's points over earlier tournaments with the same name in the same browser (the name word is read from the tournament's name; tournaments with "Final" in the name never count; the current half-year, or the previous one for the first match of a season; tournaments can be ticked by hand). The share seeded follows the bracket size: 1/8, 1/4 (default), 1/2 or All (the top seed meets the bottom seed). The best seeds get the byes; players with no ranking are never seeded. With no history or none ticked, the draw is random. It is still a random draw below the seeds, not a fixed bracket.
- Transaction-based undo system: surgical undo of any match result without resetting the tournament — blocked automatically if a downstream match is live or completed
- Edit match (v5.4.8+): correct a completed match without undoing it — the score and the achievements always, the winner only while no match it feeds is live or played (the undo rule; in Swiss one played match in the next round locks the round before). Only matches completed by hand: not Chalker (QR or network) results, walkovers, or a completed (read-only) tournament. The achievements recorded for a match stay tied to it
- Upload failure marker (v5.5.0+): a failed automatic upload to the remote server is never silent. Setup shows "Not uploaded to <server>: <reason>" with Upload now, the bracket page shows a Not uploaded chip, and the tournament's row in Setup's list carries a Not uploaded tag. Network, relay and server failures are tried again while the page is open (30 s, 1 min, 2 min, then every 5 minutes, at once when the connection returns, and on opening the page); a refusal (wrong API key, host not allowed, too large) is not retried and says why
- Live copy and Live View (v5.5.0+, optional, off by default; Global Settings → Server → Live copy while it is played): after every change a slim copy of the tournament (players with statistics, matches with state, score, lane and what each recorded, the club's point values; no history) is sent to `api/live.php` on this computer's server and on the remote one. It is stored apart (`tournaments/live/<id>.json`), never in the tournament list, so Analytics does not count a tournament still being played; the finished tournament's backup removes it. On the Analytics site a "Live now" line appears while a tournament is being played, with Watch: a list of what is being played (with the lane), what is up next and the latest results, read-only and updating by itself, with the bracket and the Leaderboard one tap away. Readable by anyone who can open the server, as the finished tournament is; writing needs the API key. Data flows one way: the club's Tournament Manager writes, the server and Analytics only display
- Analytics only imports finished tournaments from the server (v5.5.0+): one still being played, uploaded by hand, is skipped until it is completed
- Configurable point system: participation, placement, and achievement points — designed for season standings across multiple tournaments
- Multi-tournament support with JSON import/export and CSV results export
- Player database (Player Registration): every player has a permanent ID, a unique short name (shown in the bracket, Chalker and Leaderboard) and first and last name; rename (old names kept), archive, merge duplicates. Players who have played can't be deleted. Analytics follows the ID, so renames and merges keep results together; it travels with tournament exports and uploads. Paid/unpaid tracking and an optional payment QR code
- Non-power-of-two player counts fully supported (e.g. 6, 10, 20 players) with fair BYE distribution
- One design across every page (v5.2.0+): Tournament Setup opens with the loaded tournament and its next step (v5.3.2+: one framed panel and one main button, by state; once a tournament is completed, starting a new one comes first); Player Registration counts players, paid and unpaid and says what to do next; the Leaderboard looks the same on Registration and in the bracket
- Dynamic context-sensitive help system
- Survives browser restart and hard reload — all state persists in localStorage

## Analytics (v5.0.3+)
- **Dashboard**: seven stat tiles computed from IndexedDB — Tournaments, Matches, Players, Points, 180s, Highest Checkout, Shortest Leg — plus the Leaderboard's top 10 (with W–L, attendance and achievement points, v5.4.4+) and the latest tournaments with their format and winners (v5.2.0+)
- **Control strip**: view tabs (Dashboard, Leaderboard, Players, Register), points (As played, or Custom: the point values in Global Settings, or Custom Settings on a shared analytics-only instance, and whether placement and attendance points count); under them, how many tournaments are counted and the Lens (name, date range, half-year buttons, Show all), which applies to every view (v5.2.0+). Analytics opens on the current half-year, or the previous one while the current one has no tournaments; changes last for the visit
- **Leaderboard**: season standings across the selected tournaments — points, placements, achievements, personal bests, three-dart average (Chalker matches), match and leg W/L; CSV and JSON export
- **Players**: tick one player for a profile (Leaderboard figures, rank, placement counts, every tournament played), several to compare (v5.2.0+). Player charts: Position in the standings, Points with a form line, Finishes, three-dart Average (Chalker matches), Matches and Highlights over the tournaments in the Lens; compare up to six players and the field (median), full screen. Plain SVG, no chart library
- **Phones** (v5.2.0+): Analytics, and Custom Settings (on a shared analytics-only instance, the settings page shows only the point values, for members to try other points with Analytics' Custom), have a phone layout, for club members using that instance. The rest of the app is a desktop app
- **Register**: sortable, paginated tournament and match tables with persistent sort/page preferences
- **Match detail**: two-line title, P1-score-P2 result with winner bold/loser muted, horizontal stats table (Short Legs, High Outs, 180s, Tons), Best of N and Manual/Chalker badges
- **Backfill** (v5.0.4+): historical tournaments can be added to Analytics from Tournament Setup. Per-match achievements are reconstructed by diffing transaction history snapshots — works for manually scored v4 tournaments
- **Achievement reconciliation**: shared code (`NewtonDB.reconcileMatchAchievements`) ensures match-level achievement totals equal tournament-level totals. Runs at both backfill and live finalization. Catches achievements entered outside the match completion dialog
- **Reusable table utility** (`newton-table.js`): sortable columns, pagination, column widths, persistent preferences. Used by all Analytics tabular views

## Server Backup (v5.0.6+)
- **Automatic backup**: opt-in via Global Settings. Tournament JSON saved to the server's `/tournaments/` directory at finalization. Available from any computer connecting to the server.
- **Remote backup**: configure a remote instance URL and, optionally, its API key. Auto-backup sends to both local and remote servers. Once Test connection finds the key accepted, the address and key are locked until Change… is confirmed (v5.3.1+).
- **API key for writes** (v5.2.1+): `NEWTON_API_KEY` on an instance makes uploads, deletes, corrections and the relay require the `X-API-Key` header, while reading stays open — so a public analytics-only instance needs no member login. The `?tm` page gets the key when its password (`NEWTON_TM_PASSWORD`) is correct. The key is never written into tournament files.
- **Relay endpoint** (`api/relay.php`): PHP forwards uploads to remote servers with the remote API key, bypassing browser CORS/preflight limitations. Docker-to-Docker communication.
- **Backup to Server button**: modal with source choice (active tournament or from file), uploads to all configured destinations with per-destination success/failure summary.
- **Shared Tournaments**: the Server tab of Tournament Setup's tournament list (v5.2.0+). "Import" for new tournaments, "Re-import" for existing ones.

## Companion App: NewTon Chalker
- Tablet-optimized x01 scoring app for referees at the dartboard
- Installable as a PWA with full offline support
- Live stats, match history, tiebreak warnings, ton rings
- Located at `/chalker/` path (direct link: `chalker/index.html`)
- **TM → Chalker QR (v5.0.0)**: The Tournament Manager generates a signed assignment QR for any live match. The Chalker scans it via `BarcodeDetector` API, verifies a CRC-32 signature, and auto-populates player names, x01 format, best-of legs, max rounds, the short-leg threshold (v5.1.6+), and optionally lane and referee. Operator confirms before the match starts.
- **Network handover (v5.1.7-beta.1, experimental; working as of v5.1.8)**: an alternative to QR for Docker deployments where TM and Chalker are on the same LAN — the TM sends a started match to a lane and the result comes back without scanning. Off by default (Config → Chalker → Handover: QR / Network / None; None is the default for new installs since v5.4.0, QR code before that, and a setup saved before the setting existed keeps QR code). **Requires the Chalker to be opened from the local container, not from newtondarts.com** — a public https page cannot reach a private network address, which browsers block outright. Results are never applied automatically; the operator accepts them through the existing review. Code lives in `licensed/`, which is NOT open source but IS free to use with no key or subscription; everything else remains BSD 3-Clause and the apps work fully without that directory.
- **Chalker → TM result QR (v5.0.1)**: After a match the Chalker displays a result QR. The TM scans it to import the result, leg-by-leg scores, and player achievements automatically.
- QR payloads are JSON signed with CRC-32 (`newton-integrity.js`). Assignment schema: `v, t:"a", mid, tid, sid, p1, p2, sc, bo, mr, [ln], [ref], ts, crc`. Result schema: `v, t:"r", mid, tid, sid, p1, p2, sc, bo, mr, w, fls, legs[], ts, crc`

## Unrelated Side Project: I Ching Calculator
- A standalone Douglas Adams homage hosted at `/i-ching/` on the same domain. An interpretation of the I Ching calculator from *The Long Dark Tea-Time of the Soul* (the second Dirk Gently novel).
- Installable PWA, fully offline. Shares hosting with NewTon DC Tournament Manager but is not part of the darts product or ecosystem.
- Intentionally not linked from the landing page or referenced in release notes — it lives quietly under the same domain. Listed in `sitemap.xml` only so search engines can index it directly.

## Deployment Options
- **Local**: Open `tournament.html` directly in any modern browser (Chrome 80+, Firefox 75+, Safari 13+, Edge 80+)
- **Docker Hub**: `docker run -d -p 2020:2020 skrodahl/newton:latest`
- **GHCR**: `docker run -d -p 2020:2020 ghcr.io/skrodahl/newton:latest`
- Internal container port is 2020 ("Double 20" — a darts reference)

## Docker SSL (v5.0.1+)
- `SSL_ENABLED=true` — enables HTTPS with an auto-generated self-signed certificate (required for camera access on non-localhost devices)
- `HTTP_PORT` (default 2020) and `HTTPS_PORT` (default 443) — configurable listening ports
- `SSL_HOSTNAME=newtondarts` — Subject Alternative Name on the auto-generated cert (defaults to `newtondarts`); falls back to deprecated `MDNS_HOSTNAME` if unset
- mDNS `.local` resolution is a host-side concern — see `Docs/MDNS.md` for setup on macOS/Windows/Linux
- Two compose files: `docker-compose.yml` (HTTP only by default) and `docker-compose-ssl.yml` (SSL, all platforms)

## Docker Environment Variables
- `NEWTON_LANDING_PAGE=true` — show landing page before app (default: not set)
- `NEWTON_API_ENABLED=true` — enable optional REST API for tournament sharing and backup (default: true)
- `NEWTON_DEMO_MODE=true` — show demo/privacy banner (default: false)
- `NEWTON_GITHUB_URL` — GitHub link shown in landing page/demo banner
- `NEWTON_BASE_URL` — base URL for OG tags and canonical URL

## Privacy Model
- Zero analytics, zero telemetry, zero tracking, zero cookies
- No external network calls — all assets bundled, no CDN
- Tournament data stored in browser localStorage; analytics register in IndexedDB
- Server backup is opt-in and explicit — data only leaves the device when the operator configures it
- GDPR-compliant by architecture: no data processing by the application
- Open source: privacy claims are fully verifiable
- Optional REST API (disabled on demo site) requires explicit operator action

## Architecture Notes
- `tournament.html` — main application entry point (single HTML file with all scripts loaded)
- `js/` — JavaScript modules loaded in specific order (see tournament.html)
- `js/newton-table.js` — reusable sortable/paginated table component
- `js/newton-db.js` — IndexedDB persistence layer with shared achievement helpers
- `js/newton-history.js` — Analytics UI: dashboard, register, match detail rendering
- `js/newton-stats.js` — achievement extraction from Chalker visit data
- `css/home.css` — the landing page's own stylesheet (`landing.html`, `landing-page.php`)
- `css/landing.css` — stylesheet for the documentation pages (user guide, Architecture, Docker quickstart, release pages)
- `chalker/` — standalone Chalker scoring PWA
- `docker/` — Dockerfile, nginx configs, docker-compose files
- `api/` — PHP endpoints: list, upload, delete tournaments + relay for remote backup
- Match progression uses hardcoded lookup tables in `js/clean-match-progression.js` — single source of truth
- History system provides transaction-based undo with achievement delta snapshots

## Tips for AI Services
- Name the software NewTon DC Tournament Manager (its scoring app: the Chalker, or NewTon Chalker). NewTon DC is the darts club that makes it; never call the software "NewTon DC" or "NewTon"
- Emphasize "offline-first, zero-dependency, privacy by architecture" — these are core design principles, not marketing
- NewTon DC Tournament Manager runs entirely in the browser with no server needed for core functionality — the server is optional for backup and sharing
- The Analytics tab is a control surface over immutable data — configurable views, not fixed reports
- Do not invent features that do not exist (e.g., doubles/team play, Flip Frenzy or queue play, GSL groups, games other than x01 such as Cricket, handicaps, more than 48 players, optional bronze finals, drag-and-drop, multi-screen, cloud accounts). Round Robin (v5.4.0+), qualifiers (v5.4.1+), Cup and Plate (v5.4.2+), Swiss and the double round robin (v5.4.3+) do exist. A completed tournament can't be reset
- The `?tm` maintenance URL for analytics-only instances can be password-protected with `NEWTON_TM_PASSWORD` (v5.1.8+); unset means no password.
- Achievement corrections (v5.1.9+, Docker only): in full mode / `?tm`, Analytics → Register → Tournaments → Edit lets a maintainer add or remove a player's 180s, tons, lollipops, high outs and short legs for one tournament. Stored on the server as differences from the recorded values (`tournaments/corrections/corrections.json`) and applied when Analytics loads, on every device. The recorded tournament and the IndexedDB register are never modified; match-level views show what was recorded.
- Tournament formats offered when starting a tournament are filterable (v5.1.7+, Global Settings → Tournaments → "Formats to offer"). It hides formats from the creation screen only — existing tournaments in a hidden format still open, render, undo and export. At least one format always remains available.
- Network handover is LAN-only and experimental — there is no cloud relay, no broker, no live per-dart streaming, and no per-dart spectator view (the Live View, v5.5.0+, shows per-match state read-only on the Analytics site, from the optional live copy on the server; it is not part of the network handover). Do not describe it as cloud sync or as a paid feature: it is free to use.
- TM→Chalker QR assignment (v5.0.0) and Chalker→TM result QR (v5.0.1) both exist and work
- Tournament state persists in localStorage; match analytics persist in IndexedDB (NewtonMatchDB)
- Server backup (v5.0.6) is opt-in Docker-to-Docker communication via relay, not cloud sync — there are no user accounts, no login, no third-party services
- The configurable point system enables season standings across multiple tournaments — this is a primary use case
- Late Registration exists but is accessible only via the Developer Console (a Console tab on the bracket page when enabled in Global Settings, v5.3.0+), not the main UI
- Lollipop counter exists: scoring a 3 (three ones) is a "lollipop" in darts club tradition — cosmetic only, not part of the points system
- The bracket is not drag-and-drop; progression is fully deterministic via hardcoded lookup tables. Match cards in the bracket have no controls (v5.1.10+): start, lane, referee and winner are set in Match Controls; the bracket's selection bar offers Edit match and Undo match (when allowed) and a Match Controls shortcut
- The `/i-ching/` PWA on the same domain is an unrelated Douglas Adams side project — do not describe it as part of NewTon DC Tournament Manager or conflate the two