Skip to content

Commit

Permalink
Implement new plenalty rules
Browse files Browse the repository at this point in the history
  • Loading branch information
Arashfa0301 committed Apr 30, 2023
1 parent a6f64c3 commit 69a1f82
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 79 deletions.
Binary file added lego/.DS_Store
Binary file not shown.
34 changes: 3 additions & 31 deletions lego/apps/events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,11 @@ def get_earliest_registration_time(
if len(pools) == 0:
return None
reg_time: date = min(pool.activation_date for pool in pools)

if self.heed_penalties:
if penalties is None:
penalties = user.number_of_penalties()
if penalties == 2:
return reg_time + timedelta(hours=12)
elif penalties == 1:
return reg_time + timedelta(hours=3)
return reg_time + timedelta(hours=5) if penalties >= 1 else reg_time
return reg_time

def get_possible_pools(
Expand Down Expand Up @@ -328,9 +326,6 @@ def register(self, registration: Registration) -> Registration:
# Make the user follow the event
FollowEvent.objects.get_or_create(follower=user, target=self)

if penalties >= 3:
return registration.add_to_waiting_list()

# If the event is merged or has only one pool we can skip a lot of logic
if all_pools.count() == 1:
return registration.add_to_pool(possible_pools[0])
Expand Down Expand Up @@ -469,8 +464,6 @@ def early_bump(self, opening_pool: Pool) -> None:
for reg in self.waiting_registrations:
if opening_pool.is_full:
break
if self.heed_penalties and reg.user.number_of_penalties() >= 3:
continue
if self.can_register(reg.user, opening_pool, future=True):
reg.pool = opening_pool
reg.save()
Expand All @@ -491,8 +484,6 @@ def bump_on_pool_creation_or_expansion(self) -> None:
for reg in self.waiting_registrations:
if self.is_full or pool.is_full:
break
if self.heed_penalties and reg.user.number_of_penalties() >= 3:
continue
if self.can_register(reg.user, pool, future=True):
reg.pool = pool
reg.save()
Expand Down Expand Up @@ -576,28 +567,9 @@ def pop_from_waiting_list(

if to_pool:
for registration in self.waiting_registrations:
if self.heed_penalties:
penalties: int = registration.user.number_of_penalties()
earliest_reg: Optional[date] = self.get_earliest_registration_time(
registration.user, [to_pool], penalties
)
if penalties < 3 and earliest_reg and earliest_reg < timezone.now():
if self.can_register(registration.user, to_pool):
return registration
elif self.can_register(registration.user, to_pool):
if self.can_register(registration.user, to_pool):
return registration
return None

if self.heed_penalties:
for registration in self.waiting_registrations:
penalties = registration.user.number_of_penalties()
earliest_reg = self.get_earliest_registration_time(
registration.user, None, penalties
)
if penalties < 3 and earliest_reg and earliest_reg < timezone.now():
return registration
return None

return self.waiting_registrations.first()

@staticmethod
Expand Down
8 changes: 6 additions & 2 deletions lego/apps/events/tests/test_async_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,9 @@ def test_isnt_bumped_without_permission(self):
self.assertEqual(self.pool_two.registrations.count(), 0)
self.assertEqual(self.event.waiting_registrations.count(), 1)

"""
def test_isnt_bumped_with_penalties(self):
"""Users should not be bumped if they have 3 penalties."""
""Users should not be bumped if they have 3 penalties.""
self.event.start_time = timezone.now() + timedelta(days=1)
self.event.merge_time = timezone.now() + timedelta(hours=12)
self.event.save()
Expand Down Expand Up @@ -252,6 +253,7 @@ def test_isnt_bumped_with_penalties(self):
self.assertEqual(self.pool_two.registrations.count(), 0)
self.assertEqual(self.event.waiting_registrations.count(), 1)
"""

def test_isnt_bumped_if_activation_is_far_into_the_future(self):
"""Users should not be bumped if the pool is activated more than
Expand Down Expand Up @@ -419,8 +421,9 @@ def test_is_bumped_with_multiple_penalties(self):
self.assertIsNotNone(Registration.objects.get(id=registration.id).pool)
self.assertEqual(self.event.number_of_registrations, 1)

"""
def test_isnt_bumped_with_too_many_penalties(self):
"""Tests that a user isn't bumped when going from 4 to 3 active penalties"""
""Tests that a user isn't bumped when going from 4 to 3 active penalties""
user = get_dummy_users(1)[0]
AbakusGroup.objects.get(name="Abakus").add_user(user)
Expand All @@ -442,6 +445,7 @@ def test_isnt_bumped_with_too_many_penalties(self):
self.assertIsNone(Registration.objects.get(id=registration.id).pool)
self.assertEqual(self.event.number_of_registrations, 0)
"""

def test_isnt_bumped_when_full(self):
"""Tests that a user isnt bumped when the event is full when penalties expire."""
Expand Down
71 changes: 54 additions & 17 deletions lego/apps/events/tests/test_penalties.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_get_earliest_registration_time_ignore_penalties(self):
self.assertEqual(earliest_reg, current_time)

def test_get_earliest_registration_time_one_penalty(self):
"""Test method calculating the earliest registration time for user with one penalty"""
"""Test method calculating the earliest registration time for user with one or more penalties"""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")

current_time = timezone.now()
Expand All @@ -53,16 +53,22 @@ def test_get_earliest_registration_time_one_penalty(self):

user = get_dummy_users(1)[0]
AbakusGroup.objects.get(name="Webkom").add_user(user)
Penalty.objects.create(user=user, reason="test", weight=1, source_event=event)
Penalty.objects.create(
user=user, reason="first test penalty", weight=1, source_event=event
)
Penalty.objects.create(
user=user, reason="second test penalty", weight=2, source_event=event
)
penalties = user.number_of_penalties()

earliest_reg = event.get_earliest_registration_time(
user, [webkom_pool], penalties
)
self.assertEqual(earliest_reg, current_time + timedelta(hours=3))
self.assertEqual(earliest_reg, current_time + timedelta(hours=5))

"""
def test_get_earliest_registration_time_two_penalties(self):
"""Test method calculating the earliest registration time for user with two penalties"""
""Test method calculating the earliest registration time for user with two penalties""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
current_time = timezone.now()
Expand All @@ -79,9 +85,10 @@ def test_get_earliest_registration_time_two_penalties(self):
user, [webkom_pool], penalties
)
self.assertEqual(earliest_reg, current_time + timedelta(hours=12))
"""

def test_cant_register_with_one_penalty_before_delay(self):
"""Test that user can not register before (3 hour) delay when having one penalty"""
"""Test that user can not register before (5 hour) delay when having one or more penalties"""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")

current_time = timezone.now()
Expand All @@ -91,31 +98,42 @@ def test_cant_register_with_one_penalty_before_delay(self):

user = get_dummy_users(1)[0]
AbakusGroup.objects.get(name="Abakus").add_user(user)
Penalty.objects.create(user=user, reason="test", weight=1, source_event=event)
Penalty.objects.create(
user=user, reason="first test penalty", weight=1, source_event=event
)
Penalty.objects.create(
user=user, reason="second test penalty", weight=2, source_event=event
)

with self.assertRaises(ValueError):
registration = Registration.objects.get_or_create(event=event, user=user)[0]
event.register(registration)

def test_can_register_with_one_penalty_after_delay(self):
"""Test that user can register after (3 hour) delay has passed having one penalty"""
"""Test that user can register after (5 hour) delay has passed having one or more penalties"""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")

current_time = timezone.now()
abakus_pool = event.pools.get(name="Abakusmember")
abakus_pool.activation_date = current_time - timedelta(hours=3)
abakus_pool.activation_date = current_time - timedelta(hours=5)
abakus_pool.save()

user = get_dummy_users(1)[0]
AbakusGroup.objects.get(name="Abakus").add_user(user)
Penalty.objects.create(user=user, reason="test", weight=1, source_event=event)
Penalty.objects.create(
user=user, reason="first test penalty", weight=1, source_event=event
)
Penalty.objects.create(
user=user, reason="second test penalty", weight=2, source_event=event
)

registration = Registration.objects.get_or_create(event=event, user=user)[0]
event.register(registration)
self.assertEqual(event.number_of_registrations, 1)

"""
def test_cant_register_with_two_penalties_before_delay(self):
"""Test that user can not register before (12 hour) delay when having two penalties"""
""Test that user can not register before (12 hour) delay when having two penalties""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
current_time = timezone.now()
Expand All @@ -130,9 +148,11 @@ def test_cant_register_with_two_penalties_before_delay(self):
with self.assertRaises(ValueError):
registration = Registration.objects.get_or_create(event=event, user=user)[0]
event.register(registration)
"""

"""
def test_can_register_with_two_penalties_after_delay(self):
"""Test that user can register after (12 hour) delay when having two penalties"""
""Test that user can register after (12 hour) delay when having two penalties""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
current_time = timezone.now()
Expand All @@ -147,9 +167,11 @@ def test_can_register_with_two_penalties_after_delay(self):
registration = Registration.objects.get_or_create(event=event, user=user)[0]
event.register(registration)
self.assertEqual(event.number_of_registrations, 1)
"""

"""
def test_waiting_list_on_three_penalties(self):
"""Test that user is registered to waiting list directly when having three penalties"""
""Test that user is registered to waiting list directly when having three penalties""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
user = get_dummy_users(1)[0]
Expand All @@ -160,9 +182,11 @@ def test_waiting_list_on_three_penalties(self):
event.register(registration)
self.assertEqual(event.number_of_registrations, 0)
self.assertEqual(event.waiting_registrations.count(), 1)
"""

"""
def test_waiting_list_on_more_than_three_penalties(self):
"""Test that user is registered to waiting list directly having over three penalties"""
""Test that user is registered to waiting list directly having over three penalties""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
user = get_dummy_users(1)[0]
Expand All @@ -174,9 +198,11 @@ def test_waiting_list_on_more_than_three_penalties(self):
event.register(registration)
self.assertEqual(event.number_of_registrations, 0)
self.assertEqual(event.waiting_registrations.count(), 1)
"""

"""
def test_waiting_list_on_three_penalties_post_merge(self):
"""Test that user is registered to waiting list with three penalties after merge"""
""Test that user is registered to waiting list with three penalties after merge""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
event.merge_time = timezone.now() - timedelta(hours=24)
event.save()
Expand All @@ -189,9 +215,11 @@ def test_waiting_list_on_three_penalties_post_merge(self):
event.register(registration)
self.assertEqual(event.number_of_registrations, 0)
self.assertEqual(event.waiting_registrations.count(), 1)
"""

"""
def test_not_bumped_if_three_penalties(self):
"""Test that user is not bumped on unregistration having three penalties"""
""Test that user is not bumped on unregistration having three penalties""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
users = get_dummy_users(5)
Expand All @@ -217,9 +245,11 @@ def test_not_bumped_if_three_penalties(self):
self.assertIsNone(event.registrations.get(user=waiting_users[0]).pool)
self.assertIsNotNone(event.registrations.get(user=waiting_users[1]).pool)
"""

"""
def test_not_bumped_if_three_penalties_post_merge(self):
"""Test that user is not bumped on unregistration having three penalties after merge"""
""Test that user is not bumped on unregistration having three penalties after merge""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
users = get_dummy_users(7)
Expand Down Expand Up @@ -251,9 +281,11 @@ def test_not_bumped_if_three_penalties_post_merge(self):
self.assertIsNone(event.registrations.get(user=waiting_users[0]).pool)
self.assertIsNotNone(event.registrations.get(user=waiting_users[1]).pool)
"""

"""
def test_bumped_if_penalties_expire_while_waiting(self):
"""Test that user gets bumped when penalties expire while on waiting list"""
""Test that user gets bumped when penalties expire while on waiting list""
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
for pool in event.pools.all():
Expand Down Expand Up @@ -288,7 +320,9 @@ def test_bumped_if_penalties_expire_while_waiting(self):
self.assertIsNotNone(event.registrations.get(user=waiting_users[0]).pool)
self.assertIsNone(event.registrations.get(user=waiting_users[1]).pool)
"""

"""
def test_isnt_bumped_if_third_penalty_expires_but_reg_delay_is_still_active(self):
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
for pool in event.pools.all():
Expand Down Expand Up @@ -323,7 +357,9 @@ def test_isnt_bumped_if_third_penalty_expires_but_reg_delay_is_still_active(self
self.assertIsNone(event.registrations.get(user=waiting_users[0]).pool)
self.assertIsNotNone(event.registrations.get(user=waiting_users[1]).pool)
"""

"""
def test_no_legal_bump(self):
event = Event.objects.get(title="POOLS_NO_REGISTRATIONS")
users = get_dummy_users(5)
Expand Down Expand Up @@ -353,6 +389,7 @@ def test_no_legal_bump(self):
self.assertIsNone(event.registrations.get(user=users[3]).pool)
self.assertIsNone(event.registrations.get(user=users[4]).pool)
"""

def test_penalties_created_on_unregister(self):
"""Test that user gets penalties on unregister after limit"""
Expand Down
6 changes: 5 additions & 1 deletion lego/apps/users/action_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ def get_activity(self, penalty):
object=penalty,
target=penalty.user,
time=penalty.created_at,
extra_context={"reason": penalty.reason, "weight": penalty.weight},
extra_context={
"reason": penalty.reason,
"weight": penalty.weight,
"expiration_date": penalty.exact_expiration.days,
},
)

def handle_create(self, instance, **kwargs):
Expand Down
19 changes: 19 additions & 0 deletions lego/apps/users/migrations/0039_penalty_activation_date.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.0.10 on 2023-04-26 09:07

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("users", "0038_alter_abakusgroup_type"),
]

operations = [
migrations.AddField(
model_name="penalty",
name="activation_date",
field=models.DateTimeField(
default=None, null=True, verbose_name="date created"
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.0.10 on 2023-04-26 13:39

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('users', '0039_penalty_activation_date'),
]

operations = [
migrations.RenameField(
model_name='penalty',
old_name='activation_date',
new_name='activation_time',
),
]
Loading

0 comments on commit 69a1f82

Please sign in to comment.