如何在 Python 中编写投注结算函数

How to write a bet settling function in Python

我正在尝试编写一个接受体育投注的函数和 returns 它的净结果。

虽然我设法完成了总投注,但我无法完成让分盘的投注结算,因为它导致了一些巨大的嵌套 if/else 语句墙。

如果您不熟悉博彩,详尽的测试套件应该有助于理解程序应该做什么。

主要问题是如何以不同于列举所有可能情况的方式解决这个问题。

非常感谢任何反馈。

SUPPORTED_BET_TYPES = ['total', 'handicap']
SIDES = ['home', 'away', 'over', 'under']
BET_OUTCOMES = ['Won', 'Lost', 'Cancelled', 'Half Won', 'Half Lost']


def settle_bet(bet_type, side, points, price, bet_amount, home_score, away_score):
    '''Returns a result of the bet'''

    if bet_type == 'total':
        return settle_total_bet(side, points, price, bet_amount, home_score, away_score)
    elif bet_type == 'handicap':
        return settle_handicap_bet(side, points, price, bet_amount, home_score, away_score)


def settle_total_bet(side, points, price, bet_amount, home_score, away_score):
    '''Returns Net result of the bet on total'''

    outcome = determine_total_bet_outcome(side, points, home_score, away_score)

    if outcome == 'Won':
        return bet_amount * (price - 1)
    elif outcome == 'Half Won':
        return bet_amount * ((price - 1) / 2)
    elif outcome == 'Cancelled':
        return 0
    elif outcome == 'Half Lost':
        return bet_amount * (-1 / 2)
    else:
        return bet_amount * -1


def determine_total_bet_outcome(side, points, home_score, away_score):
    '''Returns the appropriate outcome of the bet from BET_OUTCOMES'''

    total_score = home_score + away_score
    points_score_diff = points - total_score

    if points_score_diff == 0:
        return 'Cancelled'
    elif points_score_diff == 0.25:
        if side == 'over':
            return 'Half Lost'
        else:
            return 'Half Won'
    elif points_score_diff == -0.25:
        if side == 'over':
            return 'Half Won'
        else:
            return 'Half Lost'
    elif points_score_diff >= 0.5:
        if side == 'over':
            return 'Lost'
        else:
            return 'Won'
    elif points_score_diff <= -0.5:
        if side == 'over':
            return 'Won'
        else:
            return 'Lost'


