Make the active players/servers/maps use the cache.
authorAnt Zucaro <azucaro@gmail.com>
Sat, 6 Feb 2016 21:21:44 +0000 (16:21 -0500)
committerAnt Zucaro <azucaro@gmail.com>
Sat, 6 Feb 2016 21:21:44 +0000 (16:21 -0500)
Instead of fetching from the base data, the active players/server/maps views
will fetch from the so-called "materialized view" tables instead. These tables
are precomputed and will be MUCH faster, performance-wise. Regular Beaker
caching remains the same for these, and the paginated pages now only support
clicking "more" until the list is exhausted. Perhaps in the future they will be
fetched via JSON and appended to the page in a "never-ending scroll" thing.

xonstat/__init__.py
xonstat/models.py
xonstat/templates/main_index.mako
xonstat/templates/top_maps_by_times_played.mako
xonstat/templates/top_players_by_time.mako
xonstat/templates/top_servers_by_players.mako
xonstat/views/__init__.py
xonstat/views/main.py

index 1609f4d..5466efd 100644 (file)
@@ -101,14 +101,14 @@ def main(global_config, **settings):
     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+}")
index e34a295..0ae5a52 100644 (file)
@@ -389,6 +389,45 @@ class PlayerCapTime(object):
             }
 
 
+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
@@ -417,6 +456,9 @@ def initialize_db(engine=None):
     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)
@@ -438,3 +480,6 @@ def initialize_db(engine=None):
     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)
index 5f4fa79..3405039 100644 (file)
@@ -73,7 +73,7 @@
 ##### 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>
index ceb32f8..4a8f358 100644 (file)
@@ -1,6 +1,5 @@
 <%inherit file="base.mako"/>
 <%namespace name="nav" file="nav.mako" />
-<%namespace file="navlinks.mako" import="navlinks" />
 
 <%block name="navigation">
   ${nav.nav('maps')}
@@ -10,8 +9,11 @@
   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
index 37a47e9..9f75ff6 100644 (file)
@@ -1,6 +1,5 @@
 <%inherit file="base.mako"/>
 <%namespace name="nav" file="nav.mako" />
-<%namespace file="navlinks.mako" import="navlinks" />
 
 <%block name="navigation">
   ${nav.nav('players')}
@@ -10,8 +9,11 @@
   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
index ea6912f..4adba45 100644 (file)
@@ -1,6 +1,5 @@
 <%inherit file="base.mako"/>
 <%namespace name="nav" file="nav.mako" />
-<%namespace file="navlinks.mako" import="navlinks" />
 
 <%block name="navigation">
   ${nav.nav('servers')}
@@ -10,8 +9,11 @@
   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
index d293a83..4ca6718 100644 (file)
@@ -26,8 +26,8 @@ from xonstat.views.search import search_json
 
 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
 
index 1e937bf..98973a7 100644 (file)
@@ -111,125 +111,58 @@ def get_ranks(game_type_cd):
     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):
@@ -258,13 +191,13 @@ 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()
@@ -284,22 +217,7 @@ def main_index(request):
     """
     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):
@@ -309,43 +227,61 @@ 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,
+            }