diff options
| author | Max Nanis | 2026-03-06 16:49:46 -0500 |
|---|---|---|
| committer | Max Nanis | 2026-03-06 16:49:46 -0500 |
| commit | 91d040211a4ed6e4157896256a762d3854777b5e (patch) | |
| tree | cd95922ea4257dc8d3f4e4cbe8534474709a20dc /tests/models/thl/test_contest/test_leaderboard_contest.py | |
| download | generalresearch-91d040211a4ed6e4157896256a762d3854777b5e.tar.gz generalresearch-91d040211a4ed6e4157896256a762d3854777b5e.zip | |
Initial commitv3.3.4
Diffstat (limited to 'tests/models/thl/test_contest/test_leaderboard_contest.py')
| -rw-r--r-- | tests/models/thl/test_contest/test_leaderboard_contest.py | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/tests/models/thl/test_contest/test_leaderboard_contest.py b/tests/models/thl/test_contest/test_leaderboard_contest.py new file mode 100644 index 0000000..98f3215 --- /dev/null +++ b/tests/models/thl/test_contest/test_leaderboard_contest.py @@ -0,0 +1,213 @@ +from datetime import timezone +from uuid import uuid4 + +import pytest + +from generalresearch.currency import USDCent +from generalresearch.managers.leaderboard.manager import LeaderboardManager +from generalresearch.models.thl.contest import ContestPrize +from generalresearch.models.thl.contest.definitions import ( + ContestType, + ContestPrizeKind, +) +from generalresearch.models.thl.contest.leaderboard import ( + LeaderboardContest, +) +from generalresearch.models.thl.contest.utils import ( + distribute_leaderboard_prizes, +) +from generalresearch.models.thl.leaderboard import LeaderboardRow +from tests.models.thl.test_contest.test_contest import TestContest + + +class TestLeaderboardContest(TestContest): + + @pytest.fixture + def leaderboard_contest( + self, product, thl_redis, user_manager + ) -> "LeaderboardContest": + board_key = f"leaderboard:{product.uuid}:us:weekly:2025-05-26:complete_count" + + c = LeaderboardContest( + uuid=uuid4().hex, + product_id=product.uuid, + contest_type=ContestType.LEADERBOARD, + leaderboard_key=board_key, + name="$15 1st place, $10 2nd, $5 3rd place US weekly", + prizes=[ + ContestPrize( + name="$15 Cash", + estimated_cash_value=USDCent(15_00), + cash_amount=USDCent(15_00), + kind=ContestPrizeKind.CASH, + leaderboard_rank=1, + ), + ContestPrize( + name="$10 Cash", + estimated_cash_value=USDCent(10_00), + cash_amount=USDCent(10_00), + kind=ContestPrizeKind.CASH, + leaderboard_rank=2, + ), + ContestPrize( + name="$5 Cash", + estimated_cash_value=USDCent(5_00), + cash_amount=USDCent(5_00), + kind=ContestPrizeKind.CASH, + leaderboard_rank=3, + ), + ], + ) + c._redis_client = thl_redis + c._user_manager = user_manager + return c + + def test_init(self, leaderboard_contest, thl_redis, user_1, user_2): + model = leaderboard_contest.leaderboard_model + assert leaderboard_contest.end_condition.ends_at is not None + + lbm = LeaderboardManager( + redis_client=thl_redis, + board_code=model.board_code, + country_iso=model.country_iso, + freq=model.freq, + product_id=leaderboard_contest.product_id, + within_time=model.period_start_local, + ) + + lbm.hit_complete_count(product_user_id=user_1.product_user_id) + lbm.hit_complete_count(product_user_id=user_2.product_user_id) + lbm.hit_complete_count(product_user_id=user_2.product_user_id) + + lb = leaderboard_contest.get_leaderboard() + print(lb) + + def test_win(self, leaderboard_contest, thl_redis, user_1, user_2, user_3): + model = leaderboard_contest.leaderboard_model + lbm = LeaderboardManager( + redis_client=thl_redis, + board_code=model.board_code, + country_iso=model.country_iso, + freq=model.freq, + product_id=leaderboard_contest.product_id, + within_time=model.period_start_local.astimezone(tz=timezone.utc), + ) + + lbm.hit_complete_count(product_user_id=user_1.product_user_id) + lbm.hit_complete_count(product_user_id=user_1.product_user_id) + + lbm.hit_complete_count(product_user_id=user_2.product_user_id) + + lbm.hit_complete_count(product_user_id=user_3.product_user_id) + + leaderboard_contest.end_contest() + assert len(leaderboard_contest.all_winners) == 3 + + # Prizes are $15, $10, $5. user 2 and 3 ties for 2nd place, so they split (10 + 5) + assert leaderboard_contest.all_winners[0].awarded_cash_amount == USDCent(15_00) + assert ( + leaderboard_contest.all_winners[0].user.product_user_id + == user_1.product_user_id + ) + assert leaderboard_contest.all_winners[0].prize == leaderboard_contest.prizes[0] + assert leaderboard_contest.all_winners[1].awarded_cash_amount == USDCent( + 15_00 / 2 + ) + assert leaderboard_contest.all_winners[2].awarded_cash_amount == USDCent( + 15_00 / 2 + ) + + +class TestLeaderboardContestPrizes: + + def test_distribute_prizes_1(self): + prizes = [USDCent(15_00)] + leaderboard_rows = [ + LeaderboardRow(bpuid="a", value=20, rank=1), + LeaderboardRow(bpuid="b", value=10, rank=2), + ] + result = distribute_leaderboard_prizes(prizes, leaderboard_rows) + + # a gets first prize, b gets nothing. + assert result == { + "a": USDCent(15_00), + } + + def test_distribute_prizes_2(self): + prizes = [USDCent(15_00), USDCent(10_00)] + leaderboard_rows = [ + LeaderboardRow(bpuid="a", value=20, rank=1), + LeaderboardRow(bpuid="b", value=10, rank=2), + ] + result = distribute_leaderboard_prizes(prizes, leaderboard_rows) + + # a gets first prize, b gets 2nd prize + assert result == { + "a": USDCent(15_00), + "b": USDCent(10_00), + } + + def test_distribute_prizes_3(self): + prizes = [USDCent(15_00), USDCent(10_00)] + leaderboard_rows = [ + LeaderboardRow(bpuid="a", value=20, rank=1), + ] + result = distribute_leaderboard_prizes(prizes, leaderboard_rows) + + # A gets first prize, no-one gets $10 + assert result == { + "a": USDCent(15_00), + } + + def test_distribute_prizes_4(self): + prizes = [USDCent(15_00)] + leaderboard_rows = [ + LeaderboardRow(bpuid="a", value=20, rank=1), + LeaderboardRow(bpuid="b", value=20, rank=1), + LeaderboardRow(bpuid="c", value=20, rank=1), + LeaderboardRow(bpuid="d", value=20, rank=1), + ] + result = distribute_leaderboard_prizes(prizes, leaderboard_rows) + + # 4-way tie for the $15 prize; it gets split + assert result == { + "a": USDCent(3_75), + "b": USDCent(3_75), + "c": USDCent(3_75), + "d": USDCent(3_75), + } + + def test_distribute_prizes_5(self): + prizes = [USDCent(15_00), USDCent(10_00)] + leaderboard_rows = [ + LeaderboardRow(bpuid="a", value=20, rank=1), + LeaderboardRow(bpuid="b", value=20, rank=1), + LeaderboardRow(bpuid="c", value=10, rank=3), + ] + result = distribute_leaderboard_prizes(prizes, leaderboard_rows) + + # 2-way tie for the $15 prize; the top two prizes get split. Rank 3 + # and below get nothing + assert result == { + "a": USDCent(12_50), + "b": USDCent(12_50), + } + + def test_distribute_prizes_6(self): + prizes = [USDCent(15_00), USDCent(10_00), USDCent(5_00)] + leaderboard_rows = [ + LeaderboardRow(bpuid="a", value=20, rank=1), + LeaderboardRow(bpuid="b", value=10, rank=2), + LeaderboardRow(bpuid="c", value=10, rank=2), + LeaderboardRow(bpuid="d", value=10, rank=2), + ] + result = distribute_leaderboard_prizes(prizes, leaderboard_rows) + + # A gets first prize, 3 way tie for 2nd rank: they split the 2nd and + # 3rd place prizes (10 + 5)/3 + assert result == { + "a": USDCent(15_00), + "b": USDCent(5_00), + "c": USDCent(5_00), + "d": USDCent(5_00), + } |
