django+redis实现可设置概率的大转盘抽奖

php按照奖品百分比随机抽奖代码分析 公平的同概率中奖代码 阅读详情

你好,大家好,我以及很久很久没有在优快云上写文章了,上一篇文章还是在2018年一月份写的,现在以及过去了大半年,我也从一个做PHP开发实习生变成了一个目前做的Python的开发的搬砖工,希望大佬们多多指正。

废话不多说,我们开始正文。

目前公司的项目是一个做游戏盒子的微信小程序,里面涉及到一个大转盘抽奖的系统,UI给的设计图如下:

要求是可以设置各个奖品,以及控制每个奖品获取的概率。

这该怎么办呢,随机数是肯定要用到的,但是该如何做呢

我在网上搜索的大转盘算法,找到了这篇文章:链接

这位大佬给出了两种方式解决问题:

第一种:根据设置的概率,把奖品的数目相应的翻倍,比方说10%的概率,所有的奖品总量为长度为100的数组,则把该奖品×10,存放于数组中

A [0] = iphone 
A [1] = iphone 
A [2] = iphone 
....

A [10] = iphone

A [11] = 100元购物卷 
A [12] = 100元购物卷 

这种方法的缺陷很明显,如果需要设置一个万分之一的概率,那就得将数组长度设置为10000,十万分之一的概率那就得将数组设置为10W,这会造成内存极大的消耗,所以不推荐使用。

第二种方法:

将概率映射为数字段,若数字段一共有10000,10%的概率也就是取0-1000之间的数字就可以了,直接上图:

很明显,这种方式很巧妙,不会因为大概率事件(比方说一万分之一,十万分之一)可能会造成的大量占用内存的情况。

因此我决定采用第二种方式来做抽奖处理,在那位大佬的文章中,他使用了Java的的的中的散列结构来做,但是Python的中的中,并没有散列数据结构,我想到的就是借用的Redis的的的哈希来处理这个问题,下面我们来看代码:

我目前的项目是使用django,rest framework框架来提供接口给微信小程序用的,数据库使用postgresql

首先需要一张存储奖品的表:

class WechatLuckyDial(models.Model):

    id = models.AutoField(primary_key=True)
    prize_name = models.CharField(max_length=100, default='', verbose_name='奖品文字')
    prize_img_num = models.IntegerField(default=0, verbose_name='大转盘上钻石的数目') # 0 代表使用红包的图片
    prize_type = models.IntegerField(default=0, verbose_name='奖品类型') # 0 钻石奖励 1 红包奖励
    prize_amount = models.IntegerField(default=0, verbose_name='奖品数目') # 0 代表随机奖励
    prize_probability = models.IntegerField(default=0, verbose_name='获奖概率') # 单位%  20 就是20%的意思
    create_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'hd_wechat_luckdial'
        ordering = ('id',)

其中prize_img_num不需要管,这是为了配合前台展示图片才设立的字段。

最重要的就是奖品的id和prize_probability(概率性),

然后python manage.py makemigrations {模块名}和python manage.py migrate {模块名}一下,在数据库中创建表。

随后创建这个模型的视图集中,实现对这张表的增删改查:

class WechatLuckyDialViewSet(ModelViewSet):
    queryset = WechatLuckyDial.objects.all()
    serializer_class = WechatLuckyDialSerizlizer

其中serialzier_class也普通,没有做什么特别处理:

class WechatLuckyDialSerizlizer(ModelSerializer):
    prize_name = serializers.CharField(required=True, error_messages={'required': '奖励名称不能为空'})
    prize_type = serializers.CharField(required=True, error_messages={'required': '奖励类型不能为空'})
    prize_probability = serializers.CharField(required=True, error_messages={'required': '概率不能为空'})

    class Meta:
        model = WechatLuckyDial
        fields = '__all__'

    def to_representation(self, instance):
        ret = super(WechatLuckyDialSerizlizer, self).to_representation(instance)

        ret.update({
            'create_at': instance.create_at.strftime('%Y-%m-%d %H:%M:%S')
        })
        return ret

