Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
 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))
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
        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
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
 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))
Ejemplo n.º 8
0
                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('''
Ejemplo n.º 9
0

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,
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
 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))
Ejemplo n.º 15
0
                           %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
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
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