You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
349 lines
12 KiB
349 lines
12 KiB
<?php
|
|
|
|
namespace app\logic;
|
|
use app\model\AwardsRecords;
|
|
use app\model\ConsumptionRecords;
|
|
use app\model\User;
|
|
use app\model\ZoneGoods;
|
|
use app\model\ZoneGoodsParam;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 专区逻辑层
|
|
*/
|
|
class Zone
|
|
{
|
|
/**
|
|
* 判断余额是否足够
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public static function judgeBalance($user_id,$zoneGoodsId)
|
|
{
|
|
|
|
$userModel = User::field('balance')->find($user_id);
|
|
$balance = $userModel->balance ?: 0;
|
|
|
|
$zoneGoodsModel = ZoneGoods::field('price')->find($zoneGoodsId);
|
|
$price = $zoneGoodsModel->price ?: 0;
|
|
if ($balance < $price) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 余额扣减后 生成订单
|
|
* @param $user_id
|
|
* @param $zone_goods_id
|
|
* @return array
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public static function createOrder($user_id,$zone_goods_id)
|
|
{
|
|
# 判断用户是否存在未刮的
|
|
$inspect = self::inspectCompleteRecord($user_id);
|
|
if ($inspect['status']) {
|
|
return $inspect;
|
|
}
|
|
|
|
# 获取奖项个参数
|
|
$zoneParamArr = ZoneGoodsParam::getList(['zone_goods_id' => $zone_goods_id]);
|
|
if (empty($zoneParamArr)) return ['status' => 0, 'msg' => '刮奖失败'];
|
|
# 获取刮刮乐信息
|
|
$resData = self::getWinningPrize($zoneParamArr);
|
|
$data = $resData['data'];
|
|
$save_data = $resData['save_data'];
|
|
|
|
# 开启事务
|
|
$connection = Db::connect();
|
|
try {
|
|
$connection->startTrans();
|
|
# 扣除余额
|
|
$zoneGoodsModel = ZoneGoods::field('price')->find($zone_goods_id);
|
|
$price = $zoneGoodsModel['price'];
|
|
$balance = User::decrBalance($user_id,$price);
|
|
|
|
# 消费记录
|
|
$c_r_id = ConsumptionRecords::createRecords($user_id,$zone_goods_id,$price,$price,$balance,$save_data);
|
|
|
|
$connection->commit();
|
|
# 返回刮刮乐图标、金额、订单id
|
|
return ['status' => 1, 'data' => $data, 'c_r_id' => $c_r_id];
|
|
} catch (\Exception $e) {
|
|
|
|
$connection->rollback();
|
|
return ['status' => 0, 'msg' => '操作失败'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 刮奖完成
|
|
* @param $user_id
|
|
* @param $c_r_id
|
|
* @return array
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public static function endOrder($user_id,$c_r_id)
|
|
{
|
|
|
|
# 验证
|
|
$queryWhere = ['user_id' => $user_id, 'id' => $c_r_id];
|
|
$ConsumptionRecords = new ConsumptionRecords();
|
|
$query = $ConsumptionRecords->where($queryWhere)->field('text_data,zone_goods_id,status')->find();
|
|
if (!$query) return ['status' => 0, 'msg' => '数据不存在'];
|
|
if ($query['status'] == 1) return ['status' => 0, 'msg' => '刮奖结果已公布'];
|
|
|
|
# 解密
|
|
$data = unserialize($query['text_data']);
|
|
# 解析是否中奖
|
|
$awards_amount = 0;
|
|
foreach ($data as $key => $goodsParam) {
|
|
foreach ($goodsParam as $k => $item) {
|
|
$data[$key][$k]['is_awards'] = 0;
|
|
if (isset($item['id'])) {
|
|
$awardsAmountRes = ZoneGoodsParam::getAwardsAmount($item['id']);
|
|
if ($awardsAmountRes) {
|
|
$data[$key][$k]['is_awards'] = 1;
|
|
$awards_amount += $item['amount'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$returnData = self::handleTextData($data);
|
|
$ConsumptionRecords->awardsData($data,$c_r_id);
|
|
|
|
# 开启事务
|
|
$connection = Db::connect();
|
|
try {
|
|
$connection->startTrans();
|
|
|
|
# 判断是否中奖
|
|
if ($awards_amount > 0) {
|
|
|
|
# 修改用户余额
|
|
$balance = User::incrWithdrawalBalance($user_id,$awards_amount);
|
|
|
|
# 中奖做记录
|
|
AwardsRecords::createRecords($user_id,$c_r_id,$awards_amount,$balance);
|
|
}
|
|
|
|
# 完成订单
|
|
ConsumptionRecords::endOrder($c_r_id,$awards_amount);
|
|
|
|
$connection->commit();
|
|
return ['status' => 1, 'msg' => '完成', 'awards_amount' => $awards_amount, 'data' => $returnData];
|
|
} catch (\Exception $e) {
|
|
|
|
$connection->rollback();
|
|
return ['status' => 0, 'msg' => '操作异常'];
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 检查用户是否存在未刮的
|
|
* @param $user_id
|
|
* @return array|int[]
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public static function inspectCompleteRecord($user_id)
|
|
{
|
|
$query = ConsumptionRecords::where(['user_id' => $user_id,'status' => 0])->find();
|
|
if ($query) {
|
|
$data = self::handleTextData(unserialize($query['text_data']));
|
|
return ['status' => 1, 'data' => $data, 'c_r_id' => $query['id']];
|
|
};
|
|
|
|
return ['status' => 0];
|
|
}
|
|
|
|
/**
|
|
* 处理刮奖信息数据
|
|
* @param $data
|
|
* @return mixed
|
|
*/
|
|
public static function handleTextData($data)
|
|
{
|
|
foreach ($data as $key => $value) {
|
|
|
|
foreach ($value as $k => $v) {
|
|
|
|
unset($data[$key][$k]['id']);
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 获取刮刮乐信息(概率算法)
|
|
* @param array $patterns // 数据 和 占比
|
|
* @param int $direction // 纵向数量
|
|
* @param int $transverse // 横向数量
|
|
* @return array[]
|
|
*/
|
|
public static function getWinningPrize(array $patterns,int $direction = 3,int $transverse = 4)
|
|
{
|
|
// $patterns = [
|
|
// ['image' => 'prize1.png', 'probability' => 0.3], // 奖项图案,概率为30%
|
|
// ['image' => 'prize2.png', 'probability' => 0.2], // 奖项图案,概率为20%
|
|
// ['image' => 'no_prize1.png', 'probability' => 0.1], // 奖项图案,概率为10%
|
|
// ['image' => 'no_prize2.png', 'probability' => 0.32], // 奖项图案,概率为32%
|
|
// ['image' => 'test1.png', 'probability' => 0.07], // 奖项图案,概率为7%
|
|
// ['image' => 'test2.png', 'probability' => 0.002], // 奖项图案,概率为0.2%
|
|
// ['image' => 'test3.png', 'probability' => 0.003], // 奖项图案,概率为0.3%
|
|
// ['image' => 'test4.png', 'probability' => 0.004], // 奖项图案,概率为0.4%
|
|
// ['image' => 'test5.png', 'probability' => 0.001], // 奖项图案,概率为0.1%
|
|
// ];
|
|
|
|
// 计算概率总和
|
|
$totalProbability = 0;
|
|
foreach ($patterns as $pattern) {
|
|
$totalProbability += $pattern['probability'];
|
|
}
|
|
|
|
// 归一化处理,并计算累积概率
|
|
$accumulatedProbability = 0;
|
|
foreach ($patterns as &$pattern) {
|
|
$pattern['probability'] /= $totalProbability; // 归一化处理
|
|
$accumulatedProbability += $pattern['probability'];
|
|
$pattern['accumulatedProbability'] = $accumulatedProbability; // 累积概率
|
|
}
|
|
unset($pattern);
|
|
|
|
$data = [];
|
|
$save_data = [];
|
|
for ($i = 0; $i < $direction; $i++) {
|
|
|
|
for ($j = 0; $j < $transverse; $j++) { // 每组生成 3 个图案
|
|
$selectedPattern = null;
|
|
$randomNumber = mt_rand() / mt_getrandmax(); // 生成 0 到 1 之间的随机数
|
|
|
|
foreach ($patterns as $pattern) {
|
|
if ($randomNumber <= $pattern['accumulatedProbability']) {
|
|
$selectedPattern = $pattern;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$data[$i][] = [
|
|
'amount' => $selectedPattern['amount'],
|
|
'image' => get_image_url($selectedPattern['image'])
|
|
];
|
|
$save_data[$i][] = [
|
|
'id' => $selectedPattern['id'],
|
|
'amount' => $selectedPattern['amount'],
|
|
'image' => get_image_url($selectedPattern['image'])
|
|
];
|
|
}
|
|
|
|
}
|
|
return [
|
|
'data' => $data,
|
|
'save_data' => $save_data
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 自动刮奖测试机
|
|
* @param $user_id
|
|
* @param $zone_goods_id
|
|
* @param $count
|
|
* @return string|void
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public static function auto($user_id = 1,$zone_goods_id = 1,$count = 500)
|
|
{
|
|
# 验证
|
|
$user = User::find($user_id);
|
|
if (!$user) return '用户不存在';
|
|
$zoneGoods = ZoneGoods::find($zone_goods_id);
|
|
if (!$zoneGoods) return '刮奖商品不存在';
|
|
$zoneGoodsParam = ZoneGoodsParam::where('zone_goods_id',$zone_goods_id)->where('status',1)->find();
|
|
if (!$zoneGoodsParam) return '刮奖奖项不存在';
|
|
$balance = $user->balance ?: 0;
|
|
$sumPrice = $count * $zoneGoods['price'];
|
|
if ($balance < $sumPrice) return '用户余额不足';
|
|
|
|
# 开始执行
|
|
$limit = 1;
|
|
while ($limit <= $count) {
|
|
|
|
# 获取奖项个参数
|
|
$zoneParamArr = ZoneGoodsParam::getList(['zone_goods_id' => $zone_goods_id]);
|
|
if (empty($zoneParamArr)) return '奖项不存在';
|
|
|
|
# 获取刮刮乐信息
|
|
$resData = Zone::getWinningPrize($zoneParamArr);
|
|
$data = $resData['data'];
|
|
$save_data = $resData['save_data'];
|
|
|
|
# 开启事务
|
|
$connection = Db::connect();
|
|
try {
|
|
|
|
$connection->startTrans();
|
|
|
|
# 扣除余额
|
|
$zoneGoodsModel = ZoneGoods::field('price')->find($zone_goods_id);
|
|
$price = $zoneGoodsModel['price'];
|
|
$balance = User::decrBalance($user_id,$price);
|
|
|
|
# 消费记录
|
|
$c_r_id = ConsumptionRecords::createRecords($user_id,$zone_goods_id,$price,$price,$balance,$save_data);
|
|
|
|
# 解析是否中奖
|
|
$awards_amount = 0;
|
|
foreach ($save_data as $key => $goodsParam) {
|
|
foreach ($goodsParam as $k => $item) {
|
|
$save_data[$key][$k]['is_awards'] = 0;
|
|
if (isset($item['id'])) {
|
|
$awardsAmountRes = ZoneGoodsParam::getAwardsAmount($item['id']);
|
|
if ($awardsAmountRes) {
|
|
$save_data[$key][$k]['is_awards'] = 1;
|
|
$awards_amount += $item['amount'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$ConsumptionRecords = new ConsumptionRecords();
|
|
|
|
$ConsumptionRecords::awardsData($save_data,$c_r_id);
|
|
|
|
# 判断是否中奖
|
|
if ($awards_amount > 0) {
|
|
|
|
# 修改用户余额
|
|
$balance = User::incrWithdrawalBalance($user_id,$awards_amount);
|
|
|
|
# 中奖做记录
|
|
AwardsRecords::createRecords($user_id,$c_r_id,$awards_amount,$balance);
|
|
}
|
|
|
|
# 完成订单
|
|
ConsumptionRecords::endOrder($c_r_id,$awards_amount);
|
|
|
|
$connection->commit();
|
|
|
|
# 返回刮刮乐图标、金额、订单id
|
|
} catch (\Exception $e) {
|
|
|
|
$connection->rollback();
|
|
return $e->getMessage();
|
|
}
|
|
# 循环执行
|
|
$limit++;
|
|
}
|
|
return '完成';
|
|
}
|
|
}
|