def matchProb(s, t, gv=0, gw=0, sv=0, sw=0, mv=0, mw=0, sets=3):
    ## calculates probability of winning a match from any given score,
    ## given:
    ## s, t: p(server wins a service point), p(server wins return point)
    ## gv, gw: current score within the game. e.g. 30-15 is 2, 1
    ## sv, sw: current score within the set. e.g. 5, 4
    ## mv, mw: current score within the match (number of sets for each player)
    ## v's are serving player; w's are returning player
    ## sets: "best of", so default is best of 3
    a = gameProb(s)
    b = gameProb(t)
    c = setGeneral(s, t)
    #print 'set prob: ',c[0]
    if gv == 0 and gw == 0: ## no point score
        if sv == 0 and sw == 0: ## no game score
            #print 'mwin: ', matchGeneral(c[0], v=mv, w=mw, s=sets)
            return matchGeneral(c[0], v=mv, w=mw, s=sets)
        else:   ## we're in mid-set, no point score
            sWin = setGeneral(s, t, v=sv, w=sw)[0]
            sLoss = 1 - sWin
    elif sv == 6 and sw == 6:
        sWin = tiebreakProb(s, t, v=gv, w=gw)
        sLoss = 1 - sWin
    else:
        gWin = gameProb(s, v=gv, w=gw)
        gLoss = 1 - gWin
        sWin = gWin*(1 - setGeneral(1-t, 1-s, v=sw, w=sv+1)[0])
        sWin += gLoss*(1 - setGeneral(1-t, 1-s, v=sw+1, w=sv)[0])
        sLoss = 1 - sWin
    mWin = sWin*matchGeneral(c[0], v=mv+1, w=mw, s=sets)
    mWin += sLoss*matchGeneral(c[0], v=mv, w=mw+1, s=sets)
    #print 'mwin: ', mWin
    return mWin
def matchProb(s, t, gv=0, gw=0, sv=0, sw=0, mv=0, mw=0, sets=3):
    ## calculates probability of winning a match from any given score,
    ## given:
    ## s, t: p(server wins a service point), p(server wins return point)
    ## gv, gw: current score within the game. e.g. 30-15 is 2, 1
    ## sv, sw: current score within the set. e.g. 5, 4
    ## mv, mw: current score within the match (number of sets for each player)
    ## v's are serving player; w's are returning player
    ## sets: "best of", so default is best of 3
    a = gameProb(s)
    b = gameProb(t)
    c = setGeneral(s, t)
    if gv == 0 and gw == 0: ## no point score
        if sv == 0 and sw == 0: ## no game score
            return matchGeneral(c, v=mv, w=mw, s=sets)
        else:   ## we're in mid-set, no point score
            sWin = setGeneral(a, b, s, t, v=sv, w=sw)
            sLoss = 1 - sWin
    elif sv == 6 and sw == 6:         
        sWin = tiebreakProb(s, t, v=gv, w=gw)
        sLoss = 1 - sWin       
    else:
        gWin = gameProb(s, v=gv, w=gw)
        gLoss = 1 - gWin
        sWin = gWin*(1 - setGeneral((1-b), (1-a), (1-t), (1-s), v=sw, w=(sv+1)))
        sWin += gLoss*(1 - setGeneral((1-b), (1-a), (1-t), (1-s), v=(sw+1), w=sv))
        sLoss = 1 - sWin
    mWin = sWin*matchGeneral(c, v=(mv+1), w=mw, s=sets)
    mWin += sLoss*matchGeneral(c, v=mv, w=(mw+1), s=sets)
    return mWin
