WebHost: add a /stats page

This commit is contained in:
Fabian Dill 2022-04-08 15:52:49 +02:00 committed by KonoTyran
parent 8bb566a250
commit dae0e233b8
5 changed files with 95 additions and 1 deletions

View File

@ -207,6 +207,7 @@ def get_datapackge():
return Response(json.dumps(network_data_package, indent=4), mimetype="text/plain")
@app.route('/index')
@app.route('/sitemap')
def get_sitemap():
available_games = []
@ -217,6 +218,6 @@ def get_sitemap():
from WebHostLib.customserver import run_server_process
from . import tracker, upload, landing, check, generate, downloads, api # to trigger app routing picking up on it
from . import tracker, upload, landing, check, generate, downloads, api, stats # to trigger app routing picking up on it
app.register_blueprint(api.api_endpoints)

View File

@ -4,3 +4,4 @@ waitress>=2.1.0
flask-caching>=1.10.1
Flask-Compress>=1.11
Flask-Limiter>=2.2.0
bokeh>=2.4.2

70
WebHostLib/stats.py Normal file
View File

@ -0,0 +1,70 @@
from collections import Counter, defaultdict
from itertools import cycle
from datetime import datetime, timedelta, date
from math import pi
from bokeh.embed import components
from bokeh.palettes import Dark2_8 as palette
from bokeh.plotting import figure, ColumnDataSource
from bokeh.resources import INLINE
from flask import render_template
from pony.orm import select
from . import app, cache
from .models import Room
pi2 = 2 * pi
@app.route('/stats')
@cache.memoize(timeout=60*60) # regen once per hour should be plenty
def stats():
plot = figure(title="Games played per day", x_axis_type='datetime', x_axis_label="Date", y_axis_label="Played",
sizing_mode="scale_both")
games_played = defaultdict(Counter)
total_games = Counter()
room: Room
games = set()
cutoff = date.today()-timedelta(days=30000)
for room in select(room for room in Room if room.creation_time >= cutoff):
for slot in room.seed.slots:
total_games[slot.game] += 1
games.add(slot.game)
games_played[room.creation_time.date()][slot.game] += 1
days = sorted(games_played)
cyc_palette = cycle(palette)
for game in sorted(games):
occurences = []
for day in days:
occurences.append(games_played[day][game])
plot.line([datetime.combine(day, datetime.min.time()) for day in days],
occurences, legend_label=game, line_width=2, color=next(cyc_palette))
total = sum(total_games.values())
pie = figure(plot_height=350, title=f"Games played in the last 30 days. (Total: {total})", toolbar_location=None,
tools="hover", tooltips=[("Game:", "@games"), ("Played:", "@count")],
sizing_mode="scale_both")
pie.axis.visible = False
data = {
"games": [],
"count": [],
"start_angles": [],
"end_angles": [],
}
current_angle = 0
for i, (game, count) in enumerate(total_games.most_common()):
data["games"].append(game)
data["count"].append(count)
data["start_angles"].append(current_angle)
angle = count / total * pi2
current_angle += angle
data["end_angles"].append(current_angle)
data["colors"] = [element[1] for element in sorted((game, color) for game, color in zip(data["games"], cycle(palette)))]
pie.wedge(x=0.5, y=0.5, radius=0.5,
start_angle="start_angles", end_angle="end_angles", fill_color="colors",
source=ColumnDataSource(data=data), legend_field="games")
script, charts = components((plot, pie))
return render_template("stats.html", js_resources=INLINE.render_js(), css_resources=INLINE.render_css(),
chart_data=script, charts=charts)

View File

@ -25,6 +25,7 @@
<li><a href="/tutorial">Tutorials Page</a></li>
<li><a href="/user-content">User Content</a></li>
<li><a href="/weighted-settings">Weighted Settings Page</a></li>
<li><a href="{{url_for('stats')}}">Game Statistics</a></li>
</ul>
<h2>Game Info Pages</h2>

View File

@ -0,0 +1,21 @@
{% extends 'pageWrapper.html' %}
{% block head %}
<title>Site Map</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/markdown.css") }}" />
{{ css_resources|indent(4)|safe }}
{{ js_resources|indent(4)|safe }}
{{ chart_data|indent(4)|safe }}
{% endblock %}
{% block body %}
{% include 'header/grassFlowersHeader.html' %}
<div id="stats" class="markdown">
<h1>Stats</h1>
{% for chart in charts %}
{{ chart|indent(12)|safe }}
{% endfor %}
</div>
{% endblock %}