2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
import solo_turnier
|
|
|
|
import logging
|
|
|
|
import os
|
2022-11-11 18:28:52 +00:00
|
|
|
import pprint
|
|
|
|
|
|
|
|
import tabulate
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
class BatchWorker:
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
config: solo_turnier.cli.Cli
|
|
|
|
):
|
|
|
|
self.l = logging.getLogger('solo_turnier.batch')
|
|
|
|
self.config = config
|
|
|
|
|
|
|
|
self.__groupMap = {
|
|
|
|
'Kin.': 0,
|
|
|
|
'Kin./Jun.': 1,
|
|
|
|
'Jun.': 10,
|
|
|
|
'Jun./Jug.': 11,
|
|
|
|
'Jug.': 20
|
|
|
|
}
|
|
|
|
self.__danceMap = {
|
|
|
|
'Samba': 1,
|
|
|
|
'Cha Cha': 2,
|
|
|
|
'Rumba': 3,
|
|
|
|
'Paso Doble': 4,
|
|
|
|
'Jive': 5,
|
|
|
|
'Langs. Walzer': 11,
|
|
|
|
'Tango': 12,
|
|
|
|
'Wiener Walzer': 13,
|
|
|
|
'Slowfox': 14,
|
|
|
|
'Quickstep': 15
|
|
|
|
}
|
2022-11-11 18:28:52 +00:00
|
|
|
self.__groupFinalMap = {
|
|
|
|
'Kinder': 'Kin.',
|
|
|
|
'Junioren': 'Jun.',
|
|
|
|
'Jugend': 'Jug.'
|
|
|
|
}
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
def __extractDataFromFiles(self):
|
|
|
|
allResultName = os.path.join(self.config.importPath(), 'allresults.csv')
|
|
|
|
readerAllResults = solo_turnier.reader.AllResultReader(allResultName)
|
|
|
|
allResults = readerAllResults.readFile()
|
|
|
|
|
|
|
|
finals = []
|
|
|
|
|
|
|
|
# Do this in a loop
|
2022-11-11 18:28:52 +00:00
|
|
|
finalName = os.path.join(self.config.importPath(), 'wert_er.txt')
|
|
|
|
readerFinal = solo_turnier.reader.ERReader(finalName)
|
|
|
|
result = readerFinal.readFile()
|
|
|
|
finals.append(result)
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
return (allResults, finals)
|
|
|
|
|
|
|
|
def __convertFinalToTuple(self, result):
|
2022-11-11 18:28:52 +00:00
|
|
|
return {
|
|
|
|
'group': result['gruppe'],
|
|
|
|
'class': result['klasse'],
|
|
|
|
'dance': result['tanz'],
|
|
|
|
'finalists': result['finalisten']
|
|
|
|
}
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
def __extractAllData(self, r):
|
|
|
|
return {
|
|
|
|
'date': r[1],
|
|
|
|
'group': r[2],
|
|
|
|
'class': r[3],
|
|
|
|
'dance': r[4],
|
|
|
|
'id': int(r[5]),
|
|
|
|
'firstName': r[6],
|
|
|
|
'lastName': r[7],
|
|
|
|
'club': r[10],
|
|
|
|
'ltv': r[11],
|
|
|
|
'place': r[12],
|
|
|
|
'placeTo': r[13],
|
|
|
|
'points': r[14],
|
|
|
|
'personGroup': r[15],
|
|
|
|
'personClass': r[16],
|
|
|
|
'remarks': r[17]
|
|
|
|
}
|
|
|
|
|
|
|
|
def __extractPersonData(self, r):
|
|
|
|
data = self.__extractAllData(r)
|
|
|
|
person = solo_turnier.participant.Person(
|
|
|
|
firstName=data['firstName'],
|
|
|
|
lastName=data['lastName'],
|
|
|
|
club=data['club'],
|
|
|
|
group=data['personGroup']
|
|
|
|
)
|
|
|
|
return person
|
|
|
|
|
|
|
|
def __extractPersons(self, allResults):
|
2022-11-11 18:28:52 +00:00
|
|
|
def decorate(person,i):
|
|
|
|
return (person.firstName, person.lastName, person.club, i, person)
|
2022-11-10 21:40:12 +00:00
|
|
|
|
2022-11-11 18:28:52 +00:00
|
|
|
personRows = [self.__extractPersonData(r) for r in allResults['data']]
|
|
|
|
persons = list(set(personRows))
|
|
|
|
persons = [decorate(p,i) for i,p in enumerate(persons)]
|
|
|
|
persons.sort()
|
|
|
|
persons = [p[4] for p in persons]
|
|
|
|
return persons
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
def __extractAllResults(self, allResults, persons: list[solo_turnier.participant.Person]):
|
2022-11-11 18:28:52 +00:00
|
|
|
def __extractDanceResult(r):
|
|
|
|
data = self.__extractAllData(r)
|
|
|
|
try:
|
|
|
|
return {
|
|
|
|
'dance': data['dance'],
|
|
|
|
'class': data['personClass'],
|
|
|
|
'place': int(data['place']),
|
|
|
|
'placeTo': int(data['placeTo']),
|
|
|
|
'id': data['id']
|
|
|
|
}
|
|
|
|
except ValueError:
|
|
|
|
self.l.debug('Issue found with data %s.', data)
|
|
|
|
return None
|
|
|
|
|
2022-11-10 21:40:12 +00:00
|
|
|
ret = {}
|
|
|
|
for row in allResults['data']:
|
2022-11-11 18:28:52 +00:00
|
|
|
danceResult = __extractDanceResult(row)
|
2022-11-10 21:40:12 +00:00
|
|
|
if danceResult is not None:
|
|
|
|
person = self.__extractPersonData(row)
|
|
|
|
if person not in ret:
|
|
|
|
ret[person] = []
|
|
|
|
|
|
|
|
ret[person].append(danceResult)
|
|
|
|
return ret
|
|
|
|
|
|
|
|
def __extractCompetitionEntries(self, r):
|
|
|
|
data = self.__extractAllData(r)
|
|
|
|
return (data['personGroup'], data['dance'])
|
|
|
|
|
|
|
|
def __extractCompetitions(self, allResults):
|
|
|
|
def __decorate(r):
|
|
|
|
return (self.__groupMap[r[0]], self.__danceMap[r[1]],r)
|
|
|
|
competitionsRows = [self.__extractCompetitionEntries(r) for r in allResults['data']]
|
|
|
|
# competitions = list(set([self.__extractDanceResult(r) for r in allResults['data']]))
|
|
|
|
competitions = [__decorate(r) for r in list(set(competitionsRows))]
|
|
|
|
competitions.sort()
|
|
|
|
competitions = [r[2] for r in competitions]
|
|
|
|
return competitions
|
2022-11-11 18:28:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
def __extractGroups(self, allResults):
|
|
|
|
def __extractGroupEntries(r):
|
|
|
|
data = self.__extractAllData(r)
|
|
|
|
return data['personGroup']
|
|
|
|
|
|
|
|
def __decorate(r):
|
|
|
|
return (self.__groupMap[r], r)
|
|
|
|
|
|
|
|
rows = [__extractGroupEntries(r) for r in allResults['data']]
|
|
|
|
groups = [__decorate(r) for r in list(set(rows))]
|
|
|
|
groups.sort()
|
|
|
|
groups = [r[1] for r in groups]
|
|
|
|
return groups
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
def __extarctBasicData(self, allResults):
|
|
|
|
def __extractRow(r):
|
|
|
|
ret = {
|
|
|
|
'firstName': r[6],
|
|
|
|
'lastName': r[7],
|
|
|
|
'number': int(r[5]),
|
|
|
|
'club': r[10],
|
|
|
|
'place': int(r[12]),
|
|
|
|
'placeTo': int(r[13]),
|
|
|
|
'group': r[15],
|
|
|
|
'class': r[16]
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
|
|
|
|
return [__extractRow(r) for r in allResults['data'][0:2]]
|
|
|
|
|
|
|
|
def run(self):
|
2022-11-16 09:22:45 +00:00
|
|
|
self.l.debug(self.config.__dict__)
|
|
|
|
|
|
|
|
locator = solo_turnier.html_locator.HtmlLocator()
|
2022-11-27 08:10:17 +00:00
|
|
|
self.l.info('Checking for feasible preview HTML export files in "%s"', self.config.importHtmlPath())
|
|
|
|
htmlCandidatesPreview = locator.findPreviewRoundCandidates(self.config.importHtmlPath())
|
|
|
|
self.l.debug('Found HTML file candidates for preview rounds: %s', htmlCandidatesPreview)
|
|
|
|
|
2023-09-13 13:23:04 +00:00
|
|
|
htmlResultFiles = locator.findCandidates(self.config.importHtmlPath())
|
|
|
|
self.l.debug('Using HTML result files for result extraction: %s', htmlResultFiles)
|
|
|
|
|
2022-12-03 20:46:19 +00:00
|
|
|
worker = solo_turnier.worker.Worker()
|
2023-09-13 13:23:04 +00:00
|
|
|
importedData = worker.collectAllData(htmlCandidatesPreview, self.config.importCSVPath(), htmlResultFiles)
|
|
|
|
worker.combineData(importedData)
|
2022-12-03 13:29:35 +00:00
|
|
|
|
2023-09-13 13:23:04 +00:00
|
|
|
# csvReader = solo_turnier.reader.CSVResultReader(self.config.importCSVPath())
|
2022-12-03 13:29:35 +00:00
|
|
|
# self.l.info('Loading the total result CSV file %s', self.config.importCSVPath())
|
|
|
|
# csvData = csvReader.readFile()
|
|
|
|
# self.l.info('CSV file has been read')
|
|
|
|
|
2023-09-13 13:23:04 +00:00
|
|
|
# csvExtractor = solo_turnier.reader.CSVExtractor()
|
2022-12-03 13:29:35 +00:00
|
|
|
# self.l.info('Importing CSV data into internal structures')
|
|
|
|
# csvRows = csvExtractor.mapCSVImport(csvData)
|
|
|
|
|
|
|
|
# worker = solo_turnier.worker.DataWorker()
|
|
|
|
|
2023-09-13 13:23:04 +00:00
|
|
|
# /////
|
2022-11-27 08:10:17 +00:00
|
|
|
|
|
|
|
# self.l.info('Checking for feasible HTML export files in "%s"', self.config.importHtmlPath())
|
|
|
|
# htmlCandidates = locator.findCandidates(self.config.importHtmlPath())
|
|
|
|
# self.l.debug('Found HTML file candidates: %s', htmlCandidates)
|
|
|
|
|
|
|
|
# htmlParser = solo_turnier.html_parser.HtmlParser()
|
|
|
|
# htmlImports = []
|
|
|
|
# self.l.info('Importing the candidates')
|
|
|
|
# for candidate in htmlCandidates:
|
|
|
|
# self.l.debug('Processing file %s', candidate)
|
|
|
|
# with open(candidate, 'r') as fp:
|
|
|
|
# fileContent = fp.read()
|
|
|
|
# htmlImports.append(htmlParser.parseString(fileContent))
|
|
|
|
# self.l.info('All HTML files have been parsed')
|
|
|
|
|
|
|
|
|
|
|
|
# self.l.info('Processing the imported data')
|
|
|
|
|
|
|
|
|
|
|
|
# self.l.debug('Combining results from CSV for individual users')
|
|
|
|
# data = worker.combineRowsByPerson(csvRows)
|
|
|
|
# self.l.debug('Fix the groups for combined competitions')
|
|
|
|
# unambiguous, fixedGroups = worker.consolidateGroups(data)
|
|
|
|
# if fixedGroups:
|
|
|
|
# self.l.info('It was required to fix some group issues.')
|
|
|
|
# if not unambiguous:
|
|
|
|
# self.warning('There were couples whose group could not be extracted unambiguously.')
|
|
|
|
# self.l.debug('Merging HTML and CSV data')
|
|
|
|
# worker.mergeHtmlData(data, htmlImports)
|
|
|
|
# self.l.info('Data is prepared')
|
|
|
|
|
|
|
|
# consoleOutputtter = solo_turnier.output.ConsoleOutputter()
|
|
|
|
# consoleOutputtter.output(data)
|
2022-11-16 09:22:45 +00:00
|
|
|
|
|
|
|
def run1(self):
|
2022-11-10 21:40:12 +00:00
|
|
|
allResults, finals = self.__extractDataFromFiles()
|
|
|
|
|
|
|
|
persons = self.__extractPersons(allResults)
|
|
|
|
self.l.debug('Found persons: %s', persons)
|
|
|
|
|
|
|
|
totalResults = self.__extractAllResults(allResults, persons)
|
|
|
|
self.l.debug('Total results: %s', totalResults)
|
|
|
|
|
2022-11-11 18:28:52 +00:00
|
|
|
groups = self.__extractGroups(allResults)
|
|
|
|
self.l.debug('Found groups: %s', groups)
|
|
|
|
|
|
|
|
groupRes = {}
|
|
|
|
for group in groups:
|
|
|
|
self.l.info('Processing group %s', group)
|
|
|
|
groupRes[group] = {}
|
|
|
|
|
|
|
|
personsInGroup = [p for p in persons if p.group == group]
|
|
|
|
self.l.debug('Remaining persons: %s', personsInGroup)
|
|
|
|
groupRes[group]['participants'] = personsInGroup
|
|
|
|
|
|
|
|
groupRes[group]['results'] = {}
|
|
|
|
for person in personsInGroup:
|
|
|
|
groupRes[group]['results'][person] = totalResults[person]
|
|
|
|
# resultsInGroup = totalResults[personsInGroup]
|
|
|
|
# self.l.debug('Results in group: %s', resultsInGroup)
|
|
|
|
|
|
|
|
# Do this in a loop
|
|
|
|
finalists = [self.__convertFinalToTuple(r) for r in finals]
|
|
|
|
self.l.debug('Mapped to tuples: %s', finalists)
|
|
|
|
|
|
|
|
self.l.info('Augmenting the list of participants')
|
|
|
|
for finalistList in finalists:
|
|
|
|
self.l.debug('Augmenting competition %s', finalistList)
|
|
|
|
longGroup = finalistList['group']
|
|
|
|
grep = self.__groupFinalMap[longGroup]
|
|
|
|
|
|
|
|
for person in groupRes[group]['results'].keys():
|
|
|
|
self.l.debug('Checking %s for finalist state in competition', person)
|
|
|
|
for competition in groupRes[group]['results'][person]:
|
|
|
|
if competition['dance'] != finalistList['dance']:
|
|
|
|
continue
|
|
|
|
if competition['class'] != finalistList['class']:
|
|
|
|
continue
|
|
|
|
|
|
|
|
competition['finalist'] = (competition['id'] in finalistList['finalists'])
|
|
|
|
self.l.debug('Organized results: %s', groupRes)
|
|
|
|
|
|
|
|
dancesRaw = [competition['dance'] for group in groups for person in groupRes[group]['participants'] for competition in groupRes[group]['results'][person]]
|
|
|
|
dances = list(set(dancesRaw))
|
|
|
|
dances = [(self.__danceMap[d], d) for d in dances]
|
|
|
|
dances.sort()
|
|
|
|
dances = [r[1] for r in dances]
|
|
|
|
self.l.debug('Found dances in competition: %s', dances)
|
|
|
|
|
|
|
|
ret = {}
|
|
|
|
for group in groups:
|
|
|
|
ret[group] = {}
|
|
|
|
|
|
|
|
for person in groupRes[group]['participants']:
|
|
|
|
ret[group][person] = {}
|
|
|
|
# Seed the data structure
|
|
|
|
for dance in dances:
|
|
|
|
ret[group][person][dance] = {
|
|
|
|
'participated': False,
|
|
|
|
'class': '',
|
|
|
|
'finalist': False,
|
|
|
|
'place': '',
|
|
|
|
'id': 0
|
|
|
|
}
|
|
|
|
|
|
|
|
for competition in groupRes[group]['results'][person]:
|
|
|
|
def __getPlace():
|
|
|
|
if competition['place'] == competition['placeTo']:
|
|
|
|
return str(competition['place'])
|
|
|
|
else:
|
|
|
|
return f"{competition['place']}-{competition['placeTo']}"
|
|
|
|
|
|
|
|
dance = competition['dance']
|
|
|
|
ret[group][person][dance]['participated'] = True
|
|
|
|
ret[group][person][dance]['class'] = competition['class']
|
|
|
|
ret[group][person][dance]['finalist'] = competition.get('finalist', False)
|
|
|
|
ret[group][person][dance]['place'] = __getPlace()
|
|
|
|
ret[group][person][dance]['id'] = competition['id']
|
|
|
|
|
|
|
|
self.l.debug('Returned data: %s', pprint.pformat(ret))
|
|
|
|
|
|
|
|
for group in groups:
|
|
|
|
self.l.debug('Outputting table for group %s', group)
|
|
|
|
|
|
|
|
print(f'Ergebnisse der Gruppe {group}')
|
|
|
|
print()
|
|
|
|
|
|
|
|
row = ['Teilnehmer(in)'] + dances
|
|
|
|
table = [row]
|
|
|
|
|
|
|
|
for person in ret[group]:
|
|
|
|
row = [str(person)]
|
|
|
|
for dance in dances:
|
|
|
|
if not ret[group][person][dance]['participated']:
|
|
|
|
row.append('')
|
|
|
|
continue
|
|
|
|
if not ret[group][person][dance]['finalist']:
|
|
|
|
row.append('x')
|
|
|
|
continue
|
|
|
|
row.append(f"{ret[group][person][dance]['place']} ({ret[group][person][dance]['class']}, {ret[group][person][dance]['id']})")
|
|
|
|
table.append(row)
|
|
|
|
|
|
|
|
self.l.debug(table)
|
|
|
|
# print(tabulate.tabulate(table))
|
|
|
|
print(tabulate.tabulate(table, headers='firstrow', tablefmt='fancy_grid'))
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
|
|
# self.l.debug('Organized results: %s', pprint.pformat( groupRes['Jun.']))
|
|
|
|
# competitions = self.__extractCompetitions(allResults)
|
|
|
|
# self.l.debug('Competitions: %s', competitions)
|
2022-11-10 21:40:12 +00:00
|
|
|
|
|
|
|
# basicData = self.__extarctBasicData(allResults)
|
|
|
|
# self.l.debug('Basic extracted data: %s', basicData)
|
|
|
|
|
|
|
|
|