随后将viewset映射为url,我先用postman往里面存入相应的奖励以及设置好概率。

好了,现在基础的数据以及最重要的概率以及有了,目前我设置的概率为19%,19%,19%,19%,19%,5%,其中随机现金红包概率为5%,现在还需要将概率映射为数字段。

数字段由一个最大值和一个最小值构成,奖品在整个序列的位置和概率大小决定了最大值和最小值。当有了这个最大值和最小值之后,每当用户点抽奖,我们随机出一个数字,要是这个数字存在与最大值和最小值之间,则中这个奖励。

所以我这里选择使用Redis的哈希的结构去存储这两个值,我设立了两张表:

# 两张redis的hash表:
# 一张存储大转盘单个奖励概率最大值的表 field luckydial_id
LUCKYDIAL_PRIZE_SCOPE_MAX = 'wechat_luckdial_prize_scope_max'
# 一张存储大转盘单个奖励概率最小值的表
LUCKYDIAL_PRIZE_SCOPE_MIN = 'wechat_luckdial_prize_scope_min'

一张存储最大值,一张存储最小值,现场为奖品的ID,VAL为相应的值。以上代码我写在项目的settings.py文件中,防止表名出错

所以接下来我们得通过计算,获得每个奖品的最大值和最小值。

我用了rest framework的APIView去实现:

class SaveLuckDialsettingView(APIView):

    def get(self, requset):
        sql = """
            select * from hd_wechat_luckdial order by id asc 
        """
        cursor = connection.cursor()
        cursor.execute(sql)
        result = [i for i in dictfetchall(cursor)] #先将所有奖品从数据库中取出,放在数组里,

        conn = get_redis_connection('default') # 链接redis
        tempInt = 0 # 设置一个记录值,用于记录上一条奖品的最大值和下一个奖品的最小值

        for i in range(len(result)): #循环所有奖品
            if tempInt == 0:   #如果是第一个奖品,就记录值就为0  否则就将记录值+1设置为当前奖品的最小值
                tempInt = 0
            else:
                tempInt = tempInt + 1

            min = tempInt  
            if i == 0:
                max = tempInt + result[i]['prize_probability'] * 100
            else:
                max = tempInt + result[i]['prize_probability'] * 100 - 1

            conn.hset(settings.LUCKYDIAL_PRIZE_SCOPE_MAX, result[i]['id'], max)
            conn.hset(settings.LUCKYDIAL_PRIZE_SCOPE_MIN, result[i]['id'], min)
            tempInt = max

        return Response({'message': '设置成功'}, status=status.HTTP_200_OK)

通过以上代码,我们就能将每个商品的最大值和最小值设置数字段,我这里因为数据库中概率为10即代表10%,这里我将概率×100用来设置数字段,比方说第一个奖品概率为10%,那么他对应的代码段就是0-1000。总数字段长度为10000,玩家抽奖的随机数的范围也就是0-10000。

这样我们就成功设置了数字段,接下来进行抽奖就变得很容易,随机0-10000的数字即可,判断随机出来的数字在哪个数字区间内,直接上代码:

