[WEI] Extreme test with full buses and quality constraints

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
Yohann D'ANELLO 2021-09-02 01:36:37 +02:00
parent 451851c955
commit 74ab4df9fe
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
3 changed files with 49 additions and 3 deletions

View File

@ -53,7 +53,8 @@ class WEIBusInformation:
def free_seats(self, surveys: List["WEISurvey"] = None): def free_seats(self, surveys: List["WEISurvey"] = None):
size = self.bus.size size = self.bus.size
already_occupied = WEIMembership.objects.filter(bus=self.bus).count() already_occupied = WEIMembership.objects.filter(bus=self.bus).count()
valid_surveys = sum(1 for survey in surveys if survey.information.valid) if surveys else 0 valid_surveys = sum(1 for survey in surveys if survey.information.valid
and survey.information.get_selected_bus() == self.bus) if surveys else 0
return size - already_occupied - valid_surveys return size - already_occupied - valid_surveys
def has_free_seats(self, surveys=None): def has_free_seats(self, surveys=None):

View File

@ -190,6 +190,9 @@ class WEISurveyAlgorithm2021(WEISurveyAlgorithm):
# If it does not exist, choose the next bus. # If it does not exist, choose the next bus.
least_preferred_survey.free() least_preferred_survey.free()
least_preferred_survey.save() least_preferred_survey.save()
free_surveys.append(least_preferred_survey)
survey.select_bus(bus) survey.select_bus(bus)
survey.save() survey.save()
break break
else:
raise ValueError(f"User {survey.registration.user} has no free seat")

View File

@ -1,3 +1,4 @@
import math
import random import random
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -26,7 +27,7 @@ class TestWEIAlgorithm(TestCase):
self.buses = [] self.buses = []
for i in range(10): for i in range(10):
bus = Bus.objects.create(wei=self.wei, name=f"Bus {i}", size=50) bus = Bus.objects.create(wei=self.wei, name=f"Bus {i}", size=10)
self.buses.append(bus) self.buses.append(bus)
information = WEIBusInformation2021(bus) information = WEIBusInformation2021(bus)
for word in WORDS: for word in WORDS:
@ -39,7 +40,7 @@ class TestWEIAlgorithm(TestCase):
There are only a few people in each bus, ensure that each person has its best bus There are only a few people in each bus, ensure that each person has its best bus
""" """
# Add a few users # Add a few users
for i in range(50): for i in range(10):
user = User.objects.create(username=f"user{i}") user = User.objects.create(username=f"user{i}")
registration = WEIRegistration.objects.create( registration = WEIRegistration.objects.create(
user=user, user=user,
@ -63,3 +64,44 @@ class TestWEIAlgorithm(TestCase):
preferred_bus = survey.ordered_buses()[0][0] preferred_bus = survey.ordered_buses()[0][0]
chosen_bus = survey.information.get_selected_bus() chosen_bus = survey.information.get_selected_bus()
self.assertEqual(preferred_bus, chosen_bus) self.assertEqual(preferred_bus, chosen_bus)
def test_survey_algorithm_full(self):
"""
Buses are full of first year people, ensure that they are happy
"""
# Add a lot of users
for i in range(95):
user = User.objects.create(username=f"user{i}")
registration = WEIRegistration.objects.create(
user=user,
wei=self.wei,
first_year=True,
birth_date='2000-01-01',
)
information = WEISurveyInformation2021(registration)
for j in range(1, 21):
setattr(information, f'word{j}', random.choice(WORDS))
information.step = 20
information.save(registration)
registration.save()
# Run algorithm
WEISurvey2021.get_algorithm_class()().run_algorithm()
penalty = 0
# Ensure that everyone seems to be happy
# We attribute a penalty for each user that didn't have its first choice
# The penalty is the square of the distance between the score of the preferred bus
# and the score of the attributed bus
# We consider it acceptable if the mean of this distance is lower than 5 %
for r in WEIRegistration.objects.filter(wei=self.wei).all():
survey = WEISurvey2021(r)
chosen_bus = survey.information.get_selected_bus()
buses = survey.ordered_buses()
score = min(v for bus, v in buses if bus == chosen_bus)
max_score = buses[0][1]
penalty += (max_score - score) ** 2
self.assertLessEqual(max_score - score, 20) # Always less than 20 % of tolerance
self.assertLessEqual(penalty / 100, 25) # Tolerance of 5 %