# Double Duty simulation model

Updated September 10, 2026. These are transparent game-design coefficients, not a predictive sports model or official scouting grades.

## Adaptation from Puck Perfection

Read-only reference: Puck Perfection `docs/SCORING.md`, supplied by the user, current working copy read September 10, 2026. We borrowed its separation of roster evaluation from season outcomes, meaningful depth, fixed weak-slot anchors, postseason-specific rotations, and qualitative roster profiles. Puck Perfection’s source and live game were not changed.

We did not transplant hockey’s goalie ceiling, chemistry bonuses, 84-game perfect-season gates, tier labels, or playoff structure. There is insufficient sport-specific evidence to justify those mechanisms here. Scoring and roster formats remain separate per league.

## Shared guarantees

- Server validation checks eligibility, unique players and exact budget before simulation. Difficulty multiplies leaderboard points only, never strength.
- Every team, including the user, intact opponents and the unused combined pool, uses the same player-based evaluation. NBA/MLB no longer pit a player-derived user rating against historical-differential opponent ratings.
- Reference mean and standard deviation come from the frozen current eligible pools, separately for regular season and postseason. Candidate edits do not change that reference. Historical standings still determine the difficulty bonus and schedule placement.
- For NBA/MLB/EPL, an unfilled opponent slot explicitly receives rating 45, rather than inventing a player. NFL uses 35 for a missing skill/slot. Opponent selection is a deterministic greedy eligible lineup; it is not a global lineup optimizer. User lineups must be complete and legal.
- Fixed-slot quality `q(r) = r - 0.15 × max(0, 60-r)`. There is no max–min/spread penalty: raising any selected player's rating cannot lower the same fixed lineup's raw rating. Clamping can make increases neutral at the strength ceiling. This guarantee concerns model strength, not any particular random season record.
- Interchangeable reserves and pitchers are ranked by quality when they receive unequal weights. Swapping their display slots cannot improve strength.
- Scores generate winners and regular-season scoring totals. There is no independent season-record roll. Positive differential does not guarantee a winning record in a finite season.
- The seed includes the data version, scoring version, sorted source pair and canonical slot assignments. The server stores results, roster snapshots and versions; old results are not recomputed. Old-version challenges become read-only. Idempotent retries retain their original result.

## Basketball / NBA — nba-rotation-v4

Player evaluation retains recent NBA box-score Game Score, sample shrinkage and dated rookie pedigree. The shared roster-quality transform is applied before weighted aggregation.

| Rotation | Regular season | Postseason, including play-in |
| --- | --- | --- |
| Each of five starters | 14% | 16.8% |
| Reserves, strongest to weakest | 7.5, 6, 4.5, 3.5, 2.5, 2, 1.5, 1, 0.8, 0.7% | 5, 4, 3, 1.5, 1, 0.5, 0.3, 0.3, 0.2, 0.2% |

These are influence weights representing a shorter postseason rotation, not tracked minutes or a fatigue/injury simulator. A bench player does not automatically replace a user-selected starter.

Strength is a roster z-score multiplied by 4.5, clamped to ±13.5. The reference standard deviation has a floor of 1 rating point. Home advantage is 2.4. Each game draws scores around `113 ± differential/2`, independent normal noise with standard deviation 11, minimum 65. Ties receive a simplified decisive extra point, weighted by differential. This is not possession-level overtime.

82-game balanced schedule, existing play-in and four best-of-seven rounds. Score: `(2 × wins + 25 × playoff rounds won + 100 × champion) × difficulty`; play-in wins do not count as rounds won. NBA currently uses the labelled $164.961M hard game budget, not a CBA exception/apron simulator.

## Baseball / MLB — mlb-rotation-v3

Player evaluation retains OPS, baserunning, ERA, strikeout rate and MLB Pipeline sample-weighted priors. Fixed-slot quality applies to batting and pitching ratings.

Regular influence: batting lineup 45% equally across nine; four bench players 5% equally; five starters 32.5% equally; eight relievers 17.5% equally.

Postseason influence: batting lineup 48% equally; bench 2% split 0.8/0.6/0.4/0.2%; starting pitching 30% with ranked shares 35/29/23/10/3%; bullpen 20% with ranked shares 25/20/16/13/10/7/5/4%. Every roster slot retains nonzero influence. This is an aggregate series rotation, not game-by-game pitcher availability or rest scheduling.

