php 实现红包随机领取

vendor下创建文件

<?php

namespace common\vendor;

class LiveMoney
{
    protected $amount;
    protected $num;
    protected $coupon_min;
    protected $items = [];
    /**
     * 初始化
     * @param float $amount     红包金额(单位:元)最多保留2位小数
     * @param int   $num        红包个数
     * @param float $coupon_min 每个至少领取的红包金额
     */
    public function __construct($amount, $num = 1, $coupon_min = 0.01)
    {
        $this->amount = $amount;
        $this->num = $num;
        $this->coupon_min = $coupon_min;
    }
    /**
     * 处理返回
     * @return array
     */
    public function handle()
    {
        // A. 验证
        if ($this->amount < $validAmount = $this->coupon_min * $this->num) {
            throw new Exception('红包总金额必须≥'.$validAmount.'元');
        }
        // B. 分配红包
        $this->apportion();
        return [
            'items' => $this->items,
        ];
    }
    /**
     * 分配红包
     */
    protected function apportion()
    {
        $num = $this->num; 
        $amount = $this->amount; 
        while ($num >= 1) {
            // 剩余一个的时候,直接取剩余红包
            if ($num == 1) {
                $coupon_amount = $this->decimal_number($amount);
            } else {
                $avg_amount = $this->decimal_number($amount / $num);  // 剩余的红包的平均金额
                $coupon_amount = $this->decimal_number(
                    $this->calcCouponAmount($avg_amount, $amount, $num)
                );
            }
            $this->items[] = $coupon_amount; // 追加分配
            $amount -= $coupon_amount;
            --$num;
        }
        shuffle($this->items);  //随机打乱
    }
    /**
     * 计算分配的红包金额
     *
     * @param float $avg_amount 每次计算的平均金额
     * @param float $amount     剩余可领取金额
     * @param int   $num        剩余可领取的红包个数
     * @return float
     */
    protected function calcCouponAmount($avg_amount, $amount, $num)
    {
        // 如果平均金额小于等于最低金额,则直接返回最低金额
        if ($avg_amount <= $this->coupon_min) {
            return $this->coupon_min;
        }
        // 浮动计算
        $coupon_amount = $this->decimal_number($avg_amount * (1 + $this->apportionRandRatio()));
        // 如果低于最低金额或超过可领取的最大金额,则重新获取
        if ($coupon_amount < $this->coupon_min
            || $coupon_amount > $this->calcCouponAmountMax($amount, $num)
        ) {
            return $this->calcCouponAmount($avg_amount, $amount, $num);
        }
        return $coupon_amount;
    }
    /**
     * 计算分配的红包金额-可领取的最大金额
     * @param float $amount
     * @param int   $num
     */
    protected function calcCouponAmountMax($amount, $num)
    {
        return $this->coupon_min + $amount - $num * $this->coupon_min;
    }
    /**
     * 红包金额浮动比例
     */
    protected function apportionRandRatio()
    {
        // 60%机率获取剩余平均值的大幅度红包(可能正数、可能负数)
        if (rand(1, 100) <= 60) {
            return rand(-70, 70) / 100; // 上下幅度70%
        }
        return rand(-30, 30) / 100; // 其他情况,上下浮动30%;
    }
    /**
     * 格式化金额,保留2位
     * @param float $amount
     * @return float
     */
    protected function decimal_number($amount)
    {
        return sprintf('%01.2f', round($amount, 2));
    }
}

控制器文件

//随机生成一个红包金额
        $coupon = new LiveMoney($moneyInfo['sheng_money'],$sheng_num,0.01);   //剩余金额  可领人数    最小金额
        $res = $coupon->handle();
        // var_dump($coupon);
        $a = mt_rand(0,count($res['items'])-1);   //随机取数组中的一个
        // var_dump($a);
        // var_dump($res['items'][$a]);die;

$a即为随机红包的一个值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值