前言: 没有特别幸运,那么请先特别努力,别因为懒惰而失败,还矫情地将原因归于自己倒霉。你必须特别努力,才能显得毫不费力。
希望:所以说,树倒了,没有一片雪花是无辜的,抽奖都是假的,只有人家想让你中和不想让你中,如果大家觉得文章有帮助,请给博主一波关注和评论。
目录
一、初始化奖品
- id 奖品的id
- pid 奖品的自定义id
- type 奖品类型,1、虚拟奖品 2、实物奖品 3、礼包码 待扩充
- name 奖品名称
- total 奖品总数
- chance 获奖概率/抽奖基数10000
- daynum 每日数量限制
- pay 充值限制
-
<?php
-
$prize = [
-
[
'id' =>
1,
'pid' =>
11,
'type' =>
1,
'name' =>
'典藏英雄',
'total' =>
20,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
2000 ],
-
[
'id' =>
2,
'pid' =>
12,
'type' =>
1,
'name' =>
'史诗皮肤',
'total' =>
40,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
4000 ],
-
[
'id' =>
3,
'pid' =>
13,
'type' =>
1,
'name' =>
'钻石奖励',
'total' =>
80,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
4000 ],
-
[
'id' =>
4,
'pid' =>
14,
'type' =>
1,
'name' =>
'荣耀水晶',
'total' =>
20,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
8000 ]
-
];
- 奖品详情应该从数据库中读出来
- 奖品详情应该加入缓存,避免数据库的压力
二、谢谢参与
-
<?php
-
$thanks_prize = [
-
'id' =>
0,
-
'pid' =>
0,
-
'type' =>
1,
-
'name' =>
'谢谢参与'
-
];
- 为填充剩余概率的奖品
三、过滤抽奖、如充值条件
-
<?php
-
$pay_total =
7000;
-
foreach ($prize
as $key => $value) {
-
if($value[
'pay'] > $pay_total)
unset($prize[$key]);
-
}
- 初步过滤一些必要因素,比如充值,角色创建时间等
四、重组概率
-
<?php
-
$now_chance = array_sum(array_column($prize,
'chance'));
-
$remain_chance =
10000 - $now_chance;
-
$prize[] = [
'id' =>
0,
'pid' =>
0,
'type' =>
1,
'name' =>
'谢谢参与',
'total' =>
0,
'chance' => $remain_chance,
'daynum' =>
0,
'pay' =>
0];
-
-
$award = [];
-
$num =
0;
-
foreach ($prize
as $_v) {
-
$num += $_v[
'chance'];
-
$award[] = [
'id' => $_v[
'id'],
'pid' => $_v[
'pid'],
'type' => $_v[
'type'],
'name' => $_v[
'name'],
'total' => $_v[
'total'],
'chance' => $num,
'daynum' => $_v[
'daynum'],
'pay' => $_v[
'pay']];
-
}
- 初步过滤后,重构新的抽奖信息,加入谢谢参与
- 第二步重组概率
五、进行抽奖
-
<?php
-
$rand = mt_rand(
1,
10000);
-
$result = [];
-
foreach ($award
as $_k => $_v) {
-
if ($_k ==
0) {
-
if ($rand >
0 && $rand <= $_v[
'chance']) {
-
$result = $_v;
-
break;
-
}
-
}
else {
-
if ($rand > $award[$_k -
1][
'chance'] && $rand <= $_v[
'chance']) {
-
$result = $_v;
-
break;
-
}
-
}
-
}
-
开始抽奖,并返回抽中的结果
六、过滤回调
-
<?php
-
//此处应该查询数据库,查看该奖品已经抽中的数量
-
$yet_num =
50;
-
if($result[
'pid'] !=
0 && $yet_num > $result[
'total']) {
-
$result = $thanks_prize;
-
}
-
-
//此处应该查询数据库,查看该奖品今日已经抽中的数量
-
$yet_today_num =
50;
-
if($result[
'pid'] !=
0 && $yet_today_num > $result[
'daynum']) {
-
$result = $thanks_prize;
-
}
- 二次过滤,奖品总数的限制以及奖品的每日限制等
七、最终抽奖结果
-
<?php
-
//删除敏感字段
-
unset($result[
'total'],$result[
'chance'],$result[
'daynum'],$result[
'pay']);
-
-
//返回最终抽奖结果
-
echo json_encode([
-
'prize' => $award,
-
'rand' => $rand,
-
'result' => $result
-
]);
八、抽奖封装成类
-
<?php
-
/**
-
* Created by PhpStorm.
-
* User: autofelix
-
* Date: 2020/10/30
-
* Time: 13:14
-
* Desc: 抽奖算法
-
*/
-
-
class Lottery
-
{
-
/**
-
* 概率基数
-
* @var int
-
*/
-
private $total_chance =
10000;
-
-
/**
-
* 谢谢参与奖励
-
* @var array
-
*/
-
private $thanks_prize = [
-
'id' =>
0,
-
'pid' =>
0,
-
'type' =>
1,
-
'name' =>
'谢谢参与'
-
];
-
-
/**
-
* 奖池
-
* @var array
-
*/
-
private $prize = [
-
[
'id' =>
1,
'pid' =>
11,
'type' =>
1,
'name' =>
'典藏英雄',
'total' =>
20,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
2000 ],
-
[
'id' =>
2,
'pid' =>
12,
'type' =>
1,
'name' =>
'史诗皮肤',
'total' =>
40,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
4000 ],
-
[
'id' =>
3,
'pid' =>
13,
'type' =>
1,
'name' =>
'钻石奖励',
'total' =>
80,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
4000 ],
-
[
'id' =>
4,
'pid' =>
14,
'type' =>
1,
'name' =>
'荣耀水晶',
'total' =>
20,
'chance' =>
1000,
'daynum' =>
10,
'pay' =>
8000 ]
-
];
-
-
/**
-
* Lottery constructor.
-
*/
-
public
function __construct()
-
{
-
}
-
-
/**
-
* @return int
-
*/
-
private
function get_user_pay()
-
{
-
//这里应该调用接口,返回用户正确的充值信息
-
return
3000;
-
}
-
-
/**
-
* 重构奖池、重组概率
-
* @return array
-
*/
-
private
function init_lottery_pond()
-
{
-
$award = [];
-
-
//充值限制
-
$user_pay =
$this->get_user_pay();
-
foreach (
$this->prize
as $key => $value) {
-
if($value[
'pay'] <= $user_pay)
unset(
$this->prize[$key]);
-
}
-
-
//加入谢谢惠顾
-
$now_chance = array_sum(array_column(
$this->prize,
'chance'));
-
$remain_chance =
$this->total_chance - $now_chance;
-
$this->prize[] = [
'id' =>
0,
'pid' =>
0,
'type' =>
1,
'name' =>
'谢谢参与',
'total' =>
0,
'chance' => $remain_chance,
'daynum' =>
0,
'pay' =>
0];
-
-
//重组概率
-
$num =
0;
-
foreach (
$this->prize
as $_v) {
-
$num += $_v[
'chance'];
-
$award[] = [
'id' => $_v[
'id'],
'pid' => $_v[
'pid'],
'type' => $_v[
'type'],
'name' => $_v[
'name'],
'total' => $_v[
'total'],
'chance' => $num,
'daynum' => $_v[
'daynum'],
'pay' => $_v[
'pay']];
-
}
-
-
return $award;
-
}
-
-
/**
-
* 获取抽奖结果
-
* @return array
-
*/
-
public
function get_prize()
-
{
-
$award =
$this->init_lottery_pond();
-
$rand = mt_rand(
1,
$this->total_chance);
-
$result = [];
-
foreach ($award
as $_k => $_v) {
-
if ($_k ==
0) {
-
if ($rand >
0 && $rand <= $_v[
'chance']) {
-
$result = $_v;
-
break;
-
}
-
}
else {
-
if ($rand > $award[$_k -
1][
'chance'] && $rand <= $_v[
'chance']) {
-
$result = $_v;
-
break;
-
}
-
}
-
}
-
-
$result =
$this->filter($result);
-
return $result;
-
}
-
-
/**
-
* 抽奖过滤回调函数
-
* @param $result
-
* @return array
-
*/
-
public
function filter($result)
-
{
-
//奖品总数限制,此处应该查数据库
-
$yet_num =
50;
-
if($result[
'pid'] !=
0 && $yet_num > $result[
'total']) {
-
$result =
$this->thanks_prize;
-
}
-
-
//奖品每日数量限制,此处应该查数据库
-
$yet_today_num =
50;
-
if($result[
'pid'] !=
0 && $yet_today_num > $result[
'daynum']) {
-
$result =
$this->thanks_prize;
-
}
-
-
//不暴露敏感信息
-
unset($result[
'total'], $result[
'chance'], $result[
'daynum'], $result[
'pay'] );
-
return $result;
-
}
-
-
private
function __clone()
-
{
-
}
-
}
-
-
echo json_encode((
new Lottery())->get_prize());
转载:https://blog.csdn.net/weixin_41635750/article/details/109390653
查看评论