Starta på en felles resultat generator
This commit is contained in:
		
							parent
							
								
									8516bfd313
								
							
						
					
					
						commit
						aa61d7a415
					
				
							
								
								
									
										
											BIN
										
									
								
								otime/data/fonts/LiberationSans-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								otime/data/fonts/LiberationSans-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								otime/data/fonts/LiberationSans-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								otime/data/fonts/LiberationSans-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										622
									
								
								otime/otime.py
									
									
									
									
									
								
							
							
						
						
									
										622
									
								
								otime/otime.py
									
									
									
									
									
								
							| @ -1,9 +1,313 @@ | ||||
| import copy | ||||
| import datetime | ||||
| import re | ||||
| import xml.etree.ElementTree as etree | ||||
| import pdf | ||||
| 
 | ||||
| class Runner: | ||||
|     def __init__(self, runner_id: int, first: str, last: str, club=None, club_id=None, | ||||
|                  country=None, card_id=None, o_class_str=None, o_class=None, | ||||
|                  fork=0, start_time=None, fee_id=None, fee=None): | ||||
|         self.id = runner_id | ||||
|         self.first = first | ||||
|         self.last = last | ||||
|         self.club = club | ||||
|         self.club_id = club_id | ||||
|         self.country = country | ||||
|         self.card_id = card_id | ||||
|         self.o_class = o_class | ||||
|         self.fork = fork | ||||
|         self.start_time = start_time | ||||
|         self.fee_id = fee_id | ||||
|      | ||||
|     def __repr__(self): | ||||
|         return(f'name({self.fullname()})') | ||||
|          | ||||
|     def from_ttime_string(ttime_db_line): | ||||
|         # Reads 1 line of a ttime db | ||||
|         #https://web.archive.org/web/20191229124046/http://wiki.ttime.no/index.php/Developer | ||||
|         runner_data = ttime_db_line.split(';') | ||||
|         eventorid = runner_data[0] | ||||
|         country = '' | ||||
|         name = runner_data[2].split(',') | ||||
|         try: | ||||
|             first = name[1].strip() | ||||
|         except: | ||||
|             first = '' | ||||
|         last = name[0] | ||||
|         try: | ||||
|             club = runner_data[4] | ||||
|         except: | ||||
|             club = '' | ||||
|         try: | ||||
|             card = int(runner_data[6]) | ||||
|         except: | ||||
|             card = 0 | ||||
|         try: | ||||
|             o_class = runner_data[3] | ||||
|         except: | ||||
|             o_class = '' | ||||
|         options = runner_data[5].split(',') | ||||
|         try: | ||||
|             club_id = options[options.index('A')+3] | ||||
|         except: | ||||
|             club_id = 0 | ||||
|         try: | ||||
|             start_time = options[options.index('U')+1] | ||||
|         except: | ||||
|             start_time = None | ||||
|         return Runner(eventorid, first, last, club=club, club_id=club_id, | ||||
|                         country=country, card_id=card, o_class=o_class, start_time=start_time) | ||||
| 
 | ||||
|     def fullname(self): | ||||
|         return '{} {}'.format(self.first, self.last) | ||||
| 
 | ||||
|     def check_codes(self): | ||||
|         return contains(self.res_codes(), self.card_r.controls) | ||||
| 
 | ||||
|     def totaltime(self): | ||||
|         f_control = self.res_codes()[-1] | ||||
|         try: | ||||
|             index = self.card_r.controls.index(f_control) | ||||
|             return self.card_r.splits[index] | ||||
|         except: | ||||
|             return 0 | ||||
| 
 | ||||
|     def status(self): | ||||
|         if hasattr(self, 'card_r') is False or self.o_class is None: | ||||
|             return 'Active' | ||||
|         elif self.check_codes(): | ||||
|             return 'OK' | ||||
|         elif self.check_codes() is False: | ||||
|             return 'Disqualified' | ||||
| 
 | ||||
|     # TODO: må forbedres | ||||
|     def rank(self, allrunners): | ||||
|         c_ranked = rank_runners(allrunners, self.o_class) | ||||
|         try: | ||||
|             return c_ranked.index(self) + 1 | ||||
|         except ValueError: | ||||
|             return None | ||||
| 
 | ||||
|     def get_codes(self): | ||||
|         if self.o_class.course.forked is False: | ||||
|             return self.o_class.course.codes | ||||
|         else: | ||||
|             return self.o_class.course.variations[self.fork] | ||||
| 
 | ||||
|     # TODO: Mange bugs med løyper som har samme post flere ganger | ||||
|     # Used for making result files and tables | ||||
|     def get_splits(self): | ||||
|         if self.status() == 'OK': | ||||
|             splits_cpy = self.card_r.splits.copy() | ||||
|             for control in self.card_r.controls: | ||||
|                 if control not in self.res_codes(): | ||||
|                     index = self.card_r.controls.index(control) | ||||
|                     split = self.card_r.splits[index] | ||||
|                     splits_cpy.remove(split) | ||||
|             return splits_cpy | ||||
| 
 | ||||
|         else: | ||||
|             splits_cpy = self.card_r.splits.copy() | ||||
|             for control in self.card_r.controls: | ||||
|                 if control not in self.res_codes(): | ||||
|                     index = self.card_r.controls.index(control) | ||||
|                     split = self.card_r.splits[index] | ||||
|                     try: | ||||
|                         splits_cpy.remove(split) | ||||
|                     except Exception: | ||||
|                         print('aaaaaa') | ||||
| 
 | ||||
| 
 | ||||
|             punches = self.card_r.controls.copy() | ||||
|             splits = [] | ||||
|             for code in self.res_codes(): | ||||
|                 if punches[0] == code: | ||||
|                     splits.append(splits_cpy[0]) | ||||
|                     splits_cpy.pop(0) | ||||
|                     punches.pop(0) | ||||
|                     continue | ||||
|                 else: | ||||
|                     splits.append(None) | ||||
|             return splits | ||||
| 
 | ||||
|     def asdict(self): | ||||
|         return { | ||||
|             'id': self.id, | ||||
|             'first': self.first, | ||||
|             'last': self.last, | ||||
|             'club_id': self.club_id, | ||||
|             'club': self.club, | ||||
|             'country': self.country, | ||||
|             'card': self.card, | ||||
|             'o_class_str': self.o_class_str, | ||||
|             'fork' : self.fork, | ||||
|             'start_time': self.start_time, | ||||
|             'fee_id': self.fee_id | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class CardDump: | ||||
|     def __init__(self, card, controls, splits, read_time, s_time, f_time): | ||||
|         self.card = card | ||||
|         self.controls = controls | ||||
|         self.splits = splits | ||||
|         self.read_time = read_time | ||||
|         self.s_time = s_time | ||||
|         self.f_time = f_time | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'card({self.card}) controls({self.controls}) splits({self.splits})' | ||||
| 
 | ||||
|     def from_mtr_bytes(datamsg): | ||||
|         card = int.from_bytes(datamsg[20:23], 'little') | ||||
| 
 | ||||
|         #Extract codes and splits: | ||||
|         controls = [] | ||||
|         splits = [] | ||||
|         splits_offset = 26 | ||||
|         code_numbytes = 1 | ||||
|         time_numbytes = 2 | ||||
|         split_numbytes = code_numbytes + time_numbytes | ||||
|         for split_index in range(50): | ||||
|             code_offset = splits_offset + split_index * split_numbytes | ||||
|             time_offset = code_offset + code_numbytes | ||||
|             code = int.from_bytes(datamsg[code_offset:code_offset+code_numbytes], 'little') | ||||
|             time = int.from_bytes(datamsg[time_offset:time_offset+time_numbytes], 'little') | ||||
|             if code != 0: | ||||
|                 controls.append(code) | ||||
|                 splits.append(time) | ||||
| 
 | ||||
|         # Extract start time: | ||||
|         year = int.from_bytes(datamsg[8:9], 'little') | ||||
|         month = int.from_bytes(datamsg[9:10], 'little') | ||||
|         day = int.from_bytes(datamsg[10:11], 'little') | ||||
|         hours = int.from_bytes(datamsg[11:12], 'little') | ||||
|         minutes = int.from_bytes(datamsg[12:13], 'little') | ||||
|         seconds = int.from_bytes(datamsg[13:14], 'little') | ||||
|         milliseconds = int.from_bytes(datamsg[14:16], 'little') | ||||
| 
 | ||||
|         read_time = datetime.datetime(year, month, day, hours, minutes, seconds, milliseconds) | ||||
|         if len(controls) > 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: | ||||
|             s_time = read_time | ||||
|             f_time = read_time | ||||
| 
 | ||||
|         return(CardDump(card, controls, splits, read_time, s_time, f_time)) | ||||
| 
 | ||||
|     def list_from_mtr_f(mtr_file): | ||||
|         with open(mtr_file) as f: | ||||
|             data = [i.replace('"','').split(',') for i in f.readlines()] | ||||
|         cards = [] | ||||
|         # hver rad er brikkenummer med tilhørende info | ||||
|         for row in data: | ||||
|             controls = [] | ||||
|             splits = [] | ||||
|             # postkodene kommer på oddetall fra og med den 11. De blir hevet inn i controls | ||||
|             for item in row[11::2]: | ||||
|                 if item == '250': | ||||
|                     controls.append(int(item)) | ||||
|                     break | ||||
|                 elif item == '000': | ||||
|                     break | ||||
|                 else: | ||||
|                     controls.append(int(item)) | ||||
|             # strekktidene kommer på partall fra og med den 12. De blir hevet i splits. | ||||
|             for item in row[12::2]: | ||||
|                 if item == '00000': | ||||
|                     break | ||||
|                 else: | ||||
|                     splits.append(int(item)) | ||||
|             # looper gjonnom løperobjektene og legger til poster og strekktider + start og sluttid | ||||
|             # usikker på om dette er riktig klokeslett | ||||
|             tl = row[5].split(' ') | ||||
|             tl[0] = tl[0].split('.') | ||||
|             tl[0][2] = '20' + tl[0][2] | ||||
|             tl[0] = list(map(int, tl[0])) | ||||
|             tl[1] = tl[1].split(':') | ||||
|             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 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: | ||||
|                 s_time = read_time | ||||
|                 f_time = read_time | ||||
|             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, forked=False, variations=None): | ||||
|         self.name = name | ||||
|         self.codes = codes | ||||
|         self.forked = forked | ||||
|         # Variations is a list | ||||
|         self.variations = variations | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'name({self.name})' | ||||
| 
 | ||||
|     def asdict(self): | ||||
|         return { | ||||
|             'name': self.name, | ||||
|             'codes': self.codes, | ||||
|             'forked': self.forked, | ||||
|             'variations': self.variations | ||||
|         } | ||||
| 
 | ||||
| # Stored in Event.o_classes | ||||
| class OClass: | ||||
|     def __init__(self, name, course): | ||||
|         self.name = name | ||||
|         self.course = course | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'name({self.name})' | ||||
| 
 | ||||
| class RunnerResult: | ||||
|     def __init__(self, runner_id: int, first: str, last: str, status: str, place: int, total_time: int, split_times: list[int], end_time, | ||||
|                  club=None, club_id=None, country=None, card_id=None, o_class=None, fork=0, start_time=None, fee_id=None): | ||||
|         self.id = runner_id | ||||
|         self.first = first | ||||
|         self.last = last | ||||
|         self.club = club | ||||
|         self.club_id = club_id | ||||
|         self.country = country | ||||
|         self.card_id = card_id | ||||
|         self.o_class = o_class | ||||
|         self.fork = fork | ||||
|         self.start_time = start_time | ||||
|         self.fee_id = fee_id | ||||
| 
 | ||||
|         self.status = status | ||||
|         self.place = place | ||||
|         self.total_time = total_time | ||||
|         self.split_times = split_times | ||||
|         self.end_time = end_time | ||||
| 
 | ||||
| class ClassResult: | ||||
|     def __init__(self, name: str, course: Course, runner_results: list[RunnerResult]): | ||||
|         self.name | ||||
|         self.course | ||||
|         self.runner_results | ||||
| 
 | ||||
