2022-11-14 19:01:32 +00:00
|
|
|
import logging
|
|
|
|
|
2022-11-15 15:52:19 +00:00
|
|
|
from solo_turnier import html_parser
|
2022-11-15 17:11:40 +00:00
|
|
|
|
2022-11-14 19:01:32 +00:00
|
|
|
class ResultRow:
|
2022-11-15 15:50:08 +00:00
|
|
|
def __init__(self, firstName, lastName, club, id, group, class_, dance, place, placeTo, competitionGroup, competitionClass):
|
2022-11-14 19:01:32 +00:00
|
|
|
self.firstName = firstName
|
|
|
|
self.lastName = lastName
|
|
|
|
self.name = f'{firstName} {lastName}'
|
|
|
|
self.club = club
|
|
|
|
self.id = id
|
|
|
|
self.group = group
|
|
|
|
self.class_ = class_
|
|
|
|
self.dance = dance
|
|
|
|
self.place = place
|
|
|
|
self.placeTo = placeTo
|
2022-11-15 15:50:08 +00:00
|
|
|
self.competitionGroup = competitionGroup
|
|
|
|
self.competitionClass = competitionClass
|
2022-11-14 19:01:32 +00:00
|
|
|
|
|
|
|
class ResultPerson:
|
2022-11-15 09:48:50 +00:00
|
|
|
def __init__(self, firstName, lastName, club, id = None, group = None):
|
2022-11-14 19:01:32 +00:00
|
|
|
self.firstName = firstName
|
|
|
|
self.lastName = lastName
|
|
|
|
self.name = f'{firstName} {lastName}'
|
|
|
|
self.club = club
|
|
|
|
self.id = id
|
2022-11-15 09:48:50 +00:00
|
|
|
self.group = group
|
2022-11-14 19:01:32 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def extractFromResultRow(row: ResultRow):
|
|
|
|
return ResultPerson(
|
|
|
|
firstName=row.firstName,
|
|
|
|
lastName=row.lastName,
|
|
|
|
club=row.club
|
|
|
|
)
|
2022-11-15 09:48:50 +00:00
|
|
|
|
|
|
|
def __eq__(self, o):
|
|
|
|
if not isinstance(o, ResultPerson):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return (
|
|
|
|
self.firstName == o.firstName and
|
|
|
|
self.lastName == o.lastName and
|
|
|
|
self.club == o.club and
|
|
|
|
self.id == o.id
|
|
|
|
)
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
if self.id is None:
|
|
|
|
return f'{self.name} ({self.club})'
|
|
|
|
else:
|
|
|
|
return f'{self.name} ({self.club}) [{self.id}]'
|
|
|
|
|
|
|
|
def __hash__(self):
|
|
|
|
text = str(self)
|
|
|
|
return text.__hash__()
|
2022-11-14 19:01:32 +00:00
|
|
|
|
|
|
|
class CompetitionResult:
|
2022-11-15 15:50:08 +00:00
|
|
|
def __init__(self, dance, group, class_, place, placeTo, id, competitionGroup, competitionClass):
|
2022-11-14 19:01:32 +00:00
|
|
|
self.dance = dance
|
2022-11-15 09:48:50 +00:00
|
|
|
self.group = group
|
2022-11-14 19:01:32 +00:00
|
|
|
self.class_ = class_
|
|
|
|
self.place = place
|
|
|
|
self.placeTo = placeTo
|
|
|
|
self.id = int(id)
|
2022-11-15 15:50:08 +00:00
|
|
|
self.competitionGroup = competitionGroup
|
|
|
|
self.competitionClass = competitionClass
|
2022-11-15 13:38:46 +00:00
|
|
|
self.finalist = None
|
2022-11-14 19:01:32 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def extractFromResultRow(row: ResultRow):
|
|
|
|
return CompetitionResult(
|
|
|
|
dance=row.dance,
|
2022-11-15 09:48:50 +00:00
|
|
|
group=row.group,
|
2022-11-14 19:01:32 +00:00
|
|
|
class_=row.class_,
|
|
|
|
place=row.place, placeTo=row.placeTo,
|
2022-11-15 15:50:08 +00:00
|
|
|
id=row.id,
|
|
|
|
competitionGroup=row.competitionGroup,
|
|
|
|
competitionClass=row.competitionClass
|
2022-11-14 19:01:32 +00:00
|
|
|
)
|
|
|
|
|
2022-11-15 09:48:50 +00:00
|
|
|
def __repr__(self):
|
|
|
|
if self.place == self.placeTo:
|
|
|
|
result = f'{self.place}.'
|
|
|
|
else:
|
|
|
|
result = f'{self.place}.-{self.placeTo}.'
|
2022-11-15 13:38:46 +00:00
|
|
|
|
|
|
|
if self.finalist == True:
|
|
|
|
finalist = '[F]'
|
|
|
|
else:
|
|
|
|
finalist = ''
|
|
|
|
return f'Result[{self.id}]({self.group} {self.class_} {self.dance} as {result}{finalist})'
|
2022-11-15 09:48:50 +00:00
|
|
|
|
|
|
|
def __eq__(self, o):
|
|
|
|
if not isinstance(o, CompetitionResult):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return (
|
|
|
|
self.dance == o.dance and
|
2022-11-15 15:50:08 +00:00
|
|
|
self.competitionClass == o.competitionClass and
|
|
|
|
self.competitionGroup == o.competitionGroup and
|
2022-11-15 09:48:50 +00:00
|
|
|
self.place == o.place and self.placeTo == o.placeTo and
|
|
|
|
self.id == o.id
|
|
|
|
)
|
|
|
|
|
2022-11-14 19:01:32 +00:00
|
|
|
class CSVExtractor:
|
|
|
|
def __init__(self):
|
|
|
|
self.l = logging.getLogger('solo_turnier.worker')
|
|
|
|
|
|
|
|
def mapCSVImport(self, imported) -> list[ResultRow]:
|
|
|
|
ret = []
|
|
|
|
|
|
|
|
def __processRow(row):
|
|
|
|
result = ResultRow(
|
2022-11-15 15:50:08 +00:00
|
|
|
competitionGroup=row[2],
|
|
|
|
competitionClass=row[3],
|
2022-11-14 19:01:32 +00:00
|
|
|
dance=row[4],
|
|
|
|
id=row[5],
|
|
|
|
firstName=row[6], lastName=row[7],
|
|
|
|
club=row[10],
|
|
|
|
place=row[12], placeTo=row[13],
|
|
|
|
group=row[15], class_=row[16]
|
|
|
|
)
|
|
|
|
ret.append(result)
|
|
|
|
|
|
|
|
for row in imported['data']:
|
|
|
|
__processRow(row)
|
|
|
|
|
|
|
|
return ret
|
2022-11-15 09:48:50 +00:00
|
|
|
|
|
|
|
class DataWorker:
|
|
|
|
def __init__(self):
|
|
|
|
self.l = logging.getLogger('solo_turnier.worker')
|
|
|
|
|
|
|
|
def combineRowsByPerson(self, rows: list[ResultRow]) -> dict[ResultPerson, list[CompetitionResult]]:
|
|
|
|
ret = {}
|
|
|
|
for row in rows:
|
|
|
|
result = CompetitionResult.extractFromResultRow(row)
|
|
|
|
|
|
|
|
if result.place == '-' or result.placeTo == '-':
|
|
|
|
continue
|
|
|
|
|
|
|
|
person = ResultPerson.extractFromResultRow(row)
|
|
|
|
if person not in ret:
|
|
|
|
ret[person] = []
|
|
|
|
ret[person].append(result)
|
|
|
|
return ret
|
|
|
|
|
|
|
|
def checkUniqueIds(self, data: dict[ResultPerson, list[CompetitionResult]]) -> bool:
|
|
|
|
unique = True
|
|
|
|
for person in data:
|
|
|
|
ids = set([c.id for c in data[person]])
|
|
|
|
if len(ids) == 1:
|
|
|
|
person.id = list(ids)[0]
|
|
|
|
else:
|
|
|
|
unique = False
|
|
|
|
|
|
|
|
return unique
|
2022-11-15 12:00:17 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
Return a tuple
|
|
|
|
The first one is True, if all persons could be unambiguously identified a group
|
|
|
|
The second one is True if there was the need to override a group but it was possible to extract from other data
|
|
|
|
The second one can be seen as a warning
|
|
|
|
"""
|
|
|
|
def consolidateGroups(self, data:dict[ResultPerson, list[CompetitionResult]]) -> tuple[bool, bool]:
|
|
|
|
ambiguous = False
|
|
|
|
warnChange = False
|
|
|
|
|
|
|
|
unambiguousGroups = set(['Kin.', 'Jun.', 'Jug.'])
|
|
|
|
combinations = set(['Kin./Jun.', 'Jun./Jug.'])
|
|
|
|
|
|
|
|
for person in data:
|
|
|
|
groupsRaw = set([c.group for c in data[person]])
|
|
|
|
|
|
|
|
unknown = groupsRaw.difference(unambiguousGroups).difference(combinations)
|
|
|
|
if len(unknown) > 0:
|
|
|
|
raise Exception(f'There were unknown groups found for {person}: {unknown}')
|
|
|
|
|
|
|
|
numUnambiguousGroups = len(groupsRaw.intersection(unambiguousGroups))
|
|
|
|
|
|
|
|
if numUnambiguousGroups == 0:
|
|
|
|
if len(groupsRaw) == 2:
|
|
|
|
warnChange = True
|
|
|
|
person.group = 'Jun.'
|
|
|
|
else:
|
|
|
|
ambiguous = True
|
|
|
|
if len(groupsRaw) == 1:
|
|
|
|
person.group = list(groupsRaw)[0]
|
|
|
|
|
|
|
|
elif numUnambiguousGroups == 1:
|
|
|
|
if len(groupsRaw.intersection(combinations)) > 0:
|
|
|
|
warnChange = True
|
|
|
|
|
|
|
|
person.group = list(groupsRaw.intersection(unambiguousGroups))[0]
|
|
|
|
|
|
|
|
else:
|
|
|
|
raise Exception(f'{person} cannot have different groups.')
|
|
|
|
|
|
|
|
return (not ambiguous, warnChange)
|
2022-11-15 15:52:19 +00:00
|
|
|
|
|
|
|
def _createHtmlLUT(self, htmlImports: list[html_parser.HtmlImport]):
|
|
|
|
ret = {}
|
|
|
|
parser = html_parser.HtmlParser()
|
|
|
|
for imp in htmlImports:
|
|
|
|
parsed = parser.guessDataFromHtmlTitle(imp.title)
|
|
|
|
key = (parsed['group'], parsed['class_'], parsed['dance'])
|
|
|
|
ret[key] = imp
|
|
|
|
return ret
|
|
|
|
|
2022-11-15 17:11:40 +00:00
|
|
|
def mergeHtmlData(self, data:dict[ResultPerson, list[CompetitionResult]], htmlImports: list[html_parser.HtmlImport]):
|
|
|
|
lut = self._createHtmlLUT(htmlImports)
|
|
|
|
|
|
|
|
for person in data:
|
|
|
|
for competition in data[person]:
|
|
|
|
key = (competition.competitionGroup, competition.competitionClass, competition.dance)
|
|
|
|
htmlImport = lut[key]
|
|
|
|
participant = htmlImport.participants[str(competition.id)]
|
|
|
|
if participant.name != person.name:
|
|
|
|
self.l.error(f'Names for {person} and participant in HTML import ({participant}) do not match. Please check carefully.')
|
|
|
|
competition.finalist = participant.finalist
|