]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views/player.py
Add a hashkey view similar to the player_info JSON one.
[xonotic/xonstat.git] / xonstat / views / player.py
index 36ca55dd1f588ffc0b258dc3ea3be6e7f6c381a3..66e74eb3e78b14871dbc773bd43582ff4405dfd7 100644 (file)
@@ -5,13 +5,14 @@ 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
+from xonstat.util import page_url, to_json, pretty_date
 
 log = logging.getLogger(__name__)
 
@@ -130,6 +131,8 @@ def get_overall_stats(player_id):
         - total_deaths
         - k_d_ratio
         - last_played (last time the player played the game type)
+        - last_played_epoch (same as above, but in seconds since epoch)
+        - last_played_fuzzy (same as above, but in relative date)
         - total_playing_time (total amount of time played the game type)
         - total_pickups (ctf only)
         - total_captures (ctf only)
@@ -141,8 +144,9 @@ def get_overall_stats(player_id):
     "overall" game_type_cd which sums the totals and computes the total ratios.
     """
     OverallStats = namedtuple('OverallStats', ['total_kills', 'total_deaths',
-        'k_d_ratio', 'last_played', 'total_playing_time', 'total_pickups',
-        'total_captures', 'cap_ratio', 'total_carrier_frags', 'game_type_cd'])
+        'k_d_ratio', 'last_played', 'last_played_epoch', 'last_played_fuzzy',
+        'total_playing_time', 'total_pickups', 'total_captures', 'cap_ratio',
+        'total_carrier_frags', 'game_type_cd'])
 
     raw_stats = DBSession.query('game_type_cd', 'total_kills',
             'total_deaths', 'last_played', 'total_playing_time',
@@ -190,7 +194,7 @@ def get_overall_stats(player_id):
             k_d_ratio = None
 
         try:
-            cap_ratio = float(row.total_pickups)/row.total_captures
+            cap_ratio = float(row.total_captures)/row.total_pickups
         except:
             cap_ratio = None
 
@@ -201,6 +205,8 @@ def get_overall_stats(player_id):
                 total_deaths=row.total_deaths,
                 k_d_ratio=k_d_ratio,
                 last_played=row.last_played,
+                last_played_epoch=timegm(row.last_played.timetuple()),
+                last_played_fuzzy=pretty_date(row.last_played),
                 total_playing_time=row.total_playing_time,
                 total_pickups=row.total_pickups,
                 total_captures=row.total_captures,
@@ -220,6 +226,8 @@ def get_overall_stats(player_id):
             total_deaths=overall_deaths,
             k_d_ratio=overall_k_d_ratio,
             last_played=overall_last_played,
+            last_played_epoch=timegm(overall_last_played.timetuple()),
+            last_played_fuzzy=pretty_date(overall_last_played),
             total_playing_time=overall_playing_time,
             total_pickups=None,
             total_captures=None,
@@ -318,7 +326,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(
@@ -337,11 +345,15 @@ 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)
-        
+
+
         if not found_top_rank:
             ranks['overall'] = rank
             found_top_rank = True
+        elif rank.percentile > ranks['overall'].percentile:
+            ranks['overall'] = rank
 
         ranks[row.game_type_cd] = rank
 
@@ -549,38 +561,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,
@@ -596,6 +608,10 @@ def player_info_json(request):
 
 
 def player_game_index_data(request):
+    RecentGame = namedtuple('RecentGame', ['game_id', 'game_type_cd', 'winner',
+        'game_create_dt', 'game_epoch', 'game_fuzzy', 'server_id',
+        'server_name', 'map_id', 'map_name', 'team', 'rank', 'elo_delta'])
+
     player_id = request.matchdict['player_id']
 
     if request.params.has_key('page'):
@@ -604,7 +620,14 @@ def player_game_index_data(request):
         current_page = 1
 
     try:
-        games_q = DBSession.query(Game, Server, Map).\
+        player = DBSession.query(Player).filter_by(player_id=player_id).\
+                filter(Player.active_ind == True).one()
+
+        games_q = DBSession.query(Game.game_id, Game.game_type_cd, Game.winner,
+                Game.create_dt, Server.server_id,
+                Server.name.label('server_name'), Map.map_id,
+                Map.name.label('map_name'), PlayerGameStat.team,
+                PlayerGameStat.rank, PlayerGameStat.elo_delta).\
             filter(PlayerGameStat.game_id == Game.game_id).\
             filter(PlayerGameStat.player_id == player_id).\
             filter(Game.server_id == Server.server_id).\
@@ -613,20 +636,32 @@ def player_game_index_data(request):
 
         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()
+        # replace the items in the canned pagination class with more rich ones
+        games.items = [RecentGame(
+            game_id        = row.game_id,
+            game_type_cd   = row.game_type_cd,
+            winner         = row.winner,
+            game_create_dt = row.create_dt,
+            game_epoch     = timegm(row.create_dt.timetuple()),
+            game_fuzzy     = pretty_date(row.create_dt),
+            server_id      = row.server_id,
+            server_name    = row.server_name,
+            map_id         = row.map_id,
+            map_name       = row.map_name,
+            team           = row.team,
+            rank           = row.rank,
+            elo_delta      = row.elo_delta
+        ) 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):
@@ -752,3 +787,76 @@ 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,
+    }]