| class Event: | ||||
|     def __init__(self, eventid, name, git astart_time=None, end_time=None, | ||||
|     def __init__(self, eventid, name, start_time=None, end_time=None, | ||||
|                  organiser=None, courses=[], o_classes=[], runners=[], | ||||
|                  card_dumps=[], fees=[]): | ||||
|         self.id = eventid | ||||
| @ -32,6 +336,9 @@ class Event: | ||||
|         for n in args: | ||||
|             self.runners.append(n) | ||||
|              | ||||
|     def get_runners_in_o_class(self, o_class: str) -> list[Runner]: | ||||
|         return [i for i in self.runners if i.o_class == o_class] | ||||
| 
 | ||||
|     def add_fees(self, *args): | ||||
|         for n in args: | ||||
|             self.fees.append(n) | ||||
| @ -40,11 +347,16 @@ class Event: | ||||
|         pass | ||||
| 
 | ||||
|     def get_o_class(self, name): | ||||
|         pass | ||||
|         return next((copy.copy(i) for i in self.o_classes if i.name == name), None) | ||||
| 
 | ||||
|     def get_runner(self, name): | ||||
|         pass | ||||
|      | ||||
|     def get_result(self, o_classes: list[str] = []) -> list[ClassResult]: | ||||
|         if not o_classes: | ||||
|             o_classes = [i.name for i in self.o_classes] | ||||
|         return [produce_class_result(self, i) for i in o_classes] | ||||
| 
 | ||||
|     def read_xml_entries(self, xml_file): | ||||
|         self.add_runners(*runners_from_xml_entries(xml_file)) | ||||
|         self.add_fees(*fees_from_xml_entries(xml_file)) | ||||
| @ -89,7 +401,13 @@ class Event: | ||||
|     def read_mtr_file(self, mtr_file): | ||||
|         self.card_dumps = CardDump.list_from_mtr_f(mtr_file) | ||||
| 
 | ||||
|     def get_result_xml(self): | ||||
|     def create_start_list_pdf(self, file_path): | ||||
|         pdf.create_start_list(copy.deepcopy(self), file_path) | ||||
| 
 | ||||
|     def create_result_pdf(self, file_path): | ||||
|         pdf.create_result_list(copy.deepcopy(self), file_path) | ||||
| 
 | ||||
|     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') | ||||
| @ -176,286 +494,6 @@ class Event: | ||||
|         return tree | ||||
| 
 | ||||
| # The runner object stores all the data specific to a runner. | ||||
| class Runner: | ||||
|     def __init__(self, runner_id: int, first: str, last: str, club=None, club_id=None, | ||||
|                  country=None, card_id=None, o_class_str=None, o_class=None, | ||||
|                  fork=0, start_time=None, fee_id=None, fee=None): | ||||
|         self.id = runner_id | ||||
|         self.first = first | ||||
|         self.last = last | ||||
|         self.club = club | ||||
|         self.club_id = club_id | ||||
|         self.country = country | ||||
|         self.card_id = card_id | ||||
|         self.o_class = o_class | ||||
|         self.fork = fork | ||||
|         self.start_time = start_time | ||||
|         self.fee_id = fee_id | ||||
|      | ||||
|     def __repr__(self): | ||||
|         return(f'name({self.fullname()})') | ||||
|          | ||||
|     def from_ttime_string(ttime_db_line): | ||||
|         # Reads 1 line of a ttime db | ||||
|         #https://web.archive.org/web/20191229124046/http://wiki.ttime.no/index.php/Developer | ||||
|         runner_data = ttime_db_line.split(';') | ||||
|         eventorid = runner_data[0] | ||||
|         country = '' | ||||
|         name = runner_data[2].split(',') | ||||
|         try: | ||||
|             first = name[1].strip() | ||||
|         except: | ||||
|             first = '' | ||||
|         last = name[0] | ||||
|         try: | ||||
|             club = runner_data[4] | ||||
|         except: | ||||
|             club = '' | ||||
|         try: | ||||
|             card = int(runner_data[6]) | ||||
|         except: | ||||
|             card = 0 | ||||
|         try: | ||||
|             o_class = runner_data[3] | ||||
|         except: | ||||
|             o_class = '' | ||||
|         options = runner_data[5].split(',') | ||||
|         try: | ||||
|             club_id = options[options.index('A')+3] | ||||
|         except: | ||||
|             club_id = 0 | ||||
|         try: | ||||
|             start_time = options[options.index('U')+1] | ||||
|         except: | ||||
|             start_time = None | ||||
|         return Runner(eventorid, first, last, club=club, club_id=club_id, | ||||
|                         country=country, card_id=card, o_class=o_class, start_time=start_time) | ||||
| 
 | ||||
|     def fullname(self): | ||||
|         return '{} {}'.format(self.first, self.last) | ||||
| 
 | ||||
|     def check_codes(self): | ||||
|         return contains(self.res_codes(), self.card_r.controls) | ||||
| 
 | ||||
|     def totaltime(self): | ||||
|         f_control = self.res_codes()[-1] | ||||
|         try: | ||||
|             index = self.card_r.controls.index(f_control) | ||||
|             return self.card_r.splits[index] | ||||
|         except: | ||||
|             return 0 | ||||
| 
 | ||||
|     def status(self): | ||||
|         if hasattr(self, 'card_r') is False or self.o_class is None: | ||||
|             return 'Active' | ||||
|         elif self.check_codes(): | ||||
|             return 'OK' | ||||
|         elif self.check_codes() is False: | ||||
|             return 'Disqualified' | ||||
| 
 | ||||
|     # TODO: må forbedres | ||||
|     def rank(self, allrunners): | ||||
|         c_ranked = rank_runners(allrunners, self.o_class) | ||||
|         try: | ||||
|             return c_ranked.index(self) + 1 | ||||
|         except ValueError: | ||||
|             return None | ||||
| 
 | ||||
|     def res_codes(self): | ||||
|         if self.o_class.course.forked is False: | ||||
|             return self.o_class.course.codes | ||||
|         else: | ||||
|             return self.o_class.course.variations[self.fork] | ||||
| 
 | ||||
|     # TODO: Mange bugs med løyper som har samme post flere ganger | ||||
|     # Used for making result files and tables | ||||
|     def res_splits(self): | ||||
|         if self.status() == 'OK': | ||||
|             splits_cpy = self.card_r.splits.copy() | ||||
|             for control in self.card_r.controls: | ||||
|                 if control not in self.res_codes(): | ||||
|                     index = self.card_r.controls.index(control) | ||||
|                     split = self.card_r.splits[index] | ||||
|                     splits_cpy.remove(split) | ||||
|             return splits_cpy | ||||
| 
 | ||||
|         else: | ||||
|             splits_cpy = self.card_r.splits.copy() | ||||
|             for control in self.card_r.controls: | ||||
|                 if control not in self.res_codes(): | ||||
|                     index = self.card_r.controls.index(control) | ||||
|                     split = self.card_r.splits[index] | ||||
|                     try: | ||||
|                         splits_cpy.remove(split) | ||||
|                     except Exception: | ||||
|                         print('aaaaaa') | ||||
| 
 | ||||
| 
 | ||||
|             punches = self.card_r.controls.copy() | ||||
|             splits = [] | ||||
|             for code in self.res_codes(): | ||||
|                 if punches[0] == code: | ||||
|                     splits.append(splits_cpy[0]) | ||||
|                     splits_cpy.pop(0) | ||||
|                     punches.pop(0) | ||||
|                     continue | ||||
|                 else: | ||||
|                     splits.append(None) | ||||
|             return splits | ||||
| 
 | ||||
|     def asdict(self): | ||||
|         return { | ||||
|             'id': self.id, | ||||
|             'first': self.first, | ||||
|             'last': self.last, | ||||
|             'club_id': self.club_id, | ||||
|             'club': self.club, | ||||
|             'country': self.country, | ||||
|             'card': self.card, | ||||
|             'o_class_str': self.o_class_str, | ||||
|             'fork' : self.fork, | ||||
|             'start_time': self.start_time, | ||||
|             'fee_id': self.fee_id | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| class CardDump: | ||||
|     def __init__(self, card, controls, splits, read_time, s_time, f_time): | ||||
|         self.card = card | ||||
|         self.controls = controls | ||||
|         self.splits = splits | ||||
|         self.read_time = read_time | ||||
|         self.s_time = s_time | ||||
|         self.f_time = f_time | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'card({self.card}) controls({self.controls}) splits({self.splits})' | ||||
| 
 | ||||
|     def from_mtr_bytes(datamsg): | ||||
|         card = int.from_bytes(datamsg[20:23], 'little') | ||||
| 
 | ||||
|         #Extract codes and splits: | ||||
|         controls = [] | ||||
|         splits = [] | ||||
|         splits_offset = 26 | ||||
|         code_numbytes = 1 | ||||
|         time_numbytes = 2 | ||||
|         split_numbytes = code_numbytes + time_numbytes | ||||
|         for split_index in range(50): | ||||
|             code_offset = splits_offset + split_index * split_numbytes | ||||
|             time_offset = code_offset + code_numbytes | ||||
|             code = int.from_bytes(datamsg[code_offset:code_offset+code_numbytes], 'little') | ||||
|             time = int.from_bytes(datamsg[time_offset:time_offset+time_numbytes], 'little') | ||||
|             if code != 0: | ||||
|                 controls.append(code) | ||||
|                 splits.append(time) | ||||
| 
 | ||||
|         # Extract start time: | ||||
|         year = int.from_bytes(datamsg[8:9], 'little') | ||||
|         month = int.from_bytes(datamsg[9:10], 'little') | ||||
|         day = int.from_bytes(datamsg[10:11], 'little') | ||||
|         hours = int.from_bytes(datamsg[11:12], 'little') | ||||
|         minutes = int.from_bytes(datamsg[12:13], 'little') | ||||
|         seconds = int.from_bytes(datamsg[13:14], 'little') | ||||
|         milliseconds = int.from_bytes(datamsg[14:16], 'little') | ||||
| 
 | ||||
|         read_time = datetime.datetime(year, month, day, hours, minutes, seconds, milliseconds) | ||||
|         if len(controls) > 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: | ||||
|             s_time = read_time | ||||
|             f_time = read_time | ||||
| 
 | ||||
|         return(CardDump(card, controls, splits, read_time, s_time, f_time)) | ||||
| 
 | ||||
|     def list_from_mtr_f(mtr_file): | ||||
|         with open(mtr_file) as f: | ||||
|             data = [i.replace('"','').split(',') for i in f.readlines()] | ||||
|         print(data) | ||||
|         cards = [] | ||||
|         # hver rad er brikkenummer med tilhørende info | ||||
|         for row in data: | ||||
|             controls = [] | ||||
|             splits = [] | ||||
|             # postkodene kommer på oddetall fra og med den 11. De blir hevet inn i controls | ||||
|             for item in row[11::2]: | ||||
|                 if item == '250': | ||||
|                     controls.append(int(item)) | ||||
|                     break | ||||
|                 elif item == '000': | ||||
|                     break | ||||
|                 else: | ||||
|                     controls.append(int(item)) | ||||
|             # strekktidene kommer på partall fra og med den 12. De blir hevet i splits. | ||||
|             for item in row[12::2]: | ||||
|                 if item == '00000': | ||||
|                     break | ||||
|                 else: | ||||
|                     splits.append(int(item)) | ||||
|             # looper gjonnom løperobjektene og legger til poster og strekktider + start og sluttid | ||||
|             # usikker på om dette er riktig klokeslett | ||||
|             tl = row[5].split(' ') | ||||
|             tl[0] = tl[0].split('.') | ||||
|             tl[0][2] = '20' + tl[0][2] | ||||
|             tl[0] = list(map(int, tl[0])) | ||||
|             tl[1] = tl[1].split(':') | ||||
|             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 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: | ||||
|                 s_time = read_time | ||||
|                 f_time = read_time | ||||
|             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, forked=False, variations=None): | ||||
|         self.name = name | ||||
|         self.codes = codes | ||||
|         self.forked = forked | ||||
|         # Variations is a list | ||||
|         self.variations = variations | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'name({self.name})' | ||||
| 
 | ||||
|     def asdict(self): | ||||
|         return { | ||||
|             'name': self.name, | ||||
|             'codes': self.codes, | ||||
|             'forked': self.forked, | ||||
|             'variations': self.variations | ||||
|         } | ||||
| 
 | ||||
| # Stored in Event.o_classes | ||||
| class OClass: | ||||
|     def __init__(self, name, course_str, course): | ||||
|         self.name = name | ||||
|         self.course = course | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return f'name({self.name})' | ||||
| 
 | ||||
|     def asdict(self): | ||||
|         return { | ||||
|             'name': self.name, | ||||
|             'course_str': self.course_str | ||||
|         } | ||||
| 
 | ||||
| class Fee: | ||||
|     def __init__(self, fee_id, name, currency, amount, from_birth_date=None, | ||||
| @ -477,6 +515,12 @@ class Fee: | ||||
|             'to_birth_date': self.to_birth_date | ||||
|         } | ||||
| 
 | ||||
| def produce_class_result(event, o_class_name) -> ClassResult: | ||||
|     o_class = event.get_o_class(o_class_name) | ||||
|     runners = event.get_runners_in_o_class(o_class_name) | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
| # TODO: Take string instead of file. | ||||
| def courses_from_ttime_conf(ttime_file): | ||||
|     with open(ttime_file, 'r') as f: | ||||
| @ -504,7 +548,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].name, courses[loops])) | ||||
|                     o_classes.append(OClass(i, courses[loops].name)) | ||||
|                 loops += 1 | ||||
|     return o_classes | ||||
| 
 | ||||
