import datetime import xml.etree.ElementTree as ET import otime def xml_child(parent, tag, content): # Used to make creating xml files easier e = ET.SubElement(parent, tag) e.text = str(content) def create_result_file(event, file_path, o_classes=[]): results = event.get_result(o_classes) root = ET.Element('ResultList') root.set('xmlns', 'http://www.orienteering.org/datastandard/3.0') root.set('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance') root.set('iofVersion', '3.0') root.set('createTime', datetime.datetime.now().isoformat(timespec='seconds')) root.set('creator', 'oTime') root.set('status', 'Complete') tree = ET.ElementTree(root) xml_event = ET.SubElement(root, 'Event') xml_child(xml_event, 'Id', event.id) xml_child(xml_event, 'Name', event.name) for i in results: # class_result = ET.SubElement(root, 'ClassResult') # t = ET.SubElement(class_result, 'Class') xml_child(t, 'Name', i.name) # for n in i.runner_results: person_result = ET.SubElement(class_result, 'PersonResult') # person = ET.SubElement(person_result, 'Person') xml_child(person, 'Id', n.id) # name = ET.SubElement(person, 'Name') xml_child(name, 'Family', n.last) xml_child(name, 'Given', n.first) # # # org = ET.SubElement(person_result, 'Organisation') xml_child(org, 'Id', n.club_id) xml_child(org, 'Name', n.club) country = ET.SubElement(org, 'Country') # TODO: hent land fra løperobjektet country.text = 'Norway' country.set('code', 'NOR') # # result = ET.SubElement(person_result, 'Result') if n.status == 'OK' or n.status == 'MissingPunch': xml_child(result, 'StartTime', n.start_time.isoformat()) xml_child(result, 'FinishTime', n.end_time.isoformat()) xml_child(result, 'Time', n.total_time) if n.status == 'OK': # xml_child(result, 'TimeBehind', n.total_time - i.runner_results[0].total_time) # xml_child(result, 'Position', n.place) xml_child(result, 'Status', n.status) # # TODO: ta utgangspunkt i løypa, ikke det brikka har stempla for code, split in zip(i.course.codes, n.splits): st = ET.SubElement(result, 'SplitTime') xml_child(st, 'ControlCode', code) xml_child(st, 'Time', split) # elif n.status == 'MissingPunch': xml_child(result, 'Status', n.status) for code, split in zip(i.course.codes, n.splits): st = ET.SubElement(result, 'SplitTime') xml_child(st, 'ControlCode', code) if split != 0: xml_child(st, 'Time', split) else: xml_child(result, 'Status', n.status) else: xml_child(result, 'Status', n.status) # # # ET.indent(root, space=' ', level=0) tree.write(file_path) def runners_from_xml_entries(xml_file): tree = ET.parse(xml_file) root = tree.getroot() url = '{http://www.orienteering.org/datastandard/3.0}' runners = [] person_entries = root.findall(f'./{url}PersonEntry') for p_entry in person_entries: rid = p_entry[1][0].text person = p_entry.find(f'./{url}Person') name = person.find(f'./{url}Name') first = name.find(f'./{url}Given').text last = name.find(f'./{url}Family').text organisation = p_entry.find(f'./{url}Organisation') if organisation is not None: club_id = organisation.find(f'./{url}Id').text club_name = organisation.find(f'./{url}Name').text club_name_short = organisation.find(f'./{url}ShortName').text country = organisation.find(f'./{url}Country').attrib['code'] else: club_id = club_name = club_name_short = country = None class_el = p_entry.find(f'./{url}Class') class_str = class_el.find(f'./{url}Name').text fee_id = int(p_entry.find(f'./{url}AssignedFee/{url}Fee/{url}Id').text) try: card = int(p_entry.find(f'./{url}ControlCard').text) except AttributeError: card = None start_time = None runners.append(otime.Runner(rid, first, last, club=club_name, club_id=club_id, country=country,card_id=card, o_class_str=class_str, start_time=start_time, fee_id=fee_id)) return runners def fees_from_xml_entries(xml_file): tree = ET.parse(xml_file) root = tree.getroot() url = '{http://www.orienteering.org/datastandard/3.0}' allfees = root.findall(f'.//{url}Fee') added_ids = [] fee_objs = [] for fee in allfees: f_id = int(fee.find(f'./{url}Id').text) if f_id not in added_ids: added_ids.append(f_id) fee_id = f_id name = fee.find(f'./{url}Name').text currency = fee.find(f'./{url}Amount').attrib['currency'] amount = int(fee.find(f'./{url}Amount').text) try: from_birth_date = fee.find(f'./{url}FromDateOfBirth').text except AttributeError: from_birth_date = None try: to_birth_date = fee.find(f'./{url}ToDateOfBirth').text except AttributeError: to_birth_date = None fee_objs.append(otime.Fee(fee_id, name, currency, amount, from_birth_date=from_birth_date, to_birth_date=to_birth_date)) return fee_objs def courses_from_xml(xml_file): tree = ET.parse(xml_file) root = tree.getroot() url = '{http://www.orienteering.org/datastandard/3.0}' allcourses = root.findall(f'.//{url}Course') courseobjs = [] for c in allcourses: name = c.find(f'./{url}Name').text controls = [] allcontrols = c.findall(f'./{url}CourseControl') for n in allcontrols: controls.append(n.find(f'./{url}Control').text) controls.remove('STA1') controls.remove('FIN1') controls = [int(l) for l in controls] courseobjs.append(otime.Course(name, controls)) return courseobjs def event_from_xml_entries(xml_file): tree = ET.parse(xml_file) root = tree.getroot() url = '{http://www.orienteering.org/datastandard/3.0}' event_el = root.find(f'./{url}Event') event_id = int(event_el.find(f'./{url}Id').text) name = event_el.find(f'./{url}Name').text organiser = event_el.find(f'./{url}Organiser/{url}Name').text start_ds = event_el.find(f'./{url}StartTime/{url}Date').text start_ts = event_el.find(f'./{url}StartTime/{url}Time').text[:-1] start_time = datetime.datetime.fromisoformat(f'{start_ds}T{start_ts}') end_ds = event_el.find(f'./{url}EndTime/{url}Date').text end_ts = event_el.find(f'./{url}EndTime/{url}Time').text[:-1] end_time = datetime.datetime.fromisoformat(f'{end_ds}T{end_ts}') person_entries = root.findall(f'./{url}PersonEntry') class_names = [] for p_entry in person_entries: class_names.append(p_entry.find(f'./{url}Class/{url}Name').text) o_classes = [otime.OClass(i, []) for i in set(class_names)] runners = runners_from_xml_entries(xml_file) fees = fees_from_xml_entries(xml_file) return otime.Event(event_id, name, organiser=organiser, runners=runners, fees=fees, start_time=start_time, end_time=end_time, o_classes=o_classes)