# 🏈 Betta Bring It — Fantasy Draft Board (2026–2027)

A local, crash-safe, dual-screen draft board in **light mode**. No internet needed during
the draft (only to fetch player data beforehand). Everything saves to the host PC after
**every pick** and recovers automatically if the machine crashes.

## Files
| File | What it is |
|---|---|
| `draftboard.html` | **Control screen** — the operator drives the draft here |
| `board.html` | **TV Screen 1** — full running draft grid, auto-updates |
| `pick.html` | **TV Screen 2** — giant "latest pick" + live timer for the back of the room |
| `fetch_players.py` | Pulls latest NFL names/teams/positions/headshots from ESPN (free, no key) |
| `players.json` | The player data the fetch script produces |
| `1_fetch_players.bat` | Double-click to fetch players (Windows) |
| `2_start_draft.bat` | Double-click to start the local server + open control screen |

## Setup (once)
1. Install **Python 3** from python.org — check **"Add Python to PATH"** during install.
2. Put this whole folder on the host PC.

## Draft day
1. **Double-click `1_fetch_players.bat`** — this is your **one-button refresh**: it pulls the latest
   rosters, **ADP, player news, bye weeks, and team logos** into `players.json` (needs internet; takes
   1–2 min). The data is then **cached** so the rest of the draft runs fully offline. **Re-run this any
   time on draft day** to get the freshest ADP/news, then in the app click ⚙️ → **Load / Refresh Players**.
2. **Double-click `2_start_draft.bat`** — starts a local server and opens the control screen.
   *(The local server is required so the app can read `players.json` and build the Excel/Word
   exports. Everything stays on your PC — nothing is uploaded.)*
3. Click the **⚙️ gear** (top-left) to open **Settings** — this is where ALL configuration lives:
   - League name, **Snake/Linear**, **Rounds**
   - **Pick timer** (default **90 seconds**) and on/off
   - **Next Pick Player Blur** (on/off) — see "During the draft" below
   - **Draft reveal — seconds on screen** (default **10**) — how long the big drafted-player card is held
     up on the control screen and the draft-board TV before it flies to the board. Shorten it to keep a
     fast draft moving, lengthen it for a bigger reaction. *(Doesn't change the "Latest Pick" TV, which
     always shows the most recent pick.)*
   - **Auto-pick if a manager runs out of time** (**off by default**) — turn it on and set a **grace
     period** (default 15s). When someone's clock hits 0 and the grace runs out, the app drafts a
     **random player from the top 20 available by ADP** for them and moves on. The timer shows
     "OVER — auto-pick in Ns" so the room sees it coming. Requires the pick timer to be enabled.
   - **Teams, managers, draft order, colors & logos** — your 12 team names are pre-loaded, each with
     a color. Drag the ⠿ handle to set today's pick 1–12 order, or hit **🎲 Randomize**. Use the
     color swatch to change a team's color, and the 📷 button to upload a team logo (right-click it to clear).
   - **Keepers (pre-draft)** — pre-assign kept players a few days early: type a player's name,
     pick the **team** and the **round** their pick is used, and hit **➕ Add Keeper**. That player
     leaves the pool and is **auto-drafted** for that team when the pick comes around. Set these
     before the draft starts. (Remove one with the ✕ next to it.) Keepers are marked with a **🔑**
     on the board and team lists, play the big reveal with a **KEEPER** badge, and export as
     `Keeper = Yes` for the commish.
   - **League Rules & Starting Lineup** — the starting-lineup slots (QB 1 · RB 2 · WR 3 · TE 1 · **FLEX 2** ·
     K 1 · D/ST 1 · Bench 5 — matching your NFL.com settings) that drive each team's live **roster needs**,
     plus an editable **scoring/rules reference** you can read off during the draft.
   - **Split into 3 leagues** — one click randomly splits the 12 teams into 3 mini-leagues of 4 (with color dots).
   - **Load / Refresh Players** and all **Exports**
4. Click the **📺 icon** (top-left, next to the ⚙️ gear) to **Open TV Screens** — opens `board.html`
   and `pick.html` in new windows. Drag each to its TV and press **F11** for fullscreen.
