Files
stack/src/lead/suspect.py

51 lines
1.5 KiB
Python

"""A suspect is a status change, by coding or by care.
Coding makes a status the person already has visible to the score. Care
changes the underlying state. Demographic reweighting multiplies only the
coding delta. The two are never collapsed into one number.
"""
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True)
class SuspectMove:
"""How far each mechanism moves the score."""
coding_delta: float
care_delta: float
coding_after_reweight: float
def suspect_move(
*,
before_status: str,
after_status: str,
score_before: float,
score_coding: float,
score_care: float,
weight_before: float,
weight_after: float,
) -> SuspectMove:
"""Return the coding delta, the care delta, and the reweighted coding delta.
Raises:
ValueError: the status does not change, the weights are equal, or
the starting weight is zero.
"""
if before_status == after_status:
raise ValueError("a suspect is a status change")
if weight_before == weight_after:
raise ValueError("reweight needs a different weight")
if weight_before == 0:
raise ValueError("weight_before must not be zero")
coding_delta = score_coding - score_before
care_delta = score_care - score_before
return SuspectMove(
coding_delta=coding_delta,
care_delta=care_delta,
coding_after_reweight=coding_delta * (weight_after / weight_before),
)