]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views/player.py
Simplify the rank table calculations. Woohoo, negative LOC!
[xonotic/xonstat.git] / xonstat / views / player.py
index a03ab6c7f94bb777dbcc2057635c2a38e3a3985c..d773e134efd849017869e2c4069b0e65e19f7b80 100644 (file)
@@ -1,18 +1,19 @@
 import datetime
 import json
 import logging
+import pyramid.httpexceptions
 import re
 import sqlalchemy as sa
 import sqlalchemy.sql.functions as func
 import time
 from calendar import timegm
 from collections import namedtuple
-from pyramid.response import Response
 from pyramid.url import current_route_url
 from sqlalchemy import desc, distinct
 from webhelpers.paginate import Page, PageURL
 from xonstat.models import *
 from xonstat.util import page_url, to_json, pretty_date
+from xonstat.views.helpers import RecentGame, recent_games_q
 
 log = logging.getLogger(__name__)
 
@@ -326,7 +327,7 @@ def get_ranks(player_id):
     The key to the dictionary is the game type code. There is also an
     "overall" game_type_cd which is the overall best rank.
     """    
-    Rank = namedtuple('Rank', ['rank', 'max_rank', 'game_type_cd'])
+    Rank = namedtuple('Rank', ['rank', 'max_rank', 'percentile', 'game_type_cd'])
 
     raw_ranks = DBSession.query("game_type_cd", "rank", "max_rank").\
             from_statement(
@@ -345,14 +346,14 @@ def get_ranks(player_id):
     for row in raw_ranks:
         rank = Rank(rank=row.rank,
             max_rank=row.max_rank,
+            percentile=100 - 100*float(row.rank)/row.max_rank,
             game_type_cd=row.game_type_cd)
 
-        percentile = 100 - float(row.rank)/row.max_rank
 
         if not found_top_rank:
             ranks['overall'] = rank
             found_top_rank = True
-        elif percentile > 100 - float(ranks['overall'].rank)/ranks['overall'].max_rank:
+        elif rank.percentile > ranks['overall'].percentile:
             ranks['overall'] = rank
 
         ranks[row.game_type_cd] = rank
@@ -390,27 +391,13 @@ def get_elos(player_id):
 
 def get_recent_games(player_id):
     """
-    Provides a list of recent games.
-
-    Returns the full PlayerGameStat, Game, Server, Map
-    objects for all recent games.
+    Provides a list of recent games for a player. Uses the recent_games_q helper.
     """
-    RecentGame = namedtuple('RecentGame', ['player_stats', 'game', 'server', 'map'])
-
-    # recent games table, all data
-    recent_games = DBSession.query(PlayerGameStat, Game, Server, Map).\
-            filter(PlayerGameStat.player_id == player_id).\
-            filter(PlayerGameStat.game_id == Game.game_id).\
-            filter(Game.server_id == Server.server_id).\
-            filter(Game.map_id == Map.map_id).\
-            order_by(Game.game_id.desc())[0:10]
+    # recent games played in descending order
+    rgs = recent_games_q(player_id=player_id).limit(10).all()
+    recent_games = [RecentGame(row) for row in rgs]
 
-    return [
-        RecentGame(player_stats=row.PlayerGameStat,
-            game=row.Game,
-            server=row.Server,
-            map=row.Map)
-        for row in recent_games ]
+    return recent_games
 
 
 def get_recent_weapons(player_id):
@@ -561,38 +548,38 @@ def player_info_json(request):
     """
     Provides detailed information on a specific player. JSON.
     """
-    
+
     # All player_info fields are converted into JSON-formattable dictionaries
     player_info = player_info_data(request)    
-    
+
     player = player_info['player'].to_dict()
 
     games_played = {}
     for game in player_info['games_played']:
         games_played[game.game_type_cd] = to_json(game)
-    
+
     overall_stats = {}
     for gt,stats in player_info['overall_stats'].items():
         overall_stats[gt] = to_json(stats)
-    
+
     elos = {}
     for gt,elo in player_info['elos'].items():
         elos[gt] = to_json(elo.to_dict())
-    
+
     ranks = {}
     for gt,rank in player_info['ranks'].items():
         ranks[gt] = to_json(rank)
-    
+
     fav_maps = {}
     for gt,mapinfo in player_info['fav_maps'].items():
         fav_maps[gt] = to_json(mapinfo)
-     
+
     recent_games = []
     for game in player_info['recent_games']:
         recent_games.append(to_json(game))
-    
+
     #recent_weapons = player_info['recent_weapons']
-    
+
     return [{
         'player':           player,
         'games_played':     games_played,
@@ -616,29 +603,25 @@ def player_game_index_data(request):
         current_page = 1
 
     try:
-        games_q = DBSession.query(Game, Server, Map).\
-            filter(PlayerGameStat.game_id == Game.game_id).\
-            filter(PlayerGameStat.player_id == player_id).\
-            filter(Game.server_id == Server.server_id).\
-            filter(Game.map_id == Map.map_id).\
-            order_by(Game.game_id.desc())
-
-        games = Page(games_q, current_page, items_per_page=10, url=page_url)
-
-        pgstats = {}
-        for (game, server, map) in games:
-            pgstats[game.game_id] = DBSession.query(PlayerGameStat).\
-                    filter(PlayerGameStat.game_id == game.game_id).\
-                    order_by(PlayerGameStat.rank).\
-                    order_by(PlayerGameStat.score).all()
+        player = DBSession.query(Player).filter_by(player_id=player_id).\
+                filter(Player.active_ind == True).one()
+
+        rgs_q = recent_games_q(player_id=player.player_id)
+
+        games = Page(rgs_q, current_page, items_per_page=10, url=page_url)
+
+        # replace the items in the canned pagination class with more rich ones
+        games.items = [RecentGame(row) for row in games.items]
 
     except Exception as e:
         player = None
         games = None
 
-    return {'player_id':player_id,
+    return {
+            'player_id':player.player_id,
+            'player':player,
             'games':games,
-            'pgstats':pgstats}
+           }
 
 
 def player_game_index(request):
@@ -764,3 +747,112 @@ def player_damage_json(request):
        games = over how many games to display damage. Can be up to 50.
     """
     return player_damage_data(request)
