-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathleaderboard.py
149 lines (127 loc) · 4.75 KB
/
leaderboard.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import json
from datetime import datetime, timedelta
import numpy as np
import pandas as pd
import streamlit as st
from plotly import express as px
def load_json(fn: str) -> dict:
with open(fn) as file:
content = json.load(file)
return content
def json_to_dataframe(data_json: dict, year: int) -> pd.DataFrame:
def tokey(k: int, p: int) -> str:
return f"{k}_{p}"
index = []
data = {f"{k}_{p}": [] for k in range(26) for p in range(1, 3)}
data.update({f"{k}_{p}_delta": [] for k in range(26) for p in range(1, 3)})
other_keys = ["local_score", "global_score", "stars", "last_star_ts"]
for key in other_keys:
data[key] = []
ignore_empty_members = st.checkbox(
"Ignore members without participation", value=True
)
for _, member in data_json["members"].items():
if member["stars"] == 0 and ignore_empty_members:
continue
index.append(member["name"])
for key in other_keys:
data[key].append(member[key])
completions = member["completion_day_level"]
for k in range(1, 26):
start_time = (datetime(year, 12, k) + timedelta(hours=6)).timestamp()
for p in range(1, 3):
if str(k) in completions and str(p) in completions[str(k)]:
time = completions[str(k)][str(p)]["get_star_ts"]
data[tokey(k, p)].append(time)
data[tokey(k, p) + "_delta"].append(time - start_time)
else:
data[tokey(k, p)].append(None)
data[tokey(k, p) + "_delta"].append(None)
for k in range(26):
if np.all(np.array(data[tokey(k, 1)]) == None):
del data[tokey(k, 1)]
del data[tokey(k, 2)]
del data[tokey(k, 1) + "_delta"]
del data[tokey(k, 2) + "_delta"]
return pd.DataFrame(data, index)
def add_dt(df: pd.DataFrame):
for k in range(26):
if f"{k}_1" not in df.columns:
continue
df[f"{k}_dt"] = df[f"{k}_2"] - df[f"{k}_1"]
def custom_score(df: pd.DataFrame, format_key: str):
scores = list(range(len(df), 0, -1))
format_score = format_key + "_score"
df[format_key.format("total") + "_score"] = 0
for k in range(26):
if format_key.format(k) not in df.columns:
continue
df[format_score.format(k)] = 0
sorted_vals = df[format_key.format(k)].sort_values()
for nu, (name, val) in enumerate(sorted_vals.items()):
if not pd.isna(val):
df.at[name, format_score.format(k)] = scores[nu]
df[format_score.format("total")] += df[format_score.format(k)]
def chart(df: pd.DataFrame, format_key: str, ylog: bool):
data = dict()
for k in range(26):
if format_key.format(k) not in df.columns:
continue
data[k] = df[format_key.format(k)]
df = pd.DataFrame(data)
long = df.T.melt(ignore_index=False)
long.index.name = "Day"
long.rename(columns={"value": "Score", "variable": "Name"}, inplace=True)
fig = px.line(long, x=long.index, y="Score", color="Name", log_y=ylog)
st.plotly_chart(fig)
def main(fn: str):
# load data
now = datetime.now()
max_year = now.year - (now.month < 12)
year = st.number_input("Current year", 2015, max_year, max_year)
data_json = load_json(fn)
df = json_to_dataframe(data_json, year)
# add custom score
add_dt(df)
custom_score(df, "{}_dt")
custom_score(df, "{}_1")
custom_score(df, "{}_2")
for k in range(26):
if f"{k}_1_score" not in df.columns:
continue
df[f"{k}_local_score"] = df[f"{k}_1_score"] + df[f"{k}_2_score"]
df["total_local_score"] = df["total_1_score"] + df["total_2_score"]
df = df.sort_values(
by=["stars", "total_dt_score", "total_local_score"], ascending=False
)
# display table
print_keys = st.multiselect(
"Which keys should be shown?",
df.columns,
[
"stars",
"local_score",
"global_score",
"total_dt_score",
],
)
if len(print_keys) == 0:
print_keys = df.columns
st.write(df[print_keys])
# display over time
chart_keys = {
"Local score": "{}_local_score",
"Score part 1": "{}_1_score",
"Time to part 1": "{}_1_delta",
"Score part 2": "{}_2_score",
"Time to part 2": "{}_2_delta",
"Time diff score": "{}_dt_score",
"Time diff": "{}_dt",
}
options = list(chart_keys.keys())
chart_key = st.selectbox("What to plot?", options, index=options.index("Time diff"))
ylog = st.checkbox("Y-Log-Scale", chart_key == "Time diff")
chart(df, chart_keys[chart_key], ylog)
if __name__ == "__main__":
from fire import Fire
Fire(main)