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

[REFACTOR] 코드 조회 및 저장 API 수정 #461

Merged
merged 4 commits into from
Oct 17, 2023
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 @@ -25,8 +25,6 @@ public class TestDuringController {

private final SolvedCheckService solvedCheckService;

private final TempCodeService tempCodeService;

@PostMapping("/output")
@Operation(summary = "코드 실행 결과값 반환", description = "사용자가 특정 코드를 실행할 경우 결과값을 제공합니다.")
public ResponseEntity<OutputDto> getOutputResult
Expand All @@ -45,24 +43,4 @@ public class TestDuringController {
(@RequestBody TestCheckDto testCheckDto) {
return new ResponseEntity<>(solvedCheckService.isSolvedCheck(testCheckDto), HttpStatus.OK);
}

@PostMapping("/code")
@Operation(summary = "테스트 중인 코드를 저장합니다", description = "테스트 중인 코드를 저장\n" +
"testId와 attemptProblemId를 통해 테스트 중인 코드를 지속적으로 저장함\n")
public void saveTempCode(@RequestBody TempCodeDto tempCodeDto) {
tempCodeService.saveTempCode(tempCodeDto);
}

@GetMapping("/code")
@Operation(summary = "저장된 코드를 확인합니다", description = "테스트 중일 때, 문제 번호를 바꿀 때 코드 정보를\n" +
"testId와 attemptProblemId를 이용하여 가져온다. \n")
public ResponseEntity<TempCode> getTempCode(@RequestParam String testId,
@RequestParam String problemNumber,
@RequestParam String language) {

String key = String.format("testId:%s:problemNumber:%s:language:%s", testId, problemNumber, language);

return new ResponseEntity<>(tempCodeService.getTempCode(key), HttpStatus.OK);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
@AllArgsConstructor
@Builder
public class InputData {
private Long testId;
private Long problemNumber;
private String language;
private String code;
private String input;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.*;

import java.time.LocalDateTime;

@NoArgsConstructor
@Builder
@AllArgsConstructor
@Getter
@Setter
public class TempCode {

public void setCode(String code) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
@AllArgsConstructor
@Builder
public class TestInputData {
private Long testId;
private Long problemNumber;
private String language;
private String code;
private List<String> input;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
@Slf4j
public class RunCodeService {

private final TempCodeService tempCodeService;

@Value("${compile.url}")
public String url;

Expand All @@ -30,6 +32,9 @@ public class RunCodeService {

public OutputDto runCode(InputData inputData) throws Exception {

tempCodeService.saveTempCode(inputData.getTestId(), inputData.getProblemNumber(),
inputData.getLanguage(), inputData.getCode());

CloseableHttpClient httpClient = HttpClients.createDefault();

ObjectMapper objectMapper = new ObjectMapper();
Expand All @@ -55,6 +60,9 @@ public OutputDto runCode(InputData inputData) throws Exception {
}
public List<OutputDto> runTestCaseCode(TestInputData testInputData) throws Exception {

tempCodeService.saveTempCode(testInputData.getTestId(),
testInputData.getProblemNumber(), testInputData.getLanguage(), testInputData.getCode());

CloseableHttpClient httpClient = HttpClients.createDefault();

ObjectMapper objectMapper = new ObjectMapper();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import swm_nm.morandi.domain.testDuring.dto.InputData;
import swm_nm.morandi.domain.testDuring.dto.TempCode;
import swm_nm.morandi.domain.testDuring.dto.TempCodeDto;
import swm_nm.morandi.domain.testRecord.repository.AttemptProblemRepository;
Expand All @@ -22,15 +23,15 @@ public class TempCodeService {

private final RedisTemplate<String, Object> redisTemplate;

public void saveTempCode(TempCodeDto tempCodeDto) {
String key = generateKey(tempCodeDto);
public void saveTempCode(Long testId, Long problemNumber, String language, String code) {
String key = generateKey(testId, problemNumber, language);
Long remainingTTL = redisTemplate.getExpire(key);

if (remainingTTL != null && remainingTTL > 0) {
TempCode tempCode = Optional.ofNullable((TempCode) redisTemplate.opsForValue().get(key))
.orElseThrow(() -> new MorandiException(TestErrorCode.KEY_NOT_FOUND));

tempCode.setCode(tempCodeDto.getCode());
tempCode.setCode(code);

// 테스트 시작 시간으로부터 남은 시간을 계산한다
Duration duration = Duration.between(LocalDateTime.now(), tempCode.endTime);
Expand All @@ -45,9 +46,9 @@ public void saveTempCode(TempCodeDto tempCodeDto) {
throw new MorandiException(TestErrorCode.TTL_EXPIRED);
}
}
public String generateKey(TempCodeDto tempCodeDto) {
public String generateKey(Long testId, Long problemNumber, String language) {
return String.format("testId:%s:problemNumber:%s:language:%s",
tempCodeDto.getTestId(), tempCodeDto.getProblemNumber(), tempCodeDto.getLanguage());
testId, problemNumber, language);
}

public TempCode getTempCode(String key) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.springframework.web.bind.annotation.RestController;
import swm_nm.morandi.domain.testDuring.dto.TestCheckDto;
import swm_nm.morandi.domain.testExit.dto.AttemptCodeDto;
import swm_nm.morandi.domain.testExit.dto.AttemptProblemDto;
import swm_nm.morandi.domain.testExit.dto.TestResultDto;
import swm_nm.morandi.domain.testExit.service.SaveCodeService;
import swm_nm.morandi.domain.testExit.service.TestExitService;
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/swm_nm/morandi/domain/testStart/dto/TestCodeDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package swm_nm.morandi.domain.testStart.dto;

import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TestCodeDto {
private Long problemNumber;
private String pythonCode;
private String cppCode;
private String javaCode;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
public class TestStartResponseDto {
private Long testId;
private List<Long> bojProblemIds = new ArrayList<>();
private List<TestCodeDto> testCodeDtos = new ArrayList<>();
private Long remainingTime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import org.springframework.stereotype.Service;
import swm_nm.morandi.domain.problem.dto.BojProblem;
import swm_nm.morandi.domain.problem.entity.Problem;
import swm_nm.morandi.domain.testDuring.dto.TempCode;
import swm_nm.morandi.domain.testDuring.service.TempCodeService;
import swm_nm.morandi.domain.testInfo.entity.TestType;
import swm_nm.morandi.domain.testInfo.repository.TestTypeRepository;
import swm_nm.morandi.domain.testStart.dto.TestCodeDto;
import swm_nm.morandi.domain.testStart.dto.TestStartResponseDto;
import swm_nm.morandi.domain.testInfo.entity.AttemptProblem;
import swm_nm.morandi.domain.testInfo.entity.Tests;
Expand All @@ -22,6 +25,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

import static java.lang.Math.max;

Expand All @@ -35,6 +40,7 @@ public class TestStartUseCase {
private final SaveProblemsService saveProblemsService;
private final TempCodeInitializer tempCodeInitializer;
private final MemberInfoService memberInfoService;
private final TempCodeService tempCodeService;
private final TestTypeRepository testTypeRepository;
private final TestProgressCheckService testProgressCheckService;

Expand All @@ -53,7 +59,7 @@ public TestStartResponseDto getTestStartsData(Long testTypeId) {
// 이미 테스트 중인지 확인
Tests test = testProgressCheckService.isTestinProgress(member);
if (test != null) {
return getTestStartResponseDto(member.getCurrentTestId(), test);
return getTestStartResponseDto(test);
}
TestType testType = testTypeRepository.findById(testTypeId)
.orElseThrow(() -> new MorandiException(TestTypeErrorCode.TEST_TYPE_NOT_FOUND));
Expand All @@ -78,28 +84,53 @@ public TestStartResponseDto getTestStartsData(Long testTypeId) {
return getTestStartResponseDto(test, bojProblems);
}

private static TestStartResponseDto getTestStartResponseDto(Tests test, List<BojProblem> bojProblems) {
List<Long> bojProblemIds = new ArrayList<>();
for (BojProblem bojProblem : bojProblems) {
bojProblemIds.add(bojProblem.getProblemId());
}

private TestStartResponseDto getTestStartResponseDto(Tests test, List<BojProblem> bojProblems) {
List<Long> bojProblemIds = bojProblems.stream().map(BojProblem::getProblemId).collect(Collectors.toList());
List<TestCodeDto> testCodeDtos = getTestCodeDtos(test);
return TestStartResponseDto.builder()
.testId(test.getTestId())
.bojProblemIds(bojProblemIds)
.remainingTime(test.getRemainingTime())
.testCodeDtos(testCodeDtos)
.build();
}

private TestStartResponseDto getTestStartResponseDto(Long currentTestId, Tests test) {
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(currentTestId);
private List<TestCodeDto> getTestCodeDtos(Tests test) {
Long testId = test.getTestId();
List<String> languages = List.of("Python", "Cpp", "Java");
List<TestCodeDto> testCodeDtos = new ArrayList<>();
LongStream.rangeClosed(1, test.getProblemCount()).forEach(problemNumber -> {
String pythonCode = "", cppCode = "", javaCode = "";
for (String language : languages) {
String key = String.format("testId:%s:problemNumber:%s:language:%s", testId, problemNumber, language);
String code = tempCodeService.getTempCode(key).getCode();
if (language.equals("Python")) pythonCode = code;
else if (language.equals("Cpp")) cppCode = code;
else if (language.equals("Java")) javaCode = code;
}
TestCodeDto testCodeDto = TestCodeDto.builder()
.problemNumber(problemNumber)
.pythonCode(pythonCode)
.cppCode(cppCode)
.javaCode(javaCode)
.build();
testCodeDtos.add(testCodeDto);
});
return testCodeDtos;
}

private TestStartResponseDto getTestStartResponseDto(Tests test) {
Long testId = test.getTestId();
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(testId);
List<Long> bojProblemIds = attemptProblems.stream().map(AttemptProblem::getProblem)
.map(Problem::getBojProblemId).collect(Collectors.toList());
List<TestCodeDto> testCodeDtos = getTestCodeDtos(test);
TestStartResponseDto testStartResponseDto
= TestStartResponseDto.builder()
.testId(currentTestId)
.testId(testId)
.bojProblemIds(bojProblemIds)
.remainingTime(test.getRemainingTime())
.testCodeDtos(testCodeDtos)
.build();

// 테스트 시작에 대한 ResponseDto 반환
Expand Down
Loading