377 lines
17 KiB
Python
377 lines
17 KiB
Python
# encoding=utf-8
|
|
import pymysql
|
|
import os
|
|
import json
|
|
import hashlib, uuid
|
|
import datetime
|
|
from datetime import datetime
|
|
|
|
from app import app, randomUrlSuffix
|
|
from flask import Flask, flash, render_template, request, redirect, url_for, jsonify
|
|
from flask_wtf import FlaskForm
|
|
from flask_bootstrap import Bootstrap
|
|
from flask_basicauth import BasicAuth
|
|
from wtforms import StringField, PasswordField, BooleanField
|
|
from wtforms import DateField
|
|
from wtforms.validators import InputRequired, Email, Length
|
|
from forms import motmForm, adminSettingsForm2, goalsAssistsForm
|
|
from db_config import sql_write, sql_write_static, sql_read, sql_read_static
|
|
from tables import matchSquadTable
|
|
from readSettings import mySettings
|
|
|
|
app.config['BASIC_AUTH_USERNAME'] = 'admin'
|
|
app.config['BASIC_AUTH_PASSWORD'] = 'letmein'
|
|
basic_auth = BasicAuth(app)
|
|
|
|
|
|
@app.route('/')
|
|
def index():
|
|
"""Main index page for MOTM system"""
|
|
return render_template('index.html')
|
|
|
|
|
|
# ==================== PUBLIC VOTING SECTION ====================
|
|
|
|
@app.route('/motm/<randomUrlSuffix>')
|
|
def motm_vote(randomUrlSuffix):
|
|
"""Public voting page for Man of the Match and Dick of the Day"""
|
|
sql = "SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _hkfcD_matchSquad ORDER BY RAND()"
|
|
sql2 = "SELECT nextClub, nextTeam, nextDate, oppoLogo, hkfcLogo, currMotM, currDotD, nextFixture FROM hkfcDAdminSettings"
|
|
rows = sql_read(sql)
|
|
nextInfo = sql_read_static(sql2)
|
|
nextClub = nextInfo[0]['nextClub']
|
|
nextTeam = nextInfo[0]['nextTeam']
|
|
nextFixture = nextInfo[0]['nextFixture']
|
|
hkfcLogo = nextInfo[0]['hkfcLogo']
|
|
oppoLogo = nextInfo[0]['oppoLogo']
|
|
currMotM = nextInfo[0]['currMotM']
|
|
currDotD = nextInfo[0]['currDotD']
|
|
oppo = nextTeam
|
|
sql3 = "SELECT hockeyResults2021.hockeyFixtures.date, hockeyResults.hkfcDAdminSettings.nextFixture FROM hockeyResults2021.hockeyFixtures INNER JOIN hockeyResults.hkfcDAdminSettings ON hockeyResults2021.hockeyFixtures.fixtureNumber = hockeyResults.hkfcDAdminSettings.nextFixture"
|
|
nextMatchDate = sql_read(sql3)
|
|
nextDate = nextMatchDate[0]['date']
|
|
formatDate = datetime.strftime(nextDate, '%A, %d %B %Y')
|
|
|
|
sql3 = "SELECT playerPictureURL FROM _HKFC_players INNER JOIN hockeyResults.hkfcDAdminSettings ON _HKFC_players.playerNumber=hockeyResults.hkfcDAdminSettings.currMotM"
|
|
sql4 = "SELECT playerPictureURL FROM _HKFC_players INNER JOIN hockeyResults.hkfcDAdminSettings ON _HKFC_players.playerNumber=hockeyResults.hkfcDAdminSettings.currDotD"
|
|
motm = sql_read(sql3)
|
|
dotd = sql_read(sql4)
|
|
motmURL = motm[0]['playerPictureURL']
|
|
dotdURL = dotd[0]['playerPictureURL']
|
|
|
|
sql5 = "SELECT comment FROM _motmComments INNER JOIN hockeyResults.hkfcDAdminSettings ON _motmComments.matchDate=hockeyResults.hkfcDAdminSettings.nextDate ORDER BY RAND() LIMIT 1"
|
|
comment = sql_read(sql5)
|
|
if comment == "":
|
|
comment = "No comments added yet"
|
|
form = motmForm()
|
|
sql6 = "SELECT motmUrlSuffix FROM hockeyResults.hkfcDAdminSettings WHERE userid='admin'"
|
|
urlSuff = sql_read_static(sql6)
|
|
randomSuff = urlSuff[0]['motmUrlSuffix']
|
|
print(randomSuff)
|
|
if randomSuff == randomUrlSuffix:
|
|
return render_template('motm_vote.html', data=rows, comment=comment, formatDate=formatDate, matchNumber=nextFixture, oppo=oppo, hkfcLogo=hkfcLogo, oppoLogo=oppoLogo, dotdURL=dotdURL, motmURL=motmURL, form=form)
|
|
else:
|
|
return render_template('error.html')
|
|
|
|
|
|
@app.route('/motm/comments', methods=['GET', 'POST'])
|
|
def match_comments():
|
|
"""Display and allow adding match comments"""
|
|
sql = "SELECT nextClub, nextTeam, nextDate, oppoLogo, hkfcLogo FROM hkfcDAdminSettings"
|
|
row = sql_read_static(sql)
|
|
_oppo = row[0]['nextClub']
|
|
commentDate = row[0]['nextDate'].strftime('%Y-%m-%d')
|
|
_matchDate = row[0]['nextDate'].strftime('%Y_%m_%d')
|
|
hkfcLogo = row[0]['hkfcLogo']
|
|
oppoLogo = row[0]['oppoLogo']
|
|
if request.method == 'POST':
|
|
_comment = request.form['matchComment']
|
|
if _comment != 'Optional comments added here':
|
|
_fixed_comment = _comment.replace("'", "\\'")
|
|
sql3 = "INSERT INTO _motmComments (matchDate, opposition, comment) VALUES ('" + commentDate + "', '" + _oppo + "', '" + _fixed_comment + "')"
|
|
sql_write(sql3)
|
|
sql = "SELECT comment FROM _motmComments WHERE matchDate='" + _matchDate + "' ORDER BY RAND()"
|
|
comments = sql_read(sql)
|
|
return render_template('match_comments.html', comments=comments, hkfcLogo=hkfcLogo, oppoLogo=oppoLogo)
|
|
|
|
|
|
@app.route('/motm/vote-thanks', methods=['POST'])
|
|
def vote_thanks():
|
|
"""Process MOTM/DotD votes and comments"""
|
|
try:
|
|
_motm = request.form['motmVote']
|
|
_dotd = request.form['dotdVote']
|
|
_comments = request.form['motmComment']
|
|
_fixed_comments = _comments.replace("'", "\\'")
|
|
_matchDate = request.form['matchNumber']
|
|
_oppo = request.form['oppo']
|
|
|
|
if _motm and _dotd and request.method == 'POST':
|
|
sql = "INSERT INTO _hkfc_d_motm (playerNumber, playerName, motmTotal, motm_" + _matchDate + ") SELECT playerNumber, playerNickname, '1', '1' FROM _HKFC_players WHERE playerNumber='" + _motm + "' ON DUPLICATE KEY UPDATE motmTotal = motmTotal + 1, motm_" + _matchDate + " = motm_" + _matchDate + " + 1"
|
|
sql2 = "INSERT INTO _hkfc_d_motm (playerNumber, playerName, dotdTotal, dotd_" + _matchDate + ") SELECT playerNumber, playerNickname, '1', '1' FROM _HKFC_players WHERE playerNumber='" + _dotd + "' ON DUPLICATE KEY UPDATE dotdTotal = dotdTotal + 1, dotd_" + _matchDate + " = dotd_" + _matchDate + " + 1"
|
|
if _comments == "":
|
|
print("No comment")
|
|
elif _comments == "Optional comments added here":
|
|
print("No comment")
|
|
else:
|
|
sql3 = "INSERT INTO _motmComments (_matchDate, opposition, comment) VALUES ('" + _matchDate + "', '" + _oppo + "', '" + _fixed_comments + "')"
|
|
sql_write(sql3)
|
|
sql_write(sql)
|
|
sql_write(sql2)
|
|
return render_template('vote_thanks.html')
|
|
else:
|
|
return 'Ouch ... something went wrong here'
|
|
except Exception as e:
|
|
print(e)
|
|
finally:
|
|
print('Votes cast')
|
|
|
|
|
|
# ==================== ADMIN SECTION ====================
|
|
|
|
@app.route('/admin/motm', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def motm_admin():
|
|
"""Admin page for managing MOTM settings"""
|
|
form = adminSettingsForm2()
|
|
prevFixture = mySettings('prevFixture')
|
|
if prevFixture is None:
|
|
prevFixture = '1'
|
|
else:
|
|
prevFixture = str(prevFixture)
|
|
if request.method == 'POST':
|
|
if form.saveButton.data:
|
|
print('Saved')
|
|
else:
|
|
print('Activated')
|
|
_nextTeam = request.form['nextOppoTeam']
|
|
_nextFixture = request.form['nextMatch']
|
|
_currMotM = request.form['currMotM']
|
|
_currDotD = request.form['currDotD']
|
|
sql1 = "SELECT club FROM _clubTeams WHERE displayName='" + _nextTeam + "'"
|
|
_nextClubName = sql_read_static(sql1)
|
|
_nextClub = _nextClubName[0]['club']
|
|
sql = "UPDATE hkfcDAdminSettings SET nextFixture='" + _nextFixture + "', nextClub='" + _nextClub + "', nextTeam='" + _nextTeam + "', currMotM=" + _currMotM + ", currDotD=" + _currDotD + ""
|
|
sql_write_static(sql)
|
|
sql2 = "UPDATE hkfcDAdminSettings INNER JOIN mensHockeyClubs ON hkfcDAdminSettings.nextClub = mensHockeyClubs.hockeyClub SET hkfcDAdminSettings.oppoLogo = mensHockeyClubs.logoURL WHERE mensHockeyClubs.hockeyClub='" + _nextClub + "'"
|
|
sql_write_static(sql2)
|
|
if form.saveButton.data:
|
|
flash('Settings saved!')
|
|
urlSuffix = randomUrlSuffix(8)
|
|
print(urlSuffix)
|
|
sql3 = "UPDATE hkfcDAdminSettings SET motmUrlSuffix='" + urlSuffix + "' WHERE userid='admin'"
|
|
sql_write_static(sql3)
|
|
flash('MotM URL https://hockey.ervine.cloud/motm/'+urlSuffix)
|
|
elif form.activateButton.data:
|
|
sql4 = "ALTER TABLE _hkfc_d_motm ADD COLUMN motm_" + _nextFixture + " smallint DEFAULT 0, ADD COLUMN dotd_" + _nextFixture + " smallint DEFAULT 0, ADD COLUMN assists_" + _nextFixture + " smallint DEFAULT 0, ADD COLUMN goals_" + _nextFixture + " smallint DEFAULT 0 "
|
|
sql_write(sql4)
|
|
sql5 = "SELECT motmUrlSuffix FROM hkfcDAdminSettings WHERE userid='admin'"
|
|
tempSuffix = sql_read_static(sql5)
|
|
currSuffix = tempSuffix[0]['motmUrlSuffix']
|
|
print(currSuffix)
|
|
flash('Man of the Match vote is now activated')
|
|
flash('MotM URL https://hockey.ervine.cloud/motm/'+currSuffix)
|
|
else:
|
|
flash('Something went wrong - check with Smithers')
|
|
|
|
sql7 = "SELECT date, homeTeam, awayTeam, venue, fixtureNumber FROM hockeyFixtures WHERE homeTeam='HKFC D' OR awayTeam='HKFC D'"
|
|
matches = sql_read(sql7)
|
|
form.nextMatch.choices = [(match['fixtureNumber'], match['date']) for match in matches]
|
|
sql4 = "SELECT hockeyClub FROM mensHockeyClubs ORDER BY hockeyClub"
|
|
sql5 = "SELECT nextClub, oppoLogo FROM hkfcDAdminSettings"
|
|
sql6 = "SELECT playerNumber, playerForenames, playerSurname FROM _hkfcD_matchSquad_" + prevFixture + " ORDER BY playerForenames"
|
|
clubs = sql_read_static(sql4)
|
|
settings = sql_read_static(sql5)
|
|
players = sql_read(sql6)
|
|
form.nextOppoClub.choices = [(oppo['hockeyClub'], oppo['hockeyClub']) for oppo in clubs]
|
|
form.currMotM.choices = [(player['playerNumber'], player['playerForenames'] + " " + player['playerSurname']) for player in players]
|
|
form.currDotD.choices = [(player['playerNumber'], player['playerForenames'] + " " + player['playerSurname']) for player in players]
|
|
clubLogo = settings[0]['oppoLogo']
|
|
|
|
return render_template('motm_admin.html', form=form, nextOppoLogo=clubLogo)
|
|
|
|
|
|
@app.route('/admin/squad', methods=['GET'])
|
|
@basic_auth.required
|
|
def match_squad():
|
|
"""Admin page for managing match squad"""
|
|
sql1 = "SELECT team from _clubTeams WHERE club='HKFC' ORDER BY team"
|
|
sql2 = "SELECT playerTeam, playerForenames, playerSurname, playerNickname, playerNumber FROM _HKFC_players"
|
|
teams = sql_read(sql1)
|
|
players = sql_read(sql2)
|
|
return render_template('match_squad.html', teams=teams, players=players)
|
|
|
|
|
|
@app.route('/admin/squad/submit', methods=['POST'])
|
|
@basic_auth.required
|
|
def match_squad_submit():
|
|
"""Process squad selection"""
|
|
_playerNumbers = request.form.getlist('playerNumber')
|
|
for _playerNumber in _playerNumbers:
|
|
sql = "INSERT INTO _hkfcD_matchSquad (playerNumber, playerForenames, playerSurname, playerNickname) SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _HKFC_players WHERE playerNumber='" + _playerNumber + "'"
|
|
sql_write(sql)
|
|
sql2 = "SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _hkfcD_matchSquad"
|
|
players = sql_read(sql2)
|
|
table = matchSquadTable(players)
|
|
table.border = True
|
|
table.classes = ['table-striped', 'table-condensed', 'table-hover']
|
|
return render_template('match_squad_selected.html', table=table)
|
|
|
|
|
|
@app.route('/admin/squad/list')
|
|
@basic_auth.required
|
|
def match_squad_list():
|
|
"""Display current squad list"""
|
|
sql = "SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _hkfcD_matchSquad"
|
|
players = sql_read(sql)
|
|
table = matchSquadTable(players)
|
|
table.border = True
|
|
table.classes = ['table-striped', 'table-condensed', 'table-hover']
|
|
return render_template('match_squad_selected.html', table=table)
|
|
|
|
|
|
@app.route('/admin/squad/remove', methods=['POST'])
|
|
@basic_auth.required
|
|
def delPlayerFromSquad():
|
|
"""Remove player from squad"""
|
|
_playerNumber = request.args['playerNumber']
|
|
sql = "DELETE FROM _hkfcD_matchSquad WHERE playerNumber=" + _playerNumber + ""
|
|
sql_write(sql)
|
|
return render_template('player_removed.html', number=_playerNumber)
|
|
|
|
|
|
@app.route('/admin/squad/reset')
|
|
@basic_auth.required
|
|
def matchSquadReset():
|
|
"""Reset squad for new match"""
|
|
_matchNumber = str(mySettings('fixture'))
|
|
print(_matchNumber)
|
|
sql1 = "RENAME TABLE _hkfcD_matchSquad TO _hkfcD_matchSquad_" + _matchNumber + ""
|
|
sql2 = "CREATE TABLE _hkfcD_matchSquad (playerNumber smallint UNIQUE, playerForenames varchar(50), playerSurname varchar(30), playerNickname varchar(30) NOT NULL, PRIMARY KEY (playerNumber))"
|
|
sql3 = "UPDATE hkfcDAdminSettings SET prevFixture='" + _matchNumber + "'"
|
|
sql_write(sql1)
|
|
sql_write(sql2)
|
|
sql_write_static(sql3)
|
|
return render_template('match_squad_reset.html')
|
|
|
|
|
|
@app.route('/admin/stats', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def stats_admin():
|
|
"""Admin page for managing goals and assists statistics"""
|
|
form = goalsAssistsForm()
|
|
sql = "SELECT date, homeTeam, awayTeam, venue, fixtureNumber FROM hockeyFixtures WHERE homeTeam='HKFC D' OR awayTeam='HKFC D'"
|
|
matches = sql_read(sql)
|
|
form.match.choices = [(match['fixtureNumber'], match['date']) for match in matches]
|
|
sql2 = "SELECT playerNumber, playerNickname FROM _hkfcD_matchSquad"
|
|
players = sql_read(sql2)
|
|
return render_template('goals_assists_admin.html', data=players, form=form)
|
|
|
|
|
|
@app.route('/admin/stats/submit', methods=['POST'])
|
|
@basic_auth.required
|
|
def goalsAssistsSubmit():
|
|
"""Process goals and assists statistics"""
|
|
try:
|
|
data = request.form
|
|
playerName = request.form.getlist('playerName')
|
|
playerNumber = request.form.getlist('playerNumber')
|
|
assists = request.form.getlist('assists')
|
|
goals = request.form.getlist('goals')
|
|
match = request.form['match']
|
|
for idx, player in enumerate(playerNumber):
|
|
sql = "INSERT INTO _hkfc_d_motm (playerNumber, playerName, assistsTotal, goalsTotal, assists_" + match + ", goals_" + match + ") SELECT playerNumber, playerNickname, '" + assists[idx] + "', '" + goals[idx] + "', '" + assists[idx] + "', '" + goals[idx] + "' FROM _HKFC_players WHERE playerNumber='" + player + "' ON DUPLICATE KEY UPDATE assistsTotal = assistsTotal + " + assists[idx] + ", goalsTotal = goalsTotal + " + goals[idx] + ", assists_" + match + " = " + assists[idx] + ", goals_" + match + " = " + goals[idx] + ""
|
|
sql_write(sql)
|
|
except Exception as e:
|
|
print(e)
|
|
finally:
|
|
return render_template('goals_thanks.html', data=data)
|
|
|
|
|
|
# ==================== API ENDPOINTS ====================
|
|
|
|
@app.route('/admin/api/team/<club>')
|
|
def admin_team_lookup(club):
|
|
"""API endpoint for team lookup by club"""
|
|
sql = "SELECT team FROM _clubTeams WHERE club='" + club + "'"
|
|
myteams = sql_read(sql)
|
|
return jsonify(myteams)
|
|
|
|
|
|
@app.route('/admin/api/logo/<club>')
|
|
def get_logo(club):
|
|
"""API endpoint for club logo lookup"""
|
|
sql = "SELECT logoURL FROM mensHockeyClubs WHERE hockeyClub='" + club + "'"
|
|
clubLogo = sql_read(sql)
|
|
return jsonify(clubLogo)
|
|
|
|
|
|
@app.route('/admin/api/fixture/<fixture>')
|
|
def admin_fixture_lookup(fixture):
|
|
"""API endpoint for fixture team lookup"""
|
|
sql = "SELECT homeTeam, awayTeam FROM hockeyFixtures WHERE fixtureNumber='" + fixture + "'"
|
|
myteams = sql_read(sql)
|
|
if myteams[0]['homeTeam'].startswith("HKFC"):
|
|
nextOppo = myteams[0]['awayTeam']
|
|
else:
|
|
nextOppo = myteams[0]['homeTeam']
|
|
return jsonify(nextOppo)
|
|
|
|
|
|
@app.route('/admin/api/fixture/<fixture>/logo')
|
|
def admin_fixture_logo_lookup(fixture):
|
|
"""API endpoint for fixture logo lookup"""
|
|
sql = "SELECT homeTeam, awayTeam FROM hockeyFixtures WHERE fixtureNumber='" + fixture + "'"
|
|
myteams = sql_read(sql)
|
|
if myteams[0]['homeTeam'].startswith("HKFC D"):
|
|
nextOppo = myteams[0]['awayTeam']
|
|
else:
|
|
nextOppo = myteams[0]['homeTeam']
|
|
sql2 = "SELECT club FROM _clubTeams WHERE displayName ='" + nextOppo + "'"
|
|
clubs = sql_read_static(sql2)
|
|
clubName = clubs[0]['club']
|
|
sql3 = "SELECT logoUrl FROM mensHockeyClubs WHERE hockeyClub ='" + clubName + "'"
|
|
logo = sql_read_static(sql3)
|
|
clubLogo = logo[0]['logoUrl']
|
|
return jsonify(clubLogo)
|
|
|
|
|
|
@app.route('/api/vote-results')
|
|
def vote_results():
|
|
"""API endpoint for voting results"""
|
|
_matchDate = str(mySettings('fixture'))
|
|
print(_matchDate)
|
|
sql = "SELECT playerName, motm_" + _matchDate + ", dotd_" + _matchDate + " FROM _hkfc_d_motm WHERE (motm_" + _matchDate + " > '0') OR (dotd_" + _matchDate + " > '0')"
|
|
print(sql)
|
|
rows = sql_read(sql)
|
|
print(rows)
|
|
return json.dumps(rows)
|
|
|
|
|
|
@app.route('/api/poty-results')
|
|
def poty_results():
|
|
"""API endpoint for Player of the Year results"""
|
|
sql = "SELECT playerName, motmTotal, dotdTotal FROM _hkfc_d_motm WHERE (motmTotal > '0') OR (dotdTotal > '0')"
|
|
print(sql)
|
|
rows = sql_read(sql)
|
|
return json.dumps(rows)
|
|
|
|
|
|
@app.route('/admin/voting')
|
|
@basic_auth.required
|
|
def voting_chart():
|
|
"""Admin page for viewing voting charts"""
|
|
matchDate = mySettings('fixture')
|
|
return render_template('vote_chart.html', _matchDate=matchDate)
|
|
|
|
|
|
@app.route('/admin/poty')
|
|
@basic_auth.required
|
|
def poty_chart():
|
|
"""Admin page for Player of the Year chart"""
|
|
return render_template('poty_chart.html')
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(host='0.0.0.0', port=5000, debug=True)
|