0

I've been searching for days but I just can't find the correct solution. I'm better in maths than I am in Python.

I have a script, called "tennisTotal.py". This is a probability calculator for Tennis Matches. In this calculator I have 11 variable fields.

s_point=0
v_game_point=0
w_game_point=0
v_tiebreak=0
w_tiebreak=0
returnpoint_server=0.30
v_games_in_set=0
w_games_in_set=0
v_sets_won=0
w_sets_won=0
best_of=5

I would like those fields to be populated with input form a GUI. (The GUI is still in development, more fields need to be added)

Where I want to go to is when I put a value in the GUI, for example "Service Points Won" that this value comes up in the "s_point" field. Same goes for the value in the GUI "Return Points Won", I want this value to appear in the "returnpoint_server"

My question is than, how do I get those values from my GUI into my "probability" calculator?

GUI Script

from Tkinter import *

fields = 'Service Points Won', 'Return Points Won'

def fetch(variables):
    for variable in variables:
        print  "%s" % variable.get()    

def makeform(root, fields):
    lab1= Label(text="Stats", font="Verdana 10 bold")
    form = Frame(root)                              
    left = Frame(form)
    rite = Frame(form)
    lab1.pack(side=TOP)
    form.pack(fill=X) 
    left.pack(side=LEFT)
    rite.pack(side=RIGHT)

    variables = []
    for field in fields:
        lab1= Label()
        lab = Label(left, text=field)
        ent = Entry(rite)
        lab.pack(anchor='w')
        ent.pack(fill=X)
        var = StringVar()
        ent.config(textvariable=var)
        var.set('0.5')
        variables.append(var)
    return variables


if __name__ == '__main__':
    root = Tk()
    vars = makeform(root, fields)
    Button(root, text='Fetch', 
                 command=(lambda v=vars: fetch(v))).pack()
    root.bind('<Return>', (lambda event, v=vars: fetch(v)))   
    root.mainloop()

Probability Script

s_point=0
v_game_point=0
w_game_point=0
v_tiebreak=0
w_tiebreak=0
returnpoint_server=0.30
v_games_in_set=0
w_games_in_set=0
v_sets_won=0
w_sets_won=0
best_of=5


def fact(x):
    if x in[0, 1]:
        return 1
    r = 1
    for a in range(1, (x+1)):
        r = r*a
    return r


def ch(a, b):
    return fact(a)/(fact(b)*fact(a-b))


def gameOutcome(s, a, b):
    return ch((a+b), a)*(s**a)*((1-s)**b)*s

# Game Probability
def gameProb(s=s_point, v=v_game_point, w=w_game_point):
    # function calculates the probability of server winning
    # a single game, given p(winning any given point) [s],
    # and the current point score.
    # v, w = current game score, where love = 0, 15 = 1, etc.
    # - e.g. 30-15 is v=2, w=1
    # check if game is already over:
    if v >= 4 and (v-w) >= 2:
        return 1
    elif w >= 4 and (w-v) >= 2:
        return 0
    else:
        pass
    # if deuce or ad score e.g. 5-4, reduce to e.g. 3-2
    while True:
        if (v+w) > 6:
            v -= 1
            w -= 1
        else:
            break
    # specific probabilities:
    if w == 0:
        w0 = gameOutcome(s, 3-v, 0)
    else:
        w0 = 0
    if w <= 1:
        w15 = gameOutcome(s, 3-v, 1-w)
    else:
        w15 = 0
    if w <= 2:
        w30 = gameOutcome(s, 3-v, 2-w)
    else:
        w30 = 0
    if v == 4:
        wAd, lAd = s, 0
        d = 1-s
    elif w == 4:
        wAd, lAd = 0, 1-s
        d = s
    else:
        wAd, lAd = 0, 0
        a = 3 - v
        b = 3 - w
        d = ch((a+b), a)*(s**a)*((1-s)**b)
    if v <= 2:
        l30 = gameOutcome((1-s), 3-w, 2-v)
    else:
        l30 = 0
    if v <= 1:
        l15 = gameOutcome((1-s), 3-w, 1-v)
    else:
        l15 = 0
    if v == 0:
        l0 = gameOutcome((1-s), 3-w, 0)
    else:
        l0 = 0
    # given d = prob of getting to deuce,
    # math to divide up further outcomes
    denom = s**2 + (1-s)**2
    wd = (d*(s**2))/denom
    ld = (d*((1-s)**2))/denom
    win = w0 + w15 + w30 + wd + wAd
    lose = l0 + l15 + l30 + ld + lAd
    return win

