diff --git a/apps/web/src/workers/sim.worker.test.ts b/apps/web/src/workers/sim.worker.test.ts index 0665617..3081a23 100644 --- a/apps/web/src/workers/sim.worker.test.ts +++ b/apps/web/src/workers/sim.worker.test.ts @@ -1230,6 +1230,20 @@ describe('sim worker narrative APIs', () => { expect(wins.filter((winTotal) => winTotal < 81).length).toBeGreaterThanOrEqual(10); }); + it('keeps setup preview projections conservative instead of clustering at 97 wins', () => { + const workerApi = api as typeof api & MinorLeagueWorkerApi; + const wins = TEAMS.map((team) => parseProjectedWins(workerApi.getSetupPreview({ + seed: 2124, + userTeamId: team.id, + difficulty: 'standard', + }).projectedRecord)); + + expect(Math.max(...wins)).toBeLessThanOrEqual(95); + expect(wins.filter((winTotal) => winTotal >= 95)).toHaveLength(1); + expect(wins.filter((winTotal) => winTotal >= 90).length).toBeLessThanOrEqual(6); + expect(wins.filter((winTotal) => winTotal >= 97)).toHaveLength(0); + }); + it('initializes career mode and exposes the GM career ledger', () => { startGameWithOptions({ seed: 919, diff --git a/packages/sim-core/src/onboarding/dayOne.ts b/packages/sim-core/src/onboarding/dayOne.ts index 1bcec7d..f5a3166 100644 --- a/packages/sim-core/src/onboarding/dayOne.ts +++ b/packages/sim-core/src/onboarding/dayOne.ts @@ -159,8 +159,8 @@ interface DayOneTeamMetadata { const REQUIRED_LINEUP_POSITIONS: readonly Position[] = ['C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF', 'DH']; const LEAGUE_AVERAGE_WINS = 81; -const PROJECTED_WIN_MAX_SPREAD = 20; -const PROJECTED_WIN_CURVE_EXPONENT = 0.82; +const PROJECTED_WIN_MAX_SPREAD = 14; +const PROJECTED_WIN_CURVE_EXPONENT = 1.2; const ROSTER_WIN_WEIGHTS = { offense: 0.4, rotation: 0.34, diff --git a/packages/sim-core/tests/dayOne.test.ts b/packages/sim-core/tests/dayOne.test.ts index 97df985..0559e52 100644 --- a/packages/sim-core/tests/dayOne.test.ts +++ b/packages/sim-core/tests/dayOne.test.ts @@ -237,6 +237,16 @@ describe('day one helpers', () => { expect(wins.filter((winTotal) => winTotal < 81).length).toBeGreaterThanOrEqual(10); }); + it('keeps setup projections conservative instead of assigning many elite records', () => { + const players = generateLeaguePlayers(new GameRNG(2124), TEAMS.map((team) => team.id)); + const wins = TEAMS.map((team) => buildDayOneOrgReview(players, team.id).projectedWins); + + expect(Math.max(...wins)).toBeLessThanOrEqual(95); + expect(wins.filter((winTotal) => winTotal >= 95)).toHaveLength(1); + expect(wins.filter((winTotal) => winTotal >= 90).length).toBeLessThanOrEqual(6); + expect(wins.filter((winTotal) => winTotal >= 97)).toHaveLength(0); + }); + it('builds deterministic teaser copy from the same team and Day One choices', () => { const context = { teamId: 'hou',