196 lines
7.4 KiB
Python
196 lines
7.4 KiB
Python
from flask import Flask, abort, request, render_template, url_for
|
|
import math
|
|
import MySQLdb
|
|
import MySQLdb.cursors
|
|
import datetime as dt
|
|
app = Flask(__name__)
|
|
|
|
PAGE_SIZE=20
|
|
# TODO: Search
|
|
|
|
def now():
|
|
# TODO: If it's January and no races have been run this year, return last year
|
|
return dt.datetime.now()
|
|
|
|
@app.route('/')
|
|
@app.route('/list')
|
|
@app.route('/list/<title>') # title = { races, rankings, runners, licence }
|
|
@app.route('/list/<title>/<int:year>')
|
|
def list(title=None, year=None):
|
|
''' Set defaults for the index page '''
|
|
if year is None and title is None:
|
|
year = now().year
|
|
title = 'runners'
|
|
if title not in ( 'races', 'rankings', 'runners', 'licence', ):
|
|
abort(404)
|
|
start = int(request.args.get('start', '0'))
|
|
limit = int(request.args.get('limit', PAGE_SIZE))
|
|
results = read_db(start, limit, listing=title, year=year)
|
|
return render_template('list-'+title+'.html', ltype='listing', title=title, year=year,
|
|
results=results, start=start, limit=limit,
|
|
request=request, now=now(), PAGE_SIZE=PAGE_SIZE)
|
|
@app.route('/all')
|
|
@app.route('/all/<int:year>')
|
|
@app.route('/all/<int:year>/<title>') # this does nothing, and is simply here to prevent title from being added to the query string
|
|
def index(title=None, year=None):
|
|
start = int(request.args.get('start', '0'))
|
|
limit = int(request.args.get('limit', PAGE_SIZE))
|
|
results = read_db(start, limit, year=year)
|
|
return render_template('index.html', ltype='index', year=year,
|
|
results=results, start=start, limit=limit,
|
|
request=request, now=now(), PAGE_SIZE=PAGE_SIZE)
|
|
|
|
|
|
@app.route('/race/<int:year>/<title>')
|
|
def race(year=None, title=None):
|
|
start = int(request.args.get('start', '0'))
|
|
limit = int(request.args.get('limit', PAGE_SIZE))
|
|
results = read_db(start, limit, event=title, year=year)
|
|
return render_template('index.html', ltype='race', title=title, year=year,
|
|
results=results, start=start, limit=limit,
|
|
request=request, now=now(), PAGE_SIZE=PAGE_SIZE)
|
|
|
|
@app.route('/person/<title>')
|
|
@app.route('/person/<title>/<int:year>')
|
|
def person(title=None, year=None):
|
|
start = int(request.args.get('start', '0'))
|
|
limit = int(request.args.get('limit', PAGE_SIZE))
|
|
results = read_db(start, limit, person=title, year=year)
|
|
return render_template('index.html', ltype='person', title=title, year=year,
|
|
results=results, start=start, limit=limit,
|
|
request=request, now=now(), PAGE_SIZE=PAGE_SIZE)
|
|
|
|
@app.route('/licence/<int:year>')
|
|
@app.route('/licence/<int:year>/<title>')
|
|
def licence(year=now().year, title=None):
|
|
start = int(request.args.get('start', '0'))
|
|
limit = int(request.args.get('limit', PAGE_SIZE))
|
|
results = read_db(start, limit, licence=title, year=year)
|
|
return render_template('index.html', ltype='licence', title=title, year=year,
|
|
results=results, start=start, limit=limit,
|
|
request=request, now=now(), PAGE_SIZE=PAGE_SIZE)
|
|
|
|
|
|
def read_db(start=0, limit=PAGE_SIZE, listing=None, event=None, person=None, licence=None, year=None):
|
|
db = MySQLdb.connect(user = 'aac', passwd = 'saOAcCWHg4LaoSSA', db = 'AAC', cursorclass = MySQLdb.cursors.DictCursor)
|
|
c = db.cursor()
|
|
|
|
count = 0
|
|
|
|
select = '*'
|
|
where = 'WHERE club LIKE "AAC"'
|
|
group = ''
|
|
order = 'date DESC, event, position'
|
|
close = ''
|
|
if event:
|
|
where += ' AND event LIKE "{}"'.format(event)
|
|
if person:
|
|
where += ' AND CONCAT_WS(" ", name, surname) LIKE "{}"'.format(person)
|
|
if licence:
|
|
where += ' AND licence LIKE "{}"'.format(licence)
|
|
if year:
|
|
firstdate = dt.datetime.min
|
|
lastdate = dt.datetime.max
|
|
firstdate = firstdate.replace(year=int(year))
|
|
lastdate = lastdate.replace(year=int(year))
|
|
where += ' AND date > "{}" AND date < "{}"'.format(firstdate, lastdate)
|
|
|
|
if listing:
|
|
if listing == 'races':
|
|
select = 'event, date'
|
|
group = 'GROUP BY event'
|
|
elif listing == 'runners':
|
|
select = 'CONCAT_WS(" ", name, surname) person, FORMAT(SUM(distance),0) total'
|
|
where += ' AND CONCAT_WS(" ", name, surname) NOT LIKE "%NO RETURN%"'
|
|
where += ' AND CONCAT_WS(" ", name, surname) NOT LIKE "%BLANK CARD%"'
|
|
group = 'GROUP BY CONCAT_WS(" ", name, surname)'
|
|
order = 'SUM(distance) DESC, surname'
|
|
elif listing == 'rankings':
|
|
select = 'CONCAT_WS(" ", name, surname) person, SUM(position) positions, COUNT(event) races, SUM(position)/COUNT(event) podiums, FORMAT(SUM(position)/COUNT(event),1) score'
|
|
group = 'GROUP BY CONCAT_WS(" ", name, surname)'
|
|
order = 'podiums, races DESC'
|
|
elif listing == 'licence':
|
|
select = 'licence, date, CONCAT_WS(" ", name, surname) person'
|
|
group = 'GROUP BY licence'
|
|
order = 'surname, date DESC'
|
|
|
|
sql = 'SELECT {} FROM `results` {} {} ORDER BY {} LIMIT {},{} {};'.format(select, where, group, order, start, limit, close)
|
|
#app.logger.debug(sql)
|
|
c.execute(sql)
|
|
queryresults = c.fetchall()
|
|
|
|
select = 'COUNT(*)'
|
|
if listing:
|
|
if listing == 'races':
|
|
select = 'COUNT(*) FROM ( SELECT COUNT(event)'
|
|
close = ') races'
|
|
elif listing == 'runners':
|
|
select = 'COUNT(*) FROM ( SELECT COUNT(name)'
|
|
group = 'GROUP BY CONCAT_WS(" ", name, surname)'
|
|
close = ') runners'
|
|
elif listing == 'rankings':
|
|
select = 'COUNT(*) FROM ( SELECT COUNT(name)'
|
|
group = 'GROUP BY CONCAT_WS(" ", name, surname)'
|
|
close = ') rankings'
|
|
elif listing == 'licence':
|
|
pass
|
|
|
|
sql = 'SELECT {} FROM `results` {} {} {};'.format(select, where, group, close)
|
|
#app.logger.debug(sql)
|
|
c.execute(sql)
|
|
countresult = c.fetchone()
|
|
for x in countresult.keys():
|
|
count = countresult[x]
|
|
app.logger.debug(count)
|
|
|
|
return { 'count': int(count), 'rows': queryresults }
|
|
|
|
|
|
@app.template_filter('pace')
|
|
def pace(time):
|
|
return (dt.datetime(1,1,1) + time).strftime('%M:%S')
|
|
|
|
@app.template_filter('year')
|
|
def year(time):
|
|
return time.strftime('%Y')
|
|
|
|
@app.template_filter('cleandate')
|
|
def clean_date(time):
|
|
if time.month == 1 and time.day == 1:
|
|
return time.strftime('%Y')
|
|
return time.strftime('%Y-%m-%d')
|
|
|
|
@app.template_filter('ordinal')
|
|
def ordinal(n):
|
|
return "%d%s" % (n,"tsnrhtdd"[(math.floor(n/10)%10!=1)*(n%10<4)*n%10::4])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=True)
|
|
|
|
|
|
# most race KMs in the year, by distance
|
|
# fastest race pace over the year (time / KMs)
|
|
# individual KMs, and race results (race, position, time) by name
|
|
# - and by race number and year
|
|
# by race
|
|
# - and by gender
|
|
|
|
# tabs:
|
|
# list of races (sorted by recent)
|
|
# list of people (sorted by total kms for the year)
|
|
# list of licences for the year (sorted by number of races)
|
|
# list of podiums/rankings (people sorted by total_position/total_races)
|
|
# click to expand by
|
|
# person (races by recent)
|
|
# person (races by pace)]
|
|
# race (all AAC members by position)
|
|
# SEARCH
|
|
|
|
# /?sort={distance,pace}&sex={m,f}
|
|
# /race/2018/HEWAT ETC?sort={position,pace}&sex={m,f}
|
|
# /person/Timothy Allen?sort={pace,date}
|
|
# /person/Timothy Allen/2018
|
|
# /license/2018/4356
|
|
# /license/2018/4356
|