otime/otime/iof_xml.py

176 lines
6.7 KiB
Python

import datetime
import xml.etree.ElementTree as ET
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:
# <ClassResult>
class_result = ET.SubElement(root, 'ClassResult')
# <Class>
t = ET.SubElement(class_result, 'Class')
xml_child(t, 'Name', i.name)
# <PersonResult>
for n in i.runner_results:
person_result = ET.SubElement(class_result, 'PersonResult')
# <Person>
person = ET.SubElement(person_result, 'Person')
xml_child(person, 'Id', n.id)
# <Name>
name = ET.SubElement(person, 'Name')
xml_child(name, 'Family', n.last)
xml_child(name, 'Given', n.first)
# </Name>
# </Person>
# <Organisation>
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')
# </Organisation>
# <Result>
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':
# <TimeBehind>
xml_child(result, 'TimeBehind', n.total_time - i.runner_results[0].total_time)
# </TimeBehind>
xml_child(result, 'Position', n.place)
xml_child(result, 'Status', n.status)
# <SplitTime>
# 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)
# </SplitTime>
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)
# </Result>
# </PersonResult>
# </Class>
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(Runner(rid, first, last, club=club_name, club_id=club_id,
country=country,card=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(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(Course(name, controls))
return courseobjs