RoyAalekh's picture
refactored project structure. renamed scheduler dir to src
6a28f91
Raw
History Blame Contribute Delete
1.7 kB
"""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)