아직 패킷 전송 부분에 대해서 생각하지 못해 TODO로 냅두고 클래스 만들어서 테스트 해보았다.
임시로 만든 테스트 코드 흐름에는 문제가 없는데... 패킷 전송부 구현 후 테스트가 두렵다
import Timer from '../utils/Timer.class.js';
class CheckPoint {
#users;
#status;
currentStatus;
constructor(name) {
this.name = name;
this.#users = [[], []]; // 0: 팀 A, 1: 팀 B
this.#status = 'waiting';
this.currentStatus = this.#status;
this.timer = new Timer(5000, this.completeOccupation.bind(this)); // 5초 타이머
}
// 유닛 추가/제거
modifyUnit(team, unit, action) {
const array = this.#users[team];
switch (action) {
case 'add':
array.push(unit);
this.checkStatus(team);// 상태 확인 (waiting, occupied(0,1), attempting(0,1))
break;
case 'remove':
array.splice(array.indexOf(unit), 1);
this.checkStatus(team);
break;
default:
break;
}
}
checkStatus(team) {
const myUnits = this.getUsersCount(team);// 내 유닛 수
const opponentUnits = this.getUsersCount(1 - team); // 상대 유닛 수
const timerStatus = this.timer.status; // 타이머 상태
/*
상태에 따른 행동
waiting - 내 유닛이 있으면 점령 시도 (동시에 적팀도 들어갈 확률은 없음, 패킷도착순)
occupied(0,1) - 점령 상태 기준에서 상대방 유닛만 있을 경우 점령시도
attempting(0,1) - 점령 시도 중 상대방 유닛이 들어올 경우 일시정지
handleAttempt 함수에서 상태에 따른 행동 처리
*/
const actions = {
waiting: () => {
if (myUnits) this.attemptedOccupation(team);
},
[`occupied${team}`]: () => {
if (!myUnits && opponentUnits) this.attemptedOccupation(1 - team);
},
[`occupied${1 - team}`]: () => {
if (myUnits && !opponentUnits) this.attemptedOccupation(team);
},
[`attempting${team}`]: () => {
this.handleAttempt(opponentUnits, myUnits, timerStatus);
},
[`attempting${1 - team}`]: () => {
this.handleAttempt(myUnits, opponentUnits, timerStatus);
},
};
const action = actions[this.#status];
if (action) action();
}
handleAttempt(opponentUnits, myUnits, timerStatus) {
if (opponentUnits && timerStatus) {
this.pauseOccupation();
} else if (!opponentUnits && !timerStatus) {
this.resumeOccupation();
} else if (!myUnits) {
this.clearOccupation();
this.#status = this.currentStatus;
}
}
getUsersCount(team) {
return this.#users[team].length;
}
attemptedOccupation(team) {
this.#status = `attempting${team}`;
console.log(`${team} 팀 ${this.name}점령시도중 현재 상태: ${this.#status}`);
this.timer.start();
// TODO: 점령 시도 패킷 전송
}
clearOccupation() {
this.#status = this.currentStatus;
console.log(`${this.name}점령초기화 현재 상태: ${this.#status}`);
this.timer.clear();
// TODO: 점령 타이머 초기화 패킷 전송
}
pauseOccupation() {
console.log(`${this.name}점령일시정지 현재 상태: ${this.#status}`);
this.timer.pause();
// TODO: 점령 일시정지 패킷 전송
}
resumeOccupation() {
console.log(`${this.name}점령재개 현재 상태: ${this.#status}`);
this.timer.resume();
// TODO: 점령 재개 패킷 전송
}
completeOccupation() {
this.#status = `occupied${this.#status.replace('attempting', '')}`;
console.log(`${this.name}점령완료 현재 상태: ${this.#status}`);
this.currentStatus = this.#status;
this.timer.clear();
// TODO: 점령완료 패킷 전송
}
}
export default CheckPoint;
import CheckPoint from '../models/CheckPoint.class.js';
class CheckPointManager {
#topPoint;
#bottomPoint;
constructor() {
this.#topPoint = new CheckPoint('top');
this.#bottomPoint = new CheckPoint('bottom');
}
addUnit(isTop, team, unit) {
const checkPoint = isTop ? this.#topPoint : this.#bottomPoint; // isTop에 따른 체크포인트 인스턴스 선택
checkPoint.modifyUnit(team, unit, 'add'); // 체크포인트에 유닛 추가
}
removeUnit(isTop, team, unit) {
const checkPoint = isTop ? this.#topPoint : this.#bottomPoint;
checkPoint.modifyUnit(team, unit, 'remove');
}
}
export default CheckPointManager;