import re from typing import Tuple, Dict, List, Any from app.models.stats import PlayerStatRow, TeamTotalsRow, TeamStatistics def parse_made_attempted(value: str) -> Tuple[int, int]: """Parse a field like '5-10' or '5/10' into (made, attempted). Returns (0, 0) if invalid.""" if not value or not isinstance(value, str): return 0, 0 match = re.search(r'(\d+)\s*[\-/\|]\s*(\d+)', value) if match: return int(match.group(1)), int(match.group(2)) return 0, 0 def validate_and_compute_totals(players: List[PlayerStatRow]) -> TeamTotalsRow: """Computes all FIBA-style totals from player rows.""" totals = TeamTotalsRow() for p in players: # Re-parse ratios if integer components are 0 but ratio strings exist if p.fg and p.fg_m == 0 and p.fg_a == 0: p.fg_m, p.fg_a = parse_made_attempted(p.fg) if p.tp and p.tp_m == 0 and p.tp_a == 0: p.tp_m, p.tp_a = parse_made_attempted(p.tp) if p.thp and p.thp_m == 0 and p.thp_a == 0: p.thp_m, p.thp_a = parse_made_attempted(p.thp) if p.ft and p.ft_m == 0 and p.ft_a == 0: p.ft_m, p.ft_a = parse_made_attempted(p.ft) # Update percentages p.fg_pct = round((p.fg_m / p.fg_a * 100), 1) if p.fg_a > 0 else 0.0 p.tp_pct = round((p.tp_m / p.tp_a * 100), 1) if p.tp_a > 0 else 0.0 p.thp_pct = round((p.thp_m / p.thp_a * 100), 1) if p.thp_a > 0 else 0.0 p.ft_pct = round((p.ft_m / p.ft_a * 100), 1) if p.ft_a > 0 else 0.0 # Aggregate totals.pts += p.pts totals.fg_m += p.fg_m totals.fg_a += p.fg_a totals.tp_m += p.tp_m totals.tp_a += p.tp_a totals.thp_m += p.thp_m totals.thp_a += p.thp_a totals.ft_m += p.ft_m totals.ft_a += p.ft_a totals.off += p.off totals.def_reb += p.def_reb totals.reb += p.reb totals.ast += p.ast totals.to_cnt += p.to_cnt totals.stl += p.stl totals.blk += p.blk totals.pf += p.pf totals.fls_on += p.fls_on totals.index += (p.index or 0) # Compute team percentages totals.fg_pct = round((totals.fg_m / totals.fg_a * 100), 1) if totals.fg_a > 0 else 0.0 totals.tp_pct = round((totals.tp_m / totals.tp_a * 100), 1) if totals.tp_a > 0 else 0.0 totals.thp_pct = round((totals.thp_m / totals.thp_a * 100), 1) if totals.thp_a > 0 else 0.0 totals.ft_pct = round((totals.ft_m / totals.ft_a * 100), 1) if totals.ft_a > 0 else 0.0 return totals