Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 결과 조회 기능 구현 #46

Merged
merged 2 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum ExceptionCode {
INVALID_CONTENT(106, "내용이 누락 되었습니다."),
NOT_ALIVE_PLAYER(107, "이미 사망한 사람입니다."),
INVALID_PLAYER(108, "존재 하지 않는 사람입니다."),
GAME_IS_NOT_FINISHED(108, "현재 게임이 진행 중입니다."),

NOT_PARTICIPATING_GAME(200, "게임에 참가해 주십시오."),
INVALID_JOB(201, "마피아만 지목 대상을 볼 수 있습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import mafia.mafiatogether.service.dto.RoomCreateRequest;
import mafia.mafiatogether.service.dto.RoomInfoResponse;
import mafia.mafiatogether.service.dto.RoomModifyRequest;
import mafia.mafiatogether.service.dto.RoomResultResponse;
import mafia.mafiatogether.service.dto.RoomStatusResponse;
import mafia.mafiatogether.service.dto.RoomValidateResponse;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -79,4 +80,11 @@ public ResponseEntity<RoomInfoResponse> findRoomInfo(
) {
return ResponseEntity.ok(roomService.findRoomInfo(playerInfoDto.code(), playerInfoDto.name()));
}

@GetMapping("/result")
public ResponseEntity<RoomResultResponse> findResult(
@PlayerInfo final PlayerInfoDto playerInfoDto
) {
return ResponseEntity.ok(roomService.findResult(playerInfoDto.code()));
}
}
18 changes: 15 additions & 3 deletions src/main/java/mafia/mafiatogether/domain/Room.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public StatusType getStatusType(final Long now) {
return status.getType();
}

// statusType 제거
public void modifyStatus(final StatusType statusType, final Long now) {
this.status = status.getNextStatus(this, now);
}
Expand Down Expand Up @@ -114,11 +115,22 @@ public Long getPlayerCount() {
}

public boolean isEnd() {
final long playerCount = getPlayerCount();
final long mafia = players.values().stream()
long aliveMafia = getAliveMafia();
return getAliveCitizen() / 2 < aliveMafia || aliveMafia == 0;
}

public long getAliveMafia(){
return players.values().stream()
.filter(player -> player.getJobType().equals(JobType.MAFIA))
.filter(player -> player.isAlive() == true)
.count();
}

public long getAliveCitizen(){
return players.values().stream()
.filter(player -> !player.getJobType().equals(JobType.MAFIA))
.filter(player -> player.isAlive() == true)
.count();
return playerCount / 2 < mafia || mafia == 0;
}

public void executeVote() {
Expand Down
52 changes: 49 additions & 3 deletions src/main/java/mafia/mafiatogether/domain/status/EndStatus.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
package mafia.mafiatogether.domain.status;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import mafia.mafiatogether.domain.Player;
import mafia.mafiatogether.domain.Room;
import mafia.mafiatogether.domain.job.JobType;

public class EndStatus extends Status {

private final List<Player> players;

public static final Long ONE_MINUTE = 60_000L;

private EndStatus(final Long start, final Long end) {
private EndStatus(final List<Player> players, final Long start, final Long end) {
super(start, end);
this.players = players;
}

public static EndStatus create(final List<Player> players, final Long now) {
return new EndStatus(players, now, now + ONE_MINUTE);
}

public JobType getWinnerJob() {
if(getAliveMafia()==0){
return JobType.CITIZEN;
}
return JobType.MAFIA;
}

private Map<Boolean, List<Player>> partitionPlayersByRole() {
return players
.stream()
.collect(Collectors.partitioningBy(Player::isMafia));
}

public List<Player> getWinner() {
Map<Boolean, List<Player>> players = partitionPlayersByRole();

if (getAliveMafia() == 0) {
return players.get(Boolean.FALSE);
}
return players.get(Boolean.TRUE);
}

public List<Player> getLoser() {
Map<Boolean, List<Player>> players = partitionPlayersByRole();

if (getAliveMafia() == 0) {
return players.get(Boolean.TRUE);
}
return players.get(Boolean.FALSE);
Comment on lines +21 to +53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

room에서 이 역할들을 해주면 room의 역할이 너무 커지니까 status내부로 옮긴건가? room 역할 줄인건 좋은데 다운캐스팅을 하면 추상화한게 좀 아쉬워지는 느낌이라 지양하고 싶긴한데

}

public static EndStatus create(final Long now) {
return new EndStatus(now, now + ONE_MINUTE);
private long getAliveMafia(){
return players.stream()
.filter(player -> player.getJobType().equals(JobType.MAFIA))
.filter(player -> player.isAlive() == true)
.count();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package mafia.mafiatogether.domain.status;

import java.util.List;
import mafia.mafiatogether.domain.Player;
import mafia.mafiatogether.domain.Room;

public class NightStatus extends Status {
Expand All @@ -17,8 +19,12 @@ public static NightStatus create(final Long now) {
@Override
public Status getNextStatus(final Room room, final Long now) {
room.executeJobTarget();
final List<Player> players = room.getPlayers()
.values()
.stream()
.toList();
if (room.isEnd()) {
return EndStatus.create(now);
return EndStatus.create(players, now);
}
return DayIntroStatus.create(now);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package mafia.mafiatogether.domain.status;

import java.util.List;
import mafia.mafiatogether.domain.Player;
import mafia.mafiatogether.domain.Room;

public class VoteResultStatus extends Status {
Expand All @@ -17,7 +19,11 @@ protected static VoteResultStatus create(final Long now) {
@Override
public Status getNextStatus(final Room room, final Long now) {
if (room.isEnd()) {
return EndStatus.create(now);
final List<Player> players = room.getPlayers()
.values()
.stream()
.toList();
return EndStatus.create(players, now);
}
return NightIntroStatus.create(now);
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/mafia/mafiatogether/service/RoomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import java.time.Clock;
import lombok.RequiredArgsConstructor;
import mafia.mafiatogether.config.exception.ExceptionCode;
import mafia.mafiatogether.config.exception.RoomException;
import mafia.mafiatogether.domain.Player;
import mafia.mafiatogether.domain.Room;
import mafia.mafiatogether.domain.RoomManager;
import mafia.mafiatogether.domain.status.EndStatus;
import mafia.mafiatogether.service.dto.RoomCodeResponse;
import mafia.mafiatogether.service.dto.RoomCreateRequest;
import mafia.mafiatogether.service.dto.RoomInfoResponse;
import mafia.mafiatogether.service.dto.RoomModifyRequest;
import mafia.mafiatogether.service.dto.RoomResultResponse;
import mafia.mafiatogether.service.dto.RoomStatusResponse;
import mafia.mafiatogether.service.dto.RoomValidateResponse;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -50,4 +54,12 @@ public RoomInfoResponse findRoomInfo(final String code, final String name) {
public RoomValidateResponse validateCode(final String code) {
return new RoomValidateResponse(roomManager.validateCode(code));
}

public RoomResultResponse findResult(final String code) {
final Room room = roomManager.findByCode(code);
if(!room.isEnd()){
throw new RoomException(ExceptionCode.GAME_IS_NOT_FINISHED);
}
return RoomResultResponse.of((EndStatus) room.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다운캐스팅 조금 아쉽긴한데 그렇지 않으면 내부의 함수를 room으로 빼야해서 또 room의 역할이 너무 커지네;;;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package mafia.mafiatogether.service.dto;

import mafia.mafiatogether.domain.Player;

public record RoomResultPlayerDto(
String name,
Boolean isAlive,
String job
) {
public static RoomResultPlayerDto of(
final Player player
) {
return new RoomResultPlayerDto(
player.getName(),
player.isAlive(),
player.getJobType().name()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package mafia.mafiatogether.service.dto;

import java.sql.Timestamp;
import java.util.List;
import mafia.mafiatogether.domain.status.EndStatus;

public record RoomResultResponse(
String winnerJob,
Timestamp endTime,
List<RoomResultPlayerDto> winner,
List<RoomResultPlayerDto> loser
) {
public static RoomResultResponse of(
final EndStatus endStatus
) {
final List<RoomResultPlayerDto> winner = endStatus.getWinner()
.stream()
.map(RoomResultPlayerDto::of)
.toList();

final List<RoomResultPlayerDto> loser = endStatus.getLoser()
.stream()
.map(RoomResultPlayerDto::of)
.toList();

return new RoomResultResponse(
endStatus.getWinnerJob().name(),
endStatus.getEndTime(),
winner,
loser
);
}
}
55 changes: 55 additions & 0 deletions src/test/java/mafia/mafiatogether/domain/status/EndStatusTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package mafia.mafiatogether.domain.status;

import java.time.Clock;
import java.util.List;
import mafia.mafiatogether.domain.Player;
import mafia.mafiatogether.domain.job.JobType;
import mafia.mafiatogether.domain.job.Mafia;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

class EndStatusTest {

@Test
void 시민_승리_결과_반환() {
Mafia mafia = new Mafia();
Player A = Player.create("A");
A.modifyJob(mafia);
A.kill();
Player B = Player.create("B");
B.modifyJob(mafia);
B.kill();
Player C = Player.create("C");
Player D = Player.create("D");
Player E = Player.create("E");

List<Player> players = List.of(A, B, C, D, E);

EndStatus endStatus = EndStatus.create(players, Clock.systemUTC().millis());

Assertions.assertThat(endStatus.getWinnerJob()).isEqualTo(JobType.CITIZEN);
Assertions.assertThat(endStatus.getWinner()).containsAll(List.of(C, D, E));
Assertions.assertThat(endStatus.getLoser()).containsAll(List.of(A, B));
}

@Test
void 마피아_승리_결과_반환() {
Mafia mafia = new Mafia();
Player A = Player.create("A");
A.modifyJob(mafia);
Player B = Player.create("B");
B.modifyJob(mafia);
Player C = Player.create("C");
C.kill();
Player D = Player.create("D");
Player E = Player.create("E");

List<Player> players = List.of(A, B, C, D, E);

EndStatus endStatus = EndStatus.create(players, Clock.systemUTC().millis());

Assertions.assertThat(endStatus.getWinnerJob()).isEqualTo(JobType.MAFIA);
Assertions.assertThat(endStatus.getLoser()).containsAll(List.of(C, D, E));
Assertions.assertThat(endStatus.getWinner()).containsAll(List.of(A, B));
}
}
Loading