Skip to content
Snippets Groups Projects
Commit 6147e386 authored by Felix Blanke's avatar Felix Blanke
Browse files

Merge branch 'feature/timeslot-from-default-slots' into 'feature-json-export'

Generate timeslots based on default slots

See merge request !1
parents aea39c3c 15f238b0
No related branches found
No related tags found
2 merge requests!3Merge into fork's `main` branch,!1Generate timeslots based on default slots
Pipeline #236052 passed
import itertools import itertools
import json import json
from datetime import timedelta from datetime import datetime, timedelta
from typing import Iterable
from django.db import models from django.db import models
from django.apps import apps from django.apps import apps
...@@ -163,67 +164,91 @@ class Event(models.Model): ...@@ -163,67 +164,91 @@ class Event(models.Model):
.filter(availabilities__count=0, owners__count__gt=0) .filter(availabilities__count=0, owners__count__gt=0)
) )
def time_slots(self, *, slots_in_an_hour=1.0): def _generate_slots_from_block(
self, start: datetime, end: datetime, slot_duration: timedelta, slot_index: int = 0
) -> Iterable[list[int, "Availability"]]:
from AKModel.availability.models import Availability from AKModel.availability.models import Availability
rooms = Room.objects.filter(event=self) current_slot_start = start
slot_duration = timedelta(hours=(1.0 / slots_in_an_hour)) previous_slot_start: datetime | None = None
slot_index = 0
current_slot = self.start
current_block = []
previous_slot = None
room_availabilities = list({availability
for room in rooms
for availability in room.availabilities.all()})
while current_slot < self.end: current_block = []
slot = Availability(event=self,
start=current_slot,
end=current_slot + slot_duration)
if any((availability.contains(slot) room_availabilities = list({
for availability in room_availabilities)): availability
if previous_slot is not None and previous_slot + slot_duration < current_slot: for room in Room.objects.filter(event=self)
for availability in room.availabilities.all()
})
while current_slot_start + slot_duration <= end:
slot = Availability(
event=self,
start=current_slot_start,
end=current_slot_start + slot_duration,
)
if any((availability.contains(slot) for availability in room_availabilities)):
# no gap in a block
if (
previous_slot_start is not None
and previous_slot_start + slot_duration < current_slot_start
):
yield current_block yield current_block
current_block = [] current_block = []
current_block.append(slot_index) current_block.append((slot_index, slot))
previous_slot = current_slot previous_slot_start = current_slot_start
slot_index += 1 slot_index += 1
current_slot += slot_duration current_slot_start += slot_duration
yield current_block if current_block:
yield current_block
def time_slot(self, *, time_slot_index: int, slots_in_an_hour: float = 1.0) -> "Availability": return slot_index
from AKModel.availability.models import Availability
slot_duration = timedelta(hours=(1.0 / slots_in_an_hour))
start = self.start + time_slot_index * slot_duration def uniform_time_slots(self, *, slots_in_an_hour=1.0) -> Iterable[list[int, "Availability"]]:
yield from self._generate_slots_from_block(
start=self.start,
end=self.end,
slot_duration=timedelta(hours=(1.0 / slots_in_an_hour)),
)
return Availability(event=self, def default_time_slots(self, *, slots_in_an_hour=1.0) -> Iterable[list[int, "Availability"]]:
start=start, slot_duration = timedelta(hours=(1.0 / slots_in_an_hour))
end=start + slot_duration) slot_index = 0
for block_slot in DefaultSlot.objects.filter(event=self).order_by("start", "end"):
# NOTE: We do not differentiate between different primary categories
slot_index = yield from self._generate_slots_from_block(
start=block_slot.start,
end=block_slot.end,
slot_duration=slot_duration,
slot_index=slot_index,
)
def schedule_from_json(self, schedule: str) -> None: def schedule_from_json(self, schedule: str) -> None:
schedule = json.loads(schedule) schedule = json.loads(schedule)
slots_in_an_hour = schedule["input"]["timeslots"]["info"]["duration"] slots_in_an_hour = schedule["input"]["timeslots"]["info"]["duration"]
timeslot_dict = {
slot_idx: slot
for block in self.default_time_slots(slots_in_an_hour=slots_in_an_hour)
for slot_idx, slot in block
}
for scheduled_slot in schedule["scheduled_aks"]: for scheduled_slot in schedule["scheduled_aks"]:
slot = AKSlot.objects.get(id=int(scheduled_slot["ak_id"])) slot = AKSlot.objects.get(id=int(scheduled_slot["ak_id"]))
slot.room = Room.objects.get(id=int(scheduled_slot["room_id"])) slot.room = Room.objects.get(id=int(scheduled_slot["room_id"]))
scheduled_slot["timeslot_ids"] = list(map(int, scheduled_slot["timeslot_ids"])) scheduled_slot["timeslot_ids"] = list(map(int, scheduled_slot["timeslot_ids"]))
start = min(scheduled_slot["timeslot_ids"]) start_timeslot = timeslot_dict[min(scheduled_slot["timeslot_ids"])]
end = max(scheduled_slot["timeslot_ids"]) end_timeslot = timeslot_dict[max(scheduled_slot["timeslot_ids"])]
slot.start = self.time_slot(time_slot_index=start,
slots_in_an_hour=slots_in_an_hour).start
slot.duration = (end - start + 1) * timedelta(hours=(1.0 / slots_in_an_hour)).total_seconds() / 3600.0 slot.start = start_timeslot.start
slot.duration = (end_timeslot.end - start_timeslot.start).total_seconds() / 3600.0
slot.save() slot.save()
class AKOwner(models.Model): class AKOwner(models.Model):
......
...@@ -107,12 +107,10 @@ class AKJSONExportView(AdminViewMixin, FilterByEventSlugMixin, ListView): ...@@ -107,12 +107,10 @@ class AKJSONExportView(AdminViewMixin, FilterByEventSlugMixin, ListView):
def _test_add_constraint(slot: Availability, availabilities: List[Availability]) -> bool: def _test_add_constraint(slot: Availability, availabilities: List[Availability]) -> bool:
return _test_event_covered(slot, availabilities) and _test_slot_contained(slot, availabilities) return _test_event_covered(slot, availabilities) and _test_slot_contained(slot, availabilities)
for block in self.event.time_slots(slots_in_an_hour=SLOTS_IN_AN_HOUR): for block in self.event.default_time_slots(slots_in_an_hour=SLOTS_IN_AN_HOUR):
current_block = [] current_block = []
for slot_index in block: for slot_index, slot in block:
slot = self.event.time_slot(time_slot_index=slot_index,
slots_in_an_hour=SLOTS_IN_AN_HOUR)
time_constraints = [] time_constraints = []
if self.event.reso_deadline is None or slot.end < self.event.reso_deadline: if self.event.reso_deadline is None or slot.end < self.event.reso_deadline:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment