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