0 时:选择利润最接近「总投注额 × 目标盈利率」的结果 * - targetProfitRate == 0 时:选择平台利润最高的结果(原逻辑) * * @param array $bets 当期所有投注 [{bet_type, bet_target, amount, odds}, ...] * @param array $waterConfig [{bet_type => win_rate_pct}, ...] * 当前版本中 waterConfig 的 win_rate_pct 未直接参与结果选择, * 因为开奖结果是全局排列,无法单独控制某个投注类型的胜率。 * 保留此参数供未来扩展(如按类型加权评分、分类型概率偏移等)。 * @param int $attempts 最大尝试次数 * @param float $targetProfitRate 目标盈利率(百分比,如 5.0 表示 5%) */ public static function generateControlledResult(array $bets, array $waterConfig, int $attempts = 100, float $targetProfitRate = 0): array { if (empty($bets)) { return self::generateResult(); } // 计算目标利润(仅当 targetProfitRate > 0 时生效) $targetProfit = 0; if ($targetProfitRate > 0) { $totalBet = 0; foreach ($bets as $bet) { $totalBet += (float)$bet['amount']; } $targetProfit = $totalBet * ($targetProfitRate / 100); } $bestResult = null; $bestProfit = PHP_INT_MIN; $bestDistance = PHP_FLOAT_MAX; for ($i = 0; $i < $attempts; $i++) { $result = self::generateResult(); $profit = self::calculatePlatformProfit($result, $bets); if ($targetProfitRate > 0) { // 目标盈利率模式:选择利润最接近目标值的结果 $distance = abs($profit - $targetProfit); if ($distance < $bestDistance) { $bestDistance = $distance; $bestProfit = $profit; $bestResult = $result; } } else { // 原逻辑:选择平台利润最高的结果 if ($profit > $bestProfit) { $bestProfit = $profit; $bestResult = $result; } } } return $bestResult; } /** * 计算某个开奖结果下平台的利润 */ public static function calculatePlatformProfit(array $result, array $bets): float { $totalBet = 0; $totalPayout = 0; foreach ($bets as $bet) { $amount = (float)$bet['amount']; $totalBet += $amount; if (self::checkWin($result, $bet['bet_type'], $bet['bet_target'])) { $totalPayout += $amount + $amount * (float)$bet['odds']; } } return $totalBet - $totalPayout; } /** * 核心中奖判定 * @param array $result 开奖排名 [冠军车号, 亚军车号, ..., 第十名车号] * @param string $betType 投注类型: rank/bs/oe/dt/sum/sum_bs * @param string $betTarget 投注目标: rank1_5/rank1_big/dt1_dragon/sum_11/sum_big... */ public static function checkWin(array $result, string $betType, string $betTarget): bool { switch ($betType) { case 'rank': return self::checkRank($result, $betTarget); case 'bs': return self::checkBigSmall($result, $betTarget); case 'oe': return self::checkOddEven($result, $betTarget); case 'dt': return self::checkDragonTiger($result, $betTarget); case 'sum': return self::checkSum($result, $betTarget); case 'sum_bs': return self::checkSumBigSmall($result, $betTarget); default: return false; } } // 名次投注: rank{N}_{carNo} 如 rank1_5 = 冠军是5号车 private static function checkRank(array $r, string $target): bool { if (!preg_match('/^rank(\d+)_(\d+)$/', $target, $m)) return false; $pos = (int)$m[1] - 1; // 0-indexed $car = (int)$m[2]; return isset($r[$pos]) && $r[$pos] === $car; } // 大小: rank{N}_big/small, 车号>=6为大, <=5为小 private static function checkBigSmall(array $r, string $target): bool { if (!preg_match('/^rank(\d+)_(big|small)$/', $target, $m)) return false; $pos = (int)$m[1] - 1; if (!isset($r[$pos])) return false; $car = $r[$pos]; return $m[2] === 'big' ? $car >= 6 : $car <= 5; } // 单双: rank{N}_odd/even private static function checkOddEven(array $r, string $target): bool { if (!preg_match('/^rank(\d+)_(odd|even)$/', $target, $m)) return false; $pos = (int)$m[1] - 1; if (!isset($r[$pos])) return false; $car = $r[$pos]; return $m[2] === 'odd' ? ($car % 2 === 1) : ($car % 2 === 0); } // 龙虎: dt{N}_dragon/tiger, N=1-5, 对应 1vs10, 2vs9, 3vs8, 4vs7, 5vs6 private static function checkDragonTiger(array $r, string $target): bool { if (!preg_match('/^dt(\d)_(dragon|tiger)$/', $target, $m)) return false; $pair = (int)$m[1]; // 1-5 $frontPos = $pair - 1; // 0,1,2,3,4 $backPos = 10 - $pair; // 9,8,7,6,5 if (!isset($r[$frontPos], $r[$backPos])) return false; $front = $r[$frontPos]; $back = $r[$backPos]; if ($front === $back) return false; // 和局(PK10不会出现) return $m[2] === 'dragon' ? $front > $back : $front < $back; } // 冠亚和值: sum_{3-19} private static function checkSum(array $r, string $target): bool { if (!preg_match('/^sum_(\d+)$/', $target, $m)) return false; $sumVal = $r[0] + $r[1]; // 冠军+亚军 return $sumVal === (int)$m[1]; } // 冠亚和大小单双: sum_big/small/odd/even, 和>=12为大, <=11为小 private static function checkSumBigSmall(array $r, string $target): bool { $sumVal = $r[0] + $r[1]; switch ($target) { case 'sum_big': return $sumVal >= 12; case 'sum_small': return $sumVal <= 11; case 'sum_odd': return $sumVal % 2 === 1; case 'sum_even': return $sumVal % 2 === 0; default: return false; } } /** * 获取名次中文/英文名称 */ public static function getRankName(int $pos): string { $names = [1=>'champion',2=>'runner_up',3=>'rank_n',4=>'rank_n',5=>'rank_n', 6=>'rank_n',7=>'rank_n',8=>'rank_n',9=>'rank_n',10=>'rank_n']; return $names[$pos] ?? 'rank_n'; } /** * 龙虎对应关系 */ public static function getDragonTigerPairs(): array { return [ 1 => [1, 10], // 第1名 vs 第10名 2 => [2, 9], 3 => [3, 8], 4 => [4, 7], 5 => [5, 6], ]; } /** * 期号生成 */ public static function generatePeriodNumber(int $gameId): string { return 'PK' . $gameId . date('Ymd') . str_pad(mt_rand(1, 9999), 4, '0', STR_PAD_LEFT); } public static function getResultTable(): ?string { return 'pk10_results'; } public static function formatResultForStorage(array $result, int $periodId): array { return [ 'period_id' => $periodId, 'rank_1' => $result[0], 'rank_2' => $result[1], 'rank_3' => $result[2], 'rank_4' => $result[3], 'rank_5' => $result[4], 'rank_6' => $result[5], 'rank_7' => $result[6], 'rank_8' => $result[7], 'rank_9' => $result[8], 'rank_10' => $result[9], 'champion_sum' => $result[0] + $result[1], ]; } public static function parseResultFromDb(array $row): array { $r = []; for ($i = 1; $i <= 10; $i++) $r[] = (int)($row['rank_' . $i] ?? 0); return $r; } }