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
1 changed files with 202 additions and 29 deletions

231
otime.py
View File

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