""" GET /rounds/stats/summary skal blande org-turnering-runder inn i de samme trend-/snitt-tallene som frittstående runder (scoring-paritet-gap punkt 3, se FEATURE_BACKLOG.md), med kilde-antall vist separat (`rounds_completed_personal`/`rounds_completed_tournament`) -- speiler `app/hole_history.py` sin `times_personal`/`times_tournament`-presedens. Speiler `test_hole_history.py` sitt integrasjonsmønster (ekte router- funksjoner, ikke rå SQL for selve scoringen) for personal/tournament- scoring, men mot `get_rounds_stats_summary` i stedet for hull-historikk. """ from app.auth import CurrentUser from app.routers.individual_tournaments import ( HoleUpdate as TournamentHoleUpdate, update_hole as tournament_update_hole, ) from app.routers.rounds import HoleUpdate as RoundHoleUpdate, get_rounds_stats_summary, update_hole as round_update_hole from tests.conftest import ( add_membership, create_hole, create_org, create_org_hole, create_course, create_participant, create_player, create_round, create_tee, create_tournament, create_tournament_participant, create_tournament_round, create_tournament_round_participant, create_user, ) import app.db as app_db async def _score_personal_hole(round_id, participant_id, user_id, hole_number, score, putts=None): user = CurrentUser(user_id=user_id) await round_update_hole( round_id, participant_id, hole_number, RoundHoleUpdate(score=score, putts=putts, expected_version=None), user=user, ) async def _score_tournament_hole(tournament_id, round_id, rp_id, org_id, user_id, hole_number, score, putts=None): user = CurrentUser(user_id=user_id) await tournament_update_hole( tournament_id, round_id, rp_id, hole_number, TournamentHoleUpdate(gross_strokes=score, putts=putts, expected_version=None), organization_id=org_id, user=user, ) async def _make_completed_personal_round(user_id, *, score_per_hole, putts_per_hole=None, par=4, stat_level="strokes_and_putts"): async with app_db.plain_connection() as conn: round_id = await create_round(conn, user_id) participant_id = await create_participant(conn, round_id, user_id=user_id, is_owner=True) for n in range(1, 19): await create_hole(conn, participant_id, hole_number=n, par=par, stroke_index=n) await conn.execute("UPDATE round_participant SET stat_level = $1 WHERE id = $2", stat_level, participant_id) for n in range(1, 19): await _score_personal_hole( round_id, participant_id, user_id, n, score_per_hole, putts=putts_per_hole, ) async with app_db.plain_connection() as conn: await conn.execute("UPDATE round SET completed_at = now() WHERE id = $1", round_id) return round_id, participant_id async def _make_tournament_round( user_id, *, score_per_hole, putts_per_hole=None, par=4, holes_scored=18, stat_level="strokes_and_putts", set_scheduled_at=True, org_id=None, ): if org_id is None: org_id = await create_org() await add_membership(org_id, user_id, role="member") tournament_id = await create_tournament(org_id) course_id = await create_course(org_id) for n in range(1, 19): await create_org_hole(org_id, course_id, hole_number=n, par=par, stroke_index=n) tee_id = await create_tee(org_id, course_id) tournament_round_id = await create_tournament_round(org_id, tournament_id, course_id) if set_scheduled_at: async with app_db.org_connection(org_id) as conn: await conn.execute("UPDATE tournament_round SET scheduled_at = now() WHERE id = $1", tournament_round_id) player_id = await create_player(org_id, user_id=user_id) tp_id = await create_tournament_participant(org_id, tournament_id, player_id) async with app_db.org_connection(org_id) as conn: await conn.execute("UPDATE tournament_participant SET stat_level = $1 WHERE id = $2", stat_level, tp_id) rp_id = await create_tournament_round_participant(org_id, tournament_round_id, tp_id, tee_id) for n in range(1, holes_scored + 1): await _score_tournament_hole( tournament_id, tournament_round_id, rp_id, org_id, user_id, n, score_per_hole, putts=putts_per_hole, ) return org_id, tournament_round_id, rp_id async def test_blends_personal_and_tournament_rounds(pool): user_id = await create_user() await _make_completed_personal_round(user_id, score_per_hole=5, putts_per_hole=2, par=4) # +18 til par await _make_tournament_round(user_id, score_per_hole=4, putts_per_hole=2, par=4) # +0 til par out = await get_rounds_stats_summary(window="all", user=CurrentUser(user_id=user_id)) assert out.current.rounds_completed == 2 assert out.current.rounds_completed_personal == 1 assert out.current.rounds_completed_tournament == 1 assert out.current.avg_score_to_par == 9.0 # (18 + 0) / 2 async def test_tournament_strokes_only_round_excluded_from_putts(pool): user_id = await create_user() await _make_completed_personal_round(user_id, score_per_hole=4, putts_per_hole=2, par=4) await _make_tournament_round( user_id, score_per_hole=4, putts_per_hole=None, par=4, stat_level="strokes_only", ) out = await get_rounds_stats_summary(window="all", user=CurrentUser(user_id=user_id)) assert out.current.rounds_completed == 2 assert out.current.rounds_completed_tournament == 1 # Kun den frittstående runden sporet putter -- strokes_only-turnerings- # runden skal IKKE forurense putt-snittet (samme regel som gjelder for # en frittstående strokes_only-runde). assert out.current.putts_tracked_rounds == 1 assert out.current.avg_putts_per_18 == 36.0 async def test_incomplete_tournament_round_is_excluded(pool): user_id = await create_user() await _make_completed_personal_round(user_id, score_per_hole=4, putts_per_hole=2, par=4) await _make_tournament_round(user_id, score_per_hole=4, holes_scored=10) # kun 10 av 18 hull out = await get_rounds_stats_summary(window="all", user=CurrentUser(user_id=user_id)) assert out.current.rounds_completed == 1 assert out.current.rounds_completed_personal == 1 assert out.current.rounds_completed_tournament == 0 async def test_tournament_round_without_scheduled_at_is_excluded(pool): user_id = await create_user() await _make_completed_personal_round(user_id, score_per_hole=4, putts_per_hole=2, par=4) await _make_tournament_round(user_id, score_per_hole=4, set_scheduled_at=False) out = await get_rounds_stats_summary(window="all", user=CurrentUser(user_id=user_id)) assert out.current.rounds_completed == 1 assert out.current.rounds_completed_tournament == 0 async def test_tournament_round_in_foreign_org_without_player_row_is_excluded(pool): """`player_organizations_for_user` returnerer kun org-er brukeren har en `player`-rad i -- en fullført turneringsrunde i en org der brukeren IKKE er spiller skal aldri kunne telles med i brukerens egen statistikk.""" user_id = await create_user() other_user_id = await create_user() await _make_completed_personal_round(user_id, score_per_hole=4, putts_per_hole=2, par=4) # Turneringsrunde scoret for en ANNEN bruker, i en org `user_id` ikke er medlem/spiller i. await _make_tournament_round(other_user_id, score_per_hole=4, putts_per_hole=2, par=4) out = await get_rounds_stats_summary(window="all", user=CurrentUser(user_id=user_id)) assert out.current.rounds_completed == 1 assert out.current.rounds_completed_tournament == 0