108 lines
3.4 KiB
PHP
108 lines
3.4 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace app\common\service;
|
||
|
||
use app\common\library\game\StreakWinReward;
|
||
use support\think\Db;
|
||
|
||
/**
|
||
* 对局维度统计:平台盈亏、中奖人数(与 GameLiveService 单号派彩口径一致)。
|
||
*/
|
||
final class GameRecordStatService
|
||
{
|
||
/**
|
||
* 根据注单与开奖号码回写 game_record 统计字段(已结束对局)。
|
||
*/
|
||
public static function refreshForRecordId(int $recordId): void
|
||
{
|
||
if ($recordId <= 0) {
|
||
return;
|
||
}
|
||
$record = Db::name('game_record')->where('id', $recordId)->find();
|
||
if (!$record) {
|
||
return;
|
||
}
|
||
$status = (int) ($record['status'] ?? 0);
|
||
$now = time();
|
||
|
||
if ($status !== 4) {
|
||
Db::name('game_record')->where('id', $recordId)->update([
|
||
'platform_profit_amount' => '0.0000',
|
||
'winner_user_count' => 0,
|
||
'update_time' => $now,
|
||
]);
|
||
GameHotDataCoordinator::afterGameRecordCommitted($recordId);
|
||
|
||
return;
|
||
}
|
||
|
||
$resultRaw = $record['result_number'] ?? null;
|
||
if ($resultRaw === null || $resultRaw === '') {
|
||
return;
|
||
}
|
||
$resultNum = (int) $resultRaw;
|
||
|
||
$bets = Db::name('bet_order')->where('period_id', $recordId)->select()->toArray();
|
||
$totalBet = '0.0000';
|
||
$totalPayout = '0.0000';
|
||
$winnerUserIds = [];
|
||
|
||
foreach ($bets as $bet) {
|
||
$st = (int) ($bet['status'] ?? 0);
|
||
if ($st === 3) {
|
||
continue;
|
||
}
|
||
$tb = (string) ($bet['total_amount'] ?? '0');
|
||
$totalBet = bcadd($totalBet, $tb, 4);
|
||
|
||
if ($st === 2) {
|
||
$payout = bcadd((string) ($bet['win_amount'] ?? '0'), (string) ($bet['jackpot_extra_amount'] ?? '0'), 4);
|
||
} else {
|
||
$payout = self::estimatePayoutForBet($bet, $resultNum);
|
||
}
|
||
|
||
$totalPayout = bcadd($totalPayout, $payout, 4);
|
||
if (bccomp($payout, '0', 4) > 0) {
|
||
$uid = (int) ($bet['user_id'] ?? 0);
|
||
if ($uid > 0) {
|
||
$winnerUserIds[$uid] = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
$profit = bcsub($totalBet, $totalPayout, 4);
|
||
|
||
Db::name('game_record')->where('id', $recordId)->update([
|
||
'platform_profit_amount' => $profit,
|
||
'winner_user_count' => count($winnerUserIds),
|
||
'update_time' => $now,
|
||
]);
|
||
GameHotDataCoordinator::afterGameRecordCommitted($recordId);
|
||
}
|
||
|
||
/**
|
||
* 与 GameLiveService::estimateLossForNumber 一致:命中号码时 total_amount × odds_factor。
|
||
*/
|
||
private static function estimatePayoutForBet(array $bet, int $resultNumber): string
|
||
{
|
||
$pickNumbers = $bet['pick_numbers'] ?? null;
|
||
if (is_string($pickNumbers)) {
|
||
$decoded = json_decode($pickNumbers, true);
|
||
$pickNumbers = is_array($decoded) ? $decoded : [];
|
||
}
|
||
if (!is_array($pickNumbers)) {
|
||
$pickNumbers = [];
|
||
}
|
||
if (!in_array($resultNumber, array_map('intval', $pickNumbers), true)) {
|
||
return '0.0000';
|
||
}
|
||
$total = (string) ($bet['total_amount'] ?? '0');
|
||
$streak = (int) ($bet['streak_at_bet'] ?? 0);
|
||
$odds = StreakWinReward::totalOddsMultiplierForStreakAtBet($streak);
|
||
|
||
return bcmul($total, $odds, 4);
|
||
}
|
||
}
|