logo头像

Always believe youself.

日常开发之抽奖

本文于1518天之前发表,文中内容可能已经过时。

今天开发的需求新添加了抽奖!!!


这好像是第一次比较正式的写这种的需求吧,之前都是用随机函数在写,但是随机函数是不能特别友好地进行随机。
lottery_num = random.randint(0, 99) 我在使用 1/100的概率进行随机测试,进行1W次测试,只有73次中奖。我拿到需求是必须保证1/100的概率,分布是均匀的,100次是必须有一次中奖的,而且不是后期的处理公布,是必须实时的返回中奖结果且要准确的中奖率。

在这个过程中我也查了较多的资料,

  • 部分抽奖是统计完所有用户后台再次抽奖,这种抽奖的操作性较大,毕竟是后期进行公布,很多细节都是可以进行处理的。
  • 饼图处理+权重,带权随机算法思想很简单,就是”把所有物品根据其权重构成一个个区间,权重大的区间大.可以想象成一个饼图. 然后,扔骰子,看落在哪个区间,”

    示例代码:

    #coding=utf-8
    import random
    def weighted_random(items):
        total = sum(w for _,w in items)
        n = random.uniform(0, total)#在饼图扔骰子
        for x, w in items:#遍历找出骰子所在的区间
            if n<w:
                break
            n -= w
        return x
    
    print weighted_random([('iphone', 10), ('ipad', 40), ('itouch', 50)])
    
  • 肯定还有其他的(较多,但不适合我个人的应用业务)

在思考并尝试了多次后,使用数据进行决定,因为我的业务中每次抽奖会入库,是否中奖也有特殊的字段进行标示,这就有利于我的判断,解决抽奖过程中100次内未中奖,或者100次后多次中奖的不友好结果出现。

上代码(部分代码):业务中有两项抽奖同时进行的。
lottery_kinds0,1,2 表示未中奖,一等奖,二等奖;中奖随机数可随便取值;并加了最高抽奖数判断,在过程也尝试加了前后期的抽奖同概率的分布,此次为用到。

luck_num = 50
lottery_num = random.randint(0, 99)
luck_boy = 599
luck_boy_num = random.randint(1, 1000)
if lottery_num == luck_num:
    #徽章
    lottery_kinds = 1
elif luck_boy == luck_boy_num:
    #盲盒
    lottery_kinds = 2
else:
    lottery_kinds = 0

# 在做一次判断每100次内只有一个 1  1000次内只有一个2
users_query = "select count(id) from p_lottery"
cur.execute(users_query)
uses_c = cur.fetchone()
if uses_c[0] == 1000:
    users_query_f = "select count(id) from p_lottery where lottery_kinds =2 "
    cur.execute(users_query_f)
    uses_f = cur.fetchone()
    if uses_f[0] == 0:
        lottery_kinds == 2

if lottery_kinds ==2 or lottery_kinds ==0:
    letterys_query = "select count(id) from p_lottery where lottery_kinds =2"
    cur.execute(letterys_query)
    letterys_c = cur.fetchone()
    if letterys_c[0] < 10:
        if uses_c[0] // 1000 == letterys_c[0]:
            pass
        elif uses_c[0] // 1000 < letterys_c[0] and letterys_c[0] - uses_c[0] // 1000 == 1:
            lottery_kinds = 0
        else:
            if uses_c[0] // 1000 - letterys_c[0] == 1:
                lottery_kinds = 2
            else:
                lottery_kinds = 0
    else:
        lottery_kinds = 0
if lottery_kinds ==1 or lottery_kinds ==0:
    letterys_query = "select count(id) from p_lottery where lottery_kinds =1"
    cur.execute(letterys_query)
    letterys_c = cur.fetchone()
    if letterys_c[0] <90:
        if uses_c[0]//100 ==letterys_c[0]:
            pass
        elif uses_c[0]//100<letterys_c[0] and letterys_c[0]-uses_c[0]//100 ==1:
            lottery_kinds = 0
        else:
            if uses_c[0]//100  - letterys_c[0] == 1:
                lottery_kinds =1
            else:
                lottery_kinds = 0
    else:
        lottery_kinds = 0

今天加班较晚啊!
image