| @ -616,16 +660,6 @@ def contains(small, big): | ||||
|     else: | ||||
|         return False | ||||
| 
 | ||||
| 
 | ||||
| def get_runners_in_class(runners, o_class): | ||||
|     # Filters out runner objects that dont have the correct o_class | ||||
|     list_filtrd = [] | ||||
|     for i in runners: | ||||
|         if i.o_class == o_class: | ||||
|             list_filtrd.append(i) | ||||
|     return list_filtrd | ||||
| 
 | ||||
| 
 | ||||
| def rank_runners(allrunners, o_class): | ||||
|     runners = get_runners_in_class(allrunners, o_class) | ||||
|     runners_ranked = [] | ||||
|  | ||||
							
								
								
									
										315
									
								
								otime/pdf.py
									
									
									
									
									
								
							
							
						
						
									
										315
									
								
								otime/pdf.py
									
									
									
									
									
								
							| @ -1,186 +1,187 @@ | ||||
| # Denne koden funker ikke! Den er bare revet ut av prsojektet og skal fikses senere | ||||
| from fpdf import FPDF | ||||
| def create_start_list_pdf(self, file_name): | ||||
| 
 | ||||
| def create_start_list(event, file_path): | ||||
|         pdf = FPDF() | ||||
| 
 | ||||
