高度可自定义 抽奖概率 解决方案 PHP

客户很多时候难以正确理解概率的意义,或者难以给出概率,此时可大致上把奖品数量作为权重进行抽奖
权重作为概率抽奖时,可以用循环把每个奖品放进数组,权重多大就有多少个值,然后用array_rand获取数组的key,再获得奖品
但是客户可能要求不同时段概率不同,所以我们可以事先将所有概率和时段的关系写好,然后抽奖时进行判断,获取相应的权重数组,之后再执行上述权重作为概率抽奖

权重抽奖实例

$current = date('Y-m-d H:i:s');
// $current = '2018-08-30 18:30:00';
$keys   = array_keys($this->weight);
$period = [];
$nowkey = '';
foreach ($keys as $k => $v)
{
    // 当前约束
    $nowkey = $v;

    // 最后一个
    if ($v == '2018-09-15 00:00:00')
    {
        $period = $this->weight[$nowkey];
        break;
    }

    //
    $nextkey = $keys[$k + 1];
    if ($current >= $nowkey && $current < $nextkey)
    {
        $period = $this->weight[$nowkey];
        break;
    }
}
$result = array_intersect($this->prize, $giftlist);
$gifts  = [];
foreach ($period as $k => $value)
{
    if (empty($result[$k]))
    {
        continue;
    }
    for ($i = 0; $i < $value; $i++)
    {
        $gifts[] = $k;
    }
}

$giftindex = $gifts[array_rand($gifts)];
return $result[$giftindex];

权重写法如下

public $weight = ['2018-08-30 00:00:00' => [7862, 0, 0, 0, 0, 0, 0, 0, 0, 1069, 1069]];

以上写法在为建行做的抽奖活动中使用,经受住了实践的检验,但是很明显,当客户要求两个奖品概率相差千倍时候,他的效率不高
于是给出以下改进方案,把每个奖品与数字区间对应,然后使用mt_rand即可高效的随机获得奖品
以下方案在为加拿大牛肉协会做的抽奖活动中使用过,经受住了实践检验

改进写法

class Weight
{
    public $prize = ['1', '2', '3', '4'];

    public $default = 4;

    public $weight = [
        '2018-09-04 00:00:00' => [[0, 1], [2, 11], [12, 212], [213, 1013]],
    ];

    public function rand($giftlist)
    {
        $current = date('Y-m-d H:i:s');
        $keys    = array_keys($this->weight);
        // 当前概率
        $period = [];
        // 当前日期
        $nowkey = '';
        foreach ($keys as $k => $v)
        {
            // 当前约束
            $nowkey = $v;

            // 最后一个
            if ($v == $keys[count($keys) - 1])
            {
                $period = $this->weight[$nowkey];
                break;
            }

            //
            $nextkey = $keys[$k + 1];
            if ($current >= $nowkey && $current < $nextkey)
            {
                $period = $this->weight[$nowkey];
                break;
            }
        }

        // 可中奖品
        $result = array_intersect($this->prize, $giftlist);

        // 全部奖品
        $gifts = [];
        foreach ($period as $k => $value)
        {
            $gifts = array_merge($gifts, $value);
        }
        sort($gifts);
        $len = count($gifts);

        // 抽奖号码
        $giftnumber = mt_rand($gifts[0], $gifts[$len - 1]);

        foreach ($period as $key => $value)
        {
            if (empty($result[$key]))
            {
                $prize = $this->default;
                break;
            }
            if ($giftnumber >= $value[0] && $giftnumber <= $value[1])
            {
                $prize = $result[$key];
                break;
            }
        }
        return $prize;
    }
}

相关文章

此处评论已关闭