Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…m-2-BE into sandbox
  • Loading branch information
comforest committed Jul 26, 2024
2 parents 2751412 + e1260f9 commit e0b0065
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ fun XorkerException.getButtons(): List<ExceptionButtonType> {
InvalidBroadcastException,
is InvalidMafiaPhaseException,
InvalidRequestOnlyMyTurnException,
InvalidMafiaGameVotePhaseStatusException,
-> buttonOk
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.xorker.draw.exception.InvalidRequestValueException
import com.xorker.draw.mafia.MafiaGameUseCase
import com.xorker.draw.mafia.MafiaPhaseUseCase
import com.xorker.draw.mafia.MafiaVoteUseCase
import com.xorker.draw.room.RoomId
import com.xorker.draw.user.UserId
import com.xorker.draw.websocket.message.request.RequestAction
import com.xorker.draw.websocket.message.request.dto.StartMafiaGameRequest
import com.xorker.draw.websocket.message.request.dto.VoteMafiaRequest
import com.xorker.draw.websocket.message.request.dto.WebSocketRequest
import org.springframework.stereotype.Component
import org.springframework.web.socket.WebSocketSession
Expand All @@ -18,6 +21,7 @@ class WebSocketRouter(
private val sessionUseCase: SessionUseCase,
private val mafiaPhaseUseCase: MafiaPhaseUseCase,
private val mafiaGameUseCase: MafiaGameUseCase,
private val mafiaVoteUseCase: MafiaVoteUseCase,
) {
fun route(session: WebSocketSession, request: WebSocketRequest) {
when (request.action) {
Expand All @@ -31,6 +35,14 @@ class WebSocketRouter(

RequestAction.DRAW -> mafiaGameUseCase.draw(session.getDto(), request.extractBody())
RequestAction.END_TURN -> mafiaGameUseCase.nextTurnByUser(session.getDto())

RequestAction.VOTE -> {
val requestDto = request.extractBody<VoteMafiaRequest>()
val userId = UserId(requestDto.userId)
val sessionDto = sessionUseCase.getSession(SessionId(session.id)) ?: throw InvalidRequestValueException

mafiaVoteUseCase.voteMafia(sessionDto, userId)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ enum class RequestAction(
START_GAME("마피아 게임 시작"),
DRAW("그림 그리기"),
END_TURN("턴 넘기기"),
VOTE("마피아 투표"),
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.xorker.draw.websocket.message.request.dto

data class VoteMafiaRequest(
val userId: Long,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.xorker.draw.websocket.message.response

import com.xorker.draw.exception.InvalidMafiaGamePlayingPhaseStatusException
import com.xorker.draw.exception.InvalidMafiaGameVotePhaseStatusException
import com.xorker.draw.mafia.MafiaGameInfo
import com.xorker.draw.mafia.MafiaGameMessenger
import com.xorker.draw.mafia.MafiaPhase
Expand All @@ -17,6 +18,8 @@ import com.xorker.draw.websocket.message.response.dto.MafiaPlayerListBody
import com.xorker.draw.websocket.message.response.dto.MafiaPlayerListMessage
import com.xorker.draw.websocket.message.response.dto.MafiaPlayerTurnListBody
import com.xorker.draw.websocket.message.response.dto.MafiaPlayerTurnListMessage
import com.xorker.draw.websocket.message.response.dto.MafiaVoteStatusBody
import com.xorker.draw.websocket.message.response.dto.MafiaVoteStatusMessage
import com.xorker.draw.websocket.message.response.dto.toResponse
import org.springframework.stereotype.Component

Expand Down Expand Up @@ -105,4 +108,18 @@ class MafiaGameMessengerImpl(
)
broadcaster.broadcast(gameInfo.room.id, MafiaGameTurnInfoMessage(body))
}

override fun broadcastVoteStatus(mafiaGameInfo: MafiaGameInfo) {
val roomId = mafiaGameInfo.room.id

val phase = mafiaGameInfo.phase as? MafiaPhase.Vote ?: throw InvalidMafiaGameVotePhaseStatusException

val message = MafiaVoteStatusMessage(
MafiaVoteStatusBody(phase.players),
)

val event = BroadcastEvent(roomId, message)

broadcaster.publishBroadcastEvent(event)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.xorker.draw.websocket.message.response.dto

import com.xorker.draw.user.UserId
import com.xorker.draw.websocket.ResponseAction
import com.xorker.draw.websocket.SessionMessage

class MafiaVoteStatusMessage(
override val body: MafiaVoteStatusBody,
) : SessionMessage {
override val action = ResponseAction.VOTE_STATUS
override val status = SessionMessage.Status.OK
}

data class MafiaVoteStatusBody(
val players: Map<UserId, Set<UserId>>,
)
46 changes: 46 additions & 0 deletions core/src/main/kotlin/com/xorker/draw/mafia/MafiaVoteService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.xorker.draw.mafia

import com.xorker.draw.exception.InvalidMafiaGameVotePhaseStatusException
import com.xorker.draw.exception.InvalidRequestValueException
import com.xorker.draw.user.UserId
import com.xorker.draw.websocket.Session
import java.util.concurrent.ConcurrentHashMap
import org.springframework.stereotype.Component

@Component
internal class MafiaVoteService(
private val mafiaGameRepository: MafiaGameRepository,
private val mafiaGameMessenger: MafiaGameMessenger,
) : MafiaVoteUseCase {

override fun voteMafia(session: Session, targetUserId: UserId) {
val roomId = session.roomId

val voter = session.user
val voterUserId = voter.id

val gameInfo = mafiaGameRepository.getGameInfo(roomId) ?: throw InvalidMafiaGameVotePhaseStatusException

val phase = gameInfo.phase as? MafiaPhase.Vote ?: throw InvalidMafiaGameVotePhaseStatusException

vote(phase.players, voterUserId, targetUserId)

mafiaGameMessenger.broadcastVoteStatus(gameInfo)
}

@Synchronized
private fun vote(
players: ConcurrentHashMap<UserId, MutableSet<UserId>>,
voterUserId: UserId,
targetUserId: UserId,
) {
players.forEach { player ->
val userIds = player.value

if (voterUserId in userIds) {
userIds.remove(voterUserId)
}
}
players[targetUserId]?.add(voterUserId) ?: InvalidRequestValueException
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.xorker.draw.mafia

import com.xorker.draw.user.UserId
import com.xorker.draw.websocket.Session

interface MafiaVoteUseCase {
fun voteMafia(session: Session, targetUserId: UserId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ data object UnSupportedException : CriticalException("crt003", "정의하지 않
data object InvalidMafiaGamePlayingPhaseStatusException : CriticalException("crt004", "마피아 게임 Playing 단계에서 유효하지 않은 상태") { private fun readResolve(): Any = InvalidMafiaGamePlayingPhaseStatusException }
data object InvalidBroadcastException : CriticalException("crt005", "유효하지 않은 브로드캐스트 상태") { private fun readResolve(): Any = InvalidBroadcastException }
class InvalidMafiaPhaseException(message: String) : CriticalException("crt004", message) { private fun readResolve(): Any = InvalidMafiaGamePlayingPhaseStatusException }
data object InvalidMafiaGameVotePhaseStatusException : CriticalException("crt006", "마피아 게임 Vote 단계에서 유효하지 않은 상태") { private fun readResolve(): Any = InvalidMafiaGameVotePhaseStatusException }
//endregion
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ interface MafiaGameMessenger {
fun broadcastPlayerTurnList(mafiaGameInfo: MafiaGameInfo)
fun broadcastDraw(roomId: RoomId, data: Map<String, Any>)
fun broadcastNextTurn(gameInfo: MafiaGameInfo)
fun broadcastVoteStatus(mafiaGameInfo: MafiaGameInfo)
}
5 changes: 4 additions & 1 deletion domain/src/main/kotlin/com/xorker/draw/mafia/MafiaPhase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.xorker.draw.exception.InvalidMafiaPhaseException
import com.xorker.draw.mafia.event.JobWithStartTime
import com.xorker.draw.mafia.turn.TurnInfo
import com.xorker.draw.user.UserId
import java.util.concurrent.ConcurrentHashMap
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

Expand Down Expand Up @@ -37,7 +38,9 @@ sealed class MafiaPhase {
var timerJob: JobWithStartTime,
) : MafiaPhase(), MafiaPhaseWithTurnList, TurnInfo by turnInfo

class Vote() : MafiaPhase()
class Vote(
val players: ConcurrentHashMap<UserId, MutableSet<UserId>>,
) : MafiaPhase()

class InferAnswer() : MafiaPhase()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ enum class ResponseAction(
PLAYER_TURN_LIST("플레이어 턴 순서"),
DRAW("그림 데이터"),
TURN_INFO("새로운 턴 시작"),
VOTE_STATUS("마피아 투표 현황"),

PHASE_WAIT("Wait Phase 시작/초기화"),
PHASE_READY("Ready Phase 시작/초기화"),
Expand Down

0 comments on commit e0b0065

Please sign in to comment.