]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views/player.py
Integrate the new helpers everywhere.
[xonotic/xonstat.git] / xonstat / views / player.py
index 805b8634fe652fe547a0ebea4ebb033591aa6e6d..d773e134efd849017869e2c4069b0e65e19f7b80 100644 (file)
@@ -1,17 +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
+from xonstat.util import page_url, to_json, pretty_date
+from xonstat.views.helpers import RecentGame, recent_games_q
 
 log = logging.getLogger(__name__)
 
@@ -130,6 +132,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 +145,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 +195,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 +206,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 +227,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 +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(
@@ -337,11 +346,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
 
@@ -378,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 played in descending order
+    rgs = recent_games_q(player_id=player_id).limit(10).all()
+    recent_games = [RecentGame(row) for row in rgs]
 
-    # 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]
-
-    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):
@@ -549,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']
-    
+
+    #recent_weapons = player_info['recent_weapons']
+
     return [{
         'player':           player,
         'games_played':     games_played,
@@ -589,7 +588,8 @@ def player_info_json(request):
         'elos':             elos,
         'ranks':            ranks,
         'recent_games':     recent_games,
-        'recent_weapons':   recent_weapons,
+    #    'recent_weapons':   recent_weapons,
+        'recent_weapons':   ['not implemented'],
     }]
     #return [{'status':'not implemented'}]
 
@@ -603,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):
@@ -751,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,
+    }]