File size: 1,605 Bytes
7a31ba6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Styling and color utilities for the leaderboard display."""

import pandas as pd


def format_metric_value(value: float | None, fmt: str) -> str:
    """Format a metric value for display."""
    if value is None or pd.isna(value):
        return "--"
    try:
        return fmt.format(float(value))
    except Exception:
        return f"{value}"


def hex_to_rgb(code: str) -> tuple[int, int, int]:
    """Convert hex color code to RGB tuple."""
    code = code.lstrip("#")
    return tuple(int(code[i:i + 2], 16) for i in (0, 2, 4))


def rgb_to_hex(rgb: tuple[float, float, float]) -> str:
    """Convert RGB tuple to hex color code."""
    return "#" + "".join(f"{max(0, min(255, int(round(channel)))):02x}" for channel in rgb)


def interpolate_color(start_hex: str, end_hex: str, ratio: float) -> str:
    """Interpolate between two colors based on ratio."""
    ratio = max(0.0, min(1.0, ratio))
    start = hex_to_rgb(start_hex)
    end = hex_to_rgb(end_hex)
    blended = tuple(start[i] + (end[i] - start[i]) * ratio for i in range(3))
    return rgb_to_hex(blended)


def cell_color(value: float | None, minimum: float | None, maximum: float | None, better: str) -> str:
    """Get cell background color based on value and metric direction."""
    if value is None or pd.isna(value) or minimum is None or maximum is None:
        return "#f3f4f6"
    if abs(maximum - minimum) < 1e-9:
        ratio = 0.5
    else:
        ratio = (float(value) - minimum) / (maximum - minimum)
    if better == "higher":
        ratio = 1.0 - ratio
    return interpolate_color("#d9f7be", "#ffccc7", ratio)