implement balance query

This commit is contained in:
Yannik Schmidt
2020-06-19 01:43:10 +02:00
parent 9bdad9a1c4
commit d0c3403cba
3 changed files with 47 additions and 24 deletions

View File

@@ -37,6 +37,9 @@ class PlayerInRound(Player):
def __str__(self): def __str__(self):
return "PlayerInRound: N: {} ID: {} Team: {}".format(self.name, self.id, self.team) return "PlayerInRound: N: {} ID: {} Team: {}".format(self.name, self.id, self.team)
def playerInRoundFromJson(jsonDict):
return PlayerInRound(jsonDict["id"], jsonDict["name"], jsonDict["team"], timestamp=dt.datetime.now())
class PlayerInDatabase(Player): class PlayerInDatabase(Player):
def __init__(self, playerId, name, rating, wins, games): def __init__(self, playerId, name, rating, wins, games):

View File

@@ -1,9 +1,9 @@
#!/usr/bin/python3 #!/usr/bin/python3
from trueskill import TrueSkill, Rating import trueskill
import scipy import scipy.stats
import math import math
env = TrueSkill(draw_probability=0, mu=1500, sigma=833, tau=40, backend='mpmath') env = trueskill.TrueSkill(draw_probability=0, mu=1500, sigma=833, tau=40, backend='mpmath')
env.make_as_global() env.make_as_global()
##################################################### #####################################################
@@ -71,9 +71,9 @@ def evaluateRound(r):
def newRating(mu=None, sigma=None): def newRating(mu=None, sigma=None):
if mu and sigma: if mu and sigma:
return Rating(mu=mu, sigma=sigma) return trueskill.Rating(mu=mu, sigma=sigma)
elif mu: elif mu:
return Rating(mu=mu, sigma=env.sigma) return trueskill.Rating(mu=mu, sigma=env.sigma)
else: else:
return env.create_rating() return env.create_rating()
@@ -91,8 +91,8 @@ def predictOutcome(teamA, teamB):
ratingsB = [ p.rating for p in teamB ] ratingsB = [ p.rating for p in teamB ]
muTeamA = sum([ r.mu for r in ratingsA]) muTeamA = sum([ r.mu for r in ratingsA])
muTeamB = sum([ r.mu for r in ratingsB]) muTeamB = sum([ r.mu for r in ratingsB])
sigmaTeamA = math.sqrt(sum([ r.sigma**2 for r in ratingsA])) sigmaTeamA = sum([ r.sigma for r in ratingsA])
sigmaTeamB = math.sqrt(sum([ r.sigma**2 for r in ratingsB])) sigmaTeamB = sum([ r.sigma for r in ratingsB])
# probabilty that a random point from normDistTeamA is greater # probabilty that a random point from normDistTeamA is greater
# than a random point from normDistB is normA - normB and then the # than a random point from normDistB is normA - normB and then the
@@ -103,12 +103,19 @@ def predictOutcome(teamA, teamB):
return (0, prob) return (0, prob)
elif prob < 0.5: elif prob < 0.5:
return (1, 1-prob) return (1, 1-prob)
else:
raise ValueError("Probability was NAN, team rating must have been malformed.")
def balance(players, buddies=None):
sortedByRating = sorted(players, key=lambda p: env.expose(p.rating))
teamA = []
teamB = []
for i in range(0, len(players)):
if i % 2 == 0:
teamA += [sortedByRating[i]]
else:
teamB += [sortedByRating[i]]
def quality(teamA, teamB): prediction, confidence = predictOutcome(teamA, teamB)
'''Take two teams of players and calculate a game quality''' quality = 1-abs(0.5 - confidence)
return ((teamA, teamB), quality)
ratingsA = [ p.rating for p in teamA ]
ratingsB = [ p.rating for p in teamB ]
return trueskill.quality(ratingsA, ratingsB)

View File

@@ -2,6 +2,7 @@
import backends.database as db import backends.database as db
import backends.trueskillWrapper as ts import backends.trueskillWrapper as ts
import backends.entities.Players as players
import backends.eventStream import backends.eventStream
import Round import Round
import json import json
@@ -28,20 +29,32 @@ def getPlayer():
def getOutcomePrediction(): def getOutcomePrediction():
'''Make a prediction based tww submitted teams of players''' '''Make a prediction based tww submitted teams of players'''
teamB = [ db.getPlayer(pJson["id"]) for pJson in flask.request.get("teamA") ] teamA = filter(lambda x: x["team"] % 2 == 0, flask.request.json["players"])
teamB = [ db.getPlayer(pJson["id"]) for pJson in flask.request.get("teamB") ] teamB = filter(lambda x: x["team"] % 2 == 1, flask.request.json["players"])
cnameTeamA = flask.request.get("cnameTeamA")
cnameTeamB = flask.request.get("cnameTeamB")
quality = ts.quality(teamA, teamB)
prediction, confidence = ts.predict(teamA, teamB) playersA = [ db.getOrCreatePlayer(players.playerInRoundFromJson(pJson)) for pJson in teamA ]
playersB = [ db.getOrCreatePlayer(players.playerInRoundFromJson(pJson)) for pJson in teamB ]
prediction, confidence = ts.predictOutcome(playersA, playersB)
quality = 1-abs(0.5-confidence)
balanceSuggestion, qualityOfSuggestion = ts.balance(playersA+playersB)
retData = dict() retData = dict()
retData.update( { "cnameTeamA" : cnameTeamA } )
retData.update( { "cnameTeamB" : cnameTeamB } )
retData.update( { "quality" : quality } ) retData.update( { "quality" : quality } )
retData.update( { "prediction" : prediction } ) retData.update( { "prediction" : prediction } )
retData.update( { "confidence" : confidence } ) retData.update( { "prediction-confidence" : confidence } )
balanceSuggestionJson = {
"teamA" : [ json.loads(p.toJson()) for p in balanceSuggestion[0] ],
"teamB" : [ json.loads(p.toJson()) for p in balanceSuggestion[1] ]
}
retData.update( { "teamA-orig" : [ json.loads(p.toJson()) for p in playersA ] })
retData.update( { "teamB-orig" : [ json.loads(p.toJson()) for p in playersB ] })
retData.update( { "qualityOfSuggestion" : qualityOfSuggestion } )
retData.update( { "balanceSuggestion" : balanceSuggestionJson } )
return flask.json.jsonify(retData) return flask.json.jsonify(retData)