$totalSharesByCode 自下而上,如 C,B,A(百分比 0-100) * @param array $extraRebateByCode 谁设置谁承担 * @param list $chainFromPlayer 自下而上参与方 code,末位为平台侧用 platform */ public function calculate( float $sharedNetWinLoss, array $totalSharesByCode, array $extraRebateByCode = [], float $gameWinLoss = 0, float $basicRebate = 0, array $chainFromPlayer = [], ): ShareSettlementResult { if ($gameWinLoss !== 0.0 || $basicRebate !== 0.0) { $extraTotal = array_sum(array_map(floatval(...), $extraRebateByCode)); $playerNet = $gameWinLoss - $basicRebate - $extraTotal; $shared = $gameWinLoss - $basicRebate; } else { $playerNet = $sharedNetWinLoss - array_sum(array_map(floatval(...), $extraRebateByCode)); $shared = $sharedNetWinLoss; } $ordered = $chainFromPlayer !== [] ? $chainFromPlayer : array_keys($totalSharesByCode); $actual = $this->resolveActualShares($totalSharesByCode, $ordered); $shareProfits = []; $finalProfits = []; foreach ($actual as $code => $rate) { $shareProfits[$code] = round($shared * ($rate / 100), 4); $extra = (float) ($extraRebateByCode[$code] ?? 0); $finalProfits[$code] = round($shareProfits[$code] - $extra, 4); } $tierSettlements = $this->buildTierSettlements($playerNet, $finalProfits, $ordered); return new ShareSettlementResult( playerNetSettlement: round($playerNet, 4), sharedNetWinLoss: round($shared, 4), shareProfits: $shareProfits, finalProfits: $finalProfits, tierSettlements: $tierSettlements, ); } /** * @param array $totalSharesByCode * @param list $orderedBottomUp * @return array */ private function resolveActualShares(array $totalSharesByCode, array $orderedBottomUp): array { $actual = []; $prev = 0.0; foreach ($orderedBottomUp as $code) { $total = (float) ($totalSharesByCode[$code] ?? 0); $actual[$code] = max(0, $total - $prev); $prev = $total; } $topTotal = $prev; $actual['platform'] = max(0, 100 - $topTotal); return $actual; } /** * @param array $finalProfits * @param list $orderedBottomUp * @return array */ private function buildTierSettlements(float $playerNet, array $finalProfits, array $orderedBottomUp): array { $keys = ['P_to_'.($orderedBottomUp[0] ?? 'agent')]; for ($i = 0; $i < count($orderedBottomUp) - 1; $i++) { $keys[] = $orderedBottomUp[$i].'_to_'.$orderedBottomUp[$i + 1]; } if (count($orderedBottomUp) >= 1) { $last = $orderedBottomUp[count($orderedBottomUp) - 1]; $keys[] = $last.'_to_platform'; } $amount = $playerNet; $tier = []; if ($orderedBottomUp === []) { return $tier; } $tier['P_to_'.$orderedBottomUp[0]] = round($amount, 4); for ($i = 0; $i < count($orderedBottomUp); $i++) { $code = $orderedBottomUp[$i]; $keep = (float) ($finalProfits[$code] ?? 0); $amount = round($amount - $keep, 4); if ($i < count($orderedBottomUp) - 1) { $next = $orderedBottomUp[$i + 1]; $tier[$code.'_to_'.$next] = $amount; } else { $tier[$code.'_to_platform'] = $amount; } } return $tier; } }