Deduplicate handicap calculation into _playing_data helper
Extracts playing_handicaps + strokes_per_hole into a single helper used by both game_page and game_summary, instead of duplicating the logic in each route. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+41
-37
@@ -65,6 +65,44 @@ async def _broadcast(game_id: str, message: dict):
|
|||||||
_connections.get(game_id, set()).difference_update(dead)
|
_connections.get(game_id, set()).difference_update(dead)
|
||||||
|
|
||||||
|
|
||||||
|
def _playing_data(
|
||||||
|
players: list,
|
||||||
|
holes: list,
|
||||||
|
hole_pars: dict,
|
||||||
|
hole_stroke_indices: dict,
|
||||||
|
) -> tuple[dict, dict]:
|
||||||
|
"""Return (playing_handicaps, strokes_per_hole).
|
||||||
|
|
||||||
|
playing_handicaps – {player_id: course_handicap (int) or None}
|
||||||
|
strokes_per_hole – {player_id: {hole_number: strokes_received}}
|
||||||
|
"""
|
||||||
|
course_par = sum(hole_pars.get(h, 0) for h in holes if h in hole_pars)
|
||||||
|
playing_handicaps: dict = {}
|
||||||
|
for p in players:
|
||||||
|
hc = p.get("handicap_snapshot")
|
||||||
|
slope = p.get("slope")
|
||||||
|
rating = p.get("tee_rating")
|
||||||
|
if hc is not None and slope and rating and course_par:
|
||||||
|
playing_handicaps[p["id"]] = round(hc * (slope / 113) + (rating - course_par))
|
||||||
|
else:
|
||||||
|
playing_handicaps[p["id"]] = None
|
||||||
|
|
||||||
|
strokes_per_hole: dict = {}
|
||||||
|
played_with_si = {h: hole_stroke_indices[h] for h in holes if h in hole_stroke_indices}
|
||||||
|
if played_with_si:
|
||||||
|
n_si = len(played_with_si)
|
||||||
|
for p in players:
|
||||||
|
ph = playing_handicaps.get(p["id"])
|
||||||
|
if ph is not None and ph > 0:
|
||||||
|
base, extra = divmod(ph, n_si)
|
||||||
|
strokes_per_hole[p["id"]] = {
|
||||||
|
h: base + (1 if played_with_si[h] <= extra else 0)
|
||||||
|
for h in holes if h in played_with_si
|
||||||
|
}
|
||||||
|
|
||||||
|
return playing_handicaps, strokes_per_hole
|
||||||
|
|
||||||
|
|
||||||
def _calc_skins(players: list, scores: dict, holes: list, carryover: bool = True):
|
def _calc_skins(players: list, scores: dict, holes: list, carryover: bool = True):
|
||||||
"""Returns (skins_per_player, hole_results, unclaimed_pot)"""
|
"""Returns (skins_per_player, hole_results, unclaimed_pot)"""
|
||||||
skins = {p["id"]: 0 for p in players}
|
skins = {p["id"]: 0 for p in players}
|
||||||
@@ -280,31 +318,7 @@ async def game_summary(game_id: str, request: Request, user: dict = Depends(get_
|
|||||||
if row["stroke_index"] is not None:
|
if row["stroke_index"] is not None:
|
||||||
hole_stroke_indices[row["hole_number"]] = row["stroke_index"]
|
hole_stroke_indices[row["hole_number"]] = row["stroke_index"]
|
||||||
|
|
||||||
# Playing handicap per player: HI × (slope / 113) + (course_rating − course_par)
|
playing_handicaps, strokes_per_hole = _playing_data(players, holes, hole_pars, hole_stroke_indices)
|
||||||
course_par = sum(hole_pars.get(h, 0) for h in holes if h in hole_pars)
|
|
||||||
playing_handicaps: dict[str, int | None] = {}
|
|
||||||
for p in players:
|
|
||||||
hc = p.get("handicap_snapshot")
|
|
||||||
slope = p.get("slope")
|
|
||||||
rating = p.get("tee_rating")
|
|
||||||
if hc is not None and slope and rating and course_par:
|
|
||||||
playing_handicaps[p["id"]] = round(hc * (slope / 113) + (rating - course_par))
|
|
||||||
else:
|
|
||||||
playing_handicaps[p["id"]] = None
|
|
||||||
|
|
||||||
# Strokes received per player per hole (requires stroke index data on course)
|
|
||||||
strokes_per_hole: dict[str, dict[int, int]] = {}
|
|
||||||
played_with_si = {h: hole_stroke_indices[h] for h in holes if h in hole_stroke_indices}
|
|
||||||
if played_with_si:
|
|
||||||
n_si = len(played_with_si)
|
|
||||||
for p in players:
|
|
||||||
ph = playing_handicaps.get(p["id"])
|
|
||||||
if ph is not None and ph > 0:
|
|
||||||
base, extra = divmod(ph, n_si)
|
|
||||||
strokes_per_hole[p["id"]] = {
|
|
||||||
h: base + (1 if played_with_si[h] <= extra else 0)
|
|
||||||
for h in holes if h in played_with_si
|
|
||||||
}
|
|
||||||
|
|
||||||
skins_won, skins_hole_results, unclaimed = None, None, 0
|
skins_won, skins_hole_results, unclaimed = None, None, 0
|
||||||
if game["format"] == "skins":
|
if game["format"] == "skins":
|
||||||
@@ -350,23 +364,13 @@ async def game_page(game_id: str, request: Request, user: dict = Depends(get_cur
|
|||||||
if row["stroke_index"] is not None:
|
if row["stroke_index"] is not None:
|
||||||
hole_stroke_indices[row["hole_number"]] = row["stroke_index"]
|
hole_stroke_indices[row["hole_number"]] = row["stroke_index"]
|
||||||
|
|
||||||
# Playing handicap per player: HI × (slope / 113) + (course_rating − par)
|
playing_handicaps, strokes_per_hole = _playing_data(players, holes, hole_pars, hole_stroke_indices)
|
||||||
course_par = sum(hole_pars.values())
|
|
||||||
playing_handicaps: dict[str, int | None] = {}
|
|
||||||
for p in players:
|
|
||||||
hc = p.get("handicap_snapshot")
|
|
||||||
slope = p.get("slope")
|
|
||||||
rating = p.get("tee_rating")
|
|
||||||
if hc is not None and slope and rating and course_par:
|
|
||||||
playing_handicaps[p["id"]] = round(hc * (slope / 113) + (rating - course_par))
|
|
||||||
else:
|
|
||||||
playing_handicaps[p["id"]] = None
|
|
||||||
|
|
||||||
return templates.TemplateResponse("games/game.html", {
|
return templates.TemplateResponse("games/game.html", {
|
||||||
"request": request, "user": user, "game": dict(game),
|
"request": request, "user": user, "game": dict(game),
|
||||||
"players": players, "scores": scores, "totals": totals,
|
"players": players, "scores": scores, "totals": totals,
|
||||||
"holes": holes, "hole_pars": hole_pars, "hole_stroke_indices": hole_stroke_indices,
|
"holes": holes, "hole_pars": hole_pars, "hole_stroke_indices": hole_stroke_indices,
|
||||||
"playing_handicaps": playing_handicaps,
|
"playing_handicaps": playing_handicaps, "strokes_per_hole": strokes_per_hole,
|
||||||
"carryover": bool(game["carryover"]),
|
"carryover": bool(game["carryover"]),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user