def test():
    # Bets on Total

    # Won or Lost
    assert settle_bet('total', 'over', 2.5, 1.90, 100, 3, 2) == 100 * (1.90 - 1)
    assert settle_bet('total', 'over', 3.5, 1.85, 100, 0, 1) == 100 * -1
    assert settle_bet('total', 'under', 2.5, 1.94, 100, 0, 0) == 100 * (1.94 - 1)
    assert settle_bet('total', 'under', 3.5, 1.75, 100, 1, 3) == 100 * -1

    # Won or Lost Or Cancelled
    assert settle_bet('total', 'over', 3.0, 1.82, 100, 2, 2) == 100 * (1.82 - 1)
    assert settle_bet('total', 'over', 3.0, 1.82, 100, 1, 2) == 100 * 0
    assert settle_bet('total', 'over', 3.0, 1.82, 100, 0, 0) == 100 * -1

    assert settle_bet('total', 'under', 3.0, 1.82, 100, 2, 2) == 100 * -1
    assert settle_bet('total', 'under', 3.0, 1.82, 100, 1, 2) == 100 * 0
    assert settle_bet('total', 'under', 3.0, 1.82, 100, 0, 0) == 100 * (1.82 - 1)

    # Won or Lost or Half Won or Half Lost
    assert settle_bet('total', 'over', 2.25, 1.95, 100, 2, 1) == 100 * (1.95 - 1)
    assert settle_bet('total', 'over', 2.25, 1.90, 100, 0, 0) == 100 * -1
    assert settle_bet('total', 'over', 2.25, 1.80, 100, 1, 1) == 100 * (-1 / 2)

    assert settle_bet('total', 'under', 2.25, 1.95, 100, 2, 1) == 100 * -1
    assert settle_bet('total', 'under', 2.25, 1.90, 100, 0, 0) == 100 * (1.90 - 1)
    assert settle_bet('total', 'under', 2.25, 1.80, 100, 1, 1) == 100 * ((1.80 - 1) / 2)

    assert settle_bet('total', 'over', 2.75, 1.90, 100, 3, 3) == 100 * (1.90 - 1)
    assert settle_bet('total', 'over', 2.75, 1.88, 100, 1, 2) == 100 * ((1.88 - 1) / 2)
    assert settle_bet('total', 'over', 2.75, 1.90, 100, 1, 0) == 100 * -1

    assert settle_bet('total', 'under', 2.75, 1.90, 100, 3, 3) == 100 * -1
    assert settle_bet('total', 'under', 2.75, 1.88, 100, 1, 2) == 100 * (-1 / 2)
    assert settle_bet('total', 'under', 2.75, 1.90, 100, 1, 0) == 100 * (1.90 - 1)

    # Bets on Handicap

    # Won or Lost

    # assert settle_bet('handicap', 'home', -0.5, 1.88, 100, 4, 0) == 100 * (1.88 - 1)
    # assert settle_bet('handicap', 'home', -0.5, 1.88, 100, 0, 0) == 100 * -1
    # assert settle_bet('handicap', 'home', -0.5, 1.88, 100, 1, 2) == 100 * -1
    #
    # assert settle_bet('handicap', 'away', -0.5, 1.88, 100, 4, 0) == 100 * -1
    # assert settle_bet('handicap', 'away', -0.5, 1.88, 100, 0, 0) == 100 * -1
    # assert settle_bet('handicap', 'away', -0.5, 1.88, 100, 1, 2) == 100 * (1.88 - 1)
    #
    # # Won or Lost Or Cancelled
    # assert settle_bet('handicap', 'home', 0.0, 1.90, 100, 1, 0) == 100 * (1.90 - 1)
    # assert settle_bet('handicap', 'home', 0.0, 1.85, 100, 2, 2) == 100 * 0
    # assert settle_bet('handicap', 'home', 0.0, 1.97, 100, 1, 3) == 100 * -1
    #
    # assert settle_bet('handicap', 'away', 0.0, 1.90, 100, 1, 0) == 100 * -1
    # assert settle_bet('handicap', 'away', 0.0, 1.85, 100, 2, 2) == 100 * 0
    # assert settle_bet('handicap', 'away', 0.0, 1.97, 100, 1, 3) == 100 * (1.97 - 1)
    #
    # # Won or Lost or Half Won or Half Lost
    #
    # assert settle_bet('handicap', 'home', -0.25, 1.84, 100, 1, 0) == 100 * (1.84 - 1)
    # assert settle_bet('handicap', 'home', -0.25, 1.84, 100, 2, 2) == 100 * (-1 / 2)
    # assert settle_bet('handicap', 'home', -0.25, 1.84, 100, 1, 3) == 100 * -1
    #
    # assert settle_bet('handicap', 'home', 1.25, 1.96, 100, 3, 2) == 100 * (1.96 - 1)
    # assert settle_bet('handicap', 'home', 1.25, 1.96, 100, 1, 1) == 100 * (1.96 - 1)
    # assert settle_bet('handicap', 'home', 1.25, 1.96, 100, 1, 2) == 100 * ((1.96 - 1) / 2)
    # assert settle_bet('handicap', 'home', 1.25, 1.96, 100, 0, 2) == 100 * -1
    #
    # assert settle_bet('handicap', 'away', -1.25, 1.86, 100, 0, 2) == 100 * (1.86 - 1)
    # assert settle_bet('handicap', 'away', -1.25, 1.86, 100, 1, 2) == 100 * (-1 / 2)
    # assert settle_bet('handicap', 'away', -1.25, 1.86, 100, 0, 0) == 100 * -1
    # assert settle_bet('handicap', 'away', -1.25, 1.86, 100, 3, 0) == 100 * -1
    #
    # assert settle_bet('handicap', 'away', 0.25, 1.97, 100, 1, 0) == 100 * -1
    # assert settle_bet('handicap', 'away', 0.25, 1.97, 100, 2, 2) == 100 * ((1.97 - 1) / 2)
    # assert settle_bet('handicap', 'away', 0.25, 1.97, 100, 1, 4) == 100 * (1.97 - 1)
    #
    # assert settle_bet('handicap', 'home', -0.75, 1.90, 100, 4, 0) == 100 * (1.90 - 1)
    # assert settle_bet('handicap', 'home', -0.75, 1.90, 100, 3, 2) == 100 * ((1.90 - 1) / 2)
    # assert settle_bet('handicap', 'home', -0.75, 1.90, 100, 1, 1) == 100 * -1
    # assert settle_bet('handicap', 'home', -0.75, 1.90, 100, 0, 2) == 100 * -1
    #
    # assert settle_bet('handicap', 'home', 1.75, 1.88, 100, 0, 3) == 100 * (1.88 - 1)
    # assert settle_bet('handicap', 'home', 1.75, 1.88, 100, 2, 4) == 100 * (-1 / 2)
    # assert settle_bet('handicap', 'home', 1.75, 1.88, 100, 1, 1) == 100 * (1.88 - 1)
    # assert settle_bet('handicap', 'home', 1.75, 1.88, 100, 1, 0) == 100 * (1.88 - 1)
    #
    # assert settle_bet('handicap', 'away', -2.75, 1.92, 100, 0, 4) == 100 * (1.92 - 1)
    # assert settle_bet('handicap', 'away', -2.75, 1.92, 100, 1, 4) == 100 * ((1.92 - 1) / 2)
    # assert settle_bet('handicap', 'away', -2.75, 1.92, 100, 2, 3) == 100 * -1
    # assert settle_bet('handicap', 'away', -2.75, 1.92, 100, 1, 1) == 100 * -1
    # assert settle_bet('handicap', 'away', -2.75, 1.92, 100, 1, 0) == 100 * -1
    #
    # assert settle_bet('handicap', 'away', 0.75, 1.91, 100, 1, 2) == 100 * (1.91 - 1)
    # assert settle_bet('handicap', 'away', 0.75, 1.91, 100, 0, 0) == 100 * ((1.91 - 1) / 2)
    # assert settle_bet('handicap', 'away', 0.75, 1.91, 100, 3, 2) == 100 * -1

    print("All tests passed.")


