87 lines
2.8 KiB
Python
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 = os.environ.get("AOC_TOKEN")
|
|
if not token:
|
|
return "Missing AOC_TOKEN environment variable. 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
|