Implemented some (preliminary) JSON API to retrieve player data
authorJan D. Behrens <zykure@web.de>
Sat, 15 Sep 2012 17:47:25 +0000 (19:47 +0200)
committerJan D. Behrens <zykure@web.de>
Sat, 15 Sep 2012 17:47:25 +0000 (19:47 +0200)
This function will be used e.g. by the Xonotic IRC pickup bot.

.gitignore
development.ini
xonstat/batch/badges/gen_badges.py
xonstat/crypto-keygen-standalone [new symlink]
xonstat/static/js/bootstrap-tabs.js [new file with mode: 0644]
xonstat/util.py
xonstat/views/player.py

index 8e48bc7692b8264bb196983b972be87bab001422..aa68c64a5008f1b10c4d0ce376f1a6b028a9e795 100644 (file)
@@ -1,5 +1,7 @@
-*.pyc
 *~
 *.bak
 *~
 *.bak
-xonstat/batch/badges/output/*.png
-xonstat/batch/badges/output/*/*.png
+*.tmp
+*.old
+*.pyc
+/xonstat/batch/badges/output/*.png
+/xonstat/batch/badges/output/*/*.png
index c3d1cf83f50a443f9ffc25209d2c372f447d1b2f..4ba4338e332186a69e0a28f7503cf4b2cc4e2bd4 100755 (executable)
@@ -6,7 +6,7 @@ debug_notfound = false
 debug_routematch = false
 debug_templates = true
 default_locale_name = en
 debug_routematch = false
 debug_templates = true
 default_locale_name = en
-sqlalchemy.url = postgresql+psycopg2://xonstat:xonstat@localhost:5433/xonstatdb
+sqlalchemy.url = postgresql+psycopg2://xonstat:xonstat@localhost:5432/xonstatdb
 session.type = file
 session.data_dir = %(here)s/data/sessions/data
 session.lock_dir = %(here)s/data/sessions/lock
 session.type = file
 session.data_dir = %(here)s/data/sessions/data
 session.lock_dir = %(here)s/data/sessions/lock
index 0aa3f6014f28ced6956835d349b909925e9e77e6..44d73aec3da4f1ea2a16690cf9e965c954777b33 100644 (file)
@@ -7,6 +7,7 @@ import sqlalchemy.sql.functions as func
 from sqlalchemy import distinct
 from pyramid.paster import bootstrap
 from xonstat.models import *
 from sqlalchemy import distinct
 from pyramid.paster import bootstrap
 from xonstat.models import *
+from xonstat.util import datetime_seconds
 
 from skin import Skin
 from playerdata import PlayerData
 
 from skin import Skin
 from playerdata import PlayerData
@@ -146,8 +147,7 @@ playerdata = PlayerData()
 if len(players) > 0:
     stop = datetime.now()
     td = stop-start
 if len(players) > 0:
     stop = datetime.now()
     td = stop-start
-    total_seconds = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
-    print "Query took %.2f seconds" % (total_seconds)
+    print "Query took %.2f seconds" % (datetime_seconds(td))
 
     print "Creating badges for %d players ..." % len(players)
     start = datetime.now()
 
     print "Creating badges for %d players ..." % len(players)
     start = datetime.now()
@@ -159,20 +159,18 @@ if len(players) > 0:
         playerdata.get_data(player_id)
         sstop = datetime.now()
         td = sstop-sstart
         playerdata.get_data(player_id)
         sstop = datetime.now()
         td = sstop-sstart
-        total_seconds = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
-        data_time += total_seconds
+        data_time += datetime_seconds(td)
 
         sstart = datetime.now()
         for sk in skins:
             sk.render_image(playerdata, "output/%s/%d.png" % (str(sk), player_id[0]))
         sstop = datetime.now()
         td = sstop-sstart
 
         sstart = datetime.now()
         for sk in skins:
             sk.render_image(playerdata, "output/%s/%d.png" % (str(sk), player_id[0]))
         sstop = datetime.now()
         td = sstop-sstart
-        total_seconds = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
-        render_time += total_seconds
+        render_time += datetime_seconds(td)
 
     stop = datetime.now()
     td = stop-start
 
     stop = datetime.now()
     td = stop-start
-    total_seconds = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
+    total_seconds = datetime_seconds(td)
     print "Creating the badges took %.1f seconds (%.3f s per player)" % (total_seconds, total_seconds/float(len(players)))
     print "Total time for rendering images: %.3f s" % render_time
     print "Total time for getting data: %.3f s" % data_time
     print "Creating the badges took %.1f seconds (%.3f s per player)" % (total_seconds, total_seconds/float(len(players)))
     print "Total time for rendering images: %.3f s" % render_time
     print "Total time for getting data: %.3f s" % data_time
