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()