forked from Trygve/otime
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:
parent
63f9e40fc6
commit
e11e25ea81
231
otime.py
231
otime.py
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user