Removed unnecessary files from default installation,
...split controllers into seperate files, created a separate file to hold helper functions, updated TODO, updated html template to show 'None' for used filters when no filters are used
This commit is contained in:
parent
587ed03445
commit
07a633e501
8 changed files with 355 additions and 258 deletions
|
@ -9,12 +9,9 @@
|
|||
--make the site user friendly
|
||||
--look into whether or not it would make sense to use AJAX
|
||||
|
||||
-code documentation and cleanness (6/24)
|
||||
--split off the different controllers (bar,pie,line) into seperate files
|
||||
|
||||
-add new views, do dogfeed testing of all the existing work (6/25)
|
||||
|
||||
-login support, sessions (6/25-6/31)
|
||||
-login support, sessions (6/25-6/30)
|
||||
--make the addview and deleteview pages password protected
|
||||
--add email subscription support
|
||||
|
||||
|
|
Binary file not shown.
78
website/stats.wesnoth.org/helperlib.py
Normal file
78
website/stats.wesnoth.org/helperlib.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
import MySQLdb
|
||||
import types
|
||||
import configuration
|
||||
import evaluators
|
||||
import time
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("wesstats")
|
||||
|
||||
#return the intersection of the items in the lists
|
||||
def intersect(*lists):
|
||||
return list(reduce(set.intersection, (set(l) for l in lists)))
|
||||
|
||||
def isvalid(date):
|
||||
date = date.split('/')
|
||||
if len(date) != 3:
|
||||
return False
|
||||
for i in date:
|
||||
if not i.isdigit():
|
||||
return False
|
||||
if int(i) < 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def scaled_query(curs,query,threshold,evaluator):
|
||||
s_time = time.time()
|
||||
#list of all the sample sizes
|
||||
curs.execute("SELECT TABLE_NAME FROM information_schema.tables WHERE `TABLE_NAME` REGEXP '^"+configuration.DB_TABLE_PREFIX+"SMPL'")
|
||||
results = curs.fetchall()
|
||||
sizes = []
|
||||
for result in results:
|
||||
sizes.append(int(result[0][len(configuration.DB_TABLE_PREFIX+"SMPL"):]))
|
||||
sizes.sort()
|
||||
#print sizes
|
||||
#try query on all the sample sizes in increasing order until we get one that meets the threshold
|
||||
for size in sizes:
|
||||
tblname = configuration.DB_TABLE_PREFIX+"SMPL"+str(size)
|
||||
nquery = query.replace("GAMES",tblname)
|
||||
curs.execute(nquery)
|
||||
results = curs.fetchall()
|
||||
length = evaluator(results)
|
||||
if length > threshold:
|
||||
log.debug("query took " + str(time.time()-s_time) + " seconds")
|
||||
return results
|
||||
log.debug("too few results from sample tables, using entire table")
|
||||
curs.execute(query)
|
||||
log.debug("query took " + str(time.time()-s_time) + " seconds")
|
||||
return curs.fetchall()
|
||||
|
||||
def fconstruct(filters,colname,list):
|
||||
if list[0] == "all":
|
||||
return filters
|
||||
newfilter = colname+" IN ("
|
||||
for i in range(0,len(list)):
|
||||
newfilter += "'" + list[i] + "'"
|
||||
if i != len(list) - 1:
|
||||
newfilter += ','
|
||||
newfilter += ')'
|
||||
if len(filters) != 0:
|
||||
filters += " AND "
|
||||
else:
|
||||
filters += " WHERE "
|
||||
filters += newfilter
|
||||
return filters
|
||||
|
||||
def dateconstruct(filters,start_date,end_date):
|
||||
if len(filters) != 0:
|
||||
filters += " AND "
|
||||
else:
|
||||
filters += " WHERE "
|
||||
filters += "timestamp BETWEEN '"+start_date+"' AND '"+end_date+"'"
|
||||
return filters
|
||||
|
||||
def listfix(l):
|
||||
if not isinstance(l,types.ListType):
|
||||
return [l]
|
||||
return l
|
||||
|
89
website/stats.wesnoth.org/wesstats/controllers/barview.py
Normal file
89
website/stats.wesnoth.org/wesstats/controllers/barview.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# $Id$
|
||||
"""
|
||||
Copyright (C) 2009 by Gregory Shikhman <cornmander@cornmander.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import MySQLdb
|
||||
import logging
|
||||
|
||||
import configuration
|
||||
import evaluators
|
||||
import helperlib
|
||||
|
||||
from tg import expose
|
||||
from wesstats.lib.base import BaseController
|
||||
|
||||
__all__ = ['BarGraphController']
|
||||
|
||||
log = logging.getLogger("wesstats")
|
||||
|
||||
class BarGraphController(BaseController):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
||||
@expose(template="wesstats.templates.pieview")
|
||||
def default(self,**kw):
|
||||
#pull data on this view from DB
|
||||
conn = MySQLdb.connect(configuration.DB_HOSTNAME,configuration.DB_USERNAME,configuration.DB_PASSWORD,configuration.DB_NAME,use_unicode=True)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("SELECT title,xdata,ydata,xlabel,ylabel,filters,y_xform FROM _wsviews WHERE url = %s", (self.url,))
|
||||
view_data = curs.fetchall()[0]
|
||||
log.debug("pie chart request, here is SQL data for this view:")
|
||||
log.debug(view_data)
|
||||
#fetch the relevant filters for this template and their possible values
|
||||
available_filters = view_data[5].split(',')
|
||||
fdata = dict()
|
||||
for filter in available_filters:
|
||||
curs.execute("SELECT DISTINCT "+filter+" FROM GAMES")
|
||||
#curs.fetchall() returns a list of lists, we convert this to a plain list for ease of handling
|
||||
raw_fdata = curs.fetchall()
|
||||
fdata[filter] = []
|
||||
for i in raw_fdata:
|
||||
fdata[filter].append(i[0])
|
||||
#print fdata
|
||||
filters = ""
|
||||
used_filters = helperlib.intersect(kw.keys(),available_filters)
|
||||
ufilters_vals = dict()
|
||||
for filter in used_filters:
|
||||
kw[filter] = helperlib.listfix(kw[filter])
|
||||
filter_vals = helperlib.intersect(kw[filter],fdata[filter])
|
||||
filters = helperlib.fconstruct(filters,filter,filter_vals)
|
||||
ufilters_vals[filter] = filter_vals
|
||||
if 'startdate' in kw and 'enddate' in kw and helperlib.isvalid(kw['startdate']) and helperlib.isvalid(kw['enddate']):
|
||||
filters = helperlib.dateconstruct(filters,kw['startdate'],kw['enddate'])
|
||||
used_filters.append("dates")
|
||||
ufilters_vals["dates"] = [kw['startdate'] + "-" + kw['enddate']]
|
||||
#get columns and column transformations for this view
|
||||
y_xforms = view_data[6].split(',')
|
||||
y_data = view_data[2].split(',')
|
||||
y_data_str = ""
|
||||
#they must be equal!
|
||||
assert len(y_data) == len(y_xforms)
|
||||
for i in range(len(y_data)):
|
||||
y_data_str += y_xforms[i] + "(" + y_data[i] + "),"
|
||||
y_data_str = y_data_str[0:len(y_data_str)-1]
|
||||
query = "SELECT "+view_data[1]+","+y_data_str+" FROM GAMES "+filters+" GROUP BY "+view_data[1]
|
||||
log.debug("SQL query:")
|
||||
log.debug(query)
|
||||
results = helperlib.scaled_query(curs,query,100,evaluators.count_eval)
|
||||
log.debug("query result:")
|
||||
log.debug(results)
|
||||
#generate JS datafields here because genshi templating can't emit JS...
|
||||
data = ""
|
||||
for i in range(0,len(results)):
|
||||
data += "data.setValue("+str(i)+",0,'"+results[i][0]+"');\n"
|
||||
data += "data.setValue("+str(i)+",1,"+str(results[i][1])+");\n"
|
||||
return dict(title=view_data[0],xlabel=view_data[3],ylabel=view_data[4],piedata=results,
|
||||
data=data,filters=available_filters,used_filters=used_filters,
|
||||
ufilters_vals=ufilters_vals,fdata=fdata)
|
89
website/stats.wesnoth.org/wesstats/controllers/lineview.py
Normal file
89
website/stats.wesnoth.org/wesstats/controllers/lineview.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# $Id$
|
||||
"""
|
||||
Copyright (C) 2009 by Gregory Shikhman <cornmander@cornmander.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import MySQLdb
|
||||
import logging
|
||||
|
||||
import configuration
|
||||
import evaluators
|
||||
import helperlib
|
||||
|
||||
from tg import expose
|
||||
from wesstats.lib.base import BaseController
|
||||
|
||||
__all__ = ['LineGraphController']
|
||||
|
||||
log = logging.getLogger("wesstats")
|
||||
|
||||
class LineGraphController(BaseController):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
||||
@expose(template="wesstats.templates.pieview")
|
||||
def default(self,**kw):
|
||||
#pull data on this view from DB
|
||||
conn = MySQLdb.connect(configuration.DB_HOSTNAME,configuration.DB_USERNAME,configuration.DB_PASSWORD,configuration.DB_NAME,use_unicode=True)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("SELECT title,xdata,ydata,xlabel,ylabel,filters,y_xform FROM _wsviews WHERE url = %s", (self.url,))
|
||||
view_data = curs.fetchall()[0]
|
||||
log.debug("pie chart request, here is SQL data for this view:")
|
||||
log.debug(view_data)
|
||||
#fetch the relevant filters for this template and their possible values
|
||||
available_filters = view_data[5].split(',')
|
||||
fdata = dict()
|
||||
for filter in available_filters:
|
||||
curs.execute("SELECT DISTINCT "+filter+" FROM GAMES")
|
||||
#curs.fetchall() returns a list of lists, we convert this to a plain list for ease of handling
|
||||
raw_fdata = curs.fetchall()
|
||||
fdata[filter] = []
|
||||
for i in raw_fdata:
|
||||
fdata[filter].append(i[0])
|
||||
#print fdata
|
||||
filters = ""
|
||||
used_filters = helperlib.intersect(kw.keys(),available_filters)
|
||||
ufilters_vals = dict()
|
||||
for filter in used_filters:
|
||||
kw[filter] = helperlib.listfix(kw[filter])
|
||||
filter_vals = helperlib.intersect(kw[filter],fdata[filter])
|
||||
filters = helperlib.fconstruct(filters,filter,filter_vals)
|
||||
ufilters_vals[filter] = filter_vals
|
||||
if 'startdate' in kw and 'enddate' in kw and helperlib.isvalid(kw['startdate']) and helperlib.isvalid(kw['enddate']):
|
||||
filters = helperlib.dateconstruct(filters,kw['startdate'],kw['enddate'])
|
||||
used_filters.append("dates")
|
||||
ufilters_vals["dates"] = [kw['startdate'] + "-" + kw['enddate']]
|
||||
#get columns and column transformations for this view
|
||||
y_xforms = view_data[6].split(',')
|
||||
y_data = view_data[2].split(',')
|
||||
y_data_str = ""
|
||||
#they must be equal!
|
||||
assert len(y_data) == len(y_xforms)
|
||||
for i in range(len(y_data)):
|
||||
y_data_str += y_xforms[i] + "(" + y_data[i] + "),"
|
||||
y_data_str = y_data_str[0:len(y_data_str)-1]
|
||||
query = "SELECT "+view_data[1]+","+y_data_str+" FROM GAMES "+filters+" GROUP BY "+view_data[1]
|
||||
log.debug("SQL query:")
|
||||
log.debug(query)
|
||||
results = helperlib.scaled_query(curs,query,100,evaluators.count_eval)
|
||||
log.debug("query result:")
|
||||
log.debug(results)
|
||||
#generate JS datafields here because genshi templating can't emit JS...
|
||||
data = ""
|
||||
for i in range(0,len(results)):
|
||||
data += "data.setValue("+str(i)+",0,'"+results[i][0]+"');\n"
|
||||
data += "data.setValue("+str(i)+",1,"+str(results[i][1])+");\n"
|
||||
return dict(title=view_data[0],xlabel=view_data[3],ylabel=view_data[4],piedata=results,
|
||||
data=data,filters=available_filters,used_filters=used_filters,
|
||||
ufilters_vals=ufilters_vals,fdata=fdata)
|
89
website/stats.wesnoth.org/wesstats/controllers/pieview.py
Normal file
89
website/stats.wesnoth.org/wesstats/controllers/pieview.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# $Id$
|
||||
"""
|
||||
Copyright (C) 2009 by Gregory Shikhman <cornmander@cornmander.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2
|
||||
or at your option any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import MySQLdb
|
||||
import logging
|
||||
|
||||
import configuration
|
||||
import evaluators
|
||||
import helperlib
|
||||
|
||||
from tg import expose
|
||||
from wesstats.lib.base import BaseController
|
||||
|
||||
__all__ = ['PieGraphController']
|
||||
|
||||
log = logging.getLogger("wesstats")
|
||||
|
||||
class PieGraphController(BaseController):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
||||
@expose(template="wesstats.templates.pieview")
|
||||
def default(self,**kw):
|
||||
#pull data on this view from DB
|
||||
conn = MySQLdb.connect(configuration.DB_HOSTNAME,configuration.DB_USERNAME,configuration.DB_PASSWORD,configuration.DB_NAME,use_unicode=True)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("SELECT title,xdata,ydata,xlabel,ylabel,filters,y_xform FROM _wsviews WHERE url = %s", (self.url,))
|
||||
view_data = curs.fetchall()[0]
|
||||
log.debug("pie chart request, here is SQL data for this view:")
|
||||
log.debug(view_data)
|
||||
#fetch the relevant filters for this template and their possible values
|
||||
available_filters = view_data[5].split(',')
|
||||
fdata = dict()
|
||||
for filter in available_filters:
|
||||
curs.execute("SELECT DISTINCT "+filter+" FROM GAMES")
|
||||
#curs.fetchall() returns a list of lists, we convert this to a plain list for ease of handling
|
||||
raw_fdata = curs.fetchall()
|
||||
fdata[filter] = []
|
||||
for i in raw_fdata:
|
||||
fdata[filter].append(i[0])
|
||||
#print fdata
|
||||
filters = ""
|
||||
used_filters = helperlib.intersect(kw.keys(),available_filters)
|
||||
ufilters_vals = dict()
|
||||
for filter in used_filters:
|
||||
kw[filter] = helperlib.listfix(kw[filter])
|
||||
filter_vals = helperlib.intersect(kw[filter],fdata[filter])
|
||||
filters = helperlib.fconstruct(filters,filter,filter_vals)
|
||||
ufilters_vals[filter] = filter_vals
|
||||
if 'startdate' in kw and 'enddate' in kw and helperlib.isvalid(kw['startdate']) and helperlib.isvalid(kw['enddate']):
|
||||
filters = helperlib.dateconstruct(filters,kw['startdate'],kw['enddate'])
|
||||
used_filters.append("dates")
|
||||
ufilters_vals["dates"] = [kw['startdate'] + "-" + kw['enddate']]
|
||||
#get columns and column transformations for this view
|
||||
y_xforms = view_data[6].split(',')
|
||||
y_data = view_data[2].split(',')
|
||||
y_data_str = ""
|
||||
#they must be equal!
|
||||
assert len(y_data) == len(y_xforms)
|
||||
for i in range(len(y_data)):
|
||||
y_data_str += y_xforms[i] + "(" + y_data[i] + "),"
|
||||
y_data_str = y_data_str[0:len(y_data_str)-1]
|
||||
query = "SELECT "+view_data[1]+","+y_data_str+" FROM GAMES "+filters+" GROUP BY "+view_data[1]
|
||||
log.debug("SQL query:")
|
||||
log.debug(query)
|
||||
results = helperlib.scaled_query(curs,query,100,evaluators.count_eval)
|
||||
log.debug("query result:")
|
||||
log.debug(results)
|
||||
#generate JS datafields here because genshi templating can't emit JS...
|
||||
data = ""
|
||||
for i in range(0,len(results)):
|
||||
data += "data.setValue("+str(i)+",0,'"+results[i][0]+"');\n"
|
||||
data += "data.setValue("+str(i)+",1,"+str(results[i][1])+");\n"
|
||||
return dict(title=view_data[0],xlabel=view_data[3],ylabel=view_data[4],piedata=results,
|
||||
data=data,filters=available_filters,used_filters=used_filters,
|
||||
ufilters_vals=ufilters_vals,fdata=fdata)
|
|
@ -14,96 +14,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import MySQLdb
|
||||
import types
|
||||
import configuration
|
||||
import evaluators
|
||||
import time
|
||||
import logging
|
||||
|
||||
from tg import expose, flash, require, url, request, redirect
|
||||
from pylons.i18n import ugettext as _, lazy_ugettext as l_
|
||||
from catwalk.tg2 import Catwalk
|
||||
from repoze.what import predicates
|
||||
import configuration
|
||||
import helperlib
|
||||
|
||||
from tg import expose
|
||||
|
||||
from wesstats.lib.base import BaseController
|
||||
from wesstats.model import DBSession, metadata
|
||||
from wesstats.controllers.error import ErrorController
|
||||
from wesstats import model
|
||||
from wesstats.controllers.secure import SecureController
|
||||
from wesstats.controllers.pieview import PieGraphController
|
||||
from wesstats.controllers.barview import BarGraphController
|
||||
from wesstats.controllers.lineview import LineGraphController
|
||||
|
||||
__all__ = ['RootController']
|
||||
|
||||
log = logging.getLogger("wesstats")
|
||||
|
||||
#return the intersection of the items in the lists
|
||||
def intersect(*lists):
|
||||
return list(reduce(set.intersection, (set(l) for l in lists)))
|
||||
|
||||
def isvalid(date):
|
||||
date = date.split('/')
|
||||
if len(date) != 3:
|
||||
return False
|
||||
for i in date:
|
||||
if not i.isdigit():
|
||||
return False
|
||||
if int(i) < 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def scaled_query(curs,query,threshold,evaluator):
|
||||
s_time = time.time()
|
||||
#list of all the sample sizes
|
||||
curs.execute("SELECT TABLE_NAME FROM information_schema.tables WHERE `TABLE_NAME` REGEXP '^"+configuration.DB_TABLE_PREFIX+"SMPL'")
|
||||
results = curs.fetchall()
|
||||
sizes = []
|
||||
for result in results:
|
||||
sizes.append(int(result[0][len(configuration.DB_TABLE_PREFIX+"SMPL"):]))
|
||||
sizes.sort()
|
||||
#print sizes
|
||||
#try query on all the sample sizes in increasing order until we get one that meets the threshold
|
||||
for size in sizes:
|
||||
tblname = configuration.DB_TABLE_PREFIX+"SMPL"+str(size)
|
||||
nquery = query.replace("GAMES",tblname)
|
||||
curs.execute(nquery)
|
||||
results = curs.fetchall()
|
||||
length = evaluator(results)
|
||||
if length > threshold:
|
||||
log.debug("query took " + str(time.time()-s_time) + " seconds")
|
||||
return results
|
||||
log.debug("too few results from sample tables, using entire table")
|
||||
curs.execute(query)
|
||||
log.debug("query took " + str(time.time()-s_time) + " seconds")
|
||||
return curs.fetchall()
|
||||
|
||||
def fconstruct(filters,colname,list):
|
||||
if list[0] == "all":
|
||||
return filters
|
||||
newfilter = colname+" IN ("
|
||||
for i in range(0,len(list)):
|
||||
newfilter += "'" + list[i] + "'"
|
||||
if i != len(list) - 1:
|
||||
newfilter += ','
|
||||
newfilter += ')'
|
||||
if len(filters) != 0:
|
||||
filters += " AND "
|
||||
else:
|
||||
filters += " WHERE "
|
||||
filters += newfilter
|
||||
return filters
|
||||
|
||||
def dateconstruct(filters,start_date,end_date):
|
||||
if len(filters) != 0:
|
||||
filters += " AND "
|
||||
else:
|
||||
filters += " WHERE "
|
||||
filters += "timestamp BETWEEN '"+start_date+"' AND '"+end_date+"'"
|
||||
return filters
|
||||
|
||||
def listfix(l):
|
||||
if not isinstance(l,types.ListType):
|
||||
return [l]
|
||||
return l
|
||||
|
||||
class RootController(BaseController):
|
||||
@expose(template="wesstats.templates.index")
|
||||
def index(self):
|
||||
|
@ -166,179 +93,6 @@ class RootController(BaseController):
|
|||
|
||||
return view, remainder
|
||||
|
||||
class PieGraphController(object):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
||||
@expose(template="wesstats.templates.pieview")
|
||||
def default(self,**kw):
|
||||
#pull data on this view from DB
|
||||
conn = MySQLdb.connect(configuration.DB_HOSTNAME,configuration.DB_USERNAME,configuration.DB_PASSWORD,configuration.DB_NAME,use_unicode=True)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("SELECT title,xdata,ydata,xlabel,ylabel,filters,y_xform FROM _wsviews WHERE url = %s", (self.url,))
|
||||
view_data = curs.fetchall()[0]
|
||||
log.debug("pie chart request, here is SQL data for this view:")
|
||||
log.debug(view_data)
|
||||
#fetch the relevant filters for this template and their possible values
|
||||
available_filters = view_data[5].split(',')
|
||||
fdata = dict()
|
||||
for filter in available_filters:
|
||||
curs.execute("SELECT DISTINCT "+filter+" FROM GAMES")
|
||||
#curs.fetchall() returns a list of lists, we convert this to a plain list for ease of handling
|
||||
raw_fdata = curs.fetchall()
|
||||
fdata[filter] = []
|
||||
for i in raw_fdata:
|
||||
fdata[filter].append(i[0])
|
||||
#print fdata
|
||||
filters = ""
|
||||
used_filters = intersect(kw.keys(),available_filters)
|
||||
ufilters_vals = dict()
|
||||
for filter in used_filters:
|
||||
kw[filter] = listfix(kw[filter])
|
||||
filter_vals = intersect(kw[filter],fdata[filter])
|
||||
filters = fconstruct(filters,filter,filter_vals)
|
||||
ufilters_vals[filter] = filter_vals
|
||||
if 'startdate' in kw and 'enddate' in kw and isvalid(kw['startdate']) and isvalid(kw['enddate']):
|
||||
filters = dateconstruct(filters,kw['startdate'],kw['enddate'])
|
||||
used_filters.append("dates")
|
||||
ufilters_vals["dates"] = [kw['startdate'] + "-" + kw['enddate']]
|
||||
#get columns and column transformations for this view
|
||||
y_xforms = view_data[6].split(',')
|
||||
y_data = view_data[2].split(',')
|
||||
y_data_str = ""
|
||||
#they must be equal!
|
||||
assert len(y_data) == len(y_xforms)
|
||||
for i in range(len(y_data)):
|
||||
y_data_str += y_xforms[i] + "(" + y_data[i] + "),"
|
||||
y_data_str = y_data_str[0:len(y_data_str)-1]
|
||||
query = "SELECT "+view_data[1]+","+y_data_str+" FROM GAMES "+filters+" GROUP BY "+view_data[1]
|
||||
log.debug("SQL query:")
|
||||
log.debug(query)
|
||||
results = scaled_query(curs,query,100,evaluators.count_eval)
|
||||
log.debug("query result:")
|
||||
log.debug(results)
|
||||
#generate JS datafields here because genshi templating can't emit JS...
|
||||
data = ""
|
||||
for i in range(0,len(results)):
|
||||
data += "data.setValue("+str(i)+",0,'"+results[i][0]+"');\n"
|
||||
data += "data.setValue("+str(i)+",1,"+str(results[i][1])+");\n"
|
||||
return dict(title=view_data[0],xlabel=view_data[3],ylabel=view_data[4],piedata=results,
|
||||
data=data,filters=available_filters,used_filters=used_filters,
|
||||
ufilters_vals=ufilters_vals,fdata=fdata)
|
||||
|
||||
class BarGraphController(object):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
||||
@expose(template="wesstats.templates.barview")
|
||||
def default(self,**kw):
|
||||
#pull data on this view from DB
|
||||
conn = MySQLdb.connect(configuration.DB_HOSTNAME,configuration.DB_USERNAME,configuration.DB_PASSWORD,configuration.DB_NAME,use_unicode=True)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("SELECT title,xdata,ydata,xlabel,ylabel,filters,y_xform FROM _wsviews WHERE url = %s", (self.url,))
|
||||
view_data = curs.fetchall()[0]
|
||||
print view_data
|
||||
#fetch the relevant filters for this template and their possible values
|
||||
available_filters = view_data[5].split(',')
|
||||
fdata = dict()
|
||||
for filter in available_filters:
|
||||
curs.execute("SELECT DISTINCT "+filter+" FROM GAMES")
|
||||
#curs.fetchall() returns a list of lists, we convert this to a plain list for ease of handling
|
||||
raw_fdata = curs.fetchall()
|
||||
fdata[filter] = []
|
||||
for i in raw_fdata:
|
||||
fdata[filter].append(i[0])
|
||||
#print fdata
|
||||
filters = ""
|
||||
for filter in available_filters:
|
||||
print filter
|
||||
print kw
|
||||
used_filters = intersect(kw.keys(),available_filters)
|
||||
ufilters_vals = dict()
|
||||
for filter in used_filters:
|
||||
kw[filter] = listfix(kw[filter])
|
||||
filter_vals = intersect(kw[filter],fdata[filter])
|
||||
print filter_vals
|
||||
filters = fconstruct(filters,filter,filter_vals)
|
||||
ufilters_vals[filter] = filter_vals
|
||||
#get columns and column transformations for this view
|
||||
y_xforms = view_data[6].split(',')
|
||||
y_data = view_data[2].split(',')
|
||||
y_data_str = ""
|
||||
#they must be equal!
|
||||
assert len(y_data) == len(y_xforms)
|
||||
for i in range(len(y_data)):
|
||||
y_data_str += y_xforms[i] + "(" + y_data[i] + "),"
|
||||
y_data_str = y_data_str[0:len(y_data_str)-1]
|
||||
query = "SELECT "+view_data[1]+","+y_data_str+" FROM GAMES "+filters+" GROUP BY "+view_data[1]
|
||||
print query
|
||||
results = scaled_query(curs,query,100,evaluators.count_eval)
|
||||
print results
|
||||
#generate JS datafields here because genshi templating can't emit JS...
|
||||
data = ""
|
||||
for i in range(0,len(results)):
|
||||
data += "data.setValue("+str(i)+",0,'"+results[i][0]+"');\n"
|
||||
data += "data.setValue("+str(i)+",1,"+str(results[i][1])+");\n"
|
||||
return dict(title=view_data[0],xlabel=view_data[3],ylabel=view_data[4],piedata=results,
|
||||
data=data,filters=available_filters,used_filters=used_filters,
|
||||
ufilters_vals=ufilters_vals,fdata=fdata)
|
||||
|
||||
class LineGraphController(object):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
||||
@expose(template="wesstats.templates.lineview")
|
||||
def default(self,**kw):
|
||||
#pull data on this view from DB
|
||||
conn = MySQLdb.connect(configuration.DB_HOSTNAME,configuration.DB_USERNAME,configuration.DB_PASSWORD,configuration.DB_NAME,use_unicode=True)
|
||||
curs = conn.cursor()
|
||||
|
||||
curs.execute("SELECT title,xdata,ydata,xlabel,ylabel,filters,y_xform FROM _wsviews WHERE url = %s", (self.url,))
|
||||
view_data = curs.fetchall()[0]
|
||||
print view_data
|
||||
#fetch the relevant filters for this template and their possible values
|
||||
available_filters = view_data[5].split(',')
|
||||
fdata = dict()
|
||||
for filter in available_filters:
|
||||
curs.execute("SELECT DISTINCT "+filter+" FROM GAMES")
|
||||
#curs.fetchall() returns a list of lists, we convert this to a plain list for ease of handling
|
||||
raw_fdata = curs.fetchall()
|
||||
fdata[filter] = []
|
||||
for i in raw_fdata:
|
||||
fdata[filter].append(i[0])
|
||||
#print fdata
|
||||
filters = ""
|
||||
used_filters = intersect(kw.keys(),available_filters)
|
||||
ufilters_vals = dict()
|
||||
for filter in used_filters:
|
||||
kw[filter] = listfix(kw[filter])
|
||||
filter_vals = intersect(kw[filter],fdata[filter])
|
||||
filters = fconstruct(filters,filter,filter_vals)
|
||||
ufilters_vals[filter] = filter_vals
|
||||
#get columns and column transformations for this view
|
||||
y_xforms = view_data[6].split(',')
|
||||
y_data = view_data[2].split(',')
|
||||
y_data_str = ""
|
||||
#they must be equal!
|
||||
assert len(y_data) == len(y_xforms)
|
||||
for i in range(len(y_data)):
|
||||
y_data_str += y_xforms[i] + "(" + y_data[i] + "),"
|
||||
y_data_str = y_data_str[0:len(y_data_str)-1]
|
||||
query = "SELECT "+view_data[1]+","+y_data_str+" FROM GAMES "+filters+" GROUP BY "+view_data[1]
|
||||
print query
|
||||
results = scaled_query(curs,query,100,evaluators.count_eval)
|
||||
print results
|
||||
#generate JS datafields here because genshi templating can't emit JS...
|
||||
data = ""
|
||||
for i in range(0,len(results)):
|
||||
data += "data.setValue("+str(i)+",0,'"+results[i][0]+"');\n"
|
||||
data += "data.setValue("+str(i)+",1,"+str(results[i][1])+");\n"
|
||||
return dict(title=view_data[0],xlabel=view_data[3],ylabel=view_data[4],piedata=results,
|
||||
data=data,filters=available_filters,used_filters=used_filters,
|
||||
ufilters_vals=ufilters_vals,fdata=fdata)
|
||||
|
||||
class NotFoundController(object):
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
<div id="visualization" style="width: 300px; height: 300px;">
|
||||
</div>
|
||||
<div id="filter_box">
|
||||
Used filters
|
||||
Used filters:
|
||||
<b py:if="len(used_filters) == 0">None</b>
|
||||
<table border="1">
|
||||
<tr py:for="filter in used_filters">
|
||||
<td>${filter}</td>
|
||||
|
|
Loading…
Add table
Reference in a new issue