16 Commits

Author SHA1 Message Date
82fabe69a7 Update to new version 2023-11-08 21:33:59 +01:00
88bffcad8a Merge branch 'fix/incomplete-tables' 2023-11-08 21:33:06 +01:00
c7212316ee Fix native class from final result table 2023-11-08 20:46:05 +01:00
ee63871e1c Augment logging a bit 2023-11-08 20:45:44 +01:00
bb10d5fa06 Ignore failed preview round scans 2023-11-08 20:45:19 +01:00
36fa6a6dca Augment the logging for debugging 2023-11-08 20:42:11 +01:00
aaa311ee03 Avoid issue with rounds that contain all previous participants 2023-11-08 20:00:01 +01:00
366f496ba3 Enable external debugger 2023-10-06 18:39:55 +02:00
66d687d9f0 Update to new version 2023-10-06 18:18:50 +02:00
1d69d9fe8a Fix filtering w.r.t finalists in web styling
Mutiple rows were colored similarly of some are hidden
2023-10-06 18:17:37 +02:00
6f11554c18 Prepare next version 2023-10-06 17:53:15 +02:00
03fed1e1e4 Handle incomplete competitions as well 2023-10-06 17:52:52 +02:00
be5ac238bc Revert "Add UI dialog for unknown path"
This reverts commit 90f82e677e.
2023-10-06 16:20:39 +02:00
5015a4e4e1 Prepare next version 2023-10-06 13:04:49 +02:00
90f82e677e Add UI dialog for unknown path 2023-10-06 13:02:45 +02:00
fac3fe1b34 Fix bug related to showing all participants 2023-09-29 17:28:00 +02:00
10 changed files with 91 additions and 24 deletions

View File

@@ -1,6 +1,6 @@
[Application]
name=Solo Auswertung
version=0.9.2
version=0.9.7
# How to launch the app - this calls the 'main' function from the 'myapp' package:
entry_point=main:main
# icon=myapp.ico

View File

@@ -23,10 +23,14 @@ def main():
solo_turnier.flask.startFlask(
batchWorker,
debug=cli.getLogLevel() > 0,
port=cli.getPort()
port=cli.getPort(),
showOnlyFinalists=not cli.showAllParticipants(),
externalDebugger=cli.externalDebugger
)
else:
combinedData = batchWorker.run()
combinedData = batchWorker.run(
removeFilteredParicipants=not cli.showAllParticipants()
)
consoleOutputtter = solo_turnier.output.ConsoleOutputter()
consoleOutputtter.output(combinedData)

View File

@@ -29,7 +29,6 @@ class BatchWorker:
importedData = worker.collectAllData(htmlCandidatesPreview, htmlResultFiles)
combinedData = worker.combineData(importedData)
if not self.config.showAllParticipants():
worker.filterOutFinalists(combinedData, removeFilteredParicipants)
worker.filterOutFinalists(combinedData, removeFilteredParicipants)
return combinedData

View File

