How the Draft Room works

Every number on the page, and where it comes from

There is no panel of experts behind this app. Every rating, grade and suggestion is computed from public data by rules that fit on this page. This is all of them.

  1. What this is
  2. Where the numbers come from
  3. The league, and everything derived from it
  4. How the CPU teams draft
  5. Tiers
  6. The draft grade
  7. The three signals on a player
  8. Saving and resuming
  9. What it deliberately does not do

01What this is

A mock draft simulator. You take one seat, seven to thirteen computer opponents take the rest, and everyone drafts until the rounds run out. Nothing is saved to a server and nobody else is in the room.

It was built for one ten-team league and still opens on those settings, but the league shape is now yours to set: 8 to 14 teams, 8 to 20 rounds, any starting lineup, and standard, half or full PPR scoring.

02Where the numbers come from

Two free public feeds, no keys and no accounts:

Fantasy points are recomputed, not copied

Sleeper publishes its own points total, and it is thrown away. It assumes four-point passing touchdowns and flat kicker scoring, and bakes in choices you may not share. Every point you see is recalculated from raw components — attempts, yards, touchdowns, field goals by distance — under the rules below, which are the defaults and can all be changed:

Passing0.04 per yard, 6 per touchdown, −2 per interception
Rushing0.1 per yard, 6 per touchdown
Receiving0.1 per yard, 6 per touchdown, and 0, 0.5 or 1 per reception depending on the format you pick
Kicking3 inside 40, 4 from 40–49, 5 from 50–59, 6 from 60+, 1 per extra point, −1 per miss
Fumbles−2 per fumble lost
A projection of 0 from the feed means Sleeper has no forecast for that player, not that he will score nothing. Those are treated as missing. Counting them as real zeroes dragged replacement level toward zero and made everybody else look elite.

Scoring format changes the board

Full PPR moves receivers up and running backs down, so each format has its own ADP list. When a draft starts, the board is built from the list matching your scoring, and every positional rank, tier and value figure is computed from that list rather than from a fixed order.

Team count is not a second axis. Fantasy Football Calculator accepts a team-count parameter and repeats it back to you, but it returns the same drafts and the same ADP whether you ask for 8 teams or 14. Rather than store four identical copies and imply a precision that is not there, the app keeps one list per format and says so.

Scoring happens in the browser

There is no points total in the data file. stats.js holds raw components — yards, touchdowns, receptions, field goals by distance, points allowed — and every scoring rule is applied here, as the page runs. All thirty-eight of them are editable on the setup screen.

Change one and everything rescores at once: projections, every historical season, the week-by-week logs, replacement level, the Overall signal and the draft grade. Nothing is rebuilt and nothing is refetched, because the numbers were never baked in to begin with.

This is why the pipeline records facts rather than opinions about how to value them. A stat that was never stored could never be rescored, so everything scoreable is kept even when the default rules value it at zero.

One honest limit. Sleeper's projections are a coarser dataset than its record of what actually happened. They do not forecast defensive touchdowns, safeties or points allowed, and they report long field goals as a single 50+ figure rather than splitting 50–59 from 60+. So those rules change a player's history far more than they change his 2026 projection. Where a projection uses the coarse figure, it is folded into the nearest band rather than dropped.

03The league, and everything derived from it

One object in app.js describes the league. Nothing else in the app writes a league number down. Team count, round count, the starting lineup, the FLEX and the bench all live here, and the setup screen edits them:

const league = {
  teams: 10,
  rounds: 14,
  starters: { QB: 1, RB: 2, WR: 2, TE: 1, K: 1, DST: 1 },
  flex: 1,
  bench: 5,
  scoring: "half"
};

That matters more than it looks. An earlier version had "ten teams" typed into a dozen different places and a replacement level worked out by hand for one particular league. Both were correct exactly once, and quietly wrong the moment anything changed.

The setup screen refuses impossible leagues

Two combinations are rejected before a draft can start:

Replacement level

This is the most important derived number in the app. It is the last player at a position who would realistically start somewhere in the league, and it feeds the draft grade, the Overall signal and every value-over-replacement figure.

It is the number of starting slots the league creates at that position, plus that position's share of the FLEX slots, plus one:

base = teams × starters[pos]
flex = teams × flex × flexShare[pos]
rank = round(base + flex) + 1

flexShare = { RB: 0.40, WR: 0.55, TE: 0.05 }

The FLEX shares are how often each position actually wins that slot, which is why running backs and receivers run so much deeper than quarterbacks.

Worked through, at the default settings

Ten teams, one FLEX. Receivers: 10 × 2 = 20 starting slots, plus 10 × 1 × 0.55 = 5.5 from the FLEX, giving 25.5, rounded to 26, plus one → WR27. Across the board that is QB11, RB25, WR27, TE12, K11 and D/ST11.

Move to twelve teams and the same formula gives QB13, RB30, WR32, TE14, K13 and D/ST13. Nothing was retyped.