def setGeneral(s, u, v=0, w=0, tb=1):
    ## calculate the probability of the current server winning
    ## a 6-game, tiebreak set, given prob. of server winning any
    ## given service point (s) or return point (u), and the current
    ## game score (v, w)
    ## get prob of current server winning a service game:
    g = gameProb(s)
    ## and current server winning a return game:
    h = gameProb(u)
    ## is set over?
    if tb:
        if v == 7:  return 1
        elif w == 7:    return 0
        elif v == 6 and (v-w) > 1:  return 1
        elif w == 6 and (w-v) > 1:  return 0
        else:   pass
    else:
        if v >= 6 and (v-w) > 1:    return 1
        elif w >= 6 and (w-v) > 1:  return 0
        else:   pass
    ## if not over, re-adjust down to no higher than 6-6
    while True:
        if (v+w) > 12:
            v -= 1
            w -= 1
        else:   break
    ## if no tiebreak, chance that server wins set is ratio of server's prob of winning
    ## two games in a row to returner's prob of winning two games in a row
    if not tb:  deuceprob = (g*h)/((g*h) + (1-g)*(1-h))
    outcomes = {}
    ## special cases, 11 games or more already
    if (v+w) == 12:
        if tb:
            tp = tiebreakProb(s, u)
            outcomes['76'] = tp
            outcomes['67'] = 1 - tp
        else:
            outcomes['75'] = deuceprob
            outcomes['57'] = 1-deuceprob 
    elif (v+w) == 11:
        if tb:
            tp = tiebreakProb((1-u), (1-s))
            if v == 6:
                outcomes['75'] = g
                x = (1-g)
                outcomes['76'] = x*(1 - tp)
                outcomes['67'] = x*tp
            else:
                outcomes['57'] = 1-g
                x = g
                outcomes['76'] = x*(1 - tp)
                outcomes['67'] = x*tp
        else:
            if v == 6:
                outcomes['75'] = g
                outcomes['57'] = 0
                f = 1 - g ## f is p(getting to 6-6)
            else:
                outcomes['57'] = 1-g
                outcomes['75'] = 0
                f = g ## f is p(getting to 6-6)
            outcomes['75'] += f*deuceprob
            outcomes['57'] += f*(1-deuceprob)            
    else:   
        ## win probabilities
        for i in range(5): ## i = 0
            t = 6 + i - v - w ## total games remaining in set
            if t < 1:   continue
            if t % 2 == 0:
                final = h
                sGames = t/2
                rGames = sGames - 1
            else:
                final = g
                sGames = (t-1)/2
                rGames = (t-1)/2
            pOutcome = setOutcome(final, sGames, rGames, v, g, h)
            key = '6' + str(i)
            outcomes[key] = pOutcome
        ## loss probabilities
        ## this section isn't necessary, but I wrote it for informal
        ## testing purposes
        for i in range(5):
            t = 6 + i - v - w ## total games in set; here it's 6
            if t < 1:   continue
            if t % 2 == 0:
                final = 1-h
                sGames = t/2
                rGames = sGames - 1
            else:
                final = 1-g
                sGames = (t-1)/2
                rGames = (t-1)/2
            pOutcome = setOutcome(final, sGames, rGames, w, (1-g), (1-h))
            key = str(i) + '6'
            outcomes[key] = pOutcome       
        ## prob of getting to 5-5
        t = 10 - v - w
        if t % 2 == 0:
            sGames = t/2
            rGames = t/2
        else:
            sGames = (t-1)/2 + 1
            rGames = (t-1)/2
        f = setOutcome(1, sGames, rGames, v, g, h)
        if tb == 1:
            outcomes['75'] = f*g*h
            outcomes['57'] = f*(1-g)*(1-h)
            x = f*g*(1-h) + f*(1-g)*h ## p(getting to 6-6)    
            if (v+w) % 2 == 0:
                tp = tiebreakProb(s, u)
            else:
                tp = tiebreakProb(u, s)
            outcomes['76'] = x*tp
            outcomes['67'] = x - x*tp
        else:
            outcomes['75'] = f*deuceprob
            outcomes['57'] = f*(1-deuceprob)        
    win = 0
    for o in outcomes:
        if o in ['60', '61', '62', '63', '64', '75', '76']:
            win += outcomes[o]
        else:   pass
    return win, outcomes
