| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- <?php
- namespace App\Services\Sharing;
- use Carbon\Carbon;
- use InvalidArgumentException;
- /** Shared arithmetic only: callers retain their own eligibility and accounting dates. */
- final class EffectiveBet
- {
- public const SCALE = 10;
- public static function amount($betAmount, $netProfit, bool $settled = true, bool $voided = false): string
- {
- if (!$settled || $voided) return self::zero();
- $bet = self::decimal($betAmount);
- $profit = self::decimal($netProfit);
- if (bccomp($bet, '0', self::SCALE) < 0) {
- throw new InvalidArgumentException('Bet amount cannot be negative');
- }
- $absolute = bccomp($profit, '0', self::SCALE) < 0
- ? bcsub('0', $profit, self::SCALE) : $profit;
- return bccomp($bet, $absolute, self::SCALE) <= 0 ? $bet : $absolute;
- }
- public static function decimal($value): string
- {
- $value = trim((string) $value);
- if (!preg_match('/^-?\d+(?:\.\d+)?$/D', $value)) {
- throw new InvalidArgumentException('Expected a plain decimal amount');
- }
- return bcadd($value, '0', self::SCALE);
- }
- public static function zero(): string
- {
- return '0.0000000000';
- }
- public static function newYorkDate($sourceTime, string $sourceTimezone = 'Asia/Shanghai'): string
- {
- return self::time($sourceTime, $sourceTimezone)->setTimezone('America/New_York')->toDateString();
- }
- /** Reject missing dates rather than Carbon's implicit current-time fallback. */
- public static function time($sourceTime, string $sourceTimezone = 'Asia/Shanghai'): Carbon
- {
- if ($sourceTime instanceof \DateTimeInterface) return Carbon::instance($sourceTime);
- if ($sourceTime === null || trim((string) $sourceTime) === '') {
- throw new InvalidArgumentException('Source time is missing');
- }
- if (is_numeric($sourceTime)) {
- if (!preg_match('/^\d{9,11}$/D', (string) $sourceTime)) {
- throw new InvalidArgumentException('Invalid source timestamp');
- }
- return Carbon::createFromTimestamp((int) $sourceTime, 'UTC');
- }
- if (!preg_match('/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/D', (string) $sourceTime)) {
- throw new InvalidArgumentException('Invalid source datetime');
- }
- $parsed = Carbon::parse($sourceTime, $sourceTimezone);
- if ($parsed->format('Y-m-d H:i:s') !== str_replace('T', ' ', substr((string) $sourceTime, 0, 19))) {
- throw new InvalidArgumentException('Source datetime is not a valid calendar date');
- }
- return $parsed;
- }
- }
|