Boti: pauza pred vedenim kopky, spravne poradie broadcastov po tahu

Bot doteraz vedel zahodit prvu kartu novej kopky uz po BOT_MOVE_DELAY_SECONDS
(0.8s), zatial co frontend zmetaciu animaciu predoslej kopky prehraval
1650ms -- karta tak "vyletela" uprostred zmetania. _run_bot_turns teraz pri
vedeni novej kopky caka TRICK_SWEEP_SECONDS (1.7s), zhodne s SETTLE_MS+
COLLECT_MS v GameTable.tsx.

_run_bot_turns tiez posielal player_cards PRED game_status (opacne ako
human play_card handler) -- pri prechode do noveho kola tak klient dostal
novu ruku skor, nez vedel, ze zacalo nove kolo, a fixne ju hned zobrazil.
Poradie broadcastov je teraz zhodne s human handlerom.

GameTable/Hand: ruka noveho kola sa zobrazi az po dobehnuti zmetacej
animacie poslednej kopky predchadzajuceho kola (displayedHand + freeze
efekt), a Hand.tsx rezervuje fixny priestor pre karty aj ked je ruka
docasne prazdna, aby layout neposkakoval.

tests/test_bots.py: nulovanie TRICK_SWEEP_SECONDS v setUpClass, aby testy
zostali rychle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tim
2026-07-10 01:09:59 +02:00
co-authored by Claude Opus 4.8
parent b1010ae008
commit 973c279cbd
4 changed files with 78 additions and 32 deletions
+19 -15
View File
@@ -26,7 +26,6 @@ interface Props {
export default function Hand({ hand, myTurn, isPlayPhase, playableKeys, desktop = false }: Props) {
const groups = groupedByColor(hand);
if (groups.length === 0) return null;
const canPlay = isPlayPhase && myTurn;
@@ -52,20 +51,25 @@ export default function Hand({ hand, myTurn, isPlayPhase, playableKeys, desktop
<div className="h-px flex-1 max-w-[80px] bg-gradient-to-l from-transparent to-gold/20" />
</div>
{desktop ? (
// Desktop has room — keep cards grouped by suit, wrap if needed.
<div className="flex flex-wrap gap-3 justify-center items-end">
{groups.map(({ color, keys }) => (
<div key={color} className="flex gap-1 items-end">
{keys.map((key) => (
<CardView key={key} size="xl" {...cardProps(key)} />
))}
</div>
))}
</div>
) : (
<MobileHand groups={groups} cardProps={cardProps} />
)}
{/* Fixed height reserves the card row even when the hand is briefly
empty (last card of a round just played, next deal not in yet) --
otherwise this whole area collapses and the layout jumps. */}
<div className="flex items-end justify-center" style={{ minHeight: desktop ? 100 : 84 }}>
{desktop ? (
// Desktop has room — keep cards grouped by suit, wrap if needed.
<div className="flex flex-wrap gap-3 justify-center items-end">
{groups.map(({ color, keys }) => (
<div key={color} className="flex gap-1 items-end">
{keys.map((key) => (
<CardView key={key} size="xl" {...cardProps(key)} />
))}
</div>
))}
</div>
) : (
<MobileHand groups={groups} cardProps={cardProps} />
)}
</div>
</div>
);
}