S5 (a1): prop viability — lineups, injury wire, date navigation
- lineupService: statsapi hydrate=lineups (live shape verified) → CONFIRMED (batting slot) / NOT_IN (team posted without the player) / PROJECTED (not posted). 10-min cache, pure parser, injectable. - NOT_IN visibly KILLS the grade on the slate: struck through + NOT IN LINEUP chip, parlay/book actions suppressed. The locked ledger read is untouched — honesty is showing the read is dead, not deleting it. - injuryService: ESPN injuries feed → OUT/GTD/PROB chips (unknown status → no chip, never invented). Chips on slate strips via ViabilityChips. - Date navigation on the Slate: YESTERDAY (results surface — finals + THE SETTLE panel of that date's settled reads w/ outcome + CLV chips, via new ?date= filter on /api/ledger/model) / TODAY / TOMORROW (schedule until lines post). Odds/grades/pitcher layers are TODAY's and never fake other dates; 60s poll only refreshes today. - Routes /api/schedule/:sport/lineups + /injuries + Next proxies. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -314,9 +314,22 @@ function slateTeamsMatch(a, b) {
|
||||
* @param {number} [now]
|
||||
* @param {{home?: string, away?: string} | null} [gameTeams]
|
||||
*/
|
||||
function buildPlayerStripsFromProps(gameProps, gradeIndex, deltaIndex, now = Date.now(), gameTeams = null) {
|
||||
function buildPlayerStripsFromProps(gameProps, gradeIndex, deltaIndex, now = Date.now(), gameTeams = null, viability = null) {
|
||||
const byPlayer = {};
|
||||
const order = [];
|
||||
// Session 64 (A1-S5) — PROP VIABILITY resolution per player:
|
||||
// lineups.byPlayer hit → CONFIRMED (slot n)
|
||||
// team posted, player absent → NOT_IN (grade renders dead)
|
||||
// team not posted → PROJECTED. Absent feeds → no chips at all.
|
||||
const lineupStatusFor = (pk, team) => {
|
||||
const lu = viability && viability.lineups;
|
||||
if (!lu || !lu.byPlayer || Object.keys(lu.byPlayer).length === 0) return null;
|
||||
if (lu.byPlayer[pk]) return lu.byPlayer[pk];
|
||||
const posted = team && Array.isArray(lu.postedTeams)
|
||||
&& lu.postedTeams.some((t) => slateTeamsMatch(t, team));
|
||||
return posted ? { status: 'not_in' } : { status: 'projected' };
|
||||
};
|
||||
const injuryFor = (pk) => (viability && viability.injuries && viability.injuries[pk]) || null;
|
||||
for (const p of gameProps || []) {
|
||||
if (!p || !p.player) continue;
|
||||
// Session 46 — group by the normalized key so name variants ("A.J. Ewing"
|
||||
@@ -334,6 +347,8 @@ function buildPlayerStripsFromProps(gameProps, gradeIndex, deltaIndex, now = Dat
|
||||
player: displayName(p.player),
|
||||
team: knownTeam,
|
||||
archetype: rec && rec.archetype ? { primary: rec.archetype } : undefined,
|
||||
lineup: lineupStatusFor(pk, knownTeam),
|
||||
injury: injuryFor(pk),
|
||||
stats: [],
|
||||
props: [],
|
||||
};
|
||||
@@ -387,7 +402,12 @@ function buildPlayerStripsFromProps(gameProps, gradeIndex, deltaIndex, now = Dat
|
||||
const ex = byStat.get(sk);
|
||||
if (!ex || (pr.grade && !ex.grade)) byStat.set(sk, pr);
|
||||
}
|
||||
return { ...e, props: [...byStat.values()] };
|
||||
// Session 64 (A1-S5) — NOT-IN visibly kills every graded prop on the
|
||||
// strip (struck through + chip in the UI). The locked ledger read is
|
||||
// untouched — honesty is SHOWING the read is dead, not deleting it.
|
||||
const dead = e.lineup && e.lineup.status === 'not_in';
|
||||
const props = [...byStat.values()].map((pr) => (dead && pr.grade ? { ...pr, dead: true } : pr));
|
||||
return { ...e, props };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user