php 抽奖算法

<?php
 require '../vendor/autoload.php';

class Draw
{
    //奖品池
    public static $prizes = [
        ['id' => 1, 'name' => 'iphone', 'num' => 1, 'surplusNum' => 1],
        ['id' => 2, 'name' => '小米max', 'num' => 100, 'surplusNum' => 100],
        ['id' => 3, 'name' => '小米3', 'num' => 200, 'surplusNum' => 200],
        ['id' => 4, 'name' => '山寨机', 'num' => 1000, 'surplusNum' => 1000],
        ['id' => 5, 'name' => '安慰奖', 'num' => 50000, 'surplusNum' => 50000],
    ];
    //参加人数
    public static $maxNum = 0;
    //设置中奖名单
    public static $luckList = [];

    /**
     * 设定权重
     */
    public function settingDraw()
    {
        return array(
            array('id' => 1, 'name' => '一等奖', 'pid' => 1, 'v' => 1.5),
            array('id' => 2, 'name' => '二等奖', 'pid' => 2, 'v' => 2.5),
            array('id' => 3, 'name' => '三等奖', 'pid' => 3, 'v' => 10),
            array('id' => 4, 'name' => '四等奖', 'pid' => 4, 'v' => 100),
            array('id' => 5, 'name' => '五等奖', 'pid' => 5, 'v' => 100000),
            array('id' => 6, 'name' => '没中奖', 'pid' => 6, 'v' => 1000000)
        );
    }

    /**
     * 获得第一次抽奖结果
     * @param $proArr
     * @return array
     */
    public function drawResultOne($proArr)
    {
        $result = array();
        foreach ($proArr as $key => $val) {
            $arr[$key] = $val['v'];
        }
        // 概率数组的总概率
        $proSum = array_sum($arr);
        asort($arr);
        // 概率数组循环
        foreach ($arr as $k => $v) {
            $randNum = mt_rand(1, $proSum);
            if ($randNum <= $v) {
                $result = $proArr[$k];
                break;
            } else {
                $proSum -= $v;
            }
        }
        return $result;
    }

    /**
     *
     * 获取抽奖结果
     */
    public function run($user)
    {
        self::$maxNum += 1;
        //获取权重设置
        $drawRules = $this->settingDraw();
        //获得第一次抽奖结果
        $drawResult = $this->drawResultOne($drawRules);
        //读取奖池
        if ((array_search($drawResult, $drawRules) + 1) == count($drawRules)) {
            $user['get'] = $drawResult['name'];
            return $user;
        } else {
            foreach (self::$prizes as $k => &$v) {
                if ($drawResult['pid'] == $v['id']) {
                    if ($v['surplusNum'] <= 0) {
                        $user['get'] = '没中奖';
                        break;
                    } else {
                        array_push(self::$luckList, ['username' => $user['name'], 'good' => $drawResult['name'].'---'.$v['name']]);
                        $user['get'] = $drawResult['name'];
                        $v['surplusNum'] -= 1;
                    }
                }
            }
            return $user;
        }
    }

}

function dd($data)
{
    echo "<pre/>";
    print_r($data);
}


//随机生成用户数量
$users = [];
$userNum = mt_rand(1000, 100000);
$users = array_pad($users, $userNum, ['id' => '', 'name' => '', 'get' => '']);
//$users = array_chunk($users,100);
$obj = new Draw();
foreach ($users as $k => $v) {
    $v['id'] = $k + 1;
    $v['name'] = 'user' . ((string)$k + 1);
    $users[$k] = $obj->run($v);
}

//中奖结果
dd($users);
echo "<hr/>";
//奖品剩余情况
dd($obj::$prizes);
////参加人数
echo "<hr/>";
dd($obj::$maxNum);
////获奖名单
echo "<hr/>";
dd($obj::$luckList);

  计算部分不是原创 参考 https://segmentfault.com/a/1190000007431893

posted @ 2017-11-17 11:14  Vitascope  阅读(169)  评论(0编辑  收藏  举报