2020-07-22 04:02:13 +02:00
|
|
|
from datetime import date, timedelta
|
|
|
|
from typing import List
|
|
|
|
|
|
|
|
from KeRS.celery import app
|
2020-08-04 03:32:02 +02:00
|
|
|
from events.models import Event, EventRegistration, TimeSlot
|
2020-07-22 04:02:13 +02:00
|
|
|
from users.models import CustomUser
|
|
|
|
|
|
|
|
|
|
|
|
def calc_score(user: CustomUser):
|
2020-08-04 03:32:02 +02:00
|
|
|
registrations_last_month: List[EventRegistration] = EventRegistration.objects \
|
|
|
|
.filter(user_id=user.id,
|
|
|
|
time_slot__event__date__gt=date.today() - timedelta(days=30),
|
|
|
|
time_slot__event__date__lte=date.today(),
|
|
|
|
state=EventRegistration.ADMITTED)
|
2020-07-22 04:02:13 +02:00
|
|
|
score = 0
|
|
|
|
for r in registrations_last_month:
|
2020-08-04 03:32:02 +02:00
|
|
|
days_ago = (date.today() - r.time_slot.event.date).days
|
2020-07-22 04:02:13 +02:00
|
|
|
score += 1 / (days_ago + 1)
|
|
|
|
|
|
|
|
return score
|
|
|
|
|
|
|
|
|
|
|
|
@app.task(bind=True)
|
2020-08-04 03:32:02 +02:00
|
|
|
def assign_reservations(self, dry_run=False):
|
2020-07-22 04:02:13 +02:00
|
|
|
"""
|
2020-07-26 00:41:06 +02:00
|
|
|
Check if there are any events the next day.
|
2020-07-22 04:02:13 +02:00
|
|
|
If so, calculate the current score for every interested user and assign the ones with the lowest scores.
|
2020-08-04 03:32:02 +02:00
|
|
|
:param dry_run: If this is set to true, no persistent changes will be made.
|
2020-07-22 04:02:13 +02:00
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
print("Assigning reservations")
|
|
|
|
print("======================")
|
|
|
|
# Get all events of tomorrow
|
2020-08-04 03:32:02 +02:00
|
|
|
events: List[Event] = Event.objects.filter(date=date.today() + timedelta(days=1))
|
|
|
|
# Get all timeslots of tomorrow
|
|
|
|
timeslots: List[TimeSlot] = TimeSlot.objects.filter(event_id__in=map(lambda e: e.id, events))
|
2020-07-22 04:02:13 +02:00
|
|
|
|
|
|
|
# Reservations
|
2020-07-26 00:41:35 +02:00
|
|
|
registrations: List[EventRegistration] = EventRegistration.objects.filter(
|
2020-08-04 03:32:02 +02:00
|
|
|
time_slot_id__in=map(lambda timeslot: timeslot.id, timeslots),
|
2020-07-25 18:28:04 +02:00
|
|
|
state=EventRegistration.INTERESTED)
|
2020-07-22 04:02:13 +02:00
|
|
|
if len(registrations) == 0:
|
|
|
|
print("NO REGISTRATIONS?")
|
|
|
|
|
|
|
|
# Relevant users
|
|
|
|
users = set(map(lambda r: r.user, registrations))
|
|
|
|
scores = list(map(calc_score, users))
|
|
|
|
queue = sorted(list(zip(users, scores)), key=lambda tup: tup[1])
|
|
|
|
print(f"Scores: {scores}")
|
|
|
|
print(f"Queue: {queue}")
|
|
|
|
|
2020-08-04 03:32:02 +02:00
|
|
|
for timeslot in timeslots:
|
|
|
|
print(f"EVENT: {timeslot.event.date} - {timeslot.event.capacity}")
|
|
|
|
timeslot_registrations = list(filter(lambda r: r.time_slot == timeslot, registrations))
|
|
|
|
timeslot_users = set(map(lambda r: r.user, timeslot_registrations))
|
|
|
|
timeslot_queue = list(filter(lambda element: element[0] in timeslot_users, queue))
|
2020-07-22 04:02:13 +02:00
|
|
|
|
2020-08-04 03:32:02 +02:00
|
|
|
for user in timeslot_queue[0:timeslot.event.capacity]:
|
2020-07-22 04:02:13 +02:00
|
|
|
print(f"Selected {user[0]}")
|
|
|
|
r = EventRegistration.objects.get(
|
2020-08-04 03:32:02 +02:00
|
|
|
time_slot_id=timeslot.id,
|
2020-07-22 04:02:13 +02:00
|
|
|
user_id=user[0].id
|
|
|
|
)
|
2020-07-25 16:33:20 +02:00
|
|
|
r.state = EventRegistration.ADMITTED
|
2020-08-04 03:32:02 +02:00
|
|
|
if not dry_run:
|
|
|
|
r.save()
|