From 43e5f9720f6d561d7dfe9c94c4c920fb9a13d01b Mon Sep 17 00:00:00 2001 From: "Jan D. Behrens" Date: Sat, 15 Sep 2012 19:47:25 +0200 Subject: [PATCH] Implemented some (preliminary) JSON API to retrieve player data This function will be used e.g. by the Xonotic IRC pickup bot. --- .gitignore | 8 +-- development.ini | 2 +- xonstat/batch/badges/gen_badges.py | 12 ++--- xonstat/crypto-keygen-standalone | 1 + xonstat/static/js/bootstrap-tabs.js | 80 +++++++++++++++++++++++++++++ xonstat/util.py | 4 ++ xonstat/views/player.py | 41 ++++++++++++++- 7 files changed, 135 insertions(+), 13 deletions(-) create mode 120000 xonstat/crypto-keygen-standalone create mode 100644 xonstat/static/js/bootstrap-tabs.js diff --git a/.gitignore b/.gitignore index 8e48bc7..aa68c64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ -*.pyc *~ *.bak -xonstat/batch/badges/output/*.png -xonstat/batch/badges/output/*/*.png +*.tmp +*.old +*.pyc +/xonstat/batch/badges/output/*.png +/xonstat/batch/badges/output/*/*.png diff --git a/development.ini b/development.ini index c3d1cf8..4ba4338 100755 --- a/development.ini +++ b/development.ini @@ -6,7 +6,7 @@ debug_notfound = false 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 diff --git a/xonstat/batch/badges/gen_badges.py b/xonstat/batch/badges/gen_badges.py index 0aa3f60..44d73ae 100644 --- a/xonstat/batch/badges/gen_badges.py +++ b/xonstat/batch/badges/gen_badges.py @@ -7,6 +7,7 @@ import sqlalchemy.sql.functions as func 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 @@ -146,8 +147,7 @@ playerdata = PlayerData() 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() @@ -159,20 +159,18 @@ if len(players) > 0: 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 - 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 - 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 diff --git a/xonstat/crypto-keygen-standalone b/xonstat/crypto-keygen-standalone new file mode 120000 index 0000000..32f91eb --- /dev/null +++ b/xonstat/crypto-keygen-standalone @@ -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 index 0000000..a3c7ee1 --- /dev/null +++ b/xonstat/static/js/bootstrap-tabs.js @@ -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 ); diff --git a/xonstat/util.py b/xonstat/util.py index f9aa1d5..7c2692d 100644 --- a/xonstat/util.py +++ b/xonstat/util.py @@ -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))) + +def datetime_seconds(td): + return float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 + diff --git a/xonstat/views/player.py b/xonstat/views/player.py index a1ff719..a783785 100644 --- a/xonstat/views/player.py +++ b/xonstat/views/player.py @@ -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 xonstat.util import page_url +from xonstat.util import page_url, datetime_seconds log = logging.getLogger(__name__) @@ -552,7 +552,44 @@ def player_info_json(request): """ 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): -- 2.39.2