if __name__ == '__main__':
    test()

一些想法:

  1. 不是 return 表示投注结果的字符串,而是 return 表示投注结果乘数的数字。

  2. 与其分别检查投注是针对 'over' 还是 'under' 与每个得分差异,不如使用投注类型将得分差异归一化为差异对投注者有利

  3. 使用条件表达式。

因此:

def settle_total_bet(side, points, price, bet_amount, home_score, away_score):
    '''Returns Net result of the bet on total'''
    outcome = determine_total_bet_outcome(side, points, home_score, away_score)
    bet_size = (price - 1) if outcome > 0 else 1
    return bet_amount * bet_size * outcome


def determine_total_bet_outcome(side, line, home_score, away_score):
    '''Returns the appropriate outcome of the bet from BET_OUTCOMES'''
    amount_over = home_score + away_score - line
    amount_successful = amount_over if side == 'over' else -amount_over

    if amount_successful >= 0.5:
        return 1
    elif amount_successful <= -0.5:
        return -1
    elif amount_successful > 0: # == 0.25
        return 0.5
    elif amount_successful < 0: # == -0.25
        return -0.5
    else:
        return 0

顺便说一句:您程序顶部的列表现在实际上没有做任何事情。但是如果你想对这个想法采取更严格的方法——使用一组有限的值来表示一些数据——使用标准库 enum 模块。