advent-of-code/leaderboard/app.py

87 lines
2.8 KiB
Python

import collections
from datetime import datetime
import json
import os
import urllib
from flask import Flask, render_template, request
os.environ["TZ"] = "Europe/Stockholm"
app = Flask(__name__)
def get_data(token, calendar, leaderboard, dummy_data=True):
if dummy_data:
with open("leaderboard.json") as lb:
data = lb.read()
else:
try:
url = f"https://adventofcode.com/{calendar}/leaderboard/private/view/{leaderboard}.json"
headers = {"Cookie": f"session={token}"}
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req) as response:
data = response.read()
except TypeError:
data = "[]"
except urllib.error.HTTPError:
data = "[]"
return json.loads(data)
@app.route("/")
def hello_world():
calendar = request.args.get("calendar", datetime.now().year)
leaderboard = request.args.get("board")
token = request.args.get("token")
if not token:
return "Missing token get parameter. Use the session cookie on adventofcode.com"
if not leaderboard:
return "Missing board get parameter."
data = get_data(token, calendar, leaderboard, False)
if len(data) == 0:
return "Token expired or no access to board"
leaderboard = sorted(
[
(int(member["local_score"]), int(member["stars"]), member["name"])
for _, member in data["members"].items()
if int(member["stars"]) > 0
],
key=lambda x: x[0],
reverse=True,
)
timeline = collections.defaultdict(lambda: [])
for _id, m in data["members"].items():
for d, stars in m["completion_day_level"].items():
for p, tsd in stars.items():
ts = datetime.fromtimestamp(tsd["get_star_ts"])
timeline[d].append(
(datetime.strftime(ts, "%Y-%m-%dT%H:%M:%S"), d, p, m["name"])
)
timeline = sorted(timeline.items(), key=lambda x: int(x[0]), reverse=True)
timeline = [
(
d,
sorted(
tl, key=lambda entry: datetime.strptime(entry[0], "%Y-%m-%dT%H:%M:%S")
),
)
for d, tl in timeline
]
timeline = [
(
d,
[
te + (get_score(time_entries, te, len(data["members"])),)
for te in time_entries
],
)
for d, time_entries in timeline
]
return render_template("main.jinja2", leaderboard=leaderboard, timeline=timeline)
def get_score(time_entries, current_te, nr_competitors):
list_for_current_star = [te for te in time_entries if te[2] == current_te[2]]
pos = [i for i, te in enumerate(list_for_current_star) if te[3] == current_te[3]][0]
return nr_competitors - pos