使用.NET Core实现饿了吗拆红包功能
需求说明
以前很讨厌点外卖的我,最近中午经常点外卖,因为确实很方便,提前点好餐,算准时间,就可以在下班的时候吃上饭,然后省下的那些时间就可以在中午的时候多休息一下了。
点餐结束后,会有一个好友分享红包功能,虽说这个红包不能提现,但却可以抵扣点餐费用,对于经常点餐的人来说,直接用于抵扣现金确实是很大的诱惑,在点餐之后所获得的那个红包,必须要分享出去才能拆。
那么如果自己也想实现以下抢红包功能,需要说明的是,本文所描述的红包功能更多的关注与随机红包的生成,至于高并发、数据一致性等问题,本文暂未涉及,以下是本文所讨论的两个技术点:
不同的消费金额获取的红包总额不同,消费金额越大,红包总额就越大,红包总数也就越多;假设有一天,有一种需求是,需要保证参与抢红包的人获得的红包金额在平均数附近波动,也就是尽量的服从正态分布;
功能实现
本文描述的场景,所涉及到的金额以分为单位,目的是为了更好的处理随机数。总体的示意图如下:
消费后红包的初始化
需求重点,用户分享出去的红包总额跟消费总额成正比,可以分拆的子红包个数也与消费总额成正比。
比如:
10-20元的消费金额,可以分享的单个红包金额为10元,可以供5个人抢20-40元的消费金额,可以分享的单个红包金额为20元,可以供8个人抢40-60元的消费金额,可以分享的单个红包金额为30元,可以供10个人抢60-100元的消费金额,可以分享的单个红包金额为40元,可以供10个人抢100元以上的消费金额,可以分享的单个红包金额为50元,可以供10个人抢
那么我们设计出来一个实体,用于表示红包信息,以方便的配置及调整红包规则
public class redpacketsinfo { /// <summary> /// 最大消费金额 /// </summary> public int maxamount { get; set; } /// <summary> /// 最小消费金额 /// </summary> public int minamount { get; set; } /// <summary> /// 红包金额 /// </summary> public int totalamount { get; set; } /// <summary> /// 红包可被分割的数量 /// </summary> public int redpacketquantity { get; set; } }
红包初始化信息
private static list<redpacketsinfo> getredpackets() { return new list<redpacketsinfo>() { new redpacketsinfo { minamount = 1000, maxamount = 2000, redpacketquantity = 5, totalamount=1000 }, new redpacketsinfo { minamount = 2000, maxamount = 3000, redpacketquantity = 5, totalamount=1000 }, new redpacketsinfo { minamount = 4000, maxamount = 6000, redpacketquantity = 5, totalamount=1000 }, new redpacketsinfo { minamount = 6000, maxamount = 8000, redpacketquantity = 5, totalamount=1000 }, new redpacketsinfo { minamount = 10000, maxamount = int.maxvalue, redpacketquantity = 5, totalamount=1000 } }; }
接下来我们就可以通过消费金额获取相应的红包信息了。
随机红包的生成时机及处理
随机红包的生成可以在抢之前生成也可以在抢的过程中确定,一般而言,很多时候红包会在抢的过程中动态的实际分配,不过在本文中,红包在用户分享成功后会预先生成,主要原因是为了更好地处理处理数据,以使得数据能够服从正态分布。
以下是其流程图,其中有一段逻辑是回调功能,可能会有圈友会问,如何保证有回调以及回调是成功的,这个地方有很多种处理,比如mq、任务调度等,此处也不做讨论
那么我们需要设计一个新的实体,以表示分享出去的红包及其生成的随机红包:
public class sharedredpacket { /// <summary> /// 分享人userid /// </summary> public int senderuserid { get; set; } /// <summary> /// 分享时间 /// </summary> public datetime sendtime { get; set; } public list<robbedredpacket> robbedredpackets { get; set; } } public class robbedredpacket { /// <summary> /// 抢到红包的人的userid /// </summary> public int userid { get; set; } /// <summary> /// 抢到的红包金额 /// </summary> public int amount { get; set; } /// <summary> /// 抢到时间 /// </summary> public datetime robbedtime { get; set; } }
在实现过程中,根据用户消费金额获取相应红包,然后通过随机数,生成n-1个原始的随机数据,最后一个数据用总和减去n-1个数据的和获取到
//红包随机拆分 random ran = new random(); list<double> randoms = new list<double>(redpacketslist.count); for (int i = 0; i < redpacketsinfo.redpacketquantity - 1; i++) { int max = (totalamount - (redpacketsinfo.redpacketquantity - i)) * 1; int result = ran.next(1, max); randoms.add(result); totalamount -= result; } randoms.add(totalamount);
然后通过设置好系数,以处理数据达到服从正太分布的目的:
//正太分布处理 for (int i = 0; i < redpacketsinfo.redpacketquantity; i++) { double a = math.sqrt(math.abs(2 * math.log(randoms[i], math.e))); double b = math.cos(2 * math.pi * randoms[i]); randoms[i] = a * b * 0.3 + 1; }
经过第二次处理后,得到的数据与原始数据有偏差,那么我们通过等比例方式再次处理,以确保拆分后的红包总额等于红包原始总额:
//生成最终的红包数据 double d = originaltotal / randoms.sum(); sharedredpacket sharedredpacket = new sharedredpacket(); sharedredpacket.robbedredpackets = new list<robbedredpacket>(redpacketslist.count); for (int i = 0; i < redpacketsinfo.redpacketquantity - 1; i++) { sharedredpacket.robbedredpackets.add(new robbedredpacket { amount = (int)math.round(randoms[i] * d, 0) }); } sharedredpacket.robbedredpackets.add(new robbedredpacket { amount = originaltotal - sharedredpacket.robbedredpackets.sum(p => p.amount) });
测试
测试效果图如下:
部分代码如下,
console.writeline("是否分享输入y分享成功,输入n退出"); string result = console.readline(); if (result == "y") { var leftredpacket = sharedredpacket.robbedredpackets.where(p => p.userid <= 0).tolist(); var robbedredpacket = leftredpacket[new random().next(1, leftredpacket.count + 1)]; console.writeline("抢到的到红包金额是:" + robbedredpacket.amount); console.writeline("-------------------------------------------------------"); }
总结
以上所述是小编给大家介绍的使用.net core实现饿了吗拆红包功能,希望对大家有所帮助
推荐阅读
-
使用.NET Core实现饿了吗拆红包功能
-
.Net Core 下使用ZKWeb.System.Drawing实现验证码功能(图形验证码)
-
Asp.Net Core 使用Monaco Editor 实现代码编辑器功能
-
ASP.NET Core中使用MialKit实现邮件发送功能
-
.Net Core 下使用ZKWeb.System.Drawing实现验证码功能
-
使用.NET Core实现饿了吗拆红包功能
-
Asp.Net Core 使用Monaco Editor 实现代码编辑器功能
-
ASP.NET Core中使用MialKit实现邮件发送功能
-
.Net Core 下使用ZKWeb.System.Drawing实现验证码功能