Skip to content

Commit

Permalink
Add max_adr = 50, max_kd = 0.5 constraints for Peach Price
Browse files Browse the repository at this point in the history
  • Loading branch information
kostrykin committed Oct 6, 2024
1 parent 2489edd commit 587e357
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 47 deletions.
40 changes: 31 additions & 9 deletions django/stats/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,9 @@ def award(participation, **kwargs):
MatchBadge.award_kills_in_one_round_badges(participation, 5, 'ace', **kwargs)
MatchBadge.award_kills_in_one_round_badges(participation, 4, 'quad-kill', **kwargs)
MatchBadge.award_margin_badge(participation, 'carrier', order = '-adr', margin = 1.8, emoji = 'πŸ†', **kwargs)
MatchBadge.award_margin_badge(participation, 'peach', order = 'adr', margin = 0.667, emoji = 'πŸ‘', **kwargs)
MatchBadge.award_margin_badge(
participation, 'peach', order = 'adr', margin = 0.67, emoji = 'πŸ‘', max_adr = 50, max_kd = 0.5, **kwargs,
)

@staticmethod
def award_with_history(participation, old_participations):
Expand Down Expand Up @@ -1095,21 +1097,41 @@ def award_kills_in_one_round_badges(participation, kill_number, badge_type_slug,
m.squad.notify_on_discord(text)

@staticmethod
def award_margin_badge(participation, badge_type_slug, order, margin, emoji, mute_discord = False):
def award_margin_badge(participation, badge_type_slug, order, margin, emoji, mute_discord = False, **bounds):
kpi = order[1:] if order[0] in '+-' else order
badge_type = MatchBadgeType.objects.get(slug = badge_type_slug)
if MatchBadge.objects.filter(badge_type=badge_type, participation=participation).exists():
return
teammates = participation.pmatch.matchparticipation_set.filter(team = participation.team).order_by(order)

awarded = teammates[0].pk == participation.pk and any(
(
order[0] == '-' and getattr(teammates[0], kpi) > margin * getattr(teammates[1], kpi),
order[0] != '-' and getattr(teammates[0], kpi) < margin * getattr(teammates[1], kpi),
)
)
# Define the requirements for the badge
requirements = [
teammates[0].pk == participation.pk,
any(
(
order[0] == '-' and getattr(teammates[0], kpi) > margin * getattr(teammates[1], kpi),
order[0] != '-' and getattr(teammates[0], kpi) < margin * getattr(teammates[1], kpi),
)
),
]

if awarded:
# Add the bound checks to the requirements
req_bounds = list()
for bound_key, bound_val in bounds.items():
func_name, attr_name = bound_key.split('_')
attr = getattr(participation, attr_name)
match func_name:
case 'min':
req_bounds.append(attr >= bound_val)
case 'max':
req_bounds.append(attr <= bound_val)
case _:
raise ValueError(f'Invalid function name: "{func_name}"')
if req_bounds:
requirements.append(any(req_bounds))

# Check the requirements and award the badge
if all(requirements):
log.info(f'{participation.player.name} received the {badge_type.name}')
MatchBadge.objects.create(badge_type = badge_type, participation = participation)
text = (
Expand Down
136 changes: 98 additions & 38 deletions django/stats/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,19 +229,28 @@ def test(self):
)


@patch('stats.models.Match.award_badges')
class MatchBadge__award(TestCase):

def test_no_awards(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
participation = pmatch.get_participation('76561197967680028')
def setUp(self):
with patch('stats.models.Match.award_badges'):
self.pmatch = Match__create_from_data().test()
self.mp5 = self.pmatch.get_participation('76561197962477966')
self.teammates = list(
self.mp5.pmatch.matchparticipation_set.filter(
team = self.mp5.team,
).exclude(
pk = self.mp5.pk,
).order_by('-adr')
)

def test_no_awards(self):
participation = self.pmatch.get_participation('76561197967680028')
models.MatchBadge.award(participation)
self.assertEqual(len(models.MatchBadge.objects.filter(participation = participation)), 0)

def test_quad_kill(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
mp1 = pmatch.get_participation('76561197967680028')
mp2 = pmatch.get_participation('76561197961345487')
def test_quad_kill(self):
mp1 = self.pmatch.get_participation('76561197967680028')
mp2 = self.pmatch.get_participation('76561197961345487')
models.KillEvent.objects.all().delete()
models.KillEvent.objects.bulk_create(
[
Expand All @@ -260,10 +269,9 @@ def test_quad_kill(self, mock__Match__award_badges):
self.assertEqual(badge.participation.pk, mp1.pk)
self.assertEqual(badge.frequency, 1)

def test_quad_kill_twice(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
mp1 = pmatch.get_participation('76561197967680028')
mp2 = pmatch.get_participation('76561197961345487')
def test_quad_kill_twice(self):
mp1 = self.pmatch.get_participation('76561197967680028')
mp2 = self.pmatch.get_participation('76561197961345487')
models.KillEvent.objects.all().delete()
models.KillEvent.objects.bulk_create(
[
Expand All @@ -283,10 +291,9 @@ def test_quad_kill_twice(self, mock__Match__award_badges):
self.assertEqual(badge.participation.pk, mp1.pk)
self.assertEqual(badge.frequency, 2)

def test_ace(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
mp1 = pmatch.get_participation('76561197967680028')
mp2 = pmatch.get_participation('76561197961345487')
def test_ace(self):
mp1 = self.pmatch.get_participation('76561197967680028')
mp2 = self.pmatch.get_participation('76561197961345487')
models.KillEvent.objects.all().delete()
models.KillEvent.objects.bulk_create(
[
Expand All @@ -303,10 +310,9 @@ def test_ace(self, mock__Match__award_badges):
self.assertEqual(badge.participation.pk, mp1.pk)
self.assertEqual(badge.frequency, 1)

def test_ace_twice(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
mp1 = pmatch.get_participation('76561197967680028')
mp2 = pmatch.get_participation('76561197961345487')
def test_ace_twice(self):
mp1 = self.pmatch.get_participation('76561197967680028')
mp2 = self.pmatch.get_participation('76561197961345487')
models.KillEvent.objects.all().delete()
models.KillEvent.objects.bulk_create(
[
Expand All @@ -328,10 +334,9 @@ def test_ace_twice(self, mock__Match__award_badges):
self.assertEqual(badge.participation.pk, mp1.pk)
self.assertEqual(badge.frequency, 2)

def test_carrier_badge(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
mp1 = pmatch.get_participation('76561197967680028')
mp2 = pmatch.get_participation('76561197961345487')
def test_carrier_badge(self):
mp1 = self.pmatch.get_participation('76561197967680028')
mp2 = self.pmatch.get_participation('76561197961345487')

# Test with ADR right below the threshold
mp1.adr = 1.79 * mp2.adr
Expand All @@ -347,24 +352,79 @@ def test_carrier_badge(self, mock__Match__award_badges):
models.MatchBadge.award(mp1)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'carrier', participation = mp1)), 1)

def test_peach_price(self, mock__Match__award_badges):
pmatch = Match__create_from_data().test()
mp4 = pmatch.get_participation('76561198067716219')
mp5 = pmatch.get_participation('76561197962477966')

# Test with ADR right below the threshold
mp5.adr = 0.668 * mp4.adr
mp5.save()
models.MatchBadge.award(mp5)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = mp5)), 0)
def test_peach_price__within_bounds(self):
"""
Test the πŸ‘ Peach Price when the constraints βœ… "ADR <50" and βœ… "K/D <0.5" are met.
"""
for mp in self.teammates:
mp.adr = 50
mp.save()
self.mp5.kills = 1
self.mp5.deaths = 3

# Test with ADR right above the threshold
mp5.adr = 0.666 * mp4.adr
mp5.save()
self.mp5.adr = 0.68 * self.teammates[-1].adr
self.mp5.save()
models.MatchBadge.award(self.mp5)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = self.mp5)), 0)

# Test with ADR right below the threshold
self.mp5.adr = 0.66 * self.teammates[-1].adr
self.mp5.save()
for itr in range(2): # Test twice, the badge should be awarded only once
with self.subTest(itr = itr):
models.MatchBadge.award(mp5)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = mp5)), 1)
models.MatchBadge.award(self.mp5)
self.assertEqual(
len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = self.mp5)), 1,
)

def test_peach_price__kd_too_high(self):
"""
Test the πŸ‘ Peach Price when the constraint βœ… "ADR <50" is met but ❌ "K/D <0.5" is not.
"""
for mp in self.teammates:
mp.adr = 50
mp.save()
self.mp5.kills = 2
self.mp5.deaths = 3

# Test with ADR right below the threshold
self.mp5.adr = 0.66 * self.teammates[-1].adr
self.mp5.save()
models.MatchBadge.award(self.mp5)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = self.mp5)), 1)

def test_peach_price__adr_too_high(self):
"""
Test the πŸ‘ Peach Price when the constraint βœ… "K/D <0.5" is met but ❌ "ADR <50" is not.
"""
for mp in self.teammates:
mp.adr = 100
mp.save()
self.mp5.kills = 1
self.mp5.deaths = 3

# Test with ADR right below the threshold
self.mp5.adr = 0.66 * self.teammates[-1].adr
self.mp5.save()
models.MatchBadge.award(self.mp5)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = self.mp5)), 1)

def test_peach_price__kd_and_adr_too_high(self):
"""
Test the πŸ‘ Peach Price when the constraint ❌ "ADR <50" and ❌ "K/D <0.5" both are not met.
"""
for mp in self.teammates:
mp.adr = 100
mp.save()
self.mp5.kills = 2
self.mp5.deaths = 3

# Test with ADR right below the threshold
self.mp5.adr = 0.66 * self.teammates[-1].adr
self.mp5.save()
models.MatchBadge.award(self.mp5)
self.assertEqual(len(models.MatchBadge.objects.filter(badge_type = 'peach', participation = self.mp5)), 0)


class MatchBadge__award_with_history(TestCase):
Expand Down

0 comments on commit 587e357

Please sign in to comment.