RoyAalekh's picture
refactored project structure. renamed scheduler dir to src
6a28f91
"""Basic metrics for scheduler evaluation.
These helpers avoid heavy dependencies and can be used by scripts.
"""
from __future__ import annotations
from typing import Iterable, List, Tuple
def gini(values: Iterable[float]) -> float:
"""Compute the Gini coefficient for a non-negative list of values.
Args:
values: Sequence of non-negative numbers
Returns:
Gini coefficient in [0, 1]
"""
vals = [v for v in values if v is not None]
n = len(vals)
if n == 0:
return 0.0
if min(vals) < 0:
raise ValueError("Gini expects non-negative values")
sorted_vals = sorted(vals)
cum = 0.0
for i, x in enumerate(sorted_vals, start=1):
cum += i * x
total = sum(sorted_vals)
if total == 0:
return 0.0
# Gini formula: (2*sum(i*x_i)/(n*sum(x)) - (n+1)/n)
return (2 * cum) / (n * total) - (n + 1) / n
def utilization(total_scheduled: int, capacity: int) -> float:
"""Compute utilization as scheduled/capacity.
Args:
total_scheduled: Number of scheduled hearings
capacity: Total available slots
"""
if capacity <= 0:
return 0.0
return min(1.0, total_scheduled / capacity)
def urgency_sla(records: List[Tuple[bool, int]], days: int = 7) -> float:
"""Compute SLA for urgent cases.
Args:
records: List of tuples (is_urgent, working_day_delay)
days: SLA threshold in working days
Returns:
Proportion of urgent cases within SLA (0..1)
"""
urgent = [delay for is_urgent, delay in records if is_urgent]
if not urgent:
return 1.0
within = sum(1 for d in urgent if d <= days)
return within / len(urgent)