def setGeneral(s, u, v=0, w=0, tb=1):
    ## calculate the probability of the current server winning
    ## a 6-game, tiebreak set, given prob. of server winning any
    ## given service point (s) or return point (u), and the current
    ## game score (v, w)
    ## get prob of current server winning a service game:
    __ = ''  # dummy variable to address type issues
    g = gameProb(s)
    ## and current server winning a return game:
    h = gameProb(u)
    ## is set over?
    if tb:
        if v == 7: return 1, __
        elif w == 7: return 0, __
        elif v == 6 and (v - w) > 1: return 1, __
        elif w == 6 and (w - v) > 1: return 0, __
        else: pass
    else:
        if v >= 6 and (v - w) > 1: return 1, __
        elif w >= 6 and (w - v) > 1: return 0, __init__
        else: pass
    ## if not over, re-adjust down to no higher than 6-6
    while True:
        if (v + w) > 12:
            v -= 1
            w -= 1
        else:
            break
    ## if no tiebreak, chance that server wins set is ratio of server's prob of winning
    ## two games in a row to returner's prob of winning two games in a row
    if not tb: deuceprob = (g * h) / ((g * h) + (1 - g) * (1 - h))
    outcomes = {}
    ## special cases, 11 games or more already
    if (v + w) == 12:
        if tb:
            tp = tiebreakProb(s, u)
            outcomes['76'] = tp
            outcomes['67'] = 1 - tp
        else:
            outcomes['75'] = deuceprob
            outcomes['57'] = 1 - deuceprob
    elif (v + w) == 11:
        if tb:
            tp = tiebreakProb((1 - u), (1 - s))
            if v == 6:
                outcomes['75'] = g
                x = (1 - g)
                outcomes['76'] = x * (1 - tp)
                outcomes['67'] = x * tp
            else:
                outcomes['57'] = 1 - g
                x = g
                outcomes['76'] = x * (1 - tp)
                outcomes['67'] = x * tp
        else:
            if v == 6:
                outcomes['75'] = g
                outcomes['57'] = 0
                f = 1 - g  ## f is p(getting to 6-6)
            else:
                outcomes['57'] = 1 - g
                outcomes['75'] = 0
                f = g  ## f is p(getting to 6-6)
            outcomes['75'] += f * deuceprob
            outcomes['57'] += f * (1 - deuceprob)
    else:
        ## win probabilities
        for i in range(5):  ## i = 0
            t = 6 + i - v - w  ## total games remaining in set
            if t < 1: continue
            if t % 2 == 0:
                final = h
                sGames = t / 2
                rGames = sGames - 1
            else:
                final = g
                sGames = (t - 1) / 2
                rGames = (t - 1) / 2
            pOutcome = setOutcome(final, sGames, rGames, v, g, h)
            key = '6' + str(i)
            outcomes[key] = pOutcome
        ## loss probabilities
        ## this section isn't necessary, but I wrote it for informal
        ## testing purposes
        for i in range(5):
            t = 6 + i - v - w  ## total games in set; here it's 6
            if t < 1: continue
            if t % 2 == 0:
                final = 1 - h
                sGames = t / 2
                rGames = sGames - 1
            else:
                final = 1 - g
                sGames = (t - 1) / 2
                rGames = (t - 1) / 2
            pOutcome = setOutcome(final, sGames, rGames, w, (1 - g), (1 - h))
            key = str(i) + '6'
            outcomes[key] = pOutcome
        ## prob of getting to 5-5
        t = 10 - v - w
        if t % 2 == 0:
            sGames = t / 2
            rGames = t / 2
        else:
            sGames = (t - 1) / 2 + 1
            rGames = (t - 1) / 2
        f = setOutcome(1, sGames, rGames, v, g, h)
        if tb == 1:
            outcomes['75'] = f * g * h
            outcomes['57'] = f * (1 - g) * (1 - h)
            x = f * g * (1 - h) + f * (1 - g) * h  ## p(getting to 6-6)
            if (v + w) % 2 == 0:
                tp = tiebreakProb(s, u)
            else:
                tp = tiebreakProb(u, s)
            outcomes['76'] = x * tp
            outcomes['67'] = x - x * tp
        else:
            outcomes['75'] = f * deuceprob
            outcomes['57'] = f * (1 - deuceprob)
    win = 0
    for o in outcomes:
        if o in ['60', '61', '62', '63', '64', '75', '76']:
            win += outcomes[o]
        else:
            pass
    return win, outcomes