아무도 앉지 않은 방은 마지막 사람이 [방 나가기]로 나가면 바로 닫기

- 컴퓨터가 있는 방에만 있던 '나가서 앉은 사람이 없으면 바로 닫기'를 모든 방에 적용
  (아무도 들어오지 않은 대기실을 만든 사람이 나가면 목록에서 바로 사라짐)
- 관전자가 남아 있으면 그대로 두고, 마지막 관전자가 나갈 때 닫음
- 사이트를 닫거나 다른 화면으로 간 경우(자리 유지)는 기존 규칙 그대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-10-08 10:14:29 +09:00
parent f5671cda70
commit beaee4675d
3 changed files with 35 additions and 3 deletions

View File

@@ -312,6 +312,38 @@ describe('practice rooms close once nobody is there', () => {
expect(h.manager.get(room.code)).toBeUndefined(); expect(h.manager.get(room.code)).toBeUndefined();
}); });
test('a room nobody joined closes as soon as the host leaves it', () => {
const h = harness();
const room = h.create('A', 'omok', 'public');
room.join(h.conn('A'), 'player');
expect(h.manager.publicRooms('omok')).toHaveLength(1);
room.leave('A');
expect(h.manager.get(room.code)).toBeUndefined();
expect(h.store.openRooms()).toHaveLength(0);
expect(h.manager.publicRooms('omok')).toHaveLength(0);
// Taking a seat in another room frees the lobby seat: same thing.
const first = h.create('B');
const b = h.conn('B');
first.join(b, 'player');
first.disconnect(b);
h.manager.releaseOtherLobbySeats('B', 'other');
expect(h.manager.get(first.code)).toBeUndefined();
});
test('the last person leaving a game on purpose closes it; a spectator still watching keeps it', () => {
const h = harness();
const room = h.create('A');
room.join(h.conn('A'), 'player');
room.join(h.conn('B'), 'player');
room.join(h.conn('S'), 'spectator');
expect(room.start('A')).toBeNull();
room.leave('A');
room.leave('B');
expect(h.manager.get(room.code)).toBe(room); // S is still connected
room.leave('S');
expect(h.manager.get(room.code)).toBeUndefined();
});
test('rooms without computers keep the old timeouts; someone still connected keeps any room', () => { test('rooms without computers keep the old timeouts; someone still connected keeps any room', () => {
const h = harness(); const h = harness();
const room = h.create('A'); const room = h.create('A');

View File

@@ -50,8 +50,8 @@ export class RoomManager {
settings: this.deps.settings, settings: this.deps.settings,
botDelay: this.deps.botDelay, botDelay: this.deps.botDelay,
onEmpty: (room, why) => { onEmpty: (room, why) => {
// Everyone left a room with computer players on purpose: nobody can come back to it, close it now. // The last person left on purpose and nobody holds a seat (only computers, or nobody joined): close it now.
if (why === 'leave' && this.byCode.get(room.code) === room && room.hasBots() && !room.hasPeopleSeated()) this.close(room); if (why === 'leave' && this.byCode.get(room.code) === room && !room.hasPeopleSeated()) this.close(room);
}, },
onSeatChange: (room, userId, seated) => { onSeatChange: (room, userId, seated) => {
if (isBotId(userId)) return; if (isBotId(userId)) return;

View File

@@ -95,7 +95,7 @@ interface Room {
``` ```
- 한 사용자는 동시에 한 방에만 플레이어로 있을 수 있다(다른 방에 들어가면 이전 방 대기실 자리에서 빠짐. 이전 방이 게임 중이면 "진행 중인 게임이 있어요. 그래도 이동할까요?"). - 한 사용자는 동시에 한 방에만 플레이어로 있을 수 있다(다른 방에 들어가면 이전 방 대기실 자리에서 빠짐. 이전 방이 게임 중이면 "진행 중인 게임이 있어요. 그래도 이동할까요?").
- 제한: 서버 전체 방 2,000개, 사용자당 동시에 만든 방 3개. - 제한: 서버 전체 방 2,000개, 사용자당 동시에 만든 방 3개.
- 방 정리(1분마다): 접속이 하나도 없는 방 중 대기실은 10분, 끝난 방·멈춘 방은 30분 동안 활동이 없으면 닫는다. 컴퓨터가 있는 방(연습 방)은 마지막 사람이 나간 때부터 재서 대기실·끝난 방은 1분, 게임 중인 방은 30분 뒤 닫는다(사이트를 닫았으면 아래 규칙대로 1분). 사람이 [방 나가기]로 모두 나가 컴퓨터만 남으면 바로 닫는다. - 방 정리(1분마다): 접속이 하나도 없는 방 중 대기실은 10분, 끝난 방·멈춘 방은 30분 동안 활동이 없으면 닫는다. 컴퓨터가 있는 방(연습 방)은 마지막 사람이 나간 때부터 재서 대기실·끝난 방은 1분, 게임 중인 방은 30분 뒤 닫는다(사이트를 닫았으면 아래 규칙대로 1분). 마지막 사람이 [방 나가기]로 나가서 자리에 앉은 사람이 없으면(컴퓨터만 남았거나 아무도 들어오지 않은 방) 바로 닫는다.
- 게임 중이거나 끝난 방(대기실 제외)에서 자리에 앉은 사람이 모두 사이트를 닫으면(서버와 연결된 창이 하나도 없으면) 마지막 사람이 닫은 때부터 1분 뒤 정리 때 닫는다. 진행 중인 게임은 무효 처리되고, 관전자는 셈하지 않고, 남아 있던 관전자도 방에서 내보낸다. 대기실은 초대받은 사람이 들어올 수 있으므로 위 규칙을 따른다. 자리가 있는 사람은 다른 화면에 있어도 서버 연결을 유지한다(새로 연 창에서도 `/api/me`의 `activeRoom`이 있으면 연결). - 게임 중이거나 끝난 방(대기실 제외)에서 자리에 앉은 사람이 모두 사이트를 닫으면(서버와 연결된 창이 하나도 없으면) 마지막 사람이 닫은 때부터 1분 뒤 정리 때 닫는다. 진행 중인 게임은 무효 처리되고, 관전자는 셈하지 않고, 남아 있던 관전자도 방에서 내보낸다. 대기실은 초대받은 사람이 들어올 수 있으므로 위 규칙을 따른다. 자리가 있는 사람은 다른 화면에 있어도 서버 연결을 유지한다(새로 연 창에서도 `/api/me`의 `activeRoom`이 있으면 연결).
- 방 화면을 벗어나면(홈, 규칙 등) 클라이언트가 `detach`를 보낸다. 자리는 그대로이고 '접속 중'으로 남지만, 방 메시지를 받지 않고 방의 접속 수에서도 빠진다. 그 상태로 사이트를 닫으면 연결 끊김으로 처리한다. - 방 화면을 벗어나면(홈, 규칙 등) 클라이언트가 `detach`를 보낸다. 자리는 그대로이고 '접속 중'으로 남지만, 방 메시지를 받지 않고 방의 접속 수에서도 빠진다. 그 상태로 사이트를 닫으면 연결 끊김으로 처리한다.