Roster limits

How many of a position a computer team will ever hold: its starters, its share of the FLEX, and a fixed depth allowance of 3 for quarterbacks, 5 for backs and receivers, and 2 for tight ends, kickers and defences. At the default settings that works out to 4 quarterbacks, 8 backs, 8 receivers, 3 tight ends, 3 kickers and 3 defences.

04How the CPU teams draft

Each computer team scores every available player and takes the lowest. The score starts at average draft position and is multiplied by how badly that team needs the position:

score = (adp + jitter) × need × risk
need0.80still filling a starting slot
1.00sensible depth, up to two past the starters
1.45hoarding
999refuses to take the player at all
risk1.35doubtful, or physically unable to perform

A team refuses a player outright when:

Kickers and defences go last

Measured back from the final round rather than pinned to a fixed number, so it holds at any league length: kickers become available for the last two rounds, defences for the last three.

Worked through, at the default settings

Fourteen rounds, so defences come off the board from round 12 and kickers from round 13. Run a fifteen-round draft and both shift a round later on their own.

The wobble

A draft where every computer team took the best available player would be identical every time. Each player gets a fixed offset of roughly ±3 draft places, generated from a seed chosen when the draft starts. It is deterministic, not random: it stays put for the whole draft, so undoing a pick does not reshuffle how the room thinks, and a resumed draft behaves exactly like the one you left.

Picks are made one at a time on a three-quarter-second timer so you can watch the board fill in. Skip jumps straight to your turn.

05Tiers

A tier is a run of players at one position with no meaningful gap between them. The point is the sentence it lets the app say: not "take the best player available" but "take him now or lose the whole tier".

A new tier starts when the gap to the previous player is large relative to where you are on the board:

threshold = max(2, previousPlayerAdp × 0.13)

Proportional, because two picks apart means something at pick 5 and nothing at pick 120. A tier also breaks after six players regardless: gaps stop growing as fast as ADP does, so deep in the board nothing ever clears the threshold and a single tier would otherwise swallow half the position.

06The draft grade

Four components. Each is computed the same way for every team in the room, then scaled from 0 to 100 against the other teams, then weighted. Your grade is a ranking against the people you actually drafted with, not against the league at large — which is why somebody always gets the top grade and somebody always gets the bottom one.

Starter strength50%Every player in your best legal starting lineup, scored by how many places above replacement level they rank at their position. Uses the replacement ranks derived in section 03.
Draft value25%How far each player fell past the board's own order when you took them. Taking a player later than his rank says is a bargain; taking him earlier is a reach.
Roster construction15%Starts at 100. Minus 14 for each unfilled starting slot, minus 9 for every quarterback, kicker or defence beyond what the league starts, minus 6 for being thin at running back or receiver.
Bye week safety10%Minus 20 for every starter beyond the second sharing the same bye week. Judged on the starting lineup only, because bench byes cost nothing.

The weighted total is ranked, and the ranks are handed letters from a fourteen-step scale running A+ down to F, long enough to give every seat in a fourteen-team room its own letter.

Every input to this is printed on the Analysis tab while you draft. If a grade looks wrong, the four bars will show you which component caused it.

07The three signals on a player

Open any player and there are three meters. They are model output, not a consensus of analysts, and they disagree with the market on purpose — that disagreement is most of what they measure.

Overall

Projected points above a replacement starter at that position, expressed against the best such figure on the board. A player projected for exactly replacement production scores zero regardless of name.

Upside

Starts at 20 and rises with: projecting at least four positional ranks better than his draft position (up to +35), three years or less in the league (+18), first on his depth chart (+14), age 24 or under (+10), and points per game up more than 20% across his last two full seasons (+15).

Bust risk

Starts at 12 and rises with: being drafted at least four ranks ahead of where he projects (up to +35), being ruled out (+40) or carrying a lesser injury designation (+22 or +12), age (+20 for a back at 28 or older, +15 for a receiver or tight end at 31, +12 for a quarterback at 36), sitting second or lower on the depth chart (+15), playing 12 games or fewer in his last active season (+14), and having missed real time in at least half of his seasons (+12).

A player's position always comes from his listed position, never from which statistics happen to be present. Christian McCaffrey threw one pass in 2025, and an earlier version checked for passing data to decide what somebody was — which rendered him as a quarterback with no receiving line at all. Having data is not the same as being a thing.

08Saving and resuming

A draft in progress is stored in your own browser and nowhere else: your seat, the clock length, the seed, the league settings and an ordered list of player names. Refreshing the page no longer destroys a draft.

It refuses to restore rather than restore something broken, in two cases:

09What it deliberately does not do

ADP from Fantasy Football Calculator. Player, injury, statistical, projection and depth chart data from Sleeper. Fantasy points recomputed under the scoring rules in section 02. The data files are regenerated daily; the app shows you when, under the Start button.

← Back to the Draft Room