La til import og eksport av json .otime filer

Alle import metoder og funksjoner tar nå filobjekter istedet for paths.
Runner objektet bruker nå kwargs.
This commit is contained in:
Trygve 2022-05-29 22:36:50 +02:00
parent 63f9e40fc6
commit e11e25ea81

231
otime.py
View File

@ -1,21 +1,37 @@
import copy
import datetime
import csv
import re
import json
import xml.etree.ElementTree as ET
from fpdf import FPDF
# The event object stores all the event data.
# A .otime file is just a pickle dump of an event object.
# A .otime file is more or less just a json dump of the Event object.
class Event:
def __init__(self, eventid, name, **kwargs):
self.id = eventid
self.name = name
self.courses = []
self.o_classes = []
self.runners = []
self.card_dumps = []
try:
self.courses = kwargs['courses']
except KeyError:
self.courses = []
try:
self.o_classes = kwargs['o_classes']
except KeyError:
self.o_classes = []
try:
self.runners = kwargs['runners']
except KeyError:
self.runners = []
try:
self.card_dumps = kwargs['card_dumps']
except KeyError:
self.card_dumps = []
def add_course(self, *args):
for n in args:
@ -29,12 +45,16 @@ class Event:
for n in args:
self.runners.append(n)
def import_xml_entries(self, xml_file):
self.add_runners(*runners_from_xml_entries(xml_file, self.o_classes))
def import_ttime_cnf(self, ttime_file):
self.add_course(*courses_from_ttime_conf(ttime_file))
ttime_file.seek(0)
self.add_o_class(*classes_from_ttime_conf(ttime_file, self.courses))
def import_ttime_db(self, ttime_file):
csvreader = csv.reader(open(ttime_file, 'r', encoding='latin_1'), delimiter=';',)
csvreader = csv.reader(ttime_file, delimiter=';',)
runnerarray = []
for row in csvreader:
if len(row) == 0 or row[1] == '':
@ -46,10 +66,25 @@ class Event:
self.card_dumps = CardDump.list_from_mtr_f(mtr_file)
def match_runners_cards(self):
for n in self.runners:
for i in self.card_dumps:
if n.card == i.card:
n.card_r = i
for r in self.runners:
for d in self.card_dumps:
if r.card == d.card:
r.card_r = d
def match_runners_o_classes(self):
for r in self.runners:
for c in self.o_classes:
if r.o_class_str == c.name:
r.o_class = c
def match_o_classes_courses(self):
for oc in self.o_classes:
for c in self.courses:
if oc.course_str == c.name:
oc.course = c
def match_all(self):
self.match_runners_cards()
self.match_runners_o_classes()
self.match_o_classes_courses()
def get_xml_res(self):
root = ET.Element('ResultList')
@ -135,6 +170,54 @@ class Event:
ET.indent(root, space=' ', level=0)
return tree
def create_json_file(self):
rdicts = []
for runner in self.runners:
rdicts.append(runner.asdict())
cdicts = []
for course in self.courses:
cdicts.append(course.asdict())
ocdicts = []
for o_class in self.o_classes:
ocdicts.append(o_class.asdict())
ddicts = []
for dump in self.card_dumps:
ddicts.append(dump.asdict())
json_data = {
'id': self.id,
'name': self.name,
'runners': rdicts,
'courses': cdicts,
'o_classes': ocdicts,
'card_dumps': ddicts
}
return json.dumps(json_data, sort_keys=True, indent=4)
# Get event object from .otime json file
def from_json(f):
data = json.load(f)
runners = []
for r in data['runners']:
runners.append(Runner(r['id'], r['first'], r['last'], club_id=r['club_id'], club=r['club'], country=r['country'], card=r['card'], o_class_str=r['o_class_str'], fork=r['fork'],start_time=r['start_time']))
courses = []
for c in data['courses']:
courses.append(Course(c['name'], c['codes']))
o_classes = []
for c in data['o_classes']:
o_classes.append(OClass(c['name'], c['course_str'], None))
card_dumps = []
for d in data['card_dumps']:
card_dumps.append(CardDump(d['card'], d['controls'], d['splits'], datetime.datetime.fromisoformat(d['read_time']), datetime.datetime.fromisoformat(d['s_time']), datetime.datetime.fromisoformat(d['f_time'])))
return Event(data['id'], data['name'], runners=runners, courses=courses, o_classes=o_classes, card_dumps=card_dumps)
def create_start_list_pdf(self, file_name):
pdf = FPDF()
pdf.add_page()
@ -155,16 +238,52 @@ class Event:
# The runner object stores all the data specific to a runner.
class Runner:
def __init__(self, runner_id, first, last, club, club_id, country, card, o_class, start_time):
def __init__(self, runner_id, first, last, **kwargs):
self.id = runner_id
self.first = first
self.last = last
self.club = club
self.club_id = club_id
self.country = country
self.card = card
self.o_class = o_class
self.start_time = start_time
try:
self.club = kwargs['club']
except KeyError:
self.club = None
try:
self.club_id = kwargs['club_id']
except KeyError:
self.club_id = None
try:
self.country = kwargs['country']
except KeyError:
self.country = None
try:
self.card = kwargs['card']
except KeyError:
self.card = 0
try:
self.o_class_str = kwargs['o_class_str']
except KeyError:
self.o_class = None
try:
self.o_class = kwargs['o_class']
except KeyError:
self.o_class = None
try:
self.fork = kwargs['fork']
except KeyError:
self.fork = 0
try:
self.start_time = kwargs['start_time']
except KeyError:
self.start_time = None
#self.o_class = o_class
#self.start_time = start_time
def from_string(tt_line, o_classes):
#https://web.archive.org/web/20191229124046/http://wiki.ttime.no/index.php/Developer
@ -208,7 +327,9 @@ class Runner:
start_time = options[options.index('U')+1]
except:
start_time = None
return Runner(eventorid, first, last, club, club_id, country, card, runner_o_class, start_time)
return Runner(eventorid, first, last, club=club, club_id=club_id,
country=country, card=card, o_class_str=raw_class_str,
o_class=runner_o_class, start_time=start_time)
def fullname(self):
return '{} {}'.format(self.first, self.last)
@ -244,7 +365,21 @@ class Runner:
index = self.card_r.controls.index(control)
split = self.card_r.splits[index]
splits_cpy.remove(split)
return splits_cpy
return splits_cpy # list
def asdict(self):
return {
'id': self.id,
'first': self.first,
'last': self.last,
'club_id': self.club_id,
'club': self.club_id,
'country': self.country,
'card': self.card,
'o_class_str': self.o_class_str,
'fork' : self.fork,
'start_time': self.start_time
}
class CardDump:
def __init__(self, card, controls, splits, read_time, s_time, f_time):
@ -297,7 +432,7 @@ class CardDump:
return(CardDump(card, controls, splits, read_time, s_time, f_time))
def list_from_mtr_f(mtr_f):
csvreader = csv.reader(open(mtr_f))
csvreader = csv.reader(mtr_f)
rows = []
cards = []
@ -333,7 +468,7 @@ class CardDump:
tl[1][2] = float(tl[1][2])
tl[1] = list(map(int, tl[1]))
read_time = datetime.datetime(tl[0][2], tl[0][1], tl[0][0], tl[1][0], tl[1][1], tl[1][2])
if len(controls) > 2:
if len(controls) > 2 and len(splits) > 2:
s_time = read_time - datetime.timedelta(seconds = splits[-1])
f_time = read_time - (datetime.timedelta(seconds = splits[-1]) + datetime.timedelta(seconds = splits[-2]))
else:
@ -342,26 +477,61 @@ class CardDump:
cards.append(CardDump(int(row[6]), controls, splits, read_time, s_time, f_time))
return cards
def asdict(self):
return {
'card': self.card,
'controls': self.controls,
'splits': self.splits,
'read_time': self.read_time.isoformat(),
's_time': self.s_time.isoformat(),
'f_time': self.f_time.isoformat()
}
# Stored in Event.courses
class Course:
def __init__(self, name, codes):
def __init__(self, name, codes, **kwargs):
self.name = name
self.codes = codes
try:
forked = kwargs['forked']
except KeyError:
forked = False
try:
variations = kwargs['variations']
except KeyError:
variations = None
def __repr__(self):
return f'name({self.name})'
def asdict(self):
return {
'name': self.name,
'codes': self.codes
}
# Stored in Event.o_classes
class OClass:
def __init__(self, name, course):
def __init__(self, name, course_str, course):
self.name = name
self.course_str = course_str
self.course = course
def __repr__(self):
return f'name({self.name})'
def asdict(self):
return {
'name': self.name,
'course_str': self.course_str
}
# TODO: Take string instead of file.
def courses_from_ttime_conf(ttime_file):
courses = []
conf = open(ttime_file, 'r', encoding='latin_1').readlines()
conf = ttime_file.readlines()
for line in conf:
if '-codes' in line:
code_list = re.search(r'(?<=\")(.*?)(?=\")', line).group().split(';')
@ -375,7 +545,7 @@ def courses_from_ttime_conf(ttime_file):
def classes_from_ttime_conf(ttime_file, courses):
o_classes = []
conf = open(ttime_file, 'r', encoding='latin_1').readlines()
conf = ttime_file.readlines()
for line in conf:
if '-courses' in line:
raw_courselist = re.search(r'(?<=\")(.*?)(?=\")', line).group().split(';')
@ -383,7 +553,7 @@ def classes_from_ttime_conf(ttime_file, courses):
for n in raw_courselist:
split = n.split(',')
for i in split:
o_classes.append(OClass(i,courses[loops]))
o_classes.append(OClass(i, courses[loops].name, courses[loops]))
loops += 1
return o_classes
@ -406,6 +576,7 @@ def runners_from_xml_entries(xml_file, o_classes=[]):
card = int(person_root[3].text)
except:
card = 0
runner_o_class = None
try:
xml_class_str = person_root[4][1].text
except:
@ -419,8 +590,10 @@ def runners_from_xml_entries(xml_file, o_classes=[]):
# Gjør sånn at den lager nye o klasser om den ikke finnes fra før
start_time = None
runnerarray.append(Runner(rid, first, last, club, club_id, country, card, runner_o_class, start_time))
print(rid, first, last, club_id, club, card, xml_class_str)
runnerarray.append(Runner(rid, first, last, club=club, club_id=club_id,
country=country,card=card, o_class_str=xml_class_str,
o_class=runner_o_class, start_time=start_time))
#print(rid, first, last, club_id, club, card, xml_class_str)
return runnerarray