# Tiebreak Probability
def tiebreakProb(s=s_point, t=returnpoint_server, v=v_tiebreak, w=w_tiebreak, p=7):
    # calculate the probability that the current server wins a best-of-p
    # tiebreak.
    # s = p(server wins service point)
    # t = p(current server wins return point)
    # v, w = current score
    # check if tiebreak is already over:
    if v >= p and (v-w) >= 2:
        return 1
    elif w >= p and (w-v) >= 2:
        return 0
    else:
        pass
    # re-adjust so that point score is not higher than p;
    # e.g., if p=7 and score is 8-8, adjust to 6-6, which
    # is logically equivalent
    while True:
        if (v+w) > 2*(p-1):
            v -= 1
            w -= 1
        else:
            break
    outcomes = {}
    # track probability of each possible score
    # this is messy and probably not optimal, figuring out
    # how many points remain, and how many are on each
    # player's serve:
    for i in range((p-1)):
        remain = p + i - v - w
        if remain < 1:
            continue
        else:
            pass
        if remain % 2 == 1:
            if (v+w) % 2 == 0:
                if (remain-1) % 4 == 0:
                    svc = (remain+1)/2
                    ret = (remain-1)/2
                else:
                    svc = (remain-1)/2
                    ret = (remain+1)/2
            else:
                if (remain-1) % 4 == 0:
                    svc = (remain+1)/2
                    ret = (remain-1)/2
                else:
                    svc = (remain+1)/2
                    ret = (remain-1)/2
        else:
            if (v+w) % 2 == 0:
                    svc, ret = remain/2, remain/2
            else:
                svc, ret = (remain-2)/2, (remain-2)/2
                if remain % 4 == 0:
                    svc += 1
                    ret += 1
                else:
                    svc += 2
        # who serves the last point?
        if (v+w) % 2 == 0:
            if (remain % 4) in [0, 1]:
                final = s
                svc -= 1
            else:
                final = t
                ret -= 1
        else:
            if (remain % 4) in [3, 0]:
                final = t
                ret -= 1
            else:
                final = s
                svc -= 1
        pOutcome = 0
        for j in range(svc+1):
            for k in range(ret+1):
                if (j+k) == (p - 1 - v):
                    m = svc - j
                    n = ret - k
                    pr = (s**j)*(t**k)*((1-s)**m)*((1-t)**n)*ch(svc, j)*ch(ret, k)*final
                    pOutcome += pr
                else:
                    continue
        key = str(p) + str(i)
        outcomes[key] = pOutcome
    if remain % 2 == 1:
        if (v+w) % 2 == 0:
            if (remain-1) % 4 == 0:
                svc = (remain+1)/2
                ret = (remain-1)/2
            else:
                svc = (remain-1)/2
                ret = (remain+1)/2
        else:
            if (remain-1) % 4 == 0:
                svc = (remain+1)/2
                ret = (remain-1)/2
            else:
                svc = (remain+1)/2
                ret = (remain-1)/2
    else:
        if (v+w) % 2 == 0:
            svc, ret = remain/2, remain/2
        else:
            svc, ret = (remain-2)/2, (remain-2)/2
            if remain % 4 == 0:
                svc += 1
                ret += 1
            else:
                svc += 2
    # probability of getting to (p-1)-(p-1) (e.g. 6-6)
    final = 1
    x = 0
    for j in range(svc+1):
        for k in range(ret+1):
            if (j+k) == (p - 1 - v):
                m = svc - j
                n = ret - k
                pr = (s**j)*(t**k)*((1-s)**m)*((1-t)**n)*ch(svc, j)*ch(ret, k)*final
                x += pr
            else:
                continue
    outcomes['+'] = (x*s*t)/((s*t) + (1-s)*(1-t))
    # add up all positive outcomes
    wtb = 0
    for z in outcomes:
        wtb += outcomes[z]
    return wtb

