diff --git a/band/band_contacts_to_google_contacts.py b/band/band_contacts_to_google_contacts.py index 290d254..aa5b6ad 100644 --- a/band/band_contacts_to_google_contacts.py +++ b/band/band_contacts_to_google_contacts.py @@ -2,10 +2,11 @@ import csv import argparse import datetime import re +import sys def clean_instrument_name(instrument_raw): """Cleans the instrument name based on Percussion, Winds, and Default rules.""" - # Strip numerical prefix (e.g., "12 - Percussion (electronics)" -> "Percussion (electronics)") + # Strip numerical prefix if '-' in instrument_raw: instrument = instrument_raw.split('-', 1)[-1].strip() else: @@ -13,11 +14,24 @@ def clean_instrument_name(instrument_raw): lower_inst = instrument.lower() + # Pre-catch Drum Major so they are always cleanly named + if 'drum major' in lower_inst: + return 'Drum Major' + # 1. The Percussion Rule if 'percussion' in lower_inst and '(' in instrument and ')' in instrument: match = re.search(r'\((.*?)\)', instrument) if match: - return match.group(1).strip().title() + extracted = match.group(1).strip().title() + + # Ensure "Drum" is in the name + if 'Drum' not in extracted: + if extracted.lower() in ['tenor', 'tenors']: + return 'Tenor Drums' + else: + return f"{extracted} Drum" + + return extracted # 2. The Winds/General Rule elif '(' in instrument and ')' in instrument: @@ -27,9 +41,13 @@ def clean_instrument_name(instrument_raw): return instrument def get_category(instrument): - """Categorize the instrument into Woodwinds, Brass, Percussion, or Colorguard.""" + """Categorize the instrument into groups, isolating Drum Majors first.""" inst_lower = instrument.lower() + # Catch Drum Majors first so they don't get trapped by the 'drum' keyword in Percussion + if 'drum major' in inst_lower: + return 'Drum Majors' + if any(x in inst_lower for x in ['flute', 'clarinet', 'sax', 'oboe', 'bassoon', 'piccolo']): return 'Woodwinds' if any(x in inst_lower for x in ['trumpet', 'mellophone', 'horn', 'trombone', 'baritone', 'euphonium', 'tuba', 'sousaphone']): @@ -39,7 +57,7 @@ def get_category(instrument): if 'guard' in inst_lower or 'color' in inst_lower: return 'Colorguard' - return 'Leadership' # Fallback for generic roles like Drum Major + return 'Leadership' # Fallback for other potential roles def format_phone(phone_str): """Clean and standardize the phone numbers.""" @@ -65,8 +83,6 @@ def main(): parser.add_argument("input_file", help="Path to the input CSV file") parser.add_argument("-y", "--year", type=int, default=datetime.datetime.now().year, help="Target year for labels and grade calculation (defaults to current year)") - parser.add_argument("-o", "--output", default="google_contacts_import.csv", - help="Output file name") args = parser.parse_args() target_year = args.year @@ -83,11 +99,10 @@ def main(): "Address 1 - Extended Address" ] - with open(args.input_file, mode='r', encoding='utf-8') as infile, \ - open(args.output, mode='w', encoding='utf-8', newline='') as outfile: - + with open(args.input_file, mode='r', encoding='utf-8') as infile: reader = csv.DictReader(infile) - writer = csv.DictWriter(outfile, fieldnames=google_headers) + # lineterminator='\n' ensures consistent newlines across OS when printing to stdout + writer = csv.DictWriter(sys.stdout, fieldnames=google_headers, lineterminator='\n') writer.writeheader() for row in reader: @@ -117,9 +132,9 @@ def main(): else: notes = grade_raw - # Determine Label (Appended with Marching Band) + # Determine Label category = get_category(instrument) - label = f"{target_year} {category} ::: Marching Band {target_year} ::: * myContacts" + label = f"{target_year} {category} ::: Marching Band ::: * myContacts" # Build the output row out_row = {key: "" for key in google_headers} @@ -142,7 +157,5 @@ def main(): writer.writerow(out_row) - print(f"Success! Formatted contacts saved to {args.output}") - if __name__ == '__main__': main()