|         pdf.add_page() | ||||
|         pdf.add_font("LiberationSans", fname="data/fonts/LiberationSans-Regular.ttf") | ||||
|         pdf.add_font("LiberationSans", fname="../../otime/data/fonts/LiberationSans-Regular.ttf") | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         line_height = pdf.font_size * 2 | ||||
|         line_height = pdf.font_size * 1.5 | ||||
|         col_width = pdf.epw / 4  # distribute content evenly | ||||
|         for runner in self.runners: | ||||
|         for runner in event.runners: | ||||
|             pdf.multi_cell(col_width, line_height, runner.fullname(), border=1, ln=3, max_line_height=pdf.font_size, align='L') | ||||
|             pdf.multi_cell(col_width, line_height, runner.o_class_str, border=1, ln=3, max_line_height=pdf.font_size) | ||||
|             pdf.multi_cell(col_width, line_height, str(runner.card), border=1, ln=3, max_line_height=pdf.font_size) | ||||
|             pdf.multi_cell(col_width, line_height, runner.o_class, border=1, ln=3, max_line_height=pdf.font_size) | ||||
|             pdf.multi_cell(col_width, line_height, str(runner.card_id), border=1, ln=3, max_line_height=pdf.font_size) | ||||
|             if runner.start_time is not None: | ||||
|                 pdf.multi_cell(col_width, line_height, str(runner.start_time), border=1, ln=3, max_line_height=pdf.font_size) | ||||
|             else: | ||||
|                 pdf.multi_cell(col_width, line_height, '', border=1, ln=3, max_line_height=pdf.font_size) | ||||
|             pdf.ln(line_height) | ||||
|         pdf.output(file_name) | ||||
|         pdf.output(file_path) | ||||
| 
 | ||||
|     def create_all_invoices(self, filename_prefix): | ||||
|         clubs = [x.club for x in self.runners if x.club != self.runners[self.runners.index(x)-1].club and x.club is not None] | ||||
|         for club in clubs: | ||||
|             self.create_club_invoice(club, filename_prefix + club + '.pdf') | ||||
| def create_all_invoices(self, filename_prefix): | ||||
|     clubs = [x.club for x in self.runners if x.club != self.runners[self.runners.index(x)-1].club and x.club is not None] | ||||
|     for club in clubs: | ||||
|         self.create_club_invoice(club, filename_prefix + club + '.pdf') | ||||
| 
 | ||||
|     def create_club_invoice(self, club, file_name): | ||||
|         # Get only runners in specified club | ||||
|         runners_ic = [x for x in self.runners if x.club == club] | ||||
|         payments = [x.fee.amount for x in runners_ic] | ||||
|         subtotal = sum(payments) | ||||
| def create_club_invoice(self, club, file_name): | ||||
|     # Get only runners in specified club | ||||
|     runners_ic = [x for x in self.runners if x.club == club] | ||||
|     payments = [x.fee.amount for x in runners_ic] | ||||
|     subtotal = sum(payments) | ||||
| 
 | ||||
|         # Dict of runners in each fee | ||||
|         fee_dict = {} | ||||
|         for fee in self.fees: | ||||
|             fee_dict.update({fee.name: [x for x in runners_ic if x.fee.name == fee.name]}) | ||||
|             if len(fee_dict[fee.name]) == 0: | ||||
|                 fee_dict.pop(fee.name) | ||||
|     # Dict of runners in each fee | ||||
|     fee_dict = {} | ||||
|     for fee in self.fees: | ||||
|         fee_dict.update({fee.name: [x for x in runners_ic if x.fee.name == fee.name]}) | ||||
|         if len(fee_dict[fee.name]) == 0: | ||||
|             fee_dict.pop(fee.name) | ||||
| 
 | ||||
