ssbu_lokrez/lokrez/__init__.py

398 lines
12 KiB
Python

import argparse
import datetime
import logging
import os, os.path
import sys
import jinja2
import smashgg
import version
# =============================================================================
def main():
# -------------------------------------------------------------------------
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(
dest = "command",
help = "commands",
)
parser.add_argument( "--proxy", "-p",
default = None,
help = "the proxy to use" )
parser.add_argument( "--token", "-t",
default = None,
help = "the authentication token to use" )
# -------------------------------------------------------------------------
top8_parser = subparsers.add_parser(
"top8",
)
top8_parser.add_argument(
"tournament",
default = None,
help = "The tournament slug or id",
)
top8_parser.add_argument(
"--resourcesdir", "-RD",
default = "res",
help = "The directories containing images and templates resources",
)
top8_parser.add_argument(
"--templatesdir", "-TD",
default = "templates",
help = "The local result templates directory",
)
top8_parser.add_argument(
"--template", "-T",
default = "rebootlyon",
help = "The local result template to use",
)
top8_parser.add_argument(
"--lkrz-file", "-f",
default = None,
help = "The lkrz file in which the results are stored ; if it " \
"does not exist, one will be created from the smashgg data",
)
top8_parser.add_argument(
"--outfile", "-o",
default = None,
help = "The SVG local result file to output to ; defaults to " \
"./tournament-slug.svg",
)
# -------------------------------------------------------------------------
parser.add_argument( "--verbose", "-v",
default = 0,
action = "count",
help = "increase verbosity" )
parser.add_argument( "--version", "-V",
default = False,
action = "store_true",
help = "show version number" )
# -------------------------------------------------------------------------
args = parser.parse_args()
# Set log level
# -------------------------------------------------------------------------
log = logging.getLogger(version.NAME)
log.setLevel(logging.DEBUG)
log_handler_console = logging.StreamHandler()
log_handler_console.setLevel(logging.WARNING)
if(args.verbose >= 2):
log_handler_console.setLevel(logging.DEBUG)
elif(args.verbose >=1):
log_handler_console.setLevel(logging.INFO)
else:
log_handler_console.setLevel(logging.WARNING)
log_formatter_console = logging.Formatter("%(name)s:%(levelname)s: %(message)s")
log_handler_console.setFormatter(log_formatter_console)
log.addHandler(log_handler_console)
# Print version if required
# -------------------------------------------------------------------------
if args.version:
print(version.VERSION_NAME)
sys.exit(0)
# -------------------------------------------------------------------------
if args.command not in [ "top8" ]:
parser.print_help()
sys.exit(1)
# -------------------------------------------------------------------------
if args.command == "top8":
try:
with open(args.lkrz_file, "r") as f:
# TODO parse config file to fill tournament & top_players
log.error("config file loading is not implemened yet")
raise NotImplementedError
except:
# Get infos from smash.gg and write the config file
tournament, top_players = getTournamentTop(
id_or_slug = args.tournament,
top = 8,
token = args.token,
proxy = args.proxy,
log = log,
)
if tournament is None or top_players is None:
log.error("Could not load data from smash.gg")
sys.exit(1)
lkrz_data = "\n".join(
[ tournament.conf() ] \
+ list(map(
lambda p:p.conf(),
top_players.values(),
))
)
if args.lkrz_file is None:
args.lkrz_file = "{}.lkrz".format(tournament.slug)
with open(args.lkrz_file, "w", encoding="utf8") as f:
f.write(lkrz_data)
# Template rendering
log.info("Génération du SVG en utilisant le template")
jj2_env = jinja2.Environment(
loader = jinja2.FileSystemLoader(
os.path.join(
args.resourcesdir,
args.templatesdir,
)
)
)
jj2_tpl = jj2_env.get_template(
os.path.join(
args.template,
"template.svg.j2",
)
)
context = {
"tournament": tournament,
"players" : sorted(
top_players.values(),
key = lambda p: p.placement,
),
"imgdir_ssbu_chars": os.path.join(
args.resourcesdir,
"ssbu",
"Super Smash Bros Ultimate",
"Fighter Portraits",
),
}
if args.outfile is None:
args.outfile = "{}.svg".format(tournament.slug)
jj2_tpl.stream(context).dump( args.outfile )
# -----------------------------------------------------------------------------
def getTournamentTop(
id_or_slug,
top=8,
token = "",
proxy = None,
log=None):
"""Returns a tuple : the smashgg.Tournament object and a list of the top
smashgg.Player in that tournament."""
# -------------------------------------------------------------------------
# Select the right event (the one with the most entrants or the most sets)
def selectBiggestEvent(data, log=None):
try:
event = data["events"][0]
except:
log.error("No event found in data")
log.debug(data)
return None
try:
numEntrants = event["numEntrants"]
except KeyError:
numEntrants = event["standings"]["pageInfo"]["total"]
for e in data["events"]:
try:
ne = e["numEntrants"]
except KeyError:
ne = e["standings"]["pageInfo"]["total"]
if ne > numEntrants:
event = e
numEntrants = ne
log.info("Selected Event '{}' with {} entrants" \
.format(
event["name"],
numEntrants,
))
return event
# -------------------------------------------------------------------------
data = None
try:
data = smashgg.run_query(
query_name = "getTournamentTopById",
variables = {
"id" : int(id_or_slug), # If this fails, it's a slug
"top": top,
},
token = token,
proxy = proxy,
log = log,
)
except ValueError:
data = smashgg.run_query(
query_name = "getTournamentTopBySlug",
variables = {
"slug" : id_or_slug,
"top": top,
},
token = token,
proxy = proxy,
log = log,
)
try:
tournament_data = data["tournament"]
except:
log.error("Failed to load Tournaments")
return None,None
if tournament_data is None:
log.error("Failed to load Tournament")
return None,None
event = selectBiggestEvent(tournament_data, log)
if event is None :
return None,None
# Get the tournament
tournament = smashgg.Tournament(
id = tournament_data["id"],
slug = tournament_data["slug"],
name = tournament_data["name"],
startAt = \
datetime.datetime. \
fromtimestamp(tournament_data["startAt"]),
numEntrants = event["standings"]["pageInfo"]["total"],
venueAddress = tournament_data["venueAddress"],
venueName = tournament_data["venueName"],
city = tournament_data["city"],
countryCode = tournament_data["countryCode"],
hashtag = tournament_data["hashtag"],
)
# Get the top players
top_players = {}
standings = event["standings"]["nodes"]
for standing in standings :
seeding = None
for seed in standing["entrant"]["seeds"]:
# Take the seeding from the phase with *all* Event entrants
if seed["phase"]["numSeeds"] == tournament.numEntrants:
seeding = seed["groupSeedNum"]
participant_data = standing["entrant"]["participants"][0]
try:
twitterHandle = participant_data \
["player"] \
["user"] \
["authorizations"] \
[0] \
["externalUsername"]
except TypeError:
twitterHandle = None
player = smashgg.Player(
id = standing["entrant"]["id"],
prefix = participant_data["prefix"],
gamerTag = participant_data["gamerTag"],
placement = standing["placement"],
seeding = seeding,
twitterHandle = twitterHandle,
)
top_players[player.id] = player
# -------------------------------------------------------------------------
# Now, we need to find which characters those top players chose
data = None
data = smashgg.run_query(
query_name = "getCharsByTournamentIdAndEntrantIds",
variables = {
"tournamentId" : int(tournament.id),
"entrantIds": [ id for id in top_players.keys() ],
},
token = token,
proxy = proxy,
log = log,
)
try:
tournament_data = data["tournament"]
except:
log.error("Failed to load Tournament")
return None,None
if tournament_data is None:
log.error("Failed to load Tournament")
return None,None
event = selectBiggestEvent(tournament_data, log)
if event is None :
return None,None
# TODO check that sets number is < to hardcoded 100 max value (cf query)
sets = event["sets"]["nodes"]
for s in sets:
try:
for g in s["games"]:
winnerId = g["winnerId"]
for slct in g["selections"]:
if slct["selectionType"] == "CHARACTER":
eid = slct["entrant"]["id"]
try:
top_players[eid].add_character_selection(
character = slct["selectionValue"],
win = (winnerId == eid),
)
except KeyError:
pass
except TypeError:
# If some games or selections are null, this can happen
continue
# Return the data
return tournament, top_players
# =============================================================================
if __name__ == '__main__':
main()