使用.NET Core實(shí)現(xiàn)餓了嗎拆紅包功能
需求說(shuō)明
以前很討厭點(diǎn)外賣的我,最近中午經(jīng)常點(diǎn)外賣,因?yàn)榇_實(shí)很方便,提前點(diǎn)好餐,算準(zhǔn)時(shí)間,就可以在下班的時(shí)候吃上飯,然后省下的那些時(shí)間就可以在中午的時(shí)候多休息一下了。
點(diǎn)餐結(jié)束后,會(huì)有一個(gè)好友分享紅包功能,雖說(shuō)這個(gè)紅包不能提現(xiàn),但卻可以抵扣點(diǎn)餐費(fèi)用,對(duì)于經(jīng)常點(diǎn)餐的人來(lái)說(shuō),直接用于抵扣現(xiàn)金確實(shí)是很大的誘惑,在點(diǎn)餐之后所獲得的那個(gè)紅包,必須要分享出去才能拆。
那么如果自己也想實(shí)現(xiàn)以下?lián)尲t包功能,需要說(shuō)明的是,本文所描述的紅包功能更多的關(guān)注與隨機(jī)紅包的生成,至于高并發(fā)、數(shù)據(jù)一致性等問(wèn)題,本文暫未涉及,以下是本文所討論的兩個(gè)技術(shù)點(diǎn):
不同的消費(fèi)金額獲取的紅包總額不同,消費(fèi)金額越大,紅包總額就越大,紅包總數(shù)也就越多;假設(shè)有一天,有一種需求是,需要保證參與搶紅包的人獲得的紅包金額在平均數(shù)附近波動(dòng),也就是盡量的服從正態(tài)分布;
功能實(shí)現(xiàn)
本文描述的場(chǎng)景,所涉及到的金額以分為單位,目的是為了更好的處理隨機(jī)數(shù)??傮w的示意圖如下:
消費(fèi)后紅包的初始化
需求重點(diǎn),用戶分享出去的紅包總額跟消費(fèi)總額成正比,可以分拆的子紅包個(gè)數(shù)也與消費(fèi)總額成正比。
比如:
10-20元的消費(fèi)金額,可以分享的單個(gè)紅包金額為10元,可以供5個(gè)人搶20-40元的消費(fèi)金額,可以分享的單個(gè)紅包金額為20元,可以供8個(gè)人搶40-60元的消費(fèi)金額,可以分享的單個(gè)紅包金額為30元,可以供10個(gè)人搶60-100元的消費(fèi)金額,可以分享的單個(gè)紅包金額為40元,可以供10個(gè)人搶100元以上的消費(fèi)金額,可以分享的單個(gè)紅包金額為50元,可以供10個(gè)人搶
那么我們?cè)O(shè)計(jì)出來(lái)一個(gè)實(shí)體,用于表示紅包信息,以方便的配置及調(diào)整紅包規(guī)則
public class RedPacketsInfo
{
/// <summary>
/// 最大消費(fèi)金額
/// </summary>
public int MaxAmount { get; set; }
/// <summary>
/// 最小消費(fèi)金額
/// </summary>
public int MinAmount { get; set; }
/// <summary>
/// 紅包金額
/// </summary>
public int TotalAmount { get; set; }
/// <summary>
/// 紅包可被分割的數(shù)量
/// </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
}
};
}
接下來(lái)我們就可以通過(guò)消費(fèi)金額獲取相應(yīng)的紅包信息了。
隨機(jī)紅包的生成時(shí)機(jī)及處理
隨機(jī)紅包的生成可以在搶之前生成也可以在搶的過(guò)程中確定,一般而言,很多時(shí)候紅包會(huì)在搶的過(guò)程中動(dòng)態(tài)的實(shí)際分配,不過(guò)在本文中,紅包在用戶分享成功后會(huì)預(yù)先生成,主要原因是為了更好地處理處理數(shù)據(jù),以使得數(shù)據(jù)能夠服從正態(tài)分布。
以下是其流程圖,其中有一段邏輯是回調(diào)功能,可能會(huì)有圈友會(huì)問(wèn),如何保證有回調(diào)以及回調(diào)是成功的,這個(gè)地方有很多種處理,比如MQ、任務(wù)調(diào)度等,此處也不做討論
那么我們需要設(shè)計(jì)一個(gè)新的實(shí)體,以表示分享出去的紅包及其生成的隨機(jī)紅包:
public class SharedRedPacket
{
/// <summary>
/// 分享人UserId
/// </summary>
public int SenderUserId { get; set; }
/// <summary>
/// 分享時(shí)間
/// </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>
/// 搶到時(shí)間
/// </summary>
public DateTime RobbedTime { get; set; }
}
在實(shí)現(xiàn)過(guò)程中,根據(jù)用戶消費(fèi)金額獲取相應(yīng)紅包,然后通過(guò)隨機(jī)數(shù),生成n-1個(gè)原始的隨機(jī)數(shù)據(jù),最后一個(gè)數(shù)據(jù)用總和減去n-1個(gè)數(shù)據(jù)的和獲取到
//紅包隨機(jī)拆分
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);
然后通過(guò)設(shè)置好系數(shù),以處理數(shù)據(jù)達(dá)到服從正太分布的目的:
//正太分布處理
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;
}
經(jīng)過(guò)第二次處理后,得到的數(shù)據(jù)與原始數(shù)據(jù)有偏差,那么我們通過(guò)等比例方式再次處理,以確保拆分后的紅包總額等于紅包原始總額:
//生成最終的紅包數(shù)據(jù)
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)
});
測(cè)試
測(cè)試效果圖如下:
部分代碼如下,
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("-------------------------------------------------------");
}
總結(jié)
以上所述是小編給大家介紹的使用.NET Core實(shí)現(xiàn)餓了嗎拆紅包功能,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!
上一篇:VS2015+Qt5+OpenCV3開(kāi)發(fā)環(huán)境配置
欄 目:ASP.NET
本文標(biāo)題:使用.NET Core實(shí)現(xiàn)餓了嗎拆紅包功能
本文地址:http://www.jygsgssxh.com/a1/ASP_NET/10902.html
您可能感興趣的文章
- 01-11如何給asp.net core寫(xiě)個(gè)簡(jiǎn)單的健康檢查
- 01-11淺析.Net Core中Json配置的自動(dòng)更新
- 01-11.net core高吞吐遠(yuǎn)程方法如何調(diào)用組件XRPC詳解
- 01-11.NET Core 遷移躺坑記續(xù)集之Win下莫名其妙的超時(shí)
- 01-11.NET開(kāi)發(fā)人員關(guān)于ML.NET的入門(mén)學(xué)習(xí)
- 01-11docker部署Asp.net core應(yīng)用的完整步驟
- 01-11.net core webapi jwt 更為清爽的認(rèn)證詳解
- 01-11ASP.NET Core靜態(tài)文件的使用方法
- 01-11.NET Core 3.0之創(chuàng)建基于Consul的Configuration擴(kuò)展組件
- 01-11.net core EF Core調(diào)用存儲(chǔ)過(guò)程的方式


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-11vscode extension插件開(kāi)發(fā)詳解
- 01-11VsCode插件開(kāi)發(fā)之插件初步通信的方法
- 01-11如何給asp.net core寫(xiě)個(gè)簡(jiǎn)單的健康檢查
- 01-11.net core高吞吐遠(yuǎn)程方法如何調(diào)用組件
- 01-11淺析.Net Core中Json配置的自動(dòng)更新
- 01-11.NET開(kāi)發(fā)人員關(guān)于ML.NET的入門(mén)學(xué)習(xí)
- 01-11.NET Core 遷移躺坑記續(xù)集之Win下莫名其
- 01-11.net core webapi jwt 更為清爽的認(rèn)證詳解
- 01-11docker部署Asp.net core應(yīng)用的完整步驟
- 01-11ASP.NET Core靜態(tài)文件的使用方法
隨機(jī)閱讀
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 04-02jquery與jsp,用jquery
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法


