爆币
This commit is contained in:
43
application/api/controller/Lottery.php
Normal file
43
application/api/controller/Lottery.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\common\controller\BaseCom;
|
||||
use app\common\service\LotteryService;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\Log;
|
||||
|
||||
class Lottery extends BaseCom
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 中奖统计接口
|
||||
* @return json
|
||||
*/
|
||||
public function stat()
|
||||
{
|
||||
try {
|
||||
$where = [
|
||||
'uid' => $this->request->param('uid/d', 0),
|
||||
'prize_type' => $this->request->param('prize_type/d', 0),
|
||||
'start_time' => $this->request->param('start_time/d', 0),
|
||||
'end_time' => $this->request->param('end_time/d', time())
|
||||
];
|
||||
$service = new LotteryService();
|
||||
$stat = $service->statWinner($where);
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '统计成功',
|
||||
'data' => $stat
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
Log::error('中奖统计失败:' . $e->getMessage());
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => $e->getMessage(),
|
||||
'data' => []
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,13 +183,17 @@ class Room extends BaseCom
|
||||
redis_lock_exit($key_name);
|
||||
$room_id = input('room_id', 0);
|
||||
$gift_id = input('gift_id', 0);
|
||||
$gift_num = input('gift_num', 0);
|
||||
$gift_num = input('gift_num', 1);
|
||||
$to_uid = input('to_uid', 0);//收礼人ID,逗号隔开的字符串
|
||||
$type = input('type', 1);//1金币购买 2送背包礼物
|
||||
$pit_number = input('pit_number', 0);
|
||||
$heart_id = input('heart_id', 0);
|
||||
|
||||
$reslut = model('Room')->room_gift($this->uid, $to_uid, $gift_id, $gift_num, $type, $room_id, $pit_number,$heart_id);
|
||||
if($gift_id == 88){
|
||||
$reslut = model('Lottery')->gift($this->uid, $to_uid, $gift_id, $room_id,$gift_num);
|
||||
}else{
|
||||
$reslut = model('Room')->room_gift($this->uid, $to_uid, $gift_id, $gift_num, $type, $room_id, $pit_number,$heart_id);
|
||||
}
|
||||
redis_unlock($key_name);
|
||||
return V($reslut['code'], $reslut['msg'], $reslut['data']);
|
||||
}
|
||||
|
||||
@@ -148,6 +148,10 @@ class Chat extends Model
|
||||
//签约房 邀请用户上签约麦位
|
||||
// SignRoomInviteUser = 1094,
|
||||
|
||||
//爆币房推送信息
|
||||
// BlindCoinRoom = 1100,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
149
application/api/model/Lottery.php
Normal file
149
application/api/model/Lottery.php
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\model;
|
||||
|
||||
use app\common\service\LotteryService;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\Log;
|
||||
use think\Model;
|
||||
|
||||
class Lottery extends Model
|
||||
{
|
||||
/**
|
||||
* 送礼参与抽奖接口
|
||||
* @return json
|
||||
*/
|
||||
public function gift($send_uid, $recv_uid,$gift_id, $room_id, $num)
|
||||
{
|
||||
if (ceil($num) != $num) {
|
||||
return ['code' => 0, 'msg' => '打赏礼物数量必须为整数', 'data' => null];
|
||||
}
|
||||
$toarray = explode(',',$recv_uid);
|
||||
if(in_array($send_uid,$toarray)){
|
||||
return ['code' => 0, 'msg' => '收礼人不能包含自己', 'data' => null];
|
||||
}
|
||||
$gift_info = Db::name('vs_gift')->where(['gid'=>$gift_id])
|
||||
->field('gid as gift_id,gift_name,gift_price,file_type,base_image,play_image,gift_type,label,is_public_server')->find();
|
||||
//送给所有人的总价格
|
||||
$all_gift_price = $gift_info['gift_price'] * $num * count($toarray);
|
||||
//判断是否有足够的金币
|
||||
$user_waller = db::name('user_wallet')->where(['user_id'=>$send_uid])->find();
|
||||
if ($user_waller['coin'] < $all_gift_price) {
|
||||
return ['code' => 0, 'msg' => '用户金币不足', 'data' => null];
|
||||
}
|
||||
|
||||
$nums = $num * count($toarray);
|
||||
$this->lottery($send_uid,$gift_info['gift_price'],$nums,$room_id,$gift_id);
|
||||
|
||||
//送礼 开启事务
|
||||
Db::startTrans();
|
||||
//扣除用户金币并记录日志
|
||||
$wallet_update = model('GiveGift')->change_user_cion_or_earnings_log($send_uid,$all_gift_price,$room_id,1,10,'用户金币购买礼物');
|
||||
if(!$wallet_update){
|
||||
Db::rollback();
|
||||
return ['code' => 0, 'msg' => '扣除用户金币失败', 'data' => null];
|
||||
}
|
||||
//用户财富等级更新
|
||||
$user_level = model('Level')->user_level_data_update($send_uid,$all_gift_price,1,$room_id);
|
||||
if(!$user_level){
|
||||
Db::rollback();
|
||||
return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null];
|
||||
}
|
||||
|
||||
//获取送礼用户昵称
|
||||
$FromUserInfo = db::name('user')->where('id',$send_uid)->field('id as user_id,nickname,avatar,sex')->find();
|
||||
$FromUserInfo['icon'][0] = model('UserData')->user_wealth_icon($send_uid);//财富图标
|
||||
$FromUserInfo['icon'][1] = model('UserData')->user_charm_icon($send_uid);//魅力图标
|
||||
$FromUserInfo['chat_bubble'] = model('Decorate')->user_decorate_detail($send_uid,9);//聊天气泡
|
||||
|
||||
//送给一人礼物的总价格(扣除用户的数额)
|
||||
$gift_price = $gift_info['gift_price'] * $num;
|
||||
|
||||
foreach ($toarray as $k => $to_id){
|
||||
// 1. 记录礼物赠送
|
||||
$giftRecord = [
|
||||
'send_uid' => $send_uid,
|
||||
'recv_uid' => $recv_uid,
|
||||
'gift_id' => $gift_id,
|
||||
'gift_gold' => $gift_price,
|
||||
'recv_gold' => $gift_price /2 ,
|
||||
'small_pool_add' => $gift_price /2 ,
|
||||
'create_time' => time()
|
||||
];
|
||||
$giftId = Db::name('bb_lottery_gift_record')->insertGetId($giftRecord);
|
||||
|
||||
//收礼记录行为日志
|
||||
$give_gift = model('GiveGift')->change_user_give_gift_log($send_uid,$gift_id,$gift_price,$num,$to_id,2,1,$room_id,0);
|
||||
if(!$give_gift){
|
||||
Db::rollback();
|
||||
return ['code' => 0, 'msg' => '送礼失败', 'data' => null];
|
||||
}
|
||||
//计算收礼人得益
|
||||
$receiver_earnings = model('GiveGift')->receiver_earnings($to_id,$gift_price,2);
|
||||
//增加收益并记录日志
|
||||
$receiver = $this -> change_user_cion_or_earnings_log($to_id,$receiver_earnings,$room_id,2,11,'收礼增加收益');
|
||||
|
||||
//用户魅力等级更新
|
||||
$user_level = model('Level')->user_level_data_update($to_id,$gift_price,2,$room_id);
|
||||
if(!$user_level){
|
||||
Db::rollback();
|
||||
return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null];
|
||||
}
|
||||
|
||||
$ToUserInfo = Db::name('user')->where(['id' => $to_id])->field('id as user_id,nickname,avatar,sex')->find();
|
||||
$ToUserInfo['icon'][0] = model('UserData')->user_wealth_icon($to_id);//财富图标
|
||||
$ToUserInfo['icon'][1] = model('UserData')->user_charm_icon($to_id);//魅力图标
|
||||
$ToUserInfo['charm'] = db::name('vs_room_user_charm')->where(['user_id' => $to_id,'room_id' => $room_id])->value('charm');//魅力
|
||||
$text = $FromUserInfo['nickname'] . ' 送给 ' . $ToUserInfo['nickname'].' 礼物 ' .$gift_info['gift_name'].' x ' .$num;
|
||||
$text = [
|
||||
'FromUserInfo' => $FromUserInfo,
|
||||
'ToUserInfo' => $ToUserInfo,
|
||||
'GiftInfo' => $gift_info,
|
||||
'gift_num' => $num,
|
||||
'text' => $text
|
||||
];
|
||||
//聊天室推送系统消息
|
||||
model('Chat')->sendMsg(1005,$room_id,$text);
|
||||
}
|
||||
Db::commit();
|
||||
return ['code' => 1, 'msg' => '送礼成功', 'data' => null];
|
||||
}
|
||||
|
||||
|
||||
//抽奖
|
||||
public function lottery($send_uid,$gift_price,$num,$room_id,$giftId)
|
||||
{
|
||||
try {
|
||||
for($i=0;$i<$num;$i++){
|
||||
$gift_gold = $gift_price;
|
||||
$service = new LotteryService();
|
||||
$reslut = $service->handleGift($send_uid, $gift_gold, $giftId);
|
||||
if ($reslut['code'] == 1) {
|
||||
$result = $reslut['data'];
|
||||
//(未开奖时)
|
||||
if ($result['is_small_prize'] == 0) {
|
||||
//不做处理
|
||||
} else {//开奖
|
||||
// 大奖
|
||||
if ($result['is_big_prize'] == 1) {
|
||||
$tet['text'] = '爆币大奖';
|
||||
$tet['type'] = 1;
|
||||
} else { // 小奖
|
||||
$tet['text'] = '爆币小奖';
|
||||
$tet['type'] = 2;
|
||||
}
|
||||
$tet['user_id'] = $send_uid;
|
||||
$tet['play_image'] = '';
|
||||
model('api/Chat')->sendMsg(1100,$room_id,$tet);
|
||||
}
|
||||
}
|
||||
}
|
||||
return V(1, '送礼成功');
|
||||
} catch (Exception $e) {
|
||||
Log::error('抽奖处理失败:' . $e->getMessage());
|
||||
return V(0, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
135
application/common/library/LotteryGiftLua.php
Normal file
135
application/common/library/LotteryGiftLua.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\library;
|
||||
|
||||
class LotteryGiftLua
|
||||
{
|
||||
// 获取Lua脚本
|
||||
public static function getLotteryLuaScript()
|
||||
{
|
||||
return <<<LUA
|
||||
-- 接收参数:send_uid, recv_uid, gift_gold, small_trigger_times, big_threshold, small_round, big_round, big_total_gold
|
||||
local send_uid = ARGV[1]
|
||||
local recv_uid = ARGV[2]
|
||||
local gift_gold = tonumber(ARGV[3])
|
||||
local small_trigger_times = tonumber(ARGV[4])
|
||||
local big_threshold = tonumber(ARGV[5])
|
||||
local small_round = tonumber(ARGV[6]) -- 小奖池当前轮次
|
||||
local big_round = tonumber(ARGV[7]) -- 大奖池当前轮次
|
||||
local big_total_gold = tonumber(ARGV[8]) -- 大奖池当前轮次金额
|
||||
|
||||
-- 核心约束:强制小轮次 ≥ 大轮次
|
||||
if small_round < big_round then
|
||||
small_round = big_round
|
||||
end
|
||||
|
||||
-- 1. 基础金额拆分
|
||||
local recv_gold = gift_gold * 0.5
|
||||
local small_pool_add = gift_gold * 0.5
|
||||
|
||||
-- 2. Redis键定义
|
||||
local small_round_key = "lottery:small_pool:round"
|
||||
local small_total_times_key = "lottery:small_pool:total_times"
|
||||
local small_total_gold_key = "lottery:small_pool:total_gold"
|
||||
local big_round_key = "lottery:big_pool:round"
|
||||
local big_total_gold_key = "lottery:big_pool:total_gold"
|
||||
|
||||
-- 初始化轮次(确保Redis与入参一致)
|
||||
redis.call('set', small_round_key, small_round)
|
||||
redis.call('set', big_round_key, big_round)
|
||||
-- 初始化大奖池金额
|
||||
if big_total_gold == 0 or big_total_gold == nil then
|
||||
big_total_gold = tonumber(redis.call('get', big_total_gold_key) or 0)
|
||||
end
|
||||
|
||||
-- 3. 小奖池累计更新
|
||||
local small_total_times = tonumber(redis.call('incr', small_total_times_key))
|
||||
local small_total_gold = tonumber(redis.call('get', small_total_gold_key) or 0)
|
||||
small_total_gold = math.floor((small_total_gold + small_pool_add) * 100) / 100
|
||||
redis.call('set', small_total_gold_key, small_total_gold)
|
||||
|
||||
-- 4. 返回结果初始化(区分大小轮次)
|
||||
local result = {
|
||||
send_uid = send_uid,
|
||||
recv_uid = recv_uid,
|
||||
gift_gold = gift_gold,
|
||||
recv_gold = recv_gold,
|
||||
small_pool_add = small_pool_add,
|
||||
small_total_times = small_total_times,
|
||||
small_total_gold = small_total_gold,
|
||||
is_small_prize = 0,
|
||||
small_prize_amount = 0,
|
||||
small_remain_amount = 0,
|
||||
is_big_prize = 0,
|
||||
big_prize_amount = 0,
|
||||
big_release_amount = 0,
|
||||
small_round = small_round, -- 小奖池轮次
|
||||
big_round = big_round, -- 大奖池轮次
|
||||
big_total_gold = big_total_gold,
|
||||
-- 新增:记录要划入下一轮的小奖开奖金额
|
||||
small_prize_to_big_next_round = 0
|
||||
}
|
||||
|
||||
-- 5. 小奖池开奖判断(小轮次+1)
|
||||
if small_total_times >= small_trigger_times then
|
||||
result.is_small_prize = 1
|
||||
-- 小奖随机比例
|
||||
local small_ratio = math.random(2, 99)
|
||||
result.small_prize_amount = math.floor(small_total_gold * small_ratio / 100 * 100) / 100
|
||||
-- 小奖剩余金额(划入大奖池当前轮次)
|
||||
result.small_remain_amount = math.floor((small_total_gold - result.small_prize_amount) * 100) / 100
|
||||
|
||||
-- 重置小奖池,小轮次+1
|
||||
redis.call('set', small_total_times_key, 0)
|
||||
redis.call('set', small_total_gold_key, 0)
|
||||
small_round = small_round + 1
|
||||
redis.call('set', small_round_key, small_round)
|
||||
result.small_round = small_round
|
||||
|
||||
-- 6. 小奖剩余划入大奖池当前轮次
|
||||
big_total_gold = math.floor((big_total_gold + result.small_remain_amount) * 100) / 100
|
||||
redis.call('set', big_total_gold_key, big_total_gold)
|
||||
result.big_total_gold = big_total_gold
|
||||
|
||||
-- 7. 大奖池开奖判断(大轮次+1)
|
||||
if big_total_gold >= big_threshold then
|
||||
result.is_big_prize = 1
|
||||
-- 大奖比例权重
|
||||
local weight_sum = 20 + 50 + 30
|
||||
local random_weight = math.random(1, weight_sum)
|
||||
local big_ratio = random_weight <= 20 and 60 or (random_weight <= 70 and 70 or 80)
|
||||
-- 大奖金额
|
||||
result.big_prize_amount = math.floor(big_total_gold * big_ratio / 100 * 100) / 100
|
||||
result.big_release_amount = math.floor((big_total_gold - result.big_prize_amount) * 100) / 100
|
||||
|
||||
-- 原有逻辑:重置大奖池,大轮次+1
|
||||
redis.call('set', big_total_gold_key, 0)
|
||||
big_round = big_round + 1
|
||||
redis.call('set', big_round_key, big_round)
|
||||
-- 强制保证小轮次≥大轮次
|
||||
if small_round < big_round then
|
||||
small_round = big_round
|
||||
redis.call('set', small_round_key, small_round)
|
||||
result.small_round = small_round
|
||||
end
|
||||
result.big_round = big_round
|
||||
result.big_total_gold = 0
|
||||
|
||||
-- ===================== 新增核心逻辑 =====================
|
||||
-- 小奖开奖金额累加到大奖池下一轮次(新的big_round)
|
||||
result.small_prize_to_big_next_round = result.small_prize_amount
|
||||
-- 原子性更新大奖池下一轮次金额
|
||||
local new_big_total_gold = math.floor(result.small_prize_amount * 100) / 100
|
||||
redis.call('set', big_total_gold_key, new_big_total_gold)
|
||||
result.big_total_gold = new_big_total_gold
|
||||
-- ======================================================
|
||||
end
|
||||
end
|
||||
|
||||
-- 返回结果
|
||||
return cjson.encode(result)
|
||||
LUA;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
312
application/common/service/LotteryService.php
Normal file
312
application/common/service/LotteryService.php
Normal file
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\library\LotteryGiftLua;
|
||||
use think\Cache;
|
||||
use think\Db;
|
||||
use think\Exception;
|
||||
|
||||
class LotteryService
|
||||
{
|
||||
// Redis实例
|
||||
private $redis;
|
||||
// 配置参数
|
||||
private $config;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->redis = Cache::store('redis')->handler();
|
||||
// 加载配置
|
||||
$this->config = Db::name('bb_lottery_config')->column('value', 'key');
|
||||
// 初始化Redis缓存(若Redis数据丢失,从数据库恢复)
|
||||
$this->initRedisFromDb();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 缓存恢复:独立恢复大小轮次+对应金额
|
||||
*/
|
||||
private function initRedisFromDb()
|
||||
{
|
||||
// 1. 恢复小奖池轮次(取pool_type=1的最大times)
|
||||
$maxSmallRound = Db::name('lottery_pool_flow')->where('pool_type', 1)->max('times') ?: 1;
|
||||
if (!$this->redis->get('lottery:small_pool:round')) {
|
||||
$this->redis->set('lottery:small_pool:round', $maxSmallRound);
|
||||
}
|
||||
|
||||
// 2. 恢复大奖池轮次(取pool_type=2的最大times)
|
||||
$maxBigRound = Db::name('lottery_pool_flow')->where('pool_type', 2)->max('times') ?: 1;
|
||||
if (!$this->redis->get('lottery:big_pool:round')) {
|
||||
$this->redis->set('lottery:big_pool:round', $maxBigRound);
|
||||
}
|
||||
|
||||
// 3. 恢复小奖池当前轮次的次数/金额
|
||||
$small_round = intval($this->redis->get('lottery:small_pool:round'));
|
||||
if (!$this->redis->get('lottery:small_pool:total_times')) {
|
||||
$smallTotalTimes = Db::name('lottery_pool_flow')
|
||||
->where(['pool_type' => 1, 'type' => 1, 'times' => $small_round])
|
||||
->count();
|
||||
$this->redis->set('lottery:small_pool:total_times', $smallTotalTimes);
|
||||
}
|
||||
if (!$this->redis->get('lottery:small_pool:total_gold')) {
|
||||
$smallTotalGold = Db::name('lottery_pool_flow')
|
||||
->where(['pool_type' => 1, 'type' => 1, 'times' => $small_round])
|
||||
->sum('amount') ?: 0;
|
||||
$this->redis->set('lottery:small_pool:total_gold', $smallTotalGold);
|
||||
}
|
||||
|
||||
// 4. 恢复大奖池当前轮次的金额
|
||||
$big_round = intval($this->redis->get('lottery:big_pool:round'));
|
||||
if (!$this->redis->get('lottery:big_pool:total_gold')) {
|
||||
$bigAddGold = Db::name('lottery_pool_flow')
|
||||
->where(['pool_type' => 2, 'type' => 3, 'times' => $big_round])
|
||||
->sum('amount') ?: 0;
|
||||
$bigReduceGold = Db::name('lottery_pool_flow')
|
||||
->where(['pool_type' => 2, 'type' => [2,4], 'times' => $big_round])
|
||||
->sum('amount') ?: 0;
|
||||
$this->redis->set('lottery:big_pool:total_gold', $bigAddGold + $bigReduceGold);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理送礼抽奖逻辑
|
||||
* @param int $send_uid 送礼用户ID
|
||||
* @param float $gift_gold 礼物金币数
|
||||
* @param int $giftId 礼物ID
|
||||
* @return array 处理结果
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handleGift($send_uid, $gift_gold, $giftId)
|
||||
{
|
||||
// 参数校验
|
||||
if ($gift_gold <= 0 || !$send_uid) {
|
||||
throw new Exception('参数错误');
|
||||
}
|
||||
|
||||
// 读取配置+独立轮次+大奖池金额
|
||||
$small_trigger_times = intval($this->config['small_pool_trigger_times'] ?? 200);
|
||||
$big_threshold = floatval($this->config['big_pool_threshold'] ?? 1000);
|
||||
$small_round = intval($this->redis->get('lottery:small_pool:round') ?: 1);
|
||||
$big_round = intval($this->redis->get('lottery:big_pool:round') ?: 1);
|
||||
$big_total_gold = floatval($this->redis->get('lottery:big_pool:total_gold') ?: 0);
|
||||
|
||||
// 加载Lua脚本
|
||||
$luaSha = LotteryGiftLua::getLotteryLuaScript();
|
||||
|
||||
// 执行Lua脚本(入参:small_round + big_round)
|
||||
$result = $this->redis->evalSha($luaSha, [
|
||||
$send_uid, 0, $gift_gold,
|
||||
$small_trigger_times, $big_threshold,
|
||||
$small_round, $big_round, $big_total_gold
|
||||
], 0);
|
||||
$result = json_decode($result, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new Exception('Lua脚本执行失败');
|
||||
}
|
||||
|
||||
// 开启数据库事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
// . 1记录小奖池累计流水(未开奖时)
|
||||
if ($result['is_small_prize'] == 0) {
|
||||
$this->addPoolFlow(
|
||||
1, // 小奖池
|
||||
1, // 累计
|
||||
$result['small_pool_add'],
|
||||
$result['small_total_gold'] - $result['small_pool_add'],
|
||||
$result['small_total_gold'],
|
||||
$giftId,
|
||||
$result['small_round'], // 新增:传入轮次
|
||||
"小奖池累计:用户{$send_uid}送礼,轮次{$result['current_round']}"
|
||||
);
|
||||
} else {
|
||||
$winnerUid = $send_uid; // 奖默认给当前送礼用户
|
||||
// 1. 只要开小奖,小奖剩余划入大奖池流水
|
||||
$this->addPoolFlow(
|
||||
2, // 大奖池
|
||||
3, // 划转
|
||||
$result['small_remain_amount'],//小奖剩余金额
|
||||
$result['big_total_gold'] - $result['small_remain_amount'],
|
||||
$result['big_total_gold'],
|
||||
$giftId,
|
||||
$result['big_round'] - ($result['is_big_prize'] ? 1 : 0),
|
||||
"小奖剩余划转大奖池:{$result['small_remain_amount']}金币"
|
||||
);
|
||||
|
||||
|
||||
//2.开小奖剩余划入大奖后 大奖够开奖
|
||||
if ($result['is_big_prize'] == 1) {
|
||||
// 大奖中奖记录
|
||||
$this->addWinnerRecord(
|
||||
$winnerUid,
|
||||
2, // 大奖
|
||||
$result['big_prize_amount'],//中奖金额
|
||||
$result['big_total_gold'], // 开奖时大奖池金额
|
||||
$this->getBigRatio($result['big_prize_amount'], $result['big_total_gold']),
|
||||
$result['big_release_amount']//释放金额
|
||||
);
|
||||
|
||||
// 大奖释放流水
|
||||
$this->addPoolFlow(
|
||||
2, // 大奖池
|
||||
4, // 释放
|
||||
-$result['big_release_amount'],//释放金额
|
||||
$result['big_total_gold'],// 开奖时大奖池金额
|
||||
0,
|
||||
$giftId,
|
||||
$result['big_round'] - 1, // 关联已结束的小奖池轮次
|
||||
"大奖释放金额:{$result['big_release_amount']}金币"
|
||||
);
|
||||
|
||||
// 4. 小奖开奖金额划转下一次大奖池流水
|
||||
if ($result['small_prize_to_big_next_round'] > 0) {
|
||||
$this->addPoolFlow(
|
||||
2,// 大奖池
|
||||
3,// 划转
|
||||
$result['small_prize_to_big_next_round'],
|
||||
0,
|
||||
$result['small_prize_to_big_next_round'],
|
||||
$giftId,
|
||||
$result['big_round'],
|
||||
"小奖开奖金额划入大奖池下一轮:大轮次{$result['big_round']},金额{$result['small_prize_to_big_next_round']}");
|
||||
}
|
||||
} else {//只有小奖中奖
|
||||
// 小奖中奖记录
|
||||
$this->addWinnerRecord(
|
||||
$winnerUid,
|
||||
1, // 小奖
|
||||
$result['small_prize_amount'],//中奖金额
|
||||
$result['small_total_gold'],//奖池总金额
|
||||
$this->getSmallRatio($result['small_prize_amount'], $result['small_total_gold']),//中奖比例
|
||||
0 //释放金额
|
||||
);
|
||||
// 3. 小奖池开奖流水
|
||||
$this->addPoolFlow(
|
||||
1, // 小奖池
|
||||
2, // 开奖扣除
|
||||
-$result['small_total_gold'],
|
||||
$result['small_total_gold'],
|
||||
0,
|
||||
$giftId,
|
||||
$result['small_round'] - 1, // 开奖轮次为当前轮次-1(已结束的轮次)
|
||||
"小奖池开奖:轮次" . ($result['small_round'] - 1).",累计{$result['small_total_gold']}金币"
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
return [
|
||||
'code' => 1,
|
||||
'msg' => '处理成功',
|
||||
'data' => $result
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加奖池流水
|
||||
* @param int $pool_type 奖池类型:1-小 2-大
|
||||
* @param int $type 流水类型:1-累计 2-开奖 3-划转 4-释放
|
||||
* @param float $amount 金额
|
||||
* @param float $before_amount 操作前金额
|
||||
* @param float $after_amount 操作后金额
|
||||
* @param int $relate_id 关联ID
|
||||
* @param int $times 轮次
|
||||
* @param string $remark 备注
|
||||
*/
|
||||
private function addPoolFlow($pool_type, $type, $amount, $before_amount, $after_amount, $relate_id, $times, $remark)
|
||||
{
|
||||
Db::name('bb_lottery_pool_flow')->insert([
|
||||
'pool_type' => $pool_type,
|
||||
'type' => $type,
|
||||
'amount' => $amount,
|
||||
'before_amount' => $before_amount,
|
||||
'after_amount' => $after_amount,
|
||||
'relate_id' => $relate_id,
|
||||
'times' => $times, // 新增:写入轮次
|
||||
'remark' => $remark,
|
||||
'create_time' => time()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加中奖记录
|
||||
* @param int $uid 中奖用户ID
|
||||
* @param int $prize_type 奖项类型:1-小 2-大
|
||||
* @param float $prize_amount 中奖金额
|
||||
* @param float $pool_amount 奖池总金额
|
||||
* @param int $ratio 中奖比例
|
||||
* @param float $release_amount 释放金额
|
||||
*/
|
||||
private function addWinnerRecord($uid, $prize_type, $prize_amount, $pool_amount, $ratio, $release_amount)
|
||||
{
|
||||
Db::name('bb_lottery_winner_record')->insert([
|
||||
'uid' => $uid,
|
||||
'prize_type' => $prize_type,
|
||||
'prize_amount' => $prize_amount,
|
||||
'pool_amount' => $pool_amount,
|
||||
'ratio' => $ratio,
|
||||
'release_amount' => $release_amount,
|
||||
'create_time' => time(),
|
||||
'status' => 1 // 已发放
|
||||
]);
|
||||
// 此处可添加用户金币入账逻辑(如更新用户金币表)
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算小奖中奖比例
|
||||
* @param float $prize_amount 中奖金额
|
||||
* @param float $pool_amount 奖池金额
|
||||
* @return int 比例(%)
|
||||
*/
|
||||
private function getSmallRatio($prize_amount, $pool_amount)
|
||||
{
|
||||
return intval(round($prize_amount / $pool_amount * 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算大奖中奖比例
|
||||
* @param float $prize_amount 中奖金额
|
||||
* @param float $pool_amount 奖池金额
|
||||
* @return int 比例(%)
|
||||
*/
|
||||
private function getBigRatio($prize_amount, $pool_amount)
|
||||
{
|
||||
return intval(round($prize_amount / $pool_amount * 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计中奖数据
|
||||
* @param array $where 筛选条件(如uid、prize_type、time)
|
||||
* @return array 统计结果
|
||||
*/
|
||||
public function statWinner($where = [])
|
||||
{
|
||||
$query = Db::name('bb_lottery_winner_record');
|
||||
if (!empty($where['uid'])) {
|
||||
$query->where('uid', $where['uid']);
|
||||
}
|
||||
if (!empty($where['prize_type'])) {
|
||||
$query->where('prize_type', $where['prize_type']);
|
||||
}
|
||||
if (!empty($where['start_time']) && !empty($where['end_time'])) {
|
||||
$query->whereBetween('create_time', [$where['start_time'], $where['end_time']]);
|
||||
}
|
||||
// 总中奖金额、总释放金额、中奖次数
|
||||
$stat = $query->field([
|
||||
'SUM(prize_amount) as total_prize',
|
||||
'SUM(release_amount) as total_release',
|
||||
'COUNT(id) as total_times'
|
||||
])->find();
|
||||
return [
|
||||
'total_prize' => $stat['total_prize'] ?? 0,
|
||||
'total_release' => $stat['total_release'] ?? 0,
|
||||
'total_times' => $stat['total_times'] ?? 0
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user