"""Utility helpers for parsing and formatting values.""" from __future__ import annotations import math import re from datetime import datetime from typing import Any import numpy as np def to_float(value: Any, default: float = np.nan) -> float: """Convert mixed values to float and tolerate noisy numeric strings.""" if value is None: return default if isinstance(value, (int, float)): if isinstance(value, float) and math.isnan(value): return default return float(value) text = str(value).strip() if not text: return default text = text.replace("'", "").replace("_", "") text = re.sub(r"[^0-9.,-]", "", text) if text.count(",") > 0 and text.count(".") > 0: text = text.replace(",", "") elif text.count(",") > 0 and text.count(".") == 0: text = text.replace(",", ".") try: return float(text) except ValueError: return default def to_int(value: Any, default: int | None = None) -> int | None: parsed = to_float(value, np.nan) if np.isnan(parsed): return default return int(round(parsed)) def count_equipment_items(value: Any) -> int: """Count comma/semicolon separated equipment entries.""" if value is None: return 0 text = str(value).strip() if not text or text.lower() in {"none", "nan", "na"}: return 0 separators = re.split(r"[,;|]", text) return len([part for part in separators if part.strip()]) def normalize_label(value: str | None, fallback: str = "unknown") -> str: if not value: return fallback text = str(value).strip() if not text: return fallback return text def compute_age_from_year(year: Any) -> float: current_year = datetime.now().year year_int = to_int(year) if year_int is None: return np.nan age = current_year - year_int if age < 0 or age > 80: return np.nan return float(age) def bool_from_yes_no(value: Any) -> str: if value is None: return "unknown" text = str(value).strip().lower() if text in {"1", "true", "yes", "ja", "y"}: return "yes" if text in {"0", "false", "no", "nein", "n"}: return "no" return "unknown" def format_currency_chf(amount: float) -> str: if amount is None or np.isnan(amount): return "n/a" return f"CHF {amount:,.0f}".replace(",", "'")