You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.6 KiB

import csv
from random import shuffle
# 1. Load participants from CSV, now including id and last_match_id
def load_participants(filename):
participants = []
with open(filename, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
participants.append({
'id': int(row['id']),
'name': row['name'],
'household': row['household'],
'email': row['email'],
'last_match_id': int(row['last_match_id']) if row['last_match_id'] else None
})
return participants
# 2. Generate potential matches, ensuring a complete set
def generate_complete_matches(participants):
max_attempts = 100 # Limit to avoid infinite loops
attempts = 0
while attempts < max_attempts:
# Shuffle both givers and receivers lists
givers = participants.copy()
receivers = participants.copy()
shuffle(givers)
shuffle(receivers)
matches = {}
used_receivers = set() # Track receivers that have already been matched
for giver in givers:
match_found = False
for receiver in receivers:
if receiver['id'] not in used_receivers and \
giver['id'] != receiver['id'] and \
giver['household'] != receiver['household'] and \
giver['last_match_id'] != receiver['id'] and \
matches.get(receiver['id']) != giver['id']:
matches[giver['id']] = receiver
used_receivers.add(receiver['id']) # Mark this receiver as used
match_found = True
break
if not match_found:
# Incomplete match, restart the process
attempts += 1
break
else:
# Complete match set found
return matches
print("Could not find a complete match set after several attempts. Restarting the entire process.")
return None
# 3. Confirm matches interactively
def confirm_matches(participants, matches):
print("Proposed Matches:")
for giver_id, receiver in matches.items():
giver = next(p for p in participants if p['id'] == giver_id)
print(f"{giver['name']} ({giver['email']}) will give a gift to {receiver['name']} ({receiver['email']})")
response = input("Approve this match? (yes/no): ").strip().lower()
if response != 'yes':
print("Match not approved. Restarting the matching process...\n")
return False # Signal to restart if any match is disapproved
return True
# 4. Final confirmation to save matches
def final_confirmation(participants, matches):
print("\nFinal Match List:")
for giver_id, receiver in matches.items():
giver = next(p for p in participants if p['id'] == giver_id)
print(f"{giver['name']} will give a gift to {receiver['name']}")
# Final save prompt
response = input("\nDo you want to save this match list? (yes to save, no to restart): ").strip().lower()
return response == 'yes'
# 5. Update last matches in the CSV file
def update_last_match_in_file(participants, matches, filename):
for giver_id, receiver in matches.items():
for participant in participants:
if participant['id'] == giver_id:
participant['last_match_id'] = receiver['id']
with open(filename, 'w', newline='') as file:
fieldnames = ['id', 'name', 'household', 'email', 'last_match_id']
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
for participant in participants:
writer.writerow({
'id': participant['id'],
'name': participant['name'],
'household': participant['household'],
'email': participant['email'],
'last_match_id': participant['last_match_id']
})
print("Matches saved to 'participants.csv'.")
# 6. Main function to run the match process
def main():
participants = load_participants('participants.csv')
while True:
matches = generate_complete_matches(participants)
if matches and confirm_matches(participants, matches):
if final_confirmation(participants, matches):
update_last_match_in_file(participants, matches, 'participants.csv')
break
else:
print("\nRestarting the matching process...\n")
else:
print("No complete match found, restarting...\n")
if __name__ == '__main__':
main()