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).days score += 1 / (days_ago + 1) return score @app.task(bind=True) def assign_reservations(self): """ Check if there are any events the next day. If so, calculate the current score for every interested user and assign the ones with the lowest scores. :param self: :return: """ print("Assigning reservations") print("======================") # Get all events of tomorrow events = Event.objects.filter(date=date.today() + timedelta(days=1)) # Reservations registrations: List[EventRegistration] = EventRegistration.objects.filter( event_id__in=map(lambda event: event.id, events), state=EventRegistration.INTERESTED) 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}") for event in events: print(f"EVENT: {event.date} - {event.capacity}") event_registrations = list(filter(lambda r: r.event == event, registrations)) event_users = set(map(lambda r: r.user, event_registrations)) event_queue = list(filter(lambda element: element[0] in event_users, queue)) for user in event_queue[0:event.capacity]: print(f"Selected {user[0]}") r = EventRegistration.objects.get( event_id=event.id, user_id=user[0].id ) r.state = EventRegistration.ADMITTED r.save()