Update draw function to take n years of history in account

This commit is contained in:
jeanGaston 2024-10-25 10:44:39 +02:00
parent 0d9f5264d4
commit 598bae34ba

View File

@ -1,41 +1,51 @@
from random import choice from random import choice
def draw_names(previous_draw, draws_per_person): def draw_names(current_participants, history_data, draws_per_person, max_attempts=5):
""" """
Perform the Secret Santa draw considering past draws. Perform the Secret Santa draw considering past years' draws.
:param previous_draw: Last year's draw data (list of participants and recipients). :param current_participants: This year's participant list.
:param history_data: Historical draw data to avoid repeats.
:param draws_per_person: Number of people each participant should give gifts to. :param draws_per_person: Number of people each participant should give gifts to.
:param max_attempts: Maximum number of retry attempts before loosening exclusions. by default : 5.
:return: The new draw results. :return: The new draw results.
""" """
participants = [a[0] for a in previous_draw] # Get participant names participants = [p[0] for p in current_participants] # Get participant names
already_drawn = [] # Track who has been drawn already_drawn = [] # Track who has been drawn
new_draw = [] # Store new draw results new_draw = [] # Store new draw results
for i in range(len(participants)): for attempt in range(max_attempts):
giver = previous_draw[i][0] new_draw.clear()
email = previous_draw[i][1] already_drawn.clear()
print(email) success = True # Track if draw is successful in this attempt
last_year_r1 = previous_draw[i][2]
last_year_r2 = previous_draw[i][3]
available_participants = participants.copy() for i, giver in enumerate(participants):
try: email = current_participants[i][1]
available_participants.remove(giver) # Collect previous recipients to avoid drawing the same person again
available_participants.remove(last_year_r1) previous_recipients = {recipient for record in history_data if record[0] == giver for recipient in record[2:]}
available_participants.remove(last_year_r2)
except ValueError:
pass
new_recipients = [] # Create a set of available participants excluding the giver and previous recipients
while len(new_recipients) < draws_per_person: available_participants = set(participants) - {giver} - previous_recipients
selected = choice(available_participants) new_recipients = []
if already_drawn.count(selected) >= draws_per_person:
available_participants.remove(selected)
else:
new_recipients.append(selected)
already_drawn.append(selected)
available_participants.remove(selected)
new_draw.append([giver, email] + new_recipients) # Ensure there are enough available participants for the draw
if len(available_participants) < draws_per_person:
success = False
break
return new_draw # Select recipients for the current giver
while len(new_recipients) < draws_per_person:
selected = choice(list(available_participants))
if already_drawn.count(selected) < draws_per_person:
new_recipients.append(selected)
already_drawn.append(selected)
available_participants.discard(selected)
new_draw.append([giver, email] + new_recipients)
# If the draw was successful, break out of attempts
if success:
return new_draw
print(f"Attempt {attempt + 1} failed, retrying...")
# If all attempts fail, raise an error
raise ValueError("Unable to complete a valid draw after maximum attempts.")