예제 #1
0
	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()
예제 #2
0
	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()