forked from Trygve/otime
183 lines
7.5 KiB
Python
183 lines
7.5 KiB
Python
import xml.etree.ElementTree as etree
|
|
|
|
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_xml(self):
|
|
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)
|
|
event = ET.SubElement(root, 'Event')
|
|
xml_child(event, 'Id', self.id)
|
|
xml_child(event, 'Name', self.name)
|
|
for i in self.o_classes:
|
|
print('Hmmmmmm')
|
|
# <ClassResult>
|
|
class_result = ET.SubElement(root, 'ClassResult')
|
|
# <Class>
|
|
t = ET.SubElement(class_result, 'Class')
|
|
xml_child(t, 'Name', i.name)
|
|
# <PersonResult>
|
|
runners_same_c = get_runners_in_class(self.runners, i)
|
|
runners_ranked = rank_runners(runners_same_c, i)
|
|
# Put the OK runners first and Active last
|
|
runners_sorted = [i for i in runners_same_c if i not in runners_ranked]
|
|
runners_ranked.extend(runners_sorted)
|
|
|
|
for n in runners_ranked:
|
|
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')
|
|
|
|
# TODO: Dette bør skrives om til å bruke Runner metoder så mye som mulig.
|
|
if hasattr(n, 'card_r') and len(n.card_r.splits) > 2:
|
|
xml_child(result, 'StartTime', n.card_r.s_time.isoformat())
|
|
xml_child(result, 'FinishTime', n.card_r.f_time.isoformat())
|
|
xml_child(result, 'Time', n.totaltime())
|
|
if n.status() == 'OK':
|
|
# <TimeBehind>
|
|
xml_child(result, 'TimeBehind', n.totaltime() - runners_ranked[0].totaltime())
|
|
# </TimeBehind>
|
|
xml_child(result, 'Position', n.rank(self.runners))
|
|
xml_child(result, 'Status', n.status())
|
|
# <SplitTime>
|
|
# TODO: ta utgangspunkt i løypa, ikke det brikka har stempla
|
|
for code, split in zip(n.card_r.controls, n.card_r.splits):
|
|
st = ET.SubElement(result, 'SplitTime')
|
|
xml_child(st, 'ControlCode', code)
|
|
xml_child(st, 'Time', split)
|
|
if code == n.res_codes()[-1]:
|
|
break
|
|
# </SplitTime>
|
|
elif n.status() == 'Disqualified':
|
|
xml_child(result, 'Status', n.status())
|
|
for code, split in zip(n.res_codes(), n.res_splits()):
|
|
st = ET.SubElement(result, 'SplitTime')
|
|
xml_child(st, 'ControlCode', code)
|
|
if split is not None:
|
|
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)
|
|
return tree
|
|
|
|
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
|