-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
100 lines (63 loc) · 2.05 KB
/
main.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
import asyncio
import functools
import io
import json
import time
import zlib
from os import getenv
import uvicorn
from cryptography.fernet import Fernet, InvalidToken
from fastapi import FastAPI
from matplotlib import rcParams, style
from matplotlib.figure import Figure
from starlette.responses import StreamingResponse
# Matplotlib global styling
style.use("seaborn-dark")
rcParams.update({"font.size": 13})
for param in ["figure.facecolor", "axes.facecolor", "savefig.facecolor"]:
rcParams[param] = "#2F3136"
for param in ["text.color", "axes.labelcolor", "xtick.color", "ytick.color"]:
rcParams[param] = "1"
app = FastAPI()
SECRET = getenv("SECRET").encode()
IMAGE_FORMAT = "jpeg"
def generate_graph(*, colours: list, y_values: dict, fig_size: tuple, amount: int):
fig = Figure(figsize=fig_size)
axis = fig.add_subplot(1, 1, 1)
axis.set_xlabel("Tests")
axis.grid(color="#3A3C42")
x_values = range(0, amount, (amount // 100) + 1)
for i, (label, values) in enumerate(y_values.items()):
axis.plot(
x_values,
values,
label=label,
marker="o",
color=colours[i % len(colours)],
)
fig.legend(frameon=True)
fig.tight_layout()
buffer = io.BytesIO()
fig.savefig(buffer, format=IMAGE_FORMAT)
return buffer
@functools.lru_cache()
def handle_input(raw_data):
try:
decrypted = Fernet(SECRET).decrypt(raw_data.encode())
except InvalidToken:
return
data = json.loads(zlib.decompress(decrypted).decode())
until = data.pop("until", None)
if until is None or until <= time.time():
return
return generate_graph(**data)
@app.get("/score_graph")
async def score_graph(raw_data: str):
loop = asyncio.get_running_loop()
args = functools.partial(handle_input, raw_data)
buffer = await loop.run_in_executor(None, args)
if buffer is None:
return
buffer.seek(0)
return StreamingResponse(buffer, media_type=f"image/{IMAGE_FORMAT}")
uvicorn.run(app, host="0.0.0.0", port=8080)