-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #204 from boostcampwm-2024/dev-fe
Dev fe
- Loading branch information
Showing
41 changed files
with
1,440 additions
and
113 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import SocketEvents from '@/constants/socketEvents'; | ||
import { SocketDataMap } from '../socketEventTypes'; | ||
|
||
type SocketEvent = keyof SocketDataMap; | ||
|
||
export class SocketMock { | ||
private listenerSet: Record<string, ((...args: unknown[]) => void)[]> = {}; | ||
private onAnyListenerList: ((event: string, ...args: unknown[]) => void)[] = []; | ||
constructor(url: string) { | ||
console.log(`Mock WebSocket μ°κ²°: ${url}`); | ||
} | ||
id = 'memememememe'; | ||
connected = true; | ||
on(event: string, listener: (...args: unknown[]) => void) { | ||
if (!this.listenerSet[event]) this.listenerSet[event] = []; | ||
this.listenerSet[event].push(listener); | ||
} | ||
onAny(listener: (...args: unknown[]) => void) { | ||
this.onAnyListenerList.push(listener); | ||
} | ||
emit<T extends SocketEvent>(event: T, data: SocketDataMap[T]['request']) { | ||
//μ¬κΈ°μ μλ²μ λ°μ΄ν° μ μ‘ | ||
switch (event) { | ||
case SocketEvents.CHAT_MESSAGE: | ||
return this.handleChat(data as SocketDataMap[typeof SocketEvents.CHAT_MESSAGE]['request']); | ||
case SocketEvents.JOIN_ROOM: | ||
return this.handleJoin(data as SocketDataMap[typeof SocketEvents.JOIN_ROOM]['request']); | ||
case SocketEvents.UPDATE_POSITION: | ||
return this.handlePosition( | ||
data as SocketDataMap[typeof SocketEvents.UPDATE_POSITION]['request'] | ||
); | ||
case SocketEvents.UPDATE_ROOM_OPTION: | ||
return this.handleOption( | ||
data as SocketDataMap[typeof SocketEvents.UPDATE_ROOM_OPTION]['request'] | ||
); | ||
case SocketEvents.UPDATE_ROOM_QUIZSET: | ||
return this.handleQuiz( | ||
data as SocketDataMap[typeof SocketEvents.UPDATE_ROOM_QUIZSET]['request'] | ||
); | ||
default: | ||
return; | ||
} | ||
} | ||
disconnect() { | ||
this.connected = false; | ||
} | ||
|
||
//μ¬κΈ°μ μλ² μ΄λ²€νΈλ₯Ό μ€νμν¨λ€. | ||
emitServer<T extends SocketEvent>(event: T, data: SocketDataMap[T]['response']) { | ||
if (this.listenerSet[event]) { | ||
this.listenerSet[event].forEach((e) => e(data)); | ||
} | ||
this.onAnyListenerList.forEach((e) => e(event, data)); | ||
} | ||
delay(second: number) { | ||
return new Promise<void>((resolve) => { | ||
setTimeout(() => resolve(), second * 1000); | ||
}); | ||
} | ||
log(message: string) { | ||
this.emitServer('chatMessage', { | ||
playerId: '', | ||
playerName: '[LOG]', | ||
message: message, | ||
timestamp: 0 | ||
}); | ||
} | ||
//μλ κΈ°λ° λλ€ ν¨μ | ||
SEED = 7777; | ||
random() { | ||
this.SEED = (this.SEED * 16807) % 2147483647; | ||
return (this.SEED - 1) / 2147483646; | ||
} | ||
|
||
isCurrentJoin = false; | ||
currentPlayerName = ''; | ||
players: { | ||
playerId: string; | ||
playerName: string; | ||
playerPosition: [number, number]; | ||
}[] = []; | ||
|
||
quiz: { | ||
quiz: string; | ||
endTime: number; | ||
startTime: number; | ||
choiceList: { content: string; order: number }[]; | ||
} | null = null; | ||
|
||
// μλλ μλ² λΉμ¦λμ€ λ‘μ§ | ||
private async handleChat(data: SocketDataMap['chatMessage']['request']) { | ||
await this.delay(0.1); | ||
this.emitServer('chatMessage', { | ||
playerId: this.id, | ||
playerName: this.currentPlayerName, | ||
message: data.message, | ||
timestamp: 0 | ||
}); | ||
} | ||
private async handleJoin(data: SocketDataMap[typeof SocketEvents.JOIN_ROOM]['request']) { | ||
if (this.isCurrentJoin) return; | ||
this.isCurrentJoin = true; | ||
await this.delay(0.1); | ||
this.currentPlayerName = data.playerName; | ||
const currentPlayer: (typeof this.players)[number] = { | ||
playerId: this.id, | ||
playerName: data.playerName, | ||
playerPosition: [0.5, 0.5] | ||
}; | ||
this.emitServer(SocketEvents.JOIN_ROOM, { | ||
players: this.players | ||
}); | ||
this.emitServer(SocketEvents.JOIN_ROOM, { | ||
players: [currentPlayer] | ||
}); | ||
this.players.push(currentPlayer); | ||
} | ||
private async handlePosition( | ||
data: SocketDataMap[typeof SocketEvents.UPDATE_POSITION]['request'] | ||
) { | ||
await this.delay(0.1); | ||
const targetPlayer = this.players.find((p) => p.playerId === this.id); | ||
if (targetPlayer) targetPlayer.playerPosition = data.newPosition; | ||
this.emitServer(SocketEvents.UPDATE_POSITION, { | ||
playerId: this.id, | ||
playerPosition: data.newPosition | ||
}); | ||
} | ||
private async handleOption( | ||
data: SocketDataMap[typeof SocketEvents.UPDATE_ROOM_OPTION]['request'] | ||
) { | ||
await this.delay(0.1); | ||
this.emitServer(SocketEvents.UPDATE_ROOM_OPTION, { | ||
title: data.title, | ||
gameMode: data.gameMode, | ||
maxPlayerCount: data.maxPlayerCount, | ||
isPublic: data.isPublic | ||
}); | ||
} | ||
private async handleQuiz( | ||
data: SocketDataMap[typeof SocketEvents.UPDATE_ROOM_QUIZSET]['request'] | ||
) { | ||
await this.delay(0.1); | ||
this.emitServer(SocketEvents.UPDATE_ROOM_QUIZSET, data); | ||
} | ||
|
||
//ν΄μ¦ κ΄λ ¨ λΉμ¦λμ€ λ‘μ§ | ||
setQuiz(quiz: string, quizSecond: number, choiceList: string[]) { | ||
const COUNT_DOWN_TIME = 3000; | ||
this.quiz = { | ||
quiz, | ||
startTime: Date.now() + COUNT_DOWN_TIME, | ||
endTime: Date.now() + COUNT_DOWN_TIME + quizSecond * 1000, | ||
choiceList: choiceList.map((e, i) => ({ content: e, order: i })) | ||
}; | ||
this.emitServer('startQuizTime', this.quiz); | ||
} | ||
calculateScore(answer: number) { | ||
const players = this.players.map((p) => { | ||
const [y, x] = p.playerPosition; | ||
const option = | ||
Math.round(x) + Math.floor(y * Math.ceil((this.quiz?.choiceList.length || 0) / 2)) * 2; | ||
return { | ||
playerId: p.playerId, | ||
isAnswer: option === answer, | ||
score: option === answer ? 22 : 0 | ||
}; | ||
}); | ||
const payload = { answer, players }; | ||
this.emitServer('endQuizTime', payload); | ||
} | ||
|
||
async progressQuiz(quiz: string, quizSecond: number, choiceList: string[], answer: number) { | ||
this.setQuiz(quiz, quizSecond, choiceList); | ||
await this.delay(3 + quizSecond); | ||
this.calculateScore(answer); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { SocketMock } from '../SocketMock'; | ||
|
||
export default class SocketMockChat extends SocketMock { | ||
constructor() { | ||
super(''); | ||
this.players = Array(10) | ||
.fill(null) | ||
.map((_, i) => ({ | ||
playerId: String(i + 1), | ||
playerName: 'player' + i, | ||
playerPosition: [i / 10, i / 10] | ||
})); | ||
this.test1(); | ||
} | ||
// 10λͺ μ μ μ κ° μ±ν μ 보λ | ||
async test1() { | ||
for (let i = 0; i < 150; i++) { | ||
await this.delay(0.1); | ||
const index = i % this.players.length; | ||
this.emitServer('chatMessage', { | ||
playerId: this.players[index].playerId, | ||
playerName: this.players[index].playerName, | ||
message: String(i), | ||
timestamp: 0 | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { SocketMock } from '../SocketMock'; | ||
|
||
export default class SocketMockLoadTest extends SocketMock { | ||
constructor() { | ||
super(''); | ||
this.players = Array(100) | ||
.fill(null) | ||
.map((_, i) => ({ | ||
playerId: String(i + 1), | ||
playerName: 'player' + i, | ||
playerPosition: [this.random(), this.random()] | ||
})); | ||
this.testChat(); | ||
this.testMove(); | ||
} | ||
// 10λͺ μ μ μ κ° μ±ν μ 보λ | ||
async testChat() { | ||
const playerCount = this.players.length; | ||
const testTime = 10; | ||
for (let j = 0; j < testTime; j++) { | ||
//10μ΄λμ | ||
for (let i = 0; i < playerCount; i++) { | ||
await this.delay(1 / playerCount); | ||
this.emitServer('chatMessage', { | ||
playerId: this.players[i].playerId, | ||
playerName: this.players[i].playerName, | ||
message: 'message' + i, | ||
timestamp: 0 | ||
}); | ||
} | ||
} | ||
} | ||
|
||
async testMove() { | ||
const playerCount = this.players.length; | ||
const testTime = 10; | ||
for (let j = 0; j < testTime; j++) { | ||
//10μ΄λμ | ||
for (let i = 0; i < playerCount; i++) { | ||
await this.delay(1 / playerCount); | ||
this.emitServer('updatePosition', { | ||
playerId: this.players[i].playerId, | ||
playerPosition: [this.random(), this.random()] | ||
}); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.