Strength is z-score ×0.65, clamped ±1.95; reference SD floor 1. Games use Poisson runs with means `4.4 × exp(±differential/18)`, clamped 0.2–9; home advantage 0.15. Ties receive a simplified decisive extra run weighted by differential. Keep the conservative run response: widening it made the strongest affordable merged calibration pair average roughly 127 wins, which was too aggressive.

162-game balanced schedule and the existing 12-team format: Wild Card best-of-three, Division Series best-of-five, LCS/World Series best-of-seven, appropriate byes and home schedules. Score: `(wins + 25 × rounds won + 100 × champion) × difficulty`.

## Soccer / Premier League — epl-depth-v2

Keep the performance model's expected-goal involvement and defensive/goalkeeper outcomes with minutes-based shrinkage. The fixed quality anchor makes weak slots matter without penalizing star upgrades. Existing starting-XI and substitute weights remain: GK 8%, four DEF 6.5% each, five MID 7.5% each, FWD 8.5%, reserve GK 2%, eight reserve outfield players 2.25% each.

Strength is z-score ×0.45, clamped ±1.35; reference SD floor 1. Poisson goals with means `1.35 × exp(±differential/2.7)`, clamped 0.2–9; home advantage 0.2. Draws are retained. A 38-match double round robin determines the champion by points and existing tiebreakers. No postseason rotation or artificial playoff bracket. Score: `(league points + 100 × champion) × difficulty`.

## American football / NFL — nfl-blocking-v4

Retain dated player-skill assessments and the bounded verified draft adjustment, then evaluate passing, rushing, pass defense, run defense and special teams. Apply `q(block) = block - 0.25 × max(0, 60-block)` to each offensive lineman’s pass blocking and each TE/OL run-blocking input. This modest fixed-floor treatment makes a weak blocker matter while a better blocker can never worsen that unit. All other skill weights are unchanged.

Passing: 45% QB skills, 25% OL pass blocking, 30% receiving. Rushing: 55% TE/OL run blocking, 45% runner. Pass defense: 45% pass rush, 55% coverage. Run defense: 55% shedding, 45% tackling. These four units blend 92% starters with 8% relevant reserve overall ratings. Special teams: 55% kicking, 40% punting, 5% long snapper assessment. Unit z-scores reference all intact current pools, SD floor 2 and clamp ±4.

The existing drive model matches offense against opponent defense, with 10–13 drives, touchdown/field-goal chances and simplified overtime. The same player units compete in the postseason. The model does not add a hockey-style shortened rotation to football. Keep 17 games, seven qualifiers per conference, byes/reseeding and single-game playoffs. Score: `(10 × wins + 5 × ties + 20 × qualification + 25 × playoff wins + 80 × champion) × difficulty`.

## Challenges, display and calibration

Basketball and baseball friend challenges now use the same game-score function and postseason evaluation as the championship, on a neutral court/field in a best-of-seven. NFL already uses the same neutral single-game drive simulation. Soccer is one neutral friendly and can end in a draw. No synthetic winner-first score decoration remains in these paths.

Roster profiles are descriptions, not additional modifiers. NBA/MLB/EPL unit ratings at least 75 are “Strong,” below 60 “Needs depth,” otherwise “Steady.” NFL uses standardized unit strength at least +0.75 (“Strong”), below -0.75 (“Needs help”), otherwise “Steady.” Historical results without profiles still render normally.

Verification:

- `npm run test:scoring`: fixed-lineup upgrades in both phases, interchangeable slot invariance, reference parity, total points/runs/goals for = against, wins = losses, EPL points arithmetic, deterministic replay/challenges, soccer draws, blocking upgrades and 90,000 neutral games across NBA/MLB/EPL.
- `npm run test:calibration`: 300 merged seasons per NBA/MLB/EPL; actual season and championship structures, home schedules and deterministic replay.
- `npm run test:nfl`: 300 merged seasons plus 400 intact-league seasons; drive scoring, schedule and playoff validation.
- Existing budget, pedigree, API, saved-run and browser checks remain required for this release.

Evidence: `data/scoring-calibration.json`, `data/calibration.json`, `data/nfl-calibration.json`. Release gates reject evidence with stale data/scoring versions. Neutral anchors are selected by the model; merged anchors use dated strong/middle/weak source standings. A hard budget and construction heuristic can make a strong source pair produce a weaker affordable roster. These tests establish internal behavior and plausible ranges; they are not independent predictive validation, actual historical replays or proof of player-rating accuracy. Current source limitations remain documented in the roster and data audits.
