assertSame($expected, EffectiveBet::amount($stake, $profit, $settled, $voided)); } public function outcomes(): array { return [ ['100', '80', true, false, '80.0000000000'], ['100', '150', true, false, '100.0000000000'], ['100', '-100', true, false, '100.0000000000'], ['100', '-50', true, false, '50.0000000000'], ['100', '0', true, false, '0.0000000000'], ['100', '80', false, false, '0.0000000000'], ['100', '-100', true, true, '0.0000000000'], ['100.0000000001', '0.1234567891', true, false, '0.1234567891'], ]; } public function test_original_betting_day_is_converted_to_new_york_across_midnight(): void { $this->assertSame('2026-10-23', EffectiveBet::newYorkDate('2026-10-24 00:10:00')); $this->assertSame('2026-10-23', EffectiveBet::newYorkDate(1792771800)); } public function test_missing_source_date_is_rejected_instead_of_becoming_today(): void { $this->expectException(\InvalidArgumentException::class); EffectiveBet::newYorkDate(null); } public function test_invalid_calendar_date_is_rejected(): void { $this->expectException(\InvalidArgumentException::class); EffectiveBet::newYorkDate('2026-02-31 10:00:00'); } public function test_pc28_pending_filter_keeps_zero_so_retries_do_not_select_settled_bets(): void { $this->assertContains(['lottery_status', '=', 0], BetService::getWhere(['lottery_status' => 0])); } }