# 开始抽奖!
class ZhuanQiLaiView(APIView):
    permission_classes = (PlayerPermissions,)

    def get(self, request):
        try:
            with transaction.atomic():
                open_id = request.user.openid
                sql = """
                      select diamond_amount, money_amount from hd_wechatuser where openid='{openid}'
                  """.format(openid=open_id)
                cursor = connection.cursor()
                cursor.execute(sql)
                result = dictfetchall(cursor)
                diamond_amount = result[0]['diamond_amount']

                if diamond_amount < 200:
                    return Response({'message': '您的钻石不够抽奖'}, status=status.HTTP_400_BAD_REQUEST)

                player_lucky_num = random.randint(0, 10000)
                conn = get_redis_connection('default')
                queryset = WechatLuckyDial.objects.all()
                serizalize = WechatLuckyDialSerizlizer(queryset, many=True)
                luckydial_data = serizalize.data

                for i in luckydial_data:
                    max = conn.hget(settings.LUCKYDIAL_PRIZE_SCOPE_MAX, i['id'])
                    min = conn.hget(settings.LUCKYDIAL_PRIZE_SCOPE_MIN, i['id'])
                    if player_lucky_num > int(min) and player_lucky_num < int(max):
                        prize = i
                        break

                print(prize)

                if prize['prize_type'] == 1:
                # 红包奖励
                    if prize['prize_amount'] == 0:
                #随机奖励
                        award_money = random.randint(10, 100)
                        money_amonut = result[0]['money_amount']
                        now_money_amount = award_money + money_amonut
                        WechatUser.objects.filter(openid=open_id).update(money_amount=now_money_amount)
                        message = '恭喜你获取红包{task_award}元'.format(task_award=award_money / 100)
                elif prize['prize_type'] == 0:
                # 钻石奖励
                    task_award = prize['prize_amount']
                    now_diamond_amount = task_award + diamond_amount
                    message = '恭喜你获得{task_award}个钻石'.format(task_award=task_award)

                try:
                    now_diamond_amount
                except NameError:
                    end_diamond_amount = diamond_amount - 200
                else:
                    end_diamond_amount = now_diamond_amount - 200

                WechatUser.objects.filter(openid=open_id).update(diamond_amount=end_diamond_amount)
        except Exception as e:
            return Response({'message': '抽奖失败'}, status=status.HTTP_400_BAD_REQUEST)

        data = {
            'message': message,
            'prize_id': prize['id']
        }

        return Response({'data': data}, status=status.HTTP_200_OK)

这一段代码略多,里面包含了检测玩家钻石够不够抽奖,以及抽奖之后奖品的发放等等,核心的抽奖代码我抽取出来是这样的:

                player_lucky_num = random.randint(0, 10000)
                conn = get_redis_connection('default')
                queryset = WechatLuckyDial.objects.all()
                serizalize = WechatLuckyDialSerizlizer(queryset, many=True)
                luckydial_data = serizalize.data  #将奖品信息从数据库取出来

                for i in luckydial_data:
                    max = conn.hget(settings.LUCKYDIAL_PRIZE_SCOPE_MAX, i['id'])
                    min = conn.hget(settings.LUCKYDIAL_PRIZE_SCOPE_MIN, i['id'])
                    if player_lucky_num > int(min) and player_lucky_num < int(max):
                        prize = i #若在区间内,就中这个奖励
                        break

                # prize包含了中的奖励的所有信息
                 print(prize)

至此我们就实现了大转盘抽奖的功能,道理并不复杂,也可以用很多方式实现,我这里只是用我想到的一种方式去处理,若有什么好的想法,可联系我,我的邮箱是13047908816@163.com。欢迎大家来交流,互相学习。

极验滑块验证码破解与研究(一):AST还原混淆JS 极验滑块验证码破解与研究(一):AST还原混淆JS声明一、环境安装1. node安装1.1. node下载1.2. 配置环境变量1.3. node安装检测1.4. pycharm配置node环境2. babel库安装2.1. babel库安装命令2.2. babel库安装检测二、AST还原混淆JS1. 模块导入2. AST还原流程3. 复制还原需要用到的js源码4. AST还原函数详解4.1. replace_unicode4.2. replace_unicode, replace_name_array, 阅读详情

相关推荐

AT32F421玩转AM32电调:手把手教你调试过零点比较器,告别电机抖动

本文详细介绍了如何使用AT32F421芯片调试AM32电调的过零点比较器,解决电机抖动问题。通过硬件配置、软件环境搭建、比较器电路原理分析及filter_level参数动态调整等实战步骤,帮助开发者精准诊断和优化电机控制性能。

