mirror of
https://github.com/FAUSheppy/skillbird
synced 2025-12-06 14:51:36 +01:00
151 lines
4.9 KiB
Python
151 lines
4.9 KiB
Python
from datetime import timedelta, datetime
|
|
import threading
|
|
from Player import PlayerInRound
|
|
import TrueSkillWrapper as TS
|
|
|
|
## A comment on why the login-offset is nessesary ##
|
|
## - losing teams tend to have players leaving and joining more rapidly
|
|
## - every time a new player joins he has to setup
|
|
## - new players are unfamiliar with postions of enemy team
|
|
## - new players have to run from spawn
|
|
## --> their impact factor must account for that
|
|
loginoffset = timedelta(seconds=60)
|
|
|
|
class Round:
|
|
writeLock = threading.RLock()
|
|
def __init__(self, winner_team, loser_team, _map, duration,\
|
|
starttime, winner_side=None, cache=None):
|
|
self.winners = winner_team
|
|
self.losers = loser_team
|
|
self.winner_side = winner_side
|
|
self.map = _map
|
|
self.duration = duration
|
|
self.start = starttime
|
|
#self.add_fake_players()
|
|
if cache:
|
|
Round.writeLock.acquire()
|
|
with open(cache, "a") as f:
|
|
f.write(self.serialize())
|
|
f.write("\n")
|
|
f.flush()
|
|
Round.writeLock.release()
|
|
|
|
|
|
def normalized_playtimes(self):
|
|
'''returns a dict-Object with {key=(teamid,player):value=player_time_played/total_time_of_round}'''
|
|
np = dict()
|
|
|
|
for p in self.winners:
|
|
if self.duration == None:
|
|
d = 1.0
|
|
else:
|
|
d = (p.active_time-loginoffset)/self.duration
|
|
if d < -1:
|
|
print("lol")
|
|
if d < 0:
|
|
d = 0.0
|
|
elif d > 1:
|
|
d = 1.0
|
|
np.update({(0,p):d})
|
|
for p in self.losers:
|
|
if self.duration == None:
|
|
d = 1.0
|
|
else:
|
|
d = (p.active_time-loginoffset)/self.duration
|
|
if d < 0:
|
|
d = 0.0
|
|
elif d > 1:
|
|
d = 1.0
|
|
np.update({(1,p):d})
|
|
|
|
return np
|
|
|
|
def add_fake_players(self):
|
|
''' adds map/side specific player to account for asynchronous gameplay '''
|
|
if not self.map:
|
|
#print("Warning: No map info, cannot add fake players.")
|
|
return
|
|
ins = self.map+str(2)
|
|
sec = self.map+str(3)
|
|
|
|
p_ins = PlayerInRound(ins,2,None)
|
|
p_sec = PlayerInRound(sec,3,None)
|
|
|
|
if p_ins in Storrage.known_players:
|
|
p_ins = Storrage.known_players[p_ins]
|
|
if p_sec in Storrage.known_players:
|
|
p_sec = Storrage.known_players[p_sec]
|
|
|
|
if self.winner_side == 2:
|
|
self.winners += [p_ins]
|
|
self.losers += [p_sec]
|
|
else:
|
|
self.winners += [p_sec]
|
|
self.losers += [p_ins]
|
|
|
|
def pt_difference(self):
|
|
'''Used to check difference in playtimes per team'''
|
|
if self.duration == None:
|
|
return 1
|
|
w1 = w2 = 0
|
|
for p in self.winners:
|
|
if p.is_fake:
|
|
w1 += 1.0
|
|
continue
|
|
d = (p.active_time-loginoffset)/self.duration
|
|
if d < 0:
|
|
d = 0.0
|
|
elif d > 1:
|
|
d = 1.0
|
|
w1 += d
|
|
for p in self.losers:
|
|
d = (p.active_time-loginoffset)/self.duration
|
|
if p.is_fake:
|
|
w2 += 1.0
|
|
continue
|
|
if d < 0:
|
|
d = 0.0
|
|
elif d > 1:
|
|
d = 1.0
|
|
w2 += d
|
|
|
|
# no div0 plox
|
|
if min(w1,w2) <= 0:
|
|
return 0
|
|
|
|
return max(w1,w2)/min(w1,w2)
|
|
|
|
def serialize(self):
|
|
# full = winners|losers|winner_side|map|duration|start
|
|
# winners/losers = p1,p2,p3 ...
|
|
winners = ""
|
|
losers = ""
|
|
for p in self.winners:
|
|
winners += "," + p.serialize()
|
|
for p in self.losers:
|
|
losers += "," + p.serialize()
|
|
|
|
teams = "{}|{}".format(winners, losers)
|
|
startTimeStr = self.start.strftime("%b %d %H:%M:%S")
|
|
|
|
ret = "{}|{}|{}|{}|{}".format(teams, self.winner_side, \
|
|
self.map, self.duration.seconds, startTimeStr)
|
|
return ret
|
|
|
|
def deserialize(string):
|
|
string = string.strip("\n")
|
|
winnersStr, losersStr, winner_side, _map, duration, startTimeStr = string.split("|")
|
|
winners = dict()
|
|
losers = dict()
|
|
for pStr in winnersStr.split(","):
|
|
if pStr == "":
|
|
continue
|
|
winners.update({PlayerInRound.deserialize(pStr):TS.new_rating()})
|
|
for pStr in losersStr.split(","):
|
|
if pStr == "":
|
|
continue
|
|
losers.update({PlayerInRound.deserialize(pStr):TS.new_rating()})
|
|
startTime = datetime.strptime(startTimeStr, "%b %d %H:%M:%S")
|
|
duration = timedelta(seconds=int(duration))
|
|
return Round(winners, losers, _map, duration, startTime, winner_side)
|