Opprydning og navnendringer

This commit is contained in:
Trygve 2022-05-11 15:07:33 +02:00
parent 643e3623e0
commit ac2bdab1cf
5 changed files with 133 additions and 107 deletions

10
cli.py
View File

@ -146,14 +146,14 @@ def main():
args = parser.parse_args() args = parser.parse_args()
if args.command == 'show_runners': if args.command == 'show_runners':
event = otime.event(0, 'NoName') event = otime.Event(0, 'NoName')
event.import_ttime_cnf(args.ttcnf) event.import_ttime_cnf(args.ttcnf)
event.import_ttime_db(args.ttdb) event.import_ttime_db(args.ttdb)
event.import_mtr_file(args.mtr) event.import_mtr_file(args.mtr)
event.match_runners_cards() event.match_runners_cards()
print_runners(event.runners) print_runners(event.runners)
elif args.command == 'show_runner': elif args.command == 'show_runner':
event = otime.event(0, 'NoName') event = otime.Event(0, 'NoName')
event.import_ttime_cnf(args.ttcnf) event.import_ttime_cnf(args.ttcnf)
event.import_ttime_db(args.ttdb) event.import_ttime_db(args.ttdb)
event.import_mtr_file(args.mtr) event.import_mtr_file(args.mtr)
@ -167,7 +167,7 @@ def main():
elif args.command == 'show_result': elif args.command == 'show_result':
event = otime.event(0, 'NoName') event = otime.Event(0, 'NoName')
event.import_ttime_cnf(args.ttcnf) event.import_ttime_cnf(args.ttcnf)
event.import_ttime_db(args.ttdb) event.import_ttime_db(args.ttdb)
event.import_mtr_file(args.mtr) event.import_mtr_file(args.mtr)
@ -184,12 +184,12 @@ def main():
else: else:
print_class_result(event.runners, o_class) print_class_result(event.runners, o_class)
elif args.command == 'show_classes': elif args.command == 'show_classes':
event = otime.event(0, 'NoName') event = otime.Event(0, 'NoName')
event.import_ttime_cnf(args.ttcnf) event.import_ttime_cnf(args.ttcnf)
print_o_classes(event.o_classes) print_o_classes(event.o_classes)
elif args.command == 'create_xml': elif args.command == 'create_xml':
event = otime.event(0, 'NoName') event = otime.Event(0, 'NoName')
event.import_ttime_cnf(args.ttcnf) event.import_ttime_cnf(args.ttcnf)
event.import_ttime_db(args.ttdb) event.import_ttime_db(args.ttdb)
event.import_mtr_file(args.mtr) event.import_mtr_file(args.mtr)

8
config.py Normal file
View File

@ -0,0 +1,8 @@
config = {
'event_name': 'KOK 2-dagers testing',
'port': '/dev/pts/2',
'cnf_file': 'k2ds/tt.cnf',
'db_file': 'k2ds/db.csv',
'xml_res_file': 'Resultater.xml',
'otime_file': 'test.otime'
}

2
dev.py
View File

@ -6,7 +6,7 @@ from rich.columns import Columns
from rich.table import Table from rich.table import Table
if __name__ == "__main__": if __name__ == "__main__":
event = otime.event(0, 'supercup') event = otime.Event(0, 'supercup')
event.import_ttime_cnf('k2ds/tt.cnf') event.import_ttime_cnf('k2ds/tt.cnf')
event.import_ttime_db('k2ds/db.csv') event.import_ttime_db('k2ds/db.csv')
event.import_mtr_file('k2ds/mtr.txt') event.import_mtr_file('k2ds/mtr.txt')

View File

