kers/events/tasks.py

77 lines
2.6 KiB
Python

from datetime import date, timedelta
from typing import List
from KeRS.celery import app
from events.models import Event, EventRegistration
from users.models import CustomUser
def calc_score(user: CustomUser):
registrations_last_month = EventRegistration.objects.filter(
user_id=user.id,
event__date__gt=date.today() - timedelta(days=30),
event__date__lte=date.today(),
state=EventRegistration.ADMITTED
)
score = 0
for r in registrations_last_month:
days_ago = (date.today() - r.event.date.date()).days
score += 1 / (days_ago + 1)
return score
@app.task(bind=True)
def assign_reservations(self):
"""
Check if there are any events tomorrow.
If so, calculate the current score for every interested user and assign the ones with the lowest scores.
:param self:
:return:
"""
# Get all events of tomorrow
events = Event.objects.filter(date=date.today() + timedelta(days=1))
print(f"{len(events) if events else 'Geen'} event(s)")
# Reservations
registrations: List[EventRegistration] = EventRegistration.objects.filter(
event_id__in=map(lambda event: event.id, events))
print(f"{len(registrations) if registrations else 'Geen'} registratie(s)")
print("")
# Relevant users
users = [r.user for r in registrations if r.state == EventRegistration.INTERESTED]
scores = list(map(calc_score, users))
queue = sorted(list(zip(users, scores)), key=lambda tup: tup[1])
print("Prioriteiten: " + ", ".join(f"{u.username} ({s})" for u, s in queue))
print("")
for event in events:
registrations = [r for r in registrations if r.event == event]
already_admitted_regs = [r for r in registrations if r.state == EventRegistration.ADMITTED]
left = max(event.capacity - sum(1 for r in already_admitted_regs), 0)
moment_str = Event.TIME_SLOTS[event.time]
print(f"• Event: {event.date}, {moment_str}. Vrije plaatsen: {left}/{event.capacity}")
for reg in already_admitted_regs:
print(f" = {reg.user.username}")
interested_users = {r.user for r in registrations
if r.state == EventRegistration.INTERESTED}
user_queue = list(filter(lambda element: element[0] in interested_users, queue))
for user in user_queue[0:left]:
print(f" + {user[0].username}")
r = EventRegistration.objects.get(
event_id=event.id,
user_id=user[0].id
)
r.state = EventRegistration.ADMITTED
r.save()
left -= 1
print(f" → Vrije plaatsen: {left}/{event.capacity}")