Skip to content

Commit 6041232

Browse files
denis1011101claude
andcommitted
fix: окно чата привязано к сбросу, который разберёт этот состав
Окно кончалось в ближайшую субботу у любой игры, включая назначенную позже неё. Такую игру эта ночь не трогает: чистка сносит только прошедшие разовые, сброс — только отыгранные серии. Сессия умирала в 4 утра, участие оставалось, и человек молча переставал доходить до чата, пока не наберёт /chat заново. Теперь считаем первый сброс после дня самой игры: у серии — после ближайшего вхождения, у разовой — после её даты. Игра, чей сброс уже прошёл, чат закрывает: её и саму к этому моменту удаляет еженедельная чистка. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 2d448a0 commit 6041232

2 files changed

Lines changed: 52 additions & 7 deletions

File tree

app/models/game.rb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ def coaches
6262
end
6363

6464
# Чат живёт ровно столько же, сколько состав: до еженедельного сброса участий —
65-
# ночь с пятницы на субботу, 4 утра (ResetParticipationsJob в recurring.yml).
66-
# Раньше у серии режим протухал через сутки, и человек оставался без чата
67-
# посреди недели, хотя состав, которому он писал, никуда не делся.
65+
# ночь с пятницы на субботу, 4 утра (ResetParticipationsJob в recurring.yml,
66+
# там же чистка прошедших разовых игр). Раньше у серии режим протухал через
67+
# сутки, и человек оставался без чата посреди недели, хотя состав, которому он
68+
# писал, никуда не делся.
6869
CHAT_RESET_WDAY = 6
6970
CHAT_RESET_HOUR = 4
7071

@@ -75,8 +76,13 @@ def self.next_weekly_reset_at(from = Time.current)
7576
reset
7677
end
7778

79+
# Считаем не «ближайшую субботу вообще», а ту, что действительно разберёт этот
80+
# состав: сброс сносит участия уже отыгранного вхождения, а чистка — только
81+
# прошедшую разовую игру. Игру, назначенную после ближайшей субботы, эта ночь
82+
# не касается, и гасить её чат в 4 утра не за что.
7883
def chat_open_until
79-
Game.next_weekly_reset_at
84+
closes_at = Game.next_weekly_reset_at(chat_window_anchor)
85+
closes_at > Time.current ? closes_at : nil
8086
end
8187

8288
def chat_open?
@@ -478,6 +484,13 @@ def next_time
478484
time
479485
end
480486

487+
# День, после которого состав этой игры пойдёт под нож: у серии — ближайшее
488+
# вхождение, у разовой — её дата.
489+
def chat_window_anchor
490+
occurrence = recurring? ? (next_date || date) : date
491+
occurrence ? occurrence.end_of_day : Time.current
492+
end
493+
481494
def previous_occurrence_before_next_date
482495
return nil unless recurring? && next_date.present?
483496

test/models/game_test.rb

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,44 @@ class GameTest < ActiveSupport::TestCase
406406
end
407407

408408
test "chat stays open until the weekly reset, not for a fixed day" do
409-
# Среда — до сброса ещё три ночи.
409+
game = Game.create!(court: courts(:one), user: users(:one), date: Date.new(2026, 9, 3), kind: "game")
410+
411+
# Среда: игра в четверг, разберёт её состав ближайшая суббота.
410412
travel_to Time.zone.local(2026, 9, 2, 21, 0) do
411413
assert_equal Time.zone.local(2026, 9, 5, 4, 0), Game.next_weekly_reset_at
412-
assert_equal Game.next_weekly_reset_at, games(:one).chat_open_until
413-
assert games(:one).chat_open?
414+
assert_equal Time.zone.local(2026, 9, 5, 4, 0), game.chat_open_until
415+
assert game.chat_open?
416+
end
417+
ensure
418+
game&.destroy
419+
end
420+
421+
# Ближайшая суббота ничего не делает с составом игры, назначенной после неё:
422+
# чистка сносит только прошедшие разовые игры, сброс — только отыгранные серии.
423+
test "a game scheduled beyond the coming reset keeps its chat until its own" do
424+
one_off = Game.create!(court: courts(:one), user: users(:one), date: Date.new(2026, 9, 20), kind: "game")
425+
# Серия с ближайшим вхождением в воскресенье — уже за субботней границей.
426+
series = Game.create!(court: courts(:one), user: users(:one), date: Date.new(2026, 9, 6), recurring: true, kind: "game")
427+
428+
travel_to Time.zone.local(2026, 9, 2, 21, 0) do
429+
assert_equal Time.zone.local(2026, 9, 26, 4, 0), one_off.chat_open_until
430+
assert_equal Time.zone.local(2026, 9, 12, 4, 0), series.chat_open_until
431+
assert one_off.chat_open?
432+
assert series.chat_open?
414433
end
434+
ensure
435+
[ one_off, series ].compact.each(&:destroy)
436+
end
437+
438+
test "chat closes once the cleanup that removes the game has passed" do
439+
game = Game.create!(court: courts(:one), user: users(:one), date: Date.new(2026, 8, 25), kind: "game")
440+
441+
travel_to Time.zone.local(2026, 9, 2, 21, 0) do
442+
assert_nil game.chat_open_until
443+
assert_not game.chat_open?
444+
end
445+
ensure
446+
game&.destroy
415447
end
416448

417449
test "the chat window rolls over to the next week right at the reset" do

0 commit comments

Comments
 (0)