Commit f9019538 authored by Hermann Krumrey's avatar Hermann Krumrey

Merge branch 'develop' into 'master'

Develop

See merge request namibsun/python/bundesliga-tippspiel!19
parents 50dbe759 302ff7d8
V 0.20.0:
- Added more user statistics
- Added more stats to statistics page
V 0.19.1:
- Fixed Rückrunde-table
V 0.19.0:
......
......@@ -31,7 +31,9 @@ from bundesliga_tippspiel.actions.GetPlayerAction import GetPlayerAction
from bundesliga_tippspiel.actions.GetGoalAction import GetGoalAction
from bundesliga_tippspiel.actions.LeaderboardAction import LeaderboardAction
from bundesliga_tippspiel.utils.stats import get_team_points_data, \
generate_team_points_table, get_total_points_per_team
generate_team_points_table, get_total_points_per_team, \
generate_points_distributions, create_participation_ranking, \
create_point_average_ranking
@app.route("/leaderboard", methods=["GET"])
......@@ -134,19 +136,60 @@ def user(user_id: int):
abort(404)
bets = Bet.query.all()
total_bets = len(list(filter(lambda x: x.user_id == user_id, bets)))
bets = list(filter(lambda x: x.match.finished, bets))
rr_bets = list(filter(lambda x: x.match.matchday > 17, bets))
current_matchday, leaderboard_history = \
generate_leaderboard_data(bets=bets)
_, rr_history = generate_leaderboard_data(bets=rr_bets)
bets = list(filter(lambda x: x.user_id == user_id, bets))
total_points = 0
for bet in bets:
total_points += bet.evaluate(True)
team_points = get_team_points_data(bets)[user_data]
team_points = generate_team_points_table(team_points)
points_distribution = generate_points_distributions(bets)[user_data]
average_points = create_point_average_ranking(bets)[0][1]
participation = create_participation_ranking(bets)[0][1]
placements = leaderboard_history[user_data.username][1]
rr_placements = rr_history[user_data.username][1]
current_placement = "N/A"
if len(placements) >= 1:
current_placement = placements[len(placements) - 1]
hinrunde_placement = "N/A"
if len(placements) >= 17:
hinrunde_placement = placements[16]
ruckrunde_placement = "N/A"
if len(rr_placements) >= 1:
ruckrunde_placement = rr_placements[len(rr_placements) - 1]
return render_template(
"info/user.html",
charts=True,
user=user_data,
leaderboard_history=leaderboard_history,
matchday=current_matchday,
team_points=enumerate(team_points)
team_points=enumerate(team_points),
points_distribution=points_distribution,
player_points=total_points,
player_bet_count=total_bets,
player_avg_points=average_points,
player_participation=participation,
player_correct_bets_count=points_distribution.get(15, 0),
player_incorrect_bets_count=points_distribution.get(0, 0),
player_best_team=team_points[0][0].name,
player_worst_team=team_points[len(team_points) - 1][0].name,
player_current_placement=current_placement,
player_hinrunde_placement=hinrunde_placement,
player_ruckrunde_placement=ruckrunde_placement,
player_best_placement=min(placements),
player_worst_placement=max(placements)
)
......@@ -179,6 +222,16 @@ def stats():
team_points = get_total_points_per_team(finished_bets)
team_points = generate_team_points_table(team_points)
points_distribution = {}
for _, distrib in generate_points_distributions(finished_bets).items():
for key, value in distrib.items():
if key not in points_distribution:
points_distribution[key] = 0
points_distribution[key] += value
participation_ranking = create_participation_ranking(finished_bets)
average_ranking = create_point_average_ranking(finished_bets)
return render_template(
"info/stats.html",
first_leaderboard=enumerate(leaderboards[0]),
......@@ -186,6 +239,9 @@ def stats():
max_leaderboard=enumerate(leaderboards[2]),
zero_leaderboard=enumerate(leaderboards[3]),
team_points=enumerate(team_points),
points_distribution=points_distribution,
participation_ranking=enumerate(participation_ranking),
average_ranking=enumerate(average_ranking),
show_all=True,
charts=True
)
{#
Copyright 2017 Hermann Krumrey <hermann@krumreyh.com>
This file is part of bundesliga-tippspiel.
bundesliga-tippspiel is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
bundesliga-tippspiel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>.
#}
<canvas id="points-pie" width="300" height="300"></canvas>
<!--suppress JSUnusedGlobalSymbols, JSUnusedLocalSymbols, JSDuplicatedDeclaration -->
<script async>
new Chart(document.getElementById("points-pie"), {
type: "doughnut",
data: {
labels: ["0", "3", "7", "10", "12", "15"],
datasets: [
{
label: "Punkte",
backgroundColor: [
"#ff6384",
"#ff9f40",
"#ffcd56",
"#4bc0c0",
"#36a2eb",
"#9966ff"
],
data: [
{{ points_distribution.get(0, 0) }},
{{ points_distribution.get(3, 0) }},
{{ points_distribution.get(7, 0) }},
{{ points_distribution.get(10, 0) }},
{{ points_distribution.get(12, 0) }},
{{ points_distribution.get(15, 0) }}
]
}
]
},
options: {
title: {
display: true,
fontSize: 24,
text: "Punkteverteilung"
}
}
});
</script>
......@@ -22,13 +22,7 @@ along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>.
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">
{% if count %}
#
{% else %}
Punkte
{% endif %}
</th>
<th scope="col">{{ unit }}</th>
<!--th scope="col">Tendenz</th-->
</tr>
</thead>
......
......@@ -20,7 +20,7 @@ along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>.
{% extends "components/base_layout.html" %}
{% block body %}
<h1>Rangliste</h1>
{% set count=False %}
{% set unit="Punkte" %}
{% include "components/ranking_table.html" %}
<br>
{% include "components/ranking_chart.html" %}
......
......@@ -19,34 +19,60 @@ along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>.
{% extends "components/base_layout.html" %}
{% block body %}
{% set count=False %}
{% set unit="Punkte" %}
<div class="row">
<div class="col-md-6">
<h1>Rangliste Hinrunde</h1>
<h3>Rangliste Hinrunde</h3>
{% set leaderboard=first_leaderboard %}
{% include "components/ranking_table.html" %}
</div>
<div class="col-md-6">
<h1>Rangliste Rückrunde</h1>
<h3>Rangliste Rückrunde</h3>
{% set leaderboard=second_leaderboard %}
{% include "components/ranking_table.html" %}
</div>
</div>
{% set count=True %}
{% set unit="#" %}
<div class="row">
<div class="col-md-6">
<h1>Korrekte Tipps</h1>
<h3>Korrekte Tipps</h3>
{% set leaderboard=max_leaderboard %}
{% include "components/ranking_table.html" %}
</div>
<div class="col-md-6">
<h1>Komplett falsche Tipps</h1>
<h3>Komplett falsche Tipps</h3>
{% set leaderboard=zero_leaderboard %}
{% include "components/ranking_table.html" %}
</div>
</div>
{% set unit="%" %}
<div class="row">
<div class="col-md-6">
<h3>Punkte/Tipp</h3>
{% set leaderboard=average_ranking %}
{% include "components/ranking_table.html" %}
</div>
<div class="col-md-6">
<h3>Teilnahme</h3>
{% set leaderboard=participation_ranking %}
{% include "components/ranking_table.html" %}
</div>
</div>
<div class="row">
<h1>Punkte pro Team</h1>
<div class="col-md-3"></div>
<div class="col-md-6">
{% include "components/points_distribution_pie_chart.html" %}
</div>
<div class="col-md-3"></div>
</div>
<div class="row">
<h3>Punkte pro Team</h3>
{% include "components/team_points_table.html" %}
</div>
{% endblock %}
......@@ -24,7 +24,70 @@ along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>.
<h3>Positionsentwicklung</h3>
{% include "components/ranking_chart.html" %}
</div>
<br>
<div class="row">
<div class="col-md-6">
<h3>Übersicht</h3>
<table class="table table-striped table-bordered leaderboard-table">
<tbody>
<tr>
<td>Position</td>
<td>{{ player_current_placement }}</td>
</tr>
<tr>
<td>Position (Hinrunde)</td>
<td>{{ player_hinrunde_placement }}</td>
</tr>
<tr>
<td>Position (Rückrunde)</td>
<td>{{ player_ruckrunde_placement }}</td>
</tr>
<tr>
<td>Beste Position</td>
<td>{{ player_best_placement }}</td>
</tr>
<tr>
<td>Schlechteste Position</td>
<td>{{ player_worst_placement }}</td>
</tr>
<tr>
<td>Punkte</td>
<td>{{ player_points }}</td>
</tr>
<tr>
<td>Anzahl Tipps</td>
<td>{{ player_bet_count }}</td>
</tr>
<tr>
<td>Punkteschnitt</td>
<td>{{ player_avg_points }}</td>
</tr>
<tr>
<td>Teilnahme</td>
<td>{{ player_participation }}</td>
</tr>
<tr>
<td>Korrekte Tipps</td>
<td>{{ player_correct_bets_count }}</td>
</tr>
<tr>
<td>Komplett falsche Tipps</td>
<td>{{ player_incorrect_bets_count }}</td>
</tr>
<tr>
<td>Bestes Team</td>
<td>{{ player_best_team }}</td>
</tr>
<tr>
<td>Schlechtestes Team</td>
<td>{{ player_worst_team }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
{% include "components/points_distribution_pie_chart.html" %}
</div>
</div>
<div class="row">
<h3>Punkte pro Team</h3>
{% include "components/team_points_table.html" %}
......
......@@ -21,6 +21,7 @@ from typing import Optional, List, Dict, Tuple
from bundesliga_tippspiel.models.auth.User import User
from bundesliga_tippspiel.models.match_data.Team import Team
from bundesliga_tippspiel.models.user_generated.Bet import Bet
from bundesliga_tippspiel.models.match_data.Match import Match
def get_team_points_data(bets: Optional[List[Bet]] = None) \
......@@ -32,7 +33,7 @@ def get_team_points_data(bets: Optional[List[Bet]] = None) \
:return: A dictionary mapping users to dictionaries mapping teams to points
"""
stats = {}
for user in User.query.all():
for user in User.query.filter_by(confirmed=True):
stats[user] = {}
for team in Team.query.all():
stats[user][team] = 0
......@@ -82,3 +83,90 @@ def generate_team_points_table(team_points: Dict[Team, int]) \
table.append((team, points))
table.sort(key=lambda x: x[1], reverse=True)
return table
def generate_points_distributions(bets: Optional[List[Bet]] = None) \
-> Dict[User, Dict[int, int]]:
"""
Generates a distribution detailing how often a given amount of points
a user earned while betting
:param bets: The bets to analyze. If not provided, will analyze all bets
:return: A dictionary mapping users to point amounts to their
appearance count
"""
if bets is None:
bets = Bet.query.all()
bets = list(filter(lambda x: x.match.finished, bets))
distribution = {}
for user in User.query.filter_by(confirmed=True):
distribution[user] = {}
for bet in bets:
points = bet.evaluate(True)
if points not in distribution[bet.user]:
distribution[bet.user][points] = 0
distribution[bet.user][points] += 1
return distribution
def create_participation_ranking(bets: Optional[List[Bet]] = None) \
-> [List[Tuple[User, str]]]:
"""
Creates a ranking of user's participation percentages
:param bets: The bets to analyze. If not provided, will analyze all bets
:return: A sorted list of tuples detailing the participation ranking
"""
matches = Match.query.all()
matches = list(filter(lambda x: x.finished, matches))
if bets is None:
bets = Bet.query.all()
bets = list(filter(lambda x: x.match.finished, bets))
participation_stats = {}
for user in User.query.filter_by(confirmed=True):
participation_stats[user] = 0
for bet in bets:
participation_stats[bet.user] += 1
ranking = []
for user, betcount in participation_stats.items():
percentage = int((betcount / len(matches)) * 100)
ranking.append((user, percentage))
ranking.sort(key=lambda x: x[1], reverse=True)
ranking = list(map(lambda x: (x[0], "{}%".format(x[1])), ranking))
return ranking
def create_point_average_ranking(bets: Optional[List[Bet]] = None) \
-> List[Tuple[User, str]]:
"""
Creates a ranking of points averages
:param bets: The bets to analyze
:return: The ranking
"""
distribution = generate_points_distributions(bets)
averages = []
for user, points_distrib in distribution.items():
total_points = 0
count = 0
for value, occurences in points_distrib.items():
total_points += (value * occurences)
count += occurences
try:
ratio = total_points / count
except ZeroDivisionError:
ratio = 0
averages.append((user, ratio))
averages.sort(key=lambda x: x[1], reverse=True)
averages = list(map(lambda x: (x[0], "%.2f" % x[1]), averages))
return averages
0.19.1
\ No newline at end of file
0.20.0
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment