className='toolbox-content-tiems'에 this._renderLiarGameButton()
추가
_renderLiarGameButton() {
return this.props._shouldShowButton("liarVote") ? (
<LiarVoteButton
key="liarVote"
onHandleClick={this._onRequestLiarGame}
visible={true}
/>
) : null;
}
라이어 게임 버튼을 누르면 this._onRequestLiarVote
실행
_onRequestLiarGame() {
// 방이 생성 되었는지 한 번 더 확인해주는 과정
if (!APP || !APP.conference || !APP.conference.isJoined()) {
return;
}
this._onToolbarOpenLiarGame();
}
_onToolbarOpenLiarGame() {
sendAnalytics(createToolbarEvent("liar"));
// 카테고리를 선택 중이라는 메시지를 모두에게 알림
APP.store.dispatch(
showNotification(
{
descriptionKey: "잠시만 기다려주세요.",
titleKey: "카테고리를 선택 중 입니다.",
},
NOTIFICATION_TIMEOUT
)
);
// 라이어 게임 컴포넌트를 모달 형태로 오픈
this.props.dispatch(openDialog(LiarGame));
}
// 하드코딩 된 데이터를 가져와서 맵핑
return (
<div>
<div>카테고리를 골라주세요.</div>
{data.map((theme, idx) => {
return (
<button
key={idx}
onClick={handleTitle}
value={JSON.stringify(theme)}
>
{theme.title}
</button>
);
})}
</div>
);
const handleTitle = (e) => {
e.preventDefault();
const title = JSON.parse(e.target.value).title;
const words = JSON.parse(e.target.value).words;
// store에 카테고리 타이틀 저장
dispatch(addTitle(title));
selectWord(words);
};
const selectWord = (words) => {
// 카테고리에서 단어 랜덤 선택
word.current = words[Math.floor(Math.random() * words.length)];
// store에 제시어 저장
dispatch(addWord(word.current));
// 게임시작
dispatch(openDialog(checkLiar));
};
const membersId = useRef([]); // 방 참여자 모든 아이디
membersId.current = shuffle([
...conference.listMembersIds(),
conference.getMyUserId(),
]);
return (
<Dialog handleCancelButton={true} submitDisabled={true}>
<div>누가 라이어일까요?</div>
<button onClick={selectLiar}>게임시작</button>
</Dialog>
);
const selectLiar = (e) => {
const { conference } = APP.store.getState()["features/base/conference"];
e.preventDefault();
// 제시어 뿌려주기
conference.sendCommandOnce("sendWord", {
value: _word,
attributes: { ids: membersId.current, title: _title },
});
resetIds();
};
// conference.js
room.addCommandListener("sendWord", async (data, id) => {
const prompt = data.value; // 제시어
const randomIds = data.attributes.ids.split(","); // 셔플 된 아이디 배열
const title = data.attributes.title; // 카테고리 타이틀
const category = $(`<div>카테고리: ${title}</div>`);
const elem = $(`<div>${prompt}</div>`);
const liar = $(`<div>라이어</div>`);
// 제시어 모달 오픈
await this._openPrompt();
// 투표 초기값 설정
APP.store.dispatch(gameStart(true));
APP.store.dispatch(voteLiar([]));
// 참가자 중 라이어를 랜덤으로 지정
selectLiar(randomIds, category, elem, liar, APP.store);
// 제시어 화면에 띄워주기
APP.store.dispatch(
showNotification({
descriptionKey: `제시어: ${prompt}`,
titleKey: `카테고리: ${title} `,
})
);
setTimeout(() => {
APP.store.dispatch(hideDialog(checkLiar));
}, 5000);
});
showNotification({})
this._renderLiarVoteButton()
추가
_renderLiarVoteButton() {
return this.props._shouldShowButton("liarVote") ? (
<LiarVoteButton
key="liarVote"
onHandleClick={this._onRequestLiarVote}
visible={true}
/>
) : null;
}
_onRequestLiarVote() {
if (!APP || !APP.conference || !APP.conference.isJoined()) {
return;
}
this._onToolbarOpenLiarVote();
}
_onToolbarOpenLiarVote() {
const { conference } = APP.store.getState()["features/base/conference"];
sendAnalytics(createToolbarEvent("liarVote"));
// 예외처리
// 라이어 게임을 시작하지 않고 투표를 누르거나
// 투표를 하고 투표 모달을 끄고 다시 투표 버튼을 누루거나
// 투표가 완료되고 라이어 게임을 시작하지 않고 투표를 누르는 경우
if (!this.props._start) {
alert("라이어 게임을 먼저 시작해주세요.");
} else if (this.props._liars.length === 0 && this.props._liars) {
// 투표 모달 오픈
conference.sendCommandOnce("openLiarVote", {
value: true,
});
} else {
alert("이미 투표했거나 라이어 게임을 다시 시작해 주세요.");
}
}
// conference.js
// 투표 모달 열기
room.addCommandListener("openLiarVote", (data) => {
APP.store.dispatch(openDialog(LiarVote));
});
return (
<Dialog
hideCancelButton={true}
submitDisabled={true}
titleString="투표하기"
>
<div>라이어를 찾으셨나요? 투표해보세요!</div>
{_exceptMyselfIds
? _exceptMyselfIds.map((id, idx) => {
const displayName =
conference.getParticipantDisplayName(id);
return (
<>
<label
htmlFor="voteName"
onChange={handleVote}
key={idx}
>
{displayName} // 본인 제외 투표할 유저 이름 표시
</label>
<input
type="radio"
name="voteName"
id="voteName"
value={id}
onClick={handleVote}
/>
</>
);
})
: null}
{isVoted && liar !== "" ? (
<div>집계 중 입니다...</div>
) : (
<button onClick={completeVote}>라이어 지목하기</button>
)}
</Dialog>
);
// 체크박스를 클릭 할 때마다 liar 상태 변경
const handleVote = (e) => {
setLiar(e.target.value);
};
// 체크박스로 라이어를 선택하고 라이어 지목하기를 누르면 그때 스토어에 저장
const completeVote = (e) => {
e.preventDefault();
// 라이어 선택 안 하고 라이어 지목하기 눌렀을 때 예외처리
liar !== "" ? setIsVoted(true) : null;
liar !== "" ? (liars.current = [..._liars, liar]) : null;
const { conference } = APP.store.getState()["features/base/conference"];
// 지목 된 라이어와 유저 수 전달
conference.sendCommandOnce("sendLiar", {
value: participantsId.current.length + 1,
attributes: { liar },
});
// 투표 수와 유저수가 같아지면 결과창 오픈
if (participantsId.current.length + 1 === liars.current.length) {
openResult(liars.current);
}
};
// conference.js
// 투표한 유저 아이디 수집
room.addCommandListener("sendLiar", (data) => {
const liar = data.attributes.liar;
const numOfParticipants = data.value;
liars.push(liar);
// 유저 선택을 안 하고 라이어 지목하기 버튼을 눌렀을 때 예외처리
noBlankLiars = liars.filter((liar) => liar !== "");
// 유저 숫자보다 투표 수가 많아지면 리셋
if (noBlankLiars.length > numOfParticipants) {
liars = [liar];
noBlankLiars = [liar];
}
APP.store.dispatch(voteLiar(noBlankLiars));
});
// LiarVote.js
const openResult = (liars) => {
const { conference } = APP.store.getState()["features/base/conference"];
let participantsIds = participantsId.current;
let myIds = myId.current;
// 결과창 오픈
conference.sendCommandOnce("openResult", {
value: liars,
attributes: { participantsIds, myIds },
});
};
// conference.js
room.addCommandListener("openResult", async (data) => {
const liars = data.value.split(",");
const participantsId = data.attributes.participantsIds.split(",");
const myId = data.attributes.myIds;
let resultObj = {};
// 투표 집계
resultObj = await countUpVote(resultObj, liars);
// 투표 받지 못한 사람 추가
resultObj = await getNumOfVote(resultObj, [
...participantsId,
myId,
]);
APP.store.dispatch(addResult(resultObj)); // store에 투표 결과 저장
APP.store.dispatch(openDialog(Result)); // 결과창 오픈
});
return (
<Dialog
hideCancelButton={true}
submitDisabled={true}
titleString="투표 결과창"
>
{Object.keys(_result).map((id, idx) => {
const displayName = conference.getParticipantDisplayName(id);
return (
<>
<div key={idx}>
{check
? `${displayName}: ${displayWhoIsLiar(id)}` // 득표 수 표시
: `${displayName}: ${_result[id]}`} // 플레이어 or 라이어 표시
</div>
</>
);
})}
{check ? (
<div>
라이어는 {conference.getParticipantDisplayName(_liar)}
입니다!
</div>
) : (
// 라이어 확인하기 버튼 (득표 수 -> 라이어 표시)
<button onClick={findOutRealLiar}>라이어 확인하기</button>
)}
{whoWon && check ? (
<div>라이어를 맞췄습니다! 라이어는 제시어를 맞춰주세요.</div>
) : null}
// 득표 수가 같은 경우 재투표
{highestVoter === "똑같아요" ? (
<button onClick={openReVote}>재투표</button>
) : highestVoter === "똑같아요" && reVote ? (
<div>라이어 승리</div>
) : whoWon === false && check ? (
<div>
라이어는
{conference.getParticipantDisplayName(highestVoter)}가
아닙니다. 라이어 승리!
</div>
) : null}
<button onClick={gameOver}>게임종료</button>
<button onClick={reStart}>다시하기</button>
</Dialog>
);
const findOutRealLiar = () => {
setCheck(true);
if (highestVoter === _liar) { // 표를 가장 많이 받은 사람과 라이어 아이디가 같으면
setWhoWon(true);
} else {
setWhoWon(false);
}
};
// 투표 버튼 예외처리
if (!this.props._start) { // 라이어 게임을 시작하지고 투표를 누르면
alert("라이어 게임을 먼저 시작해주세요.");
} else if (this.props._liars.length === 0 && this.props._liars) { // 라이어 게임을 시작했고 투표를 하지 않았으면
conference.sendCommandOnce("openLiarVote", {
value: true,
});
} else {
alert("이미 투표했거나 라이어 게임을 다시 시작해 주세요.");
}
투표를 진행할 때마다 store에 저장해서 바로 불러오는 방식으로 하려고 했으나 유저별로 업데이트 되지 않는 이슈 발생
liarVote 컴포넌트에서 sendCommandOnce()
사용해서 store에 저장하는 방식으로 이슈 해결
//LiarVote.js
const completeVote = (e) => {
e.preventDefault();
const { conference } = APP.store.getState()["features/base/conference"];
conference.sendCommandOnce("sendLiar", {
value: liar,
});
};
//conference.js
room.addCommandListener("sendLiar", (data) => {
const liar = data.value;
liars.push(liar);
APP.store.dispatch(voteLiar(liars));
});
conference.getParticipantDisplayName(id)
As Samantha started getting into the rhythm of blackjack, she realized that it wasn’t just about luck—it required a blend of quick thinking and careful planning. Each hand became a mental challenge, and she found herself hooked https://yabbycasinoau1.com/ on perfecting her strategy. The thrill of winning, combined with the intellectual stimulation of the game, ignited a passion she hadn’t anticipated. Soon, blackjack was no longer just a game to pass the time—it became her go-to form of entertainment.