1 需求
写一个固定红包 + 随机红包
固定红包就是每个红包金额一样,有多少个就发多少个固定红包金额就行。
随机红包的需求是。比如红包总金额5元,需要发10个红包。随机范围是 0.01到0.99;5元必需发完,金额需要有一定趋势的正态分布。(0.99可以任意指定,也可以是 avg * 2 - 0.01;比如avg = 5 / 10 = 0.5;(avg * 2 - 0.01 = 0.99))
2 需求分析
2.1 固定红包
如果是固定红包,则算法是一条直线。t就是固定红包的额度。如图。
f(x) = t;(1 <= x <= num)
image.png
2.2 随机红包
如果我们使用随机函数rand。rand(0.01,0.99);那么10次随机,如果最坏情况都是金额0.99,总金额就是9.9元。会超过5元。金额也会不正态分布。最后思考了一下借助与数学函数来当作随机红包的发生器,可以用抛物线,三角函数。最后选定了等腰三角线性函数。
1 算法原理
如果需要发红包总金额是totalMoney,红包个数是num个,金额范围是[min,max],线性方程如图。
image.png
三个点的坐标:
(x1,y1) = (1,min)
(x2,y2) = (num/2,max)
(x3,y3) = (num,min)
确定的线性方程:
$y = 1.0 * ($x - $x1) / ($x2 - $x1) * ($y2 - $y1) + $y1 ; (x1 <= x <= x2)
$y = 1.0 * ($x - $x2) / ($x3 - $x2) * ($y3 - $y2) + $y2; (x2 <= x <= x3)
修数据:
y(合) = y1 + y2 + y3 +...... ynum;
y(合)有可能 > totalMoney ,说明生成金额多了,需要修数据,则从(y1,y2,y3.....ynum)这些每次减少0.01。直到y(合) = totalMoney。
y(合)有可能 < totalMoney ,说明生成金额少了,需要修数据,则从(y1,y2,y3.....ynum)这些每次加上0.01。直到y(合) = totalMoney。
2 算法原理样例
如果需要发红包总金额是11470,红包个数是7400个,金额范围是[0.01,3.09],线性方程如图。
image.png
3 需求设计
3.1 类图设计
image.png
3.2 源码设计
/**
* 随机红包+固定红包算法[策略模式]
* copyright (c) 2016 http://blog.csdn.net/CleverCode
*/
//配置传输数据DTO
class OptionDTO
{
//红包总金额
public $totalMoney;
//红包数量
public $num;
//范围开始
public $rangeStart;
//范围结算
public $rangeEnd;
//生成红包策略
public $builderStrategy;
//随机红包剩余规则
public $randFormatType; //Can_Left:不修数据,可以有剩余;No_Left:不能有剩余
public static function create($totalMoney,$num,$rangeStart,$rangEnd,
$builderStrategy,$randFormatType = 'No_Left')
{
$self = new self();
$self->num = $num;
$self->rangeStart = $rangeStart;
$self->rangeEnd = $rangEnd;