2026-06-25 17:43:31 +00:00
|
|
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
|
|
|
|
|
|
// Mock the database context before importing any model
|
|
|
|
|
vi.mock("~/database/context", () => ({
|
|
|
|
|
database: vi.fn(),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
import { database } from "~/database/context";
|
|
|
|
|
import { batchSaveFuturesOddsForSimulator } from "../simulator";
|
|
|
|
|
|
|
|
|
|
type SetPayload = Record<string, unknown>;
|
|
|
|
|
|
|
|
|
|
const conflictSetCalls: SetPayload[] = [];
|
|
|
|
|
|
Unify futures odds with the simulation system
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.
Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.
Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
resolve each participant by the configured priority instead of a fixed order.
Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
from the season policy; defaults preserve prior calibration when no context is
passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
context-blend behavioral test, and an updated non-destructive save test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
2026-06-25 22:11:32 +00:00
|
|
|
const onConflictDoUpdate = vi.fn((arg: { set: SetPayload }) => {
|
|
|
|
|
conflictSetCalls.push(arg.set);
|
|
|
|
|
return Promise.resolve(undefined);
|
|
|
|
|
});
|
2026-06-25 17:43:31 +00:00
|
|
|
|
|
|
|
|
const mockDb = {
|
Unify futures odds with the simulation system
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.
Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.
Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
resolve each participant by the configured priority instead of a fixed order.
Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
from the season policy; defaults preserve prior calibration when no context is
passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
context-blend behavioral test, and an updated non-destructive save test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
2026-06-25 22:11:32 +00:00
|
|
|
insert: vi.fn(() => ({
|
|
|
|
|
values: vi.fn(() => ({ onConflictDoUpdate })),
|
|
|
|
|
})),
|
2026-06-25 17:43:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
vi.clearAllMocks();
|
|
|
|
|
conflictSetCalls.length = 0;
|
|
|
|
|
(database as ReturnType<typeof vi.fn>).mockReturnValue(mockDb);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("batchSaveFuturesOddsForSimulator", () => {
|
Unify futures odds with the simulation system
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.
Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.
Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
resolve each participant by the configured priority instead of a fixed order.
Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
from the season policy; defaults preserve prior calibration when no context is
passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
context-blend behavioral test, and an updated non-destructive save test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
2026-06-25 22:11:32 +00:00
|
|
|
it("persists odds without destroying a stored Elo/rating", async () => {
|
2026-06-25 17:43:31 +00:00
|
|
|
await batchSaveFuturesOddsForSimulator([
|
|
|
|
|
{ participantId: "team-1", sportsSeasonId: "season-1", sourceOdds: 550 },
|
|
|
|
|
]);
|
|
|
|
|
|
Unify futures odds with the simulation system
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.
Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.
Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
resolve each participant by the configured priority instead of a fixed order.
Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
from the season policy; defaults preserve prior calibration when no context is
passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
context-blend behavioral test, and an updated non-destructive save test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
2026-06-25 22:11:32 +00:00
|
|
|
// The upsert writes the odds and leaves Elo/rating untouched — whether the
|
|
|
|
|
// odds override them is now decided by the configurable source priority,
|
|
|
|
|
// not by nulling stored values here.
|
|
|
|
|
expect(mockDb.insert).toHaveBeenCalledTimes(1);
|
2026-06-25 17:43:31 +00:00
|
|
|
expect(conflictSetCalls).toHaveLength(1);
|
Unify futures odds with the simulation system
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.
Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.
Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
resolve each participant by the configured priority instead of a fixed order.
Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
from the season policy; defaults preserve prior calibration when no context is
passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
context-blend behavioral test, and an updated non-destructive save test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
2026-06-25 22:11:32 +00:00
|
|
|
expect(conflictSetCalls[0]).toHaveProperty("sourceOdds");
|
|
|
|
|
expect(conflictSetCalls[0]).not.toHaveProperty("sourceElo");
|
|
|
|
|
expect(conflictSetCalls[0]).not.toHaveProperty("rating");
|
2026-06-25 17:43:31 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("is a no-op when given no inputs", async () => {
|
|
|
|
|
await batchSaveFuturesOddsForSimulator([]);
|
Unify futures odds with the simulation system
Make the futures-vs-Elo relationship an explicit, configurable rule and fix
futures odds failing to override stored Elo.
Root causes addressed:
- resolveSourceElos/resolveRatings used a hardcoded precedence (direct Elo ->
projectedWins -> projectedTablePoints -> odds). The prior fix nulled sourceElo
on futures entry but not projections, which still outranked odds.
- The override relied on a destructive null-on-save hack that also wiped
manually entered Elo.
- Blended simulators buried their Elo/odds weight in module constants.
- Futures odds were not surfaced on the /admin/simulators inventory.
Changes:
- Add a configurable source policy: sourceEloPriority (ordered) and oddsWeight,
parsed/clamped in getSimulatorInputPolicy. resolveSourceElos/resolveRatings now
resolve each participant by the configured priority instead of a fixed order.
Futures-centric simulators (ncaam, ncaaw, world_cup, ncaa_football,
college_hockey) default to a futures-override priority.
- Drop the destructive nulling in batchSaveFuturesOddsForSimulator and
batchSaveSourceOdds; override is now governed by policy, preserving stored Elo.
- Thread an optional SimulationContext (oddsWeight) through the Simulator
interface so blended sims (UCL, World Cup, NCAA FB, MLB) read the blend weight
from the season policy; defaults preserve prior calibration when no context is
passed.
- Add a "Futures vs. Elo" strategy control and Odds Blend Weight input to the
Simulator Setup input-policy card, persisted via save-input-policy.
- Surface futures on /admin/simulators: a source badge and a Futures Odds quick
link; extend listSportsSeasonSimulatorSummaries with odds source info.
- Tests: configurable priority override (Elo/projections/rating), oddsWeight
parsing/clamping, prefersFuturesOdds, manifest defaults, an NCAA Football
context-blend behavioral test, and an updated non-destructive save test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhNeB7gN6VKene7sdbBVQT
2026-06-25 22:11:32 +00:00
|
|
|
expect(mockDb.insert).not.toHaveBeenCalled();
|
2026-06-25 17:43:31 +00:00
|
|
|
});
|
|
|
|
|
});
|