From 74ac670a74e517abed97b72e285280486b97ecce Mon Sep 17 00:00:00 2001
From: Felix Blanke <info@fblanke.de>
Date: Thu, 6 Feb 2025 17:41:16 +0100
Subject: [PATCH 1/4] Add export slot length to event

---
 AKModel/migrations/0061_event_export_slot.py | 24 ++++++++++++++++++++
 AKModel/models.py                            | 18 +++++++++++----
 AKModel/views/ak.py                          | 10 ++------
 3 files changed, 39 insertions(+), 13 deletions(-)
 create mode 100644 AKModel/migrations/0061_event_export_slot.py

diff --git a/AKModel/migrations/0061_event_export_slot.py b/AKModel/migrations/0061_event_export_slot.py
new file mode 100644
index 00000000..3b40b88c
--- /dev/null
+++ b/AKModel/migrations/0061_event_export_slot.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.2.13 on 2025-02-06 16:09
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("AKModel", "0060_orga_message_resolved"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="event",
+            name="export_slot",
+            field=models.DecimalField(
+                decimal_places=2,
+                default=1,
+                help_text="Slot duration in hours that is used in the timeslot discretization, when this event is exported for the solver.",
+                max_digits=4,
+                verbose_name="Export Slot Length",
+            ),
+        ),
+    ]
diff --git a/AKModel/models.py b/AKModel/models.py
index 1cd3f1ba..b3820a15 100644
--- a/AKModel/models.py
+++ b/AKModel/models.py
@@ -151,6 +151,12 @@ class Event(models.Model):
     wiki_export_template_name = models.CharField(verbose_name=_("Wiki Export Template Name"), blank=True, max_length=50)
     default_slot = models.DecimalField(max_digits=4, decimal_places=2, default=2, verbose_name=_('Default Slot Length'),
                                        help_text=_('Default length in hours that is assumed for AKs in this event.'))