|         pdf = PDF() | ||||
|     pdf = PDF() | ||||
| 
 | ||||
|         pdf.set_title(f'Faktura {self.name} {club}') | ||||
|         pdf.set_producer('oTime 0.0.1') | ||||
|         pdf.set_creator('oTime 0.0.1') | ||||
|         pdf.set_creation_date() | ||||
|     pdf.set_title(f'Faktura {self.name} {club}') | ||||
|     pdf.set_producer('oTime 0.0.1') | ||||
|     pdf.set_creator('oTime 0.0.1') | ||||
|     pdf.set_creation_date() | ||||
| 
 | ||||
|         pdf.add_page() | ||||
|         pdf.add_font("LiberationSans", fname="data/fonts/LiberationSans-Regular.ttf") | ||||
|         pdf.add_font("LiberationSans-Bold", fname="data/fonts/LiberationSans-Bold.ttf") | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         line_height = pdf.font_size * 1.5 | ||||
|     pdf.add_page() | ||||
|     pdf.add_font("LiberationSans", fname="data/fonts/LiberationSans-Regular.ttf") | ||||
|     pdf.add_font("LiberationSans-Bold", fname="data/fonts/LiberationSans-Bold.ttf") | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     line_height = pdf.font_size * 1.5 | ||||
| 
 | ||||
|         # Topp venstre: | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.multi_cell(pdf.epw / 2, line_height, self.name, align='L') | ||||
|         pdf.ln(0.2) | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         pdf.multi_cell(pdf.epw / 2, line_height, self.organiser, align='L') | ||||
|         pdf.ln(14) | ||||
|         pdf.multi_cell(pdf.epw / 2, line_height, club, align='L') | ||||
|     # Topp venstre: | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.multi_cell(pdf.epw / 2, line_height, self.name, align='L') | ||||
|     pdf.ln(0.2) | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     pdf.multi_cell(pdf.epw / 2, line_height, self.organiser, align='L') | ||||
|     pdf.ln(14) | ||||
|     pdf.multi_cell(pdf.epw / 2, line_height, club, align='L') | ||||
|     pdf.ln() | ||||
| 
 | ||||
|     # Topp høyre: | ||||
|     pdf.set_xy(-pdf.epw / 3, 10) | ||||
|     pdf.set_font("LiberationSans-Bold", size=20) | ||||
|     pdf.multi_cell(pdf.epw, line_height, 'Faktura', align='L') | ||||
|     pdf.set_xy(-pdf.epw / 3, 20) | ||||
| 
 | ||||
|     # Dato | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.multi_cell(0, line_height, 'Dato:', align='L') | ||||
|     pdf.set_xy(-pdf.epw / 3, 20) | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     pdf.multi_cell(0, line_height, datetime.date.today().strftime('%d.%m.%Y'), align='R') | ||||
| 
 | ||||
|     # Nummer | ||||
|     pdf.set_xy(-pdf.epw / 3, 20 + line_height) | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.multi_cell(0, line_height, 'Nummer:', align='L') | ||||
|     pdf.set_xy(-pdf.epw / 3, 20 + line_height) | ||||
|     pdf.multi_cell(0, line_height, '1', align='R') | ||||
| 
 | ||||
|     # Kundeid | ||||
|     pdf.set_xy(-pdf.epw / 3, 20 + line_height*2) | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.multi_cell(0, line_height, 'Kundeid:', align='L') | ||||
|     pdf.set_xy(-pdf.epw / 3, 20 + line_height*2) | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     pdf.multi_cell(0, line_height, '123', align='R') | ||||
| 
 | ||||
|     # Forfall | ||||
|     pdf.set_xy(-pdf.epw / 3, 20 + line_height*3) | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.multi_cell(0, line_height, 'Forfall:', align='L') | ||||
|     pdf.set_xy(-pdf.epw / 3, 20 + line_height*3) | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     pdf.multi_cell(0, line_height, datetime.date.today().strftime('%d.08.%Y'), align='R') | ||||
| 
 | ||||
|     pdf.set_xy(-pdf.epw, 20 + line_height*5) | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     date = self.start_time.strftime('%d.%m.%Y') | ||||
|     pdf.multi_cell(0, line_height, f'Kontingentliste {self.name} dato: {date}', align='R') | ||||
| 
 | ||||
|     pdf.ln() | ||||
| 
 | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     # Tabell | ||||
