강동현
Builds for 1 pipeline failed in 1 minute 18 seconds

준비 상태 구현

......@@ -39,6 +39,7 @@ export const RoomInfoRecord = Record({
Record({
username: String,
admin: Boolean,
ready: Boolean,
})
),
});
......
......@@ -42,6 +42,11 @@ export class ServerInboundMessageRecordMap {
message: String,
});
// 준비합니다.
ready = Record({
ready: Boolean,
});
// drawer가 단어를 선택합니다.
chooseWord = Record({
word: String,
......@@ -75,6 +80,7 @@ interface ServerOutboundMessageMap {
user: {
username: string;
admin: boolean;
ready: boolean;
};
};
......
......@@ -41,9 +41,6 @@ export class WorldGuessingGame implements Game {
constructor(room: Room) {
this.room = room;
if (this.room.users.length < 2) {
throw new Error("인원이 부족합니다.");
}
// TODO: 방장이 설정
this.maxRound = 5;
......
......@@ -19,6 +19,7 @@ export class Room {
public readonly roomManager: RoomManager;
public users: User[] = [];
public usersReady: User[] = [];
public admin?: User;
public closed: boolean = false;
......@@ -46,6 +47,13 @@ export class Room {
this.disconnect(user);
return { ok: true };
},
ready: (user, message) => {
if (user === this.admin) {
return { ok: false };
}
this.setReady(user, message.ready);
return { ok: true };
},
});
if (this.admin) {
......@@ -63,6 +71,7 @@ export class Room {
user: {
username: user.username,
admin: user === this.admin,
ready: this.usersReady.includes(user),
},
});
......@@ -74,6 +83,7 @@ export class Room {
const index = this.users.indexOf(user);
if (index > -1) {
this.users.splice(index, 1);
this.usersReady = this.usersReady.filter((u) => u !== user);
user.room = undefined;
this.broadcast("updateRoomUser", {
......@@ -81,6 +91,7 @@ export class Room {
user: {
username: user.username,
admin: user === this.admin,
ready: this.usersReady.includes(user),
},
});
......@@ -92,15 +103,73 @@ export class Room {
}
}
public setAdmin(user: User) {
if (this.users.includes(user)) {
const prevAdmin = this.admin;
this.admin = user;
this.usersReady = this.usersReady.filter((u) => u !== user);
if (prevAdmin) {
this.updateUserStatus(prevAdmin);
}
this.updateUserStatus(user);
}
}
private setNextAdmin(): void {
const nextAdmin = this.users[Math.floor(Math.random() * this.users.length)];
this.admin = nextAdmin;
this.setAdmin(nextAdmin);
}
public isAdmin(user: User): boolean {
return this.admin === user;
}
public clearReady(): void {
this.usersReady = [];
}
public setReady(user: User, ready: boolean) {
if (this.users.includes(user) && this.admin !== user) {
if (ready && !this.usersReady.includes(user)) {
this.usersReady.push(user);
} else if (!ready && this.usersReady.includes(user)) {
this.usersReady.splice(this.usersReady.indexOf(user), 1);
}
this.updateUserStatus(user);
}
}
public isReady(user: User): boolean {
return this.usersReady.includes(user);
}
public canStart(): boolean {
if (this.users.length < 2) {
return false;
}
for (let i = 0; i < this.users.length; i++) {
if (!this.isAdmin(this.users[i]) && !this.isReady(this.users[i])) {
return false;
}
}
return true;
}
public sendChat(user: User, message: string): void {
this.broadcast("chat", { sender: user.username, message: message });
}
private updateUserStatus(user: User) {
this.broadcast("updateRoomUser", {
state: "updated",
user: {
username: user.username,
admin: this.isAdmin(user),
ready: this.isReady(user),
},
});
}
public getDescription(): RoomDescription {
return {
uuid: this.uuid,
......@@ -118,7 +187,8 @@ export class Room {
users: this.users.map((u) => {
return {
username: u.username,
admin: u === this.admin,
admin: this.isAdmin(u),
ready: this.usersReady.includes(u),
};
}),
};
......
......@@ -12,7 +12,7 @@ describe("방장", () => {
const room = roomManager.create("테스트", 2, socket.connection.user);
expect(room.admin).eq(socket.connection.user);
});
it("나중에 들어온 유저는 방장이 되지 않습니다", () => {
it("나중에 들어온 유저는 방장 정보를 받지만 방장이 되지 않습니다", () => {
const socket1 = new SocketTester(roomManager);
const socket2 = new SocketTester(roomManager);
socket1.login("guest1");
......@@ -45,4 +45,50 @@ describe("방장", () => {
expect(socket1.test("leaveRoom", {}).ok).eq(true);
expect(room.admin).eq(socket2.connection.user);
});
it("방장을 인계하면 정보가 업데이트됩니다", () => {
const socket1 = new SocketTester(roomManager);
const socket2 = new SocketTester(roomManager);
socket1.login("guest1");
socket2.login("guest2");
expect(socket1.connection.user !== undefined).eq(true);
expect(socket2.connection.user !== undefined).eq(true);
const room = roomManager.create("테스트", 2, socket1.connection.user);
expect(socket2.test("joinRoom", { uuid: room.uuid }).ok).eq(true);
expect(room.admin).eq(socket1.connection.user);
expect(room.admin).not.eq(socket2.connection.user);
if (socket2.connection.user) {
room.setAdmin(socket2.connection.user);
expect(room.admin).eq(socket2.connection.user);
// guest1은 guest2가 접속했다는 메세지를 먼저 받은 상태
let message = socket1.socket.received("updateRoomUser");
expect(message.state).eq("added");
expect(message.user.username).eq("guest2");
// 먼저 이전 방장의 업데이트를 받음
message = socket1.socket.received("updateRoomUser");
expect(message.state).eq("updated");
expect(message.user.username).eq("guest1");
expect(message.user.admin).eq(false);
message = socket2.socket.received("updateRoomUser");
expect(message.state).eq("updated");
expect(message.user.username).eq("guest1");
expect(message.user.admin).eq(false);
// 현재 방장의 업데이트를 받음
message = socket1.socket.received("updateRoomUser");
expect(message.state).eq("updated");
expect(message.user.username).eq("guest2");
expect(message.user.admin).eq(true);
message = socket2.socket.received("updateRoomUser");
expect(message.state).eq("updated");
expect(message.user.username).eq("guest2");
expect(message.user.admin).eq(true);
}
});
});
......
import { expect } from "chai";
import { RoomManager } from "../room/RoomManager";
import { SocketTester } from "./util/SocketTester";
describe("준비", () => {
const roomManager = new RoomManager();
it("방에 입장하면 준비되지 않은 상태입니다", () => {
const socket = new SocketTester(roomManager);
socket.login("guest1");
const room = roomManager.create("테스트", 2);
const response = socket.test("joinRoom", { uuid: room.uuid });
expect(response.ok).eq(true);
expect(response.result?.users[0]?.username).eq("guest1");
expect(response.result?.users[0]?.ready).eq(false);
});
it("준비 상태를 설정합니다", () => {
const socket = new SocketTester(roomManager);
socket.login("guest1");
const room = roomManager.create("테스트", 2);
expect(socket.test("joinRoom", { uuid: room.uuid }).ok).eq(true);
expect(socket.connection.user !== undefined).eq(true);
if (socket.connection.user) {
expect(room.isReady(socket.connection.user)).eq(false);
expect(socket.test("ready", { ready: true }).ok).eq(true);
expect(room.isReady(socket.connection.user)).eq(true);
expect(socket.test("ready", { ready: false }).ok).eq(true);
expect(room.isReady(socket.connection.user)).eq(false);
}
});
it("방장은 준비할 수 없습니다", () => {
const socket = new SocketTester(roomManager);
socket.login("guest1");
expect(socket.connection.user !== undefined).eq(true);
if (socket.connection.user) {
const room = roomManager.create("테스트", 2, socket.connection.user);
expect(socket.test("ready", { ready: true }).ok).eq(false);
expect(room.isReady(socket.connection.user)).eq(false);
}
});
it("방장이 되면 준비 상태가 해제됩니다", () => {
const socket1 = new SocketTester(roomManager);
const socket2 = new SocketTester(roomManager);
socket1.login("guest1");
socket2.login("guest2");
expect(socket1.connection.user !== undefined).eq(true);
expect(socket2.connection.user !== undefined).eq(true);
if (socket1.connection.user && socket2.connection.user) {
const room = roomManager.create("테스트", 2, socket1.connection.user);
expect(socket2.test("joinRoom", { uuid: room.uuid }).ok).eq(true);
expect(socket2.test("ready", { ready: true }).ok).eq(true);
expect(room.isReady(socket2.connection.user));
room.setAdmin(socket2.connection.user);
expect(room.isReady(socket2.connection.user)).eq(false);
}
});
it("모두가 준비해야 게임을 시작할 수 있습니다", () => {
const socket1 = new SocketTester(roomManager);
const socket2 = new SocketTester(roomManager);
const socket3 = new SocketTester(roomManager);
socket1.login("guest1");
socket2.login("guest2");
socket3.login("guest3");
expect(socket1.connection.user !== undefined).eq(true);
expect(socket2.connection.user !== undefined).eq(true);
expect(socket3.connection.user !== undefined).eq(true);
if (
socket1.connection.user &&
socket2.connection.user &&
socket3.connection.user
) {
const room = roomManager.create("테스트", 3, socket1.connection.user);
expect(socket2.test("joinRoom", { uuid: room.uuid }).ok).eq(true);
expect(socket3.test("joinRoom", { uuid: room.uuid }).ok).eq(true);
// 2, 3 모두 준비 안함
expect(room.canStart()).eq(false);
// 2만 준비
expect(socket2.test("ready", { ready: true }).ok).eq(true);
// 3만 준비
expect(socket2.test("ready", { ready: false }).ok).eq(true);
expect(socket3.test("ready", { ready: true }).ok).eq(true);
expect(room.canStart()).eq(false);
// 2, 3 모두 준비
expect(socket2.test("ready", { ready: true }).ok).eq(true);
expect(room.canStart()).eq(true);
}
});
});