+    export_slot = models.DecimalField(max_digits=4, decimal_places=2, default=1, verbose_name=_('Export Slot Length'),
+                                        help_text=_(
+                                            'Slot duration in hours that is used in the timeslot discretization, when this event '
+                                            'is exported for the solver.'
+                                        ))
+
 
     contact_email = models.EmailField(verbose_name=_("Contact email address"), blank=True,
                                         help_text=_("An email address that is displayed on every page "
@@ -336,7 +342,7 @@ class Event(models.Model):
 
         return slot_index
 
-    def uniform_time_slots(self, *, slots_in_an_hour: float = 1.0) -> Iterable[TimeslotBlock]:
+    def uniform_time_slots(self, *, slots_in_an_hour: float) -> Iterable[TimeslotBlock]:
         """Uniformly discretize the entire event into blocks of timeslots.
 
         Discretizes entire event uniformly. May not necessarily result in a single block
@@ -358,7 +364,7 @@ class Event(models.Model):
             constraints=all_category_constraints,
         )
 
-    def default_time_slots(self, *, slots_in_an_hour: float = 1.0) -> Iterable[TimeslotBlock]:
+    def default_time_slots(self, *, slots_in_an_hour: float) -> Iterable[TimeslotBlock]:
         """Discretize all default slots into blocks of timeslots.
 
         In the discretization each default slot corresponds to one block.
@@ -384,7 +390,7 @@ class Event(models.Model):
                 constraints=category_constraints,
             )
 
-    def discretize_timeslots(self, *, slots_in_an_hour: float = 1.0) -> Iterable[TimeslotBlock]:
+    def discretize_timeslots(self, *, slots_in_an_hour: float | None = None) -> Iterable[TimeslotBlock]:
         """"Choose discretization scheme.
 
         Uses default_time_slots if the event has any DefaultSlot, otherwise uniform_time_slots.
@@ -395,6 +401,9 @@ class Event(models.Model):
         :ytype: list of TimeslotBlock
         """
 
+        if slots_in_an_hour is None:
+            slots_in_an_hour = float(self.export_slot)
+
         if DefaultSlot.objects.filter(event=self).exists():
             # discretize default slots if they exists
             yield from merge_blocks(self.default_time_slots(slots_in_an_hour=slots_in_an_hour))
@@ -1007,10 +1016,9 @@ class AKSlot(models.Model):
 
         ceil_offet_eps = decimal.Decimal(1e-4)
 
-        # self.slots_in_an_hour is set in AKJSONExportView
         data = {
             "id": str(self.pk),
-            "duration": math.ceil(self.duration * self.slots_in_an_hour - ceil_offet_eps),
+            "duration": math.ceil(self.duration * self.event.export_slot - ceil_offet_eps),
             "properties": {
                 "conflicts":
                     [str(conflict.pk) for conflict in conflict_slots.all()]
diff --git a/AKModel/views/ak.py b/AKModel/views/ak.py
index bca1c5b3..d9a5e6a8 100644
--- a/AKModel/views/ak.py
+++ b/AKModel/views/ak.py
@@ -91,17 +91,11 @@ class AKJSONExportView(AdminViewMixin, FilterByEventSlugMixin, ListView):
         rooms = Room.objects.filter(event=self.event)
         context["rooms"] = rooms
 
-        # TODO: Configure magic number in event
-        SLOTS_IN_AN_HOUR = 1
-
         timeslots = {
-            "info": {"duration": (1.0 / SLOTS_IN_AN_HOUR), },
+            "info": {"duration": (1.0 / float(self.event.export_slot)), },
             "blocks": [],
             }
 
-        for slot in context["slots"]:
-            slot.slots_in_an_hour = SLOTS_IN_AN_HOUR
-
         ak_availabilities = {
             ak.pk: Availability.union(ak.availabilities.all())
             for ak in AK.objects.filter(event=self.event).all()
@@ -115,7 +109,7 @@ class AKJSONExportView(AdminViewMixin, FilterByEventSlugMixin, ListView):
             for person in AKOwner.objects.filter(event=self.event)
         }
 
-        blocks = self.event.discretize_timeslots(slots_in_an_hour=SLOTS_IN_AN_HOUR)
+        blocks = self.event.discretize_timeslots()
 
         for block in blocks:
             current_block = []
-- 
GitLab


From 599aec3562b2ff67d8ab183e33beea8225b60fcf Mon Sep 17 00:00:00 2001
From: Felix Blanke <info@fblanke.de>
Date: Thu, 6 Feb 2025 17:41:45 +0100
Subject: [PATCH 2/4] Update language files

---
 AKModel/locale/de_DE/LC_MESSAGES/django.po | 332 +++++++++++----------
 1 file changed, 172 insertions(+), 160 deletions(-)

diff --git a/AKModel/locale/de_DE/LC_MESSAGES/django.po b/AKModel/locale/de_DE/LC_MESSAGES/django.po
index 88eb85d5..d4f3db1b 100644
--- a/AKModel/locale/de_DE/LC_MESSAGES/django.po
+++ b/AKModel/locale/de_DE/LC_MESSAGES/django.po
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-02-06 15:48+0000\n"
+"POT-Creation-Date: 2025-02-06 16:38+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -33,8 +33,8 @@ msgstr "Plan veröffentlichen"
 msgid "Unpublish plan"
 msgstr "Plan verbergen"
 
-#: AKModel/admin.py:168 AKModel/models.py:689 AKModel/models.py:1120
-#: AKModel/models.py:1156
+#: AKModel/admin.py:168 AKModel/models.py:698 AKModel/models.py:1128
+#: AKModel/models.py:1164
 #: AKModel/templates/admin/AKModel/status/event_aks.html:10
 #: AKModel/views/manage.py:75 AKModel/views/status.py:97
 msgid "AKs"
@@ -60,11 +60,11 @@ msgstr "In Wiki-Syntax exportieren"
 msgid "Cannot export AKs from more than one event at the same time."
 msgstr "Kann nicht AKs von mehreren Events zur selben Zeit exportieren."
 
-#: AKModel/admin.py:320 AKModel/views/ak.py:241
+#: AKModel/admin.py:320 AKModel/views/ak.py:235
 msgid "Reset interest in AKs"
 msgstr "Interesse an AKs zurücksetzen"
 
-#: AKModel/admin.py:330 AKModel/views/ak.py:256
+#: AKModel/admin.py:330 AKModel/views/ak.py:250
 msgid "Reset AKs' interest counters"
 msgstr "Interessenszähler der AKs zurücksetzen"
 
@@ -109,18 +109,18 @@ msgstr "Die eingegebene Verfügbarkeit enthält ein ungültiges Datum."
 msgid "Please fill in your availabilities!"
 msgstr "Bitte Verfügbarkeiten eintragen!"
 
-#: AKModel/availability/models.py:43 AKModel/models.py:160
-#: AKModel/models.py:489 AKModel/models.py:566 AKModel/models.py:599
-#: AKModel/models.py:625 AKModel/models.py:679 AKModel/models.py:821
-#: AKModel/models.py:897 AKModel/models.py:1059 AKModel/models.py:1116
-#: AKModel/models.py:1307
+#: AKModel/availability/models.py:43 AKModel/models.py:166
+#: AKModel/models.py:498 AKModel/models.py:575 AKModel/models.py:608
+#: AKModel/models.py:634 AKModel/models.py:688 AKModel/models.py:830
+#: AKModel/models.py:906 AKModel/models.py:1067 AKModel/models.py:1124
+#: AKModel/models.py:1315
 msgid "Event"
 msgstr "Event"
 
-#: AKModel/availability/models.py:44 AKModel/models.py:490
-#: AKModel/models.py:567 AKModel/models.py:600 AKModel/models.py:626
-#: AKModel/models.py:680 AKModel/models.py:822 AKModel/models.py:898
-#: AKModel/models.py:1060 AKModel/models.py:1117 AKModel/models.py:1308
+#: AKModel/availability/models.py:44 AKModel/models.py:499
+#: AKModel/models.py:576 AKModel/models.py:609 AKModel/models.py:635
+#: AKModel/models.py:689 AKModel/models.py:831 AKModel/models.py:907
+#: AKModel/models.py:1068 AKModel/models.py:1125 AKModel/models.py:1316
 msgid "Associated event"
 msgstr "Zugehöriges Event"
 
@@ -132,8 +132,8 @@ msgstr "Person"
 msgid "Person whose availability this is"
 msgstr "Person deren Verfügbarkeit hier abgebildet wird"
 
-#: AKModel/availability/models.py:61 AKModel/models.py:825
-#: AKModel/models.py:887 AKModel/models.py:1126
+#: AKModel/availability/models.py:61 AKModel/models.py:834
+#: AKModel/models.py:896 AKModel/models.py:1134
 msgid "Room"
 msgstr "Raum"
 
@@ -141,8 +141,8 @@ msgstr "Raum"
 msgid "Room whose availability this is"
 msgstr "Raum dessen Verfügbarkeit hier abgebildet wird"
 
-#: AKModel/availability/models.py:70 AKModel/models.py:688
-#: AKModel/models.py:886 AKModel/models.py:1054
+#: AKModel/availability/models.py:70 AKModel/models.py:697
+#: AKModel/models.py:895 AKModel/models.py:1062
 msgid "AK"
 msgstr "AK"
 
@@ -150,8 +150,8 @@ msgstr "AK"
 msgid "AK whose availability this is"
 msgstr "Verfügbarkeiten"
 
-#: AKModel/availability/models.py:79 AKModel/models.py:570
-#: AKModel/models.py:1132
+#: AKModel/availability/models.py:79 AKModel/models.py:579
+#: AKModel/models.py:1140
 msgid "AK Category"
 msgstr "AK-Kategorie"
 
@@ -159,7 +159,7 @@ msgstr "AK-Kategorie"
 msgid "AK Category whose availability this is"
 msgstr "AK-Kategorie, deren Verfügbarkeit hier abgebildet wird"
 
-#: AKModel/availability/models.py:309 AKModel/models.py:721
+#: AKModel/availability/models.py:309 AKModel/models.py:730
 msgid "Availabilities"
 msgstr "Verfügbarkeiten"
 
@@ -221,7 +221,7 @@ msgstr ""
 "fürWünsche markieren, z.B. um während der Präsentation auf einem Touchscreen "
 "ausgefüllt zu werden?"
 
-#: AKModel/forms.py:189 AKModel/models.py:1301
+#: AKModel/forms.py:189 AKModel/models.py:1309
 msgid "Default Slots"
 msgstr "Standardslots"
 
@@ -293,8 +293,8 @@ msgstr "Aktivieren?"
 msgid "Finish"
 msgstr "Abschluss"
 
-#: AKModel/models.py:120 AKModel/models.py:558 AKModel/models.py:596
-#: AKModel/models.py:623 AKModel/models.py:641 AKModel/models.py:813
+#: AKModel/models.py:120 AKModel/models.py:567 AKModel/models.py:605
+#: AKModel/models.py:632 AKModel/models.py:650 AKModel/models.py:822
 msgid "Name"
 msgstr "Name"
 
@@ -420,11 +420,23 @@ msgstr "Standardslotlänge"
 msgid "Default length in hours that is assumed for AKs in this event."
 msgstr "Standardlänge von Slots (in Stunden) für dieses Event"
 
-#: AKModel/models.py:155
+#: AKModel/models.py:154
+msgid "Export Slot Length"
+msgstr "Export-Slotlänge"
+
+#: AKModel/models.py:156
+msgid ""
+"Slot duration in hours that is used in the timeslot discretization, when "
+"this event is exported for the solver."
+msgstr ""
+"Länge von Slots (in Stunden) in der Zeitslot-Diskretisierung beim "
+"JSON-Export dieses Events."
+
+#: AKModel/models.py:161
 msgid "Contact email address"
 msgstr "E-Mail Kontaktadresse"
 
-#: AKModel/models.py:156
+#: AKModel/models.py:162
 msgid ""
 "An email address that is displayed on every page and can be used for all "
 "kinds of questions"
@@ -432,16 +444,16 @@ msgstr ""
 "Eine Mailadresse die auf jeder Seite angezeigt wird und für alle Arten von "
 "Fragen genutzt werden kann"
 
-#: AKModel/models.py:161
+#: AKModel/models.py:167
 msgid "Events"
 msgstr "Events"
 
-#: AKModel/models.py:430
+#: AKModel/models.py:439
 #, python-brace-format
 msgid "AK {ak_name} is not assigned any timeslot by the solver"
 msgstr "Dem AK {ak_name} wurde vom Solver kein Zeitslot zugewiesen"
 
-#: AKModel/models.py:440
+#: AKModel/models.py:449
 #, python-brace-format
 msgid ""
 "Duration of AK {ak_name} assigned by solver ({solver_duration} hours) is "
@@ -451,7 +463,7 @@ msgstr ""
 "Stunden) ist kürzer als die aktuell vorgesehene Dauer des Slots "
 "({slot_duration} Stunden)"
 
-#: AKModel/models.py:454
+#: AKModel/models.py:463
 #, python-brace-format
 msgid ""
 "Fixed AK {ak_name} assigned by solver to room {solver_room} is fixed to room "
@@ -460,7 +472,7 @@ msgstr ""
 "Dem fix geplanten AK {ak_name} wurde vom Solver Raum {solver_room} "
 "zugewiesen, dabei ist der AK bereits fix in Raum {slot_room} eingeplant."
 
-#: AKModel/models.py:465
+#: AKModel/models.py:474
 #, python-brace-format
 msgid ""
 "Fixed AK {ak_name} assigned by solver to start at {solver_start} is fixed to "
@@ -469,71 +481,71 @@ msgstr ""
 "Dem fix geplanten AK {ak_name} wurde vom Solver die Startzeit {solver_start} "
 "zugewiesen, dabei ist der AK bereits für {slot_start} eingeplant."
 
-#: AKModel/models.py:484
+#: AKModel/models.py:493
 msgid "Nickname"
 msgstr "Spitzname"
 
-#: AKModel/models.py:484
+#: AKModel/models.py:493
 msgid "Name to identify an AK owner by"
 msgstr "Name, durch den eine AK-Leitung identifiziert wird"
 
-#: AKModel/models.py:485
+#: AKModel/models.py:494
 msgid "Slug"
 msgstr "Slug"
 
-#: AKModel/models.py:485
+#: AKModel/models.py:494
 msgid "Slug for URL generation"
 msgstr "Slug für URL-Generierung"
 
-#: AKModel/models.py:486
+#: AKModel/models.py:495
 msgid "Institution"
 msgstr "Instutution"
 
-#: AKModel/models.py:486
+#: AKModel/models.py:495
 msgid "Uni etc."
 msgstr "Universität o.ä."
 
-#: AKModel/models.py:487 AKModel/models.py:650
+#: AKModel/models.py:496 AKModel/models.py:659
 msgid "Web Link"
 msgstr "Internet Link"
 
-#: AKModel/models.py:487
+#: AKModel/models.py:496
 msgid "Link to Homepage"
 msgstr "Link zu Homepage oder Webseite"
 
-#: AKModel/models.py:493 AKModel/models.py:1125
+#: AKModel/models.py:502 AKModel/models.py:1133
 msgid "AK Owner"
 msgstr "AK-Leitung"
 
-#: AKModel/models.py:494
+#: AKModel/models.py:503
 msgid "AK Owners"
 msgstr "AK-Leitungen"
 
-#: AKModel/models.py:558
+#: AKModel/models.py:567
 msgid "Name of the AK Category"
 msgstr "Name der AK-Kategorie"
 
-#: AKModel/models.py:559 AKModel/models.py:597
+#: AKModel/models.py:568 AKModel/models.py:606
 msgid "Color"
 msgstr "Farbe"
 
-#: AKModel/models.py:559 AKModel/models.py:597
+#: AKModel/models.py:568 AKModel/models.py:606
 msgid "Color for displaying"
 msgstr "Farbe für die Anzeige"
 
-#: AKModel/models.py:560 AKModel/models.py:644
+#: AKModel/models.py:569 AKModel/models.py:653
 msgid "Description"
 msgstr "Beschreibung"
 
-#: AKModel/models.py:561
+#: AKModel/models.py:570
 msgid "Short description of this AK Category"
 msgstr "Beschreibung der AK-Kategorie"
 
-#: AKModel/models.py:562
+#: AKModel/models.py:571
 msgid "Present by default"
 msgstr "Defaultmäßig präsentieren"
 
-#: AKModel/models.py:563
+#: AKModel/models.py:572
 msgid ""
 "Present AKs of this category by default if AK owner did not specify whether "
 "this AK should be presented?"
@@ -541,132 +553,132 @@ msgstr ""
 "AKs dieser Kategorie standardmäßig vorstellen, wenn die Leitungen das für "
 "ihren AK nicht explizit spezifiziert haben?"
 
-#: AKModel/models.py:571
+#: AKModel/models.py:580
 msgid "AK Categories"
 msgstr "AK-Kategorien"
 
-#: AKModel/models.py:596
+#: AKModel/models.py:605
 msgid "Name of the AK Track"
 msgstr "Name des AK-Tracks"
 
-#: AKModel/models.py:603
+#: AKModel/models.py:612
 msgid "AK Track"
 msgstr "AK-Track"
 
-#: AKModel/models.py:604
+#: AKModel/models.py:613
 msgid "AK Tracks"
 msgstr "AK-Tracks"
 
-#: AKModel/models.py:623
+#: AKModel/models.py:632
 msgid "Name of the Requirement"
 msgstr "Name der Anforderung"
 
-#: AKModel/models.py:629 AKModel/models.py:1129
+#: AKModel/models.py:638 AKModel/models.py:1137
 msgid "AK Requirement"
 msgstr "AK-Anforderung"
 
-#: AKModel/models.py:630
+#: AKModel/models.py:639
 msgid "AK Requirements"
 msgstr "AK-Anforderungen"
 
-#: AKModel/models.py:641
+#: AKModel/models.py:650
 msgid "Name of the AK"
 msgstr "Name des AKs"
 
-#: AKModel/models.py:642
+#: AKModel/models.py:651
 msgid "Short Name"
 msgstr "Kurzer Name"
 
-#: AKModel/models.py:643
+#: AKModel/models.py:652
 msgid "Name displayed in the schedule"
 msgstr "Name zur Anzeige im AK-Plan"
 
-#: AKModel/models.py:644
+#: AKModel/models.py:653
 msgid "Description of the AK"
 msgstr "Beschreibung des AKs"
 
-#: AKModel/models.py:646
+#: AKModel/models.py:655
 msgid "Owners"
 msgstr "Leitungen"
 
-#: AKModel/models.py:647
+#: AKModel/models.py:656
 msgid "Those organizing the AK"
 msgstr "Menschen, die den AK organisieren und halten"
 
-#: AKModel/models.py:650
+#: AKModel/models.py:659
 msgid "Link to wiki page"
 msgstr "Link zur Wiki Seite"
 
-#: AKModel/models.py:651
+#: AKModel/models.py:660
 msgid "Protocol Link"
 msgstr "Protokolllink"
 
-#: AKModel/models.py:651
+#: AKModel/models.py:660
 msgid "Link to protocol"
 msgstr "Link zum Protokoll"
 
-#: AKModel/models.py:653
+#: AKModel/models.py:662
 msgid "Category"
 msgstr "Kategorie"
 
-#: AKModel/models.py:654
+#: AKModel/models.py:663
 msgid "Category of the AK"
 msgstr "Kategorie des AKs"
 
-#: AKModel/models.py:655
+#: AKModel/models.py:664
 msgid "Track"
 msgstr "Track"
 
-#: AKModel/models.py:656
+#: AKModel/models.py:665
 msgid "Track the AK belongs to"
 msgstr "Track zu dem der AK gehört"
 
-#: AKModel/models.py:658
+#: AKModel/models.py:667
 msgid "Resolution Intention"
 msgstr "Resolutionsabsicht"
 
-#: AKModel/models.py:659
+#: AKModel/models.py:668
 msgid "Intends to submit a resolution"
 msgstr "Beabsichtigt eine Resolution einzureichen"
 
-#: AKModel/models.py:660
+#: AKModel/models.py:669
 msgid "Present this AK"
 msgstr "AK präsentieren"
 
-#: AKModel/models.py:661
+#: AKModel/models.py:670
 msgid "Present results of this AK"
 msgstr "Die Ergebnisse dieses AKs vorstellen"
 
-#: AKModel/models.py:663 AKModel/models.py:716 AKModel/views/status.py:170
+#: AKModel/models.py:672 AKModel/models.py:725 AKModel/views/status.py:170
 msgid "Requirements"
 msgstr "Anforderungen"
 
-#: AKModel/models.py:664
+#: AKModel/models.py:673
 msgid "AK's Requirements"
 msgstr "Anforderungen des AKs"
 
-#: AKModel/models.py:666
+#: AKModel/models.py:675
 msgid "Conflicting AKs"
 msgstr "AK-Konflikte"
 
-#: AKModel/models.py:667
+#: AKModel/models.py:676
 msgid "AKs that conflict and thus must not take place at the same time"
 msgstr ""
 "AKs, die Konflikte haben und deshalb nicht gleichzeitig stattfinden dürfen"
 
-#: AKModel/models.py:668
+#: AKModel/models.py:677
 msgid "Prerequisite AKs"
 msgstr "Vorausgesetzte AKs"
 
-#: AKModel/models.py:669
+#: AKModel/models.py:678
 msgid "AKs that should precede this AK in the schedule"
 msgstr "AKs die im AK-Plan vor diesem AK stattfinden müssen"
 
-#: AKModel/models.py:671
+#: AKModel/models.py:680
 msgid "Organizational Notes"
 msgstr "Notizen zur Organisation"
 
-#: AKModel/models.py:672
+#: AKModel/models.py:681
 msgid ""
 "Notes to organizers. These are public. For private notes, please use the "
 "button for private messages on the detail page of this AK (after creation/"
@@ -676,299 +688,299 @@ msgstr ""
 "Anmerkungen bitte den Button für Direktnachrichten verwenden (nach dem "
 "Anlegen/Bearbeiten)."
 
-#: AKModel/models.py:675 AKModel/models.py:714
+#: AKModel/models.py:684 AKModel/models.py:723
 msgid "Interest"
 msgstr "Interesse"
 
-#: AKModel/models.py:675
+#: AKModel/models.py:684
 msgid "Expected number of people"
 msgstr "Erwartete Personenzahl"
 
-#: AKModel/models.py:676
+#: AKModel/models.py:685
 msgid "Interest Counter"
 msgstr "Interessenszähler"
 
-#: AKModel/models.py:677
+#: AKModel/models.py:686
 msgid "People who have indicated interest online"
 msgstr "Anzahl Personen, die online Interesse bekundet haben"
 
-#: AKModel/models.py:682
+#: AKModel/models.py:691
 msgid "Export?"
 msgstr "Export?"
 
-#: AKModel/models.py:683
+#: AKModel/models.py:692
 msgid "Include AK in wiki export?"
 msgstr "AK bei Wiki-Export berücksichtigen?"
 
-#: AKModel/models.py:718
+#: AKModel/models.py:727
 msgid "Conflicts"
 msgstr "Konflikte"
 
-#: AKModel/models.py:720
+#: AKModel/models.py:729
 msgid "Prerequisites"
 msgstr "Voraussetzungen"
 
-#: AKModel/models.py:813
+#: AKModel/models.py:822
 msgid "Name or number of the room"
 msgstr "Name oder Nummer des Raums"
 
-#: AKModel/models.py:814
+#: AKModel/models.py:823
 msgid "Location"
 msgstr "Ort"
 
-#: AKModel/models.py:815
+#: AKModel/models.py:824
 msgid "Name or number of the location"
 msgstr "Name oder Nummer des Ortes"
 
-#: AKModel/models.py:816
+#: AKModel/models.py:825
 msgid "Capacity"
 msgstr "Kapazität"
 
-#: AKModel/models.py:817
+#: AKModel/models.py:826
 msgid "Maximum number of people (-1 for unlimited)."
 msgstr "Maximale Personenzahl (-1 wenn unbeschränkt)."
 
-#: AKModel/models.py:818
+#: AKModel/models.py:827
 msgid "Properties"
 msgstr "Eigenschaften"
 
-#: AKModel/models.py:819
+#: AKModel/models.py:828
 msgid "AK requirements fulfilled by the room"
 msgstr "AK-Anforderungen, die dieser Raum erfüllt"
 
-#: AKModel/models.py:826 AKModel/views/status.py:59
+#: AKModel/models.py:835 AKModel/views/status.py:59
 msgid "Rooms"
 msgstr "Räume"
 
-#: AKModel/models.py:886
+#: AKModel/models.py:895
 msgid "AK being mapped"
 msgstr "AK, der zugeordnet wird"
 
-#: AKModel/models.py:888
+#: AKModel/models.py:897
 msgid "Room the AK will take place in"
 msgstr "Raum in dem der AK stattfindet"
 
-#: AKModel/models.py:889 AKModel/models.py:1304
+#: AKModel/models.py:898 AKModel/models.py:1312
 msgid "Slot Begin"
 msgstr "Beginn des Slots"
 
-#: AKModel/models.py:889 AKModel/models.py:1304
+#: AKModel/models.py:898 AKModel/models.py:1312
 msgid "Time and date the slot begins"
 msgstr "Zeit und Datum zu der der AK beginnt"
 
-#: AKModel/models.py:891
+#: AKModel/models.py:900
 msgid "Duration"
 msgstr "Dauer"
 
-#: AKModel/models.py:892
+#: AKModel/models.py:901
 msgid "Length in hours"
 msgstr "Länge in Stunden"
 
-#: AKModel/models.py:894
+#: AKModel/models.py:903
 msgid "Scheduling fixed"
 msgstr "Planung fix"
 
-#: AKModel/models.py:895
+#: AKModel/models.py:904
 msgid "Length and time of this AK should not be changed"
 msgstr "Dauer und Zeit dieses AKs sollten nicht verändert werden"
 
-#: AKModel/models.py:900
+#: AKModel/models.py:909
 msgid "Last update"
 msgstr "Letzte Aktualisierung"
 
-#: AKModel/models.py:903
+#: AKModel/models.py:912
 msgid "AK Slot"
 msgstr "AK-Slot"
 
-#: AKModel/models.py:904 AKModel/models.py:1122 AKModel/models.py:1157
+#: AKModel/models.py:913 AKModel/models.py:1130 AKModel/models.py:1165
 msgid "AK Slots"
 msgstr "AK-Slot"
 
-#: AKModel/models.py:926 AKModel/models.py:935
+#: AKModel/models.py:935 AKModel/models.py:944
 msgid "Not scheduled yet"
 msgstr "Noch nicht geplant"
 
-#: AKModel/models.py:1055
+#: AKModel/models.py:1063
 msgid "AK this message belongs to"
 msgstr "AK zu dem die Nachricht gehört"
 
-#: AKModel/models.py:1056
+#: AKModel/models.py:1064
 msgid "Message text"
 msgstr "Nachrichtentext"
 
-#: AKModel/models.py:1057
+#: AKModel/models.py:1065
 msgid "Message to the organizers. This is not publicly visible."
 msgstr ""
 "Nachricht an die Organisator*innen. Diese ist nicht öffentlich sichtbar."
 
-#: AKModel/models.py:1061
+#: AKModel/models.py:1069
 msgid "Resolved"
 msgstr "Erledigt"
 
-#: AKModel/models.py:1062
+#: AKModel/models.py:1070
 msgid "This message has been resolved (no further action needed)"
 msgstr ""
 "Diese Nachricht wurde vollständig bearbeitet (keine weiteren Aktionen "
 "notwendig)"
 
-#: AKModel/models.py:1065
+#: AKModel/models.py:1073
 msgid "AK Orga Message"
 msgstr "AK-Organachricht"
 
-#: AKModel/models.py:1066
+#: AKModel/models.py:1074
 msgid "AK Orga Messages"
 msgstr "AK-Organachrichten"
 
-#: AKModel/models.py:1083
+#: AKModel/models.py:1091
 msgid "Constraint Violation"
 msgstr "Constraintverletzung"
 
-#: AKModel/models.py:1084
+#: AKModel/models.py:1092
 msgid "Constraint Violations"
 msgstr "Constraintverletzungen"
 
-#: AKModel/models.py:1091
+#: AKModel/models.py:1099
 msgid "Owner has two parallel slots"
 msgstr "Leitung hat zwei Slots parallel"
 
-#: AKModel/models.py:1092
+#: AKModel/models.py:1100
 msgid "AK Slot was scheduled outside the AK's availabilities"
 msgstr "AK Slot wurde außerhalb der Verfügbarkeit des AKs platziert"
 
-#: AKModel/models.py:1093
+#: AKModel/models.py:1101
 msgid "Room has two AK slots scheduled at the same time"
 msgstr "Raum hat zwei AK Slots gleichzeitig"
 
-#: AKModel/models.py:1094
+#: AKModel/models.py:1102
 msgid "Room does not satisfy the requirement of the scheduled AK"
 msgstr "Room erfüllt die Anforderungen des platzierten AKs nicht"
 
-#: AKModel/models.py:1095
+#: AKModel/models.py:1103
 msgid "AK Slot is scheduled at the same time as an AK listed as a conflict"
 msgstr ""
 "AK Slot wurde wurde zur gleichen Zeit wie ein Konflikt des AKs platziert"
 
-#: AKModel/models.py:1096
+#: AKModel/models.py:1104
 msgid "AK Slot is scheduled before an AK listed as a prerequisite"
 msgstr "AK Slot wurde vor einem als Voraussetzung gelisteten AK platziert"
 
-#: AKModel/models.py:1098
+#: AKModel/models.py:1106
 msgid ""
 "AK Slot for AK with intention to submit a resolution is scheduled after "
 "resolution deadline"
 msgstr ""
 "AK Slot eines AKs mit Resoabsicht wurde nach der Resodeadline platziert"
 
-#: AKModel/models.py:1099
+#: AKModel/models.py:1107
 msgid "AK Slot in a category is outside that categories availabilities"
 msgstr "AK Slot wurde außerhalb der Verfügbarkeiten seiner Kategorie"
 
-#: AKModel/models.py:1100
+#: AKModel/models.py:1108
 msgid "Two AK Slots for the same AK scheduled at the same time"
 msgstr "Zwei AK Slots eines AKs wurden zur selben Zeit platziert"
 
-#: AKModel/models.py:1101
+#: AKModel/models.py:1109
 msgid "Room does not have enough space for interest in scheduled AK Slot"
 msgstr "Room hat nicht genug Platz für das Interesse am geplanten AK-Slot"
 
-#: AKModel/models.py:1102
+#: AKModel/models.py:1110
 msgid "AK Slot is scheduled outside the event's availabilities"
 msgstr "AK Slot wurde außerhalb der Verfügbarkeit des Events platziert"
 
-#: AKModel/models.py:1108
+#: AKModel/models.py:1116
 msgid "Warning"
 msgstr "Warnung"
 
-#: AKModel/models.py:1109
+#: AKModel/models.py:1117
 msgid "Violation"
 msgstr "Verletzung"
 
-#: AKModel/models.py:1111
+#: AKModel/models.py:1119
 msgid "Type"
 msgstr "Art"
 
-#: AKModel/models.py:1112
+#: AKModel/models.py:1120
 msgid "Type of violation, i.e. what kind of constraint was violated"
 msgstr "Art der Verletzung, gibt an welche Art Constraint verletzt wurde"
 
-#: AKModel/models.py:1113
+#: AKModel/models.py:1121
 msgid "Level"
 msgstr "Level"
 
-#: AKModel/models.py:1114
+#: AKModel/models.py:1122
 msgid "Severity level of the violation"
 msgstr "Schweregrad der Verletzung"
 
-#: AKModel/models.py:1121
+#: AKModel/models.py:1129
 msgid "AK(s) belonging to this constraint"
 msgstr "AK(s), die zu diesem Constraint gehören"
 
-#: AKModel/models.py:1123
+#: AKModel/models.py:1131
 msgid "AK Slot(s) belonging to this constraint"
 msgstr "AK Slot(s), die zu diesem Constraint gehören"
 
-#: AKModel/models.py:1125
+#: AKModel/models.py:1133
 msgid "AK Owner belonging to this constraint"
 msgstr "AK Leitung(en), die zu diesem Constraint gehören"
 
-#: AKModel/models.py:1127
+#: AKModel/models.py:1135
 msgid "Room belonging to this constraint"
 msgstr "Raum, der zu diesem Constraint gehört"
 
-#: AKModel/models.py:1130
+#: AKModel/models.py:1138
 msgid "AK Requirement belonging to this constraint"
 msgstr "AK Anforderung, die zu diesem Constraint gehört"
 
-#: AKModel/models.py:1132
+#: AKModel/models.py:1140
 msgid "AK Category belonging to this constraint"
 msgstr "AK Kategorie, di zu diesem Constraint gehört"
 
-#: AKModel/models.py:1134
+#: AKModel/models.py:1142
 msgid "Comment"
 msgstr "Kommentar"
 
-#: AKModel/models.py:1134
+#: AKModel/models.py:1142
 msgid "Comment or further details for this violation"
 msgstr "Kommentar oder weitere Details zu dieser Vereletzung"
 
-#: AKModel/models.py:1137
+#: AKModel/models.py:1145
 msgid "Timestamp"
 msgstr "Timestamp"
 
-#: AKModel/models.py:1137
+#: AKModel/models.py:1145
 msgid "Time of creation"
 msgstr "Zeitpunkt der ERstellung"
 
-#: AKModel/models.py:1138
+#: AKModel/models.py:1146
 msgid "Manually Resolved"
 msgstr "Manuell behoben"
 
-#: AKModel/models.py:1139
+#: AKModel/models.py:1147
 msgid "Mark this violation manually as resolved"
 msgstr "Markiere diese Verletzung manuell als behoben"
 
-#: AKModel/models.py:1166
+#: AKModel/models.py:1174
 #: AKModel/templates/admin/AKModel/requirements_overview.html:27
 msgid "Details"
 msgstr "Details"
 
-#: AKModel/models.py:1300
+#: AKModel/models.py:1308
 msgid "Default Slot"
 msgstr "Standardslot"
 
-#: AKModel/models.py:1305
+#: AKModel/models.py:1313
 msgid "Slot End"
 msgstr "Ende des Slots"
 
-#: AKModel/models.py:1305
+#: AKModel/models.py:1313
 msgid "Time and date the slot ends"
 msgstr "Zeit und Datum zu der der Slot endet"
 
-#: AKModel/models.py:1310
+#: AKModel/models.py:1318
 msgid "Primary categories"
 msgstr "Primäre Kategorien"
 
-#: AKModel/models.py:1311
+#: AKModel/models.py:1319
 msgid "Categories that should be assigned to this slot primarily"
 msgstr "Kategorieren, die diesem Slot primär zugewiesen werden sollen"
 
@@ -1178,35 +1190,35 @@ msgstr "AK-CSV-Export"
 msgid "AK JSON Export"
 msgstr "AK-JSON-Export"
 
-#: AKModel/views/ak.py:190
+#: AKModel/views/ak.py:184
 msgid "AK Wiki Export"
 msgstr "AK-Wiki-Export"
 
-#: AKModel/views/ak.py:201 AKModel/views/manage.py:55
+#: AKModel/views/ak.py:195 AKModel/views/manage.py:55
 msgid "Wishes"
 msgstr "Wünsche"
 
-#: AKModel/views/ak.py:213
+#: AKModel/views/ak.py:207
 msgid "Delete AK Orga Messages"
 msgstr "AK-Organachrichten löschen"
 
-#: AKModel/views/ak.py:231
+#: AKModel/views/ak.py:225
 msgid "AK Orga Messages successfully deleted"
 msgstr "AK-Organachrichten erfolgreich gelöscht"
 
-#: AKModel/views/ak.py:243
+#: AKModel/views/ak.py:237
 msgid "Interest of the following AKs will be set to not filled (-1):"
 msgstr "Interesse an den folgenden AKs wird auf nicht ausgefüllt (-1) gesetzt:"
 
-#: AKModel/views/ak.py:244
+#: AKModel/views/ak.py:238
 msgid "Reset of interest in AKs successful."
 msgstr "Interesse an AKs erfolgreich zurückgesetzt."
 
-#: AKModel/views/ak.py:258
+#: AKModel/views/ak.py:252
 msgid "Interest counter of the following AKs will be set to 0:"
 msgstr "Interessensbekundungszähler der folgenden AKs wird auf 0 gesetzt:"
 
-#: AKModel/views/ak.py:259
+#: AKModel/views/ak.py:253
 msgid "AKs' interest counters set back to 0."
 msgstr "Interessenszähler der AKs zurückgesetzt"
 
-- 
GitLab


From 8501afaf52df8c23716109cb7d6c9270e5fbb363 Mon Sep 17 00:00:00 2001
From: Felix Blanke <info@fblanke.de>
Date: Thu, 6 Feb 2025 17:46:26 +0100
Subject: [PATCH 3/4] Address line length

---
 AKModel/models.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/AKModel/models.py b/AKModel/models.py
index b3820a15..e3530861 100644
--- a/AKModel/models.py
+++ b/AKModel/models.py
@@ -153,8 +153,8 @@ class Event(models.Model):
                                        help_text=_('Default length in hours that is assumed for AKs in this event.'))
     export_slot = models.DecimalField(max_digits=4, decimal_places=2, default=1, verbose_name=_('Export Slot Length'),
                                         help_text=_(
-                                            'Slot duration in hours that is used in the timeslot discretization, when this event '
-                                            'is exported for the solver.'
+                                            'Slot duration in hours that is used in the timeslot discretization, '
+                                            'when this event is exported for the solver.'
                                         ))
 
 
-- 
GitLab


From ed98da8ded352f56fc838552d7133839423c916b Mon Sep 17 00:00:00 2001
From: Lorenzo Conti <lorenzo@uni-bonn.de>
Date: Thu, 6 Feb 2025 18:14:09 +0000
Subject: [PATCH 4/4] Apply 3 suggestion(s) to 2 file(s)

Co-authored-by: Felix Blanke <s6feblan@uni-bonn.de>
---
 AKModel/models.py   | 4 ++--
 AKModel/views/ak.py | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/AKModel/models.py b/AKModel/models.py
index e3530861..8601a992 100644
--- a/AKModel/models.py
+++ b/AKModel/models.py
@@ -402,7 +402,7 @@ class Event(models.Model):
         """
 
         if slots_in_an_hour is None:
-            slots_in_an_hour = float(self.export_slot)
+            slots_in_an_hour = 1.0 / float(self.export_slot)
 
         if DefaultSlot.objects.filter(event=self).exists():
             # discretize default slots if they exists
@@ -1018,7 +1018,7 @@ class AKSlot(models.Model):
 
         data = {
             "id": str(self.pk),
-            "duration": math.ceil(self.duration * self.event.export_slot - ceil_offet_eps),
+            "duration": math.ceil(self.duration / self.event.export_slot - ceil_offet_eps),
             "properties": {
                 "conflicts":
                     [str(conflict.pk) for conflict in conflict_slots.all()]
diff --git a/AKModel/views/ak.py b/AKModel/views/ak.py
index d9a5e6a8..f6fd7932 100644
--- a/AKModel/views/ak.py
+++ b/AKModel/views/ak.py
@@ -92,7 +92,7 @@ class AKJSONExportView(AdminViewMixin, FilterByEventSlugMixin, ListView):
         context["rooms"] = rooms
 
         timeslots = {
-            "info": {"duration": (1.0 / float(self.event.export_slot)), },
+            "info": {"duration": float(self.event.export_slot)},
             "blocks": [],
             }
 
-- 
GitLab