用作脚本变量的GUI输入 - Python

时间:2016-06-30 16:00:16

标签: python-2.7

我一直在寻找好几天,但我找不到正确的解决方案。 我在数学方面比在Python方面更好。

我有一个名为" tennisTotal.py"的脚本。这是网球比赛的概率计算器。 在这个计算器中,我有11个可变字段。

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

我希望这些字段可以通过GUI填充输入。 (GUI仍处于开发阶段,需要添加更多字段)

我想去的地方是我在GUI中放置一个值,例如"服务点赢了"这个值出现在" s_point"领域。 同样适用于GUI中的值"返回点赢了",我希望这个值出现在" returnpoint_server"

我的问题是,如何将我的GUI中的这些值转换为我的"概率"计算器吗

  

GUI脚本

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()
  

概率脚本

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 个答案:

答案 0 :(得分:1)

您可以将概率脚本转换为class,然后在每次要运行时创建class对象。为此,我还将您的GUI转换为class,以便将变量传递给运行第二个脚本的按钮函数更简单。

概率脚本转换为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()

我不太熟悉Tkinter但是添加一个按钮来运行当前GUI输入的脚本应该可行。如果您在__init__() class run_method()中调用概率脚本方法,那么您只需在按钮函数中创建对象即可运行。< / p>

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, ...)