BakoAI / app /services /stats_utils.py
Okidi Norbert
Deployment fix: clean backend only
c6abe34
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