+
+
+def player_hashkey_info_data(request):
+    hashkey = request.matchdict['hashkey']
+    try:
+        player = DBSession.query(Player).\
+                filter(Player.player_id == Hashkey.player_id).\
+                filter(Player.active_ind == True).\
+                filter(Hashkey.hashkey == hashkey).one()
+
+        games_played   = get_games_played(player.player_id)
+        overall_stats  = get_overall_stats(player.player_id)
+        fav_maps       = get_fav_maps(player.player_id)
+        elos           = get_elos(player.player_id)
+        ranks          = get_ranks(player.player_id)
+
+    except Exception as e:
+        raise e
+        player         = None
+        games_played   = None
+        overall_stats  = None
+        fav_maps       = None
+        elos           = None
+        ranks          = None
+
+    return {'player':player,
+            'games_played':games_played,
+            'overall_stats':overall_stats,
+            'fav_maps':fav_maps,
+            'elos':elos,
+            'ranks':ranks,
+            }
+
+
+def player_hashkey_info_json(request):
+    """
+    Provides detailed information on a specific player. JSON.
+    """
+
+    # All player_info fields are converted into JSON-formattable dictionaries
+    player_info = player_hashkey_info_data(request)
+
+    player = player_info['player'].to_dict()
+
+    games_played = {}
+    for game in player_info['games_played']:
+        games_played[game.game_type_cd] = to_json(game)
+
+    overall_stats = {}
+    for gt,stats in player_info['overall_stats'].items():
+        overall_stats[gt] = to_json(stats)
+
+    elos = {}
+    for gt,elo in player_info['elos'].items():
+        elos[gt] = to_json(elo.to_dict())
+
+    ranks = {}
+    for gt,rank in player_info['ranks'].items():
+        ranks[gt] = to_json(rank)
+
+    fav_maps = {}
+    for gt,mapinfo in player_info['fav_maps'].items():
+        fav_maps[gt] = to_json(mapinfo)
+
+    return [{
+        'version':          1,
+        'player':           player,
+        'games_played':     games_played,
+        'overall_stats':    overall_stats,
+        'fav_maps':         fav_maps,
+        'elos':             elos,
+        'ranks':            ranks,
+    }]
+
+
+def player_elo_info_data(request):
+    """
+    Provides elo information on a specific player. Raw data is returned.
+    """
+    hashkey = request.matchdict['hashkey']
+    try:
+        player = DBSession.query(Player).\
+                filter(Player.player_id == Hashkey.player_id).\
+                filter(Player.active_ind == True).\
+                filter(Hashkey.hashkey == hashkey).one()
+
+        elos = get_elos(player.player_id)
+
+    except Exception as e:
+        log.debug(e)
+        raise pyramid.httpexceptions.HTTPNotFound
+
+    return {'elos':elos}
+
+
+def player_elo_info_json(request):
+    """
+    Provides elo information on a specific player. JSON.
+    """
+    elo_info = player_elo_info_data(request)
+
+    elos = {}
+    for gt, elo in elo_info['elos'].items():
+        elos[gt] = to_json(elo.to_dict())
+
+    return [{
+        'version':          1,
+        'elos':             elos,
+    }]