feat: refine scoring with hole info, putts, penalties, bunkers

Co-authored-by: aider (openrouter/thinkingmachines/inkling-small:free) <aider@aider.chat>
This commit is contained in:
Jiří Stachandaider committed 2026-10-09 22:52:46 +02:00
1 parent 9f72bf3a6a
commit d7c491ec22
3 files changed
+123 -76

No files matched your search

+77 -51
View File
@@ -28,6 +28,8 @@ class Hole(Base):
number = Column(Integer, nullable=False)
par = Column(Integer, nullable=False)
yardage = Column(Integer, nullable=False)
yardage_meters = Column(Integer, default=0)
tee = Column(String, default="White")
class Round(Base):
__tablename__ = "rounds"
@@ -46,6 +48,14 @@ class HoleScore(Base):
completed = Column(Boolean, default=False)
fairway_hit = Column(Boolean, default=False)
gir = Column(Boolean, default=False)
putts_green = Column(Integer, default=0)
putts_off_green = Column(Integer, default=0)
penalty_water = Column(Boolean, default=False)
penalty_ob = Column(Boolean, default=False)
penalty_lost = Column(Boolean, default=False)
bunker_greenside = Column(Boolean, default=False)
bunker_fairway = Column(Boolean, default=False)
unfinished = Column(Boolean, default=False)
class Putt(Base):
__tablename__ = "putts"
@@ -86,15 +96,15 @@ def init_mock():
db.commit()
db.refresh(course)
holes = [
Hole(course_id=course.id, number=1, par=4, yardage=350),
Hole(course_id=course.id, number=2, par=3, yardage=180),
Hole(course_id=course.id, number=3, par=5, yardage=520),
Hole(course_id=course.id, number=4, par=4, yardage=390),
Hole(course_id=course.id, number=5, par=3, yardage=160),
Hole(course_id=course.id, number=6, par=4, yardage=410),
Hole(course_id=course.id, number=7, par=5, yardage=540),
Hole(course_id=course.id, number=8, par=4, yardage=370),
Hole(course_id=course.id, number=9, par=3, yardage=190),
Hole(course_id=course.id, number=1, par=4, yardage=350, yardage_meters=320, tee="White"),
Hole(course_id=course.id, number=2, par=3, yardage=180, yardage_meters=165, tee="White"),
Hole(course_id=course.id, number=3, par=5, yardage=520, yardage_meters=480, tee="Yellow"),
Hole(course_id=course.id, number=4, par=4, yardage=390, yardage_meters=360, tee="White"),
Hole(course_id=course.id, number=5, par=3, yardage=160, yardage_meters=145, tee="Red"),
Hole(course_id=course.id, number=6, par=4, yardage=410, yardage_meters=375, tee="Blue"),
Hole(course_id=course.id, number=7, par=5, yardage=540, yardage_meters=495, tee="Yellow"),
Hole(course_id=course.id, number=8, par=4, yardage=370, yardage_meters=340, tee="White"),
Hole(course_id=course.id, number=9, par=3, yardage=190, yardage_meters=175, tee="Red"),
]
db.add_all(holes)
db.commit()
@@ -129,7 +139,7 @@ def start_round(req: StartRoundRequest):
db.refresh(round_obj)
holes = db.query(Hole).filter(Hole.course_id == req.course_id).all()
for h in holes:
hs = HoleScore(round_id=round_obj.id, hole_number=h.number, strokes=0, skipped=False, completed=False, fairway_hit=False, gir=False)
hs = HoleScore(round_id=round_obj.id, hole_number=h.number, strokes=0, skipped=False, completed=False, fairway_hit=False, gir=False, putts_green=0, putts_off_green=0, unfinished=False)
db.add(hs)
db.commit()
db.close()
@@ -144,7 +154,7 @@ def get_course():
return {
"id": course.id,
"name": course.name,
"holes": [{"number": h.number, "par": h.par, "yardage": h.yardage} for h in holes]
"holes": [{"number": h.number, "par": h.par, "yardage": h.yardage, "yardage_meters": h.yardage_meters, "tee": h.tee} for h in holes]
}
@app.get("/round/{round_id}")
@@ -163,9 +173,7 @@ def get_round(round_id: int):
"holes": []
}
for hs in hole_scores:
putts = db.query(Putt).filter(Putt.hole_score_id == hs.id).all()
penalties = db.query(Penalty).filter(Penalty.hole_score_id == hs.id).all()
bunkers = db.query(Bunker).filter(Bunker.hole_score_id == hs.id).all()
hole = db.query(Hole).filter(Hole.course_id == round_obj.course_id, Hole.number == hs.hole_number).first()
result["holes"].append({
"hole_score_id": hs.id,
"hole_number": hs.hole_number,
@@ -174,21 +182,36 @@ def get_round(round_id: int):
"completed": hs.completed,
"fairway_hit": hs.fairway_hit,
"gir": hs.gir,
"putts": [{"location": p.location} for p in putts],
"penalties": [{"type": p.type} for p in penalties],
"bunkers": [{"location": b.location} for b in bunkers]
"unfinished": hs.unfinished,
"putts_green": hs.putts_green,
"putts_off_green": hs.putts_off_green,
"penalty_water": hs.penalty_water,
"penalty_ob": hs.penalty_ob,
"penalty_lost": hs.penalty_lost,
"bunker_greenside": hs.bunker_greenside,
"bunker_fairway": hs.bunker_fairway,
"hole_info": {
"par": hole.par if hole else None,
"yardage_meters": hole.yardage_meters if hole else 0,
"tee": hole.tee if hole else "White"
}
})
db.close()
return result
class UpdateHoleRequest(BaseModel):
strokes: int = 0
strokes: int = 1
skipped: bool = False
completed: bool = False
fairway_hit: bool = False
putts: list = []
penalties: list = []
bunkers: list = []
unfinished: bool = False
putts_green: int = 0
putts_off_green: int = 0
penalty_water: bool = False
penalty_ob: bool = False
penalty_lost: bool = False
bunker_greenside: bool = False
bunker_fairway: bool = False
@app.post("/hole/{hole_score_id}")
def update_hole(hole_score_id: int, req: UpdateHoleRequest):
@@ -201,55 +224,58 @@ def update_hole(hole_score_id: int, req: UpdateHoleRequest):
hs.skipped = req.skipped
hs.completed = req.completed
hs.fairway_hit = req.fairway_hit
hs.unfinished = req.unfinished
hs.putts_green = req.putts_green
hs.putts_off_green = req.putts_off_green
hs.penalty_water = req.penalty_water
hs.penalty_ob = req.penalty_ob
hs.penalty_lost = req.penalty_lost
hs.bunker_greenside = req.bunker_greenside
hs.bunker_fairway = req.bunker_fairway
db.query(Putt).filter(Putt.hole_score_id == hole_score_id).delete()
db.query(Penalty).filter(Penalty.hole_score_id == hole_score_id).delete()
db.query(Bunker).filter(Bunker.hole_score_id == hole_score_id).delete()
for p in req.putts:
db.add(Putt(hole_score_id=hole_score_id, location=p.get("location", "green")))
for pen in req.penalties:
db.add(Penalty(hole_score_id=hole_score_id, type=pen.get("type", "water")))
for b in req.bunkers:
db.add(Bunker(hole_score_id=hole_score_id, location=b.get("location", "greenside")))
putts = db.query(Putt).filter(Putt.hole_score_id == hole_score_id).all()
putts_count = len(putts)
round_obj = db.query(Round).filter(Round.id == hs.round_id).first()
hole = db.query(Hole).filter(Hole.course_id == round_obj.course_id, Hole.number == hs.hole_number).first()
if hole:
all_green = all(p.location == "green" for p in putts) if putts else True
hs.gir = (hs.strokes - putts_count) <= (hole.par - 2) and all_green
total_putts = hs.putts_green + hs.putts_off_green
all_green = hs.putts_off_green == 0
hs.gir = (not hs.unfinished) and (hs.strokes - total_putts) <= (hole.par - 2) and all_green
db.commit()
db.refresh(hs)
db.close()
return {"hole_score_id": hs.id, "gir": hs.gir, "strokes": hs.strokes, "putts": putts_count}
return {
"hole_score_id": hs.id,
"gir": hs.gir,
"strokes": hs.strokes,
"putts_green": hs.putts_green,
"putts_off_green": hs.putts_off_green,
"unfinished": hs.unfinished
}
@app.get("/stats/{round_id}")
def get_stats(round_id: int):
db = SessionLocal()
hs_list = db.query(HoleScore).filter(HoleScore.round_id == round_id).all()
total_strokes = sum(hs.strokes for hs in hs_list if not hs.skipped)
total_putts = 0
fairways = 0
girs = 0
for hs in hs_list:
if hs.skipped:
continue
putts = db.query(Putt).filter(Putt.hole_score_id == hs.id).all()
total_putts += len(putts)
if hs.fairway_hit:
fairways += 1
if hs.gir:
girs += 1
total_strokes = sum(hs.strokes for hs in hs_list if not hs.skipped and not hs.unfinished)
total_putts = sum((hs.putts_green + hs.putts_off_green) for hs in hs_list if not hs.skipped and not hs.unfinished)
fairways = sum(1 for hs in hs_list if hs.fairway_hit and not hs.skipped and not hs.unfinished)
girs = sum(1 for hs in hs_list if hs.gir and not hs.skipped and not hs.unfinished)
penalties = sum(
(1 if hs.penalty_water else 0) + (1 if hs.penalty_ob else 0) + (1 if hs.penalty_lost else 0)
for hs in hs_list if not hs.skipped and not hs.unfinished
)
bunker_greenside = sum(1 for hs in hs_list if hs.bunker_greenside and not hs.skipped and not hs.unfinished)
bunker_fairway = sum(1 for hs in hs_list if hs.bunker_fairway and not hs.skipped and not hs.unfinished)
db.close()
return {
"total_strokes": total_strokes,
"total_putts": total_putts,
"fairways_hit": fairways,
"gir": girs,
"holes_played": len([h for h in hs_list if not h.skipped])
"penalty_strokes": penalties,
"bunker_greenside": bunker_greenside,
"bunker_fairway": bunker_fairway,
"holes_played": len([h for h in hs_list if not h.skipped and not h.unfinished])
}
app.mount("/", StaticFiles(directory="frontend", html=True), name="static")