config.add_route("player_weaponstats_data_json", "/player/{id:\d+}/weaponstats.json")
config.add_view(player_weaponstats_data_json, route_name="player_weaponstats_data_json", renderer="jsonp")
- config.add_route("top_players_by_time", "/topactive")
- config.add_view(top_players_by_time, route_name="top_players_by_time", renderer="top_players_by_time.mako")
+ config.add_route("top_players_index", "/topactive")
+ config.add_view(top_players_index, route_name="top_players_index", renderer="top_players_by_time.mako")
- config.add_route("top_servers_by_players", "/topservers")
- config.add_view(top_servers_by_players, route_name="top_servers_by_players", renderer="top_servers_by_players.mako")
+ config.add_route("top_servers_index", "/topservers")
+ config.add_view(top_servers_index, route_name="top_servers_index", renderer="top_servers_by_players.mako")
- config.add_route("top_maps_by_times_played", "/topmaps")
- config.add_view(top_maps_by_times_played, route_name="top_maps_by_times_played", renderer="top_maps_by_times_played.mako")
+ config.add_route("top_maps_index", "/topmaps")
+ config.add_view(top_maps_index, route_name="top_maps_index", renderer="top_maps_by_times_played.mako")
# GAME ROUTES
config.add_route("game_info", "/game/{id:\d+}")
}
+class ActivePlayer(object):
+ def __init__(self, sort_order=None, player_id=None, nick=None,
+ alivetime=None):
+ self.sort_order = sort_order
+ self.player_id = player_id
+ self.nick = nick
+ self.alivetime = alivetime
+
+ def nick_html_colors(self):
+ return html_colors(self.nick)
+
+ def __repr__(self):
+ return "<ActivePlayer(%s, %s)>" % (self.sort_order, self.player_id)
+
+
+class ActiveServer(object):
+ def __init__(self, sort_order=None, server_id=None, server_name=None,
+ games=None):
+ self.sort_order = sort_order
+ self.server_id = server_id
+ self.server_name = server_name
+ self.games = games
+
+ def __repr__(self):
+ return "<ActiveServer(%s, %s)>" % (self.sort_order, self.server_id)
+
+
+class ActiveMap(object):
+ def __init__(self, sort_order=None, map_id=None, map_name=None,
+ games=None):
+ self.sort_order = sort_order
+ self.map_id = map_id
+ self.map_name = map_name
+ self.games = games
+
+ def __repr__(self):
+ return "<ActiveMap(%s, %s)>" % (self.sort_order, self.map_id)
+
+
def initialize_db(engine=None):
DBSession.configure(bind=engine)
Base.metadata.bind = engine
team_game_stats_table = MetaData.tables['team_game_stats']
player_game_anticheats_table = MetaData.tables['player_game_anticheats']
player_groups_table = MetaData.tables['player_groups']
+ active_players_table = MetaData.tables['active_players_mv']
+ active_servers_table = MetaData.tables['active_servers_mv']
+ active_maps_table = MetaData.tables['active_maps_mv']
# now map the tables and the objects together
mapper(PlayerAchievement, achievements_table)
mapper(TeamGameStat, team_game_stats_table)
mapper(PlayerGameAnticheat, player_game_anticheats_table)
mapper(PlayerGroups, player_groups_table)
+ mapper(ActivePlayer, active_players_table)
+ mapper(ActiveServer, active_servers_table)
+ mapper(ActiveMap, active_maps_table)
##### ACTIVE PLAYERS #####
<div class="row">
<div class="small-12 large-4 columns">
- <h5>Most Active Players <a href="${request.route_url('top_players_by_time', page=1)}" title="See more player activity"><i class="fa fa-plus-circle"></i></a></h5>
+ <h5>Most Active Players <a href="${request.route_url('top_players_index')}" title="See more player activity"><i class="fa fa-plus-circle"></i></a></h5>
<table class="table table-hover table-condensed">
<thead>
<tr>
</tr>
</thead>
<tbody>
- <% i = 1 %>
- % for (player_id, nick, alivetime) in top_players:
+ % for tp in top_players:
<tr>
- <td>${i}</td>
- % if player_id != '-':
- <td class="no-stretch"><a href="${request.route_url('player_info', id=player_id)}" title="Go to the player info page for this player">${nick|n}</a></td>
- % else:
- <td class="no-stretch" style="max-width:150px;">${nick|n}</td>
- % endif
- <td>${alivetime}</td>
+ <td>${tp.sort_order}</td>
+ <td class="no-stretch"><a href="${request.route_url('player_info', id=tp.player_id)}" title="Go to the player info page for this player">${tp.nick_html_colors()|n}</a></td>
+ <td>${tp.alivetime}</td>
</tr>
- <% i = i+1 %>
% endfor
</tbody>
</table>
##### ACTIVE SERVERS #####
<div class="small-12 large-4 columns">
- <h5>Most Active Servers <a href="${request.route_url('top_servers_by_players', page=1)}" title="See more server activity"><i class="fa fa-plus-circle"></i></a></h5>
+ <h5>Most Active Servers <a href="${request.route_url('top_servers_index')}" title="See more server activity"><i class="fa fa-plus-circle"></i></a></h5>
<table class="table table-hover table-condensed">
<thead>
<tr>
</tr>
</thead>
<tbody>
- <% i = 1 %>
- % for (server_id, name, count) in top_servers:
+ % for ts in top_servers:
<tr>
- <td>${i}</td>
- % if server_id != '-':
- <td class="no-stretch"><a href="${request.route_url('server_info', id=server_id)}" title="Go to the server info page for ${name}">${name}</a></td>
- % else:
- <td>${name}</td>
- % endif
- <td>${count}</td>
+ <td>${ts.sort_order}</td>
+ <td class="no-stretch"><a href="${request.route_url('server_info', id=ts.server_id)}" title="Go to the server info page for ${ts.server_name}">${ts.server_name}</a></td>
+ <td>${ts.games}</td>
</tr>
- <% i = i+1 %>
% endfor
</tbody>
</table>
##### ACTIVE MAPS #####
<div class="small-12 large-4 columns">
- <h5>Most Active Maps <a href="${request.route_url('top_maps_by_times_played', page=1)}" title="See more map activity"><i class="fa fa-plus-circle"></i></a></h5>
+ <h5>Most Active Maps <a href="${request.route_url('top_maps_index')}" title="See more map activity"><i class="fa fa-plus-circle"></i></a></h5>
<table class="table table-hover table-condensed">
<thead>
<tr>
</tr>
</thead>
<tbody>
- <% i = 1 %>
- % for (map_id, name, count) in top_maps:
+ % for tm in top_maps:
<tr>
- <td>${i}</td>
- % if map_id != '-':
- <td class="no-stretch"><a href="${request.route_url('map_info', id=map_id)}" title="Go to the map info page for ${name}">${name}</a></td>
- % else:
- <td>${name}</td>
- % endif
- <td>${count}</td>
+ <td>${tm.sort_order}</td>
+ <td>${tm.map_name}</td>
+ <td>${tm.games}</td>
</tr>
- <% i = i+1 %>
% endfor
</tbody>
</table>
</div>
</div>
+
<div class="row">
<div class="small-12 columns">
<small>*Most active stats are from the past 7 days</small>
<%inherit file="base.mako"/>
<%namespace name="nav" file="nav.mako" />
-<%namespace file="navlinks.mako" import="navlinks" />
<%block name="navigation">
${nav.nav('maps')}
Active Maps Index
</%block>
-% if not top_maps:
-<h2>Sorry, no maps yet. Get playing!</h2>
+% if not top_maps and start is not None:
+ <h2 class="text-center">Sorry, no more maps!</h2>
+
+% elif not top_maps and start is None:
+ <h2 class="text-center">No active maps found. Yikes, get playing!</h2>
% else:
##### ACTIVE SERVERS #####
</tr>
</thead>
<tbody>
- ##### this is to get around the actual row_number/rank of the map not being in the actual query
- <% i = 1 + (top_maps.page-1) * 25%>
- % for (map_id, name, count) in top_maps:
+ % for tm in top_maps:
<tr>
- <td>${i}</td>
- % if map_id != '-':
- <td class="no-stretch"><a href="${request.route_url('map_info', id=map_id)}" title="Go to the map info page for ${name}">${name}</a></td>
- % else:
- <td class="nostretch">${name}</td>
- % endif
- <td>${count}</td>
+ <td>${tm.sort_order}</td>
+ <td class="no-stretch"><a href="${request.route_url('map_info', id=tm.map_id)}" title="Go to the map info page for ${tm.map_name}">${tm.map_name}</a></td>
+ <td>${tm.sort_order}</td>
</tr>
- <% i = i+1 %>
% endfor
</tbody>
</table>
- <small>*figures are from the past 7 days<small>
+ <p class="text-center"><small>Note: these figures are from the past 7 days</small>
</div>
</div>
- <div class="row">
- <div class="small-12 large-6 large-offset-3 columns">
- ${navlinks("top_maps_by_times_played", top_maps.page, top_maps.last_page)}
- </div>
+% if len(top_maps) == 20:
+<div class="row">
+ <div class="small-12 large-6 large-offset-3 columns">
+ <ul class="pagination">
+ <li>
+ <a href="${request.route_url('top_maps_index', _query=query)}" name="Next Page">Next <i class="fa fa-arrow-right"></i></a>
+ </li>
+ </ul>
</div>
+</div>
+% endif
% endif
<%inherit file="base.mako"/>
<%namespace name="nav" file="nav.mako" />
-<%namespace file="navlinks.mako" import="navlinks" />
<%block name="navigation">
${nav.nav('players')}
Active Players Index
</%block>
-% if not top_players:
- <h2>Sorry, no players yet. Get playing!</h2>
+% if not top_players and start is not None:
+ <h2 class="text-center">Sorry, no more players!</h2>
+
+% elif not top_players and start is None:
+ <h2 class="text-center">No active players found. Yikes, get playing!</h2>
% else:
##### ACTIVE PLAYERS #####
</thead>
<tbody>
- ##### this is to get around the actual row_number/rank of the player not being in the actual query
- <% i = 1 + (top_players.page-1) * 25%>
- % for (player_id, nick, alivetime) in top_players.items:
+ % for tp in top_players:
<tr>
- <td>${i}</td>
- % if player_id != '-':
- <td class="no-stretch"><a href="${request.route_url('player_info', id=player_id)}" title="Go to the player info page for this player">${nick|n}</a></td>
- % else:
- <td class="no-stretch">${nick|n}</td>
- % endif
- <td>${alivetime}</td>
+ <td>${tp.sort_order}</td>
+ <td class="no-stretch"><a href="${request.route_url('player_info', id=tp.player_id)}" title="Go to the player info page for this player">${tp.nick_html_colors()|n}</a></td>
+ <td>${tp.alivetime}</td>
</tr>
- <% i = i+1 %>
% endfor
</tbody>
</table>
- <small>*figures are from the past 7 days</small>
+ <p class="text-center"><small>Note: these figures are from the past 7 days</small>
</div>
</div>
- <div class="row">
- <div class="small-12 large-6 large-offset-3 columns">
- ${navlinks("top_players_by_time", top_players.page, top_players.last_page)}
- </div>
+% if len(top_players) == 20:
+<div class="row">
+ <div class="small-12 large-6 large-offset-3 columns">
+ <ul class="pagination">
+ <li>
+ <a href="${request.route_url('top_players_index', _query=query)}" name="Next Page">Next <i class="fa fa-arrow-right"></i></a>
+ </li>
+ </ul>
</div>
+</div>
+% endif
+
% endif
<%inherit file="base.mako"/>
<%namespace name="nav" file="nav.mako" />
-<%namespace file="navlinks.mako" import="navlinks" />
<%block name="navigation">
${nav.nav('servers')}
Active Servers Index
</%block>
-% if not top_servers:
- <h2>Sorry, no servers yet. Get playing!</h2>
+% if not top_servers and start is not None:
+ <h2 class="text-center">Sorry, no more servers!</h2>
+
+% elif not top_servers and start is None:
+ <h2 class="text-center">No active servers found. Yikes, get playing!</h2>
% else:
##### ACTIVE SERVERS #####
</tr>
</thead>
<tbody>
- ##### this is to get around the actual row_number/rank of the server not being in the actual query
- <% i = 1 + (top_servers.page-1) * 25%>
- % for (server_id, name, count) in top_servers.items:
+ % for ts in top_servers:
<tr>
- <td>${i}</td>
- % if server_id != '-':
- <td class="no-stretch"><a href="${request.route_url('server_info', id=server_id)}" title="Go to the server info page for ${name}">${name}</a></td>
- % else:
- <td class="no-stretch">${name}</td>
- % endif
- <td>${count}</td>
+ <td>${ts.sort_order}</td>
+ <td class="no-stretch"><a href="${request.route_url('server_info', id=ts.server_id)}" title="Go to the server info page for ${ts.server_name}">${ts.server_name}</a></td>
+ <td>${ts.games}</td>
</tr>
- <% i = i+1 %>
% endfor
</tbody>
</table>
- <small>*figures are from the past 7 days<small>
+ <p class="text-center"><small>Note: these figures are from the past 7 days</small>
</div>
</div>
- <div class="row">
- <div class="small-12 large-6 large-offset-3 columns">
- ${navlinks("top_servers_by_players", top_servers.page, top_servers.last_page)}
- </div>
+% if len(top_servers) == 20:
+<div class="row">
+ <div class="small-12 large-6 large-offset-3 columns">
+ <ul class="pagination">
+ <li>
+ <a href="${request.route_url('top_servers_index', _query=query)}" name="Next Page">Next <i class="fa fa-arrow-right"></i></a>
+ </li>
+ </ul>
</div>
+</div>
+% endif
% endif
from xonstat.views.exceptions import notfound
-from xonstat.views.main import main_index, top_players_by_time, top_servers_by_players
-from xonstat.views.main import top_servers_by_players, top_maps_by_times_played
+from xonstat.views.main import main_index, top_players_index, top_servers_index
+from xonstat.views.main import top_maps_index
from xonstat.views.admin import forbidden, login, merge
return ranks
-def top_players_by_time_q(cutoff_days):
- """
- Query for the top players by the amount of time played during a date range.
-
- Games older than cutoff_days days old are ignored.
- """
-
- # only games played during this range are considered
- right_now = datetime.utcnow()
- cutoff_dt = right_now - timedelta(days=cutoff_days)
-
- top_players_q = DBSession.query(Player.player_id, Player.nick,
- func.sum(PlayerGameStat.alivetime)).\
- filter(Player.player_id == PlayerGameStat.player_id).\
- filter(Player.player_id > 2).\
- filter(expr.between(PlayerGameStat.create_dt, cutoff_dt, right_now)).\
- order_by(expr.desc(func.sum(PlayerGameStat.alivetime))).\
- group_by(Player.nick).\
- group_by(Player.player_id)
-
- return top_players_q
-
-
@cache_region('hourly_term')
-def get_top_players_by_time(cutoff_days):
+def get_top_players_by_time(limit=None, start=None):
"""
The top players by the amount of time played during a date range.
-
- Games older than cutoff_days days old are ignored.
"""
- # how many to retrieve
- count = 10
-
- # only games played during this range are considered
- right_now = datetime.utcnow()
- cutoff_dt = right_now - timedelta(days=cutoff_days)
-
- top_players_q = top_players_by_time_q(cutoff_days)
+ q = DBSession.query(ActivePlayer)
- top_players = top_players_q.limit(count).all()
+ if start is not None:
+ q = q.filter(ActivePlayer.sort_order >= start)
- top_players = [(player_id, html_colors(nick), score) \
- for (player_id, nick, score) in top_players]
+ q = q.order_by(ActivePlayer.sort_order)
- return top_players
+ if limit is not None:
+ q = q.limit(limit)
-
-def top_servers_by_players_q(cutoff_days):
- """
- Query to get the top servers by the amount of players active
- during a date range.
-
- Games older than cutoff_days days old are ignored.
- """
- # only games played during this range are considered
- right_now = datetime.utcnow()
- cutoff_dt = right_now - timedelta(days=cutoff_days)
-
- top_servers_q = DBSession.query(Server.server_id, Server.name,
- func.count()).\
- filter(Game.server_id==Server.server_id).\
- filter(expr.between(Game.create_dt, cutoff_dt, right_now)).\
- order_by(expr.desc(func.count(Game.game_id))).\
- group_by(Server.server_id).\
- group_by(Server.name)
-
- return top_servers_q
+ return q.all()
@cache_region('hourly_term')
-def get_top_servers_by_players(cutoff_days):
+def get_top_servers_by_games(limit=None, start=None):
"""
- The top servers by the amount of players active during a date range.
-
- Games older than cutoff_days days old are ignored.
+ The top servers by the number of games played during a date range.
"""
- # how many to retrieve
- count = 10
-
- top_servers = top_servers_by_players_q(cutoff_days).limit(count).all()
-
- return top_servers
+ q = DBSession.query(ActiveServer)
+ if start is not None:
+ q = q.filter(ActiveServer.sort_order >= start)
-def top_maps_by_times_played_q(cutoff_days):
- """
- Query to retrieve the top maps by the amount of times it was played
- during a date range.
-
- Games older than cutoff_days days old are ignored.
- """
- # only games played during this range are considered
- right_now = datetime.utcnow()
- cutoff_dt = right_now - timedelta(days=cutoff_days)
+ q = q.order_by(ActiveServer.sort_order)
- top_maps_q = DBSession.query(Game.map_id, Map.name,
- func.count()).\
- filter(Map.map_id==Game.map_id).\
- filter(expr.between(Game.create_dt, cutoff_dt, right_now)).\
- order_by(expr.desc(func.count())).\
- group_by(Game.map_id).\
- group_by(Map.name)
+ if limit is not None:
+ q = q.limit(limit)
- return top_maps_q
+ return q.all()
@cache_region('hourly_term')
-def get_top_maps_by_times_played(cutoff_days):
+def get_top_maps_by_games(limit=None, start=None):
"""
- The top maps by the amount of times it was played during a date range.
-
- Games older than cutoff_days days old are ignored.
+ The top maps by the number of games played during a date range.
"""
- # how many to retrieve
- count = 10
+ q = DBSession.query(ActiveMap)
+
+ if start is not None:
+ q = q.filter(ActiveMap.sort_order >= start)
+
+ q = q.order_by(ActiveMap.sort_order)
- top_maps = top_maps_by_times_played_q(cutoff_days).limit(count).all()
+ if limit is not None:
+ q = q.limit(limit)
- return top_maps
+ return q.all()
def _main_index_data(request):
back_then = datetime.utcnow() - timedelta(days=leaderboard_lifetime)
# top players by playing time
- top_players = get_top_players_by_time(leaderboard_lifetime)
+ top_players = get_top_players_by_time(10)
- # top servers by number of total players played
- top_servers = get_top_servers_by_players(leaderboard_lifetime)
+ # top servers by number of games
+ top_servers = get_top_servers_by_games(10)
# top maps by total times played
- top_maps = get_top_maps_by_times_played(leaderboard_lifetime)
+ top_maps = get_top_maps_by_games(10)
# recent games played in descending order
rgs = recent_games_q(cutoff=back_then).limit(recent_games_count).all()
"""
Display the main page information.
"""
- mainindex_data = _main_index_data(request)
-
- # FIXME: code clone, should get these from _main_index_data
- leaderboard_count = 10
- recent_games_count = 20
-
- for i in range(leaderboard_count-len(mainindex_data['top_players'])):
- mainindex_data['top_players'].append(('-', '-', '-'))
-
- for i in range(leaderboard_count-len(mainindex_data['top_servers'])):
- mainindex_data['top_servers'].append(('-', '-', '-'))
-
- for i in range(leaderboard_count-len(mainindex_data['top_maps'])):
- mainindex_data['top_maps'].append(('-', '-', '-'))
-
- return mainindex_data
+ return _main_index_data(request)
def main_index_json(request):
return [{'status':'not implemented'}]
-def top_players_by_time(request):
- current_page = request.params.get('page', 1)
-
- cutoff_days = int(request.registry.settings.\
- get('xonstat.leaderboard_lifetime', 30))
-
- top_players_q = top_players_by_time_q(cutoff_days)
-
- top_players = Page(top_players_q, current_page, items_per_page=25, url=page_url)
-
- top_players.items = [(player_id, html_colors(nick), score) \
- for (player_id, nick, score) in top_players.items]
+def top_players_index(request):
+ try:
+ start = int(request.params.get('start', None))
+ except:
+ start = None
- return {'top_players':top_players}
+ top_players = get_top_players_by_time(20, start)
+ # building a query string
+ query = {}
+ if len(top_players) > 1:
+ query['start'] = top_players[-1].sort_order + 1
-def top_servers_by_players(request):
- current_page = request.params.get('page', 1)
+ return {
+ 'top_players':top_players,
+ 'query':query,
+ 'start':start,
+ }
- cutoff_days = int(request.registry.settings.\
- get('xonstat.leaderboard_lifetime', 30))
- top_servers_q = top_servers_by_players_q(cutoff_days)
+def top_servers_index(request):
+ try:
+ start = int(request.params.get('start', None))
+ except:
+ start = None
- top_servers = Page(top_servers_q, current_page, items_per_page=25, url=page_url)
+ top_servers = get_top_servers_by_games(20, start)
- return {'top_servers':top_servers}
+ # building a query string
+ query = {}
+ if len(top_servers) > 1:
+ query['start'] = top_servers[-1].sort_order + 1
+ return {
+ 'top_servers':top_servers,
+ 'query':query,
+ 'start':start,
+ }
-def top_maps_by_times_played(request):
- current_page = request.params.get('page', 1)
- cutoff_days = int(request.registry.settings.\
- get('xonstat.leaderboard_lifetime', 30))
+def top_maps_index(request):
+ try:
+ start = int(request.params.get('start', None))
+ except:
+ start = None
- top_maps_q = top_maps_by_times_played_q(cutoff_days)
+ top_maps = get_top_maps_by_games(20, start)
- top_maps = Page(top_maps_q, current_page, items_per_page=25, url=page_url)
+ # building a query string
+ query = {}
+ if len(top_maps) > 1:
+ query['start'] = top_maps[-1].sort_order + 1
- return {'top_maps':top_maps}
+ return {
+ 'top_maps':top_maps,
+ 'query':query,
+ 'start':start,
+ }