def analyze(pla, rata, plb, ratb, race): diff = rata.get_totalrating(race) - ratb.get_totalrating(race) dev = sqrt(rata.get_totaldev(race)**2 + ratb.get_totaldev(race)**2) if diff > 0: return pla, plb, cdf(-diff, scale=dev) else: return plb, pla, cdf(diff, scale=dev)
def prob_of_winning(self, opponent): mix = 0.3 my_elo = self.elo + self.elo_race[opponent.race] op_elo = opponent.elo + opponent.elo_race[self.race] my_dev = self.dev**2 + self.dev_race[opponent.race]**2 op_dev = opponent.dev**2 + opponent.dev_race[self.race]**2 return cdf(my_elo - op_elo, scale=sqrt(1+my_dev+op_dev))
def performance(oppr, opps, oppc, W, L): opp = zip(oppr, opps, oppc, W, L) ret = [0.0, 0.0, 0.0, 0.0] meanok = True for cat in xrange(0,3): spopp = [o for o in opp if o[2] == cat] sW = sum([o[3] for o in spopp]) sL = sum([o[4] for o in spopp]) if sW == 0 and sL == 0: ret[cat+1] = NA meanok = False elif sW == 0: ret[cat+1] = MININF meanok = False elif sL == 0: ret[cat+1] = INF meanok = False else: gen_phi = lambda p, x: pdf(x, loc=p[0], scale=sqrt(1+p[1]**2)) gen_Phi = lambda p, x: max(min(cdf(x, loc=p[0], scale=sqrt(1+p[1]**2)), 1-LOG_CAP), LOG_CAP) def logL(x): ret = 0.0 for p in spopp: gP = gen_Phi(p,x) ret += p[3] * log(gP) + p[4] * log(1-gP) return ret def DlogL(x): ret = 0.0 for p in spopp: gp = gen_phi(p,x) gP = gen_Phi(p,x) ret += (float(p[3])/gP - float(p[4])/(1-gP)) * gp return ret def D2logL(x): ret = 0.0 for p in spopp: gp = gen_phi(p,x) gP = gen_Phi(p,x) alpha = gp/gP beta = gp/(1-gP) sb = sqrt(1+p[1]**2) Mv = pi/sqrt(3)/sb * tanh(pi/2/sqrt(3)*(x-p[0])/sb) ret -= p[3]*alpha*(alpha+Mv) + p[4]*beta*(beta-Mv) return ret perf = maximize(logL, DlogL, D2logL, 0.0, method=None)[0] ret[cat+1] = perf if meanok: ret[0] = sum(ret[1:]) / 3 else: ret[0] = NA return ret
def discrepancy(): cur = connection.cursor() cur.execute('''SELECT ra.rating, ra.rating_vp, ra.rating_vt, ra.rating_vz, ra.dev, ra.dev_vp, ra.dev_vt, ra.dev_vz, rb.rating, rb.rating_vp, rb.rating_vt, rb.rating_vz, rb.dev, rb.dev_vp, rb.dev_vt, rb.dev_vz, m.rca, m.rcb, m.sca, m.scb, pa.country, pb.country FROM ratings_rating AS ra, ratings_rating AS rb, ratings_player AS pa, ratings_player AS pb, ratings_match AS m WHERE m.pla_id=pa.id AND m.plb_id=pb.id AND ra.player_id=pa.id AND rb.player_id=pb.id AND m.period_id=ra.period_id+1 AND m.period_id=rb.period_id+1 AND m.rca<>'R' AND m.rcb<>'R' ''') disc_kr, disc_int, disc_cross = 0, 0, 0 num_kr, num_int, num_cross = 0, 0, 0 for r in cur.fetchall(): ra = r[0] + r['PTZ'.index(r[17])+1] sa = r[4]**2 + r['PTZ'.index(r[17])+5]**2 rb = r[8] + r['PTZ'.index(r[16])+9] sb = r[12]**2 + r['PTZ'.index(r[16])+13]**2 p = cdf(ra-rb, scale=sqrt(1+sa+sb)) disc = r[18] * log(p) + r[19] * log(1-p) if r[20] == 'KR' and r[21] == 'KR': disc_kr -= disc num_kr += 1 elif r[20] != 'KR' and r[21] != 'KR': disc_int -= disc num_int += 1 else: disc_cross -= disc num_cross += 1 return (disc_kr/num_kr)**2 + (disc_int/num_int)**2 + (disc_cross/num_cross)**2
rating = m.pla.rating_set.get(period__id=m.period.id-1) rta = rating.get_totalrating(m.rcb) dva = rating.get_totaldev(m.rcb) except: rta = 0 dva = sqrt(2)*0.6 try: rating = m.plb.rating_set.get(period__id=m.period.id-1) rtb = rating.get_totalrating(m.rca) dvb = rating.get_totaldev(m.rca) except: rtb = 0 dvb = sqrt(2)*0.6 prob = cdf(rta-rtb, scale=sqrt(1+dva**2+dvb**2)) if prob < 0.5: prob = 1-prob na, nb = m.scb, m.sca elif prob > 0.5: na, nb = m.sca, m.scb else: na, nb = choice([(m.sca, m.scb), (m.scb, m.sca)]) S = int(floor(2*(prob-0.5)*num_slots)) table_w[S] += na table_l[S] += nb games += na + nb
def update(myr, mys, oppr, opps, oppc, W, L, text='', pr=False, Ncats=3): """This function updates the rating of a player according to the ratings of the opponents and the games against them.""" # If no games were played, do nothing. if len(W) == 0: return(myr, mys, [None] * (Ncats+1), [None] * (Ncats+1)) # Add fake games to prevent infinities (oppr, opps, oppc, W, L) = fix_ww(myr, mys, oppr, opps, oppc, W, L) if pr: print text print oppr print opps print oppc print W print L played_cats = sorted(unique(oppc)) # The categories against which the player played played_cats_p1 = [p+1 for p in played_cats] tot = sum(myr[array(played_cats)+1]) # The sum relative rating against those categories # (will be kept constant) M = len(W) # Number of opponents C = len(played_cats) # Number of different categories played # Convert global categories to local def loc(x): return array([played_cats.index(c) for c in x]) # Convert local categories to global def glob(x): return array([played_cats[c] for c in x]) # Extends a M-vector to an M+1-vector according to the restriction given # (that the sum of relative ratings against the played categories is constant) def extend(x): return hstack((x, tot-sum(x[1:]))) # Ensure that arrays are 1-dimensional def dim(x): if x.ndim == 0: x = array([x]) return x # Prepare some vectors and other numbers that are needed to form objective functions, derivatives and # Hessians DM = zeros((M,C)) DMex = zeros((M,C+1)) DM[:,0] = 1 DMex[:,0] = 1 for j in range(0,M): lc = loc([oppc[j]])[0] if lc < C-1: DM[j,lc+1] = 1 else: DM[j,1:] = -1 DMex[j,lc+1] = 1 mbar = oppr sbar = sqrt(opps**2 + 1) gen_phi = lambda j, x: pdf(x, loc=mbar[j], scale=sbar[j]) gen_Phi = lambda j, x: max(min(cdf(x, loc=mbar[j], scale=sbar[j]), 1-LOG_CAP), LOG_CAP) alpha = pi/2/sqrt(3) myrc = myr[[0]+played_cats_p1] mysc = mys[[0]+played_cats_p1] # Objective function def logL(x): Mv = x[0] + extend(x)[loc(oppc)+1] Phi = array([gen_Phi(i,Mv[i]) for i in range(0,M)]) if pr: print ':::', x, Mv, Phi return sum(W*log(Phi) + L*log(1-Phi)) def logE(x): return sum(log(1 - tanh(alpha*(extend(x)-myrc)/mysc)**2)) #logF = lambda x: logL(x) + logE(x) logF = lambda x: logL(x) # Derivative def DlogL(x): Mv = x[0] + extend(x)[loc(oppc)+1] phi = array([gen_phi(i,Mv[i]) for i in range(0,M)]) Phi = array([gen_Phi(i,Mv[i]) for i in range(0,M)]) vec = (W/Phi - L/(1-Phi)) * phi return array(vec * matrix(DM))[0] def DlogE(x): ret = -2*alpha*tanh(alpha*(extend(x)-myrc)/mysc)/mysc print ret return ret #DlogF = lambda x: DlogL(x) + DlogE(x) DlogF = lambda x: DlogL(x) # Hessian def D2logL(x, DM, C): Mv = x[0] + extend(x)[loc(oppc)+1] phi = array([gen_phi(i,Mv[i]) for i in range(0,M)]) Phi = array([gen_Phi(i,Mv[i]) for i in range(0,M)]) alpha = phi/Phi beta = phi/(1-Phi) Mvbar = pi/sqrt(3)/sbar * tanh(pi/2/sqrt(3)*(Mv-mbar)/sbar) coeff = - W*alpha*(alpha+Mvbar) - L*beta*(beta-Mvbar) ret = zeros((C,C)) for j in range(0,M): ret += coeff[j] * outer(DM[j,:], DM[j,:]) return ret def D2logE(x): return diag(-2*alpha**2*(1 - tanh(alpha*(extend(x)-myrc)/mysc)**2)/mysc**2) #D2logF = lambda x: D2logL(x,DM,C) + D2logE(x) D2logF = lambda x: D2logL(x,DM,C) # Prepare initial guess in unrestricted format and maximize x = hstack((myr[0], myr[played_cats_p1]))[0:-1] x = maximize(logF, DlogF, D2logF, x, method='powell', disp=pr) x = dim(x) # If maximization failed, return the current rating and print an error message if x == None: print 'Failed to converge for %s' % text return (myr, mys, [None]*(Ncats+1), [None]*(Ncats+1)) # Extend to restricted format devs = sqrt(-1/diag(D2logL(x, DMex, C+1))) #devs = -1/diag(D2logL(x, DMex, C+1)) devs = maximum(devs, RATINGS_MIN_DEV) rats = extend(x) if pr: print devs print rats # Compute new RD and rating for the indices that can change news = zeros(len(myr)) newr = zeros(len(myr)) ind = [0] + [f+1 for f in played_cats] #news[ind] = devs #newr[ind] = rats news[ind] = 1./sqrt(1./devs**2 + 1./mys[ind]**2) newr[ind] = (rats/devs**2 + myr[ind]/mys[ind]**2) * news[ind]**2 if pr: print news print newr # Enforce the restriction of sum relative rating against played categories should be constant ind = ind[1:] m = (sum(newr[ind]) - tot)/len(ind) newr[ind] -= m newr[0] += m if pr: print newr # Ratings against non-played categories should be kept as before. ind = setdiff1d(range(0,len(myr)), [0] + ind) news[ind] = mys[ind] newr[ind] = myr[ind] if pr: print news print newr # Keep new RDs between MIN_DEV and INIT_DEV news = minimum(news, RATINGS_INIT_DEV) news = maximum(news, RATINGS_MIN_DEV) if pr: print news # Ensure that mean relative rating is zero m = mean(newr[1:]) newr[1:] -= m newr[0] += m if pr: print newr # Extend the performance ratings to global indices devsex = [None] * (Ncats + 1) ratsex = [None] * (Ncats + 1) devsex[0] = devs[0] ratsex[0] = rats[0] for c in played_cats: devsex[c+1] = devs[played_cats.index(c)+1] ratsex[c+1] = rats[played_cats.index(c)+1] if pr: print '------------ Finished' return (newr, news, ratsex, devsex)
def prob_of_winning(self, opponent): my_elo = self.elo_vs_opponent(opponent) op_elo = opponent.elo_vs_opponent(self) my_dev = self.dev_vs_opponent(opponent) op_dev = opponent.dev_vs_opponent(self) return cdf(my_elo - op_elo, scale=sqrt(1+my_dev+op_dev))
AND rating.period_id=%i ) WHERE period_id=%i AND plb_id IN (%s)''' % (period.id, period.id+1, ','.join(str_ids)) ) # }}} # {{{ Bookkeeping Match.objects.filter(period=period).update(treated=True) def mean(a): return sum([f.rating for f in a])/len(a) rp = mean(filter_active(Rating.objects.filter(period=period, player__race=P)).order_by('-rating')[:5]) rt = mean(filter_active(Rating.objects.filter(period=period, player__race=T)).order_by('-rating')[:5]) rz = mean(filter_active(Rating.objects.filter(period=period, player__race=Z)).order_by('-rating')[:5]) period.dom_p = cdf(rp-rt) + cdf(rp-rz) period.dom_t = cdf(rt-rp) + cdf(rt-rz) period.dom_z = cdf(rz-rp) + cdf(rz-rt) period.num_retplayers = sum([1 if p['rating'] and len(p['wins']) > 0 else 0 for p in players.values()]) period.num_newplayers = sum([1 if not p['rating'] and len(p['wins']) > 0 else 0 for p in players.values()]) period.num_games = ngames period.computed = True period.needs_recompute = False period.save() Rating.objects.filter(period=period).update( position=None, position_vp=None, position_vt=None, position_vz=None ) cur = connection.cursor() cur.execute('''
def mean(a): return sum([f.rating for f in a]) / len(a) rp = mean( filter_active(Rating.objects.filter( period=period, player__race=P)).order_by('-rating')[:5]) rt = mean( filter_active(Rating.objects.filter( period=period, player__race=T)).order_by('-rating')[:5]) rz = mean( filter_active(Rating.objects.filter( period=period, player__race=Z)).order_by('-rating')[:5]) period.dom_p = cdf(rp - rt) + cdf(rp - rz) period.dom_t = cdf(rt - rp) + cdf(rt - rz) period.dom_z = cdf(rz - rp) + cdf(rz - rt) period.num_retplayers = sum( [1 if p['rating'] and len(p['wins']) > 0 else 0 for p in players.values()]) period.num_newplayers = sum([ 1 if not p['rating'] and len(p['wins']) > 0 else 0 for p in players.values() ]) period.num_games = ngames period.computed = True period.needs_recompute = False period.save() Rating.objects.filter(period=period).update(position=None,
def update(myr, mys, oppr, opps, oppc, W, L, text='', pr=False, Ncats=3): """This function updates the rating of a player according to the ratings of the opponents and the games against them.""" if len(W) == 0: return(myr, mys) if pr: print(text) print(oppr, len(oppr)) print(opps, len(opps)) print(oppc, len(oppc)) print(W, len(W)) print(L, len(L)) played_cats = sorted(unique(oppc)) # The categories against which the player played played_cats_p1 = [p+1 for p in played_cats] tot = sum(myr[array(played_cats)+1]) # The sum relative rating against those categories # (will be kept constant) M = len(W) # Number of opponents C = len(played_cats) # Number of different categories played # Convert global categories to local def loc(x): return array([played_cats.index(c) for c in x]) # Convert local categories to global def glob(x): return array([played_cats[c] for c in x]) # Extends a M-vector to an M+1-vector according to the restriction given # (that the sum of relative ratings against the played categories is constant) def extend(x): return hstack((x, tot-sum(x[1:]))) # Ensure that arrays are 1-dimensional def dim(x): if x.ndim == 0: x = array([x]) return x # Prepare some vectors and other numbers that are needed to form objective functions, derivatives and # Hessians DM = zeros((M,C)) DMex = zeros((M,C+1)) DM[:,0] = 1 DMex[:,0] = 1 for j in range(0,M): lc = loc([oppc[j]])[0] if lc < C-1: DM[j,lc+1] = 1 else: DM[j,1:] = -1 DMex[j,lc+1] = 1 mbar = oppr sbar = sqrt(opps**2 + 1) gen_phi = lambda j, x: pdf(x, loc=mbar[j], scale=sbar[j]) gen_Phi = lambda j, x: max(min(cdf(x, loc=mbar[j], scale=sbar[j]), 1-LOG_CAP), LOG_CAP) alpha = pi/2/sqrt(3) myrc = myr[[0]+played_cats_p1] mysc = mys[[0]+played_cats_p1] # {{{ Objective function def logL(x): Mv = x[0] + extend(x)[loc(oppc)+1] Phi = array([gen_Phi(i,Mv[i]) for i in range(0,M)]) if pr: print(':::', x, Mv, Phi) return sum(W*log(Phi) + L*log(1-Phi)) def logE(x): return sum(log(1 - tanh(alpha*(extend(x)-myrc)/mysc)**2)) logF = lambda x: logL(x) + logE(x) # }}} # {{{ Derivative def DlogL(x): Mv = x[0] + extend(x)[loc(oppc)+1] phi = array([gen_phi(i,Mv[i]) for i in range(0,M)]) Phi = array([gen_Phi(i,Mv[i]) for i in range(0,M)]) vec = (W/Phi - L/(1-Phi)) * phi return array(vec * matrix(DM))[0] def DlogE(x): ret = -2*alpha*tanh(alpha*(extend(x)-myrc)/mysc)/mysc ret = ret[0:-1] - ret[-1] return ret DlogF = lambda x: DlogL(x) + DlogE(x) # }}} # {{{ Hessian def D2logL(x, DM, C): Mv = x[0] + extend(x)[loc(oppc)+1] phi = array([gen_phi(i,Mv[i]) for i in range(0,M)]) Phi = array([gen_Phi(i,Mv[i]) for i in range(0,M)]) alpha = phi/Phi beta = phi/(1-Phi) Mvbar = pi/sqrt(3)/sbar * tanh(pi/2/sqrt(3)*(Mv-mbar)/sbar) coeff = - W*alpha*(alpha+Mvbar) - L*beta*(beta-Mvbar) ret = zeros((C,C)) for j in range(0,M): ret += coeff[j] * outer(DM[j,:], DM[j,:]) return ret def D2logE(x): diags = -2*alpha**2*(1 - tanh(alpha*(extend(x)-myrc)/mysc)**2)/mysc**2 diags, final = diags[0:-1], diags[-1] return diag(diags) + final def D2logEx(x): diags = -2*alpha**2*(1 - tanh(alpha*(extend(x)-myrc)/mysc)**2)/mysc**2 return diag(diags) D2logF = lambda x: D2logL(x,DM,C) + D2logE(x) # }}} # Prepare initial guess in unrestricted format and maximize x = hstack((myr[0], myr[played_cats_p1]))[0:-1] x = maximize(logF, DlogF, D2logF, x, disp=pr) x = dim(x) # If maximization failed, return the current rating and print an error message if x == None: print('Failed to converge for %s' % text) return (myr, mys, [None]*(Ncats+1), [None]*(Ncats+1)) # Extend to restricted format D2 = D2logL(x, DMex, C+1) + D2logEx(x) devs = sqrt(-1/diag(D2)) rats = extend(x) if pr: print(devs) print(rats) # Compute new RD and rating for the indices that can change news = zeros(len(myr)) newr = zeros(len(myr)) ind = [0] + [f+1 for f in played_cats] news[ind] = devs newr[ind] = rats if pr: print(news) print(newr) # Enforce the restriction of sum relative rating against played categories should be constant ind = ind[1:] m = (sum(newr[ind]) - tot)/len(ind) newr[ind] -= m newr[0] += m if pr: print(newr) # Ratings against non-played categories should be kept as before. ind = setdiff1d(range(0,len(myr)), [0] + ind) news[ind] = mys[ind] newr[ind] = myr[ind] if pr: print(news) print(newr) # Keep new RDs between MIN_DEV and INIT_DEV news = minimum(news, INIT_DEV) news = maximum(news, MIN_DEV) if pr: print(news) # Ensure that mean relative rating is zero m = mean(newr[1:]) newr[1:] -= m newr[0] += m if pr: print(newr) print('------------ Finished') return (newr, news)
def adjustment(request, player_id, period_id): # {{{ Get objects period = get_object_or_404(Period, id=period_id, computed=True) player = get_object_or_404(Player, id=player_id) rating = get_object_or_404(Rating, player=player, period=period) base = base_ctx('Ranking', 'Adjustments', request, context=player) base.update({ 'period': period, 'player': player, 'rating': rating, 'prevlink': etn(lambda: player.rating_set.filter(period__lt=period, decay=0). latest('period')), 'nextlink': etn(lambda: player.rating_set.filter(period__gt=period, decay=0). earliest('period')), }) # }}} # {{{ Matches matches = player.get_matchset( related=['rta', 'rtb', 'pla', 'plb', 'eventobj']).filter(period=period) # If there are no matches, we don't need to continue if not matches.exists(): return render_to_response('ratingdetails.djhtml', base) base.update({ 'matches': display_matches(matches, fix_left=player, ratings=True), 'has_treated': False, 'has_nontreated': False, }) # }}} # {{{ Perform calculations tot_rating = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} ngames = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} expwins = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} nwins = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} for m in base['matches']: if not m['match'].treated: base['has_nontreated'] = True continue base['has_treated'] = True total_score = m['pla']['score'] + m['plb']['score'] scale = sqrt(1 + m['pla']['dev']**2 + m['plb']['dev']**2) expected = total_score * cdf(m['pla']['rating'] - m['plb']['rating'], scale=scale) ngames['M'] += total_score tot_rating['M'] += m['plb']['rating'] * total_score expwins['M'] += expected nwins['M'] += m['pla']['score'] vs_races = [m['plb']['race']] if m['plb']['race'] in 'PTZ' else 'PTZ' weight = 1 / len(vs_races) for r in vs_races: ngames[r] += weight * total_score tot_rating[r] += weight * m['plb']['rating'] * total_score expwins[r] += weight * expected nwins[r] += weight * m['pla']['score'] for r in 'MPTZ': if ngames[r] > 0: tot_rating[r] /= ngames[r] base.update({ 'ngames': ngames, 'tot_rating': tot_rating, 'expwins': expwins, 'nwins': nwins, }) # }}} return render_to_response('ratingdetails.djhtml', base)
def adjustment(request, player_id, period_id): # {{{ Get objects period = get_object_or_404(Period, id=period_id, computed=True) player = get_object_or_404(Player, id=player_id) rating = get_object_or_404(Rating, player=player, period=period) base = base_ctx("Ranking", "Adjustments", request, context=player) base.update( { "period": period, "player": player, "rating": rating, "prevlink": etn(lambda: player.rating_set.filter(period__lt=period, decay=0).latest("period")), "nextlink": etn(lambda: player.rating_set.filter(period__gt=period, decay=0).earliest("period")), } ) # }}} # {{{ Matches matches = player.get_matchset(related=["rta", "rtb", "pla", "plb", "eventobj"]).filter(period=period) # If there are no matches, we don't need to continue if not matches.exists(): return render_to_response("ratingdetails.djhtml", base) base.update( { "matches": display_matches(matches, fix_left=player, ratings=True), "has_treated": False, "has_nontreated": False, } ) # }}} # {{{ Perform calculations tot_rating = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0} ngames = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0} expwins = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0} nwins = {"M": 0.0, "P": 0.0, "T": 0.0, "Z": 0.0} for m in base["matches"]: if not m["match"].treated: base["has_nontreated"] = True continue base["has_treated"] = True total_score = m["pla"]["score"] + m["plb"]["score"] scale = sqrt(1 + m["pla"]["dev"] ** 2 + m["plb"]["dev"] ** 2) expected = total_score * cdf(m["pla"]["rating"] - m["plb"]["rating"], scale=scale) ngames["M"] += total_score tot_rating["M"] += m["plb"]["rating"] * total_score expwins["M"] += expected nwins["M"] += m["pla"]["score"] vs_races = [m["plb"]["race"]] if m["plb"]["race"] in "PTZ" else "PTZ" weight = 1 / len(vs_races) for r in vs_races: ngames[r] += weight * total_score tot_rating[r] += weight * m["plb"]["rating"] * total_score expwins[r] += weight * expected nwins[r] += weight * m["pla"]["score"] for r in "MPTZ": if ngames[r] > 0: tot_rating[r] /= ngames[r] base.update({"ngames": ngames, "tot_rating": tot_rating, "expwins": expwins, "nwins": nwins}) # }}} return render_to_response("ratingdetails.djhtml", base)
def rating_details(request, player_id, period_id): period_id = int(period_id) player_id = int(player_id) period = get_object_or_404(Period, id=period_id, computed=True) player = get_object_or_404(Player, id=player_id, rating__period=period) rating = get_object_or_404(Rating, player=player, period=period) base = base_ctx('Ranking', 'Adjustments', request, context=player) try: nextlink = Rating.objects.filter(player=player, period__id__gt=period_id,\ decay=0).order_by('period__id')[0] except: nextlink = None try: prevlink = Rating.objects.filter(player=player, period__id__lt=period_id,\ decay=0).order_by('-period__id')[0] except: prevlink = None races = ['P','T','Z'] prev = rating.get_prev() if prev != None: prevrat = [prev.get_rating(), {}] prevdev = [prev.get_dev(), {}] for r in races: prevrat[1][r] = prev.get_totalrating(r) prevdev[1][r] = prev.get_totaldev(r) else: prevrat = [0., {'P': 0., 'T': 0., 'Z': 0.}] prevdev = [RATINGS_INIT_DEV, {'P': RATINGS_INIT_DEV, 'T': RATINGS_INIT_DEV, 'Z': RATINGS_INIT_DEV}] matches = Match.objects.filter(Q(pla=player) | Q(plb=player)).filter(period=period)\ .select_related('pla__rating').select_related('plb__rating').order_by('-date', '-id') if not matches.exists(): base.update({'period': period, 'player': player, 'prevlink': prevlink, 'nextlink': nextlink}) return render_to_response('ratingdetails.html', base) matches = display_matches(matches, fix_left=player, ratings=True) tot_rating = [0.0, {'P': 0.0, 'T': 0.0, 'Z': 0.0}] ngames = [0, {'P': 0, 'T': 0, 'Z': 0}] nwins = [0, {'P': 0, 'T': 0, 'Z': 0}] nlosses = [0, {'P': 0, 'T': 0, 'Z': 0}] expwins = [0.0, {'P': 0.0, 'T': 0.0, 'Z': 0.0}] treated = False nontreated = False for m in matches: if not m.treated: nontreated = True continue treated = True tot_rating[0] += m.plb_rating * (m.pla_score + m.plb_score) ngames[0] += m.pla_score + m.plb_score nwins[0] += m.pla_score nlosses[0] += m.plb_score scale = sqrt(1 + m.pla_dev**2 + m.pla_dev**2) races = [m.plb_race] if m.plb_race in ['P','T','Z'] else ['P','T','Z'] weight = float(1)/len(races) for sr in races: ew = (m.pla_score + m.plb_score) * cdf(m.pla_rating - m.plb_rating, scale=scale) expwins[0] += weight * ew expwins[1][sr] += weight * ew tot_rating[1][sr] += weight * m.plb_rating * (m.pla_score + m.plb_score) ngames[1][sr] += weight * (m.pla_score + m.plb_score) nwins[1][sr] += weight * m.pla_score nlosses[1][sr] += weight * m.plb_score base.update({'period': period, 'player': player, 'rating': rating, 'matches': matches, 'treated': treated,\ 'nontreated': nontreated, 'prevlink': prevlink, 'nextlink': nextlink}) if not treated: return render_to_response('ratingdetails.html', base) else: tot_rating[0] /= ngames[0] for r in ['P','T','Z']: if ngames[1][r] > 0: tot_rating[1][r] /= ngames[1][r] explosses = [ngames[0]-expwins[0], {}] exppctg = [expwins[0]/ngames[0]*100, {}] pctg = [float(nwins[0])/ngames[0]*100, {}] diff = [rating.rating-prevrat[0], {}] modded = False for r in ['P','T','Z']: explosses[1][r] = ngames[1][r] - expwins[1][r] if ngames[1][r] > 0: exppctg[1][r] = expwins[1][r]/ngames[1][r]*100 pctg[1][r] = float(nwins[1][r])/ngames[1][r]*100 diff[1][r] = rating.get_totalrating(r) - prevrat[1][r] if (nwins[1][r] != 0) != (nlosses[1][r] != 0): modded = True base.update({'tot_rating': tot_rating, 'ngames': ngames, 'nwins': nwins, 'nlosses': nlosses,\ 'prevrat': prevrat, 'pctg': pctg,\ 'exppctg': exppctg, 'diff': diff, 'expwins': expwins, 'explosses': explosses,\ 'prevdev': prevdev, 'modded': modded}) return render_to_response('ratingdetails.html', base)
def prob_of_winning(self, opponent): my_elo = self.elo_vs_opponent(opponent) op_elo = opponent.elo_vs_opponent(self) my_dev = self.dev_vs_opponent(opponent) op_dev = opponent.dev_vs_opponent(self) return cdf(my_elo - op_elo, scale=sqrt(1 + my_dev + op_dev))
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)''', insert_qvals) # Set all matches to treated Match.objects.filter(period=period).update(treated=True) # Compute OP/UP race def mean(a): return sum([f.rating for f in a])/len(a) rp = mean(Rating.objects.filter(period=period, player__race='P', decay__lt=4).order_by('-rating')[:5]) rt = mean(Rating.objects.filter(period=period, player__race='T', decay__lt=4).order_by('-rating')[:5]) rz = mean(Rating.objects.filter(period=period, player__race='Z', decay__lt=4).order_by('-rating')[:5]) sp = cdf(rp-rt) + cdf(rp-rz) st = cdf(rt-rp) + cdf(rt-rz) sz = cdf(rz-rp) + cdf(rz-rt) period.dom_p = sp period.dom_t = st period.dom_z = sz # Write some period statistics period.num_retplayers = num_retplayers period.num_newplayers = num_newplayers period.num_games = num_games period.computed = True period.needs_recompute = False period.save() # Write ranks
def adjustment(request, player_id, period_id): # {{{ Get objects period = get_object_or_404(Period, id=period_id, computed=True) player = get_object_or_404(Player, id=player_id) rating = get_object_or_404(Rating, player=player, period=period) base = base_ctx('Ranking', 'Adjustments', request, context=player) base.update({ 'period': period, 'player': player, 'rating': rating, 'prevlink': etn(lambda: player.rating_set.filter(period__lt=period, decay=0).latest('period')), 'nextlink': etn(lambda: player.rating_set.filter(period__gt=period, decay=0).earliest('period')), }) # }}} # {{{ Matches matches = player.get_matchset(related=['rta','rtb','pla','plb','eventobj']).filter(period=period) base.update({"title": player.tag}) # If there are no matches, we don't need to continue if not matches.exists(): return render_to_response('ratingdetails.html', base) base.update({ 'matches': display_matches(matches, fix_left=player, ratings=True), 'has_treated': False, 'has_nontreated': False, }) # }}} # {{{ Perform calculations tot_rating = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} ngames = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} expwins = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} nwins = {'M': 0.0, 'P': 0.0, 'T': 0.0, 'Z': 0.0} for m in base['matches']: if not m['match'].treated: base['has_nontreated'] = True continue base['has_treated'] = True total_score = m['pla']['score'] + m['plb']['score'] scale = sqrt(1 + m['pla']['dev']**2 + m['plb']['dev']**2) expected = total_score * cdf(m['pla']['rating'] - m['plb']['rating'], scale=scale) ngames['M'] += total_score tot_rating['M'] += m['plb']['rating'] * total_score expwins['M'] += expected nwins['M'] += m['pla']['score'] vs_races = [m['plb']['race']] if m['plb']['race'] in 'PTZ' else 'PTZ' weight = 1/len(vs_races) for r in vs_races: ngames[r] += weight * total_score tot_rating[r] += weight * m['plb']['rating'] * total_score expwins[r] += weight * expected nwins[r] += weight * m['pla']['score'] for r in 'MPTZ': if ngames[r] > 0: tot_rating[r] /= ngames[r] base.update({ 'ngames': ngames, 'tot_rating': tot_rating, 'expwins': expwins, 'nwins': nwins, }) # }}} return render_to_response('ratingdetails.html', base)
def performance(oppr, opps, oppc, W, L, text='', pr=False): opp = list(zip(oppr, opps, oppc, W, L)) ret = [0.0, 0.0, 0.0, 0.0] meanok = True if pr: print('Now performance for %s' % text) for cat in range(0,3): spopp = [o for o in opp if o[2] == cat] sW = sum([o[3] for o in spopp]) sL = sum([o[4] for o in spopp]) if sW == 0 and sL == 0: ret[cat+1] = PRF_NA meanok = False elif sW == 0: ret[cat+1] = PRF_MININF meanok = False elif sL == 0: ret[cat+1] = PRF_INF meanok = False else: gen_phi = lambda p, x: pdf(x, loc=p[0], scale=sqrt(1+p[1]**2)) gen_Phi = lambda p, x: max(min(cdf(x, loc=p[0], scale=sqrt(1+p[1]**2)), 1-LOG_CAP), LOG_CAP) def logL(x): ret = 0.0 for p in spopp: gP = gen_Phi(p,x) ret += p[3] * log(gP) + p[4] * log(1-gP) return ret def DlogL(x): ret = 0.0 for p in spopp: gp = gen_phi(p,x) gP = gen_Phi(p,x) ret += (float(p[3])/gP - float(p[4])/(1-gP)) * gp return ret def D2logL(x): ret = 0.0 for p in spopp: gp = gen_phi(p,x) gP = gen_Phi(p,x) alpha = gp/gP beta = gp/(1-gP) sb = sqrt(1+p[1]**2) Mv = pi/sqrt(3)/sb * tanh(pi/2/sqrt(3)*(x-p[0])/sb) ret -= p[3]*alpha*(alpha+Mv) + p[4]*beta*(beta-Mv) return ret perf, init = nan, 1.0 while isnan(perf): perf = maximize_1d(logL, DlogL, D2logL, init) init -= 0.1 ret[cat+1] = perf if meanok: ret[0] = sum(ret[1:]) / 3 else: ret[0] = PRF_NA return ret