doneth.at/app/graph.py

70 lines
1.6 KiB
Python

from flask import Blueprint, render_template
from flask_login import login_required, current_user
from .db import db, Accomplishment
from . import timeutils
blueprint = Blueprint('graph', __name__)
@blueprint.route('/graph.svg')
@login_required
def graph_svg():
count = 7
accomplishments = [0]*count
days = [""]*count
day = timeutils.today()
for i in range(1, count+1):
total_xp = Accomplishment.get_day_total(current_user.id, day)
accomplishments[-i] = total_xp
days[-i] = day.strftime('%a')[:2]
day = timeutils.day_before(day)
print(accomplishments)
return render_template('graph.svg', days=days, **gen_graph_data(accomplishments)), 200, {'Content-Type': 'image/svg+xml'}
def gen_scale(base=10):
return [base*i for i in range(0, 5)]
def find_scale_base(max_n):
if max_n < 20:
return 10
return (max_n - (max_n - 1) % 20 + 20) // 4
n = max_n % 20
while n % 20 != 0:
n += 1
return n//4
GRAPH_TOP_LINE = 16.6
GRAPH_BOTTOM_LINE = 83
GRAPH_RANGE = GRAPH_BOTTOM_LINE - GRAPH_TOP_LINE
def absolute_to_percentage_position(n, scale_base):
scale_top = scale_base * 4
return round(GRAPH_BOTTOM_LINE - n/scale_top * GRAPH_RANGE, 2)
def gen_graph_data(numbers):
assert len(numbers) > 1
max_n = max(numbers)
scale_base = find_scale_base(max_n)
scale = gen_scale(scale_base)
dots = [absolute_to_percentage_position(
n, scale_base) for n in numbers]
lines = list(zip(dots, dots[1:]))
return {
"dots": dots,
"lines": lines,
"scale": scale,
}