diff --git a/internal/ws/hub.go b/internal/ws/hub.go index e8cda21..707a2d5 100644 --- a/internal/ws/hub.go +++ b/internal/ws/hub.go @@ -17,6 +17,7 @@ const ( defaultMatchWait = 6 * time.Second // مهلت پر شدن میز با انسان پیش از افزودن بات defaultTrickHold = 1200 * time.Millisecond // مدت نمایش دستِ کامل پیش از جمع‌آوری defaultFirstHandDelay = 3000 * time.Millisecond // تأخیر اولین حرکتِ بات تا پایانِ اینترو+بُر زدنِ کلاینت + defaultDealDelay = 1600 * time.Millisecond // تأخیر اولین بازی تا پایانِ انیمیشنِ پخشِ کارت‌ها ) // AuthFunc توکن را تأیید کرده و (شناسه کاربر، نام نمایشی) را برمی‌گرداند. @@ -71,6 +72,7 @@ type Hub struct { matchWait time.Duration trickHold time.Duration firstHandDelay time.Duration // تأخیر اولین حرکتِ بات (هماهنگ با انیمیشنِ بُر زدنِ کلاینت) + dealDelay time.Duration // تأخیر اولین بازی پس از انتخابِ حکم (انیمیشنِ پخشِ کارت‌ها) countdownDelay time.Duration // مهلت شمارش معکوسِ میز خصوصی پیش از شروع register chan *Client @@ -101,6 +103,7 @@ func NewHub(auth AuthFunc) *Hub { matchWait: defaultMatchWait, trickHold: defaultTrickHold, firstHandDelay: defaultFirstHandDelay, + dealDelay: defaultDealDelay, countdownDelay: 3 * time.Second, register: make(chan *Client), unregister: make(chan *Client), diff --git a/internal/ws/room.go b/internal/ws/room.go index 111d8fb..6ce0e3a 100644 --- a/internal/ws/room.go +++ b/internal/ws/room.go @@ -58,8 +58,10 @@ type Room struct { turnTimeout time.Duration botDelay time.Duration trickHold time.Duration - firstHandDelay time.Duration - handStart time.Time // زمانِ شروعِ هَندِ جاری (برای پنجره‌ی بُر زدن) + firstHandDelay time.Duration // پنجره‌ی بُر زدن+پخشِ ۵ کارت (ابتدای هَند) + dealDelay time.Duration // پنجره‌ی پخشِ بقیه‌ی کارت‌ها (پس از انتخابِ حکم) + // graceUntil: تا این لحظه هیچ حرکتِ خودکاری انجام نمی‌شود (هماهنگ با انیمیشن‌های کلاینت). + graceUntil time.Time } func newRoom(id string, seats [4]*seatInfo, hub *Hub) *Room { @@ -73,6 +75,7 @@ func newRoom(id string, seats [4]*seatInfo, hub *Hub) *Room { botDelay: hub.botDelay, trickHold: hub.trickHold, firstHandDelay: hub.firstHandDelay, + dealDelay: hub.dealDelay, } } @@ -111,7 +114,7 @@ func (r *Room) start() { target = targetScore } r.game = game.NewGame(target, game.FirstHakem()) - r.handStart = time.Now() + r.graceUntil = time.Now().Add(r.firstHandDelay) // بُر زدن + پخشِ ۵ کارت for seat, s := range r.seats { if s.client != nil { s.client.trySend(mustJSON(r.matchedFor(seat))) @@ -146,7 +149,7 @@ func (r *Room) react() { r.endRoom() return } - r.handStart = time.Now() // شروعِ هَندِ جدید ⇒ پنجره‌ی بُر زدن + r.graceUntil = time.Now().Add(r.firstHandDelay) // هَندِ جدید ⇒ بُر زدن + پخشِ ۵ کارت r.broadcastState() r.armTimer() case game.PhaseGameOver: @@ -211,9 +214,9 @@ func (r *Room) armTimer() { delay := r.turnTimeout if r.seats[actor].auto() { delay = r.botDelay - // در پنجره‌ی ابتدای هَند (انیمیشنِ بُر زدنِ کلاینت)، حرکتِ خودکار را عقب - // می‌اندازیم تا کارت‌ها وسطِ بُر زدن روی میز نیفتند. نوبتِ انسان دست‌نخورده می‌ماند. - if grace := r.firstHandDelay - time.Since(r.handStart); grace > delay { + // تا پایانِ پنجره‌ی انیمیشنِ کلاینت (بُر زدن یا پخشِ کارت)، حرکتِ خودکار را + // عقب می‌اندازیم تا کارت‌ها وسطِ انیمیشن روی میز نیفتند. نوبتِ انسان دست‌نخورده می‌ماند. + if grace := time.Until(r.graceUntil); grace > delay { delay = grace } } @@ -244,6 +247,7 @@ func (r *Room) handleInput(act roomAction) { r.sendError(act.seat, err.Error()) return } + r.graceUntil = time.Now().Add(r.dealDelay) // انیمیشنِ پخشِ بقیه‌ی کارت‌ها r.react() case "play_card": card, err := game.ParseCard(act.msg.Card) @@ -294,6 +298,7 @@ func (r *Room) autoChooseTrump(seat int) { } } _ = r.game.ChooseTrump(seat, best) + r.graceUntil = time.Now().Add(r.dealDelay) // انیمیشنِ پخشِ بقیه‌ی کارت‌ها } // autoPlayCard یک کارت مجاز (پایین‌ترین کارتِ خالِ زمینه، وگرنه پایین‌ترین کارت) بازی می‌کند. diff --git a/internal/ws/ws_test.go b/internal/ws/ws_test.go index c2a83a5..dd97dd5 100644 --- a/internal/ws/ws_test.go +++ b/internal/ws/ws_test.go @@ -123,6 +123,7 @@ func testHub() *Hub { hub.matchWait = 300 * time.Millisecond hub.trickHold = 5 * time.Millisecond hub.firstHandDelay = 0 + hub.dealDelay = 0 hub.countdownDelay = 20 * time.Millisecond go hub.Run() return hub