Make style code conformant with black
This commit is contained in:
parent
ca9164552c
commit
83a0003024
11
src/main.py
11
src/main.py
@ -2,15 +2,17 @@ import solo_turnier
|
|||||||
import logging
|
import logging
|
||||||
import coloredlogs
|
import coloredlogs
|
||||||
|
|
||||||
|
|
||||||
def __initLogging():
|
def __initLogging():
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
logging.root.setLevel(logging.NOTSET)
|
logging.root.setLevel(logging.NOTSET)
|
||||||
logger = logging.getLogger('solo_turnier')
|
logger = logging.getLogger("solo_turnier")
|
||||||
|
|
||||||
coloredlogs.install(level=5, logger=logger)
|
coloredlogs.install(level=5, logger=logger)
|
||||||
|
|
||||||
return logger
|
return logger
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
l = __initLogging()
|
l = __initLogging()
|
||||||
cli = solo_turnier.cli.Cli(l)
|
cli = solo_turnier.cli.Cli(l)
|
||||||
@ -18,14 +20,14 @@ def main():
|
|||||||
batchWorker = solo_turnier.batch.BatchWorker(cli)
|
batchWorker = solo_turnier.batch.BatchWorker(cli)
|
||||||
|
|
||||||
if cli.showGUI():
|
if cli.showGUI():
|
||||||
raise Exception('Not yet implemented')
|
raise Exception("Not yet implemented")
|
||||||
elif cli.startFlaskServer():
|
elif cli.startFlaskServer():
|
||||||
solo_turnier.flask.startFlask(
|
solo_turnier.flask.startFlask(
|
||||||
batchWorker,
|
batchWorker,
|
||||||
debug=cli.getLogLevel() > 0,
|
debug=cli.getLogLevel() > 0,
|
||||||
port=cli.getPort(),
|
port=cli.getPort(),
|
||||||
showOnlyFinalists=not cli.showAllParticipants(),
|
showOnlyFinalists=not cli.showAllParticipants(),
|
||||||
externalDebugger=cli.externalDebugger
|
externalDebugger=cli.externalDebugger,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
combinedData = batchWorker.run(
|
combinedData = batchWorker.run(
|
||||||
@ -35,5 +37,6 @@ def main():
|
|||||||
consoleOutputtter = solo_turnier.output.ConsoleOutputter()
|
consoleOutputtter = solo_turnier.output.ConsoleOutputter()
|
||||||
consoleOutputtter.output(combinedData)
|
consoleOutputtter.output(combinedData)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
from . import competition_class
|
from . import competition_class
|
||||||
from . import group
|
from . import group
|
||||||
from . import types
|
from . import types
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import solo_turnier
|
import solo_turnier
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -6,24 +5,31 @@ import pprint
|
|||||||
|
|
||||||
import tabulate
|
import tabulate
|
||||||
|
|
||||||
|
|
||||||
class BatchWorker:
|
class BatchWorker:
|
||||||
def __init__(
|
def __init__(self, config: solo_turnier.cli.Cli):
|
||||||
self,
|
self.l = logging.getLogger("solo_turnier.batch")
|
||||||
config: solo_turnier.cli.Cli
|
|
||||||
):
|
|
||||||
self.l = logging.getLogger('solo_turnier.batch')
|
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
def run(self, removeFilteredParicipants=True):
|
def run(self, removeFilteredParicipants=True):
|
||||||
self.l.debug(self.config.__dict__)
|
self.l.debug(self.config.__dict__)
|
||||||
|
|
||||||
locator = solo_turnier.html_locator.HtmlLocator()
|
locator = solo_turnier.html_locator.HtmlLocator()
|
||||||
self.l.info('Checking for feasible preview HTML export files in "%s"', self.config.importHtmlPath())
|
self.l.info(
|
||||||
htmlCandidatesPreview = locator.findPreviewRoundCandidates(self.config.importHtmlPath())
|
'Checking for feasible preview HTML export files in "%s"',
|
||||||
self.l.debug('Found HTML file candidates for preview rounds: %s', htmlCandidatesPreview)
|
self.config.importHtmlPath(),
|
||||||
|
)
|
||||||
|
htmlCandidatesPreview = locator.findPreviewRoundCandidates(
|
||||||
|
self.config.importHtmlPath()
|
||||||
|
)
|
||||||
|
self.l.debug(
|
||||||
|
"Found HTML file candidates for preview rounds: %s", htmlCandidatesPreview
|
||||||
|
)
|
||||||
|
|
||||||
htmlResultFiles = locator.findCandidates(self.config.importHtmlPath())
|
htmlResultFiles = locator.findCandidates(self.config.importHtmlPath())
|
||||||
self.l.debug('Using HTML result files for result extraction: %s', htmlResultFiles)
|
self.l.debug(
|
||||||
|
"Using HTML result files for result extraction: %s", htmlResultFiles
|
||||||
|
)
|
||||||
|
|
||||||
worker = solo_turnier.worker.Worker()
|
worker = solo_turnier.worker.Worker()
|
||||||
importedData = worker.collectAllData(htmlCandidatesPreview, htmlResultFiles)
|
importedData = worker.collectAllData(htmlCandidatesPreview, htmlResultFiles)
|
||||||
|
@ -3,19 +3,50 @@ import logging
|
|||||||
|
|
||||||
import debugpy
|
import debugpy
|
||||||
|
|
||||||
|
|
||||||
class Cli:
|
class Cli:
|
||||||
def __init__(self, l: logging.Logger):
|
def __init__(self, l: logging.Logger):
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
# parser.add_argument('--gui', help='Show the GUI', action='store_true')
|
# parser.add_argument('--gui', help='Show the GUI', action='store_true')
|
||||||
parser.add_argument('--no-flask', action='store_false', dest='flask', help='Disable the internal flask web server')
|
parser.add_argument(
|
||||||
parser.add_argument('--port', help='The port to listen for incoming requests', default='8082')
|
"--no-flask",
|
||||||
|
action="store_false",
|
||||||
|
dest="flask",
|
||||||
|
help="Disable the internal flask web server",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--port", help="The port to listen for incoming requests", default="8082"
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('html', help='The path from where to look for HTML export files', nargs=1, default=['.'])
|
parser.add_argument(
|
||||||
parser.add_argument('-o', '--output', help='Set the output path of the script', nargs=1, default=[None])
|
"html",
|
||||||
parser.add_argument('--all-participants', '-a', action='store_true', help='Show all participants not only finalists')
|
help="The path from where to look for HTML export files",
|
||||||
|
nargs=1,
|
||||||
|
default=["."],
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-o",
|
||||||
|
"--output",
|
||||||
|
help="Set the output path of the script",
|
||||||
|
nargs=1,
|
||||||
|
default=[None],
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--all-participants",
|
||||||
|
"-a",
|
||||||
|
action="store_true",
|
||||||
|
help="Show all participants not only finalists",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument('-v', '--verbose', help='Increase verbosity', action='count', default=0)
|
parser.add_argument(
|
||||||
parser.add_argument('-d', '--debug', action='store_true', help='Activate debugging during startup')
|
"-v", "--verbose", help="Increase verbosity", action="count", default=0
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-d",
|
||||||
|
"--debug",
|
||||||
|
action="store_true",
|
||||||
|
help="Activate debugging during startup",
|
||||||
|
)
|
||||||
self.__args = parser.parse_args()
|
self.__args = parser.parse_args()
|
||||||
|
|
||||||
if self.__args.debug:
|
if self.__args.debug:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
class CompetitionClass:
|
class CompetitionClass:
|
||||||
def __init__(self, text: str):
|
def __init__(self, text: str):
|
||||||
self.name = text
|
self.name = text
|
||||||
@ -7,54 +8,59 @@ class CompetitionClass:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class CombinedCompetitionClass:
|
class CombinedCompetitionClass:
|
||||||
def __init__(self, clsA: CompetitionClass, clsB: CompetitionClass, clsC: CompetitionClass = None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
clsA: CompetitionClass,
|
||||||
|
clsB: CompetitionClass,
|
||||||
|
clsC: CompetitionClass = None,
|
||||||
|
):
|
||||||
self.clsA = clsA
|
self.clsA = clsA
|
||||||
self.clsB = clsB
|
self.clsB = clsB
|
||||||
self.clsC = clsC
|
self.clsC = clsC
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.clsC is None:
|
if self.clsC is None:
|
||||||
return f'{self.clsA}/{self.clsB}'
|
return f"{self.clsA}/{self.clsB}"
|
||||||
else:
|
else:
|
||||||
return f'{self.clsA}/{self.clsB}/{self.clsC}'
|
return f"{self.clsA}/{self.clsB}/{self.clsC}"
|
||||||
|
|
||||||
|
|
||||||
Class_t = CompetitionClass | CombinedCompetitionClass
|
Class_t = CompetitionClass | CombinedCompetitionClass
|
||||||
|
|
||||||
class CompetitionClassParser:
|
|
||||||
NEWC = CompetitionClass('Newc.')
|
|
||||||
BEG = CompetitionClass('Beg.')
|
|
||||||
ADV = CompetitionClass('Adv.')
|
|
||||||
|
|
||||||
PREVIEW = CompetitionClass('Sichtung')
|
class CompetitionClassParser:
|
||||||
|
NEWC = CompetitionClass("Newc.")
|
||||||
|
BEG = CompetitionClass("Beg.")
|
||||||
|
ADV = CompetitionClass("Adv.")
|
||||||
|
|
||||||
|
PREVIEW = CompetitionClass("Sichtung")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.mapNames = {
|
self.mapNames = {
|
||||||
'Newc': self.NEWC,
|
"Newc": self.NEWC,
|
||||||
'Newc.': self.NEWC,
|
"Newc.": self.NEWC,
|
||||||
'Newcomer': self.NEWC,
|
"Newcomer": self.NEWC,
|
||||||
'Beg': self.BEG,
|
"Beg": self.BEG,
|
||||||
'Beg.': self.BEG,
|
"Beg.": self.BEG,
|
||||||
'Beginner': self.BEG,
|
"Beginner": self.BEG,
|
||||||
'Adv': self.ADV,
|
"Adv": self.ADV,
|
||||||
'Adv.': self.ADV,
|
"Adv.": self.ADV,
|
||||||
'Advanced': self.ADV,
|
"Advanced": self.ADV,
|
||||||
}
|
}
|
||||||
self.namesPreview = [
|
self.namesPreview = ["Sichtung"]
|
||||||
'Sichtung'
|
|
||||||
]
|
|
||||||
self.mapShortNames = {
|
self.mapShortNames = {
|
||||||
'N': self.NEWC,
|
"N": self.NEWC,
|
||||||
'B': self.BEG,
|
"B": self.BEG,
|
||||||
'A': self.ADV,
|
"A": self.ADV,
|
||||||
}
|
}
|
||||||
|
|
||||||
def parseClass(self, cls: str, allowPreview: bool = False) -> Class_t:
|
def parseClass(self, cls: str, allowPreview: bool = False) -> Class_t:
|
||||||
if allowPreview and cls in self.namesPreview:
|
if allowPreview and cls in self.namesPreview:
|
||||||
return self.PREVIEW
|
return self.PREVIEW
|
||||||
|
|
||||||
match = re.compile('^(\\w+\\.?)/(\\w+\\.?)$').match(cls)
|
match = re.compile("^(\\w+\\.?)/(\\w+\\.?)$").match(cls)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
clsA = self.mapNames[match.group(1)]
|
clsA = self.mapNames[match.group(1)]
|
||||||
clsB = self.mapNames[match.group(2)]
|
clsB = self.mapNames[match.group(2)]
|
||||||
|
@ -4,29 +4,29 @@ import logging
|
|||||||
|
|
||||||
_l = logging.getLogger(__name__)
|
_l = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def startFlask(
|
def startFlask(
|
||||||
batchWorker: solo_turnier.batch.BatchWorker,
|
batchWorker: solo_turnier.batch.BatchWorker,
|
||||||
debug: bool = False,
|
debug: bool = False,
|
||||||
port: int = 8082,
|
port: int = 8082,
|
||||||
showOnlyFinalists: bool = True,
|
showOnlyFinalists: bool = True,
|
||||||
externalDebugger: bool = False,
|
externalDebugger: bool = False,
|
||||||
):
|
):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
|
|
||||||
@app.route('/')
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
combinedData = batchWorker.run(False)
|
combinedData = batchWorker.run(False)
|
||||||
_l.debug('Show only finalists %s', showOnlyFinalists)
|
_l.debug("Show only finalists %s", showOnlyFinalists)
|
||||||
|
|
||||||
return flask.render_template('index.html', data=combinedData, onlyFinalists=showOnlyFinalists)
|
return flask.render_template(
|
||||||
|
"index.html", data=combinedData, onlyFinalists=showOnlyFinalists
|
||||||
@app.get('/custom.css')
|
|
||||||
def css():
|
|
||||||
ret = flask.render_template(
|
|
||||||
'custom.css',
|
|
||||||
onlyFinalists=showOnlyFinalists
|
|
||||||
)
|
)
|
||||||
return flask.Response(ret, mimetype='text/css')
|
|
||||||
|
@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
|
useReloader = debug and not externalDebugger
|
||||||
app.run(host='0.0.0.0', port=port, debug=debug, use_reloader=useReloader)
|
app.run(host="0.0.0.0", port=port, debug=debug, use_reloader=useReloader)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
class Group:
|
class Group:
|
||||||
def __init__(self, text: str):
|
def __init__(self, text: str):
|
||||||
self.name = text
|
self.name = text
|
||||||
@ -10,70 +11,68 @@ class Group:
|
|||||||
def getContainedGroups(self):
|
def getContainedGroups(self):
|
||||||
return (self,)
|
return (self,)
|
||||||
|
|
||||||
|
|
||||||
class CombinedGroup:
|
class CombinedGroup:
|
||||||
def __init__(self, grpA: Group, grpB: Group):
|
def __init__(self, grpA: Group, grpB: Group):
|
||||||
self.clsA = grpA
|
self.clsA = grpA
|
||||||
self.clsB = grpB
|
self.clsB = grpB
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.clsA}/{self.clsB}'
|
return f"{self.clsA}/{self.clsB}"
|
||||||
|
|
||||||
def getContainedGroups(self):
|
def getContainedGroups(self):
|
||||||
return (self.clsA, self.clsB)
|
return (self.clsA, self.clsB)
|
||||||
|
|
||||||
|
|
||||||
Group_t = Group | CombinedGroup
|
Group_t = Group | CombinedGroup
|
||||||
|
|
||||||
|
|
||||||
class GroupParser:
|
class GroupParser:
|
||||||
KIN = Group('Kin.')
|
KIN = Group("Kin.")
|
||||||
JUN = Group('Jun.')
|
JUN = Group("Jun.")
|
||||||
JUG = Group('Jug.')
|
JUG = Group("Jug.")
|
||||||
HGR = Group('Hgr.')
|
HGR = Group("Hgr.")
|
||||||
MAS1 = Group('Mas. I')
|
MAS1 = Group("Mas. I")
|
||||||
MAS2 = Group('Mas. II')
|
MAS2 = Group("Mas. II")
|
||||||
MAS3 = Group('Mas. III')
|
MAS3 = Group("Mas. III")
|
||||||
MAS4 = Group('Mas. IV')
|
MAS4 = Group("Mas. IV")
|
||||||
MAS5 = Group('Mas. V')
|
MAS5 = Group("Mas. V")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.mapNames = {
|
self.mapNames = {
|
||||||
'Kin': self.KIN,
|
"Kin": self.KIN,
|
||||||
'Kin.': self.KIN,
|
"Kin.": self.KIN,
|
||||||
'Kinder': self.KIN,
|
"Kinder": self.KIN,
|
||||||
|
"Jun": self.JUN,
|
||||||
'Jun': self.JUN,
|
"Jun.": self.JUN,
|
||||||
'Jun.': self.JUN,
|
"Junioren": self.JUN,
|
||||||
'Junioren': self.JUN,
|
"Jug": self.JUG,
|
||||||
|
"Jug.": self.JUG,
|
||||||
'Jug': self.JUG,
|
"Jugend": self.JUG,
|
||||||
'Jug.': self.JUG,
|
"Hgr": self.HGR,
|
||||||
'Jugend': self.JUG,
|
"HGr": self.HGR,
|
||||||
|
"Hgr.": self.HGR,
|
||||||
'Hgr': self.HGR,
|
"HGr.": self.HGR,
|
||||||
'HGr': self.HGR,
|
"Hauptgruppe": self.HGR,
|
||||||
'Hgr.': self.HGR,
|
"Mas. I": self.MAS1,
|
||||||
'HGr.': self.HGR,
|
"Mas. II": self.MAS2,
|
||||||
'Hauptgruppe': self.HGR,
|
"Mas. III": self.MAS3,
|
||||||
|
"Mas. IV": self.MAS4,
|
||||||
'Mas. I': self.MAS1,
|
"Mas. V": self.MAS5,
|
||||||
'Mas. II': self.MAS2,
|
"Mas I": self.MAS1,
|
||||||
'Mas. III': self.MAS3,
|
"Mas II": self.MAS2,
|
||||||
'Mas. IV': self.MAS4,
|
"Mas III": self.MAS3,
|
||||||
'Mas. V': self.MAS5,
|
"Mas IV": self.MAS4,
|
||||||
'Mas I': self.MAS1,
|
"Mas V": self.MAS5,
|
||||||
'Mas II': self.MAS2,
|
"Masters I": self.MAS1,
|
||||||
'Mas III': self.MAS3,
|
"Masters II": self.MAS2,
|
||||||
'Mas IV': self.MAS4,
|
"Masters III": self.MAS3,
|
||||||
'Mas V': self.MAS5,
|
"Masters IV": self.MAS4,
|
||||||
'Masters I': self.MAS1,
|
"Masters V": self.MAS5,
|
||||||
'Masters II': self.MAS2,
|
|
||||||
'Masters III': self.MAS3,
|
|
||||||
'Masters IV': self.MAS4,
|
|
||||||
'Masters V': self.MAS5,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def parseClass(self, cls: str) -> Group_t:
|
def parseClass(self, cls: str) -> Group_t:
|
||||||
match = re.compile('^(\\w+\\.?)/(\\w+\\.?)$').match(cls)
|
match = re.compile("^(\\w+\\.?)/(\\w+\\.?)$").match(cls)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
grpA = self.mapNames[match.group(1)]
|
grpA = self.mapNames[match.group(1)]
|
||||||
grpB = self.mapNames[match.group(2)]
|
grpB = self.mapNames[match.group(2)]
|
||||||
@ -86,7 +85,7 @@ class GroupParser:
|
|||||||
return isinstance(parsedClass, Group)
|
return isinstance(parsedClass, Group)
|
||||||
|
|
||||||
def getGroups(self) -> list[Group]:
|
def getGroups(self) -> list[Group]:
|
||||||
return[
|
return [
|
||||||
GroupParser.KIN,
|
GroupParser.KIN,
|
||||||
GroupParser.JUN,
|
GroupParser.JUN,
|
||||||
GroupParser.JUG,
|
GroupParser.JUG,
|
||||||
@ -95,7 +94,7 @@ class GroupParser:
|
|||||||
GroupParser.MAS2,
|
GroupParser.MAS2,
|
||||||
GroupParser.MAS3,
|
GroupParser.MAS3,
|
||||||
GroupParser.MAS4,
|
GroupParser.MAS4,
|
||||||
GroupParser.MAS5
|
GroupParser.MAS5,
|
||||||
]
|
]
|
||||||
|
|
||||||
def getGroupsAsSortedList(self, groups) -> list[Group]:
|
def getGroupsAsSortedList(self, groups) -> list[Group]:
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class HtmlLocator:
|
class HtmlLocator:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.l = logging.getLogger('solo_turnier.html_locator')
|
self.l = logging.getLogger("solo_turnier.html_locator")
|
||||||
|
|
||||||
def __findRecursivelyCandidates(self, path: str, fileName: str):
|
def __findRecursivelyCandidates(self, path: str, fileName: str):
|
||||||
ret = []
|
ret = []
|
||||||
@ -21,16 +22,16 @@ class HtmlLocator:
|
|||||||
|
|
||||||
def __fingMatchingTabs(self, ergCandidate):
|
def __fingMatchingTabs(self, ergCandidate):
|
||||||
path = os.path.dirname(ergCandidate)
|
path = os.path.dirname(ergCandidate)
|
||||||
tabPath = os.path.join(path, 'tabges.htm')
|
tabPath = os.path.join(path, "tabges.htm")
|
||||||
if not os.path.exists(tabPath):
|
if not os.path.exists(tabPath):
|
||||||
tabPath = None
|
tabPath = None
|
||||||
return (ergCandidate, tabPath)
|
return (ergCandidate, tabPath)
|
||||||
|
|
||||||
def findCandidates(self, path: str):
|
def findCandidates(self, path: str):
|
||||||
candidatesErg = self.__findRecursivelyCandidates(path, 'erg.htm')
|
candidatesErg = self.__findRecursivelyCandidates(path, "erg.htm")
|
||||||
candidates = [self.__fingMatchingTabs(x) for x in candidatesErg]
|
candidates = [self.__fingMatchingTabs(x) for x in candidatesErg]
|
||||||
return candidates
|
return candidates
|
||||||
|
|
||||||
def findPreviewRoundCandidates(self, path: str):
|
def findPreviewRoundCandidates(self, path: str):
|
||||||
candidates = self.__findRecursivelyCandidates(path, 'tabges.htm')
|
candidates = self.__findRecursivelyCandidates(path, "tabges.htm")
|
||||||
return candidates
|
return candidates
|
||||||
|
@ -8,29 +8,30 @@ from .types import HtmlPreviewImport as HtmlImport, HtmlResultImport
|
|||||||
from .group import GroupParser
|
from .group import GroupParser
|
||||||
from .competition_class import CompetitionClassParser
|
from .competition_class import CompetitionClassParser
|
||||||
|
|
||||||
|
|
||||||
class IncompleteRoundException(Exception):
|
class IncompleteRoundException(Exception):
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
super(IncompleteRoundException, self).__init__(*args)
|
super(IncompleteRoundException, self).__init__(*args)
|
||||||
|
|
||||||
class HtmlParser:
|
|
||||||
|
|
||||||
|
class HtmlParser:
|
||||||
def __init__(self, text: str, fileName: str = None):
|
def __init__(self, text: str, fileName: str = None):
|
||||||
self.l = logging.getLogger('solo_turnier.html_parser')
|
self.l = logging.getLogger("solo_turnier.html_parser")
|
||||||
self.soup = BeautifulSoup(text, 'html.parser')
|
self.soup = BeautifulSoup(text, "html.parser")
|
||||||
self.fileName = fileName
|
self.fileName = fileName
|
||||||
self.groupParser = GroupParser()
|
self.groupParser = GroupParser()
|
||||||
self.classParser = CompetitionClassParser()
|
self.classParser = CompetitionClassParser()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.fileName is None:
|
if self.fileName is None:
|
||||||
return 'HtmlParser(direct text)'
|
return "HtmlParser(direct text)"
|
||||||
else:
|
else:
|
||||||
return f'HtmlParser({self.fileName})'
|
return f"HtmlParser({self.fileName})"
|
||||||
|
|
||||||
def getEventTitle(self):
|
def getEventTitle(self):
|
||||||
return self.soup.find('div', class_='eventhead').table.tr.td.contents[0]
|
return self.soup.find("div", class_="eventhead").table.tr.td.contents[0]
|
||||||
|
|
||||||
def guessDataFromHtmlTitle(self, title = None):
|
def guessDataFromHtmlTitle(self, title=None):
|
||||||
if title is None:
|
if title is None:
|
||||||
title = self.getEventTitle()
|
title = self.getEventTitle()
|
||||||
|
|
||||||
@ -40,12 +41,12 @@ class HtmlParser:
|
|||||||
raise Exception(f'Cannot parse title "{title}"')
|
raise Exception(f'Cannot parse title "{title}"')
|
||||||
|
|
||||||
rest = match.group(1)
|
rest = match.group(1)
|
||||||
rawGroup, rawClass, dance = rest.split(' ', 2)
|
rawGroup, rawClass, dance = rest.split(" ", 2)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'dance': dance.strip(),
|
"dance": dance.strip(),
|
||||||
'class_': str(self.classParser.parseClass(rawClass, True)),
|
"class_": str(self.classParser.parseClass(rawClass, True)),
|
||||||
'group': str(self.groupParser.parseClass(rawGroup))
|
"group": str(self.groupParser.parseClass(rawGroup)),
|
||||||
}
|
}
|
||||||
|
|
||||||
def parseResult(self):
|
def parseResult(self):
|
||||||
@ -53,23 +54,23 @@ class HtmlParser:
|
|||||||
|
|
||||||
def __parseRows(rows, finalist: bool):
|
def __parseRows(rows, finalist: bool):
|
||||||
def __parseRow(row):
|
def __parseRow(row):
|
||||||
tds = row.find_all('td')
|
tds = row.find_all("td")
|
||||||
|
|
||||||
if len(tds) != 2:
|
if len(tds) != 2:
|
||||||
return
|
return
|
||||||
|
|
||||||
if tds[1].contents[0].startswith('Alle Starter weiter genommen.'):
|
if tds[1].contents[0].startswith("Alle Starter weiter genommen."):
|
||||||
self.l.info('No excluded starters found.')
|
self.l.info("No excluded starters found.")
|
||||||
return
|
return
|
||||||
|
|
||||||
regex = re.compile('(.*) \\(([0-9]+)\\)')
|
regex = re.compile("(.*) \\(([0-9]+)\\)")
|
||||||
|
|
||||||
place = tds[0].contents[0]
|
place = tds[0].contents[0]
|
||||||
|
|
||||||
match = regex.fullmatch(tds[1].contents[0])
|
match = regex.fullmatch(tds[1].contents[0])
|
||||||
if match is None:
|
if match is None:
|
||||||
self.l.error('Could not match %s to regex search pattern', str(tds))
|
self.l.error("Could not match %s to regex search pattern", str(tds))
|
||||||
raise Exception(f'Could not match {tds} to regex search pattern')
|
raise Exception(f"Could not match {tds} to regex search pattern")
|
||||||
name = match.group(1)
|
name = match.group(1)
|
||||||
number = match.group(2)
|
number = match.group(2)
|
||||||
|
|
||||||
@ -82,17 +83,17 @@ class HtmlParser:
|
|||||||
|
|
||||||
def __parseFirstTable(table):
|
def __parseFirstTable(table):
|
||||||
roundName = table.tr.td.contents[0]
|
roundName = table.tr.td.contents[0]
|
||||||
if roundName != 'Endrunde':
|
if roundName != "Endrunde":
|
||||||
self.l.warning('Found table with round name %s.', roundName)
|
self.l.warning("Found table with round name %s.", roundName)
|
||||||
raise IncompleteRoundException('Could not parse HTML file')
|
raise IncompleteRoundException("Could not parse HTML file")
|
||||||
|
|
||||||
__parseRows(table.find_all('tr')[2:], True)
|
__parseRows(table.find_all("tr")[2:], True)
|
||||||
|
|
||||||
def __parseRemainingTables(tables):
|
def __parseRemainingTables(tables):
|
||||||
for table in tables:
|
for table in tables:
|
||||||
__parseRows(table.find_all('tr'), False)
|
__parseRows(table.find_all("tr"), False)
|
||||||
|
|
||||||
tables = self.soup.find('div', class_='extract').find_all('table')
|
tables = self.soup.find("div", class_="extract").find_all("table")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(tables) > 0:
|
if len(tables) > 0:
|
||||||
@ -105,30 +106,30 @@ class HtmlParser:
|
|||||||
# title = self.soup.find('div', class_='eventhead').table.tr.td.contents[0]
|
# title = self.soup.find('div', class_='eventhead').table.tr.td.contents[0]
|
||||||
|
|
||||||
# ret = HtmlImport(title, participants)
|
# ret = HtmlImport(title, participants)
|
||||||
ret = HtmlResultImport(participants)
|
ret = HtmlResultImport(participants)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def parsePreparationRound(self):
|
def parsePreparationRound(self):
|
||||||
title = self.soup.find('div', class_='eventhead').table.tr.td.contents[0]
|
title = self.soup.find("div", class_="eventhead").table.tr.td.contents[0]
|
||||||
tableData = []
|
tableData = []
|
||||||
rowTitles = []
|
rowTitles = []
|
||||||
|
|
||||||
def __mapBr(td):
|
def __mapBr(td):
|
||||||
for br in td.find_all('br'):
|
for br in td.find_all("br"):
|
||||||
br.replace_with('\n')
|
br.replace_with("\n")
|
||||||
td.smooth()
|
td.smooth()
|
||||||
return td
|
return td
|
||||||
|
|
||||||
def __extractTitles(table):
|
def __extractTitles(table):
|
||||||
for row in table.find_all('tr')[1:]:
|
for row in table.find_all("tr")[1:]:
|
||||||
rowTitles.append(__mapBr(row.td).string)
|
rowTitles.append(__mapBr(row.td).string)
|
||||||
|
|
||||||
def __extractColumns(table):
|
def __extractColumns(table):
|
||||||
content = []
|
content = []
|
||||||
|
|
||||||
def __extractContent(td):
|
def __extractContent(td):
|
||||||
for br in td.find_all('br'):
|
for br in td.find_all("br"):
|
||||||
br.replace_with('\n')
|
br.replace_with("\n")
|
||||||
|
|
||||||
span = td.span
|
span = td.span
|
||||||
if span is not None:
|
if span is not None:
|
||||||
@ -139,18 +140,15 @@ class HtmlParser:
|
|||||||
|
|
||||||
td.smooth()
|
td.smooth()
|
||||||
|
|
||||||
return {
|
return {"text": td.string.replace("\xa0", " ").strip(), "meta": meta}
|
||||||
'text': td.string.replace('\xa0', ' ').strip(),
|
|
||||||
'meta': meta
|
|
||||||
}
|
|
||||||
|
|
||||||
def __extractRow(row):
|
def __extractRow(row):
|
||||||
entries = []
|
entries = []
|
||||||
for entry in row.find_all('td')[1:]:
|
for entry in row.find_all("td")[1:]:
|
||||||
entries.append(__extractContent(entry))
|
entries.append(__extractContent(entry))
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
for row in table.find_all('tr')[1:]:
|
for row in table.find_all("tr")[1:]:
|
||||||
content.append(__extractRow(row))
|
content.append(__extractRow(row))
|
||||||
|
|
||||||
return content
|
return content
|
||||||
@ -158,8 +156,8 @@ class HtmlParser:
|
|||||||
def __mergeColumns(columns1, columns2):
|
def __mergeColumns(columns1, columns2):
|
||||||
return list(map(lambda x, y: x + y, columns1, columns2))
|
return list(map(lambda x, y: x + y, columns1, columns2))
|
||||||
|
|
||||||
extract = self.soup.find('div', class_='extract')
|
extract = self.soup.find("div", class_="extract")
|
||||||
tables = extract.find_all('table', class_='tab1')
|
tables = extract.find_all("table", class_="tab1")
|
||||||
|
|
||||||
__extractTitles(tables[0])
|
__extractTitles(tables[0])
|
||||||
tableData = __extractColumns(tables[0])
|
tableData = __extractColumns(tables[0])
|
||||||
@ -167,55 +165,52 @@ class HtmlParser:
|
|||||||
for table in tables[1:]:
|
for table in tables[1:]:
|
||||||
tableData = __mergeColumns(tableData, __extractColumns(table))
|
tableData = __mergeColumns(tableData, __extractColumns(table))
|
||||||
|
|
||||||
data = {
|
data = {"titles": rowTitles, "table": tableData}
|
||||||
'titles': rowTitles,
|
|
||||||
'table': tableData
|
|
||||||
}
|
|
||||||
|
|
||||||
return {'title': title, 'data': data}
|
return {"title": title, "data": data}
|
||||||
|
|
||||||
def cleanPreparationRoundImport(self, data):
|
def cleanPreparationRoundImport(self, data):
|
||||||
def __cleanTable(table):
|
def __cleanTable(table):
|
||||||
def __cleanText(s: str):
|
def __cleanText(s: str):
|
||||||
# print("cleaning string ", s)
|
# print("cleaning string ", s)
|
||||||
return s.strip(' \n\xa0')
|
return s.strip(" \n\xa0")
|
||||||
|
|
||||||
def __cleanEntry(entry):
|
def __cleanEntry(entry):
|
||||||
entry['text'] = __cleanText(entry['text'])
|
entry["text"] = __cleanText(entry["text"])
|
||||||
if entry['meta'] is not None:
|
if entry["meta"] is not None:
|
||||||
entry['meta'] = __cleanText(entry['meta'])
|
entry["meta"] = __cleanText(entry["meta"])
|
||||||
|
|
||||||
for row in table:
|
for row in table:
|
||||||
for entry in row:
|
for entry in row:
|
||||||
# print(entry)
|
# print(entry)
|
||||||
__cleanEntry(entry)
|
__cleanEntry(entry)
|
||||||
|
|
||||||
data['title'] = data['title'].strip()
|
data["title"] = data["title"].strip()
|
||||||
__cleanTable(data['data']['table'])
|
__cleanTable(data["data"]["table"])
|
||||||
|
|
||||||
def parseIndividualResult(self, competitionGroup, competitionClass, dance):
|
def parseIndividualResult(self, competitionGroup, competitionClass, dance):
|
||||||
|
|
||||||
participants = {}
|
participants = {}
|
||||||
|
|
||||||
def __parseTable(table):
|
def __parseTable(table):
|
||||||
rows = table.find_all('tr')
|
rows = table.find_all("tr")
|
||||||
|
|
||||||
def __getIds():
|
def __getIds():
|
||||||
row = rows[1]
|
row = rows[1]
|
||||||
entries = row('td')
|
entries = row("td")
|
||||||
entries = entries[1:]
|
entries = entries[1:]
|
||||||
entries = [x for x in entries if len(x.contents[0].strip()) > 0]
|
entries = [x for x in entries if len(x.contents[0].strip()) > 0]
|
||||||
return [x.contents[0].strip() for x in entries]
|
return [x.contents[0].strip() for x in entries]
|
||||||
|
|
||||||
ids = __getIds()
|
ids = __getIds()
|
||||||
numIds = len(ids)
|
numIds = len(ids)
|
||||||
self.l.log(5, 'Found ids in dataset: %s', ids)
|
self.l.log(5, "Found ids in dataset: %s", ids)
|
||||||
|
|
||||||
def findRowIndex(prefixStr):
|
def findRowIndex(prefixStr):
|
||||||
def isRowMatchingCriteria(row):
|
def isRowMatchingCriteria(row):
|
||||||
if row.td.contents[0].startswith(prefixStr):
|
if row.td.contents[0].startswith(prefixStr):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
l = list(map(isRowMatchingCriteria, rows))
|
l = list(map(isRowMatchingCriteria, rows))
|
||||||
|
|
||||||
if True not in l:
|
if True not in l:
|
||||||
@ -223,38 +218,43 @@ class HtmlParser:
|
|||||||
return l.index(True)
|
return l.index(True)
|
||||||
|
|
||||||
def getPlaces():
|
def getPlaces():
|
||||||
placeRowIdx = findRowIndex('Platz von')
|
placeRowIdx = findRowIndex("Platz von")
|
||||||
placeTags = rows[placeRowIdx]('td')[1:(numIds+1)]
|
placeTags = rows[placeRowIdx]("td")[1 : (numIds + 1)]
|
||||||
|
|
||||||
def getSinglePlaceStr(tag):
|
def getSinglePlaceStr(tag):
|
||||||
for br in tag('br'):
|
for br in tag("br"):
|
||||||
br.replace_with('-')
|
br.replace_with("-")
|
||||||
tag.smooth()
|
tag.smooth()
|
||||||
rawStr = tag.contents[0].strip()
|
rawStr = tag.contents[0].strip()
|
||||||
if rawStr.endswith('-'):
|
if rawStr.endswith("-"):
|
||||||
rawStr = rawStr[:-1]
|
rawStr = rawStr[:-1]
|
||||||
return rawStr
|
return rawStr
|
||||||
|
|
||||||
places = list(map(getSinglePlaceStr, placeTags))
|
places = list(map(getSinglePlaceStr, placeTags))
|
||||||
return places
|
return places
|
||||||
|
|
||||||
places = getPlaces()
|
places = getPlaces()
|
||||||
self.l.log(5, 'Found places: %s', places)
|
self.l.log(5, "Found places: %s", places)
|
||||||
|
|
||||||
def getClass():
|
def getClass():
|
||||||
classRow = findRowIndex('Startklasse')
|
classRow = findRowIndex("Startklasse")
|
||||||
if classRow is not None:
|
if classRow is not None:
|
||||||
classTags = rows[classRow]('td')[1:(numIds+1)]
|
classTags = rows[classRow]("td")[1 : (numIds + 1)]
|
||||||
return list(map(lambda x: x.contents[0], classTags))
|
return list(map(lambda x: x.contents[0], classTags))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
classes = getClass()
|
classes = getClass()
|
||||||
self.l.log(5, 'Classes: %s', classes)
|
self.l.log(5, "Classes: %s", classes)
|
||||||
|
|
||||||
def getGroups():
|
def getGroups():
|
||||||
groupRow = findRowIndex('Startgruppe')
|
groupRow = findRowIndex("Startgruppe")
|
||||||
if groupRow is not None:
|
if groupRow is not None:
|
||||||
classTags = rows[groupRow]('td')[1:(numIds+1)]
|
classTags = rows[groupRow]("td")[1 : (numIds + 1)]
|
||||||
return list(map(lambda x: x.contents[0], classTags))
|
return list(map(lambda x: x.contents[0], classTags))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
groups = getGroups()
|
groups = getGroups()
|
||||||
self.l.log(5, 'Groups: %s', groups)
|
self.l.log(5, "Groups: %s", groups)
|
||||||
|
|
||||||
for idx, id in enumerate(ids):
|
for idx, id in enumerate(ids):
|
||||||
cls = classes[idx] if classes is not None else None
|
cls = classes[idx] if classes is not None else None
|
||||||
@ -263,8 +263,8 @@ class HtmlParser:
|
|||||||
tup = (competitionGroup, competitionClass, dance, id)
|
tup = (competitionGroup, competitionClass, dance, id)
|
||||||
participants[tup] = (places[idx], cls, grp)
|
participants[tup] = (places[idx], cls, grp)
|
||||||
|
|
||||||
tables = self.soup.find('div', class_='extract').find_all('table')
|
tables = self.soup.find("div", class_="extract").find_all("table")
|
||||||
for table in tables:
|
for table in tables:
|
||||||
__parseTable(table)
|
__parseTable(table)
|
||||||
|
|
||||||
return HtmlResultTotalTable( participants)
|
return HtmlResultTotalTable(participants)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
import pprint
|
import pprint
|
||||||
@ -6,14 +5,15 @@ import pprint
|
|||||||
import solo_turnier
|
import solo_turnier
|
||||||
from solo_turnier import types
|
from solo_turnier import types
|
||||||
|
|
||||||
sections = ('Kin.', 'Jun.', 'Jug.', 'Sonst')
|
sections = ("Kin.", "Jun.", "Jug.", "Sonst")
|
||||||
sectionMap = {
|
sectionMap = {
|
||||||
'Kin.': 'Kinder',
|
"Kin.": "Kinder",
|
||||||
'Jun.': 'Junioren',
|
"Jun.": "Junioren",
|
||||||
'Jug.': 'Jugend',
|
"Jug.": "Jugend",
|
||||||
'Sonst': 'Undefiniert'
|
"Sonst": "Undefiniert",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AbstractOutputter:
|
class AbstractOutputter:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.worker = solo_turnier.worker.DataWorker()
|
self.worker = solo_turnier.worker.DataWorker()
|
||||||
@ -24,24 +24,26 @@ class AbstractOutputter:
|
|||||||
def getRowData(self, person: solo_turnier.worker.ResultPerson, results):
|
def getRowData(self, person: solo_turnier.worker.ResultPerson, results):
|
||||||
mappedResults = self.worker.mapPersonResultsToDanceList(results, self.dances)
|
mappedResults = self.worker.mapPersonResultsToDanceList(results, self.dances)
|
||||||
if self.showIds:
|
if self.showIds:
|
||||||
name = f'{person.name} ({person.id})'
|
name = f"{person.name} ({person.id})"
|
||||||
else:
|
else:
|
||||||
name = person.name
|
name = person.name
|
||||||
|
|
||||||
ret = [name]
|
ret = [name]
|
||||||
for result in mappedResults:
|
for result in mappedResults:
|
||||||
if result is None:
|
if result is None:
|
||||||
ret.append('')
|
ret.append("")
|
||||||
elif result.finalist == False:
|
elif result.finalist == False:
|
||||||
ret.append('x')
|
ret.append("x")
|
||||||
elif result.place == result.placeTo:
|
elif result.place == result.placeTo:
|
||||||
ret.append(f'{result.place}. ({result.class_})')
|
ret.append(f"{result.place}. ({result.class_})")
|
||||||
else:
|
else:
|
||||||
ret.append(f'{result.place}.-{result.placeTo}. ({result.class_})')
|
ret.append(f"{result.place}.-{result.placeTo}. ({result.class_})")
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def getTabularData(self, data, section):
|
def getTabularData(self, data, section):
|
||||||
sortedPersons, self.showIds = self.worker.sortPersonsInGroup(self.groups[section])
|
sortedPersons, self.showIds = self.worker.sortPersonsInGroup(
|
||||||
|
self.groups[section]
|
||||||
|
)
|
||||||
|
|
||||||
tableData = []
|
tableData = []
|
||||||
for person in sortedPersons:
|
for person in sortedPersons:
|
||||||
@ -49,63 +51,66 @@ class AbstractOutputter:
|
|||||||
|
|
||||||
return tableData
|
return tableData
|
||||||
|
|
||||||
|
|
||||||
class ConsoleOutputter(AbstractOutputter):
|
class ConsoleOutputter(AbstractOutputter):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.l = logging.getLogger('solo_turnier.output.console')
|
self.l = logging.getLogger("solo_turnier.output.console")
|
||||||
|
|
||||||
def __outputSection(self, data, section):
|
def __outputSection(self, data, section):
|
||||||
tableData = self.getTabularData(data, section)
|
tableData = self.getTabularData(data, section)
|
||||||
tableData = [['Name'] + self.dances] + tableData
|
tableData = [["Name"] + self.dances] + tableData
|
||||||
|
|
||||||
print(f"Einzeltanzwettbewerb der {sectionMap[section]}")
|
print(f"Einzeltanzwettbewerb der {sectionMap[section]}")
|
||||||
print(tabulate(tableData, headers='firstrow', tablefmt='fancy_grid'))
|
print(tabulate(tableData, headers="firstrow", tablefmt="fancy_grid"))
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def _outputGroup(self, group: solo_turnier.group.Group, groupResults: types.TotalGroupResult):
|
def _outputGroup(
|
||||||
|
self, group: solo_turnier.group.Group, groupResults: types.TotalGroupResult
|
||||||
|
):
|
||||||
print(f"Einzeltanzwettbewerb der Gruppe {group}")
|
print(f"Einzeltanzwettbewerb der Gruppe {group}")
|
||||||
|
|
||||||
tableData = [['Tanz'] + groupResults.dances]
|
tableData = [["Tanz"] + groupResults.dances]
|
||||||
participants = list(groupResults.results.keys())
|
participants = list(groupResults.results.keys())
|
||||||
participants.sort(key=lambda x: (x.id, x.name))
|
participants.sort(key=lambda x: (x.id, x.name))
|
||||||
|
|
||||||
for participant in participants:
|
for participant in participants:
|
||||||
results = groupResults.results[participant]
|
results = groupResults.results[participant]
|
||||||
|
|
||||||
def mapResultColumn(result: types.SingleParticipantResult):
|
def mapResultColumn(result: types.SingleParticipantResult):
|
||||||
def getPlace(place, placeTo):
|
def getPlace(place, placeTo):
|
||||||
if placeTo is None:
|
if placeTo is None:
|
||||||
return f'{place}.'
|
return f"{place}."
|
||||||
else:
|
else:
|
||||||
return f'{place}.-{placeTo}.'
|
return f"{place}.-{placeTo}."
|
||||||
|
|
||||||
if result is None:
|
if result is None:
|
||||||
return ''
|
return ""
|
||||||
|
|
||||||
placeNative = getPlace(result.placeNative, result.placeNativeTo)
|
placeNative = getPlace(result.placeNative, result.placeNativeTo)
|
||||||
place = getPlace(result.place, result.placeTo)
|
place = getPlace(result.place, result.placeTo)
|
||||||
lineOne = f'{placeNative} ({result.nativeClass})'
|
lineOne = f"{placeNative} ({result.nativeClass})"
|
||||||
lineTwo = f'[{place} in {result.competitionClass}]'
|
lineTwo = f"[{place} in {result.competitionClass}]"
|
||||||
|
|
||||||
lines = [lineOne, lineTwo]
|
lines = [lineOne, lineTwo]
|
||||||
if not result.finalist:
|
if not result.finalist:
|
||||||
lines = ['kein/e Finalist/in'] + lines
|
lines = ["kein/e Finalist/in"] + lines
|
||||||
|
|
||||||
return '\n'.join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
mappedResults = map(mapResultColumn, results)
|
mappedResults = map(mapResultColumn, results)
|
||||||
tableRow = [f'{participant.name} ({participant.id})'] + list(mappedResults)
|
tableRow = [f"{participant.name} ({participant.id})"] + list(mappedResults)
|
||||||
tableData.append(tableRow)
|
tableData.append(tableRow)
|
||||||
|
|
||||||
self.l.log(5, 'table data: %s', pprint.pformat(tableData))
|
self.l.log(5, "table data: %s", pprint.pformat(tableData))
|
||||||
print(tabulate(tableData, headers='firstrow', tablefmt='fancy_grid'))
|
print(tabulate(tableData, headers="firstrow", tablefmt="fancy_grid"))
|
||||||
|
|
||||||
|
|
||||||
def output(self, data: types.State4):
|
def output(self, data: types.State4):
|
||||||
for idx, group in enumerate(data.groups):
|
for idx, group in enumerate(data.groups):
|
||||||
if idx > 0:
|
if idx > 0:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
self.l.debug('Output for group %s', group)
|
self.l.debug("Output for group %s", group)
|
||||||
|
|
||||||
self._outputGroup(group, data.results[group])
|
self._outputGroup(group, data.results[group])
|
||||||
# self.groups = self.worker.collectPersonsInGroups(data)
|
# self.groups = self.worker.collectPersonsInGroups(data)
|
||||||
|
@ -1,12 +1,5 @@
|
|||||||
|
|
||||||
class Person:
|
class Person:
|
||||||
def __init__(
|
def __init__(self, firstName: str, lastName: str, club: str, group: str):
|
||||||
self,
|
|
||||||
firstName: str,
|
|
||||||
lastName: str,
|
|
||||||
club: str,
|
|
||||||
group: str
|
|
||||||
):
|
|
||||||
self.firstName = firstName
|
self.firstName = firstName
|
||||||
self.lastName = lastName
|
self.lastName = lastName
|
||||||
self.club = club
|
self.club = club
|
||||||
@ -17,18 +10,19 @@ class Person:
|
|||||||
False
|
False
|
||||||
|
|
||||||
return (
|
return (
|
||||||
self.firstName == o.firstName and
|
self.firstName == o.firstName
|
||||||
self.lastName == o.lastName and
|
and self.lastName == o.lastName
|
||||||
self.club == o.club and
|
and self.club == o.club
|
||||||
self.group == o.group
|
and self.group == o.group
|
||||||
)
|
)
|
||||||
|
|
||||||
def getTuple(self):
|
def getTuple(self):
|
||||||
return (self.firstName, self.lastName, self.club)
|
return (self.firstName, self.lastName, self.club)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.firstName} {self.lastName} ({self.club}, {self.group})'
|
return f"{self.firstName} {self.lastName} ({self.club}, {self.group})"
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return self.firstName.__hash__() + self.lastName.__hash__() + self.club.__hash__()
|
return (
|
||||||
|
self.firstName.__hash__() + self.lastName.__hash__() + self.club.__hash__()
|
||||||
|
)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import solo_turnier
|
import solo_turnier
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
@ -7,13 +6,14 @@ import re
|
|||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from .types import CSVResultRow as ResultRow
|
from .types import CSVResultRow as ResultRow
|
||||||
|
|
||||||
|
|
||||||
class CSVResultReader:
|
class CSVResultReader:
|
||||||
def __init__(self, fileName: str):
|
def __init__(self, fileName: str):
|
||||||
self.fileName = fileName
|
self.fileName = fileName
|
||||||
self.l = logging.getLogger('solo_turnier.reader.CSVResultReader')
|
self.l = logging.getLogger("solo_turnier.reader.CSVResultReader")
|
||||||
|
|
||||||
def readFile(self):
|
def readFile(self):
|
||||||
with open(self.fileName, 'r') as fp:
|
with open(self.fileName, "r") as fp:
|
||||||
dialect = csv.Sniffer().sniff(fp.read(1024))
|
dialect = csv.Sniffer().sniff(fp.read(1024))
|
||||||
fp.seek(0)
|
fp.seek(0)
|
||||||
|
|
||||||
@ -23,15 +23,12 @@ class CSVResultReader:
|
|||||||
for row in csvReader:
|
for row in csvReader:
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
ret = {
|
ret = {"header": rows[0], "data": rows[1:]}
|
||||||
'header': rows[0],
|
|
||||||
'data': rows[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
self.l.log(5, 'Imported results from allresults.csv file: %s', (ret))
|
self.l.log(5, "Imported results from allresults.csv file: %s", (ret))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def extractResult(self, entries = None) -> list[ResultRow]:
|
def extractResult(self, entries=None) -> list[ResultRow]:
|
||||||
if entries is None:
|
if entries is None:
|
||||||
entries = self.readFile()
|
entries = self.readFile()
|
||||||
|
|
||||||
@ -44,33 +41,28 @@ class CSVResultReader:
|
|||||||
competitionClass=classParser.parseClass(row[3]),
|
competitionClass=classParser.parseClass(row[3]),
|
||||||
dance=row[4],
|
dance=row[4],
|
||||||
id=row[5],
|
id=row[5],
|
||||||
firstName=row[6], lastName=row[7],
|
firstName=row[6],
|
||||||
|
lastName=row[7],
|
||||||
club=row[10],
|
club=row[10],
|
||||||
place=row[12], placeTo=row[13],
|
place=row[12],
|
||||||
|
placeTo=row[13],
|
||||||
group=groupParser.parseClass(row[15]),
|
group=groupParser.parseClass(row[15]),
|
||||||
class_=classParser.parseClass(row[16])
|
class_=classParser.parseClass(row[16]),
|
||||||
)
|
)
|
||||||
self.l.log(5, 'Found row in CSV: %s', result)
|
self.l.log(5, "Found row in CSV: %s", result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
ret = list(map(__processRow, entries['data']))
|
ret = list(map(__processRow, entries["data"]))
|
||||||
|
|
||||||
self.l.log(5, 'Extracted rows from CSV data: %s', ret)
|
self.l.log(5, "Extracted rows from CSV data: %s", ret)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class CSVExtractor:
|
class CSVExtractor:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.l = logging.getLogger('solo_turnier.worker')
|
self.l = logging.getLogger("solo_turnier.worker")
|
||||||
self.__groupMaps = {
|
self.__groupMaps = {"Kinder": "Kin.", "Junioren": "Jun.", "Jugend": "Jug."}
|
||||||
'Kinder': 'Kin.',
|
self.__classMaps = {"Newcomer": "Newc.", "Beginner": "Beg.", "Advanced": "Adv."}
|
||||||
'Junioren': 'Jun.',
|
|
||||||
'Jugend': 'Jug.'
|
|
||||||
}
|
|
||||||
self.__classMaps = {
|
|
||||||
'Newcomer': 'Newc.',
|
|
||||||
'Beginner': 'Beg.',
|
|
||||||
'Advanced': 'Adv.'
|
|
||||||
}
|
|
||||||
|
|
||||||
def __mapGroup(self, group):
|
def __mapGroup(self, group):
|
||||||
return self.__groupMaps.get(group, group)
|
return self.__groupMaps.get(group, group)
|
||||||
@ -87,15 +79,18 @@ class CSVExtractor:
|
|||||||
competitionClass=self.__mapClass(row[3]),
|
competitionClass=self.__mapClass(row[3]),
|
||||||
dance=row[4],
|
dance=row[4],
|
||||||
id=row[5],
|
id=row[5],
|
||||||
firstName=row[6], lastName=row[7],
|
firstName=row[6],
|
||||||
|
lastName=row[7],
|
||||||
club=row[10],
|
club=row[10],
|
||||||
place=row[12], placeTo=row[13],
|
place=row[12],
|
||||||
group=self.__mapGroup(row[15]), class_=self.__mapClass(row[16])
|
placeTo=row[13],
|
||||||
|
group=self.__mapGroup(row[15]),
|
||||||
|
class_=self.__mapClass(row[16]),
|
||||||
)
|
)
|
||||||
ret.append(result)
|
ret.append(result)
|
||||||
self.l.log(5, 'Found row in CSV: %s', result)
|
self.l.log(5, "Found row in CSV: %s", result)
|
||||||
|
|
||||||
for row in imported['data']:
|
for row in imported["data"]:
|
||||||
__processRow(row)
|
__processRow(row)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import solo_turnier.competition_class
|
import solo_turnier.competition_class
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(9))
|
@pytest.fixture(params=range(9))
|
||||||
def fix_pureClass(request):
|
def fix_pureClass(request):
|
||||||
cases = (
|
cases = (
|
||||||
('Newc', 'Newc.'),
|
("Newc", "Newc."),
|
||||||
('Newc.', 'Newc.'),
|
("Newc.", "Newc."),
|
||||||
('Newcomer', 'Newc.'),
|
("Newcomer", "Newc."),
|
||||||
('Beg', 'Beg.'),
|
("Beg", "Beg."),
|
||||||
('Beg.', 'Beg.'),
|
("Beg.", "Beg."),
|
||||||
('Beginner', 'Beg.'),
|
("Beginner", "Beg."),
|
||||||
('Adv', 'Adv.'),
|
("Adv", "Adv."),
|
||||||
('Adv.', 'Adv.'),
|
("Adv.", "Adv."),
|
||||||
('Advanced', 'Adv.'),
|
("Advanced", "Adv."),
|
||||||
)
|
)
|
||||||
return cases[request.param]
|
return cases[request.param]
|
||||||
|
|
||||||
|
|
||||||
def test_pureClassParsing(fix_pureClass):
|
def test_pureClassParsing(fix_pureClass):
|
||||||
className = fix_pureClass[0]
|
className = fix_pureClass[0]
|
||||||
expected = fix_pureClass[1]
|
expected = fix_pureClass[1]
|
||||||
@ -28,39 +30,43 @@ def test_pureClassParsing(fix_pureClass):
|
|||||||
|
|
||||||
assert parser.isPureClass(className)
|
assert parser.isPureClass(className)
|
||||||
|
|
||||||
|
|
||||||
def test_classParsingWithPreview():
|
def test_classParsingWithPreview():
|
||||||
parser = solo_turnier.competition_class.CompetitionClassParser()
|
parser = solo_turnier.competition_class.CompetitionClassParser()
|
||||||
ret = parser.parseClass('Sichtung', True)
|
ret = parser.parseClass("Sichtung", True)
|
||||||
|
|
||||||
assert isinstance(ret, solo_turnier.competition_class.CompetitionClass)
|
assert isinstance(ret, solo_turnier.competition_class.CompetitionClass)
|
||||||
assert str(ret) == 'Sichtung'
|
assert str(ret) == "Sichtung"
|
||||||
|
|
||||||
|
assert parser.isPureClass("Sichtung", True)
|
||||||
|
|
||||||
assert parser.isPureClass('Sichtung', True)
|
|
||||||
|
|
||||||
def test_classParsingInvalidPreview():
|
def test_classParsingInvalidPreview():
|
||||||
parser = solo_turnier.competition_class.CompetitionClassParser()
|
parser = solo_turnier.competition_class.CompetitionClassParser()
|
||||||
try:
|
try:
|
||||||
parser.parseClass('Sichtung')
|
parser.parseClass("Sichtung")
|
||||||
assert False
|
assert False
|
||||||
except:
|
except:
|
||||||
assert True
|
assert True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parser.isPureClass('Sichtung')
|
parser.isPureClass("Sichtung")
|
||||||
assert False
|
assert False
|
||||||
except:
|
except:
|
||||||
assert True
|
assert True
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(4))
|
@pytest.fixture(params=range(4))
|
||||||
def fix_combinedClass(request):
|
def fix_combinedClass(request):
|
||||||
cases = (
|
cases = (
|
||||||
('Newc/Beg', 'Newc./Beg.'),
|
("Newc/Beg", "Newc./Beg."),
|
||||||
('Newc./Beg', 'Newc./Beg.'),
|
("Newc./Beg", "Newc./Beg."),
|
||||||
('Beginner/Adv', 'Beg./Adv.'),
|
("Beginner/Adv", "Beg./Adv."),
|
||||||
('Beg/Adv', 'Beg./Adv.'),
|
("Beg/Adv", "Beg./Adv."),
|
||||||
)
|
)
|
||||||
return cases[request.param]
|
return cases[request.param]
|
||||||
|
|
||||||
|
|
||||||
def test_combinedClassParsing(fix_combinedClass):
|
def test_combinedClassParsing(fix_combinedClass):
|
||||||
className = fix_combinedClass[0]
|
className = fix_combinedClass[0]
|
||||||
expected = fix_combinedClass[1]
|
expected = fix_combinedClass[1]
|
||||||
|
@ -2,12 +2,13 @@ import solo_turnier.reader
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
def test_import():
|
def test_import():
|
||||||
fileName = os.path.join(os.path.dirname(__file__), 'reader', 'test.csv')
|
fileName = os.path.join(os.path.dirname(__file__), "reader", "test.csv")
|
||||||
reader = solo_turnier.reader.CSVResultReader(fileName)
|
reader = solo_turnier.reader.CSVResultReader(fileName)
|
||||||
ret = reader.readFile()
|
ret = reader.readFile()
|
||||||
|
|
||||||
with open(os.path.join(os.path.dirname(__file__), 'reader', 'expected.json')) as fp:
|
with open(os.path.join(os.path.dirname(__file__), "reader", "expected.json")) as fp:
|
||||||
expected = json.load(fp)
|
expected = json.load(fp)
|
||||||
|
|
||||||
assert ret == expected
|
assert ret == expected
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import solo_turnier.group
|
import solo_turnier.group
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(9))
|
@pytest.fixture(params=range(9))
|
||||||
def fix_pureClass(request):
|
def fix_pureClass(request):
|
||||||
cases = (
|
cases = (
|
||||||
('Kin', 'Kin.'),
|
("Kin", "Kin."),
|
||||||
('Kin.', 'Kin.'),
|
("Kin.", "Kin."),
|
||||||
('Kinder', 'Kin.'),
|
("Kinder", "Kin."),
|
||||||
('Jun', 'Jun.'),
|
("Jun", "Jun."),
|
||||||
('Jun.', 'Jun.'),
|
("Jun.", "Jun."),
|
||||||
('Junioren', 'Jun.'),
|
("Junioren", "Jun."),
|
||||||
('Jug', 'Jug.'),
|
("Jug", "Jug."),
|
||||||
('Jug.', 'Jug.'),
|
("Jug.", "Jug."),
|
||||||
('Jugend', 'Jug.'),
|
("Jugend", "Jug."),
|
||||||
)
|
)
|
||||||
return cases[request.param]
|
return cases[request.param]
|
||||||
|
|
||||||
|
|
||||||
def test_pureClassParsing(fix_pureClass):
|
def test_pureClassParsing(fix_pureClass):
|
||||||
className = fix_pureClass[0]
|
className = fix_pureClass[0]
|
||||||
expected = fix_pureClass[1]
|
expected = fix_pureClass[1]
|
||||||
@ -28,16 +30,18 @@ def test_pureClassParsing(fix_pureClass):
|
|||||||
|
|
||||||
assert parser.isPureClass(className)
|
assert parser.isPureClass(className)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(4))
|
@pytest.fixture(params=range(4))
|
||||||
def fix_combinedClass(request):
|
def fix_combinedClass(request):
|
||||||
cases = (
|
cases = (
|
||||||
('Kin/Jun', 'Kin./Jun.'),
|
("Kin/Jun", "Kin./Jun."),
|
||||||
('Kin./Jun', 'Kin./Jun.'),
|
("Kin./Jun", "Kin./Jun."),
|
||||||
('Junioren/Jug', 'Jun./Jug.'),
|
("Junioren/Jug", "Jun./Jug."),
|
||||||
('Jun/Jug', 'Jun./Jug.'),
|
("Jun/Jug", "Jun./Jug."),
|
||||||
)
|
)
|
||||||
return cases[request.param]
|
return cases[request.param]
|
||||||
|
|
||||||
|
|
||||||
def test_combinedClassParsing(fix_combinedClass):
|
def test_combinedClassParsing(fix_combinedClass):
|
||||||
className = fix_combinedClass[0]
|
className = fix_combinedClass[0]
|
||||||
expected = fix_combinedClass[1]
|
expected = fix_combinedClass[1]
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import solo_turnier.html_locator
|
import solo_turnier.html_locator
|
||||||
|
|
||||||
|
|
||||||
def test_fetchLocationCandidates():
|
def test_fetchLocationCandidates():
|
||||||
folder = os.path.join(os.path.dirname(__file__), 'html_locator', 'export')
|
folder = os.path.join(os.path.dirname(__file__), "html_locator", "export")
|
||||||
relFolder = os.path.relpath(folder)
|
relFolder = os.path.relpath(folder)
|
||||||
|
|
||||||
locator = solo_turnier.html_locator.HtmlLocator()
|
locator = solo_turnier.html_locator.HtmlLocator()
|
||||||
candidates = locator.findCandidates(relFolder)
|
candidates = locator.findCandidates(relFolder)
|
||||||
|
|
||||||
expected = [
|
expected = [
|
||||||
'solo_turnier/tests/html_locator/export/2-bar/erg.htm',
|
"solo_turnier/tests/html_locator/export/2-bar/erg.htm",
|
||||||
'solo_turnier/tests/html_locator/export/3-baz/erg.htm',
|
"solo_turnier/tests/html_locator/export/3-baz/erg.htm",
|
||||||
'solo_turnier/tests/html_locator/export/3-baz/subfolder/4-baz/erg.htm'
|
"solo_turnier/tests/html_locator/export/3-baz/subfolder/4-baz/erg.htm",
|
||||||
]
|
]
|
||||||
assert set(candidates) == set(expected)
|
assert set(candidates) == set(expected)
|
||||||
|
@ -4,20 +4,22 @@ import json
|
|||||||
|
|
||||||
import solo_turnier.html_parser
|
import solo_turnier.html_parser
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=range(2))
|
|
||||||
def dataProviderHtmlParser(request):
|
|
||||||
variant = str(request.param+1)
|
|
||||||
dir = os.path.join(os.path.dirname(__file__), 'html_parser', 'erg', variant)
|
|
||||||
htmlFile = os.path.join(dir, 'erg.htm')
|
|
||||||
jsonFile = os.path.join(dir, 'expected.json')
|
|
||||||
|
|
||||||
with open(htmlFile, 'r') as fp:
|
@pytest.fixture(scope="module", params=range(2))
|
||||||
|
def dataProviderHtmlParser(request):
|
||||||
|
variant = str(request.param + 1)
|
||||||
|
dir = os.path.join(os.path.dirname(__file__), "html_parser", "erg", variant)
|
||||||
|
htmlFile = os.path.join(dir, "erg.htm")
|
||||||
|
jsonFile = os.path.join(dir, "expected.json")
|
||||||
|
|
||||||
|
with open(htmlFile, "r") as fp:
|
||||||
html = fp.read()
|
html = fp.read()
|
||||||
with open(jsonFile, 'r') as fp:
|
with open(jsonFile, "r") as fp:
|
||||||
jsonContent = json.load(fp)
|
jsonContent = json.load(fp)
|
||||||
|
|
||||||
return (html, jsonContent)
|
return (html, jsonContent)
|
||||||
|
|
||||||
|
|
||||||
def test_extractDataFromHtml(dataProviderHtmlParser):
|
def test_extractDataFromHtml(dataProviderHtmlParser):
|
||||||
htmlString = dataProviderHtmlParser[0]
|
htmlString = dataProviderHtmlParser[0]
|
||||||
expected = dataProviderHtmlParser[1]
|
expected = dataProviderHtmlParser[1]
|
||||||
@ -29,67 +31,71 @@ def test_extractDataFromHtml(dataProviderHtmlParser):
|
|||||||
for i in actualResult.participants:
|
for i in actualResult.participants:
|
||||||
participants[i] = actualResult.participants[i].__dict__
|
participants[i] = actualResult.participants[i].__dict__
|
||||||
|
|
||||||
assert actualResult.title == expected['title']
|
assert actualResult.title == expected["title"]
|
||||||
assert participants == expected['participants']
|
assert participants == expected["participants"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(6))
|
@pytest.fixture(params=range(6))
|
||||||
def fixture_guessDataFromTitle(request):
|
def fixture_guessDataFromTitle(request):
|
||||||
cases = {
|
cases = {
|
||||||
'09.07.2022 - ETW, Solos Jun. Beginner Jive': {
|
"09.07.2022 - ETW, Solos Jun. Beginner Jive": {
|
||||||
'class_': 'Beg.',
|
"class_": "Beg.",
|
||||||
'dance': 'Jive',
|
"dance": "Jive",
|
||||||
'group': 'Jun.'
|
"group": "Jun.",
|
||||||
},
|
},
|
||||||
'09.07.2022 - ETW, Solos Jun. Newc./Beg. Rumba': {
|
"09.07.2022 - ETW, Solos Jun. Newc./Beg. Rumba": {
|
||||||
'class_': 'Newc./Beg.',
|
"class_": "Newc./Beg.",
|
||||||
'dance': 'Rumba',
|
"dance": "Rumba",
|
||||||
'group': 'Jun.'
|
"group": "Jun.",
|
||||||
},
|
},
|
||||||
'09.07.2022 - ETW, Solos Kin./Jun. Beginner Cha Cha': {
|
"09.07.2022 - ETW, Solos Kin./Jun. Beginner Cha Cha": {
|
||||||
'class_': 'Beg.',
|
"class_": "Beg.",
|
||||||
'dance': 'Cha Cha',
|
"dance": "Cha Cha",
|
||||||
'group': 'Kin./Jun.'
|
"group": "Kin./Jun.",
|
||||||
},
|
},
|
||||||
'09.07.2022 - ETW, Solos Kin. Newcomer Samba': {
|
"09.07.2022 - ETW, Solos Kin. Newcomer Samba": {
|
||||||
'class_': 'Newc.',
|
"class_": "Newc.",
|
||||||
'dance': 'Samba',
|
"dance": "Samba",
|
||||||
'group': 'Kin.'
|
"group": "Kin.",
|
||||||
},
|
},
|
||||||
'09.07.2022 - ETW, Solos Jugend Beg./Adv. Wiener Walzer': {
|
"09.07.2022 - ETW, Solos Jugend Beg./Adv. Wiener Walzer": {
|
||||||
'class_': 'Beg./Adv.',
|
"class_": "Beg./Adv.",
|
||||||
'dance': 'Wiener Walzer',
|
"dance": "Wiener Walzer",
|
||||||
'group': 'Jug.'
|
"group": "Jug.",
|
||||||
},
|
},
|
||||||
'09.07.2022 - ETW, Solos Jugend Sichtung Wiener Walzer': {
|
"09.07.2022 - ETW, Solos Jugend Sichtung Wiener Walzer": {
|
||||||
'class_': 'Sichtung',
|
"class_": "Sichtung",
|
||||||
'dance': 'Wiener Walzer',
|
"dance": "Wiener Walzer",
|
||||||
'group': 'Jug.'
|
"group": "Jug.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
keys = list(cases.keys())
|
keys = list(cases.keys())
|
||||||
key = keys[request.param]
|
key = keys[request.param]
|
||||||
return (key, cases[key])
|
return (key, cases[key])
|
||||||
|
|
||||||
|
|
||||||
def test_guessDataFromTitle(fixture_guessDataFromTitle):
|
def test_guessDataFromTitle(fixture_guessDataFromTitle):
|
||||||
parser = solo_turnier.html_parser.HtmlParser('')
|
parser = solo_turnier.html_parser.HtmlParser("")
|
||||||
ret = parser.guessDataFromHtmlTitle(fixture_guessDataFromTitle[0])
|
ret = parser.guessDataFromHtmlTitle(fixture_guessDataFromTitle[0])
|
||||||
|
|
||||||
assert ret == fixture_guessDataFromTitle[1]
|
assert ret == fixture_guessDataFromTitle[1]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(1))
|
@pytest.fixture(params=range(1))
|
||||||
def fixture_parsePreparationResult(request):
|
def fixture_parsePreparationResult(request):
|
||||||
variant = str(request.param+1)
|
variant = str(request.param + 1)
|
||||||
dir = os.path.join(os.path.dirname(__file__), 'html_parser', 'tabges', variant)
|
dir = os.path.join(os.path.dirname(__file__), "html_parser", "tabges", variant)
|
||||||
htmlFile = os.path.join(dir, 'tabges.htm')
|
htmlFile = os.path.join(dir, "tabges.htm")
|
||||||
jsonFile = os.path.join(dir, 'expected.json')
|
jsonFile = os.path.join(dir, "expected.json")
|
||||||
|
|
||||||
with open(htmlFile, 'r') as fp:
|
with open(htmlFile, "r") as fp:
|
||||||
html = fp.read()
|
html = fp.read()
|
||||||
with open(jsonFile, 'r') as fp:
|
with open(jsonFile, "r") as fp:
|
||||||
jsonContent = json.load(fp)
|
jsonContent = json.load(fp)
|
||||||
|
|
||||||
return (html, jsonContent)
|
return (html, jsonContent)
|
||||||
|
|
||||||
|
|
||||||
def test_parsePreparationResult(fixture_parsePreparationResult):
|
def test_parsePreparationResult(fixture_parsePreparationResult):
|
||||||
html = fixture_parsePreparationResult[0]
|
html = fixture_parsePreparationResult[0]
|
||||||
jsonContent = fixture_parsePreparationResult[1]
|
jsonContent = fixture_parsePreparationResult[1]
|
||||||
@ -99,25 +105,27 @@ def test_parsePreparationResult(fixture_parsePreparationResult):
|
|||||||
|
|
||||||
assert ret == jsonContent
|
assert ret == jsonContent
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(1))
|
@pytest.fixture(params=range(1))
|
||||||
def fixture_cleanPreparationImport(request):
|
def fixture_cleanPreparationImport(request):
|
||||||
variant = str(request.param+1)
|
variant = str(request.param + 1)
|
||||||
dir = os.path.join(os.path.dirname(__file__), 'html_parser', 'tabges', variant)
|
dir = os.path.join(os.path.dirname(__file__), "html_parser", "tabges", variant)
|
||||||
srcFile = os.path.join(dir, 'expected.json')
|
srcFile = os.path.join(dir, "expected.json")
|
||||||
expectedFile = os.path.join(dir, 'cleaned.json')
|
expectedFile = os.path.join(dir, "cleaned.json")
|
||||||
|
|
||||||
with open(srcFile, 'r') as fp:
|
with open(srcFile, "r") as fp:
|
||||||
source = json.load(fp)
|
source = json.load(fp)
|
||||||
with open(expectedFile, 'r') as fp:
|
with open(expectedFile, "r") as fp:
|
||||||
expected = json.load(fp)
|
expected = json.load(fp)
|
||||||
|
|
||||||
return (source, expected)
|
return (source, expected)
|
||||||
|
|
||||||
|
|
||||||
def test_cleanPreparationImport(fixture_cleanPreparationImport):
|
def test_cleanPreparationImport(fixture_cleanPreparationImport):
|
||||||
src = fixture_cleanPreparationImport[0]
|
src = fixture_cleanPreparationImport[0]
|
||||||
expected = fixture_cleanPreparationImport[1]
|
expected = fixture_cleanPreparationImport[1]
|
||||||
|
|
||||||
parser = solo_turnier.html_parser.HtmlParser('')
|
parser = solo_turnier.html_parser.HtmlParser("")
|
||||||
parser.cleanPreparationRoundImport(src)
|
parser.cleanPreparationRoundImport(src)
|
||||||
|
|
||||||
assert src == expected
|
assert src == expected
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import solo_turnier.types as types
|
import solo_turnier.types as types
|
||||||
|
|
||||||
|
|
||||||
def test_HtmlPreviewParticipant_eq():
|
def test_HtmlPreviewParticipant_eq():
|
||||||
name = 'Max Mustermann'
|
name = "Max Mustermann"
|
||||||
id = 123
|
id = 123
|
||||||
group = 'Kin'
|
group = "Kin"
|
||||||
participant = types.HtmlPreviewParticipant(name, id, group)
|
participant = types.HtmlPreviewParticipant(name, id, group)
|
||||||
|
|
||||||
l = []
|
l = []
|
||||||
@ -13,6 +14,6 @@ def test_HtmlPreviewParticipant_eq():
|
|||||||
assert participant in l
|
assert participant in l
|
||||||
|
|
||||||
assert types.HtmlPreviewParticipant(name, id, group) in l
|
assert types.HtmlPreviewParticipant(name, id, group) in l
|
||||||
assert types.HtmlPreviewParticipant('Maxime Musterfrau', id, group) not in l
|
assert types.HtmlPreviewParticipant("Maxime Musterfrau", id, group) not in l
|
||||||
assert types.HtmlPreviewParticipant(name, 234, group) not in l
|
assert types.HtmlPreviewParticipant(name, 234, group) not in l
|
||||||
assert types.HtmlPreviewParticipant(name, id, 'Jun') not in l
|
assert types.HtmlPreviewParticipant(name, id, "Jun") not in l
|
||||||
|
@ -4,178 +4,298 @@ import json
|
|||||||
import pytest
|
import pytest
|
||||||
import pytest_mock
|
import pytest_mock
|
||||||
|
|
||||||
|
|
||||||
def __importJSONData(name):
|
def __importJSONData(name):
|
||||||
path = os.path.join(os.path.dirname(__file__), 'worker', name)
|
path = os.path.join(os.path.dirname(__file__), "worker", name)
|
||||||
with open(path, 'r') as fp:
|
with open(path, "r") as fp:
|
||||||
return json.load(fp)
|
return json.load(fp)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def fixture_csvExtractor():
|
def fixture_csvExtractor():
|
||||||
data = __importJSONData('csvImport.json')
|
data = __importJSONData("csvImport.json")
|
||||||
expected = __importJSONData('csvImportResult.json')
|
expected = __importJSONData("csvImportResult.json")
|
||||||
return (data, expected)
|
return (data, expected)
|
||||||
|
|
||||||
|
|
||||||
def test_csvExtractor(fixture_csvExtractor):
|
def test_csvExtractor(fixture_csvExtractor):
|
||||||
extractor = worker.CSVExtractor()
|
extractor = worker.CSVExtractor()
|
||||||
mapped = extractor.mapCSVImport(fixture_csvExtractor[0])
|
mapped = extractor.mapCSVImport(fixture_csvExtractor[0])
|
||||||
|
|
||||||
assert len(mapped) == len(fixture_csvExtractor[1])
|
assert len(mapped) == len(fixture_csvExtractor[1])
|
||||||
for i,elem in enumerate(fixture_csvExtractor[1]):
|
for i, elem in enumerate(fixture_csvExtractor[1]):
|
||||||
assert mapped[i].__dict__ == elem
|
assert mapped[i].__dict__ == elem
|
||||||
|
|
||||||
|
|
||||||
def test_extractPersonFromRow():
|
def test_extractPersonFromRow():
|
||||||
row = worker.ResultRow('Max', 'Mustermann', 'TSC Entenhausen', '2', 'Kin', 'Adv.', 'Rumba', '2', '2', 'Kin.', 'Beg./Adv.')
|
row = worker.ResultRow(
|
||||||
|
"Max",
|
||||||
|
"Mustermann",
|
||||||
|
"TSC Entenhausen",
|
||||||
|
"2",
|
||||||
|
"Kin",
|
||||||
|
"Adv.",
|
||||||
|
"Rumba",
|
||||||
|
"2",
|
||||||
|
"2",
|
||||||
|
"Kin.",
|
||||||
|
"Beg./Adv.",
|
||||||
|
)
|
||||||
person = worker.ResultPerson.extractFromResultRow(row)
|
person = worker.ResultPerson.extractFromResultRow(row)
|
||||||
expected = {
|
expected = {
|
||||||
'firstName': 'Max',
|
"firstName": "Max",
|
||||||
'lastName': 'Mustermann',
|
"lastName": "Mustermann",
|
||||||
'name': 'Max Mustermann',
|
"name": "Max Mustermann",
|
||||||
'club': 'TSC Entenhausen',
|
"club": "TSC Entenhausen",
|
||||||
'id': None,
|
"id": None,
|
||||||
'group': None
|
"group": None,
|
||||||
}
|
}
|
||||||
assert person.__dict__ == expected
|
assert person.__dict__ == expected
|
||||||
|
|
||||||
|
|
||||||
def test_extractCompetitionFromRow():
|
def test_extractCompetitionFromRow():
|
||||||
row = worker.ResultRow('Max', 'Mustermann', 'TSC Entenhausen', '2', 'Kin', 'Adv.', 'Rumba', '2', '2', 'Kin.', 'Beg./Adv.')
|
row = worker.ResultRow(
|
||||||
|
"Max",
|
||||||
|
"Mustermann",
|
||||||
|
"TSC Entenhausen",
|
||||||
|
"2",
|
||||||
|
"Kin",
|
||||||
|
"Adv.",
|
||||||
|
"Rumba",
|
||||||
|
"2",
|
||||||
|
"2",
|
||||||
|
"Kin.",
|
||||||
|
"Beg./Adv.",
|
||||||
|
)
|
||||||
competition = worker.CompetitionResult.extractFromResultRow(row)
|
competition = worker.CompetitionResult.extractFromResultRow(row)
|
||||||
expected = {
|
expected = {
|
||||||
'dance': 'Rumba',
|
"dance": "Rumba",
|
||||||
'class_': 'Adv.',
|
"class_": "Adv.",
|
||||||
'group': 'Kin',
|
"group": "Kin",
|
||||||
'place': '2',
|
"place": "2",
|
||||||
'placeTo': '2',
|
"placeTo": "2",
|
||||||
'id': 2,
|
"id": 2,
|
||||||
'finalist': None,
|
"finalist": None,
|
||||||
'competitionGroup': 'Kin.',
|
"competitionGroup": "Kin.",
|
||||||
'competitionClass': 'Beg./Adv.'
|
"competitionClass": "Beg./Adv.",
|
||||||
}
|
}
|
||||||
assert competition.__dict__ == expected
|
assert competition.__dict__ == expected
|
||||||
|
|
||||||
|
|
||||||
def test_combineRowsByPerson():
|
def test_combineRowsByPerson():
|
||||||
rows = [
|
rows = [
|
||||||
worker.ResultRow('Max', 'Mustermann', 'TSC Entenhausen', '2', 'Kin', 'Adv.', 'Cha Cha', '-', '-', 'Kin.', 'Adv.'),
|
worker.ResultRow(
|
||||||
worker.ResultRow('Max', 'Mustermann', 'TSC Entenhausen', '2', 'Kin', 'Adv.', 'Rumba', '2', '2', 'Kin.', 'Adv.'),
|
"Max",
|
||||||
worker.ResultRow('Max', 'Mustermann', 'TSC Entenhausen', '2', 'Kin', 'Beg.', 'Jive', '1', '1', 'Kin.', 'Beg.'),
|
"Mustermann",
|
||||||
worker.ResultRow('Maxime', 'Musterfrau', '1. SC Entenhausen', '1', 'Kin', 'Adv.', 'Rumba', '1', '1', 'Kin.', 'Adv.')
|
"TSC Entenhausen",
|
||||||
|
"2",
|
||||||
|
"Kin",
|
||||||
|
"Adv.",
|
||||||
|
"Cha Cha",
|
||||||
|
"-",
|
||||||
|
"-",
|
||||||
|
"Kin.",
|
||||||
|
"Adv.",
|
||||||
|
),
|
||||||
|
worker.ResultRow(
|
||||||
|
"Max",
|
||||||
|
"Mustermann",
|
||||||
|
"TSC Entenhausen",
|
||||||
|
"2",
|
||||||
|
"Kin",
|
||||||
|
"Adv.",
|
||||||
|
"Rumba",
|
||||||
|
"2",
|
||||||
|
"2",
|
||||||
|
"Kin.",
|
||||||
|
"Adv.",
|
||||||
|
),
|
||||||
|
worker.ResultRow(
|
||||||
|
"Max",
|
||||||
|
"Mustermann",
|
||||||
|
"TSC Entenhausen",
|
||||||
|
"2",
|
||||||
|
"Kin",
|
||||||
|
"Beg.",
|
||||||
|
"Jive",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
"Kin.",
|
||||||
|
"Beg.",
|
||||||
|
),
|
||||||
|
worker.ResultRow(
|
||||||
|
"Maxime",
|
||||||
|
"Musterfrau",
|
||||||
|
"1. SC Entenhausen",
|
||||||
|
"1",
|
||||||
|
"Kin",
|
||||||
|
"Adv.",
|
||||||
|
"Rumba",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
"Kin.",
|
||||||
|
"Adv.",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
result = dataWorker.combineRowsByPerson(rows)
|
result = dataWorker.combineRowsByPerson(rows)
|
||||||
expected = {
|
expected = {
|
||||||
worker.ResultPerson('Max', 'Mustermann', 'TSC Entenhausen'): [
|
worker.ResultPerson("Max", "Mustermann", "TSC Entenhausen"): [
|
||||||
worker.CompetitionResult('Rumba', 'Kin', 'Adv.', '2', '2', '2', 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Kin', 'Beg.', '1', '1', '2', 'Kin.', 'Beg.')
|
"Rumba", "Kin", "Adv.", "2", "2", "2", "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin", "Beg.", "1", "1", "2", "Kin.", "Beg."
|
||||||
|
),
|
||||||
|
],
|
||||||
|
worker.ResultPerson("Maxime", "Musterfrau", "1. SC Entenhausen"): [
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Rumba", "Kin", "Adv.", "1", "1", "1", "Kin.", "Adv."
|
||||||
|
)
|
||||||
],
|
],
|
||||||
worker.ResultPerson('Maxime', 'Musterfrau', '1. SC Entenhausen'): [
|
|
||||||
worker.CompetitionResult('Rumba', 'Kin', 'Adv.', '1', '1', '1', 'Kin.', 'Adv.')
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
assert result == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
def test_checkUniqueIds_True():
|
def test_checkUniqueIds_True():
|
||||||
person1 = worker.ResultPerson('Max', 'Mustermann', 'TSC Entenhausen')
|
person1 = worker.ResultPerson("Max", "Mustermann", "TSC Entenhausen")
|
||||||
person2 = worker.ResultPerson('Maxime', 'Musterfrau', '1. SC Entenhausen')
|
person2 = worker.ResultPerson("Maxime", "Musterfrau", "1. SC Entenhausen")
|
||||||
data = {
|
data = {
|
||||||
person1: [
|
person1: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Kin', 'Beg.', '1', '1', 2, 'Kin.', 'Beg.')
|
"Rumba", "Kin", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin", "Beg.", "1", "1", 2, "Kin.", "Beg."
|
||||||
|
),
|
||||||
],
|
],
|
||||||
person2: [
|
person2: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin', 'Adv.', '1', '1', 1, 'Kin.', 'Adv.')
|
worker.CompetitionResult(
|
||||||
]
|
"Rumba", "Kin", "Adv.", "1", "1", 1, "Kin.", "Adv."
|
||||||
|
)
|
||||||
|
],
|
||||||
}
|
}
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
assert dataWorker.checkUniqueIds(data) == True
|
assert dataWorker.checkUniqueIds(data) == True
|
||||||
assert person1.id == 2
|
assert person1.id == 2
|
||||||
assert person2.id == 1
|
assert person2.id == 1
|
||||||
|
|
||||||
|
|
||||||
def test_checkUniqueIds_False():
|
def test_checkUniqueIds_False():
|
||||||
person1 = worker.ResultPerson('Max', 'Mustermann', 'TSC Entenhausen')
|
person1 = worker.ResultPerson("Max", "Mustermann", "TSC Entenhausen")
|
||||||
person2 = worker.ResultPerson('Maxime', 'Musterfrau', '1. SC Entenhausen')
|
person2 = worker.ResultPerson("Maxime", "Musterfrau", "1. SC Entenhausen")
|
||||||
data = {
|
data = {
|
||||||
person1: [
|
person1: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Kin', 'Beg.', '1', '1', 3, 'Kin.', 'Beg.')
|
"Rumba", "Kin", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin", "Beg.", "1", "1", 3, "Kin.", "Beg."
|
||||||
|
),
|
||||||
],
|
],
|
||||||
person2: [
|
person2: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin', 'Adv.', '1', '1', 1, 'Kin.', 'Adv.')
|
worker.CompetitionResult(
|
||||||
]
|
"Rumba", "Kin", "Adv.", "1", "1", 1, "Kin.", "Adv."
|
||||||
|
)
|
||||||
|
],
|
||||||
}
|
}
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
assert dataWorker.checkUniqueIds(data) == False
|
assert dataWorker.checkUniqueIds(data) == False
|
||||||
assert person1.id == None
|
assert person1.id == None
|
||||||
assert person2.id == 1
|
assert person2.id == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(5))
|
@pytest.fixture(params=range(5))
|
||||||
def fixture_consolidateGroups(request):
|
def fixture_consolidateGroups(request):
|
||||||
person1 = worker.ResultPerson('Max 1', 'Mustermann', 'TSC Entenhausen')
|
person1 = worker.ResultPerson("Max 1", "Mustermann", "TSC Entenhausen")
|
||||||
person2 = worker.ResultPerson('Max 2', 'Mustermann', 'TSC Entenhausen')
|
person2 = worker.ResultPerson("Max 2", "Mustermann", "TSC Entenhausen")
|
||||||
person3 = worker.ResultPerson('Max 3', 'Mustermann', 'TSC Entenhausen')
|
person3 = worker.ResultPerson("Max 3", "Mustermann", "TSC Entenhausen")
|
||||||
person4 = worker.ResultPerson('Max 4', 'Mustermann', 'TSC Entenhausen')
|
person4 = worker.ResultPerson("Max 4", "Mustermann", "TSC Entenhausen")
|
||||||
# persons = (person1, person2, person3, person4)
|
# persons = (person1, person2, person3, person4)
|
||||||
|
|
||||||
dict1 = {
|
dict1 = {
|
||||||
person1: [
|
person1: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Kin.', 'Beg.', '1', '1', 3, 'Kin.', 'Beg.')
|
"Rumba", "Kin.", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin.", "Beg.", "1", "1", 3, "Kin.", "Beg."
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
dict2 = {
|
dict2 = {
|
||||||
person2: [
|
person2: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Kin./Jun.', 'Beg.', '1', '1', 3, 'Kin./Jun.', 'Beg.')
|
"Rumba", "Kin.", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin./Jun.", "Beg.", "1", "1", 3, "Kin./Jun.", "Beg."
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
dict3 = {
|
dict3 = {
|
||||||
person3: [
|
person3: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.')
|
worker.CompetitionResult(
|
||||||
|
"Rumba", "Kin.", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
dict4 = {
|
dict4 = {
|
||||||
person4: [
|
person4: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin./Jun.', 'Adv.', '2', '2', 2, 'Kin./Jun.', 'Adv.')
|
worker.CompetitionResult(
|
||||||
|
"Rumba", "Kin./Jun.", "Adv.", "2", "2", 2, "Kin./Jun.", "Adv."
|
||||||
|
)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
dict5 = {
|
dict5 = {
|
||||||
person4: [
|
person4: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin./Jun.', 'Adv.', '2', '2', 2, 'Kin./Jun.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Cha Cha', 'Jun./Jug.', 'Beg.', '3', '4', 2, 'Jun./Jug.', 'Beg.')
|
"Rumba", "Kin./Jun.", "Adv.", "2", "2", 2, "Kin./Jun.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Cha Cha", "Jun./Jug.", "Beg.", "3", "4", 2, "Jun./Jug.", "Beg."
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
cases = (
|
cases = (
|
||||||
(dict1|dict3, (True, False), {}),
|
(dict1 | dict3, (True, False), {}),
|
||||||
(dict1|dict2|dict3, (True, True), {}),
|
(dict1 | dict2 | dict3, (True, True), {}),
|
||||||
(dict4, (False, False), {person4: 'Kin./Jun.'}),
|
(dict4, (False, False), {person4: "Kin./Jun."}),
|
||||||
(dict1|dict2|dict3|dict4, (False, True), {person4: 'Kin./Jun.'}),
|
(dict1 | dict2 | dict3 | dict4, (False, True), {person4: "Kin./Jun."}),
|
||||||
(dict5, (True, True), {person4: 'Jun.'}),
|
(dict5, (True, True), {person4: "Jun."}),
|
||||||
)
|
)
|
||||||
return cases[request.param]
|
return cases[request.param]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(2))
|
@pytest.fixture(params=range(2))
|
||||||
def fixture_consolidateGroups_fail(request, fixture_consolidateGroups):
|
def fixture_consolidateGroups_fail(request, fixture_consolidateGroups):
|
||||||
person = worker.ResultPerson('Max 5', 'Mustermann', 'TSC Entenhausen')
|
person = worker.ResultPerson("Max 5", "Mustermann", "TSC Entenhausen")
|
||||||
|
|
||||||
dict1 = {
|
dict1 = {
|
||||||
person: [
|
person: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Jun.', 'Beg.', '1', '1', 3, 'Jun.', 'Adv.')
|
"Rumba", "Kin.", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Jun.", "Beg.", "1", "1", 3, "Jun.", "Adv."
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dict2 = {
|
dict2 = {
|
||||||
person: [
|
person: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Jive', 'Hgr', 'Beg.', '1', '1', 3, 'Hgr', 'Adv.')
|
"Rumba", "Kin.", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult("Jive", "Hgr", "Beg.", "1", "1", 3, "Hgr", "Adv."),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
cases = (
|
cases = (dict1 | fixture_consolidateGroups[0], dict2 | fixture_consolidateGroups[0])
|
||||||
dict1 | fixture_consolidateGroups[0],
|
|
||||||
dict2 | fixture_consolidateGroups[0]
|
|
||||||
)
|
|
||||||
return cases[request.param]
|
return cases[request.param]
|
||||||
|
|
||||||
|
|
||||||
def test_consolidateGroups(fixture_consolidateGroups):
|
def test_consolidateGroups(fixture_consolidateGroups):
|
||||||
data = fixture_consolidateGroups[0]
|
data = fixture_consolidateGroups[0]
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
@ -183,7 +303,8 @@ def test_consolidateGroups(fixture_consolidateGroups):
|
|||||||
assert dataWorker.consolidateGroups(data) == fixture_consolidateGroups[1]
|
assert dataWorker.consolidateGroups(data) == fixture_consolidateGroups[1]
|
||||||
|
|
||||||
for person in data:
|
for person in data:
|
||||||
assert person.group == fixture_consolidateGroups[2].get(person, 'Kin.')
|
assert person.group == fixture_consolidateGroups[2].get(person, "Kin.")
|
||||||
|
|
||||||
|
|
||||||
def test_consolidateGroups_failing(fixture_consolidateGroups_fail):
|
def test_consolidateGroups_failing(fixture_consolidateGroups_fail):
|
||||||
data = fixture_consolidateGroups_fail
|
data = fixture_consolidateGroups_fail
|
||||||
@ -192,105 +313,143 @@ def test_consolidateGroups_failing(fixture_consolidateGroups_fail):
|
|||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
dataWorker.consolidateGroups(data)
|
dataWorker.consolidateGroups(data)
|
||||||
|
|
||||||
|
|
||||||
def test_createHtmlLUT(mocker):
|
def test_createHtmlLUT(mocker):
|
||||||
mock = mocker.patch('solo_turnier.html_parser.HtmlParser.guessDataFromHtmlTitle')
|
mock = mocker.patch("solo_turnier.html_parser.HtmlParser.guessDataFromHtmlTitle")
|
||||||
mock.side_effect= [
|
mock.side_effect = [
|
||||||
{'group': 'group1', 'class_': 'class1', 'dance': 'dance1'},
|
{"group": "group1", "class_": "class1", "dance": "dance1"},
|
||||||
{'group': 'group2', 'class_': 'class2', 'dance': 'dance2'},
|
{"group": "group2", "class_": "class2", "dance": "dance2"},
|
||||||
{'group': 'group3', 'class_': 'class3', 'dance': 'dance3'},
|
{"group": "group3", "class_": "class3", "dance": "dance3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
importMock1 = mocker.patch('solo_turnier.html_parser.HtmlImport')
|
importMock1 = mocker.patch("solo_turnier.html_parser.HtmlImport")
|
||||||
importMock2 = mocker.patch('solo_turnier.html_parser.HtmlImport')
|
importMock2 = mocker.patch("solo_turnier.html_parser.HtmlImport")
|
||||||
importMock3 = mocker.patch('solo_turnier.html_parser.HtmlImport')
|
importMock3 = mocker.patch("solo_turnier.html_parser.HtmlImport")
|
||||||
importMock1.title = 'Fake title 1'
|
importMock1.title = "Fake title 1"
|
||||||
importMock2.title = 'Fake title 2'
|
importMock2.title = "Fake title 2"
|
||||||
importMock3.title = 'Fake title 3'
|
importMock3.title = "Fake title 3"
|
||||||
|
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
structure = dataWorker._createHtmlLUT([importMock1, importMock2, importMock3])
|
structure = dataWorker._createHtmlLUT([importMock1, importMock2, importMock3])
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
('group1', 'class1', 'dance1'): importMock1,
|
("group1", "class1", "dance1"): importMock1,
|
||||||
('group2', 'class2', 'dance2'): importMock2,
|
("group2", "class2", "dance2"): importMock2,
|
||||||
('group3', 'class3', 'dance3'): importMock3,
|
("group3", "class3", "dance3"): importMock3,
|
||||||
}
|
}
|
||||||
assert expected == structure
|
assert expected == structure
|
||||||
|
|
||||||
|
|
||||||
def test_mergeHtmlData(mocker):
|
def test_mergeHtmlData(mocker):
|
||||||
person1 = worker.ResultPerson('Max 1', 'Mustermann', 'TSC Entenhausen')
|
person1 = worker.ResultPerson("Max 1", "Mustermann", "TSC Entenhausen")
|
||||||
person2 = worker.ResultPerson('Max 2', 'Mustermann', 'TSC Entenhausen')
|
person2 = worker.ResultPerson("Max 2", "Mustermann", "TSC Entenhausen")
|
||||||
person3 = worker.ResultPerson('Max 3', 'Mustermann', 'TSC Entenhausen')
|
person3 = worker.ResultPerson("Max 3", "Mustermann", "TSC Entenhausen")
|
||||||
person4 = worker.ResultPerson('Max 4', 'Mustermann', 'TSC Entenhausen')
|
person4 = worker.ResultPerson("Max 4", "Mustermann", "TSC Entenhausen")
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
person1: [
|
person1: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Beg.', '1', '1', 1, 'Kin./Jun.', 'Beg.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Cha Cha', 'Kin.', 'Adv.', '1', '1', 1, 'Kin.', 'Adv.'),
|
"Rumba", "Kin.", "Beg.", "1", "1", 1, "Kin./Jun.", "Beg."
|
||||||
worker.CompetitionResult('Jive', 'Kin.', 'Beg.', '1', '2', 1, 'Kin.', 'Beg.'),
|
),
|
||||||
worker.CompetitionResult('Langs. Walzer', 'Kin.', 'Beg.', '1', '1', 1, 'Kin.', 'Newc./Beg.'),
|
worker.CompetitionResult(
|
||||||
|
"Cha Cha", "Kin.", "Adv.", "1", "1", 1, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin.", "Beg.", "1", "2", 1, "Kin.", "Beg."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Langs. Walzer", "Kin.", "Beg.", "1", "1", 1, "Kin.", "Newc./Beg."
|
||||||
|
),
|
||||||
],
|
],
|
||||||
person2: [
|
person2: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Beg.', '2', '2', 2, 'Kin./Jun.', 'Beg.'),
|
worker.CompetitionResult(
|
||||||
worker.CompetitionResult('Cha Cha', 'Kin.', 'Adv.', '2', '2', 2, 'Kin.', 'Adv.'),
|
"Rumba", "Kin.", "Beg.", "2", "2", 2, "Kin./Jun.", "Beg."
|
||||||
worker.CompetitionResult('Jive', 'Kin.', 'Beg.', '1', '2', 2, 'Kin.', 'Beg.'),
|
),
|
||||||
worker.CompetitionResult('Langs. Walzer', 'Kin.', 'Newc.', '1', '1', 2, 'Kin.', 'Newc./Beg.'),
|
worker.CompetitionResult(
|
||||||
|
"Cha Cha", "Kin.", "Adv.", "2", "2", 2, "Kin.", "Adv."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Jive", "Kin.", "Beg.", "1", "2", 2, "Kin.", "Beg."
|
||||||
|
),
|
||||||
|
worker.CompetitionResult(
|
||||||
|
"Langs. Walzer", "Kin.", "Newc.", "1", "1", 2, "Kin.", "Newc./Beg."
|
||||||
|
),
|
||||||
],
|
],
|
||||||
person3: [
|
person3: [
|
||||||
worker.CompetitionResult('Rumba', 'Jun.', 'Beg.', '1', '1', 3, 'Kin./Jun.', 'Beg.'),
|
worker.CompetitionResult(
|
||||||
|
"Rumba", "Jun.", "Beg.", "1", "1", 3, "Kin./Jun.", "Beg."
|
||||||
|
),
|
||||||
# worker.CompetitionResult('Cha Cha', 'Jun.', 'Adv.', '1', '1', 3, 'Kin.', 'Adv.'),
|
# worker.CompetitionResult('Cha Cha', 'Jun.', 'Adv.', '1', '1', 3, 'Kin.', 'Adv.'),
|
||||||
# worker.CompetitionResult('Jive', 'Jun.', 'Beg.', '2', '2', 3, 'Kin.', 'Beg.'),
|
# worker.CompetitionResult('Jive', 'Jun.', 'Beg.', '2', '2', 3, 'Kin.', 'Beg.'),
|
||||||
# worker.CompetitionResult('Langs. Walzer', 'Jun.', 'Newc./Beg.', '1', '1', 3, 'Kin.', 'Beg.'),
|
# worker.CompetitionResult('Langs. Walzer', 'Jun.', 'Newc./Beg.', '1', '1', 3, 'Kin.', 'Beg.'),
|
||||||
],
|
],
|
||||||
person4: [
|
person4: [
|
||||||
worker.CompetitionResult('Rumba', 'Kin.', 'Beg.', '3', '3', 4, 'Kin./Jun.', 'Beg.'),
|
worker.CompetitionResult(
|
||||||
|
"Rumba", "Kin.", "Beg.", "3", "3", 4, "Kin./Jun.", "Beg."
|
||||||
|
),
|
||||||
# worker.CompetitionResult('Cha Cha', 'Kin.', 'Adv.', '1', '1', 4, 'Kin.', 'Adv.'),
|
# worker.CompetitionResult('Cha Cha', 'Kin.', 'Adv.', '1', '1', 4, 'Kin.', 'Adv.'),
|
||||||
# worker.CompetitionResult('Jive', 'Kin.', 'Beg.', '2', '2', 4, 'Kin.', 'Beg.'),
|
# worker.CompetitionResult('Jive', 'Kin.', 'Beg.', '2', '2', 4, 'Kin.', 'Beg.'),
|
||||||
# worker.CompetitionResult('Langs. Walzer', 'Kin.', 'Newc./Beg.', '1', '1', 4, 'Kin.', 'Beg.'),
|
# worker.CompetitionResult('Langs. Walzer', 'Kin.', 'Newc./Beg.', '1', '1', 4, 'Kin.', 'Beg.'),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlParticipant1Dance1 = html_parser.HtmlParticipant('Max 1 Mustermann', '1.', True)
|
htmlParticipant1Dance1 = html_parser.HtmlParticipant("Max 1 Mustermann", "1.", True)
|
||||||
htmlParticipant1Dance2 = html_parser.HtmlParticipant('Max 1 Mustermann', '1.', True)
|
htmlParticipant1Dance2 = html_parser.HtmlParticipant("Max 1 Mustermann", "1.", True)
|
||||||
htmlParticipant1Dance3 = html_parser.HtmlParticipant('Max 1 Mustermann', '1.-2.', True)
|
htmlParticipant1Dance3 = html_parser.HtmlParticipant(
|
||||||
htmlParticipant1Dance4 = html_parser.HtmlParticipant('Max 1 Mustermann', '1.', True)
|
"Max 1 Mustermann", "1.-2.", True
|
||||||
|
)
|
||||||
|
htmlParticipant1Dance4 = html_parser.HtmlParticipant("Max 1 Mustermann", "1.", True)
|
||||||
|
|
||||||
htmlParticipant2Dance1 = html_parser.HtmlParticipant('Max 2 Mustermann', '2.', True)
|
htmlParticipant2Dance1 = html_parser.HtmlParticipant("Max 2 Mustermann", "2.", True)
|
||||||
htmlParticipant2Dance2 = html_parser.HtmlParticipant('Max 2 Mustermann', '2.', True)
|
htmlParticipant2Dance2 = html_parser.HtmlParticipant("Max 2 Mustermann", "2.", True)
|
||||||
htmlParticipant2Dance3 = html_parser.HtmlParticipant('Max 2 Mustermann', '1.-2.', True)
|
htmlParticipant2Dance3 = html_parser.HtmlParticipant(
|
||||||
htmlParticipant2Dance4 = html_parser.HtmlParticipant('Max 2 Mustermann', '1.', True)
|
"Max 2 Mustermann", "1.-2.", True
|
||||||
|
)
|
||||||
|
htmlParticipant2Dance4 = html_parser.HtmlParticipant("Max 2 Mustermann", "1.", True)
|
||||||
|
|
||||||
htmlParticipant3Dance1 = html_parser.HtmlParticipant('Max 3 Mustermann', '1.', True)
|
htmlParticipant3Dance1 = html_parser.HtmlParticipant("Max 3 Mustermann", "1.", True)
|
||||||
|
|
||||||
htmlParticipant4Dance1 = html_parser.HtmlParticipant('Max 4 Mustermann', '3.', False)
|
htmlParticipant4Dance1 = html_parser.HtmlParticipant(
|
||||||
|
"Max 4 Mustermann", "3.", False
|
||||||
|
)
|
||||||
|
|
||||||
htmlParticipantsDance1 = {
|
htmlParticipantsDance1 = {
|
||||||
'1': htmlParticipant1Dance1,
|
"1": htmlParticipant1Dance1,
|
||||||
'2': htmlParticipant2Dance1,
|
"2": htmlParticipant2Dance1,
|
||||||
'3': htmlParticipant3Dance1,
|
"3": htmlParticipant3Dance1,
|
||||||
'4': htmlParticipant4Dance1
|
"4": htmlParticipant4Dance1,
|
||||||
}
|
}
|
||||||
htmlParticipantsDance2 = {
|
htmlParticipantsDance2 = {
|
||||||
'1': htmlParticipant1Dance2,
|
"1": htmlParticipant1Dance2,
|
||||||
'2': htmlParticipant2Dance2,
|
"2": htmlParticipant2Dance2,
|
||||||
}
|
}
|
||||||
htmlParticipantsDance3 = {
|
htmlParticipantsDance3 = {
|
||||||
'1': htmlParticipant1Dance3,
|
"1": htmlParticipant1Dance3,
|
||||||
'2': htmlParticipant2Dance3,
|
"2": htmlParticipant2Dance3,
|
||||||
}
|
}
|
||||||
htmlParticipantsDance4 = {
|
htmlParticipantsDance4 = {
|
||||||
'1': htmlParticipant1Dance4,
|
"1": htmlParticipant1Dance4,
|
||||||
'2': htmlParticipant2Dance4,
|
"2": htmlParticipant2Dance4,
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlCompetition1 = html_parser.HtmlImport('ETW, Solos Kin./Jun. Beginner Rumba', htmlParticipantsDance1)
|
htmlCompetition1 = html_parser.HtmlImport(
|
||||||
htmlCompetition2 = html_parser.HtmlImport('ETW, Solos Kin. Advanced Cha Cha', htmlParticipantsDance2)
|
"ETW, Solos Kin./Jun. Beginner Rumba", htmlParticipantsDance1
|
||||||
htmlCompetition3 = html_parser.HtmlImport('ETW, Solos Kinder Beginner Jive', htmlParticipantsDance3)
|
)
|
||||||
htmlCompetition4 = html_parser.HtmlImport('ETW, Solos Kin. Newc./Beg. Langs. Walzer', htmlParticipantsDance4)
|
htmlCompetition2 = html_parser.HtmlImport(
|
||||||
|
"ETW, Solos Kin. Advanced Cha Cha", htmlParticipantsDance2
|
||||||
|
)
|
||||||
|
htmlCompetition3 = html_parser.HtmlImport(
|
||||||
|
"ETW, Solos Kinder Beginner Jive", htmlParticipantsDance3
|
||||||
|
)
|
||||||
|
htmlCompetition4 = html_parser.HtmlImport(
|
||||||
|
"ETW, Solos Kin. Newc./Beg. Langs. Walzer", htmlParticipantsDance4
|
||||||
|
)
|
||||||
|
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
|
|
||||||
dataWorker.mergeHtmlData(data, [htmlCompetition1, htmlCompetition2, htmlCompetition3, htmlCompetition4])
|
dataWorker.mergeHtmlData(
|
||||||
|
data, [htmlCompetition1, htmlCompetition2, htmlCompetition3, htmlCompetition4]
|
||||||
|
)
|
||||||
|
|
||||||
person1Finalist = [c.finalist for c in data[person1]]
|
person1Finalist = [c.finalist for c in data[person1]]
|
||||||
person2Finalist = [c.finalist for c in data[person2]]
|
person2Finalist = [c.finalist for c in data[person2]]
|
||||||
@ -311,28 +470,54 @@ def test_mergeHtmlData(mocker):
|
|||||||
|
|
||||||
assert finalists == expectedFinalists
|
assert finalists == expectedFinalists
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=range(4))
|
@pytest.fixture(params=range(4))
|
||||||
def fixture_getAllDancesInCompetition(request, mocker):
|
def fixture_getAllDancesInCompetition(request, mocker):
|
||||||
def mockCompetition(comp):
|
def mockCompetition(comp):
|
||||||
def mockUser():
|
def mockUser():
|
||||||
return mocker.patch('solo_turnier.worker.ResultPerson')
|
return mocker.patch("solo_turnier.worker.ResultPerson")
|
||||||
|
|
||||||
def mockDances(dances):
|
def mockDances(dances):
|
||||||
def mockDance(name):
|
def mockDance(name):
|
||||||
mock = mocker.patch('solo_turnier.worker.CompetitionResult')
|
mock = mocker.patch("solo_turnier.worker.CompetitionResult")
|
||||||
mock.dance = name
|
mock.dance = name
|
||||||
return mock
|
return mock
|
||||||
|
|
||||||
return [mockDance(d) for d in dances]
|
return [mockDance(d) for d in dances]
|
||||||
|
|
||||||
return {mockUser(): mockDances(dances) for dances in comp}
|
return {mockUser(): mockDances(dances) for dances in comp}
|
||||||
|
|
||||||
cases = (
|
cases = (
|
||||||
([['Samba']], ['Samba']),
|
([["Samba"]], ["Samba"]),
|
||||||
([['Samba', 'Rumba'], ['Cha Cha']], ['Samba', 'Cha Cha', 'Rumba']),
|
([["Samba", "Rumba"], ["Cha Cha"]], ["Samba", "Cha Cha", "Rumba"]),
|
||||||
([['Samba', 'Rumba'], ['Cha Cha', 'Tango', 'Langs. Walzer']], ['Samba', 'Cha Cha', 'Rumba', 'Langs. Walzer', 'Tango']),
|
(
|
||||||
([['Cha Cha', 'Rumba', 'Jive'], ['Quickstep', 'Tango', 'Wiener Walzer', 'Langs. Walzer'], ['Slowfox', 'Langs. Walzer', 'Paso Doble', 'Samba']], ['Samba', 'Cha Cha', 'Rumba', 'Paso Doble', 'Jive', 'Langs. Walzer', 'Tango', 'Wiener Walzer', 'Slowfox', 'Quickstep'])
|
[["Samba", "Rumba"], ["Cha Cha", "Tango", "Langs. Walzer"]],
|
||||||
|
["Samba", "Cha Cha", "Rumba", "Langs. Walzer", "Tango"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
[
|
||||||
|
["Cha Cha", "Rumba", "Jive"],
|
||||||
|
["Quickstep", "Tango", "Wiener Walzer", "Langs. Walzer"],
|
||||||
|
["Slowfox", "Langs. Walzer", "Paso Doble", "Samba"],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"Samba",
|
||||||
|
"Cha Cha",
|
||||||
|
"Rumba",
|
||||||
|
"Paso Doble",
|
||||||
|
"Jive",
|
||||||
|
"Langs. Walzer",
|
||||||
|
"Tango",
|
||||||
|
"Wiener Walzer",
|
||||||
|
"Slowfox",
|
||||||
|
"Quickstep",
|
||||||
|
],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
case = cases[request.param]
|
case = cases[request.param]
|
||||||
return (mockCompetition(case[0]), case[1])
|
return (mockCompetition(case[0]), case[1])
|
||||||
|
|
||||||
|
|
||||||
def test_getAllDancesInCompetitions(fixture_getAllDancesInCompetition):
|
def test_getAllDancesInCompetitions(fixture_getAllDancesInCompetition):
|
||||||
print(fixture_getAllDancesInCompetition)
|
print(fixture_getAllDancesInCompetition)
|
||||||
data = fixture_getAllDancesInCompetition[0]
|
data = fixture_getAllDancesInCompetition[0]
|
||||||
@ -340,57 +525,76 @@ def test_getAllDancesInCompetitions(fixture_getAllDancesInCompetition):
|
|||||||
ret = dataWorker.getAllDancesInCompetitions(data)
|
ret = dataWorker.getAllDancesInCompetitions(data)
|
||||||
assert ret == fixture_getAllDancesInCompetition[1]
|
assert ret == fixture_getAllDancesInCompetition[1]
|
||||||
|
|
||||||
|
|
||||||
def test_collectPersonsInGroups(mocker):
|
def test_collectPersonsInGroups(mocker):
|
||||||
def mockPerson(group):
|
def mockPerson(group):
|
||||||
mock = mocker.patch('solo_turnier.worker.ResultPerson')
|
mock = mocker.patch("solo_turnier.worker.ResultPerson")
|
||||||
mock.group = group
|
mock.group = group
|
||||||
return mock
|
return mock
|
||||||
|
|
||||||
persons = (
|
persons = (
|
||||||
mockPerson('Kin.'), mockPerson('Kin.'), mockPerson('Jun.'),
|
mockPerson("Kin."),
|
||||||
mockPerson('Kin.'), mockPerson(None), mockPerson('Jug.'),
|
mockPerson("Kin."),
|
||||||
mockPerson(None), mockPerson('Kin./Jun.'), mockPerson('Jun.')
|
mockPerson("Jun."),
|
||||||
|
mockPerson("Kin."),
|
||||||
|
mockPerson(None),
|
||||||
|
mockPerson("Jug."),
|
||||||
|
mockPerson(None),
|
||||||
|
mockPerson("Kin./Jun."),
|
||||||
|
mockPerson("Jun."),
|
||||||
)
|
)
|
||||||
data = {p: [] for p in persons}
|
data = {p: [] for p in persons}
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
groups = dataWorker.collectPersonsInGroups(data)
|
groups = dataWorker.collectPersonsInGroups(data)
|
||||||
|
|
||||||
assert groups['Kin.'] == [persons[0], persons[1], persons[3]]
|
assert groups["Kin."] == [persons[0], persons[1], persons[3]]
|
||||||
assert groups['Jun.'] == [persons[2], persons[8]]
|
assert groups["Jun."] == [persons[2], persons[8]]
|
||||||
assert groups['Jug.'] == [persons[5]]
|
assert groups["Jug."] == [persons[5]]
|
||||||
assert groups['Sonst'] == [persons[4], persons[6], persons[7]]
|
assert groups["Sonst"] == [persons[4], persons[6], persons[7]]
|
||||||
|
|
||||||
|
|
||||||
def test_sortPersons_withId(mocker):
|
def test_sortPersons_withId(mocker):
|
||||||
def mockPerson(id):
|
def mockPerson(id):
|
||||||
mock = mocker.patch('solo_turnier.worker.ResultPerson')
|
mock = mocker.patch("solo_turnier.worker.ResultPerson")
|
||||||
mock.id = id
|
mock.id = id
|
||||||
return mock
|
return mock
|
||||||
|
|
||||||
persons = [mockPerson(2), mockPerson(1), mockPerson(5), mockPerson(3)]
|
persons = [mockPerson(2), mockPerson(1), mockPerson(5), mockPerson(3)]
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
sorted, showIds = dataWorker.sortPersonsInGroup(persons)
|
sorted, showIds = dataWorker.sortPersonsInGroup(persons)
|
||||||
assert sorted == [persons[1], persons[0], persons[3], persons[2]]
|
assert sorted == [persons[1], persons[0], persons[3], persons[2]]
|
||||||
assert showIds == True
|
assert showIds == True
|
||||||
|
|
||||||
|
|
||||||
def test_sortPersons_withoutId(mocker):
|
def test_sortPersons_withoutId(mocker):
|
||||||
def mockPerson(name):
|
def mockPerson(name):
|
||||||
mock = mocker.patch('solo_turnier.worker.ResultPerson')
|
mock = mocker.patch("solo_turnier.worker.ResultPerson")
|
||||||
mock.id = 3
|
mock.id = 3
|
||||||
mock.name = name
|
mock.name = name
|
||||||
mock.club = 'TSC Entenhausen'
|
mock.club = "TSC Entenhausen"
|
||||||
return mock
|
return mock
|
||||||
persons = [mockPerson('Max'), mockPerson('Isabel'), mockPerson('Reimund'), mockPerson('Anna')]
|
|
||||||
|
persons = [
|
||||||
|
mockPerson("Max"),
|
||||||
|
mockPerson("Isabel"),
|
||||||
|
mockPerson("Reimund"),
|
||||||
|
mockPerson("Anna"),
|
||||||
|
]
|
||||||
persons[2].id = None
|
persons[2].id = None
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
sorted, showIds = dataWorker.sortPersonsInGroup(persons)
|
sorted, showIds = dataWorker.sortPersonsInGroup(persons)
|
||||||
assert sorted == [persons[3], persons[1], persons[0], persons[2]]
|
assert sorted == [persons[3], persons[1], persons[0], persons[2]]
|
||||||
assert showIds == False
|
assert showIds == False
|
||||||
|
|
||||||
|
|
||||||
def test_mapPersonResultsToDanceList(mocker):
|
def test_mapPersonResultsToDanceList(mocker):
|
||||||
def mockResult(dance):
|
def mockResult(dance):
|
||||||
mock = mocker.patch('solo_turnier.worker.CompetitionResult')
|
mock = mocker.patch("solo_turnier.worker.CompetitionResult")
|
||||||
mock.dance = dance
|
mock.dance = dance
|
||||||
return mock
|
return mock
|
||||||
dances = ['Cha Cha', 'Rumba', 'Langs. Walzer', 'Quickstep']
|
|
||||||
results = [mockResult('Rumba'), mockResult('Quickstep'), mockResult('Cha Cha')]
|
dances = ["Cha Cha", "Rumba", "Langs. Walzer", "Quickstep"]
|
||||||
|
results = [mockResult("Rumba"), mockResult("Quickstep"), mockResult("Cha Cha")]
|
||||||
dataWorker = worker.DataWorker()
|
dataWorker = worker.DataWorker()
|
||||||
mappedResults = dataWorker.mapPersonResultsToDanceList(results, dances)
|
mappedResults = dataWorker.mapPersonResultsToDanceList(results, dances)
|
||||||
assert mappedResults == [results[2], results[0], None, results[1]]
|
assert mappedResults == [results[2], results[0], None, results[1]]
|
||||||
|
@ -1,12 +1,25 @@
|
|||||||
|
|
||||||
from . import group
|
from . import group
|
||||||
from . import competition_class
|
from . import competition_class
|
||||||
|
|
||||||
|
|
||||||
class CSVResultRow:
|
class CSVResultRow:
|
||||||
def __init__(self, firstName, lastName, club, id, group, class_, dance, place, placeTo, competitionGroup, competitionClass):
|
def __init__(
|
||||||
|
self,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
club,
|
||||||
|
id,
|
||||||
|
group,
|
||||||
|
class_,
|
||||||
|
dance,
|
||||||
|
place,
|
||||||
|
placeTo,
|
||||||
|
competitionGroup,
|
||||||
|
competitionClass,
|
||||||
|
):
|
||||||
self.firstName = firstName
|
self.firstName = firstName
|
||||||
self.lastName = lastName
|
self.lastName = lastName
|
||||||
self.name = f'{firstName} {lastName}'
|
self.name = f"{firstName} {lastName}"
|
||||||
self.club = club
|
self.club = club
|
||||||
self.id = id
|
self.id = id
|
||||||
self.group = group
|
self.group = group
|
||||||
@ -18,7 +31,8 @@ class CSVResultRow:
|
|||||||
self.competitionClass = competitionClass
|
self.competitionClass = competitionClass
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.name} ({self.id}, {self.club}) is in {self.group} {self.class_} and danced the {self.dance} in {self.competitionGroup} {self.competitionClass} getting place {self.place}-{self.placeTo}'
|
return f"{self.name} ({self.id}, {self.club}) is in {self.group} {self.class_} and danced the {self.dance} in {self.competitionGroup} {self.competitionClass} getting place {self.place}-{self.placeTo}"
|
||||||
|
|
||||||
|
|
||||||
class HtmlPreviewParticipant:
|
class HtmlPreviewParticipant:
|
||||||
def __init__(self, name, id, group_):
|
def __init__(self, name, id, group_):
|
||||||
@ -32,10 +46,16 @@ class HtmlPreviewParticipant:
|
|||||||
if type(o) != HtmlPreviewParticipant:
|
if type(o) != HtmlPreviewParticipant:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return all(map(lambda x, y: x == y, (self.name, self.id, self.group), (o.name, o.id, o.group)))
|
return all(
|
||||||
|
map(
|
||||||
|
lambda x, y: x == y,
|
||||||
|
(self.name, self.id, self.group),
|
||||||
|
(o.name, o.id, o.group),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.id} ({self.name}, {self.group})'
|
return f"{self.id} ({self.name}, {self.group})"
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.id, self.name, self.group))
|
return hash((self.id, self.name, self.group))
|
||||||
@ -43,6 +63,7 @@ class HtmlPreviewParticipant:
|
|||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
return self.id >= other.id
|
return self.id >= other.id
|
||||||
|
|
||||||
|
|
||||||
class HtmlParticipant:
|
class HtmlParticipant:
|
||||||
def __init__(self, name, id):
|
def __init__(self, name, id):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -53,10 +74,16 @@ class HtmlParticipant:
|
|||||||
if type(o) != HtmlPreviewParticipant:
|
if type(o) != HtmlPreviewParticipant:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return all(map(lambda x, y: x == y, (self.name, self.id, self.group), (o.name, o.id, o.group)))
|
return all(
|
||||||
|
map(
|
||||||
|
lambda x, y: x == y,
|
||||||
|
(self.name, self.id, self.group),
|
||||||
|
(o.name, o.id, o.group),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.id}: {self.name}'
|
return f"{self.id}: {self.name}"
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.id, self.name))
|
return hash((self.id, self.name))
|
||||||
@ -64,16 +91,20 @@ class HtmlParticipant:
|
|||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
return self.id >= other.id
|
return self.id >= other.id
|
||||||
|
|
||||||
|
|
||||||
# class PreviewParticipationData:
|
# class PreviewParticipationData:
|
||||||
# def __init__(self, dance: str, class_: competition_class.CompetitionClass):
|
# def __init__(self, dance: str, class_: competition_class.CompetitionClass):
|
||||||
# self.class_ = class_
|
# self.class_ = class_
|
||||||
# self.dance = dance
|
# self.dance = dance
|
||||||
|
|
||||||
|
|
||||||
class HtmlPreviewImport:
|
class HtmlPreviewImport:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
participants: dict[int, list[HtmlPreviewParticipant]],
|
participants: dict[int, list[HtmlPreviewParticipant]],
|
||||||
results: dict[HtmlPreviewParticipant, dict[str, competition_class.CompetitionClass]]
|
results: dict[
|
||||||
|
HtmlPreviewParticipant, dict[str, competition_class.CompetitionClass]
|
||||||
|
],
|
||||||
):
|
):
|
||||||
self.participants = participants
|
self.participants = participants
|
||||||
self.results = results
|
self.results = results
|
||||||
@ -81,6 +112,7 @@ class HtmlPreviewImport:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return (str(self.participants), str(self.results))
|
return (str(self.participants), str(self.results))
|
||||||
|
|
||||||
|
|
||||||
class HtmlResultImport:
|
class HtmlResultImport:
|
||||||
def __init__(self, results: dict[HtmlParticipant, str]):
|
def __init__(self, results: dict[HtmlParticipant, str]):
|
||||||
self.results = results
|
self.results = results
|
||||||
@ -88,6 +120,7 @@ class HtmlResultImport:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self.results)
|
return str(self.results)
|
||||||
|
|
||||||
|
|
||||||
class HtmlResultTotalTable:
|
class HtmlResultTotalTable:
|
||||||
def __init__(self, participants):
|
def __init__(self, participants):
|
||||||
self.participants = participants
|
self.participants = participants
|
||||||
@ -95,6 +128,7 @@ class HtmlResultTotalTable:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self.participants)
|
return str(self.participants)
|
||||||
|
|
||||||
|
|
||||||
class HtmlCompetitionResultRow:
|
class HtmlCompetitionResultRow:
|
||||||
def __init__(self, name, id, dance, group, class_, place, placeTo, finalist):
|
def __init__(self, name, id, dance, group, class_, place, placeTo, finalist):
|
||||||
self.dance = dance
|
self.dance = dance
|
||||||
@ -108,28 +142,30 @@ class HtmlCompetitionResultRow:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.place == self.placeTo:
|
if self.place == self.placeTo:
|
||||||
result = f'{self.place}.'
|
result = f"{self.place}."
|
||||||
else:
|
else:
|
||||||
result = f'{self.place}.-{self.placeTo}.'
|
result = f"{self.place}.-{self.placeTo}."
|
||||||
|
|
||||||
if self.finalist == True:
|
if self.finalist == True:
|
||||||
finalist = '[F]'
|
finalist = "[F]"
|
||||||
else:
|
else:
|
||||||
finalist = ''
|
finalist = ""
|
||||||
return f'Result[{self.id}]({self.group} {self.class_} {self.dance} as {result}{finalist})'
|
return f"Result[{self.id}]({self.group} {self.class_} {self.dance} as {result}{finalist})"
|
||||||
|
|
||||||
def __eq__(self, o):
|
def __eq__(self, o):
|
||||||
if not isinstance(o, CompetitionResult):
|
if not isinstance(o, CompetitionResult):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return (
|
return (
|
||||||
self.dance == o.dance and
|
self.dance == o.dance
|
||||||
self.competitionClass == o.competitionClass and
|
and self.competitionClass == o.competitionClass
|
||||||
self.competitionGroup == o.competitionGroup and
|
and self.competitionGroup == o.competitionGroup
|
||||||
self.place == o.place and self.placeTo == o.placeTo and
|
and self.place == o.place
|
||||||
self.id == o.id
|
and self.placeTo == o.placeTo
|
||||||
|
and self.id == o.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class HtmlSingleCompetitionResult:
|
class HtmlSingleCompetitionResult:
|
||||||
def __init__(self, name, place, placeTo, finalist):
|
def __init__(self, name, place, placeTo, finalist):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -141,14 +177,14 @@ class HtmlSingleCompetitionResult:
|
|||||||
if self.placeTo is None:
|
if self.placeTo is None:
|
||||||
place = self.place
|
place = self.place
|
||||||
else:
|
else:
|
||||||
place = f'{self.place}-{self.placeTo}'
|
place = f"{self.place}-{self.placeTo}"
|
||||||
|
|
||||||
if self.finalist:
|
if self.finalist:
|
||||||
return f'Res({self.name} [F], placed {place})'
|
return f"Res({self.name} [F], placed {place})"
|
||||||
else:
|
else:
|
||||||
return f'Res({self.name}, placed {place})'
|
return f"Res({self.name}, placed {place})"
|
||||||
|
|
||||||
def __gt__(self,other):
|
def __gt__(self, other):
|
||||||
return self.id > other.id
|
return self.id > other.id
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
@ -157,18 +193,36 @@ class HtmlSingleCompetitionResult:
|
|||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.id)
|
return hash(self.id)
|
||||||
|
|
||||||
|
|
||||||
class HtmlCompetitionTotalResults:
|
class HtmlCompetitionTotalResults:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.results = {}
|
self.results = {}
|
||||||
self.tabges = {}
|
self.tabges = {}
|
||||||
|
|
||||||
def __getTuple(self, group: group.Group_t, class_: competition_class.Class_t, dance: str, id: int):
|
def __getTuple(
|
||||||
|
self,
|
||||||
|
group: group.Group_t,
|
||||||
|
class_: competition_class.Class_t,
|
||||||
|
dance: str,
|
||||||
|
id: int,
|
||||||
|
):
|
||||||
return (group, class_, dance, id)
|
return (group, class_, dance, id)
|
||||||
|
|
||||||
def get(self, group: group.Group_t, class_: competition_class.Class_t, dance: str, id: int) -> list[HtmlSingleCompetitionResult]:
|
def get(
|
||||||
|
self,
|
||||||
|
group: group.Group_t,
|
||||||
|
class_: competition_class.Class_t,
|
||||||
|
dance: str,
|
||||||
|
id: int,
|
||||||
|
) -> list[HtmlSingleCompetitionResult]:
|
||||||
return self.results[self.__getTuple(group, class_, dance, id)]
|
return self.results[self.__getTuple(group, class_, dance, id)]
|
||||||
|
|
||||||
def getById(self, id: int) -> dict[tuple[str, group.Group_t, competition_class.Class_t], HtmlSingleCompetitionResult]:
|
def getById(
|
||||||
|
self, id: int
|
||||||
|
) -> dict[
|
||||||
|
tuple[str, group.Group_t, competition_class.Class_t],
|
||||||
|
HtmlSingleCompetitionResult,
|
||||||
|
]:
|
||||||
ret = {}
|
ret = {}
|
||||||
|
|
||||||
for k in self.results:
|
for k in self.results:
|
||||||
@ -187,6 +241,7 @@ class HtmlCompetitionTotalResults:
|
|||||||
l.append(result)
|
l.append(result)
|
||||||
self.results[tup] = l
|
self.results[tup] = l
|
||||||
|
|
||||||
|
|
||||||
class SingleParticipantResult:
|
class SingleParticipantResult:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -195,7 +250,7 @@ class SingleParticipantResult:
|
|||||||
dance: str,
|
dance: str,
|
||||||
finalist: bool,
|
finalist: bool,
|
||||||
place: int,
|
place: int,
|
||||||
placeTo: int|None
|
placeTo: int | None,
|
||||||
):
|
):
|
||||||
self.competitionClass = competitionClass
|
self.competitionClass = competitionClass
|
||||||
self.nativeClass = nativeClass
|
self.nativeClass = nativeClass
|
||||||
@ -211,65 +266,81 @@ class SingleParticipantResult:
|
|||||||
self.placeNativeTo = None
|
self.placeNativeTo = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
asFinalist = ' as finalist' if self.finalist else ''
|
asFinalist = " as finalist" if self.finalist else ""
|
||||||
|
|
||||||
if self.placeTo is None:
|
if self.placeTo is None:
|
||||||
return f'SR[{self.place} in {self.dance} {self.competitionClass} ({self.placeNative}-{self.placeNativeTo}, {self.nativeClass}){asFinalist}]'
|
return f"SR[{self.place} in {self.dance} {self.competitionClass} ({self.placeNative}-{self.placeNativeTo}, {self.nativeClass}){asFinalist}]"
|
||||||
|
|
||||||
return f'SR[{self.place}-{self.placeTo} in {self.dance} {self.competitionClass} ({self.placeNative}-{self.placeNativeTo}, {self.nativeClass}){asFinalist}]'
|
return f"SR[{self.place}-{self.placeTo} in {self.dance} {self.competitionClass} ({self.placeNative}-{self.placeNativeTo}, {self.nativeClass}){asFinalist}]"
|
||||||
|
|
||||||
def getPlace(self):
|
def getPlace(self):
|
||||||
if self.placeTo is None:
|
if self.placeTo is None:
|
||||||
return f'{self.place}.'
|
return f"{self.place}."
|
||||||
else:
|
else:
|
||||||
return f'{self.place}.-{self.placeTo}.'
|
return f"{self.place}.-{self.placeTo}."
|
||||||
|
|
||||||
def getNativePlace(self):
|
def getNativePlace(self):
|
||||||
if self.placeNativeTo is None:
|
if self.placeNativeTo is None:
|
||||||
return f'{self.placeNative}.'
|
return f"{self.placeNative}."
|
||||||
else:
|
else:
|
||||||
return f'{self.placeNative}.-{self.placeNativeTo}.'
|
return f"{self.placeNative}.-{self.placeNativeTo}."
|
||||||
|
|
||||||
|
|
||||||
class TotalGroupResult:
|
class TotalGroupResult:
|
||||||
def __init__(self, dances: list[str], results: dict[HtmlPreviewParticipant, list[SingleParticipantResult]]):
|
|
||||||
self.dances = dances
|
|
||||||
self.results = results
|
|
||||||
def __repr__(self):
|
|
||||||
return f'TotalGroupResult({self.dances}, {self.results})'
|
|
||||||
|
|
||||||
class State4:
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
resultPerGroup: dict[group.Group, TotalGroupResult]
|
dances: list[str],
|
||||||
|
results: dict[HtmlPreviewParticipant, list[SingleParticipantResult]],
|
||||||
):
|
):
|
||||||
|
self.dances = dances
|
||||||
|
self.results = results
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"TotalGroupResult({self.dances}, {self.results})"
|
||||||
|
|
||||||
|
|
||||||
|
class State4:
|
||||||
|
def __init__(self, resultPerGroup: dict[group.Group, TotalGroupResult]):
|
||||||
parser = group.GroupParser()
|
parser = group.GroupParser()
|
||||||
self.groups = parser.getGroupsAsSortedList(resultPerGroup.keys())
|
self.groups = parser.getGroupsAsSortedList(resultPerGroup.keys())
|
||||||
self.results = resultPerGroup
|
self.results = resultPerGroup
|
||||||
|
|
||||||
|
|
||||||
class State3:
|
class State3:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self, previewImport: HtmlPreviewImport, htmlResults: HtmlCompetitionTotalResults
|
||||||
previewImport: HtmlPreviewImport,
|
|
||||||
htmlResults: HtmlCompetitionTotalResults
|
|
||||||
):
|
):
|
||||||
self.previewImport = previewImport
|
self.previewImport = previewImport
|
||||||
self.htmlResults = htmlResults
|
self.htmlResults = htmlResults
|
||||||
|
|
||||||
|
|
||||||
class Participant:
|
class Participant:
|
||||||
def __init__(self, firstName: str, lastName: str, club: str, group: group.Group, class_: competition_class.CompetitionClass):
|
def __init__(
|
||||||
|
self,
|
||||||
|
firstName: str,
|
||||||
|
lastName: str,
|
||||||
|
club: str,
|
||||||
|
group: group.Group,
|
||||||
|
class_: competition_class.CompetitionClass,
|
||||||
|
):
|
||||||
self.firstName = firstName
|
self.firstName = firstName
|
||||||
self.lastName = lastName
|
self.lastName = lastName
|
||||||
self.club = club
|
self.club = club
|
||||||
self.group = group
|
self.group = group
|
||||||
self.class_ = class_
|
self.class_ = class_
|
||||||
|
|
||||||
|
|
||||||
class ParticipantResult:
|
class ParticipantResult:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, id: int, finalist: bool, cancelled: bool,
|
self,
|
||||||
|
id: int,
|
||||||
|
finalist: bool,
|
||||||
|
cancelled: bool,
|
||||||
group: group.Group_t,
|
group: group.Group_t,
|
||||||
class_: competition_class.Class_t,
|
class_: competition_class.Class_t,
|
||||||
dance: str,
|
dance: str,
|
||||||
place, placeTo
|
place,
|
||||||
|
placeTo,
|
||||||
):
|
):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.finalist = finalist
|
self.finalist = finalist
|
||||||
@ -280,10 +351,12 @@ class ParticipantResult:
|
|||||||
self.place = place
|
self.place = place
|
||||||
self.placeTo = placeTo
|
self.placeTo = placeTo
|
||||||
|
|
||||||
|
|
||||||
class Stage2:
|
class Stage2:
|
||||||
def __init__(self, results: dict[Participant, list[ParticipantResult]]):
|
def __init__(self, results: dict[Participant, list[ParticipantResult]]):
|
||||||
self.results = results
|
self.results = results
|
||||||
|
|
||||||
|
|
||||||
class TableCompetitionEntry:
|
class TableCompetitionEntry:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -293,7 +366,7 @@ class TableCompetitionEntry:
|
|||||||
place: int = -1,
|
place: int = -1,
|
||||||
placeTo: int = -1,
|
placeTo: int = -1,
|
||||||
group: group.Group_t = None,
|
group: group.Group_t = None,
|
||||||
id: int = None
|
id: int = None,
|
||||||
):
|
):
|
||||||
self.finalist = finalist
|
self.finalist = finalist
|
||||||
self.cancelled = cancelled
|
self.cancelled = cancelled
|
||||||
@ -304,58 +377,57 @@ class TableCompetitionEntry:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
def paramMerging(l):
|
def paramMerging(l):
|
||||||
return ', '.join(filter(lambda x: x is not None, l))
|
return ", ".join(filter(lambda x: x is not None, l))
|
||||||
|
|
||||||
if self.cancelled:
|
if self.cancelled:
|
||||||
params = paramMerging([self.group, self.class_, self.id])
|
params = paramMerging([self.group, self.class_, self.id])
|
||||||
if len(params) > 0:
|
if len(params) > 0:
|
||||||
return f'- ({params})'
|
return f"- ({params})"
|
||||||
else:
|
else:
|
||||||
return '-'
|
return "-"
|
||||||
elif not self.finalist:
|
elif not self.finalist:
|
||||||
params = paramMerging([self.group, self.class_, self.id])
|
params = paramMerging([self.group, self.class_, self.id])
|
||||||
if len(params) > 0:
|
if len(params) > 0:
|
||||||
return f'x ({params})'
|
return f"x ({params})"
|
||||||
else:
|
else:
|
||||||
return 'x'
|
return "x"
|
||||||
else:
|
else:
|
||||||
if self.place == self.placeTo:
|
if self.place == self.placeTo:
|
||||||
place = f'{self.place}.'
|
place = f"{self.place}."
|
||||||
else:
|
else:
|
||||||
place = f'{self.place}.-{self.placeTo}.'
|
place = f"{self.place}.-{self.placeTo}."
|
||||||
params = paramMerging([self.group, self.class_, self.id])
|
params = paramMerging([self.group, self.class_, self.id])
|
||||||
return f'{place} ({params})'
|
return f"{place} ({params})"
|
||||||
|
|
||||||
|
|
||||||
class TableEntry:
|
class TableEntry:
|
||||||
def __init__(self, competitions: list[TableCompetitionEntry]):
|
def __init__(self, competitions: list[TableCompetitionEntry]):
|
||||||
self.competitions = competitions
|
self.competitions = competitions
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return ', '.join(self.competitions)
|
return ", ".join(self.competitions)
|
||||||
|
|
||||||
|
|
||||||
class TableRow:
|
class TableRow:
|
||||||
def __init__(
|
def __init__(self, participant: Participant, id: int, entries: list[TableEntry]):
|
||||||
self,
|
|
||||||
participant: Participant,
|
|
||||||
id: int,
|
|
||||||
entries: list[TableEntry]
|
|
||||||
):
|
|
||||||
self.participant = participant
|
self.participant = participant
|
||||||
self.id = id
|
self.id = id
|
||||||
self.entries = entries
|
self.entries = entries
|
||||||
|
|
||||||
def getRowList(self):
|
def getRowList(self):
|
||||||
if self.id is not None:
|
if self.id is not None:
|
||||||
first = f'{self.id}. {self.participant.firstName} {self.participant.lastName} ({self.participant.club})'
|
first = f"{self.id}. {self.participant.firstName} {self.participant.lastName} ({self.participant.club})"
|
||||||
else:
|
else:
|
||||||
first = f'{self.participant.firstName} {self.participant.lastName} ({self.participant.club})'
|
first = f"{self.participant.firstName} {self.participant.lastName} ({self.participant.club})"
|
||||||
return [first] + map(str, self.entries)
|
return [first] + map(str, self.entries)
|
||||||
|
|
||||||
|
|
||||||
class OutputTable:
|
class OutputTable:
|
||||||
def __init__(self, dances: list[str], rows: list[TableRow]):
|
def __init__(self, dances: list[str], rows: list[TableRow]):
|
||||||
self.dances = dances
|
self.dances = dances
|
||||||
self.rows = rows
|
self.rows = rows
|
||||||
|
|
||||||
|
|
||||||
class Stage1:
|
class Stage1:
|
||||||
def __init__(self, tables: dict[group.Group, OutputTable]):
|
def __init__(self, tables: dict[group.Group, OutputTable]):
|
||||||
self.tables = tables
|
self.tables = tables
|
||||||
|
@ -10,6 +10,7 @@ from .types import HtmlCompetitionResultRow as CompetitionResult
|
|||||||
from . import types
|
from . import types
|
||||||
from . import competition_class
|
from . import competition_class
|
||||||
|
|
||||||
|
|
||||||
class HtmlPerson:
|
class HtmlPerson:
|
||||||
def __init__(self, name, id, group):
|
def __init__(self, name, id, group):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -17,7 +18,7 @@ class HtmlPerson:
|
|||||||
self.group = group
|
self.group = group
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.name} ({self.id}, {self.group})'
|
return f"{self.name} ({self.id}, {self.group})"
|
||||||
|
|
||||||
def __eq__(self, o):
|
def __eq__(self, o):
|
||||||
if not isinstance(o, HtmlPerson):
|
if not isinstance(o, HtmlPerson):
|
||||||
@ -27,11 +28,12 @@ class HtmlPerson:
|
|||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return str(self).__hash__()
|
return str(self).__hash__()
|
||||||
|
|
||||||
|
|
||||||
class ResultPerson:
|
class ResultPerson:
|
||||||
def __init__(self, firstName, lastName, club, id = None, group = None):
|
def __init__(self, firstName, lastName, club, id=None, group=None):
|
||||||
self.firstName = firstName
|
self.firstName = firstName
|
||||||
self.lastName = lastName
|
self.lastName = lastName
|
||||||
self.name = f'{firstName} {lastName}'
|
self.name = f"{firstName} {lastName}"
|
||||||
self.club = club
|
self.club = club
|
||||||
self.id = id
|
self.id = id
|
||||||
self.group = group
|
self.group = group
|
||||||
@ -39,9 +41,7 @@ class ResultPerson:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def extractFromResultRow(row: ResultRow):
|
def extractFromResultRow(row: ResultRow):
|
||||||
return ResultPerson(
|
return ResultPerson(
|
||||||
firstName=row.firstName,
|
firstName=row.firstName, lastName=row.lastName, club=row.club
|
||||||
lastName=row.lastName,
|
|
||||||
club=row.club
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __eq__(self, o):
|
def __eq__(self, o):
|
||||||
@ -49,17 +49,17 @@ class ResultPerson:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
return (
|
return (
|
||||||
self.firstName == o.firstName and
|
self.firstName == o.firstName
|
||||||
self.lastName == o.lastName and
|
and self.lastName == o.lastName
|
||||||
self.club == o.club and
|
and self.club == o.club
|
||||||
self.id == o.id
|
and self.id == o.id
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.id is None:
|
if self.id is None:
|
||||||
return f'{self.name} ({self.club})'
|
return f"{self.name} ({self.club})"
|
||||||
else:
|
else:
|
||||||
return f'{self.name} ({self.club}) [{self.id}]'
|
return f"{self.name} ({self.club}) [{self.id}]"
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
text = str(self)
|
text = str(self)
|
||||||
@ -69,19 +69,23 @@ class ResultPerson:
|
|||||||
class ImportNotParsableException(Exception):
|
class ImportNotParsableException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
ParserList_t = dict[str, html_parser.HtmlParser]
|
ParserList_t = dict[str, html_parser.HtmlParser]
|
||||||
|
|
||||||
|
|
||||||
class PreviewWorker:
|
class PreviewWorker:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.l = logging.getLogger('solo_turnier.worker.PreviewWorker')
|
self.l = logging.getLogger("solo_turnier.worker.PreviewWorker")
|
||||||
self.participants = {}
|
self.participants = {}
|
||||||
self.previewResults = {}
|
self.previewResults = {}
|
||||||
|
|
||||||
def filterFilesPreview(self, files: list[str]) -> ParserList_t:
|
def filterFilesPreview(self, files: list[str]) -> ParserList_t:
|
||||||
self.l.debug('Filtering the list of parsers by removing all non preview entries.')
|
self.l.debug(
|
||||||
|
"Filtering the list of parsers by removing all non preview entries."
|
||||||
|
)
|
||||||
ret = {}
|
ret = {}
|
||||||
for file in files:
|
for file in files:
|
||||||
with open(file, 'r') as fp:
|
with open(file, "r") as fp:
|
||||||
text = fp.read()
|
text = fp.read()
|
||||||
|
|
||||||
parser = html_parser.HtmlParser(text, file)
|
parser = html_parser.HtmlParser(text, file)
|
||||||
@ -89,63 +93,75 @@ class PreviewWorker:
|
|||||||
try:
|
try:
|
||||||
data = parser.guessDataFromHtmlTitle()
|
data = parser.guessDataFromHtmlTitle()
|
||||||
except:
|
except:
|
||||||
self.l.error(f'Unable to parse html file in {file}. Please check manually.')
|
self.l.error(
|
||||||
|
f"Unable to parse html file in {file}. Please check manually."
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if data['class_'] == 'Sichtung':
|
if data["class_"] == "Sichtung":
|
||||||
self.l.debug(f"Found candidate in {file}. Adding to the list.")
|
self.l.debug(f"Found candidate in {file}. Adding to the list.")
|
||||||
ret[file] = parser
|
ret[file] = parser
|
||||||
else:
|
else:
|
||||||
self.l.debug(f'Rejecting file {file} as the name {data["class_"]} did not match.')
|
self.l.debug(
|
||||||
|
f'Rejecting file {file} as the name {data["class_"]} did not match.'
|
||||||
|
)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __extractPersonsFromSinglePreview(self, parser: html_parser.HtmlParser):
|
def __extractPersonsFromSinglePreview(self, parser: html_parser.HtmlParser):
|
||||||
imported = parser.parsePreparationRound()
|
imported = parser.parsePreparationRound()
|
||||||
parser.cleanPreparationRoundImport(imported)
|
parser.cleanPreparationRoundImport(imported)
|
||||||
data = imported['data']
|
data = imported["data"]
|
||||||
|
|
||||||
headerData = parser.guessDataFromHtmlTitle()
|
headerData = parser.guessDataFromHtmlTitle()
|
||||||
dance = headerData['dance']
|
dance = headerData["dance"]
|
||||||
classParser = solo_turnier.competition_class.CompetitionClassParser()
|
classParser = solo_turnier.competition_class.CompetitionClassParser()
|
||||||
|
|
||||||
def getRowIndexOfClass():
|
def getRowIndexOfClass():
|
||||||
return data['titles'].index('Platz von\nPlatz bis')
|
return data["titles"].index("Platz von\nPlatz bis")
|
||||||
|
|
||||||
self.l.log(5, data)
|
self.l.log(5, data)
|
||||||
|
|
||||||
if data['titles'][0] != 'Wertungsrichter':
|
if data["titles"][0] != "Wertungsrichter":
|
||||||
self.l.fatal('Cannot parse the parsed content of the preview file.')
|
self.l.fatal("Cannot parse the parsed content of the preview file.")
|
||||||
raise ImportNotParsableException('Incompatible export file')
|
raise ImportNotParsableException("Incompatible export file")
|
||||||
|
|
||||||
if data['titles'][-1] == 'Startgruppe':
|
if data["titles"][-1] == "Startgruppe":
|
||||||
self.l.debug('Combined competition found. Extracting group from table required.')
|
self.l.debug(
|
||||||
|
"Combined competition found. Extracting group from table required."
|
||||||
|
)
|
||||||
extractGroup = True
|
extractGroup = True
|
||||||
else:
|
else:
|
||||||
self.l.debug('Using group from the title.')
|
self.l.debug("Using group from the title.")
|
||||||
group = parser.guessDataFromHtmlTitle(imported['title'])['group']
|
group = parser.guessDataFromHtmlTitle(imported["title"])["group"]
|
||||||
extractGroup = False
|
extractGroup = False
|
||||||
|
|
||||||
classRowIndex = getRowIndexOfClass()
|
classRowIndex = getRowIndexOfClass()
|
||||||
|
|
||||||
for index, e in enumerate(data['table'][0]):
|
for index, e in enumerate(data["table"][0]):
|
||||||
if e['text'] == '':
|
if e["text"] == "":
|
||||||
# Skip empty columns
|
# Skip empty columns
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Extract data from column
|
# Extract data from column
|
||||||
name = e['meta']
|
name = e["meta"]
|
||||||
id = int(e['text'])
|
id = int(e["text"])
|
||||||
if extractGroup:
|
if extractGroup:
|
||||||
group = data['table'][-1][index]['text']
|
group = data["table"][-1][index]["text"]
|
||||||
|
|
||||||
# dance =
|
# dance =
|
||||||
class_ = classParser.parseClass(data['table'][classRowIndex][index]['text'])
|
class_ = classParser.parseClass(data["table"][classRowIndex][index]["text"])
|
||||||
|
|
||||||
participant = types.HtmlPreviewParticipant(name, id, group)
|
participant = types.HtmlPreviewParticipant(name, id, group)
|
||||||
|
|
||||||
l = self.participants.get(id, [])
|
l = self.participants.get(id, [])
|
||||||
self.l.log(5, 'Checking for existence of %s in %s: %s', participant, l, participant in l)
|
self.l.log(
|
||||||
|
5,
|
||||||
|
"Checking for existence of %s in %s: %s",
|
||||||
|
participant,
|
||||||
|
l,
|
||||||
|
participant in l,
|
||||||
|
)
|
||||||
if participant not in l:
|
if participant not in l:
|
||||||
l.append(participant)
|
l.append(participant)
|
||||||
self.participants[id] = l
|
self.participants[id] = l
|
||||||
@ -162,52 +178,62 @@ class PreviewWorker:
|
|||||||
try:
|
try:
|
||||||
self.__extractPersonsFromSinglePreview(parser)
|
self.__extractPersonsFromSinglePreview(parser)
|
||||||
except:
|
except:
|
||||||
self.l.error('Failed to parse preview round in file %s. Skipping this file\'s content.', parser.fileName)
|
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)
|
return types.HtmlPreviewImport(self.participants, self.previewResults)
|
||||||
|
|
||||||
|
|
||||||
class ResultExtractor:
|
class ResultExtractor:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.l = logging.getLogger('solo_turnier.worker.ResultExtractor')
|
self.l = logging.getLogger("solo_turnier.worker.ResultExtractor")
|
||||||
self.rePlaceSingle = re.compile(' *([0-9]+) *')
|
self.rePlaceSingle = re.compile(" *([0-9]+) *")
|
||||||
self.rePlaceDouble = re.compile(' *([0-9]+) *- *([0-9]+) *')
|
self.rePlaceDouble = re.compile(" *([0-9]+) *- *([0-9]+) *")
|
||||||
|
|
||||||
def getAllParsers(self, files: list[tuple[str,str]]) -> ParserList_t:
|
def getAllParsers(self, files: list[tuple[str, str]]) -> ParserList_t:
|
||||||
ret = {}
|
ret = {}
|
||||||
classParser = competition_class.CompetitionClassParser()
|
classParser = competition_class.CompetitionClassParser()
|
||||||
|
|
||||||
for filePair in files:
|
for filePair in files:
|
||||||
with open(filePair[0], 'r') as fp:
|
with open(filePair[0], "r") as fp:
|
||||||
text = fp.read()
|
text = fp.read()
|
||||||
parser = html_parser.HtmlParser(text, filePair[0])
|
parser = html_parser.HtmlParser(text, filePair[0])
|
||||||
|
|
||||||
if filePair[1] is None:
|
if filePair[1] is None:
|
||||||
parserTab = None
|
parserTab = None
|
||||||
else:
|
else:
|
||||||
with open(filePair[1], 'r') as fp:
|
with open(filePair[1], "r") as fp:
|
||||||
textTab = fp.read()
|
textTab = fp.read()
|
||||||
parserTab = html_parser.HtmlParser(textTab, filePair[1])
|
parserTab = html_parser.HtmlParser(textTab, filePair[1])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = parser.guessDataFromHtmlTitle()
|
data = parser.guessDataFromHtmlTitle()
|
||||||
except:
|
except:
|
||||||
self.l.error('Cannot parse HTML file %s to check if it is a valid result. Check manually.', filePair[0])
|
self.l.error(
|
||||||
|
"Cannot parse HTML file %s to check if it is a valid result. Check manually.",
|
||||||
|
filePair[0],
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
guessedClass = classParser.parseClass(data['class_'])
|
guessedClass = classParser.parseClass(data["class_"])
|
||||||
except:
|
except:
|
||||||
self.l.error('Issue parsing class of file %s. Check manually.', filePair[0])
|
self.l.error(
|
||||||
|
"Issue parsing class of file %s. Check manually.", filePair[0]
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.l.debug('Fetched result data: %s, guessed class %s', data, guessedClass)
|
self.l.debug(
|
||||||
|
"Fetched result data: %s, guessed class %s", data, guessedClass
|
||||||
|
)
|
||||||
ret[filePair] = (parser, parserTab)
|
ret[filePair] = (parser, parserTab)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _extractPlace(self, placeStr: str):
|
def _extractPlace(self, placeStr: str):
|
||||||
s = placeStr.replace('.', '')
|
s = placeStr.replace(".", "")
|
||||||
|
|
||||||
matches = self.rePlaceSingle.fullmatch(s)
|
matches = self.rePlaceSingle.fullmatch(s)
|
||||||
if matches is not None:
|
if matches is not None:
|
||||||
@ -218,60 +244,78 @@ class ResultExtractor:
|
|||||||
return (int(matches.group(1)), int(matches.group(2)))
|
return (int(matches.group(1)), int(matches.group(2)))
|
||||||
|
|
||||||
self.l.error('Could not parse place string "%s"', placeStr)
|
self.l.error('Could not parse place string "%s"', placeStr)
|
||||||
raise Exception('Place cannot be parsed')
|
raise Exception("Place cannot be parsed")
|
||||||
|
|
||||||
def _analyzeSingleParser(self, parser: html_parser.HtmlParser, results: types.HtmlCompetitionTotalResults):
|
def _analyzeSingleParser(
|
||||||
|
self, parser: html_parser.HtmlParser, results: types.HtmlCompetitionTotalResults
|
||||||
|
):
|
||||||
data = parser.guessDataFromHtmlTitle()
|
data = parser.guessDataFromHtmlTitle()
|
||||||
competitionClass = data['class_']
|
competitionClass = data["class_"]
|
||||||
competitionGroup = data['group']
|
competitionGroup = data["group"]
|
||||||
dance = data['dance']
|
dance = data["dance"]
|
||||||
|
|
||||||
result = parser.parseResult()
|
result = parser.parseResult()
|
||||||
self.l.log(5, 'Raw data extracted: %s', result)
|
self.l.log(5, "Raw data extracted: %s", result)
|
||||||
|
|
||||||
for person in result.results.keys():
|
for person in result.results.keys():
|
||||||
placeStr = result.results[person]
|
placeStr = result.results[person]
|
||||||
place, placeTo = self._extractPlace(placeStr)
|
place, placeTo = self._extractPlace(placeStr)
|
||||||
competitionResult = types.HtmlSingleCompetitionResult(person.name, place, placeTo, person.finalist)
|
competitionResult = types.HtmlSingleCompetitionResult(
|
||||||
results.add(competitionGroup, competitionClass, dance, person.id, competitionResult)
|
person.name, place, placeTo, person.finalist
|
||||||
|
)
|
||||||
|
results.add(
|
||||||
|
competitionGroup, competitionClass, dance, person.id, competitionResult
|
||||||
|
)
|
||||||
#
|
#
|
||||||
|
|
||||||
def _analyzeIndividualResults(self, parser: html_parser.HtmlParser, results: types.HtmlCompetitionTotalResults):
|
def _analyzeIndividualResults(
|
||||||
|
self, parser: html_parser.HtmlParser, results: types.HtmlCompetitionTotalResults
|
||||||
|
):
|
||||||
data = parser.guessDataFromHtmlTitle()
|
data = parser.guessDataFromHtmlTitle()
|
||||||
competitionClass = data['class_']
|
competitionClass = data["class_"]
|
||||||
competitionGroup = data['group']
|
competitionGroup = data["group"]
|
||||||
dance = data['dance']
|
dance = data["dance"]
|
||||||
|
|
||||||
result = parser.parseIndividualResult(competitionGroup, competitionClass, dance)
|
result = parser.parseIndividualResult(competitionGroup, competitionClass, dance)
|
||||||
self.l.log(5, 'Found individual results: %s', result.participants)
|
self.l.log(5, "Found individual results: %s", result.participants)
|
||||||
results.tabges.update(result.participants)
|
results.tabges.update(result.participants)
|
||||||
|
|
||||||
def extractAllData(self, parsers: ParserList_t) -> types.HtmlCompetitionTotalResults:
|
def extractAllData(
|
||||||
|
self, parsers: ParserList_t
|
||||||
|
) -> types.HtmlCompetitionTotalResults:
|
||||||
ret = types.HtmlCompetitionTotalResults()
|
ret = types.HtmlCompetitionTotalResults()
|
||||||
|
|
||||||
for fileNameTuple in parsers:
|
for fileNameTuple in parsers:
|
||||||
fileName = fileNameTuple[0]
|
fileName = fileNameTuple[0]
|
||||||
self.l.debug('Extracting data from file %s', fileName)
|
self.l.debug("Extracting data from file %s", fileName)
|
||||||
self._analyzeSingleParser(parsers[fileNameTuple][0], ret)
|
self._analyzeSingleParser(parsers[fileNameTuple][0], ret)
|
||||||
|
|
||||||
if parsers[fileNameTuple][1] is None:
|
if parsers[fileNameTuple][1] is None:
|
||||||
self.l.info('Skipping extraction of individual result as class is not yet finished.')
|
self.l.info(
|
||||||
|
"Skipping extraction of individual result as class is not yet finished."
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.l.debug('Fetching individual result of combined competitions in %s', fileName)
|
self.l.debug(
|
||||||
|
"Fetching individual result of combined competitions in %s",
|
||||||
|
fileName,
|
||||||
|
)
|
||||||
self._analyzeIndividualResults(parsers[fileNameTuple][1], ret)
|
self._analyzeIndividualResults(parsers[fileNameTuple][1], ret)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class DataWorker:
|
class DataWorker:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.l = logging.getLogger('solo_turnier.worker.DataWorker')
|
self.l = logging.getLogger("solo_turnier.worker.DataWorker")
|
||||||
|
|
||||||
def combineRowsByPerson(self, rows: list[ResultRow]) -> dict[ResultPerson, list[CompetitionResult]]:
|
def combineRowsByPerson(
|
||||||
|
self, rows: list[ResultRow]
|
||||||
|
) -> dict[ResultPerson, list[CompetitionResult]]:
|
||||||
ret = {}
|
ret = {}
|
||||||
for row in rows:
|
for row in rows:
|
||||||
result = CompetitionResult.extractFromResultRow(row)
|
result = CompetitionResult.extractFromResultRow(row)
|
||||||
|
|
||||||
if result.place == '-' or result.placeTo == '-':
|
if result.place == "-" or result.placeTo == "-":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
person = ResultPerson.extractFromResultRow(row)
|
person = ResultPerson.extractFromResultRow(row)
|
||||||
@ -297,26 +341,31 @@ class DataWorker:
|
|||||||
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 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
|
The second one can be seen as a warning
|
||||||
"""
|
"""
|
||||||
def consolidateGroups(self, data:dict[ResultPerson, list[CompetitionResult]]) -> tuple[bool, bool]:
|
|
||||||
|
def consolidateGroups(
|
||||||
|
self, data: dict[ResultPerson, list[CompetitionResult]]
|
||||||
|
) -> tuple[bool, bool]:
|
||||||
ambiguous = False
|
ambiguous = False
|
||||||
warnChange = False
|
warnChange = False
|
||||||
|
|
||||||
unambiguousGroups = set(['Kin.', 'Jun.', 'Jug.'])
|
unambiguousGroups = set(["Kin.", "Jun.", "Jug."])
|
||||||
combinations = set(['Kin./Jun.', 'Jun./Jug.'])
|
combinations = set(["Kin./Jun.", "Jun./Jug."])
|
||||||
|
|
||||||
for person in data:
|
for person in data:
|
||||||
groupsRaw = set([c.group for c in data[person]])
|
groupsRaw = set([c.group for c in data[person]])
|
||||||
|
|
||||||
unknown = groupsRaw.difference(unambiguousGroups).difference(combinations)
|
unknown = groupsRaw.difference(unambiguousGroups).difference(combinations)
|
||||||
if len(unknown) > 0:
|
if len(unknown) > 0:
|
||||||
raise Exception(f'There were unknown groups found for {person}: {unknown}')
|
raise Exception(
|
||||||
|
f"There were unknown groups found for {person}: {unknown}"
|
||||||
|
)
|
||||||
|
|
||||||
numUnambiguousGroups = len(groupsRaw.intersection(unambiguousGroups))
|
numUnambiguousGroups = len(groupsRaw.intersection(unambiguousGroups))
|
||||||
|
|
||||||
if numUnambiguousGroups == 0:
|
if numUnambiguousGroups == 0:
|
||||||
if len(groupsRaw) == 2:
|
if len(groupsRaw) == 2:
|
||||||
warnChange = True
|
warnChange = True
|
||||||
person.group = 'Jun.'
|
person.group = "Jun."
|
||||||
else:
|
else:
|
||||||
ambiguous = True
|
ambiguous = True
|
||||||
if len(groupsRaw) == 1:
|
if len(groupsRaw) == 1:
|
||||||
@ -329,37 +378,57 @@ class DataWorker:
|
|||||||
person.group = list(groupsRaw.intersection(unambiguousGroups))[0]
|
person.group = list(groupsRaw.intersection(unambiguousGroups))[0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception(f'{person} cannot have different groups.')
|
raise Exception(f"{person} cannot have different groups.")
|
||||||
|
|
||||||
return (not ambiguous, warnChange)
|
return (not ambiguous, warnChange)
|
||||||
|
|
||||||
def _createHtmlLUT(self, htmlImports: list[html_parser.HtmlImport]):
|
def _createHtmlLUT(self, htmlImports: list[html_parser.HtmlImport]):
|
||||||
ret = {}
|
ret = {}
|
||||||
parser = html_parser.HtmlParser('')
|
parser = html_parser.HtmlParser("")
|
||||||
for imp in htmlImports:
|
for imp in htmlImports:
|
||||||
parsed = parser.guessDataFromHtmlTitle(imp.title)
|
parsed = parser.guessDataFromHtmlTitle(imp.title)
|
||||||
key = (parsed['group'], parsed['class_'], parsed['dance'])
|
key = (parsed["group"], parsed["class_"], parsed["dance"])
|
||||||
ret[key] = imp
|
ret[key] = imp
|
||||||
self.l.debug('LUT[%s] = %s', key, imp)
|
self.l.debug("LUT[%s] = %s", key, imp)
|
||||||
self.l.debug('LUT completed')
|
self.l.debug("LUT completed")
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def mergeHtmlData(self, data:dict[ResultPerson, list[CompetitionResult]], htmlImports: list[html_parser.HtmlImport]):
|
def mergeHtmlData(
|
||||||
|
self,
|
||||||
|
data: dict[ResultPerson, list[CompetitionResult]],
|
||||||
|
htmlImports: list[html_parser.HtmlImport],
|
||||||
|
):
|
||||||
lut = self._createHtmlLUT(htmlImports)
|
lut = self._createHtmlLUT(htmlImports)
|
||||||
|
|
||||||
for person in data:
|
for person in data:
|
||||||
for competition in data[person]:
|
for competition in data[person]:
|
||||||
key = (competition.competitionGroup, competition.competitionClass, competition.dance)
|
key = (
|
||||||
|
competition.competitionGroup,
|
||||||
|
competition.competitionClass,
|
||||||
|
competition.dance,
|
||||||
|
)
|
||||||
htmlImport = lut[key]
|
htmlImport = lut[key]
|
||||||
participant = htmlImport.participants[str(competition.id)]
|
participant = htmlImport.participants[str(competition.id)]
|
||||||
if participant.name != person.name:
|
if participant.name != person.name:
|
||||||
self.l.error(f'Names for {person} and participant in HTML import ({participant}) do not match. Please check carefully.')
|
self.l.error(
|
||||||
|
f"Names for {person} and participant in HTML import ({participant}) do not match. Please check carefully."
|
||||||
|
)
|
||||||
competition.finalist = participant.finalist
|
competition.finalist = participant.finalist
|
||||||
|
|
||||||
def getAllDancesInCompetitions(self, data:dict[ResultPerson, list[CompetitionResult]]) -> list[str]:
|
def getAllDancesInCompetitions(
|
||||||
|
self, data: dict[ResultPerson, list[CompetitionResult]]
|
||||||
|
) -> list[str]:
|
||||||
allDances = [
|
allDances = [
|
||||||
'Samba', 'Cha Cha', 'Rumba', 'Paso Doble', 'Jive',
|
"Samba",
|
||||||
'Langs. Walzer', 'Tango', 'Wiener Walzer', 'Slowfox', 'Quickstep'
|
"Cha Cha",
|
||||||
|
"Rumba",
|
||||||
|
"Paso Doble",
|
||||||
|
"Jive",
|
||||||
|
"Langs. Walzer",
|
||||||
|
"Tango",
|
||||||
|
"Wiener Walzer",
|
||||||
|
"Slowfox",
|
||||||
|
"Quickstep",
|
||||||
]
|
]
|
||||||
dancesPresent = {d: False for d in allDances}
|
dancesPresent = {d: False for d in allDances}
|
||||||
|
|
||||||
@ -369,21 +438,24 @@ class DataWorker:
|
|||||||
|
|
||||||
return [d for d in allDances if dancesPresent[d]]
|
return [d for d in allDances if dancesPresent[d]]
|
||||||
|
|
||||||
def collectPersonsInGroups(self, data:dict[ResultPerson, list[CompetitionResult]]) -> list[tuple[str, list[ResultPerson]]]:
|
def collectPersonsInGroups(
|
||||||
|
self, data: dict[ResultPerson, list[CompetitionResult]]
|
||||||
|
) -> list[tuple[str, list[ResultPerson]]]:
|
||||||
groups = {
|
groups = {
|
||||||
'Kin.': [p for p in data.keys() if p.group == 'Kin.'],
|
"Kin.": [p for p in data.keys() if p.group == "Kin."],
|
||||||
'Jun.': [p for p in data.keys() if p.group == 'Jun.'],
|
"Jun.": [p for p in data.keys() if p.group == "Jun."],
|
||||||
'Jug.': [p for p in data.keys() if p.group == 'Jug.'],
|
"Jug.": [p for p in data.keys() if p.group == "Jug."],
|
||||||
}
|
}
|
||||||
found = groups['Kin.'] + groups['Jun.'] + groups['Jug.']
|
found = groups["Kin."] + groups["Jun."] + groups["Jug."]
|
||||||
groups['Sonst'] = [p for p in data.keys() if p not in found]
|
groups["Sonst"] = [p for p in data.keys() if p not in found]
|
||||||
return groups
|
return groups
|
||||||
|
|
||||||
def sortPersonsInGroup(self, persons: list[ResultPerson]) -> list[ResultPerson]:
|
def sortPersonsInGroup(self, persons: list[ResultPerson]) -> list[ResultPerson]:
|
||||||
ids = [p.id for p in persons]
|
ids = [p.id for p in persons]
|
||||||
|
|
||||||
def decorateByName(p: ResultPerson):
|
def decorateByName(p: ResultPerson):
|
||||||
return (f'{p.name} ({p.club})', p)
|
return (f"{p.name} ({p.club})", p)
|
||||||
|
|
||||||
def decorateById(p: ResultPerson):
|
def decorateById(p: ResultPerson):
|
||||||
return (p.id, p)
|
return (p.id, p)
|
||||||
|
|
||||||
@ -399,91 +471,101 @@ class DataWorker:
|
|||||||
|
|
||||||
return ([d[1] for d in decorated], showIds)
|
return ([d[1] for d in decorated], showIds)
|
||||||
|
|
||||||
def mapPersonResultsToDanceList(self, results: list[CompetitionResult], dances: list[str]) -> list[CompetitionResult|None]:
|
def mapPersonResultsToDanceList(
|
||||||
|
self, results: list[CompetitionResult], dances: list[str]
|
||||||
|
) -> list[CompetitionResult | None]:
|
||||||
ret = []
|
ret = []
|
||||||
for dance in dances:
|
for dance in dances:
|
||||||
competitions = [c for c in results if c.dance == dance]
|
competitions = [c for c in results if c.dance == dance]
|
||||||
if len(competitions) == 0:
|
if len(competitions) == 0:
|
||||||
ret.append(None)
|
ret.append(None)
|
||||||
elif len(competitions) > 1:
|
elif len(competitions) > 1:
|
||||||
raise Exception(f'Multiple competitions with the same dance "{dance}" found.')
|
raise Exception(
|
||||||
|
f'Multiple competitions with the same dance "{dance}" found.'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
ret.append(competitions[0])
|
ret.append(competitions[0])
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class Worker:
|
class Worker:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.l = logging.getLogger('solo_turnier.worker.Worker')
|
self.l = logging.getLogger("solo_turnier.worker.Worker")
|
||||||
self._allDances = (
|
self._allDances = ["Samba", "Cha Cha", "Rumba", "Paso Doble", "Jive"] + [
|
||||||
['Samba', 'Cha Cha', 'Rumba', 'Paso Doble', 'Jive'] +
|
"Langs. Walzer",
|
||||||
['Langs. Walzer', 'Tango', 'Wiener Walzer', 'Slowfox', 'Quickstep']
|
"Tango",
|
||||||
)
|
"Wiener Walzer",
|
||||||
|
"Slowfox",
|
||||||
|
"Quickstep",
|
||||||
|
]
|
||||||
|
|
||||||
def collectAllData(
|
def collectAllData(
|
||||||
self,
|
self, htmlCandidatesPreview: list[str], htmlResultsFileNames: list[str]
|
||||||
htmlCandidatesPreview: list[str],
|
|
||||||
htmlResultsFileNames: list[str]
|
|
||||||
) -> types.State3:
|
) -> types.State3:
|
||||||
|
|
||||||
previewWorker = PreviewWorker()
|
previewWorker = PreviewWorker()
|
||||||
self.l.info('Filtering for pure preview rounds.')
|
self.l.info("Filtering for pure preview rounds.")
|
||||||
parsers = previewWorker.filterFilesPreview(htmlCandidatesPreview)
|
parsers = previewWorker.filterFilesPreview(htmlCandidatesPreview)
|
||||||
self.l.debug('Remaining files: %s', list(parsers.keys()))
|
self.l.debug("Remaining files: %s", list(parsers.keys()))
|
||||||
|
|
||||||
self.l.info('Extracting person data from the preview rounds.')
|
self.l.info("Extracting person data from the preview rounds.")
|
||||||
previewImport = previewWorker.importAllData(parsers)
|
previewImport = previewWorker.importAllData(parsers)
|
||||||
self.l.debug('Total preview imported participants: %s', pformat(previewImport.participants))
|
self.l.debug(
|
||||||
self.l.log(5, 'Total preview results: %s', pformat(previewImport.results))
|
"Total preview imported participants: %s",
|
||||||
|
pformat(previewImport.participants),
|
||||||
|
)
|
||||||
|
self.l.log(5, "Total preview results: %s", pformat(previewImport.results))
|
||||||
|
|
||||||
resultExtractor = ResultExtractor()
|
resultExtractor = ResultExtractor()
|
||||||
resultParsers = resultExtractor.getAllParsers(htmlResultsFileNames)
|
resultParsers = resultExtractor.getAllParsers(htmlResultsFileNames)
|
||||||
htmlResults = resultExtractor.extractAllData(resultParsers)
|
htmlResults = resultExtractor.extractAllData(resultParsers)
|
||||||
self.l.info('Overall result data extracted: %s', pformat(htmlResults.results))
|
self.l.info("Overall result data extracted: %s", pformat(htmlResults.results))
|
||||||
|
|
||||||
return types.State3(previewImport, htmlResults)
|
return types.State3(previewImport, htmlResults)
|
||||||
|
|
||||||
def combineData(self, importedData: types.State3):
|
def combineData(self, importedData: types.State3):
|
||||||
self.l.info('Starting to build data sets.')
|
self.l.info("Starting to build data sets.")
|
||||||
groups = self._extractGroups(importedData)
|
groups = self._extractGroups(importedData)
|
||||||
self.l.debug('Found groups in the dataset: %s', groups)
|
self.l.debug("Found groups in the dataset: %s", groups)
|
||||||
|
|
||||||
totalResult = {}
|
totalResult = {}
|
||||||
|
|
||||||
for group in groups:
|
for group in groups:
|
||||||
self.l.debug('Collecting data for total result of group %s', group)
|
self.l.debug("Collecting data for total result of group %s", group)
|
||||||
|
|
||||||
dances = self._extractDancesPerGroup(importedData, group)
|
dances = self._extractDancesPerGroup(importedData, group)
|
||||||
self.l.log(5, 'Found dances in group %s: %s', group, dances)
|
self.l.log(5, "Found dances in group %s: %s", group, dances)
|
||||||
|
|
||||||
participants = self._extractParticipantsPerGroup(importedData, group)
|
participants = self._extractParticipantsPerGroup(importedData, group)
|
||||||
self.l.log(5, 'Related participants %s', participants)
|
self.l.log(5, "Related participants %s", participants)
|
||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
for participant in participants:
|
for participant in participants:
|
||||||
self.l.log(5, 'Collecting data for %s', participant)
|
self.l.log(5, "Collecting data for %s", participant)
|
||||||
resultsOfParticipant = self._getResultOfSingleParticipant(
|
resultsOfParticipant = self._getResultOfSingleParticipant(
|
||||||
participant, group, importedData.previewImport,
|
participant,
|
||||||
importedData.htmlResults, dances
|
group,
|
||||||
)
|
importedData.previewImport,
|
||||||
self.l.log(5, 'Obtained result %s', resultsOfParticipant)
|
importedData.htmlResults,
|
||||||
|
dances,
|
||||||
|
)
|
||||||
|
self.l.log(5, "Obtained result %s", resultsOfParticipant)
|
||||||
results[participant] = resultsOfParticipant
|
results[participant] = resultsOfParticipant
|
||||||
|
|
||||||
self.l.log(5, 'Result before native fixing: %s', pformat(results))
|
self.l.log(5, "Result before native fixing: %s", pformat(results))
|
||||||
# self._fixNativePlaces(dances, results)
|
# self._fixNativePlaces(dances, results)
|
||||||
self._fixNativeDataFromTable(dances, results, importedData.htmlResults)
|
self._fixNativeDataFromTable(dances, results, importedData.htmlResults)
|
||||||
self.l.log(5, 'Result after native fixing: %s', pformat(results))
|
self.l.log(5, "Result after native fixing: %s", pformat(results))
|
||||||
# self.l.log(5,'Fixed data %s', results)
|
# self.l.log(5,'Fixed data %s', results)
|
||||||
|
|
||||||
totalResult[group] = types.TotalGroupResult(dances, results)
|
totalResult[group] = types.TotalGroupResult(dances, results)
|
||||||
|
|
||||||
self.l.log(5, 'Total result of all groups: %s', pformat(totalResult))
|
self.l.log(5, "Total result of all groups: %s", pformat(totalResult))
|
||||||
|
|
||||||
ret = types.State4(totalResult)
|
ret = types.State4(totalResult)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def _extractGroups(self, data: types.State3):
|
def _extractGroups(self, data: types.State3):
|
||||||
groupParser = solo_turnier.group.GroupParser()
|
groupParser = solo_turnier.group.GroupParser()
|
||||||
|
|
||||||
@ -498,11 +580,13 @@ class Worker:
|
|||||||
groupSet.update(gr.getContainedGroups())
|
groupSet.update(gr.getContainedGroups())
|
||||||
# self.l.log(5, 'Group type %s', type(gr))
|
# self.l.log(5, 'Group type %s', type(gr))
|
||||||
|
|
||||||
self.l.log(5, 'Set of active groups: %s', groupSet)
|
self.l.log(5, "Set of active groups: %s", groupSet)
|
||||||
groups = groupParser.getGroupsAsSortedList(groupSet)
|
groups = groupParser.getGroupsAsSortedList(groupSet)
|
||||||
return groups
|
return groups
|
||||||
|
|
||||||
def _extractDancesPerGroup(self, data: types.State3, group: solo_turnier.group.Group):
|
def _extractDancesPerGroup(
|
||||||
|
self, data: types.State3, group: solo_turnier.group.Group
|
||||||
|
):
|
||||||
groupParser = solo_turnier.group.GroupParser()
|
groupParser = solo_turnier.group.GroupParser()
|
||||||
|
|
||||||
dances = set()
|
dances = set()
|
||||||
@ -518,7 +602,10 @@ class Worker:
|
|||||||
additionalDances.update(foundDances.difference(self._allDances))
|
additionalDances.update(foundDances.difference(self._allDances))
|
||||||
|
|
||||||
if len(additionalDances) > 0:
|
if len(additionalDances) > 0:
|
||||||
self.l.error('There were dances found, that are not registered. A bug? The dances were: %s', additionalDances)
|
self.l.error(
|
||||||
|
"There were dances found, that are not registered. A bug? The dances were: %s",
|
||||||
|
additionalDances,
|
||||||
|
)
|
||||||
|
|
||||||
dancesList = [x for x in self._allDances if x in dances]
|
dancesList = [x for x in self._allDances if x in dances]
|
||||||
additionalDancesList = list(additionalDances)
|
additionalDancesList = list(additionalDances)
|
||||||
@ -529,8 +616,8 @@ class Worker:
|
|||||||
self,
|
self,
|
||||||
importedData: types.State3,
|
importedData: types.State3,
|
||||||
# previewData: types.HtmlPreviewImport,
|
# previewData: types.HtmlPreviewImport,
|
||||||
group: solo_turnier.group.Group
|
group: solo_turnier.group.Group,
|
||||||
) -> list[types.HtmlPreviewParticipant]:
|
) -> list[types.HtmlPreviewParticipant]:
|
||||||
groupParser = types.group.GroupParser()
|
groupParser = types.group.GroupParser()
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
@ -546,14 +633,14 @@ class Worker:
|
|||||||
|
|
||||||
fixture = importedData.htmlResults.tabges[tup]
|
fixture = importedData.htmlResults.tabges[tup]
|
||||||
if fixture[2] is not None and fixture[2] != group:
|
if fixture[2] is not None and fixture[2] != group:
|
||||||
self.l.log(5, 'Skipping id %s in group %s as not part', tup[3], group)
|
self.l.log(5, "Skipping id %s in group %s as not part", tup[3], group)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
part = importedData.htmlResults.results[tup][0]
|
part = importedData.htmlResults.results[tup][0]
|
||||||
part.id = int(tup[3])
|
part.id = int(tup[3])
|
||||||
ret.append(part)
|
ret.append(part)
|
||||||
|
|
||||||
self.l.log(5, 'ret %s', ret)
|
self.l.log(5, "ret %s", ret)
|
||||||
# raise Exception('Test')
|
# raise Exception('Test')
|
||||||
|
|
||||||
# for id in previewData.participants:
|
# for id in previewData.participants:
|
||||||
@ -569,23 +656,25 @@ class Worker:
|
|||||||
nominalGroup: solo_turnier.group.Group,
|
nominalGroup: solo_turnier.group.Group,
|
||||||
previewResults: types.HtmlPreviewImport,
|
previewResults: types.HtmlPreviewImport,
|
||||||
totalResults: types.HtmlCompetitionTotalResults,
|
totalResults: types.HtmlCompetitionTotalResults,
|
||||||
allDances: list[str]
|
allDances: list[str],
|
||||||
) -> list[types.SingleParticipantResult|None]:
|
) -> list[types.SingleParticipantResult | None]:
|
||||||
rawResults = totalResults.getById(participant.id)
|
rawResults = totalResults.getById(participant.id)
|
||||||
self.l.log(5, 'Found result data for id %i (raw): %s', participant.id, rawResults)
|
self.l.log(
|
||||||
|
5, "Found result data for id %i (raw): %s", participant.id, rawResults
|
||||||
|
)
|
||||||
|
|
||||||
results = [None for x in allDances]
|
results = [None for x in allDances]
|
||||||
|
|
||||||
for danceIdx, dance in enumerate(allDances):
|
for danceIdx, dance in enumerate(allDances):
|
||||||
# self.l.log(5, '%s %s', dance, danceIdx)
|
# self.l.log(5, '%s %s', dance, danceIdx)
|
||||||
def getResult() -> types.SingleParticipantResult|None:
|
def getResult() -> types.SingleParticipantResult | None:
|
||||||
for key in rawResults:
|
for key in rawResults:
|
||||||
if key[0] != dance:
|
if key[0] != dance:
|
||||||
continue
|
continue
|
||||||
rawResult = rawResults[key]
|
rawResult = rawResults[key]
|
||||||
|
|
||||||
if len(rawResult) != 1:
|
if len(rawResult) != 1:
|
||||||
raise Exception('Multiple results found with same key')
|
raise Exception("Multiple results found with same key")
|
||||||
rawResult = rawResult[0]
|
rawResult = rawResult[0]
|
||||||
|
|
||||||
nativeClass = key[2]
|
nativeClass = key[2]
|
||||||
@ -594,8 +683,12 @@ class Worker:
|
|||||||
|
|
||||||
# self.l.log(5, 'Result %s => %s', key, rawResult)
|
# self.l.log(5, 'Result %s => %s', key, rawResult)
|
||||||
ret = types.SingleParticipantResult(
|
ret = types.SingleParticipantResult(
|
||||||
key[2], nativeClass, dance, rawResult.finalist,
|
key[2],
|
||||||
rawResult.place, rawResult.placeTo
|
nativeClass,
|
||||||
|
dance,
|
||||||
|
rawResult.finalist,
|
||||||
|
rawResult.place,
|
||||||
|
rawResult.placeTo,
|
||||||
)
|
)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@ -609,18 +702,18 @@ class Worker:
|
|||||||
self,
|
self,
|
||||||
dances: list[str],
|
dances: list[str],
|
||||||
data: dict[types.HtmlPreviewParticipant, list[types.SingleParticipantResult]],
|
data: dict[types.HtmlPreviewParticipant, list[types.SingleParticipantResult]],
|
||||||
importedData: types.HtmlCompetitionTotalResults
|
importedData: types.HtmlCompetitionTotalResults,
|
||||||
):
|
):
|
||||||
rePlace = re.compile('([0-9]+)(?:-([0-9]+))?')
|
rePlace = re.compile("([0-9]+)(?:-([0-9]+))?")
|
||||||
classParser = competition_class.CompetitionClassParser()
|
classParser = competition_class.CompetitionClassParser()
|
||||||
|
|
||||||
for participant in data.keys():
|
for participant in data.keys():
|
||||||
self.l.log(5, 'fixing participant %s', participant)
|
self.l.log(5, "fixing participant %s", participant)
|
||||||
results = data[participant]
|
results = data[participant]
|
||||||
for result in results:
|
for result in results:
|
||||||
if result is None:
|
if result is None:
|
||||||
continue
|
continue
|
||||||
self.l.log(5, 'Looking at result set %s', result)
|
self.l.log(5, "Looking at result set %s", result)
|
||||||
|
|
||||||
def selectEntry(k):
|
def selectEntry(k):
|
||||||
return k[2] == result.dance and int(k[3]) == participant.id
|
return k[2] == result.dance and int(k[3]) == participant.id
|
||||||
@ -633,13 +726,19 @@ class Worker:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
raw = importedData.tabges[keys[selectedIndex]]
|
raw = importedData.tabges[keys[selectedIndex]]
|
||||||
self.l.log(5,'Raw %s', raw)
|
self.l.log(5, "Raw %s", raw)
|
||||||
nativePlaceRaw = raw[0]
|
nativePlaceRaw = raw[0]
|
||||||
matcher = rePlace.fullmatch(nativePlaceRaw)
|
matcher = rePlace.fullmatch(nativePlaceRaw)
|
||||||
if matcher is None:
|
if matcher is None:
|
||||||
self.l.error('Cannot parse place string %s for participant %u (%s) in dance %s', nativePlaceRaw, participant.id, participant, result.dance)
|
self.l.error(
|
||||||
|
"Cannot parse place string %s for participant %u (%s) in dance %s",
|
||||||
|
nativePlaceRaw,
|
||||||
|
participant.id,
|
||||||
|
participant,
|
||||||
|
result.dance,
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
self.l.log(5, 'Found strings by regex: %s', matcher.groups())
|
self.l.log(5, "Found strings by regex: %s", matcher.groups())
|
||||||
result.placeNative = matcher.group(1)
|
result.placeNative = matcher.group(1)
|
||||||
result.placeNativeTo = matcher.group(2)
|
result.placeNativeTo = matcher.group(2)
|
||||||
|
|
||||||
@ -651,15 +750,17 @@ class Worker:
|
|||||||
def _fixNativePlaces(
|
def _fixNativePlaces(
|
||||||
self,
|
self,
|
||||||
dances: list[str],
|
dances: list[str],
|
||||||
data: dict[types.HtmlPreviewParticipant, list[types.SingleParticipantResult]]
|
data: dict[types.HtmlPreviewParticipant, list[types.SingleParticipantResult]],
|
||||||
):
|
):
|
||||||
classParser = solo_turnier.competition_class.CompetitionClassParser()
|
classParser = solo_turnier.competition_class.CompetitionClassParser()
|
||||||
allClasses = classParser.getAllClasses()
|
allClasses = classParser.getAllClasses()
|
||||||
allClasses.reverse()
|
allClasses.reverse()
|
||||||
|
|
||||||
for class_ in allClasses:
|
for class_ in allClasses:
|
||||||
for danceIdx, dance in enumerate(dances):
|
for danceIdx, dance in enumerate(dances):
|
||||||
self.l.log(5, 'Fixing native places for class %s in dance %s', class_, dance)
|
self.l.log(
|
||||||
|
5, "Fixing native places for class %s in dance %s", class_, dance
|
||||||
|
)
|
||||||
|
|
||||||
remainingParticipants = []
|
remainingParticipants = []
|
||||||
|
|
||||||
@ -676,7 +777,9 @@ class Worker:
|
|||||||
# self.l.log(5, 'Skipping %s as the native class is higher', participant)
|
# self.l.log(5, 'Skipping %s as the native class is higher', participant)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
remainingParticipants.append((danceResult.place, participant.id, participant))
|
remainingParticipants.append(
|
||||||
|
(danceResult.place, participant.id, participant)
|
||||||
|
)
|
||||||
|
|
||||||
remainingParticipants.sort()
|
remainingParticipants.sort()
|
||||||
# self.l.log(5, 'Remaining participants %s', remainingParticipants)
|
# self.l.log(5, 'Remaining participants %s', remainingParticipants)
|
||||||
@ -684,7 +787,10 @@ class Worker:
|
|||||||
def getAllParticipantsWithSamePlace():
|
def getAllParticipantsWithSamePlace():
|
||||||
first = remainingParticipants.pop(0)
|
first = remainingParticipants.pop(0)
|
||||||
ret = [first]
|
ret = [first]
|
||||||
while len(remainingParticipants) > 0 and remainingParticipants[0][0] == first[0]:
|
while (
|
||||||
|
len(remainingParticipants) > 0
|
||||||
|
and remainingParticipants[0][0] == first[0]
|
||||||
|
):
|
||||||
ret.append(remainingParticipants.pop(0))
|
ret.append(remainingParticipants.pop(0))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -711,26 +817,31 @@ class Worker:
|
|||||||
|
|
||||||
def filterOutFinalists(self, data: types.State4, filterOut: bool):
|
def filterOutFinalists(self, data: types.State4, filterOut: bool):
|
||||||
for group in data.results:
|
for group in data.results:
|
||||||
self.l.debug('Cleaning up group %s', group.name)
|
self.l.debug("Cleaning up group %s", group.name)
|
||||||
participants = data.results[group].results.keys()
|
participants = data.results[group].results.keys()
|
||||||
droppedParticipants = []
|
droppedParticipants = []
|
||||||
|
|
||||||
for participant in participants:
|
for participant in participants:
|
||||||
self.l.debug('Checking %s', participant)
|
self.l.debug("Checking %s", participant)
|
||||||
|
|
||||||
def isFinalistInDance(x: types.HtmlSingleCompetitionResult|None):
|
def isFinalistInDance(x: types.HtmlSingleCompetitionResult | None):
|
||||||
if x is None:
|
if x is None:
|
||||||
return False
|
return False
|
||||||
return x.finalist
|
return x.finalist
|
||||||
mapped = list(map(isFinalistInDance, data.results[group].results[participant]))
|
|
||||||
|
mapped = list(
|
||||||
|
map(isFinalistInDance, data.results[group].results[participant])
|
||||||
|
)
|
||||||
finalist = True in mapped
|
finalist = True in mapped
|
||||||
self.l.log(5,'Check for finalist (in dances %s): %s', mapped, finalist)
|
self.l.log(5, "Check for finalist (in dances %s): %s", mapped, finalist)
|
||||||
|
|
||||||
if finalist:
|
if finalist:
|
||||||
participant.finalist = True
|
participant.finalist = True
|
||||||
else:
|
else:
|
||||||
participant.finalist = False
|
participant.finalist = False
|
||||||
self.l.info('Dropping %s from the output as no finalist', participant)
|
self.l.info(
|
||||||
|
"Dropping %s from the output as no finalist", participant
|
||||||
|
)
|
||||||
droppedParticipants.append(participant)
|
droppedParticipants.append(participant)
|
||||||
|
|
||||||
if filterOut:
|
if filterOut:
|
||||||
|
Loading…
Reference in New Issue
Block a user