def Update(self,ladder_id,match,db): #print 'match id %d'%match.id scores, result_dict = calculateWinnerOrder(match,db) session = db.session() teams = defaultdict(tuple) player_id_map = defaultdict(list) def constant_factory(value): import itertools return itertools.repeat(value).next minteam_score = defaultdict(constant_factory(100000)) for name,result in result_dict.iteritems(): score = scores[name] * -1 player_id = session.query( Player ).filter( Player.nick == name ).first().id rank = session.query( TrueskillRanks ).filter( TrueskillRanks.ladder_id == ladder_id ).filter( TrueskillRanks.player_id == player_id ).first() if not rank: rank = TrueskillRanks() rank.ladder_id = ladder_id rank.player_id = player_id session.add(rank) rank.rank = score l = list(teams[result.team]) l.append(rank.rating) teams[result.team] = tuple(l) player_id_map[result.team].append(player_id) minteam_score[result.team] = min(minteam_score[result.team],score) session.commit() ordered_teams = [] ordered_minteam_score = [] team_ids = teams.keys() team_ids.sort() for i in range(len(teams)): ordered_teams.append(teams[team_ids[i]]) ordered_minteam_score.append(minteam_score[team_ids[i]]) i = 0 if len(ordered_teams) < 2: Log.error('less than 2 teams, cannot update ranking') raise Exception('not enough teams') for team_ratings in trueskill.transform_ratings(ordered_teams,ordered_minteam_score): j = 0 current_team = team_ids[i] q = session.query( TrueskillRanks ).filter( TrueskillRanks.ladder_id == ladder_id ) for rating in team_ratings: pids = player_id_map[current_team] pid = pids[j] rank = q.filter( TrueskillRanks.player_id == pid ).one() rank.rating = rating session.add( rank ) j += 1 i += 1 session.commit() session.close()
def Update(self,ladder_id,match,db): scores, result_dict = calculateWinnerOrder(match,db) session = db.session() #step one pre = dict() #name -> GlickoRanks avg_match_delta = db.GetAvgMatchDelta( ladder_id ) for name,result in result_dict.iteritems(): previous_match = session.query( Result ).filter( Result.player_id == result.player_id ).filter( Result.ladder_id == ladder_id ).filter(Result.date < match.date).order_by( Result.date.desc() ).filter( Result.id != match.id ).first() if previous_match: last_match_unixT = time.mktime(match.date.timetuple()) prev_match_unixT = time.mktime(previous_match.date.timetuple()) else: prev_match_unixT = last_match_unixT = 0 delta = last_match_unixT - prev_match_unixT t = delta / avg_match_delta db.UpdateAvgMatchDelta( ladder_id, delta ) player_id = session.query( Player ).filter( Player.nick == name ).first().id rank = session.query( GlickoRanks ).filter( GlickoRanks.ladder_id == ladder_id ).filter( GlickoRanks.player_id == player_id ).first() if not rank: rank = GlickoRanks() rank.ladder_id = ladder_id rank.player_id = player_id #actual calc else: rank.rd = min( math.sqrt( rank.rd*rank.rd + self.c*self.c * t ), 350.0 )#increase rd up to 350 session.add(rank) #must i commit everytime? session.commit() pre[name] = rank #end step 1 #step 2 post = dict() #name -> ( r\' , RD\' ) # build rd_j and r_j and s_j lists for each player lists = dict() # name -> ( [r_j] , [rd_j] , [s_j] ) for name,result in result_dict.iteritems(): r_j_list = [] rd_j_list = [] s_j_list = [] my_score = scores[name] my_ally = result.ally for other,other_result in result_dict.iteritems(): if name == other or other_result.ally == my_ally: continue r_j_list.append( pre[other].rating ) rd_j_list.append( pre[other].rd ) other_score = scores[other] if my_score > other_score: s_j_list.append( 1.0 ) elif my_score < other_score: s_j_list.append( 0.0 ) else: s_j_list.append( 0.5 ) lists[name] = ( r_j_list, rd_j_list, s_j_list ) #compute updates for name in result_dict.keys(): r = pre[name].rating RD = pre[name].rd r_j_list = lists[name][0] rd_j_list = lists[name][1] s_j_list = lists[name][2] ds = self.d_squared( r, r_j_list, rd_j_list ) denom = ( 1.0 / ( RD*RD ) ) + ( 1.0 / ds ) # calc r' su = 0.0 for j in range(len(r_j_list)): su += self.g( rd_j_list[j] ) * (s_j_list[j] - self.E( r, r_j_list[j], rd_j_list[j] ) ) r_new = r + ( ( self.q / denom ) * su ) rd_new = math.sqrt( 1.0 / denom ) post[name] = ( r_new, rd_new ) #commit updates for name in result_dict.keys(): rank = pre[name] rank.rating = post[name][0] rank.rd = max(post[name][1], self.rd_lower_bound ) session.add ( rank ) session.commit() #end step 2 session.close()