weixin_42525632的博客 276

随笔-自控概率的大转盘抽奖

游戏自控概率的大转盘抽奖功能

zhangchong5522的博客 3561

COMSOL仿真分析高压直流GIS/GIL绝缘性能优化

高压直流气体绝缘设备(GIS/GIL)的绝缘性能是保障电网可靠运行的关键。通过COMSOL Multiphysics多物理场仿真,可以深入分析气固界面电场分布与电荷积聚机理。该技术结合静电场、热场和电荷传输耦合计算,能准确模拟温度梯度对SF6气体与环氧树脂界面特性的影响。工程实践中,这类仿真可优化导体结构设计、改进绝缘材料配方,并建立电场-温度关联预警模型。特别是在80℃高温工况下,仿真显示界面电荷密度会显著增加23%,这对设备安全运行具有重要指导价值。

weixin_32075843的博客 192

php 大转盘抽奖概率 角度,在线抽奖大转盘和概率计算

html>抽奖效果演示.rotary{position:relative;width:854px;height:504px;margin:0auto;background:#d71f2eurl(p_w_picpaths/bg1.png);}.rotaryArrow{position:absolute;left:181px;top:104px;widt...

weixin_35390057的博客 516

避坑指南:vmdk转qcow2镜像时你可能会遇到的5个问题及解决方法

本文详细解析了将VMDK虚拟机镜像转换为QCOW2格式时可能遇到的五大核心问题,特别是启动失败的常见原因及解决方案。内容涵盖格式差异、预处理优化、转换命令详解,并针对根文件系统挂载失败、GRUB引导失败、网卡识别、性能异常等典型故障提供了具体排查与修复步骤,旨在帮助运维人员高效、可靠地完成镜像迁移。

websocket5live的博客 275

win10和Mac上安装Freesurfer

Mac安装Freesurfer 软件下载地址 可以根据官方给出的demo视频一步一步下载

Daily_365的博客 6077

Django计算机毕业设计java抽奖系统设计(程序+LW)Python

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程项目运行环境配置:Pychram社区版+py项目技术:django + python+ Vue 等等组成,B/S模式 +pychram管理等等。环境需要1.运行环境:最好是python3.7.7,我们在这个版本上开发的。其他版本理论上也可以。2.pycharm环境:pycharm都可以。推荐pycharm社区版;3.mysql环境:建议是用5.7版本均可。

Django毕设程序杰哥 316

车辆横向控制MPC实战:从‘老王模型’到CasADi求解的保姆级避坑指南

本文详细解析了车辆横向控制MPC的实战应用,从经典动力学模型选择到CasADi求解器的优化配置,提供了一套完整的避坑指南。重点介绍了车辆动力学模型的验证要点、CasADi环境的高效配置技巧以及MPC问题建模的核心要素,帮助开发者快速实现稳健的横向控制方案。

weixin_42524499的博客 346

chatgpt赋能python:如何用Python打造一个简单的抽奖程序

通过本文的介绍,我们可以发现使用Python实现一个简单的抽奖程序是一件非常容易的事情。Python的random库提供了强有力的随机数生成功能,而且语法简洁易懂,用户可以非常便捷地实现自己的抽奖程序。如果您现在正在计划一次营销活动,并且需要一款方便快捷的抽奖程序,那么不妨考虑使用Python来实现。相信这将带给您意想不到的效果。本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。

虚幻私塾 758

AD20 Channel-Offset Error 解决办法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言AD20 PCB相同电路模块ROOM格式复用时出现 Channel-Offset Error 解决办法一、问题现象二、解决办法 前言 AD20 PCB相同电路模块ROOM格式复用时出现 Channel-Offset Error 解决办法 一、问题现象 我们经常在使用Room格式快速布局相同模块电路时出现以下问题, 二、解决办法 相同模块电路PCB布局复制的过程网上有很多,这里不再做赘述,步骤都差不多,只说问题根源; 1:.

m0_47201213的博客 7623

通过InoDriverShop伺服调试软件连接汇川SV660F系列伺服的具体方法示例

通过InoDriverShop伺服调试软件连接汇川SV660F系列伺服的具体方法示例

Robot_PLC_HMI_Automation 1万+

python配合django+redis实现可设置概率的大转盘抽奖

自己刚刚做完一个转盘抽奖活动,偶然间发现了一个和自己实现的类似的文章,特此记录以下 目前公司的项目是一个做游戏盒子的微信小程序,里面涉及到一个大转盘抽奖的系统,UI给的设计图如下: 要求是可以设置各个奖品,以及控制每个奖品获取的概率。 这该怎么办呢,随机数是肯定要用到的,但是该如何做呢 我在网上搜索的大转盘算法,找到了这篇文章:链接 这位大佬给出了两种方式解决问题: 第一种:根据...

mr~li的博客 1374

基于 transformer、lstm、LSTM多特征的交通流量预测 完整数据代码 超全项目 本科硕士毕设卓卓有余

基于 transformer、lstm、LSTM多特征的交通流量预测 完整数据代码 超全项目 本科硕士毕设卓卓有余

4655

微信小程序 超市商场客户管理系统(购物商城 抽奖 优惠卷)_w263hx38

微信小程序超市商场客户管理系统是一款集购物商城、抽奖活动和优惠券发放于一体的综合性客户管理工具。该系统旨在帮助超市和商场提升客户粘性、增加销售额,同时优化客户管理流程。通过微信小程序的便捷性,商家可以快速触达目标客户群体,实现精准营销。

QQ_188083800的博客 653

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Python之Redis操作方法

Redis(Remote Dictionary Server)是一个高性能的键值存储数据库,它支持各种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis 通常被用作缓存、消息队列、实时统计等场景。本教程介绍了使用 Python 操作 Redis 的基本操作,包括键值对、哈希表、列表、集合、有序集合和发布/订阅等数据操作,以及事务操作、过期时间、持久化、分布式锁、缓存和性能优化等高级功能和用例。

专注于Python编程技术的分享与交流,致力于帮助开发者提升编程技能,解决实际问题,探索Python的无限可能。 2万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

原生js实现轮盘抽奖,控制中奖概率(完整示例)

文章目录1.实现旋转2.控制得奖概率3. 控制旋转动画落点4.测试概率完整代码 本想找一个现成的,结果发现网上只有能实现转了,但是效果并不是让人很满意,于是我就借鉴一个样式,重新改了js实现,效果如下: 图片素材:(网上一搜就有=-=) pointer.png turntable.png turntable-bg.jpg 1.实现旋转 原理很简单,就是通过css动画来实现旋转动画,用js来控制旋转度, img[src^="turntable"] { posi

marendu的博客 3万+

Android 可控制概率家务转盘

** 指针所指向的角度数据 *//** 转盘内容数组 */private String[] arrayHouseWork = { “扫地”, “洗衣服”, “休息”, “做饭”, “洗碗”, “休息” };/** 监听动画状态的监听器 */@Override@Override@Override@Override// 每次转圈角度增量// 初始化旋转动画// 计算动画播放总时间// 设置动画播放时间。

2401_84132685的博客 767

如何做一个抽奖 转盘 设置概率

3.可以把奖品的每一项的等级和中奖概率 自己整合成数组 当抽到三等奖 比如三等奖有三个选项 分别是第三个 第五个和第八个。就可以在这三个内再随机选一个出来 乘以一份的角度 再减去一半的角度。2.概率可以用1到100的随机数 设置概率 例如1到60是三等奖 60到80是二等奖 80到95是一等奖 95到100是特等奖 概率可以自己设置100还是1000。1.可以把份数用360度 除以 多少个抽奖项 转到哪 就多加想要的那一项是第几个乘以 一份的角度 减去一半的角度 就刚好转到那个位置的中间。

kilito_01的博客 3126

抽奖活动不同概率实现

说道抽奖活动,首先肯定会想到Random的使用,在整数和小数之中取随机数需要注意的是nextInt()和nextDouble(),前者是有参函数,后者是无参函数(如下): int random = new Random().nextInt(10); double randomIndex = new Random().nextDouble(); 前者表示从0-10之间取任意随机数;后者表示在0-1之间取任意小数,如果需要取得指定范围内小数,可进行如下操作: double randomIndex = new

weixin_56772904的博客 828

给你个抽奖活动,概率你该如何设置?

抽奖算法需要满足的需求如下:       1.可以控制中奖的概率       2.具有随机性      3.最好可以控制奖品的数量     4.根据用户ID或者ip、手机号、QQ号等条件限制抽奖次数        不同概率的抽奖原理就是把0到*(比重总数)的区间分块      分块的依据是物品占整个的比重,再根据随机数种子来产生0-* 中的某个数      判断这个数是落在哪个区间...

YiFeng_888的博客 1万+

在Vue/JS里面怎么做前端抽奖转盘,并且调整中奖概率?

一、受前端广大网友的启发,编写在Vue里面做抽奖转盘的程序,同时可以调整中奖概率; 1、效果图 2、附素材原图,可自行下载练习(名称顺序为pointer.png turntable.png turntable-bg.jpg) 3、演示视频 Vue/JS里做前端抽奖转盘 二、实现原理:CSS的transitions:rotate属性,传入度数即可旋转;调整中奖概率各有各的做法

weixin_46683455的博客 8215

微信小程序 自定义组件之《转盘》

微信小程序自定义组件转盘

涛々的技术博客 7万+

php 大转盘抽奖概率 角度,PHP大转盘中奖概率算法与示例代码

header("Content-type: text/html; charset=utf-8");$prize_arr = array('0' => array('id'=>1,'prize'=>'平板电脑','v'=>1),'1' => array('id'=>2,'prize'=>'数码相机','v'=>5),'2' => array('i...

weixin_36358383的博客 193

PHP抽奖概率

随机输出“苹果”,“橘子”,“香蕉”要求输出“苹果”的概率为50%,“橘子”的概率为30%,“香蕉”的概率为20% 1.第一种算法 function getRandom($pr){ $temp = rand(0,array_sum($pr)); $left = 0; $right = 0; foreach ($pr as $k=>$v){ $right+=$v; if($left<=$temp && $tem...

magee_sh的博客 330

【开发经验】redis实现抽奖功能

抽奖的功能在互联网的项目中随处可见,通过这些给用户惊喜的功能,来达到引流的效果。但是这个功能说难也难,说简单也简单。因为一般互联网的工程都是集群部署,抽奖的时候还要考虑线程间奖品争夺的问题,通过redis可以很轻松实现抽奖功能,我阐述下我的思路,请大家参考。

叁滴水 的博客 6260

JS动态转盘可自由设置个数与概率

让我为大家介绍一下转盘的实现过程与原理,介绍都放在下面代码块中,一步一步的教会你。 我们转盘使用线段来实现 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> .boss { width: 400px; h

m0_74577714的博客 1939

python实现转盘概率的几种设计方法

最近接手了一个大转盘的抽奖活动,刚开始也没有具体的思路,在经过冥思苦想并查找后总结出以下几种实现概率的方案: 第一种 import random def select(): num = ["一等奖", "二等奖", "三等奖"] # 概率列表 r = [0.1, 0.3, 0.6] sum = 0 ran_num = random.random(...

mr~li的博客 3600
上一篇: 解决使用Validform插件,datatype里用ajax验证数据是否已经存在时出现的问题
下一篇: linux守护进程(supervisor)的使用以及遇到的一些问题和解决方法
wry_developer
博客等级 码龄9年 8粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值