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

Generate timeslots based on default slots

parent aea39c3c
No related branches found
No related tags found
2 merge requests!3Merge into fork's `main` branch,!1Generate timeslots based on default slots
import itertools
import json
from datetime import timedelta
from datetime import datetime, timedelta
from typing import Iterable
from django.db import models
from django.apps import apps
......@@ -163,67 +164,91 @@ class Event(models.Model):
.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
rooms = Room.objects.filter(event=self)
slot_duration = timedelta(hours=(1.0 / slots_in_an_hour))
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()})
current_slot_start = start
previous_slot_start: datetime | None = None
while current_slot < self.end:
slot = Availability(event=self,
start=current_slot,
end=current_slot + slot_duration)
current_block = []
if any((availability.contains(slot)
for availability in room_availabilities)):
if previous_slot is not None and previous_slot + slot_duration < current_slot:
room_availabilities = list({
availability
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
current_block = []
current_block.append(slot_index)
previous_slot = current_slot
current_block.append((slot_index, slot))
previous_slot_start = current_slot_start
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":
from AKModel.availability.models import Availability
slot_duration = timedelta(hours=(1.0 / slots_in_an_hour))
return slot_index
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,
start=start,
end=start + slot_duration)
def default_time_slots(self, *, slots_in_an_hour=1.0) -> Iterable[list[int, "Availability"]]:
slot_duration = timedelta(hours=(1.0 / slots_in_an_hour))
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:
schedule = json.loads(schedule)
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"]:
slot = AKSlot.objects.get(id=int(scheduled_slot["ak_id"]))
slot.room = Room.objects.get(id=int(scheduled_slot["room_id"]))
scheduled_slot["timeslot_ids"] = list(map(int, scheduled_slot["timeslot_ids"]))
start = min(scheduled_slot["timeslot_ids"])
end = max(scheduled_slot["timeslot_ids"])
slot.start = self.time_slot(time_slot_index=start,
slots_in_an_hour=slots_in_an_hour).start
start_timeslot = timeslot_dict[min(scheduled_slot["timeslot_ids"])]
end_timeslot = timeslot_dict[max(scheduled_slot["timeslot_ids"])]
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()
class AKOwner(models.Model):
......
......@@ -107,12 +107,10 @@ class AKJSONExportView(AdminViewMixin, FilterByEventSlugMixin, ListView):
def _test_add_constraint(slot: Availability, availabilities: List[Availability]) -> bool:
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 = []
for slot_index in block:
slot = self.event.time_slot(time_slot_index=slot_index,
slots_in_an_hour=SLOTS_IN_AN_HOUR)
for slot_index, slot in block:
time_constraints = []
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