120 lines
3.5 KiB
PHP
120 lines
3.5 KiB
PHP
<?php
|
||
|
||
namespace App\Jobs;
|
||
|
||
use Illuminate\Bus\Queueable;
|
||
use Illuminate\Queue\SerializesModels;
|
||
use Illuminate\Queue\InteractsWithQueue;
|
||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||
use Illuminate\Foundation\Bus\Dispatchable;
|
||
use App\Models\ParticipantRedPacket;
|
||
class CreateParticipantPacket implements ShouldQueue
|
||
{
|
||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||
|
||
protected $min;
|
||
protected $max;
|
||
protected $num;
|
||
protected $total;
|
||
/**
|
||
* Create a new job instance.
|
||
*
|
||
* @return void
|
||
*/
|
||
public function __construct($data)
|
||
{
|
||
$this->min = $data['min'];
|
||
$this->max = $data['max'];
|
||
$this->num = $data['num'];
|
||
$this->total = $data['total'];
|
||
}
|
||
|
||
/**
|
||
* Execute the job.
|
||
*
|
||
* @return void
|
||
*/
|
||
public function handle()
|
||
{
|
||
$min = $this->min;
|
||
$max = $this->max;
|
||
$num = $this->num;
|
||
$total = $this->total;
|
||
if ($max) {
|
||
$packet_arr = $this->rand_section($min, $max, $num, $total);
|
||
}else{
|
||
$packet_arr = $this->demo($total, $num, $min);
|
||
}
|
||
|
||
ParticipantRedPacket::insert($packet_arr);
|
||
}
|
||
|
||
public function rand_section($min,$max,$num,$total){
|
||
|
||
$data = array();
|
||
if ($min * $num > $total) {
|
||
return array();
|
||
}
|
||
if($max*$num < $total){
|
||
return array();
|
||
}
|
||
while ($num >= 1) {
|
||
$num--;
|
||
$kmix = max($min, $total - $num * $max);
|
||
$kmax = min($max, $total - $num * $min);
|
||
$kAvg = $total / ($num + 1);
|
||
//获取最大值和最小值的距离之间的最小值
|
||
$kDis = min($kAvg - $kmix, $kmax - $kAvg);
|
||
//获取0到1之间的随机数与距离最小值相乘得出浮动区间,这使得浮动区间不会超出范围
|
||
$r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
|
||
$k = sprintf("%.2f", $kAvg + $r);
|
||
$total -= $k;
|
||
// $data[] = $k;
|
||
$arr = [];
|
||
$arr['price'] = $k;
|
||
$arr['created_at']=date('Y-m-d H:i:s');
|
||
$arr['updated_at']=date('Y-m-d H:i:s');
|
||
$data[] = $arr;
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
function demo($total, $num, $min = 0.01)
|
||
{
|
||
$overPlus = $total - $num * $min; // 剩余待发钱数
|
||
$base = 0; // 总基数
|
||
// 存放所有人数据
|
||
$container = array();
|
||
// 每个人保底
|
||
for ($i = 0; $i < $num; $i++) {
|
||
// 计算比重
|
||
$weight = round(lcg_value() * 1000);
|
||
$container[$i]['weight'] = $weight; // 权重
|
||
$container[$i]['money'] = $min; // 最小值都塞进去
|
||
$base += $weight; // 总基数
|
||
}
|
||
|
||
$len = $num - 1; // 下面要计算总人数-1的数据,
|
||
for ($i = 0; $i < $len; $i++) {
|
||
$money = floor($container[$i]['weight'] / $base * $overPlus * 100) / 100; // 向下取整,否则会超出
|
||
$container[$i]['money'] += $money;
|
||
}
|
||
|
||
// 弹出最后一个元素
|
||
array_pop($container);
|
||
$result = array_column($container, 'money');
|
||
$last_one = round($total - array_sum($result), 2);
|
||
array_push($result, $last_one);
|
||
$data = [];
|
||
foreach ($result as $res) {
|
||
$arr = [];
|
||
$arr['price'] = $res;
|
||
$arr['created_at']=date('Y-m-d H:i:s');
|
||
$arr['updated_at']=date('Y-m-d H:i:s');
|
||
$data[] = $arr;
|
||
}
|
||
return $data;
|
||
}
|
||
|
||
}
|