Lead angles and storylines
- Concept
- Engine v0.18.0
- Facts schema 0.10.0 and later
- commishdesk.com/docs/leads-and-storylines/
Definition
These two lists are the engine's own suggestions for what an issue could open on. They are chosen in code from the numbers, not by the narrator, and each carries a factual one-sentence hook built from those numbers.
Lead candidates are ranked angles for the lead of this issue. Weekly kinds, in priority order:
lineup_loss: a team lost a game it should have won: a perfect lineup would have added more points than the team lost by;biggest_blowout: the week's blowout (seeblowout-and-week-shape);closest_game: the smallest margin;week_high_score: the best score of the week, which is always available as the floor.
An angle that led one of the last few issues steps behind the fresh ones, so leads rotate. Draft-recap kinds are positional_run, manager_approach, positional_hoard and biggest_score.
Storyline candidates are threads that run across weeks. A thread opens the first week its signal fires, keeps its weeks_running count while the signal continues, and closes the week the signal stops. Its id is <kind>:<roster_id>. Weekly kinds are luck_extreme (season luck of at least 1.5 in either direction), streak (the longest active streak, at least 3) and power_climb (a model-rank move of at least 3). Draft-recap kinds are grade_extreme, boldest_swing and round_stack.
Worked example
Fixture expected-weekly-facts-week10.json
| Row | rank |
|---|---|
| Row 1 | 1 |
| Row 2 | 2 |
Fixture: tests/fixtures/facts/expected-weekly-facts-week10.json (the anonymized league "Trench Warfare").
{
"lead_candidates": [
{
"rank": 1,
"kind": "lineup_loss",
"roster_ids": [
"7"
],
"hook": "Kneel-Down Koalas lost by 6.06, and a perfect lineup adds 108.86, including TreVeyon Henderson."
},
{
"rank": 2,
"kind": "biggest_blowout",
"roster_ids": [
"1",
"5"
],
"hook": "Flea Flicker Union beat Nickel Newts by 138.19, the week's biggest blowout."
}
],
"storyline_candidates": [
{
"id": "luck_extreme:12",
"kind": "luck_extreme",
"roster_ids": [
"12"
],
"hook": "Yardage Yaks has run the league's best luck, +2.5 wins over expectation.",
"weeks_running": 1
},
{
"id": "streak:11",
"kind": "streak",
"roster_ids": [
"11"
],
"hook": "Bubble-Screen Bobcats has lost six straight.",
"weeks_running": 1
}
]
}
Roster 7 (Kneel-Down Koalas) lost by 6.06, and a perfect lineup adds 108.86 points, so lineup_loss leads: 108.86 is more than 6.06, and the gap is the largest of any losing team. The week's biggest blowout, roster 1 over roster 5 by 138.19, ranks second. For storylines, Yardage Yaks (roster 12) carry the league's best luck, +2.5, which clears the 1.5 threshold, and Bubble-Screen Bobcats (roster 11) have a six-game losing streak, well over the length of three. Both have run for one week.
See Lead angles and storylines in a full league
Put in your Sleeper username or league ID, or look around a fictional league first.
Supported: Sleeper · See supported apps
See a full league while we open sign-ups.
Code
Show the code commishdesk/facts/leads.py::build_weekly_lead_candidates
Source: commishdesk/facts/leads.py::build_weekly_lead_candidates
def build_weekly_lead_candidates(
teams: list[WeeklyTeam],
period: WeeklyPeriod,
*,
recent_kinds: Sequence[str] = (),
) -> list[LeadCandidate]:
"""Ranked lead angles for the weekly recap (Story 5.9).
Mirrors :func:`build_lead_candidates`'s shape: only detectors that fire are
emitted, in :data:`WEEKLY_LEAD_KIND_PRIORITY` order, then ``rank`` is
renumbered ``1..N``. Returns ``[]`` only when no roster played a game this
week — the ``week_high_score`` floor otherwise guarantees at least one angle,
so a ``lineup_loss`` read is never buried behind a single high score (FR-14).
``recent_kinds`` are the angles the league's last Issues led on. An angle that
just led steps behind the fresh ones (the kind priority still orders each
group), so a season rotates its leads instead of opening on the same story
every week; when every fired angle is recent, or none is, the plain priority
order stands. ``lineup_loss`` still leads any week that has not just used it.
"""
angles = [
_lineup_loss(teams),
_biggest_blowout(teams, period),
_closest_game(teams, period),
_week_high_score(teams),
]
fired = [a for a in angles if a is not None]
fired.sort(key=lambda a: WEEKLY_LEAD_KIND_PRIORITY.index(a.kind))
fired = [a for a in fired if a.kind not in recent_kinds] + [a for a in fired if a.kind in recent_kinds]
return [a.model_copy(update={"rank": i}) for i, a in enumerate(fired, start=1)]Edge cases
- Empty lists. A weekly document has no lead candidates only when no team played. Otherwise the high-score angle is a guaranteed floor. A draft with no picks has none either.
- Rotation. An angle that just led steps behind the others, and if every angle is recent the plain priority order stands.
- Playoffs.
luck_extremeandstreakstorylines stop firing in playoff weeks, because those values are frozen.power_climbstill fires. - Pruning. A resolved storyline is dropped four weeks after it closes.
- Draft recap storylines
grade_extremefire only for a grade at the very top (A or A+) or bottom (D- or F) of the scale, so a middling "lowest grade" never becomes a thread. - Hooks are plain. They are factual sentences. The narrator may rewrite them in voice, and the safety checks verify the numbers it uses.
See Lead angles and storylines in a full league
Put in your Sleeper username or league ID, or look around a fictional league first.
Supported: Sleeper · See supported apps
See a full league while we open sign-ups.