diff --git a/xonstat/crypto-keygen-standalone b/xonstat/crypto-keygen-standalone
new file mode 120000 (symlink)
index 0000000..32f91eb
--- /dev/null
@@ -0,0 +1 @@
+/usr/local/games/Xonotic/misc/infrastructure/keygen/crypto-keygen-standalone
\ No newline at end of file
diff --git a/xonstat/static/js/bootstrap-tabs.js b/xonstat/static/js/bootstrap-tabs.js
new file mode 100644 (file)
index 0000000..a3c7ee1
--- /dev/null
@@ -0,0 +1,80 @@
+/* ========================================================
+ * bootstrap-tabs.js v1.4.0
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2011 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function( $ ){
+
+  "use strict"
+
+  function activate ( element, container ) {
+    container
+      .find('> .active')
+      .removeClass('active')
+      .find('> .dropdown-menu > .active')
+      .removeClass('active')
+
+    element.addClass('active')
+
+    if ( element.parent('.dropdown-menu') ) {
+      element.closest('li.dropdown').addClass('active')
+    }
+  }
+
+  function tab( e ) {
+    var $this = $(this)
+      , $ul = $this.closest('ul:not(.dropdown-menu)')
+      , href = $this.attr('href')
+      , previous
+      , $href
+
+    if ( /^#\w+/.test(href) ) {
+      e.preventDefault()
+
+      if ( $this.parent('li').hasClass('active') ) {
+        return
+      }
+
+      previous = $ul.find('.active a').last()[0]
+      $href = $(href)
+
+      activate($this.parent('li'), $ul)
+      activate($href, $href.parent())
+
+      $this.trigger({
+        type: 'change'
+      , relatedTarget: previous
+      })
+    }
+  }
+
+
+ /* TABS/PILLS PLUGIN DEFINITION
+  * ============================ */
+
+  $.fn.tabs = $.fn.pills = function ( selector ) {
+    return this.each(function () {
+      $(this).delegate(selector || '.tabs li > a, .pills > li > a', 'click', tab)
+    })
+  }
+
+  $(document).ready(function () {
+    $('body').tabs('ul[data-tabs] li > a, ul[data-pills] > li > a')
+  })
+
+}( window.jQuery || window.ender );
index f9aa1d5c07f96135f47cfdc71d2972bb3b693ec1..7c2692d45d51651605b2e78ba9ff98929fd7fd50 100644 (file)
@@ -151,3 +151,7 @@ def pretty_date(time=False):
         return "almost 2 years ago"
     else:
         return "about {0} years ago".format(int(round(dim/525600.0)))
         return "almost 2 years ago"
     else:
         return "about {0} years ago".format(int(round(dim/525600.0)))
+
+def datetime_seconds(td):
+    return float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
+
index a1ff71919612d4c1e2051e0c4586ba3cafe7150f..a783785324bf8a2ab021503717152b192194caa4 100644 (file)
@@ -10,7 +10,7 @@ from pyramid.url import current_route_url
 from sqlalchemy import desc, distinct
 from webhelpers.paginate import Page, PageURL
 from xonstat.models import *
 from sqlalchemy import desc, distinct
 from webhelpers.paginate import Page, PageURL
 from xonstat.models import *
-from xonstat.util import page_url
+from xonstat.util import page_url, datetime_seconds
 
 log = logging.getLogger(__name__)
 
 
 log = logging.getLogger(__name__)
 
@@ -552,7 +552,44 @@ def player_info_json(request):
     """
     Provides detailed information on a specific player. JSON.
     """
     """
     Provides detailed information on a specific player. JSON.
     """
-    return [{'status':'not implemented'}]
+    player_info = player_info_data(request)
+    json_result = {
+        'player': {
+            'id':               player_info['player'].player_id,
+            'nick':             player_info['player'].nick.encode('utf-8'),
+            'stripped_nick':    player_info['player'].nick_strip_colors(),
+            'joined':           player_info['player'].create_dt.isoformat(),
+            },
+        'elos':         player_info['elos'],
+        'ranks':        player_info['ranks'],
+        'total_stats':  {
+                'games':            player_info['total_stats']['games'],
+                'games_breakdown':  player_info['total_stats']['games_breakdown'],
+                'alivetime':        datetime_seconds(player_info['total_stats']['alivetime']),
+                'kills':            player_info['total_stats']['kills'],
+                'deaths':           player_info['total_stats']['deaths'],
+                'suicides':         player_info['total_stats']['suicides'],
+                'wins':             player_info['total_stats']['wins'],
+                # FIXME - current "wins" query is flawed!
+                #'losses':           player_info['total_stats']['loses'],
+            },
+        'recent_games': [
+                {
+                    'game_id':      game.game_id,
+                    'game_type':    game.game_type_cd,
+                    'server':       server.name,
+                    'map':          map.name,
+                    'team':         gamestat.team,
+                    'rank':         gamestat.rank,
+                    'win':          ((gamestat.team != None and gamestat.team == game.winner)
+                                        or (gamestat.team == None and gamestat.rank == 1)),
+                    'time':         game.create_dt.isoformat(),
+                }
+                for (gamestat, game, server, map) in player_info['recent_games'][:5]
+            ],
+        }
+    print json_result
+    return json_result
 
 
 def player_game_index_data(request):
 
 
 def player_game_index_data(request):