expand api

This commit is contained in:
2019-11-02 11:21:46 +01:00
parent 19a31cdaa4
commit 1de9b97a5d
2 changed files with 99 additions and 47 deletions

View File

@@ -35,6 +35,8 @@ def sync_from_database(players):
p.rating = known_players[p].rating p.rating = known_players[p].rating
if type(players) == dict: if type(players) == dict:
players[p] = p.rating players[p] = p.rating
if not p.name or p.name == "PLACEHOLDER":
p.name = known_players[p].name
else: else:
lastUpdate = datetime.now() lastUpdate = datetime.now()
known_players.update(\ known_players.update(\
@@ -106,27 +108,11 @@ def save_psql():
###################### Python API ########################### ###################### Python API ###########################
############################################################# #############################################################
def getBalanceForPlayers(players, buddies=None):
if not players:
return ""
StorrageBackend.sync_from_database(players)
for p in players:
print(p, p.rating)
arr = sorted(players, key=lambda x: x.rating.mu, reverse=True)
ret=""
i = 0
while i < len(arr):
ret += "{}|{},".format(players[i].name,(i%2)+2)
i += 1
return ret
def getPlayer(pid, name="NOTFOUND"): def getPlayer(pid, name="NOTFOUND"):
return known_player[pid] return known_player[pid]
def fuzzy_find_player(name): def searchPlayerByName(name):
return "Not Implemented" '''Find a player by his name'''
def findPlayer(name):
global player_ranks global player_ranks
ret = "" ret = ""
@@ -146,22 +132,71 @@ def findPlayer(name):
playerRankTupel = [] playerRankTupel = []
for p in players: for p in players:
try: try:
playerRankTupel += [(p, player_ranks[p])] playerRankTupel += [(p.steamid, p.name, p.rating, player_ranks[p])]
except KeyError: except KeyError:
playerRankTupel += [(p, "N/A")] noRankExplanation = "inactive"
if p.games < 10:
noRankExplanation = "not enough games"
playerRankTupel += [(p.steamid, p.name, p.rating, noRankExplanation)]
finally: finally:
TS.unlock() TS.unlock()
return playerRankTupel return playerRankTupel
def getPlayerRank(playerID):
'''Get a players rank'''
def get_player_rank(p): global player_ranks
global player_ranks try:
try: return str(player_ranks[playerID])
return str(player_ranks[p]) except KeyError:
except KeyError: return "N/A"
return "N/A"
def getBalancedTeams(players, buddies=None, teamCount=2):
'''Balance a number of players into teams'''
if teamCount != 2:
raise NotImplementedError("Only supporting balancing into two teams currently")
if not players:
return ValueError("Input contains no players")
if type(players[0]) == str:
players = [ Player.DummyPlayer(playerID) for playerID in players]
sync_from_database(players)
arr = sorted(players, key=lambda x: x.rating.mu, reverse=True)
ret=""
i = 0
while i < len(arr):
ret += "{}|{},".format(players[i].name,(i%2)+2)
i += 1
return ret
def qualityForTeams(teamArray):
'''Get quality for number of teams with players'''
if not teamArray or len(teamArray) < 2 or not teamArray[0]:
raise ValueError("Team Array must be more than one team with more than one player each")
if type(teamArray[0][0]) == str:
teamArray = [ [ Player.DummyPlayer(playerID) for playerID in team ] for team in teamArray ]
for team in teamArray:
print(team[0].steamid)
sync_from_database(team)
teamAsRatings = [ [ player.rating for player in team ] for team in teamArray ]
teamAsNames = [ [ player.name for player in team ] for team in teamArray ]
# TODO: implement for !=2 teams #
if len(teamArray) != 2:
raise NotImplementedError("Quality is only supported for exactly two teams")
return qualityForRatings(teamAsRatings[0], teamAsRatings[1], teamAsNames[0], teamAsNames[1])
def qualityForRatings(team1, team2, names1 = [""], names2 = [""]):
'''Get Quality for two arrays containing TrueSkill.Rating objects'''
def quality(team1, team2, names1 = [""], names2 = [""]):
mu1 = sum(r.mu for r in team1) mu1 = sum(r.mu for r in team1)
mu2 = sum(r.mu for r in team2) mu2 = sum(r.mu for r in team2)
mu_tot = mu1 + mu2 mu_tot = mu1 + mu2
@@ -169,34 +204,31 @@ def quality(team1, team2, names1 = [""], names2 = [""]):
sig2 = sum(r.sigma for r in team2) sig2 = sum(r.sigma for r in team2)
sigtot = sig1 + sig2 sigtot = sig1 + sig2
names1 = list(map(lambda x: str(x.name), names1)) print(team1, team2)
names2 = list(map(lambda x: str(x.name), names2))
diff = abs(mu1 - mu2) diff = abs(mu1 - mu2)
percent = 50 + diff/mu_tot*100 percent = 50 + diff/mu_tot*100
if percent > 100: if percent > 100:
percent = 100 percent = 100
if mu1 > mu2: if mu1 > mu2:
string = "{} win at {:.2f}% - {:.2f} to {:.2f} Uncertainty: {:.2f}%".format(\ string = "{} win at {:.2f}% - {:.2f} to {:.2f}".format(names1, percent, mu1, mu2 )
",".join(names1), \
percent, mu1, mu2, sigtot/diff*100)
else: else:
string = "{} win at {:.2f}% - {:.2f} to {:.2f} Uncertainty: {:.2f}%".format(\ string = "{} win at {:.2f}% - {:.2f} to {:.2f}".format(names2, percent, mu2, mu1 )
",".join(names2), \
percent, mu2, mu1, sigtot/diff*100)
return string return string
def getRankListLength(revalidateRanks=False): def getRankListLength(revalidateRanks=False):
global playerRankList '''Get the total number of entries in the ranking'''
global playerRankList
updatePlayerRanks(revalidateRanks) updatePlayerRanks(revalidateRanks)
return len(playerRankList) return len(playerRankList)
def getRankRange(start, end, revalidateRanks=False): def getRankRange(start, end, revalidateRanks=False):
'''Returns a list of player, optionally flushing the ranks-cache first''' '''Returns a list of player, optionally flushing the ranks-cache first'''
global playerRankList global playerRankList
print(start,end) print(start,end)
@@ -206,9 +238,15 @@ def getRankRange(start, end, revalidateRanks=False):
return [] return []
return playerRankList[start:end] return playerRankList[start:end]
def hasChanged(time): def rankHasChanged(time):
'''Indicates to a http-querier if the availiable data has changed''' '''Indicates to a http-querier if the availiable data has changed'''
if last_rank_update > time: if last_rank_update > time:
return "True" return "True"
else: else:
return "False" return "False"
def debugInformation():
'''Dump a string of debugging information (this may take some times)'''
return [ "{} {} {}".format(p.steamid, p.name, p.rating) for p in known_players.values() ]

View File

@@ -11,9 +11,14 @@ def invalidParameters(*args):
######################################################## ########################################################
@app.route('/dumpdebug')
def dumpDebug():
return "<br>".join(SB.debugInformation())
@app.route('/getplayer') @app.route('/getplayer')
def getPlayer(): def getPlayer():
raise NotImplementedError() playerName = flask.request.args.get("name")
return str(SB.searchPlayerByName(playerName))
@app.route('/getmaxentries') @app.route('/getmaxentries')
def getMaxEntries(): def getMaxEntries():
@@ -32,14 +37,23 @@ def getRankRange():
players = SB.getRankRange(start, end) players = SB.getRankRange(start, end)
return "\n".join([p.serialize() for p in players]) return "\n".join([p.serialize() for p in players])
@app.route('/findplayer')
def findPlayer():
string = flask.request.args.get("string")
players = SB.findPlayer(string)
return "|".join([pt[0].serialize() + "," + str(pt[1]) for pt in players])
@app.route('/haschanged') @app.route('/haschanged')
def hasChanged(): def hasChanged():
string = flask.request.args.get("time") string = flask.request.args.get("time")
# TODO get time with timezone # TODO get time with timezone
return SB.hasChanged(localizedTime) return SB.rankHasChanged(localizedTime)
@app.route('/getbalancedteams')
def getBalancedTeams():
players = flask.request.args.get("players").split(",")
return SB.getBalancedTeams(players)
@app.route('/quality')
def quality():
'''Get a game quality estimate for two or more given teams'''
string = flask.request.args.get("playerswithteams")
teams = string.split("|")
if len(teams) < 2:
flask.abort("Invalid input string: {}".format(string))
teams = [ x.split(",") for x in teams ]
return SB.qualityForTeams(teams)