Skip to content

Commit

Permalink
Core server: PR#66, PR#68
Browse files Browse the repository at this point in the history
  • Loading branch information
Berygna committed Jun 22, 2024
1 parent a045f98 commit 7ca2cdd
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 107 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package gooroommoon.algofi_core.algorithmproblem;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.Optional;
import java.util.List;

public interface AlgorithmproblemRepository extends JpaRepository<Algorithmproblem, Long> {

/**
*랜덤으로 문제 가져오는 쿼리
*/
@Query("select a from Algorithmproblem a where a.level like :level order by rand() limit 1")
Optional<Algorithmproblem> getRandomAlgorithmproblem(@Param("level")String level);
List<Algorithmproblem> findAllByLevel(String level);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package gooroommoon.algofi_core.algorithmproblem;

import gooroommoon.algofi_core.algorithmproblem.dto.AlgorithmproblemResponse;
import gooroommoon.algofi_core.algorithmproblem.exception.AlgorithmproblemNotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Random;

@Slf4j
@Service
@RequiredArgsConstructor
Expand All @@ -16,18 +18,34 @@ public class AlgorithmproblemService {
/**
* 랜덤으로 가져오는 서비스 작성 -> repository에서 해결
*/
public AlgorithmproblemResponse getRandom(String level) {
Algorithmproblem randomAlgorithmproblem = algorithmproblemRepository.getRandomAlgorithmproblem(level)
.orElseThrow(() -> new AlgorithmproblemNotFoundException("문제를 찾을 수 없습니다."));
public Algorithmproblem getRandom(String level) {
List<Algorithmproblem> findAllProblems = algorithmproblemRepository.findAllByLevel(level);

//random으로 값을
Random random = new Random();
int size = findAllProblems.size();

return fromAlgorithmproblem(randomAlgorithmproblem);
return findAllProblems.get(random.nextInt(size));
}

private AlgorithmproblemResponse fromAlgorithmproblem(Algorithmproblem Algorithmproblem) {
public AlgorithmproblemResponse toResponse(Algorithmproblem algorithmproblem) {
return AlgorithmproblemResponse.builder()
.title(Algorithmproblem.getTitle())
.content(Algorithmproblem.getContent())
.level(Algorithmproblem.getLevel())
.title(algorithmproblem.getTitle())
.content(algorithmproblem.getContent())
.level(algorithmproblem.getLevel())
.build();
}

// private List<AlgorithmproblemResponse> fromAlgorithmproblems(List<Algorithmproblem> Algorithmproblems) {
// List<AlgorithmproblemResponse> results = new ArrayList<>();
// for (Algorithmproblem algorithmproblem : Algorithmproblems) {
// algorithmproblem.builder()
// .title(algorithmproblem.getTitle())
// .level(algorithmproblem.getLevel())
// .content(algorithmproblem.getContent())
// .build();
// }
//
// return results;
// }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package gooroommoon.algofi_core.game.session;

import gooroommoon.algofi_core.algorithmproblem.dto.AlgorithmproblemResponse;
import gooroommoon.algofi_core.algorithmproblem.Algorithmproblem;
import gooroommoon.algofi_core.game.session.exception.GameIsFullException;
import lombok.Getter;
import lombok.Setter;
Expand Down Expand Up @@ -33,11 +33,13 @@ public class GameSession {
@Setter
private String otherGameCode;

private AlgorithmproblemResponse algorithmProblem;
private Algorithmproblem algorithmProblem;

private boolean isStarted;

private long startTime;
@Setter
private int runningTime;

private final String chatroomId;

Expand Down Expand Up @@ -102,9 +104,9 @@ protected void updateSettings(String title, String problemLevel, Integer timerTi

}

protected void start() {
//TODO 알고리즘 문제 받아오기
protected void start(Algorithmproblem algorithmproblem) {
isStarted = true;
startTime = System.currentTimeMillis();
this.algorithmProblem = algorithmproblem;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package gooroommoon.algofi_core.game.session;


import gooroommoon.algofi_core.algorithmproblem.Algorithmproblem;
import gooroommoon.algofi_core.algorithmproblem.AlgorithmproblemService;
import gooroommoon.algofi_core.algorithmproblem.dto.AlgorithmproblemResponse;
import gooroommoon.algofi_core.algorithmproblem.exception.AlgorithmproblemNotFoundException;
import gooroommoon.algofi_core.auth.member.MemberService;
import gooroommoon.algofi_core.chat.dto.MessageDTO;
import gooroommoon.algofi_core.chat.entity.Chatroom;
Expand All @@ -15,23 +12,19 @@
import gooroommoon.algofi_core.game.session.exception.*;
import gooroommoon.algofi_core.gameresult.GameresultService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import java.util.Map;
import java.util.Set;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;

@Service
@RequiredArgsConstructor
@Slf4j
public class GameSessionService {

//유저가 채팅방에 새로 들어올 때 입장 메시지 보내는 메서드 호출하기
Expand Down Expand Up @@ -141,42 +134,20 @@ public void startGame(String hostId) {
if(!session.getHostId().equals(hostId)) {
throw new NotAHostException("방장만 게임을 시작할 수 있습니다.");
}
String problemLevel = session.getProblemLevel();
//TODO 문제 가져와서 넣기
//랜덤 알고리즘문제
try {
int attempts = 0;
int maxAttempts = 5; // 최대 재시도 횟수 설정
boolean success = false;

while (attempts < maxAttempts && !success) {
try {
AlgorithmproblemResponse randomProblem = algorithmproblemService.getRandom(problemLevel);
log.info("randomProblem.title = {}", randomProblem.getTitle());
log.info("randomProblem.level = {}", randomProblem.getLevel());
success = true; // 성공적으로 문제를 찾음
} catch (AlgorithmproblemNotFoundException e) {
attempts++;
log.warn("문제를 찾을 수 없습니다. 재시도 중... ({}/{})", attempts, maxAttempts);
}
}

if (!success) {
log.error("문제를 찾을 수 없습니다. 재시도 횟수 초과");
// 클라이언트에게 실패 응답을 보냄 (선택사항)
throw new AlgorithmproblemNotFoundException("문제를 찾을 수 없습니다. 재시도 횟수 초과");
}
} catch (Exception e) {
log.error("예상치 못한 오류 발생", e);
// 클라이언트에게 오류 응답을 보냄 (선택사항)
}
session.start(algorithmproblemService.getRandom(session.getProblemLevel()));
GameSessionStartResponse startResponse = new GameSessionStartResponse(session.getTimerTime(),
algorithmproblemService.toResponse(session.getAlgorithmProblem()));
session.getPlayersStream().forEach(id -> {
messagingTemplate.convertAndSendToUser(id, "/queue/game/start", startResponse);
});

session.start();
//TODO 알고리즘 문제 가져와서 메시지 발행
sendSessions();

//타이머 태스크 등록
GameSessionService gameSessionService = this;
ScheduledFuture<?> timeOverTask = executorService.schedule(() ->
gameSessionService.closeGame(session,null, session.getTimerTime())
gameSessionService.closeGame(session,null)
, session.getTimerTime(), TimeUnit.SECONDS);
session.setTimeOverTask(timeOverTask);
}
Expand All @@ -186,10 +157,9 @@ public void submitCode(String playerId, GameCodeRequest request) {
if(!session.isStarted()) {
throw new GameIsNotStartedException("게임이 아직 시작되지 않았습니다.");
}
//TODO 실제 알고리즘 ID로 변경

sendChat(session.getChatroomId(), playerId, "코드를 제출했습니다!");
SubmitCodeRequest submitRequest = new SubmitCodeRequest(1L, request.getLanguage(), request.getCode());
SubmitCodeRequest submitRequest = new SubmitCodeRequest(session.getAlgorithmProblem().getAlgorithmproblemId(), request.getLanguage(), request.getCode());
webClient.post()
.uri("/api/judge-problem")
.body(submitRequest, SubmitCodeRequest.class)
Expand All @@ -199,14 +169,16 @@ public void submitCode(String playerId, GameCodeRequest request) {
String message = response.getBody().getMessage();
messagingTemplate.convertAndSendToUser(playerId, "/queue/game/result", message);
if(message.equals("맞았습니다.")) {
closeGame(session, playerId, (int)(System.currentTimeMillis() - session.getStartTime()));
closeGame(session, playerId);
} else {
sendChat(session.getChatroomId(), playerId, "틀렸습니다!");
}
});
}

public void closeGame(GameSession session, String winnerId, int runningTime) {
public void closeGame(GameSession session, String winnerId) {
int runningTime = (int) (System.currentTimeMillis() - session.getStartTime());
session.setRunningTime(runningTime);
if(winnerId != null) {
GameSessionOverResponse winnerResponse = new GameSessionOverResponse(GameOverType.WIN, runningTime);
GameSessionOverResponse loserResponse = new GameSessionOverResponse(GameOverType.LOSE, runningTime);
Expand Down Expand Up @@ -244,16 +216,14 @@ public void savePlayerCode(String playerId, GameCodeRequest request) {
}

private void saveResult(GameSession session) {
//TODO 게임 결과 저장
//TODO hostCode, guestCode,
String chatroomId = session.getChatroomId();
Set<String> players = session.getPlayers();
String hostCode = "hostCode";
String guestCode = "guestCode";
Algorithmproblem algorithmproblem = new Algorithmproblem();
gameresultService.save(chatroomId,players,hostCode,guestCode,algorithmproblem,runningTime);
gameresultService.save(session.getChatroomId(),
session.getPlayers(),
session.getHostGameCode(),
session.getOtherGameCode(),
session.getAlgorithmProblem(),
session.getRunningTime());

removeSession(session);
//TODO 게임 세션 삭제
}

public void removeSession(GameSession session) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package gooroommoon.algofi_core.game.session.dto;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import gooroommoon.algofi_core.algorithmproblem.dto.AlgorithmproblemResponse;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class GameSessionStartResponse {
private int timerTime;
private AlgorithmproblemResponse algorithmProblem;
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ public class CreateRandomProblemControllerTest {
public void setup() {
stompClient = new WebSocketStompClient(new StandardWebSocketClient());
stompClient.setMessageConverter(new MappingJackson2MessageConverter());

for (int i = 1; i <= 5; i++) {
Algorithmproblem algorithmproblem = Algorithmproblem.builder()
.title("title" + i)
.level("3")
.content("content" + i)
.recommend_time(30 + i)
.build();
algorithmproblemRepository.save(algorithmproblem);
}

Algorithmproblem algorithmproblem = Algorithmproblem.builder()
.title("title" + 6)
.level("1")
.content("content" + 6)
.recommend_time(30 + 6)
.build();

algorithmproblemRepository.save(algorithmproblem);
}

@AfterEach
Expand All @@ -80,31 +99,13 @@ void afterEach() {

@Test
@DisplayName("레벨에 맞는 문제 random select 테스트")
void createRandomProblem() {
//given
for (int i = 1; i <= 5; i++) {
Algorithmproblem algorithmproblem = Algorithmproblem.builder()
.title("title" + i)
.level("3")
.content("content" + i)
.recommend_time(30 + i)
.build();

algorithmproblemRepository.save(algorithmproblem);
}

Algorithmproblem algorithmproblem = Algorithmproblem.builder()
.title("title" + 6)
.level("1")
.content("content" + 6)
.recommend_time(30 + 6)
.build();

void createRandomProblem() throws InterruptedException {
//when
AlgorithmproblemResponse randomProblem = algorithmproblemService.getRandom("3");

//then
for (int i = 0; i < 100; i++) {
for (int i = 0; i < 50; i++) {
Algorithmproblem randomProblem = algorithmproblemService.getRandom("3");
Thread.sleep(1000);
Assertions.assertNotEquals(randomProblem.getTitle(), "title6");
}
}
Expand All @@ -124,8 +125,6 @@ void SuccessSendProblem() throws ExecutionException, InterruptedException, Timeo
connectHeaders.add("Authorization", "Bearer " + token);
connectHeaders.add("userName", "user");

// StompHeaders connectStompHeaders =

//여기는 "user의 세션"
//여기서 인증정보를 넘겨줘야하나?
StompSession stompSession = stompClient.connect(websocketUri, connectHeaders, new StompSessionHandlerAdapter() {
Expand Down Expand Up @@ -198,37 +197,29 @@ public void handleFrame(StompHeaders headers, Object payload) {
//TODO 게임 참가
stompSessionMember.send(sendJoinHeaders, gameSessionJoinRequest);

for (int i = 1; i <= 5; i++) {
Algorithmproblem algorithmproblem = Algorithmproblem.builder()
.title("title" + i)
.level("3")
.content("content" + i)
.recommend_time(30 + i)
.build();
algorithmproblemRepository.save(algorithmproblem);
}

//TODO 게임 준비
StompHeaders sendReadyHeaders = new StompHeaders();
sendReadyHeaders.setDestination("/app/game/ready");
sendReadyHeaders.add("Authorization", "Bearer " + memberToken);
sendReadyHeaders.setLogin("user");

//TODO 게임 준비 User
stompSession.send(sendReadyHeaders, null);

StompHeaders sendReadyHeaders2 = new StompHeaders();
sendReadyHeaders2.setDestination("/app/game/ready");
sendReadyHeaders2.add("Authorization", "Bearer " + token);
sendReadyHeaders.setLogin("member");

//TODO 게임 준비 Member
stompSessionMember.send(sendReadyHeaders2, null);

StompHeaders sendHeaders = new StompHeaders();
sendHeaders.setDestination("/app/game/start");
sendHeaders.add("Authorization", "Bearer " + token);
sendHeaders.setLogin("user");

//TODO 게임 시작
//TODO 게임 시작 User
stompSession.send(sendHeaders,null);

}
Expand Down

0 comments on commit 7ca2cdd

Please sign in to comment.