5. **Dark or light per screen** — each screen (control + both TVs) has a small **🌙 toggle** (or press **D**)
   that flips *just that screen* between light and dark. Set the TVs however looks best in your room — they're
   independent, and each remembers its choice. Everything starts in light mode.

Once configured, settings stay hidden — the draft screen and both TVs stay clean during play.

## Starting the draft
When everyone's seated and connected, press the big green **▶ Start Draft** button (top-left of the control
screen). That's the official go signal — it **starts the pick clock**, unlocks picking for the operator *and*
the phones, drops the full-screen join QR into the corner of the "Latest Pick" TV, and flashes **"ROUND 1 —
DRAFT IS LIVE"** on the draft-board TV.

Before you press it nothing can be drafted (so a stray click during setup can't start the draft by accident),
though **keepers still fill in** automatically. Once it's live the button is replaced by a small
**● DRAFT IS LIVE** indicator. *(Reset Draft in Settings puts it back to not-started.)*

## During the draft
- Players are **ranked by ADP** (average draft position) — the best available sit at the top, each
  with its ADP shown in the corner and its **bye week** on the card. Only ~268 players have a real ADP;
  scroll past them and you'll hit a **"── below: no ADP available (unranked) ──"** divider — everyone under
  it is deep-bench/camp filler shown alphabetically with a **—** instead of a number. **Search** by name or team, or
  filter by **position chips** (QB/RB/WR/TE/**FLEX**/K/**DST**) — the **FLEX** chip lists every RB/WR/TE.
  Team **defenses are draftable** (all 32, under DST).
- **Click a player → confirm** → the confirm popup shows their **photo, team logo, and ADP** →
  drafted, removed from the pool, both TVs update instantly.
- **Big draft reveal — on BOTH screens:** each pick zooms up to a large card (team, pick #, player)
  and **holds ~10 seconds** so the whole room can see it, then flies over to that team — to the team
  card on the dev box, and to the team's cell on the TV draft board. Click the overlay on the dev box
  to skip early. (The pick clock pauses during the reveal and starts fresh right after.)
- **Round Recap** — at the end of every round the **draft-board TV** shows a **"Round N Recap"** listing
  every player taken off the board that round (pick number, position, player, and the manager who took
  them — keepers marked 🔑), held for **15 seconds** so the room can catch up before the next round.
- **Color-coded by position:** every player card and every drafted cell on the board is outlined in its
  position color — **QB red, RB green, WR blue, TE orange, K purple, DST brown** (fullbacks show as RB).
- **Next Pick Player Blur** (optional, Settings): to stop managers from just grabbing the top-ranked
  name, turn this on. After each pick the player board **frosts over** — names, ADP ranks, and even the
  position colors are hidden. The hidden panel shows **who's up**, a recap of the **last pick** (with a
  steal/reach-vs-ADP verdict and the player's latest news), and a **rotating NFL fact** (won't repeat
  until round 9). The **clock is already running** — the next manager taps **👀 Ready to Pick** just to
  reveal the board.
- The **pick clock** turns **red and flashes under 10 seconds**, then stays **solid red** once time expires.
- The **draft-board TV** uses fixed, even columns with **uniformly sized tiles** (names wrap; no clutter),
  keeps the **team header frozen at the top**, and **auto-scrolls down** to follow the current round.
- The **Teams panel shows the upcoming pick order** — the team on the clock is on top, then **ON
  DECK**, then 3rd/4th/5th to pick — each in its **team color**, with **colored position circles**
  (e.g. a green ● RB with a count) so you can see each roster's shape at a glance. The current
  picker always stays at the top (the list auto-scrolls so it never slides off).
- **Roster needs on the clock** — the on-clock panel shows what **starting** slots the current team
  still needs (e.g. `WR ×3`, `FLEX ×2`); when every starter is filled it reads **"✅ Starters full —
  bench now."** FLEX is satisfied by any spare RB/WR/TE.
- **Timer** counts down from 90s (or your setting). It auto-starts on each new pick, turns
  amber at 15s, and counts *up in red* if a manager goes over. Start/Pause on the control screen.
- **Undo Last Pick** and the timer **Reset** are protected by a **4-digit PIN (3133)** so they
  can't be hit by accident. Undo returns the player to the pool and resets the timer.
- **Write-In** button (top-right of the player list, next to the filters) for rookies or anyone not in the data.

## Draft from your phone (optional)
Managers can draft from their own phones on the same Wi-Fi — or just let the operator run everything from
the control PC (both work; the phone is a convenience, and the control PC can always pick for anyone).

- **Host:** `2_start_draft.bat` runs the little server that phones connect to, and **auto-restarts** if it
  ever crashes (reloading the last state). Keep that black window open. Open the **control screen on the PC
  via `http://localhost:8777/draftboard.html`** (the bat does this) — that's required for the phone features.
- **Players join:** on their phone's browser they go to **`http://<your-PC-IP>:8777/lobby.html`**, enter the
  **join PIN**, and tap **their team** (it locks to their phone). Set/share the join PIN in **⚙️ Settings →
  📱 Connections** (default `2026`).
- **On-screen QR (easiest for players):** in ⚙️ **Settings → 📱 Connections**, the **Lobby URL** auto-fills
  from your PC's detected IP — **double-check it's the right one** (the PC may have several), then generate a
  QR for that exact URL with any offline QR tool and **upload it** there. **The URL must include the port
  `:8777`** or phones will hit the wrong port — the app now adds it automatically if you leave it off, and
  the URL is printed under the QR on the TV so you can check it matches the code you generated. The **"Latest Pick" TV** shows that
  QR **full-screen with the join PIN before the draft**, then moves it to the **bottom-left corner** once
  picks start, so latecomers can still scan it.
- **Picking:** a manager can only draft **on their turn** — their screen shows a green *"YOU'RE ON THE
  CLOCK,"* their **roster + remaining needs**, the timer, an alphabetical player list (search + position/FLEX
  filters, drafted players marked with who took them), and *"you pick in N."* They tap a player → confirm →
  it drops onto the board and both TVs exactly like an operator pick. **No one can pick out of turn or grab a
  player twice** — the control PC verifies every pick.
- **Write-In from the phone:** managers also get a **✎ Write-In** button (under the filters) for a rookie or
  anyone not in the list — enter name, team, and position, and it drafts just like any other pick.
- **Every manager gets tabs on their own phone** — once they claim their team, a bar appears at the bottom
  of their screen with **📋 My Draft** and **📊 Big Board**, so they can flip between picking and watching the
  full draft board without leaving their phone. Each device shows only that person's own tabs. *(You also
  get a third tab, **🧠 War Room**, which nobody else sees.)*
- **Board shows who's on:** each connected manager gets a **green dot** by their name on the draft-board TV.
- **Fix a wrong team:** if someone taps the wrong team, go to **Settings → 📱 Connections → Release** (asks
  for your PIN 3133) to free it so the right person can claim it. *Release* only clears the connection — it
  never removes any picks. You can **Release all** to reset every phone.
- **If the network drops:** phones fall off, but the **control PC keeps drafting normally** — nothing is lost.

### Managers joining from somewhere else (Tailscale)
You can run the draft with some people **in the room** and others **joining over the internet** at the same
time. In ⚙️ **Settings → 📱 Connections** fill in **both**:
- **📶 Lobby URL — here on our Wi-Fi** — e.g. `http://10.20.0.251:8777/lobby.html`
- **🌐 Lobby URL — remote / from anywhere** — your Tailscale address, e.g.
  `https://cdidirit.tailf91193.ts.net/lobby.html`

Upload a QR for each. The "Latest Pick" TV then shows **both codes side by side, labelled**, so people scan
whichever applies to them. **Folks in the room should use the Wi-Fi code** — it is faster and keeps working
even if your internet drops.

To turn remote access on for the night, start the draft server, then run
`tailscale funnel --bg 8777`. Turn it off afterwards with `tailscale funnel reset`.
**Keep the control screen on `http://localhost:8777/draftboard.html`** — the admin controls are deliberately
blocked through the tunnel so nobody on the internet can touch your draft.

*Tip: tell each manager to stick with one URL. Switching between the Wi-Fi and remote address makes their
phone look like a new device, so they would have to claim their team again (it frees up after ~15 seconds).*
- **"It won't connect" on someone's phone?** Make sure they typed **`http://`** — not `https://`. Phone
  browsers often try https first, which this server can't answer. The server window will tell you:
  *"!! 192.168.x.x tried HTTPS. Tell them to use http://…"*. Having them tap the QR code avoids this entirely.

## The operator's secret weapon: 🧠 Draft Guide
A private, PIN-locked war room only you can open. In **Settings → 📱 Connections** set **Draft Guide — your
team** to your own team. Then on your device: open the **lobby**, claim your team, and tap the **🧠 Guide**
button — it asks for your **Guide PIN (2060)**, which is separate from the shared 3133 Settings PIN — and unlocks:

- **Pick suggestions with reasons** — live value vs ADP, your starter needs, position runs and tier cliffs,
  bye-week clashes, and injury flags, recalculated after every pick.
- **"Before my next pick"** — what every manager between you and your next turn *needs*, who they'll
  probably take, and who's likely gone if you wait.
- **💤 Sleeper tracker** — a researched 2026 PPR sleeper list with target rounds; each lights up **TAKE
  NOW** when its round arrives and crosses out when someone grabs it. Plus a fade list, tier notes, and a
  round-by-round 1-PPR plan.
- **Live extras** — injury flags (❗), latest player news (📰), byes, and the full best-available board.
- **Tab bar on your phone (yours only)** — once you claim your own team, a bar appears at the bottom of
  your phone with **📋 My Draft · 🧠 War Room · 📊 Big Board**, so you can jump straight from the guide back
  to your pick screen, or pull up the full draft board, without retyping anything. Other managers never see
  it, and it never appears on the TVs.
- **Your own lobby is different** — when you claim **your** team on your phone, the player list is in
  **ADP order with ADP shown** (matching the main board). Every other manager still sees the neutral
  alphabetical list, so nobody can read the rankings off their screen.
- **Draft right from the guide** on your turn — same rules as everyone else, nothing special leaks to the room.

- **Click any player** (suggestions, board, injured list, sleepers) for a full **scouting card**: photo,
  FantasyPros expert tier + consensus rank, **projected PPR points** (FantasyPros + ESPN), the last **4
  seasons rescored to this league's exact scoring** with points-per-game, latest news, injury report — and
  a big **DRAFT NOW** button when you're on the clock.
- **Tier chips** on every player (T1, T2… — `~` means ADP-estimated beyond FantasyPros' top-10s), plus a
  live **FantasyPros news ticker**.
- **VBD value** — every player scored on points over a replacement starter, so you can compare a RB to a
  WR to a TE honestly. Sort the board by **ADP / VBD / Projected points**.
- **Survival odds** — "only ≈2% he survives to your next pick (#54)" instead of a guess, so you know when
  you can wait and when you can't.
- **⚖️ Cost of Waiting** — for each position: the best guy now vs. who you'd realistically get at your next
  pick, and the projected points it costs you (e.g. *TE −34*).
- **Opponent read** — the guide learns each manager's habits as they draft (needs-drafter vs. best-available,
  reacher) and tags them in the prediction list.
- **Durability, age, ADP momentum (↑/↓ vs. an earlier fetch), and fantasy-playoff schedule** (weeks 15–17,
  🎄 soft / 🧱 tough) on every scouting card and in the pick reasoning.
- **🔄 News** button — mid-draft, re-pulls live injury statuses + news from the host PC's internet and
  updates your board in place. Perfect for a draft two days after final roster cuts.
- **🖨 Sheet** button — prints a one-page cheat sheet (tiers, VBD, sleepers, fades, strategy) as a paper
  backup in case the device dies.
- Value tags read plainly: green **▲9 fell** = he fell 9 past ADP (value); red **▼9 early** = you'd be
  taking him 9 before ADP (reach).
- Sleepers light up **SOON** (amber) when the draft is within 15 picks of their ADP, **TAKE NOW** (purple)
  when their target round arrives, and drop off the list once drafted.

**Draft-morning data refresh:** just double-click **`1_fetch_players.bat`** — it now does *both* steps
(rosters/ADP/news/injuries, then the war-room tiers/projections/4-year stats/playoff schedules using your
FantasyPros key from `.fantasypros.env`, which stays private and is never served). Takes a few minutes.
**Your data is never lost:** if ESPN throttles or a source is down, anything that fails to download simply
keeps the value from the last run — re-running only ever adds. If a run looks thin, just run it again. *Tip: run
`fetch_guide_stats.py` once a week between now and the draft — it snapshots ADP each time, which is what
powers the ↑/↓ momentum arrows.* The sleeper research file is dated
**2026-08-03** — ask Claude to refresh `guide_data.json` the week of the draft so it reflects camp news.

## The first Write-In gets a ceremony
The very first time anyone drafts a **Write-In** player (a rookie or anyone not in the data), the control
screen and the draft-board TV stop for a moment: a giant **#2 pencil** wobbles on screen under
*"Announcing our very first WRITE-IN!"*, a scribble draws itself across the screen, and it welcomes the
player by name - it holds for **10 seconds**, then fades into the normal pick reveal. It only happens **once per draft**, so it stays
special. Every write-in player also gets a **#2 pencil as their photo** on the board, the reveal and the
Latest Pick TV.

## Manager time tracking (just for fun)
Behind the scenes the app records, per pick: how many **seconds** the manager took and how many
seconds they were **over** the clock. The **Time Report** export (Settings) totals it up per manager —
total time, average per pick, longest pick, and total seconds over. Great for calling out the
slowpokes at the end.

## Exports (for the commissioner)
All in Settings. Each downloads to the host PC's Downloads folder:
- **Excel (.xlsx)** — styled table, every pick with team/manager/player/pos/NFL team + times
- **Word (.docx)** — titled document with a formatted results table
- **CSV** — universal, opens anywhere
- **Time Report (.csv)** — the per-manager time stats above

The commissioner can open any of these and key the results into the NFL Fantasy league manually.

## Crash recovery & backups
Every pick is written to local storage immediately. If the PC crashes or the browser closes,
just **re-open the control screen** (`2_start_draft.bat`) — the draft resumes exactly where it
left off, including all pick times. The two TV windows auto-recover on refresh.

For extra safety, the app also **auto-saves a full backup file** to your Downloads every few picks
(Settings → **Backup & Restore**; default every 10 picks — set to 0 to turn off, or hit **💾 Download
Backup Now** anytime). If the whole machine is lost or storage is wiped, open the control screen on
any PC and use **📂 Import / Restore Draft…** to load the newest backup and **resume exactly where you
left off** — teams, managers, colors, keepers, picks, and times all come back.

## After the draft
Settings → **🏆 Draft Recap / Awards** shows fun awards (biggest steal & reach vs ADP, fastest &
slowest drafter, longest single pick, Mr. Irrelevant) **plus a letter grade for every team** (how well
they drafted versus ADP). The **draft board TV automatically shows the recap full-screen** the moment
the last pick is made.

## Practice / test run
Settings → **🧪 Simulate Full Draft** instantly auto-drafts a complete **random mock** — no animations,
no clicking, keepers kept — and pops the recap. Great for practicing the flow or seeing the board, recap,
and exports fully filled in without drafting by hand. It **replaces the current picks**, so use it before
your real draft; click it again any time for a fresh random result.

## Notes
- Cleanest setup: control laptop + two HDMI outputs (one per TV), each browser window in fullscreen.
- Player **headshots** and **team logos** come from ESPN; if one is missing the card still shows name/team/pos.
- **Team D/ST and kickers are already included** (all 32 defenses draftable under the DST chip).
- **ADP** comes from FantasyFootballCalculator (PPR by default). To match a different scoring format,
  open `fetch_players.py` and change `ppr` in `ADP_URL` to `half-ppr` or `standard`, then re-fetch.
- Want individual defensive players (IDP leagues)? Open `fetch_players.py`, set `KEEP_ALL = True`, re-fetch.
- The fetch also grabs a short **recent-news blurb** for ranked players (shown in the "blur" panel). This
  adds ~1–2 minutes to the fetch; set `FETCH_NEWS = False` in `fetch_players.py` to skip it.