@@ -22,6 +22,8 @@ class Cli:
debugpy.listen(5678)
debugpy.wait_for_client()
self.externalDebugger = self.__args.debug
map = {
0: logging.ERROR,
1: logging.WARN,

View File

@@ -44,6 +44,11 @@ class CompetitionClassParser:
self.namesPreview = [
'Sichtung'
]
self.mapShortNames = {
'N': self.NEWC,
'B': self.BEG,
'A': self.ADV,
}
def parseClass(self, cls: str, allowPreview: bool = False) -> Class_t:
if allowPreview and cls in self.namesPreview:
@@ -57,6 +62,9 @@ class CompetitionClassParser:
else:
return self.mapNames[cls]
def parseAbbreviatedClass(self, cls: str) -> Class_t:
return self.mapShortNames[cls]
def isPureClass(self, cls: str, allowPreview: bool = False) -> bool:
parsedClass = self.parseClass(cls, allowPreview)
return isinstance(parsedClass, CompetitionClass)

View File

@@ -1,17 +1,32 @@
import flask
import solo_turnier
import logging
_l = logging.getLogger(__name__)
def startFlask(
batchWorker: solo_turnier.batch.BatchWorker,
debug: bool = False,
port: int = 8082
port: int = 8082,
showOnlyFinalists: bool = True,
externalDebugger: bool = False,
):
app = flask.Flask(__name__)
@app.route('/')
def index():
combinedData = batchWorker.run(False)
_l.debug('Show only finalists %s', showOnlyFinalists)
return flask.render_template('index.html', data=combinedData)
return flask.render_template('index.html', data=combinedData, onlyFinalists=showOnlyFinalists)
app.run(host='0.0.0.0', port=port, debug=debug)
@app.get('/custom.css')
def css():
ret = flask.render_template(
'custom.css',
onlyFinalists=showOnlyFinalists
)
return flask.Response(ret, mimetype='text/css')
useReloader = debug and not externalDebugger
app.run(host='0.0.0.0', port=port, debug=debug, use_reloader=useReloader)

View File

@@ -8,6 +8,10 @@ from .types import HtmlPreviewImport as HtmlImport, HtmlResultImport
from .group import GroupParser
from .competition_class import CompetitionClassParser
class IncompleteRoundException(Exception):
def __init__(self, *args):
super(IncompleteRoundException, self).__init__(*args)
class HtmlParser:
def __init__(self, text: str, fileName: str = None):
@@ -53,12 +57,17 @@ class HtmlParser:
if len(tds) != 2:
return
if tds[1].contents[0].startswith('Alle Starter weiter genommen.'):
self.l.info('No excluded starters found.')
return
regex = re.compile('(.*) \\(([0-9]+)\\)')
place = tds[0].contents[0]
match = regex.fullmatch(tds[1].contents[0])
if match is None:
self.l.error('Could not match %s to regex search pattern', str(tds))
raise Exception(f'Could not match {tds} to regex search pattern')
name = match.group(1)
number = match.group(2)
@@ -73,7 +82,8 @@ class HtmlParser:
def __parseFirstTable(table):
roundName = table.tr.td.contents[0]
if roundName != 'Endrunde':
raise Exception('Could not parse HTML file')
self.l.warning('Found table with round name %s.', roundName)
raise IncompleteRoundException('Could not parse HTML file')
__parseRows(table.find_all('tr')[2:], True)
@@ -82,10 +92,14 @@ class HtmlParser:
__parseRows(table.find_all('tr'), False)
tables = self.soup.find('div', class_='extract').find_all('table')
if len(tables) > 0:
__parseFirstTable(tables[0])
try:
if len(tables) > 0:
__parseFirstTable(tables[0])
__parseRemainingTables(tables[1:])
__parseRemainingTables(tables[1:])
except IncompleteRoundException:
pass
# title = self.soup.find('div', class_='eventhead').table.tr.td.contents[0]

View File

@@ -0,0 +1,5 @@
{% if onlyFinalists %}
.no-finalist {
display: none;
}
{% endif %}

View File

@@ -6,6 +6,7 @@
{# <meta name="description" content="Webpage for xxxx"> #}
<!-- http://meyerweb.com/eric/tools/css/reset/ -->
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="stylesheet" href="/custom.css">
</head>
<body>
{# <h1>Finalauswertung Solo-Turniere</h1> #}
@@ -27,6 +28,7 @@
{% if not participant.finalist %}
{% set rowCls = "no-finalist" %}
{% endif %}
{% if participant.finalist or not onlyFinalists %}
<tr class="{{ rowCls }}">
<td>{{ participant.name }} ({{ participant.id }})</td>
{% for dance in data.results[group].dances %}
@@ -46,6 +48,7 @@
{% endblock %}
{% endfor %}
</tr>
{% endif %}
{% endblock %}
{% endfor %}
</table>

View File

@@ -159,7 +159,10 @@ class PreviewWorker:
for file in parsers:
parser = parsers[file]
self.__extractPersonsFromSinglePreview(parser)
try:
self.__extractPersonsFromSinglePreview(parser)
except:
self.l.error('Failed to parse preview round in file %s. Skipping this file\'s content.', parser.fileName)
return types.HtmlPreviewImport(self.participants, self.previewResults)
@@ -177,10 +180,14 @@ class ResultExtractor:
for filePair in files:
with open(filePair[0], 'r') as fp:
text = fp.read()
with open(filePair[1], 'r') as fp:
textTab = fp.read()
parser = html_parser.HtmlParser(text, filePair[0])
parserTab = html_parser.HtmlParser(textTab, filePair[1])
if filePair[1] is None:
parserTab = None
else:
with open(filePair[1], 'r') as fp:
textTab = fp.read()
parserTab = html_parser.HtmlParser(textTab, filePair[1])
try:
data = parser.guessDataFromHtmlTitle()
@@ -247,8 +254,11 @@ class ResultExtractor:
self.l.debug('Extracting data from file %s', fileName)
self._analyzeSingleParser(parsers[fileNameTuple][0], ret)
self.l.debug('Fetching individual result of combined competitions in %s', fileName)
self._analyzeIndividualResults(parsers[fileNameTuple][1], ret)
if parsers[fileNameTuple][1] is None:
self.l.info('Skipping extraction of individual result as class is not yet finished.')
else:
self.l.debug('Fetching individual result of combined competitions in %s', fileName)
self._analyzeIndividualResults(parsers[fileNameTuple][1], ret)
return ret
@@ -460,11 +470,11 @@ class Worker:
self.l.log(5, 'Obtained result %s', resultsOfParticipant)
results[participant] = resultsOfParticipant
self.l.log(5, 'Result before native fixing: %s', (results))
self.l.log(5, 'Result before native fixing: %s', pformat(results))
# self._fixNativePlaces(dances, results)
self._fixNativePlacesFromTable(dances, results, importedData.htmlResults)
# self.l.log(5, 'Result after native fixing: %s', pformat(results))
self.l.log(5,'Data %s', results)
self._fixNativeDataFromTable(dances, results, importedData.htmlResults)
self.l.log(5, 'Result after native fixing: %s', pformat(results))
# self.l.log(5,'Fixed data %s', results)
totalResult[group] = types.TotalGroupResult(dances, results)
@@ -540,7 +550,9 @@ class Worker:
raise Exception('Multiple results found with same key')
rawResult = rawResult[0]
nativeClass = previewResults.results[participant][dance]
nativeClass = key[2]
# nativeClass = previewResults.results[participant][dance]
# nativeClass = key[2]
# self.l.log(5, 'Result %s => %s', key, rawResult)
ret = types.SingleParticipantResult(
@@ -555,13 +567,15 @@ class Worker:
return results
def _fixNativePlacesFromTable(
def _fixNativeDataFromTable(
self,
dances: list[str],
data: dict[types.HtmlPreviewParticipant, list[types.SingleParticipantResult]],
importedData: types.HtmlCompetitionTotalResults
):
rePlace = re.compile('([0-9]+)(?:-([0-9]+))?')
classParser = competition_class.CompetitionClassParser()
for participant in data.keys():
self.l.log(5, 'fixing participant %s', participant)
results = data[participant]
@@ -588,6 +602,9 @@ class Worker:
result.placeNative = matcher.group(1)
result.placeNativeTo = matcher.group(2)
if raw[1] is not None:
result.nativeClass = classParser.parseAbbreviatedClass(raw[1])
pass
def _fixNativePlaces(