# Set Probability
def setOutcome(final, sGames, rGames, vw, g, h):
    pOutcome = 0
    for j in range((sGames+1)):
        for k in range((rGames+1)):
            if (j + k) == (6 - 1 - vw):
                m = sGames - j
                n = rGames - k
                p = (g**j)*(h**k)*((1-g)**m)*((1-h)**n)*ch(sGames, j)*ch(rGames, k)*final
                pOutcome += p
            else:
                continue
    return pOutcome


def setGeneral(s=s_point, u=returnpoint_server, v=v_games_in_set, w=w_games_in_set, 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
            else:
                outcomes['57'] = 1-g
                outcomes['75'] = 0
                f = g
            outcomes['75'] += f*deuceprob
            outcomes['57'] += f*(1-deuceprob)
    else:
        for i in range(5):
            t = 6 + i - v - w
            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
            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
        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
            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

#Match Probability
def matchGeneral(e, v=0, w=0, s=3):
    # calculates probability of winning the match
    # from the beginning of a set
    # e is p(winning a set)
    # v and w is current set score
    # s is total number of sets ("best of")
    towin = (s+1)/2
    left = towin - v
    if left == 0:
        return 1
    remain = s - v - w
    if left > remain:
        return 0
    win = 0
    for i in range(left, (remain+1)):
        add = ch((i-1), (left-1))*(e**(left-1))*((1-e)**(i-left))*e
        win += add
    return win


def matchProb(s=s_point, t=returnpoint_server, gv=v_game_point, gw=w_game_point, sv=v_games_in_set, sw=w_games_in_set, mv=v_sets_won, mw=w_sets_won, sets=best_of):
    # 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:
        if sv == 0 and sw == 0:
            return matchGeneral(c, v=mv, w=mw, s=sets)
        else:
            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, sLoss
print "Server Game = ""{0:.2%}".format(gameProb())
print "Receiver Game = ""{0:.2%}".format(1-gameProb())
print "Server Tiebreak = ""{0:.2%}".format(tiebreakProb())
print "Receiver Tiebreak = ""{0:.2%}".format(1-tiebreakProb())
print "Server Set = ""{0:.2%}".format(setGeneral())
print "Receiver Set = ""{0:.2%}".format(1-setGeneral())
print "Server Match = ""{0:.2%}".format(matchProb())
print "Receiver Match= ""{0:.2%}".format(1-matchProb())

1 Answer 1

1

You could turn your probability script into a class and then create the class object each time you want to run it. For this I would also turn your GUI into a class so that passing your variables into some button function that runs the second script is simpler.

Convert your probability script into a class:

class probScript():

    def __init__(self, s_point, v_game_point, w_game_point, v_tiebreak, ...):
        self.s_point=s_point
        self.v_game_point=v_game_point
        self.w_game_point=w_game_point
        ...

        run_method()

Im not overly familiar with Tkinter but adding a button to run the script with the current GUI inputs should work. If you call your probability script method in the __init__() of the class (run_method() here) then all you have to do is create the object in your button function for it to be run.

button = Tkinter.Button(text="Check Probability", command=self.run_prob_script)
button.pack()
root.mainloop()

def run_prob_script(self):
    prob_script = probScript(self.input_1, self.input_2, ...)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.