From b739537c97f5cd36ea3b61f1b41c5a186764ad9d Mon Sep 17 00:00:00 2001 From: Brennan Bibic Date: Mon, 23 Sep 2024 13:40:09 -0400 Subject: [PATCH] Try global leaderboard stuff --- .../templates/ranked/global_leaderboard.html | 26 ++++++++ ranked/templates/ranked/leaderboard.html | 5 +- ranked/urls.py | 1 + ranked/views.py | 66 ++++++++++++++++++- 4 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 ranked/templates/ranked/global_leaderboard.html diff --git a/ranked/templates/ranked/global_leaderboard.html b/ranked/templates/ranked/global_leaderboard.html new file mode 100644 index 0000000..bf041cd --- /dev/null +++ b/ranked/templates/ranked/global_leaderboard.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} + +{% block content %} +

Global Elo Leaderboard

+ + + + + + + + + + + {% for entry in players_with_rank %} + + + + + + + + {% endfor %} + +
RankPlayerEloRank Title
{{ forloop.counter }}{{ entry.player.username }}{{ entry.global_elo }}{{ entry.rank }}
+{% endblock %} \ No newline at end of file diff --git a/ranked/templates/ranked/leaderboard.html b/ranked/templates/ranked/leaderboard.html index 14397f5..bc6bd49 100644 --- a/ranked/templates/ranked/leaderboard.html +++ b/ranked/templates/ranked/leaderboard.html @@ -33,8 +33,9 @@

{{ player_data.player.player }} {{ player_data.player.elo|floatformat:1 }} - {{ player_data.player.mmr|floatformat:1 }} - {{ player_data.rank }} + {{ player_data.mmr|floatformat:1 }} + + {{ player_data.rank }} {{ player_data.player.matches_played }} {{ player_data.player.win_rate|floatformat:2 }}% {{ player_data.player.matches_won }} diff --git a/ranked/urls.py b/ranked/urls.py index bbadb99..32ef713 100644 --- a/ranked/urls.py +++ b/ranked/urls.py @@ -6,4 +6,5 @@ path('', views.ranked_home, name='home'), path('/', views.leaderboard, name='leaderboard'), path('/', views.player_info, name='player_info'), + path('global_leaderboard/', views.global_leaderboard, name='global_leaderboard'), ] diff --git a/ranked/views.py b/ranked/views.py index 9d9e08e..aca8f40 100644 --- a/ranked/views.py +++ b/ranked/views.py @@ -1,5 +1,5 @@ from django.shortcuts import render, HttpResponseRedirect -from django.db.models import Max, Min, F, Q, Count, ExpressionWrapper, FloatField, Case, When, Value +from django.db.models import Max, Min, F, Q, Count, ExpressionWrapper, FloatField, Case, When, Value, Sum from django.utils import timezone from datetime import datetime, timedelta import math @@ -115,3 +115,67 @@ def player_info(request, name, player_id): def mmr_calc(elo, matches_played, delta_hours): return elo * 2 / ((1 + pow(math.e, 1/168 * pow(delta_hours, 0.63))) * (1 + pow(math.e, -0.33 * matches_played))) + +def global_leaderboard(request): + # Fetch all players + players = PlayerElo.objects.all() + + global_scores = [] + + for player in players: + # Fetch all game modes for the player + game_modes = GameMode.objects.filter(playerelo=player) + + if not game_modes.exists(): + continue + + # Determine the most played game mode per game type + game_type_dict = {} + for mode in game_modes: + game_type = mode.game + match_count = mode.match_count # Assuming 'match_count' exists + if game_type not in game_type_dict or match_count > game_type_dict[game_type]['match_count']: + game_type_dict[game_type] = {'mode': mode, 'match_count': match_count} + + # Calculate weighted Elo + total_weight = 0 + weighted_elo = 0 + for game_type, data in game_type_dict.items(): + weight = data['match_count'] # Full weight for the most played game + weighted_elo += data['mode'].elo * weight + total_weight += weight + + # Adjust weights for less played games (1/3 weight) + for game_type, data in game_type_dict.items(): + if data['match_count'] < max(d['match_count'] for d in game_type_dict.values()): + weighted_elo += data['mode'].elo * (data['match_count'] / 3) + total_weight += data['match_count'] / 3 + + if total_weight > 0: + global_elo = weighted_elo / total_weight + global_scores.append({'player': player, 'global_elo': global_elo}) + + # Sort players by global Elo in descending order + global_scores = sorted(global_scores, key=lambda x: x['global_elo'], reverse=True) + + # Assign ranks and colors + highest_elo = global_scores[0]['global_elo'] if global_scores else 0 + lowest_elo = global_scores[-1]['global_elo'] if global_scores else 0 + + players_with_rank = [] + for entry in global_scores: + rank, color = mmr_to_rank(entry['global_elo'], highest_elo, lowest_elo) + players_with_rank.append({ + 'player': entry['player'], + 'rank': rank, + 'color': color, + 'global_elo': round(entry['global_elo'], 1), + }) + + context = { + 'leaderboard_code': 'global', + 'leaderboard_name': 'Global Elo Leaderboard', + 'players_with_rank': players_with_rank, + } + + return render(request, "ranked/global_leaderboard.html", context)