@ -5,7 +5,6 @@ import datetime
import os import os
from time import sleep from time import sleep
import serial import serial
import binascii
import pickle import pickle
import argparse import argparse
from difflib import Differ from difflib import Differ
@ -17,6 +16,7 @@ from rich.table import Table
from rich.panel import Panel from rich.panel import Panel
from rich.console import Group from rich.console import Group
def save(obj): def save(obj):
f = open(config['otime_file'], "wb") f = open(config['otime_file'], "wb")
pickle.dump(obj,f) pickle.dump(obj,f)
@ -35,15 +35,17 @@ def start_parse():
else: else:
print('Starter fra scratch') print('Starter fra scratch')
start_event() start_event()
def start_event(): def start_event():
global event global event
event = otime.event(0, config['event_name']) event = otime.Event(0, config['event_name'])
event.import_ttime_cnf(config['cnf_file']) event.import_ttime_cnf(config['cnf_file'])
event.import_ttime_db(config['db_file']) event.import_ttime_db(config['db_file'])
save(event) save(event)
global db_file global db_file
global db_file_u global db_file_u
db_file = open(config['db_file'], 'r', encoding='latin_1').read().splitlines() db_file = open(config['db_file'], 'r', encoding='latin_1').read().splitlines()
def load_event(ot_file): def load_event(ot_file):
global event global event
f = open(ot_file, "r") f = open(ot_file, "r")
@ -64,7 +66,6 @@ def assign_card_r_to_runner(runners, card_r):
panel = Panel.fit(cont, title=str(card_r.card), border_style='white') panel = Panel.fit(cont, title=str(card_r.card), border_style='white')
print(panel) print(panel)
def runner_info(runner): def runner_info(runner):
time = str(datetime.timedelta(seconds=runner.totaltime())) time = str(datetime.timedelta(seconds=runner.totaltime()))
if runner.status() == 'Disqualified': if runner.status() == 'Disqualified':
@ -97,13 +98,13 @@ def read_db_changes():
for line in result: for line in result:
if line[:1] == '+': if line[:1] == '+':
clean = str(line).replace('+ ', '').split(';') clean = str(line).replace('+ ', '').split(';')
runner = otime.runner.from_string(clean, event.o_classes) runner = otime.Runner.from_string(clean, event.o_classes)
if runner.first != None: if runner.first != None:
added_raw.append(runner) added_raw.append(runner)
elif line[:1] == '-': elif line[:1] == '-':
clean = str(line).replace('- ', '').split(';') clean = str(line).replace('- ', '').split(';')
runner = otime.runner.from_string(clean, event.o_classes) runner = otime.Runner.from_string(clean, event.o_classes)
if runner.first != None: if runner.first != None:
removed_raw.append(runner) removed_raw.append(runner)
@ -140,6 +141,7 @@ def read_db_changes():
print(runner_info(n)) print(runner_info(n))
event.match_runners_cards() event.match_runners_cards()
event.get_xml_res().write(config['xml_res_file']) event.get_xml_res().write(config['xml_res_file'])
def read_mtr(mtr): def read_mtr(mtr):
global event global event
if mtr.in_waiting > 0: if mtr.in_waiting > 0:
@ -148,8 +150,8 @@ def read_mtr(mtr):
if size == b'\xe6': if size == b'\xe6':
meat = mtr.read(229) meat = mtr.read(229)
full = b'\xFF\xFF\xFF\xFF' + size + meat full = b'\xFF\xFF\xFF\xFF' + size + meat
card_r = otime.card_punch.from_mtr_bytes(full) card_r = otime.CardDump.from_mtr_bytes(full)
event.card_punches.append(card_r) event.card_dumps.append(card_r)
assign_card_r_to_runner(event.runners, card_r) assign_card_r_to_runner(event.runners, card_r)
elif size == b'\x37': elif size == b'\x37':
meat = mtr.read(55) meat = mtr.read(55)
@ -157,6 +159,7 @@ def read_mtr(mtr):
inspect(status) inspect(status)
print(status.year(),status.month(),status.day(),status.hours(),status.minutes()) print(status.year(),status.month(),status.day(),status.hours(),status.minutes())
event.get_xml_res().write(config['xml_res_file']) event.get_xml_res().write(config['xml_res_file'])
def main(): def main():
global event global event
global db_file global db_file

103
otime.py
View File

@ -5,15 +5,18 @@ import re
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from fpdf import FPDF from fpdf import FPDF
class event:
# The event object stores all the event data.
# A .otime file is just a pickle dump of an event object.
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.courses = []
self.o_classes = [] self.o_classes = []
self.runners = [] self.runners = []
self.card_punches= [] self.card_dumps = []
def add_course(self, *args): def add_course(self, *args):
for n in args: for n in args:
self.courses.append(n) self.courses.append(n)
@ -25,6 +28,7 @@ class event:
def add_runners(self, *args): def add_runners(self, *args):
for n in args: for n in args:
self.runners.append(n) self.runners.append(n)
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))
self.add_o_class(*classes_from_ttime_conf(ttime_file, self.courses)) self.add_o_class(*classes_from_ttime_conf(ttime_file, self.courses))
@ -35,13 +39,15 @@ class event:
for row in csvreader: for row in csvreader:
if len(row) == 0 or row[1] == '': if len(row) == 0 or row[1] == '':
continue continue
runnerarray.append(runner.from_string(row, self.o_classes)) runnerarray.append(Runner.from_string(row, self.o_classes))
self.runners = runnerarray self.runners = runnerarray
def import_mtr_file(self, mtr_file): def import_mtr_file(self, mtr_file):
self.card_punches = card_punch.list_from_mtr_f(mtr_file) self.card_dumps = card_punch.list_from_mtr_f(mtr_file)
def match_runners_cards(self): def match_runners_cards(self):
for n in self.runners: for n in self.runners:
for i in self.card_punches: for i in self.card_dumps:
if n.card == i.card: if n.card == i.card:
n.card_r = i n.card_r = i
@ -58,12 +64,12 @@ class event:
xml_child(event, 'Id', self.id) xml_child(event, 'Id', self.id)
xml_child(event, 'Name', self.name) xml_child(event, 'Name', self.name)
for i in self.o_classes: for i in self.o_classes:
#<ClassResult> # <ClassResult>
class_result = ET.SubElement(root, 'ClassResult') class_result = ET.SubElement(root, 'ClassResult')
#<Class> # <Class>
t = ET.SubElement(class_result, 'Class') t = ET.SubElement(class_result, 'Class')
xml_child(t, 'Name', i.name) xml_child(t, 'Name', i.name)
#<PersonResult> # <PersonResult>
runners_same_c = get_runners_in_class(self.runners, i) runners_same_c = get_runners_in_class(self.runners, i)
runners_ranked = rank_runners(runners_same_c, i) runners_ranked = rank_runners(runners_same_c, i)
# Put the OK runners first and Active last # Put the OK runners first and Active last
@ -72,16 +78,16 @@ class event:
for n in runners_ranked: for n in runners_ranked:
person_result = ET.SubElement(class_result, 'PersonResult') person_result = ET.SubElement(class_result, 'PersonResult')
#<Person> # <Person>
person = ET.SubElement(person_result, 'Person') person = ET.SubElement(person_result, 'Person')
xml_child(person, 'Id', n.id) xml_child(person, 'Id', n.id)
#<Name> # <Name>
name = ET.SubElement(person, 'Name') name = ET.SubElement(person, 'Name')
xml_child(name, 'Family', n.last) xml_child(name, 'Family', n.last)
xml_child(name, 'Given', n.first) xml_child(name, 'Given', n.first)
#</Name> # </Name>
#</Person> # </Person>
#<Organisation> # <Organisation>
org = ET.SubElement(person_result, 'Organisation') org = ET.SubElement(person_result, 'Organisation')
xml_child(org, 'Id', '0') xml_child(org, 'Id', '0')
xml_child(org, 'Name', n.club) xml_child(org, 'Name', n.club)
@ -89,43 +95,43 @@ class event:
# TODO: hent land fra løperobjektet # TODO: hent land fra løperobjektet
country.text = 'Norway' country.text = 'Norway'
country.set('code', 'NOR') country.set('code', 'NOR')
#</Organisation> # </Organisation>
#<Result> # <Result>
result = ET.SubElement(person_result, 'Result') result = ET.SubElement(person_result, 'Result')
if hasattr(n,'card_r') and len(n.card_r.splits) > 2: 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, 'StartTime', n.card_r.s_time.isoformat())
xml_child(result, 'FinishTime', n.card_r.f_time.isoformat()) xml_child(result, 'FinishTime', n.card_r.f_time.isoformat())
xml_child(result, 'Time', n.totaltime()) xml_child(result, 'Time', n.totaltime())
if n.status() == 'OK': if n.status() == 'OK':
#<TimeBehind> # <TimeBehind>
xml_child(result, 'TimeBehind', n.totaltime() - runners_ranked[0].totaltime()) xml_child(result, 'TimeBehind', n.totaltime() - runners_ranked[0].totaltime())
#</TimeBehind> # </TimeBehind>
xml_child(result, 'Position', n.rank(self.runners)) xml_child(result, 'Position', n.rank(self.runners))
xml_child(result, 'Status', n.status()) xml_child(result, 'Status', n.status())
#<SplitTime> # <SplitTime>
#TODO: ta utgangspunkt i løypa, ikke det brikka har stempla # TODO: ta utgangspunkt i løypa, ikke det brikka har stempla
for code,split in zip(n.card_r.controls,n.card_r.splits): for code, split in zip(n.card_r.controls, n.card_r.splits):
st = ET.SubElement(result, 'SplitTime') st = ET.SubElement(result, 'SplitTime')
xml_child(st, 'ControlCode', code) xml_child(st, 'ControlCode', code)
xml_child(st, 'Time', split) xml_child(st, 'Time', split)
if code == n.o_class.course.codes[-1]: if code == n.o_class.course.codes[-1]:
break break
#</SplitTime> # </SplitTime>
elif n.status() == 'Disqualified': elif n.status() == 'Disqualified':
xml_child(result, 'Status', n.status()) xml_child(result, 'Status', n.status())
for code in n.o_class.course.codes: for code in n.o_class.course.codes:
st = ET.SubElement(result, 'SplitTime') st = ET.SubElement(result, 'SplitTime')
xml_child(st, 'ControlCode', code) xml_child(st, 'ControlCode', code)
for control,split in zip(n.card_r.controls,n.card_r.splits): for control, split in zip(n.card_r.controls, n.card_r.splits):
if code == control: if code == control:
xml_child(st, 'Time', split) xml_child(st, 'Time', split)
else: else:
xml_child(result, 'Status', n.status()) xml_child(result, 'Status', n.status())
else: else:
xml_child(result, 'Status', n.status()) xml_child(result, 'Status', n.status())
#</Result> # </Result>
#</PersonResult> # </PersonResult>
#</Class> # </Class>
ET.indent(root, space=' ', level=0) ET.indent(root, space=' ', level=0)
return tree return tree
@ -147,7 +153,9 @@ class event:
pdf.ln(line_height) pdf.ln(line_height)
pdf.output(file_name) pdf.output(file_name)
class runner:
# The runner object stores all the data specific to a runner.
class Runner:
def __init__(self, runner_id, first, last, club, country, card, o_class, start_time): def __init__(self, runner_id, first, last, club, country, card, o_class, start_time):
self.id = runner_id self.id = runner_id
self.first = first self.first = first
@ -157,6 +165,7 @@ class runner:
self.card = card self.card = card
self.o_class = o_class self.o_class = o_class
self.start_time = start_time 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
eventorid = tt_line[0] eventorid = tt_line[0]
@ -195,13 +204,15 @@ 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, country, card, runner_o_class, start_time) return Runner(eventorid, first, last, club, country, card, runner_o_class, start_time)
def fullname(self): def fullname(self):
return '{} {}'.format(self.first, self.last) return '{} {}'.format(self.first, self.last)
def check_codes(self): def check_codes(self):
# Returns False if not ok and touple if ok # Returns False if not ok and touple if ok
return contains(self.o_class.course.codes, list(self.card_r.controls)) return contains(self.o_class.course.codes, list(self.card_r.controls))
def totaltime(self): def totaltime(self):
f_control = self.o_class.course.codes[-1] f_control = self.o_class.course.codes[-1]
try: try:
@ -217,9 +228,11 @@ class runner:
return 'OK' return 'OK'
elif self.check_codes() == False: elif self.check_codes() == False:
return 'Disqualified' return 'Disqualified'
def rank(self, allrunners): def rank(self, allrunners):
c_ranked = rank_runners(allrunners, self.o_class) c_ranked = rank_runners(allrunners, self.o_class)
return c_ranked.index(self) + 1 return c_ranked.index(self) + 1
def res_splits(self): def res_splits(self):
splits_cpy = self.card_r.splits.copy() splits_cpy = self.card_r.splits.copy()
for control in self.card_r.controls: for control in self.card_r.controls:
@ -229,7 +242,7 @@ class runner:
splits_cpy.remove(split) splits_cpy.remove(split)
return splits_cpy return splits_cpy
class card_punch: 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):
self.card = card self.card = card
self.controls = controls self.controls = controls
@ -237,6 +250,7 @@ class card_punch:
self.read_time = read_time self.read_time = read_time
self.s_time = s_time self.s_time = s_time
self.f_time = f_time self.f_time = f_time
def __repr__(self): def __repr__(self):
return f'card({self.card}) controls({self.controls}) splits({self.splits})' return f'card({self.card}) controls({self.controls}) splits({self.splits})'
@ -271,12 +285,12 @@ class card_punch:
read_time = datetime.datetime(year, month, day, hours, minutes, seconds, milliseconds) read_time = datetime.datetime(year, month, day, hours, minutes, seconds, milliseconds)
if len(controls) > 2: if len(controls) > 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:
s_time = read_time s_time = read_time
f_time = read_time f_time = read_time
return(card_punch(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(open(mtr_f))
@ -321,23 +335,27 @@ class card_punch:
else: else:
s_time = read_time s_time = read_time
f_time = read_time f_time = read_time
cards.append(card_punch(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
class course:
# Stored in Event.courses
class Course:
def __init__(self, name, codes): def __init__(self, name, codes):
self.name = name self.name = name
self.codes = codes self.codes = codes
def __repr__(self): def __repr__(self):
return f'name({self.name})' return f'name({self.name})'
class o_class: # Stored in Event.o_classes
class OClass:
def __init__(self, name, course): def __init__(self, name, course):
self.name = name self.name = name
self.course = course self.course = course
def __repr__(self): def __repr__(self):
return f'name({self.name})' return f'name({self.name})'
def courses_from_ttime_conf(ttime_file = 'sc_2021_ttime/ttime.cnf.txt'): # TODO: Take string instead of file.
def courses_from_ttime_conf(ttime_file):
courses = [] courses = []
conf = open(ttime_file, 'r', encoding='latin_1').readlines() conf = open(ttime_file, 'r', encoding='latin_1').readlines()
for line in conf: for line in conf:
@ -348,8 +366,9 @@ def courses_from_ttime_conf(ttime_file = 'sc_2021_ttime/ttime.cnf.txt'):
n = n.split(',') n = n.split(',')
loops += 1 loops += 1
n = list(map(int, n)) n = list(map(int, n))
courses.append(course('course_'+str(loops), n)) courses.append(Course('course_'+str(loops), n))
return courses return courses
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 = open(ttime_file, 'r', encoding='latin_1').readlines()
@ -360,16 +379,12 @@ 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(o_class(i,courses[loops])) o_classes.append(OClass(i,courses[loops]))
loops += 1 loops += 1
return o_classes return o_classes
# Checks if small list is in big list
def contains(small, big): def contains(small, big):
# Checks if small list is in big list
valid = True valid = True
mark = 0 mark = 0
map_bl = [] map_bl = []
@ -404,7 +419,7 @@ def rank_runners(allrunners, o_class):
runners_ranked.sort(key=lambda x: x.totaltime()) runners_ranked.sort(key=lambda x: x.totaltime())
return runners_ranked return runners_ranked
# Used to make creating xml files easier
def xml_child(parent, tag, content): def xml_child(parent, tag, content):
# Used to make creating xml files easier
e = ET.SubElement(parent, tag) e = ET.SubElement(parent, tag)
e.text = str(content) e.text = str(content)