diff --git a/apps/wei/forms/surveys/wei2021.py b/apps/wei/forms/surveys/wei2021.py index 8d5adfad..b0cfb0cb 100644 --- a/apps/wei/forms/surveys/wei2021.py +++ b/apps/wei/forms/surveys/wei2021.py @@ -40,19 +40,31 @@ class WEISurveyForm2021(forms.Form): if not information.seed: information.seed = int(1000 * time.time()) information.save(registration) + registration._force_save = True registration.save() - rng = Random(information.seed) - - words = [] - for _ignored in range(information.step + 1): - # Generate N times words - words = [rng.choice(WORDS) for _ignored2 in range(10)] - words = [(w, w) for w in words] if self.data: self.fields["word"].choices = [(w, w) for w in WORDS] if self.is_valid(): return + + rng = Random((information.step + 1) * information.seed) + + words = None + + buses = WEISurveyAlgorithm2021.get_buses() + informations = {bus: WEIBusInformation2021(bus) for bus in buses} + scores = sum((list(informations[bus].scores.values()) for bus in buses), []) + average_score = sum(scores) / len(scores) + + preferred_words = {bus: [word for word in WORDS + if informations[bus].scores[word] >= average_score] + for bus in buses} + while words is None or len(set(words)) != len(words): + # Ensure that there is no the same word 2 times + words = [rng.choice(words) for _ignored2, words in preferred_words.items()] + rng.shuffle(words) + words = [(w, w) for w in words] self.fields["word"].choices = words diff --git a/apps/wei/management/commands/import_scores.py b/apps/wei/management/commands/import_scores.py new file mode 100644 index 00000000..f8587cfd --- /dev/null +++ b/apps/wei/management/commands/import_scores.py @@ -0,0 +1,50 @@ +# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later +import argparse +import sys + +from django.core.management import BaseCommand +from django.db import transaction + +from ...forms import CurrentSurvey +from ...forms.surveys.wei2021 import WORDS # WARNING: this is specific to 2021 +from ...models import Bus + + +class Command(BaseCommand): + """ + This script is used to load scores for buses from a CSV file. + """ + def add_arguments(self, parser): + parser.add_argument('file', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help='Input CSV file') + + @transaction.atomic + def handle(self, *args, **options): + file = options['file'] + head = file.readline().replace('\n', '') + bus_names = head.split(';') + bus_names = [name for name in bus_names if name] + buses = [] + for name in bus_names: + qs = Bus.objects.filter(name__iexact=name) + if not qs.exists(): + raise ValueError(f"Bus '{name}' does not exist") + buses.append(qs.get()) + + informations = {bus: CurrentSurvey.get_algorithm_class().get_bus_information(bus) for bus in buses} + + for line in file: + elem = line.split(';') + word = elem[0] + if word not in WORDS: + raise ValueError(f"Word {word} is not used") + + for i, bus in enumerate(buses): + info = informations[bus] + info.scores[word] = float(elem[i + 1].replace(',', '.')) + + for bus, info in informations.items(): + info.save() + bus.save() + if options['verbosity'] > 0: + self.stdout.write(f"Bus {bus.name} saved!") diff --git a/apps/wei/tests/test_wei_registration.py b/apps/wei/tests/test_wei_registration.py index 2a49a5d8..bcd755d8 100644 --- a/apps/wei/tests/test_wei_registration.py +++ b/apps/wei/tests/test_wei_registration.py @@ -84,6 +84,13 @@ class TestWEIRegistration(TestCase): wei=self.wei, description="Test Bus", ) + + # Setup the bus + bus_info = CurrentSurvey.get_algorithm_class().get_bus_information(self.bus) + bus_info.scores["Jus de fruit"] = 70 + bus_info.save() + self.bus.save() + self.team = BusTeam.objects.create( name="Test Team", bus=self.bus, @@ -761,58 +768,6 @@ class TestDefaultWEISurvey(TestCase): self.assertEqual(CurrentSurvey.get_year(), 2021) -class TestWEISurveyAlgorithm(TestCase): - """ - Run the WEI Algorithm. - TODO: Improve this test with some test data once the algorithm will be implemented. - """ - fixtures = ("initial",) - - def setUp(self) -> None: - self.year = timezone.now().year - self.wei = WEIClub.objects.create( - name="Test WEI", - email="gc.wei@example.com", - parent_club_id=2, - membership_fee_paid=12500, - membership_fee_unpaid=5500, - membership_start=date(self.year, 1, 1), - membership_end=date(self.year, 12, 31), - year=self.year, - date_start=date.today() + timedelta(days=2), - date_end=date(self.year, 12, 31), - ) - NoteClub.objects.create(club=self.wei) - self.bus = Bus.objects.create( - name="Test Bus", - wei=self.wei, - description="Test Bus", - ) - self.team = BusTeam.objects.create( - name="Test Team", - bus=self.bus, - color=0xFFFFFF, - description="Test Team", - ) - - self.user = User.objects.create(username="toto") - self.registration = WEIRegistration.objects.create( - user_id=self.user.id, - wei_id=self.wei.id, - soge_credit=True, - caution_check=True, - birth_date=date(2000, 1, 1), - gender="nonbinary", - clothing_cut="male", - clothing_size="XL", - health_issues="I am a bot", - emergency_contact_name="Pikachu", - emergency_contact_phone="+33123456789", - first_year=True, - ) - CurrentSurvey(self.registration).save() - - class TestWeiAPI(TestAPI): def setUp(self) -> None: super().setUp() diff --git a/apps/wei/views.py b/apps/wei/views.py index cf7c3911..cb8e3646 100644 --- a/apps/wei/views.py +++ b/apps/wei/views.py @@ -487,9 +487,16 @@ class WEIRegister1AView(ProtectQuerysetMixin, ProtectedCreateView): def get_sample_object(self): wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + if "myself" in self.request.path: + user = self.request.user + else: + # To avoid unique validation issues, we use an account that can't join the WEI. + # In development mode, the note account may not exist, we use a random user (may fail) + user = User.objects.get(username="note") \ + if User.objects.filter(username="note").exists() else User.objects.first() return WEIRegistration( wei=wei, - user=self.request.user, + user=user, first_year=True, birth_date="1970-01-01", gender="No", @@ -555,9 +562,16 @@ class WEIRegister2AView(ProtectQuerysetMixin, ProtectedCreateView): def get_sample_object(self): wei = WEIClub.objects.get(pk=self.kwargs["wei_pk"]) + if "myself" in self.request.path: + user = self.request.user + else: + # To avoid unique validation issues, we use an account that can't join the WEI. + # In development mode, the note account may not exist, we use a random user (may fail) + user = User.objects.get(username="note") \ + if User.objects.filter(username="note").exists() else User.objects.first() return WEIRegistration( wei=wei, - user=self.request.user, + user=user, first_year=True, birth_date="1970-01-01", gender="No",