|     line_height = pdf.font_size * 2 | ||||
|     col_width = pdf.epw / 8  # distribute content evenly | ||||
|     # Top row | ||||
|     pdf.set_fill_color(191, 191, 191) | ||||
|     pdf.set_draw_color(191, 191, 191) | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.multi_cell(col_width, line_height, 'Startnr', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.multi_cell(col_width*2, line_height, 'Navn', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.multi_cell(col_width, line_height, 'Klasse', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.multi_cell(col_width, line_height, 'Brikke', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     # pdf.multi_cell(col_width, line_height, 'Starttid', border=1, ln=3,max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.multi_cell(col_width, line_height, 'Resultat', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.multi_cell(col_width, line_height, 'Plass', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.multi_cell(col_width, line_height, 'Kontigent', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|     pdf.ln() | ||||
|     pdf.set_draw_color(0, 0, 0) | ||||
|     for runners in fee_dict.values(): | ||||
|         pdf.set_font("LiberationSans-Bold", size=11) | ||||
|         pdf.multi_cell(len(runners[0].fee.name)*2.3, pdf.font_size * 1.1, runners[0].fee.name, border='B', align='L') | ||||
|         pdf.set_font("LiberationSans", size=8) | ||||
|         line_height = pdf.font_size * 1.6 | ||||
|         pdf.ln() | ||||
|         for runner in runners: | ||||
|             pdf.multi_cell(col_width, line_height, runner.id, ln=3, max_line_height=pdf.font_size, align='L') # Start Number | ||||
|             pdf.multi_cell(col_width*2, line_height, f'{runner.last}, {runner.first}', ln=3, max_line_height=pdf.font_size, align='L') # Name | ||||
|             pdf.multi_cell(col_width, line_height, runner.o_class_str, ln=3, max_line_height=pdf.font_size, align='L') # Class | ||||
|             pdf.multi_cell(col_width, line_height, str(runner.card), ln=3, max_line_height=pdf.font_size) # card | ||||
|             # Starttime: | ||||
|             #if runner.start_time != None: | ||||
|             #    pdf.multi_cell(col_width, line_height, str(runner.start_time), ln=3, max_line_height=pdf.font_size) | ||||
|             #else: | ||||
|             #    pdf.multi_cell(col_width, line_height, 'Fristart', ln=3, max_line_height=pdf.font_size) | ||||
|             # Time used: | ||||
|             if runner.status() == 'OK': | ||||
|                 pdf.multi_cell(col_width, line_height, str(datetime.timedelta(seconds=runner.totaltime())), ln=3, max_line_height=pdf.font_size) | ||||
|             elif runner.status() == 'Disqualified': | ||||
|                 pdf.multi_cell(col_width, line_height, 'DSQ', ln=3, max_line_height=pdf.font_size) | ||||
|             elif runner.status() == 'Active': | ||||
|                 pdf.multi_cell(col_width, line_height, 'DNS', ln=3, max_line_height=pdf.font_size) | ||||
|             else: | ||||
|                 pdf.multi_cell(col_width, line_height, runner.status(), ln=3, max_line_height=pdf.font_size) | ||||
| 
 | ||||
|         # Topp høyre: | ||||
|         pdf.set_xy(-pdf.epw / 3, 10) | ||||
|         pdf.set_font("LiberationSans-Bold", size=20) | ||||
|         pdf.multi_cell(pdf.epw, line_height, 'Faktura', align='L') | ||||
|         pdf.set_xy(-pdf.epw / 3, 20) | ||||
|             # Rank: | ||||
|             if runner.status() == 'OK': | ||||
|                 pdf.multi_cell(col_width, line_height, str(runner.rank(self.runners)) + '.', ln=3, max_line_height=pdf.font_size) | ||||
|             else: | ||||
|                 pdf.multi_cell(col_width, line_height, '', ln=3, max_line_height=pdf.font_size) | ||||
| 
 | ||||
|         # Dato | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.multi_cell(0, line_height, 'Dato:', align='L') | ||||
|         pdf.set_xy(-pdf.epw / 3, 20) | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         pdf.multi_cell(0, line_height, datetime.date.today().strftime('%d.%m.%Y'), align='R') | ||||
|             pdf.multi_cell(col_width, line_height, str(runner.fee.amount), ln=3, max_line_height=pdf.font_size, align='R') | ||||
|             pdf.ln(line_height) | ||||
| 
 | ||||
|         # Nummer | ||||
|         pdf.set_xy(-pdf.epw / 3, 20 + line_height) | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.multi_cell(0, line_height, 'Nummer:', align='L') | ||||
|         pdf.set_xy(-pdf.epw / 3, 20 + line_height) | ||||
|         pdf.multi_cell(0, line_height, '1', align='R') | ||||
|     pdf.set_draw_color(0, 0, 0) | ||||
|     # sum | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.set_x(col_width*8) | ||||
|     pdf.cell(0, line_height, 'Sum    ' + str(subtotal), border='TB', align='R') | ||||
| 
 | ||||
|         # Kundeid | ||||
|         pdf.set_xy(-pdf.epw / 3, 20 + line_height*2) | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.multi_cell(0, line_height, 'Kundeid:', align='L') | ||||
|         pdf.set_xy(-pdf.epw / 3, 20 + line_height*2) | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         pdf.multi_cell(0, line_height, '123', align='R') | ||||
|     pdf.set_font("LiberationSans", size=10) | ||||
|     line_height = pdf.font_size * 1.5 | ||||
|     pdf.ln(20) | ||||
|     pdf.multi_cell(0, line_height, 'Antall løpere   ' + str(len(runners_ic)), ln=3, max_line_height=pdf.font_size, align='L') | ||||
| 
 | ||||
|         # Forfall | ||||
|         pdf.set_xy(-pdf.epw / 3, 20 + line_height*3) | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.multi_cell(0, line_height, 'Forfall:', align='L') | ||||
|         pdf.set_xy(-pdf.epw / 3, 20 + line_height*3) | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         pdf.multi_cell(0, line_height, datetime.date.today().strftime('%d.08.%Y'), align='R') | ||||
| 
 | ||||
|         pdf.set_xy(-pdf.epw, 20 + line_height*5) | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         date = self.start_time.strftime('%d.%m.%Y') | ||||
|         pdf.multi_cell(0, line_height, f'Kontingentliste {self.name} dato: {date}', align='R') | ||||
| 
 | ||||
|         pdf.ln() | ||||
| 
 | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         # Tabell | ||||
|         line_height = pdf.font_size * 2 | ||||
|         col_width = pdf.epw / 8  # distribute content evenly | ||||
|         # Top row | ||||
|         pdf.set_fill_color(191, 191, 191) | ||||
|         pdf.set_draw_color(191, 191, 191) | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.multi_cell(col_width, line_height, 'Startnr', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.multi_cell(col_width*2, line_height, 'Navn', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.multi_cell(col_width, line_height, 'Klasse', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.multi_cell(col_width, line_height, 'Brikke', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         # pdf.multi_cell(col_width, line_height, 'Starttid', border=1, ln=3,max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.multi_cell(col_width, line_height, 'Resultat', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.multi_cell(col_width, line_height, 'Plass', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.multi_cell(col_width, line_height, 'Kontigent', border=1, ln=3, max_line_height=pdf.font_size, align='L', fill=True) | ||||
|         pdf.ln() | ||||
|         pdf.set_draw_color(0, 0, 0) | ||||
|         for runners in fee_dict.values(): | ||||
|             pdf.set_font("LiberationSans-Bold", size=11) | ||||
|             pdf.multi_cell(len(runners[0].fee.name)*2.3, pdf.font_size * 1.1, runners[0].fee.name, border='B', align='L') | ||||
|             pdf.set_font("LiberationSans", size=8) | ||||
|             line_height = pdf.font_size * 1.6 | ||||
|             pdf.ln() | ||||
|             for runner in runners: | ||||
|                 pdf.multi_cell(col_width, line_height, runner.id, ln=3, max_line_height=pdf.font_size, align='L') # Start Number | ||||
|                 pdf.multi_cell(col_width*2, line_height, f'{runner.last}, {runner.first}', ln=3, max_line_height=pdf.font_size, align='L') # Name | ||||
|                 pdf.multi_cell(col_width, line_height, runner.o_class_str, ln=3, max_line_height=pdf.font_size, align='L') # Class | ||||
|                 pdf.multi_cell(col_width, line_height, str(runner.card), ln=3, max_line_height=pdf.font_size) # card | ||||
|                 # Starttime: | ||||
|                 #if runner.start_time != None: | ||||
|                 #    pdf.multi_cell(col_width, line_height, str(runner.start_time), ln=3, max_line_height=pdf.font_size) | ||||
|                 #else: | ||||
|                 #    pdf.multi_cell(col_width, line_height, 'Fristart', ln=3, max_line_height=pdf.font_size) | ||||
|                 # Time used: | ||||
|                 if runner.status() == 'OK': | ||||
|                     pdf.multi_cell(col_width, line_height, str(datetime.timedelta(seconds=runner.totaltime())), ln=3, max_line_height=pdf.font_size) | ||||
|                 elif runner.status() == 'Disqualified': | ||||
|                     pdf.multi_cell(col_width, line_height, 'DSQ', ln=3, max_line_height=pdf.font_size) | ||||
|                 elif runner.status() == 'Active': | ||||
|                     pdf.multi_cell(col_width, line_height, 'DNS', ln=3, max_line_height=pdf.font_size) | ||||
|                 else: | ||||
|                     pdf.multi_cell(col_width, line_height, runner.status(), ln=3, max_line_height=pdf.font_size) | ||||
| 
 | ||||
|                 # Rank: | ||||
|                 if runner.status() == 'OK': | ||||
|                     pdf.multi_cell(col_width, line_height, str(runner.rank(self.runners)) + '.', ln=3, max_line_height=pdf.font_size) | ||||
|                 else: | ||||
|                     pdf.multi_cell(col_width, line_height, '', ln=3, max_line_height=pdf.font_size) | ||||
| 
 | ||||
|                 pdf.multi_cell(col_width, line_height, str(runner.fee.amount), ln=3, max_line_height=pdf.font_size, align='R') | ||||
|                 pdf.ln(line_height) | ||||
| 
 | ||||
|         pdf.set_draw_color(0, 0, 0) | ||||
|         # sum | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.set_x(col_width*8) | ||||
|         pdf.cell(0, line_height, 'Sum    ' + str(subtotal), border='TB', align='R') | ||||
| 
 | ||||
|         pdf.set_font("LiberationSans", size=10) | ||||
|         line_height = pdf.font_size * 1.5 | ||||
|         pdf.ln(20) | ||||
|         pdf.multi_cell(0, line_height, 'Antall løpere   ' + str(len(runners_ic)), ln=3, max_line_height=pdf.font_size, align='L') | ||||
| 
 | ||||
|         pdf.set_x(col_width*7) | ||||
|         pdf.multi_cell(col_width, line_height, 'Total sum', ln=3, max_line_height=pdf.font_size, align='L') | ||||
|         pdf.multi_cell(0, line_height, str(subtotal), ln=3, max_line_height=pdf.font_size, align='R') | ||||
|         pdf.ln() | ||||
|         pdf.set_x(col_width*7) | ||||
|         pdf.multi_cell(col_width, line_height, 'Betalt', ln=3, max_line_height=pdf.font_size, align='L') | ||||
|         pdf.multi_cell(0, line_height, '0', ln=3, max_line_height=pdf.font_size, align='R') | ||||
|         pdf.ln() | ||||
|         pdf.set_font("LiberationSans-Bold", size=10) | ||||
|         pdf.set_x(col_width*7) | ||||
|         pdf.multi_cell(col_width, line_height, 'Skyldig', border='B', ln=3, max_line_height=pdf.font_size, align='L') | ||||
|         pdf.multi_cell(0, line_height, str(subtotal), border='B',ln=3, max_line_height=pdf.font_size, align='R') | ||||
|     pdf.set_x(col_width*7) | ||||
|     pdf.multi_cell(col_width, line_height, 'Total sum', ln=3, max_line_height=pdf.font_size, align='L') | ||||
|     pdf.multi_cell(0, line_height, str(subtotal), ln=3, max_line_height=pdf.font_size, align='R') | ||||
|     pdf.ln() | ||||
|     pdf.set_x(col_width*7) | ||||
|     pdf.multi_cell(col_width, line_height, 'Betalt', ln=3, max_line_height=pdf.font_size, align='L') | ||||
|     pdf.multi_cell(0, line_height, '0', ln=3, max_line_height=pdf.font_size, align='R') | ||||
|     pdf.ln() | ||||
|     pdf.set_font("LiberationSans-Bold", size=10) | ||||
|     pdf.set_x(col_width*7) | ||||
|     pdf.multi_cell(col_width, line_height, 'Skyldig', border='B', ln=3, max_line_height=pdf.font_size, align='L') | ||||
|     pdf.multi_cell(0, line_height, str(subtotal), border='B',ln=3, max_line_height=pdf.font_size, align='R') | ||||
| 
 | ||||
| 
 | ||||
|         pdf.output(file_name) | ||||
|     pdf.output(file_name) | ||||
| """ | ||||
| class PDF(FPDF): | ||||
|     def footer(self): | ||||
|  | ||||
| @ -7,8 +7,7 @@ def main(): | ||||
|     event.read_ttime_cnf('tt.cnf') | ||||
|     event.read_ttime_db('db.csv') | ||||
|     event.read_mtr_file('mtr.csv') | ||||
|     print(event) | ||||
|     print(event.card_dumps[1]) | ||||
| 
 | ||||
|     print(event.get_result()) | ||||
|     event.create_start_list_pdf('output/result.pdf') | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user