mirror of
https://github.com/FAUSheppy/open-web-leaderboard.git
synced 2025-12-07 07:31:36 +01:00
Compare commits
3 Commits
ese-custom
...
ese-custom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
159871be47 | ||
|
|
6e677c663b | ||
|
|
12c001ac71 |
@@ -1,63 +0,0 @@
|
||||
import json
|
||||
import datetime
|
||||
import player
|
||||
import datetime
|
||||
|
||||
class MapSummary:
|
||||
def __init__(self, rounds):
|
||||
'''Create a map MapSummary from a Round-Array'''
|
||||
|
||||
self.securityWins = 0
|
||||
self.insurgentWins = 0
|
||||
self.times = []
|
||||
self.predictions = []
|
||||
self.totalGames = 0
|
||||
self.confidence = []
|
||||
self.mapName = None
|
||||
|
||||
for r in rounds:
|
||||
self.mapName = r.mapName
|
||||
self.totalGames += 1
|
||||
if r.winnerSideString == "Insurgent":
|
||||
self.insurgentWins += 1
|
||||
else:
|
||||
self.securityWins += 1
|
||||
|
||||
self.predictions += [r.numericPrediction]
|
||||
self.confidence += [r.confidence]
|
||||
self.times += [r.duration]
|
||||
|
||||
self.insurgentWinPercent = ""
|
||||
self.securityWinPercent = ""
|
||||
self.ratingSystemDeviation = "-"
|
||||
self.averageTime = ""
|
||||
|
||||
try:
|
||||
self.insurgentWinPercent = self.insurgentWins / self.totalGames*100
|
||||
self.securityWinPercent = self.securityWins / self.totalGames*100
|
||||
averageSeconds = sum([t.total_seconds() for t in self.times]) / len(self.times)
|
||||
self.averageTime = datetime.timedelta(seconds=int(averageSeconds))
|
||||
|
||||
mapper = [ 1 if x == 0 else -1 for x in self.predictions ]
|
||||
reverseMapper = [ 1 if x == 0 else 0 for x in self.predictions ]
|
||||
self.ratingSystemDeviation = 0
|
||||
|
||||
confidenceCutoff = 60
|
||||
confidenceTupels = list(filter(lambda x: x[1] > confidenceCutoff,
|
||||
zip(reverseMapper, self.confidence)))
|
||||
|
||||
mapperTupels = list(filter(lambda x: x[1] > confidenceCutoff,
|
||||
zip(mapper, self.confidence)))
|
||||
|
||||
for i in range(0, len(mapperTupels)):
|
||||
self.ratingSystemDeviation += mapperTupels[i][0] * max(100, 50+mapperTupels[i][1])
|
||||
|
||||
self.ratingSystemDeviation /= len(mapperTupels)
|
||||
self.predictionCorrectPercentage = sum([x[0] for x in confidenceTupels])
|
||||
self.predictionCorrectPercentage /= len(confidenceTupels)
|
||||
self.predictionCorrectPercentage *= 100
|
||||
self.predictionCorrectPercentage = round(self.predictionCorrectPercentage)
|
||||
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
60
Round.py
60
Round.py
@@ -1,60 +0,0 @@
|
||||
import json
|
||||
import datetime
|
||||
import player
|
||||
import json
|
||||
import os
|
||||
|
||||
class Round:
|
||||
def __init__(self, dbRow):
|
||||
'''Create Round Object from cursor database row'''
|
||||
|
||||
timestamp, winners, losers, winnerSide, mapName, duration, prediction, confidence = dbRow
|
||||
startTime = datetime.datetime.fromtimestamp(int(float(timestamp)))
|
||||
winnersParsed = json.loads(winners)
|
||||
losersParsed = json.loads(losers)
|
||||
|
||||
self.startTime = startTime
|
||||
self.id = int(float(timestamp))
|
||||
self.winners = [ player.playerFromDict(wp, int(duration)) for wp in winnersParsed ]
|
||||
self.losers = [ player.playerFromDict(lp, int(duration)) for lp in losersParsed ]
|
||||
self.winnerSide = winnerSide
|
||||
self.duration = datetime.timedelta(seconds=int(duration))
|
||||
|
||||
self.blacklist = False
|
||||
blacklistNames = []
|
||||
blacklistFile = "blacklist.json"
|
||||
if os.path.isfile(blacklistFile):
|
||||
with open(blacklistFile) as f:
|
||||
blacklistNames = json.load(f)["blacklist"]
|
||||
|
||||
for name in blacklistNames:
|
||||
for p in self.winners:
|
||||
if p.name == name:
|
||||
self.blacklist = True
|
||||
for p in self.losers:
|
||||
if p.name == name:
|
||||
self.blacklist = True
|
||||
|
||||
|
||||
if winnerSide == 1:
|
||||
self.winnerSideString = "Red"
|
||||
self.loserSideString = "Blue"
|
||||
else:
|
||||
self.winnerSideString = "Blue"
|
||||
self.loserSideString = "Red"
|
||||
if mapName:
|
||||
self.mapName = mapName
|
||||
else:
|
||||
self.mapName = "unavailiable"
|
||||
|
||||
self.numericPrediction = prediction
|
||||
self.confidence = (int(confidence * 100) - 50)*2
|
||||
self.quality = int(150 - self.confidence)
|
||||
if self.confidence < 50:
|
||||
self.prediction = "-"
|
||||
elif prediction == 0:
|
||||
self.prediction = self.winnerSideString
|
||||
elif prediction == 1:
|
||||
self.prediction = self.loserSideString
|
||||
else:
|
||||
self.prediction = "Error"
|
||||
68
balance.py
Normal file
68
balance.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from constants import *
|
||||
|
||||
NO_CHANGE = -1
|
||||
|
||||
def shouldSwapBasedOnPrio(teams, curIndex, compareIndex, curTeamIndex):
|
||||
'''Return a team ID in which to switch with the compare index'''
|
||||
|
||||
otherTeam = (curTeamIndex + 1) % 2
|
||||
|
||||
curPrio = teams[curTeamIndex].affinityFor(curIndex)
|
||||
compPrioOtherTeam = teams[otherTeam].affinityFor(compareIndex)
|
||||
compPrioSameTeam = team[otherTeam].affinityFor(compareIndex)
|
||||
|
||||
if curPrio > compPrioSameTeam and compPrioSameTeam > compPrioOtherTeam:
|
||||
return compPrioSameTeam
|
||||
elif curPrio > compPrioOtherTeam:
|
||||
return compPrioOtherTeam
|
||||
else:
|
||||
return NO_CHANGE
|
||||
|
||||
def swap(teams, teamIndex1, teamIndex2, pos1, pos2):
|
||||
'''Swap two positions in the same or different teams'''
|
||||
|
||||
tmp = teams[teamIndex1][pos1]
|
||||
teams[teamIndex1][pos1] = teams[teamIndex2][pos2]
|
||||
teams[teamIndex2][pos2] = tmp
|
||||
|
||||
def ratingDiff(team1, team2):
|
||||
'''Positive if first > seconds, negative if second > first, 0 if equal'''
|
||||
return sum([p.rating for p in team1]) - sum([p.rating for p in team2])
|
||||
|
||||
def balance(players):
|
||||
|
||||
# initial teams #
|
||||
playersByRating = sorted(players, key=lambda p: p.rating)
|
||||
|
||||
teams = dict( { 0 : [] }, { 1 : [] } )
|
||||
for i in range(0, len(playersByRating)):
|
||||
teams[i%2] = playersByRating[i]
|
||||
|
||||
# optimize positions worst case ~8n^2 * 2log(n) #
|
||||
for teamIndex in teams.keys():
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
for curIndex in range(0, 5)
|
||||
for compareIndex in range(curIndex, 5)
|
||||
if curIndex == compareIndex:
|
||||
continue
|
||||
|
||||
# shouldSwap return -1 for no swap or the team to swap with #
|
||||
swapTeam = shouldSwapBasedOnPrio(teams, curIndex, compareIndex, teamIndex)
|
||||
elif VALID_INDEX(swapTeam):
|
||||
changed = True
|
||||
swap(teams, teamIndex, swapTeam, curIndex, compareIndex)
|
||||
|
||||
# optimize team rating #
|
||||
changedRating = True
|
||||
while changedRating:
|
||||
|
||||
diff = ratingDiff(teams[0], teams[1])
|
||||
diffByPos = [ teams[0][i] - teams[1][i] for i in range(0, 5) ]
|
||||
|
||||
for i in range(0, diffByPos):
|
||||
diffHelper = abs(diffByPos[i]-diff)
|
||||
if diffHelper <
|
||||
for curIndex in range(0, len(teams[0])):
|
||||
if rating diff
|
||||
@@ -1,2 +0,0 @@
|
||||
# rename to config.py and remove this line for this file to have effect
|
||||
DB_PATH="players.sqlite"
|
||||
8
constants.py
Normal file
8
constants.py
Normal file
@@ -0,0 +1,8 @@
|
||||
POSITIONS_NAMES = ["Top", "Jungle", "Mid", "Bottom", "Support" ]
|
||||
DATABASE_PRIO_NAMES = ["prioTop", "prioJungle", "prioMid", "prioBot", "prioSupport" ]
|
||||
TYPE_JSON = 'application/json'
|
||||
|
||||
HTTP_OK = 200
|
||||
|
||||
def VALID_INDEX(index):
|
||||
return index == 0 or index == 1
|
||||
49
player.py
49
player.py
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
import flask
|
||||
|
||||
def playerFromDict(d, duration):
|
||||
p = PlayerInLeaderboard([d["id"], d["name"], None, 0, 0, 0, 0])
|
||||
p.participation = min(int(d["active_time"]/duration*100), 100)
|
||||
return p
|
||||
|
||||
class PlayerInLeaderboard:
|
||||
def __init__(self, dbRow):
|
||||
'''Initialize a player object later to be serialized to HTML'''
|
||||
|
||||
playerId, name, lastGame, wins, mu, sigma, games = dbRow
|
||||
|
||||
# set relevant values #
|
||||
self.name = name
|
||||
self.playerId = playerId
|
||||
self.mu = mu
|
||||
self.sigma = sigma
|
||||
self.rating = int(self.mu) - 2*int(self.sigma)
|
||||
self.ratingStr = str(self.rating)
|
||||
self.games = int(games)
|
||||
self.wins = int(wins)
|
||||
self.loses = self.games - self.wins
|
||||
self.rank = None
|
||||
self.lastGame = lastGame
|
||||
self.participation = -1
|
||||
|
||||
self.muChange = None
|
||||
self.sigmaChange = None
|
||||
self.ratingChangeString = "N/A"
|
||||
|
||||
# determine winratio #
|
||||
if self.games == 0:
|
||||
self.winratio = "N/A"
|
||||
else:
|
||||
self.winratio = str(int(self.wins/self.games * 100))
|
||||
|
||||
def getLineHTML(self, rank):
|
||||
'''Build a single line for a specific player in the leaderboard'''
|
||||
|
||||
string = flask.render_template("playerLine.html", \
|
||||
playerRank = rank, \
|
||||
playerName = self.name, \
|
||||
playerRating = self.rating, \
|
||||
playerGames = self.games, \
|
||||
playerWinratio = self.winratio)
|
||||
|
||||
return flask.Markup(string)
|
||||
364
server.py
364
server.py
@@ -3,202 +3,114 @@ import flask
|
||||
import requests
|
||||
import argparse
|
||||
import datetime
|
||||
import flask_caching as fcache
|
||||
import itertools
|
||||
import json
|
||||
import os
|
||||
import MapSummary
|
||||
import random
|
||||
import secrets
|
||||
import riotwatcher
|
||||
import time
|
||||
import statistics
|
||||
|
||||
from database import DatabaseConnection
|
||||
import api
|
||||
|
||||
from constants import *
|
||||
|
||||
|
||||
app = flask.Flask("open-leaderboard")
|
||||
|
||||
WATCHER = None
|
||||
KEY = None
|
||||
|
||||
|
||||
if os.path.isfile("config.py"):
|
||||
app.config.from_object("config")
|
||||
|
||||
cache = fcache.Cache(app, config={'CACHE_TYPE': 'simple'})
|
||||
cache.init_app(app)
|
||||
|
||||
SEGMENT=100
|
||||
SERVERS=list()
|
||||
|
||||
from sqlalchemy import Column, Integer, String, Boolean, or_, and_
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.sql import func
|
||||
import sqlalchemy
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
def prettifyMinMaxY(computedMin, computedMax):
|
||||
if computedMax > 0 and computedMin > 0:
|
||||
return (0, 4000)
|
||||
else:
|
||||
return (computedMin - 100, 4000)
|
||||
class PlayerInDatabase(db.Model):
|
||||
__tablename__ = "players"
|
||||
player = Column(String, primary_key=True)
|
||||
rating = Column(Integer)
|
||||
ratingFix = Column(Integer)
|
||||
lastUpdated = Column(Integer)
|
||||
|
||||
@app.route("/players-online")
|
||||
def playersOnline():
|
||||
'''Calc and return the online players'''
|
||||
class Submission(db.Model):
|
||||
__tablename__ = "submissions"
|
||||
ident = Column(String, primary_key=True)
|
||||
submissionId = Column(String)
|
||||
player = Column(String)
|
||||
prioTop = Column(Integer)
|
||||
prioJungle = Column(Integer)
|
||||
prioMid = Column(Integer)
|
||||
prioBot = Column(Integer)
|
||||
prioSupport = Column(Integer)
|
||||
|
||||
playerTotal = 0
|
||||
error = ""
|
||||
def toDict():
|
||||
pass
|
||||
|
||||
for s in SERVERS:
|
||||
try:
|
||||
with valve.source.a2s.ServerQuerier((args.host, args.port)) as server:
|
||||
playerTotal += int(server.info()["player_count"])
|
||||
except NoResponseError:
|
||||
error = "Server Unreachable"
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
|
||||
retDict = { "player_total" : playerTotal, "error" : error }
|
||||
return flask.Response(json.dumps(retDict), 200, mimetype='application/json')
|
||||
|
||||
|
||||
|
||||
@app.route("/round-info")
|
||||
def singleRound():
|
||||
'''Display info about a single round itdentified by it's timestamp'''
|
||||
|
||||
timestamp = flask.request.args.get("id")
|
||||
if not timestamp:
|
||||
return ("ID Missing", 404)
|
||||
if not timestamp.endswith(".0"):
|
||||
timestamp = timestamp + ".0"
|
||||
db = DatabaseConnection(app.config["DB_PATH"])
|
||||
r = db.getRoundByTimestamp(timestamp)
|
||||
if not r:
|
||||
return ("Round not found", 404)
|
||||
elif r.blacklist:
|
||||
return ("Unavailable due to pending GDPR deletion request", 451)
|
||||
r = db.calcRatingChanges(r)
|
||||
|
||||
if not r:
|
||||
return ("", 404)
|
||||
|
||||
r.winners = sorted(r.winners, key=lambda p: p.participation, reverse=True)
|
||||
r.losers = sorted(r.losers, key=lambda p: p.participation, reverse=True)
|
||||
|
||||
return flask.render_template("single_round.html", r=r)
|
||||
|
||||
@app.route("/livegames")
|
||||
def liveGames():
|
||||
'''Display info about a single round itdentified by it's timestamp'''
|
||||
|
||||
db = DatabaseConnection(app.config["DB_PATH"])
|
||||
rounds = db.getLiveGames()
|
||||
return flask.render_template("livegames.html", liveGameRounds=rounds, noRounds=not bool(rounds))
|
||||
|
||||
@app.route("/maps")
|
||||
def maps():
|
||||
'''Show an overview of maps'''
|
||||
|
||||
db = DatabaseConnection(app.config["DB_PATH"])
|
||||
start = datetime.datetime.now() - datetime.timedelta(days=4000)
|
||||
end = datetime.datetime.now()
|
||||
rounds = db.roundsBetweenDates(start, end)
|
||||
distinctMaps = db.distinctMaps()
|
||||
maps = []
|
||||
for mapName in [ tupel[0] for tupel in distinctMaps]:
|
||||
roundsWithMap = list(filter(lambda r: r.mapName == mapName , rounds))
|
||||
maps += [MapSummary.MapSummary(roundsWithMap)]
|
||||
|
||||
allMaps = MapSummary.MapSummary(rounds)
|
||||
allMaps.mapName = "All Maps*"
|
||||
maps += [allMaps]
|
||||
|
||||
|
||||
mapsFiltered = filter(lambda x: x.mapName, maps)
|
||||
return flask.render_template("maps.html", maps=mapsFiltered)
|
||||
|
||||
@app.route("/rounds-by-timestamp")
|
||||
@app.route("/rounds")
|
||||
def rounds():
|
||||
'''Show rounds played on the server'''
|
||||
|
||||
start = flask.request.args.get("start")
|
||||
end = flask.request.args.get("end")
|
||||
|
||||
if not start or not end:
|
||||
start = datetime.datetime.now() - datetime.timedelta(days=365)
|
||||
end = datetime.datetime.now()
|
||||
else:
|
||||
start = datetime.datetime.fromtimestamp(start)
|
||||
end = datetime.datetime.fromtimestamp(end)
|
||||
|
||||
db = DatabaseConnection(app.config["DB_PATH"])
|
||||
rounds = db.roundsBetweenDates(start, end)
|
||||
|
||||
return flask.render_template("rounds.html", rounds=rounds)
|
||||
|
||||
|
||||
# get timestamp
|
||||
# display players
|
||||
# display rating change
|
||||
# display outcome
|
||||
# display map
|
||||
def affinityFor(self, posIndex):
|
||||
prio = getattr(self, DATABASE_PRIO_NAMES[posIndex])
|
||||
return prio
|
||||
|
||||
class Player:
|
||||
def __init__(self, name, prio):
|
||||
self.name = name
|
||||
self.prio = prio
|
||||
self.name = name
|
||||
self.prio = prio
|
||||
|
||||
# TODO
|
||||
submission = dict()
|
||||
@app.route("/role-submission", methods=['GET', 'POST'])
|
||||
def roleSubmissionTool():
|
||||
positions=["Top", "Jungle", "Mid", "Bottom", "Support" ]
|
||||
|
||||
ident = flask.request.args.get("id")
|
||||
submissionId = flask.request.args.get("id")
|
||||
player = flask.request.args.get("player")
|
||||
|
||||
if flask.request.method == 'POST':
|
||||
|
||||
if not ident in submission:
|
||||
submission.update({ ident : [] })
|
||||
|
||||
tmp = dict()
|
||||
tmp.update({ "name" : flask.request.form["playername"] })
|
||||
for p in positions:
|
||||
tmp.update({ p : flask.request.form["prio_{}".format(p)] })
|
||||
submissionQuery = db.session.query(PlayerInDatabase)
|
||||
identKey = "{}-{}".format(submissionId, player)
|
||||
submission = submissionQuery.filter(PlayerInDatabase.ident == identKey).first()
|
||||
|
||||
existed = False
|
||||
for pl in submission[ident]:
|
||||
if pl["name"] == tmp["name"]:
|
||||
for p in positions:
|
||||
pl.update({ p : flask.request.form["prio_{}".format(p)] })
|
||||
existed = True
|
||||
break;
|
||||
if not submission:
|
||||
submission = Submission(identKey, submissionId, player, -1, -1, -1, -1, -1)
|
||||
|
||||
if not existed:
|
||||
submission[ident] += [tmp]
|
||||
for i in range(0, 5):
|
||||
formKey = "prio_" + POSITIONS_NAMES[i]
|
||||
setattr(submission, DATABASE_PRIO_NAMES[i], flask.request.form[formKey])
|
||||
|
||||
return flask.redirect("/balance-tool?id={}".format(ident))
|
||||
db.session.merge(submission)
|
||||
db.session.commit()
|
||||
|
||||
return flask.redirect("/balance-tool?id=" + ident)
|
||||
else:
|
||||
return flask.render_template("role_submission.html",
|
||||
positions=positions,
|
||||
ident=ident)
|
||||
return flask.render_template("role_submission.html", positions=positions, ident=ident)
|
||||
|
||||
@app.route("/balance-tool-data")
|
||||
def balanceToolData():
|
||||
ident = flask.request.args.get("id")
|
||||
retDict = dict()
|
||||
if not ident in submission:
|
||||
return flask.Response(json.dumps({ "no-data" : False }), 200, mimetype='application/json')
|
||||
retDict.update({ "submissions" : submission[ident] })
|
||||
return flask.Response(json.dumps(retDict), 200, mimetype='application/json')
|
||||
|
||||
submissionId = flask.request.args.get("id")
|
||||
submissionsQuery = db.session.query(PlayerInDatabase)
|
||||
submissions = submissionsQuery.filter(PlayerInDatabase.submissionId == submissionId).all()
|
||||
|
||||
if not submissions:
|
||||
return flask.Response(json.dumps({ "no-data" : False }), HTTP_OK, mimetype=TYPE_JSON)
|
||||
|
||||
retDict.update()
|
||||
|
||||
dicts = [ s.toDict() for s in submissions ]
|
||||
return flask.Response(json.dumps({ "submissions" : dicts }), HTTP_OK, mimetype=TYPE_JSON)
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@app.route("/balance-tool", methods=['GET', 'POST'])
|
||||
def balanceTool():
|
||||
positions=["Top", "Jungle", "Mid", "Bottom", "Support"]
|
||||
|
||||
#db = DatabaseConnection(app.config["DB_PATH"])
|
||||
|
||||
if flask.request.method == 'POST':
|
||||
|
||||
@@ -345,9 +257,6 @@ def balanceTool():
|
||||
positions=positions,
|
||||
sides=["left", "right"],
|
||||
ident=ident)
|
||||
@app.route("/get-cache")
|
||||
def getCacheLoc():
|
||||
return (json.dumps(api.getCache()), 200)
|
||||
|
||||
@app.route("/player-api")
|
||||
def playerApi():
|
||||
@@ -365,140 +274,9 @@ def playerApiCache():
|
||||
else:
|
||||
return ("Nope", 404)
|
||||
|
||||
@app.route("/player")
|
||||
def player():
|
||||
'''Show Info about Player'''
|
||||
|
||||
playerId = flask.request.args.get("id")
|
||||
if(not playerId):
|
||||
return ("", 404)
|
||||
|
||||
db = DatabaseConnection(app.config["DB_PATH"])
|
||||
player = db.getPlayerById(playerId)
|
||||
|
||||
if(not player):
|
||||
return ("", 404)
|
||||
|
||||
player.rank = db.getPlayerRank(player)
|
||||
histData = db.getHistoricalForPlayerId(playerId)
|
||||
|
||||
csv_month_year = []
|
||||
csv_ratings = []
|
||||
csv_timestamps = []
|
||||
|
||||
minRating = 3000
|
||||
maxRating = 0
|
||||
|
||||
if histData:
|
||||
datapoints = histData[playerId]
|
||||
if datapoints:
|
||||
|
||||
tickCounter = 10
|
||||
for dpk in datapoints.keys():
|
||||
t = datetime.datetime.fromtimestamp(int(float(dpk)))
|
||||
tsMs = str(int(t.timestamp() * 1000))
|
||||
ratingString = str(int(datapoints[dpk]["mu"]) - 2*int(datapoints[dpk]["sigma"]))
|
||||
ratingAmored = '{ x : ' + tsMs + ', y : ' + ratingString + '}'
|
||||
csv_timestamps += [str(tsMs)]
|
||||
csv_ratings += [ratingAmored]
|
||||
|
||||
tickCounter -= 1
|
||||
if tickCounter <= 0:
|
||||
tickCounter = 10
|
||||
csv_month_year += ['new Date({})'.format(tsMs)]
|
||||
|
||||
minRating = min(minRating, int(ratingString))
|
||||
maxRating = max(maxRating, int(ratingString))
|
||||
|
||||
yMin, yMax = prettifyMinMaxY(minRating, maxRating)
|
||||
|
||||
# change displayed rank to start from 1 :)
|
||||
player.rank += 1
|
||||
|
||||
return flask.render_template("player.html", player=player, CSV_RATINGS=",".join(csv_ratings),
|
||||
CSV_MONTH_YEAR_OF_RATINGS=",".join(csv_month_year),
|
||||
CSV_TIMESTAMPS=csv_timestamps,
|
||||
Y_MIN=yMin, Y_MAX=yMax)
|
||||
|
||||
@app.route('/leaderboard')
|
||||
@cache.cached(timeout=10, query_string=True)
|
||||
def leaderboard():
|
||||
'''Show main leaderboard page with range dependant on parameters'''
|
||||
|
||||
# parse parameters #
|
||||
page = flask.request.args.get("page")
|
||||
playerName = flask.request.args.get("string")
|
||||
db = DatabaseConnection(app.config["DB_PATH"])
|
||||
|
||||
if page:
|
||||
pageInt = int(page)
|
||||
if pageInt < 0:
|
||||
pageInt = 0
|
||||
start = SEGMENT * int(page)
|
||||
else:
|
||||
pageInt = 0
|
||||
start = 0
|
||||
|
||||
# handle find player request #
|
||||
cannotFindPlayer = ""
|
||||
searchName = ""
|
||||
|
||||
playerList = None
|
||||
doNotComputeRank = True
|
||||
if playerName:
|
||||
playersInLeaderboard = db.findPlayerByName(playerName)
|
||||
if not playersInLeaderboard:
|
||||
cannotFindPlayer = flask.Markup("<div class=noPlayerFound>No player of that name</div>")
|
||||
start = 0
|
||||
else:
|
||||
if len(playersInLeaderboard) == 1:
|
||||
rank = playersInLeaderboard[0].rank
|
||||
if(playersInLeaderboard[0].games < 10):
|
||||
return flask.redirect("/player?id={}".format(playersInLeaderboard[0].playerId))
|
||||
searchName = playersInLeaderboard[0].name
|
||||
start = rank - (rank % SEGMENT)
|
||||
else:
|
||||
playerList = playersInLeaderboard
|
||||
for p in playerList:
|
||||
if p.rank == -1:
|
||||
p.rankStr = "N/A"
|
||||
else:
|
||||
p.rankStr = str(p.rank)
|
||||
doNotComputeRank = False
|
||||
|
||||
reachedEnd = False
|
||||
maxEntry = 0
|
||||
if not playerList:
|
||||
# compute range #
|
||||
end = start + SEGMENT
|
||||
maxEntry = db.getTotalPlayers()
|
||||
reachedEnd = False
|
||||
if end > maxEntry:
|
||||
start = maxEntry - ( maxEntry % SEGMENT ) - 1
|
||||
end = maxEntry - 1
|
||||
print(maxEntry)
|
||||
reachedEnd = True
|
||||
|
||||
playerList = db.getRankRange(start, end)
|
||||
|
||||
endOfBoardIndicator = ""
|
||||
if reachedEnd:
|
||||
endOfBoardHtml = "<div id='eof' class=endOfBoardIndicator> - - - End of Board - - - </div>"
|
||||
endOfBoardIndicator = flask.Markup(endOfBoardHtml)
|
||||
|
||||
# fix <100 player start at 0 #
|
||||
if maxEntry <= 100:
|
||||
start = max(start, 0)
|
||||
|
||||
finalResponse = flask.render_template("base.html", playerList=playerList, \
|
||||
doNotComputeRank=doNotComputeRank, \
|
||||
start=start, \
|
||||
endOfBoardIndicator=endOfBoardIndicator, \
|
||||
findPlayer=cannotFindPlayer, \
|
||||
searchName=searchName,
|
||||
nextPageNumber=int(pageInt)+1,
|
||||
prevPageNumber=int(pageInt)-1)
|
||||
return finalResponse
|
||||
@app.route("/get-cache")
|
||||
def getCacheLoc():
|
||||
return (json.dumps(api.getCache()), 200)
|
||||
|
||||
@app.route('/static/<path:path>')
|
||||
def send_js(path):
|
||||
@@ -508,22 +286,22 @@ def send_js(path):
|
||||
def init():
|
||||
|
||||
global WATCHER
|
||||
|
||||
app.config["DB"] = db
|
||||
db.create_all()
|
||||
|
||||
with open("key.txt","r") as f:
|
||||
key = f.read().strip()
|
||||
WATCHER = riotwatcher.LolWatcher(key)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser(description='Start open-leaderboard', \
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--interface', default="localhost", \
|
||||
help='Interface on which flask (this server) will take requests on')
|
||||
parser.add_argument('--port', default="5002", \
|
||||
help='Port on which flask (this server) will take requests on')
|
||||
|
||||
parser.add_argument('--skillbird-db', required=False, help='skillbird database (overrides web connection if set)')
|
||||
|
||||
parser.add_argument('--interface', default="localhost")
|
||||
parser.add_argument('--port', default="5002")
|
||||
|
||||
args = parser.parse_args()
|
||||
app.config["DB_PATH"] = args.skillbird_db
|
||||
|
||||
app.config["TEMPLATES_AUTO_RELOAD"] = True
|
||||
app.run(host=args.interface, port=args.port)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
CREATE TABLE players(
|
||||
playerName TEXT PRIMARY KEY,
|
||||
rating INTEGER,
|
||||
lastupdated TEXT
|
||||
);
|
||||
Reference in New Issue
Block a user