mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-26 18:37:12 +00:00
a6b479db19
- /apps/activity/api/serializers.py - /apps/activity/api/urls.py - /apps/activity/api/views.py - /apps/activity/tests/test_activities.py - /apps/activity/__init__.py - /apps/activity/admin.py - /apps/activity/apps.py - /apps/activity/forms.py - /apps/activity/tables.py - /apps/activity/urls.py - /apps/activity/views.py - /apps/api/__init__.py - /apps/api/apps.py - /apps/api/serializers.py - /apps/api/tests.py - /apps/api/urls.py - /apps/api/views.py - /apps/api/viewsets.py - /apps/logs/signals.py - /apps/logs/apps.py - /apps/logs/__init__.py - /apps/logs/api/serializers.py - /apps/logs/api/urls.py - /apps/logs/api/views.py - /apps/member/api/serializers.py - /apps/member/api/urls.py - /apps/member/api/views.py - /apps/member/templatetags/memberinfo.py - /apps/member/__init__.py - /apps/member/admin.py - /apps/member/apps.py - /apps/member/auth.py - /apps/member/forms.py - /apps/member/hashers.py - /apps/member/signals.py - /apps/member/tables.py - /apps/member/urls.py - /apps/member/views.py - /apps/note/api/serializers.py - /apps/note/api/urls.py - /apps/note/api/views.py - /apps/note/models/__init__.py - /apps/note/static/note/js/consos.js - /apps/note/templates/note/mails/negative_balance.txt - /apps/note/templatetags/getenv.py - /apps/note/templatetags/pretty_money.py - /apps/note/tests/test_transactions.py - /apps/note/__init__.py - /apps/note/admin.py - /apps/note/apps.py - /apps/note/forms.py - /apps/note/signals.py - /apps/note/tables.py - /apps/note/urls.py - /apps/note/views.py - /apps/permission/api/serializers.py - /apps/permission/api/urls.py - /apps/permission/api/views.py - /apps/permission/templatetags/perms.py - /apps/permission/tests/test_oauth2.py - /apps/permission/tests/test_permission_denied.py - /apps/permission/tests/test_permission_queries.py - /apps/permission/tests/test_rights_page.py - /apps/permission/__init__.py - /apps/permission/admin.py - /apps/permission/backends.py - /apps/permission/apps.py - /apps/permission/decorators.py - /apps/permission/permissions.py - /apps/permission/scopes.py - /apps/permission/signals.py - /apps/permission/tables.py - /apps/permission/urls.py - /apps/permission/views.py - /apps/registration/tests/test_registration.py - /apps/registration/__init__.py - /apps/registration/apps.py - /apps/registration/forms.py - /apps/registration/tables.py - /apps/registration/tokens.py - /apps/registration/urls.py - /apps/registration/views.py - /apps/treasury/api/serializers.py - /apps/treasury/api/urls.py - /apps/treasury/api/views.py - /apps/treasury/templatetags/escape_tex.py - /apps/treasury/tests/test_treasury.py - /apps/treasury/__init__.py - /apps/treasury/admin.py - /apps/treasury/apps.py - /apps/treasury/forms.py - /apps/treasury/signals.py - /apps/treasury/tables.py - /apps/treasury/urls.py - /apps/treasury/views.py - /apps/wei/api/serializers.py - /apps/wei/api/urls.py - /apps/wei/api/views.py - /apps/wei/forms/surveys/__init__.py - /apps/wei/forms/surveys/base.py - /apps/wei/forms/surveys/wei2021.py - /apps/wei/forms/surveys/wei2022.py - /apps/wei/forms/surveys/wei2023.py - /apps/wei/forms/__init__.py - /apps/wei/forms/registration.py - /apps/wei/management/commands/export_wei_registrations.py - /apps/wei/management/commands/import_scores.py - /apps/wei/management/commands/wei_algorithm.py - /apps/wei/templates/wei/weilist_sample.tex - /apps/wei/tests/test_wei_algorithm_2021.py - /apps/wei/tests/test_wei_algorithm_2022.py - /apps/wei/tests/test_wei_algorithm_2023.py - /apps/wei/tests/test_wei_registration.py - /apps/wei/__init__.py - /apps/wei/admin.py - /apps/wei/apps.py - /apps/wei/tables.py - /apps/wei/urls.py - /apps/wei/views.py - /note_kfet/settings/__init__.py - /note_kfet/settings/base.py - /note_kfet/settings/development.py - /note_kfet/settings/secrets_example.py - /note_kfet/static/js/base.js - /note_kfet/admin.py - /note_kfet/inputs.py - /note_kfet/middlewares.py - /note_kfet/urls.py - /note_kfet/views.py - /note_kfet/wsgi.py - /entrypoint.sh
111 lines
4.0 KiB
Python
111 lines
4.0 KiB
Python
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import random
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.test import TestCase
|
|
|
|
from ..forms.surveys.wei2021 import WEIBusInformation2021, WEISurvey2021, WORDS, WEISurveyInformation2021
|
|
from ..models import Bus, WEIClub, WEIRegistration
|
|
|
|
|
|
class TestWEIAlgorithm(TestCase):
|
|
"""
|
|
Run some tests to ensure that the WEI algorithm is working well.
|
|
"""
|
|
fixtures = ('initial',)
|
|
|
|
def setUp(self):
|
|
"""
|
|
Create some test data, with one WEI and 10 buses with random score attributions.
|
|
"""
|
|
self.wei = WEIClub.objects.create(
|
|
name="WEI 2021",
|
|
email="wei2021@example.com",
|
|
date_start='2021-09-17',
|
|
date_end='2021-09-19',
|
|
year=2021,
|
|
)
|
|
|
|
self.buses = []
|
|
for i in range(10):
|
|
bus = Bus.objects.create(wei=self.wei, name=f"Bus {i}", size=10)
|
|
self.buses.append(bus)
|
|
information = WEIBusInformation2021(bus)
|
|
for word in WORDS:
|
|
information.scores[word] = random.randint(0, 101)
|
|
information.save()
|
|
bus.save()
|
|
|
|
def test_survey_algorithm_small(self):
|
|
"""
|
|
There are only a few people in each bus, ensure that each person has its best bus
|
|
"""
|
|
# Add a few users
|
|
for i in range(10):
|
|
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()
|
|
|
|
# Ensure that everyone has its first choice
|
|
for r in WEIRegistration.objects.filter(wei=self.wei).all():
|
|
survey = WEISurvey2021(r)
|
|
preferred_bus = survey.ordered_buses()[0][0]
|
|
chosen_bus = survey.information.get_selected_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, 25) # Always less than 25 % of tolerance
|
|
|
|
self.assertLessEqual(penalty / 100, 25) # Tolerance of 5 %
|