From 2cbbbc6d616c850f5cb81d1664d75ecb1daf646d Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 5 Jan 2024 13:24:07 +0900 Subject: [PATCH 01/46] =?UTF-8?q?feat:=20compiler=20dto=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/compiler/dto/ProblemInfoDto.java | 20 +++++++++++++++++++ .../compiler/dto/ProblemResponseDto.java | 17 ++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java new file mode 100644 index 0000000..918e1d2 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java @@ -0,0 +1,20 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProblemInfoDto { + + private int problemId; + private String titleKo; + private int level; + +} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java new file mode 100644 index 0000000..df39ced --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java @@ -0,0 +1,17 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class ProblemResponseDto { + + private int problemId; + private String titleKo; + private int level; +} From 98608f319701e5cd7f8b11028f163caba67cb14d Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 5 Jan 2024 13:26:24 +0900 Subject: [PATCH 02/46] =?UTF-8?q?feat:=20CompilerService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/service/CompilerService.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java new file mode 100644 index 0000000..2d8ac3d --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -0,0 +1,32 @@ +package com.api.TaveShot.domain.compiler.service; + +import com.api.TaveShot.domain.compiler.converter.CompilerConverter; +import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; +import com.api.TaveShot.domain.compiler.dto.ProblemResponseDto; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Service +public class CompilerService { + + private final WebClient webClient; + + public CompilerService(WebClient.Builder webClientBuilder) { + this.webClient = webClientBuilder.baseUrl("https://solved.ac/api/v3").build(); + } + + public ProblemInfoDto getProblemInfo(int problemId) { + Mono problemResponseMono = webClient.get() + .uri(uriBuilder -> uriBuilder.path("/problem/show") + .queryParam("problemId",problemId) + .build()) + .retrieve() + .bodyToMono(ProblemResponseDto.class); + + ProblemResponseDto problemResponse = problemResponseMono.block(); + assert problemResponse != null; + return CompilerConverter.responseToInfoDto(problemResponse); + } + +} \ No newline at end of file From df05c1e2fcb6ba1771b3100b62081e020df33ced Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 5 Jan 2024 13:26:41 +0900 Subject: [PATCH 03/46] =?UTF-8?q?feat:=20CompilerConverter=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/converter/CompilerConverter.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java new file mode 100644 index 0000000..278486b --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java @@ -0,0 +1,16 @@ +package com.api.TaveShot.domain.compiler.converter; + +import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; +import com.api.TaveShot.domain.compiler.dto.ProblemResponseDto; + +public class CompilerConverter { + + public static ProblemInfoDto responseToInfoDto(final ProblemResponseDto response){ + return new ProblemInfoDto( + response.getProblemId(), + response.getTitleKo(), + response.getLevel() + ); + } + +} From d8cd075293b2b4556c6cd187598df906cceda7e5 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 5 Jan 2024 13:26:52 +0900 Subject: [PATCH 04/46] =?UTF-8?q?feat:=20CompilerController=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java new file mode 100644 index 0000000..3cb8d82 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -0,0 +1,26 @@ +package com.api.TaveShot.domain.compiler.controller; + +import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; +import com.api.TaveShot.domain.compiler.service.CompilerService; +import com.api.TaveShot.global.success.SuccessResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/api/compile") +public class CompilerController { + + private final CompilerService compilerService; + @GetMapping + public SuccessResponse getProblemInfo(@RequestParam int problemId) { + ProblemInfoDto problemInfo = compilerService.getProblemInfo(problemId); + return new SuccessResponse<>(problemInfo); + } +} \ No newline at end of file From 7ed33f21a27d1e0cc2223c5ee9f82fe7507b512b Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 5 Jan 2024 13:34:02 +0900 Subject: [PATCH 05/46] =?UTF-8?q?feat:=20=EB=AC=B8=EC=A0=9C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EC=97=90=20Tag=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/converter/CompilerConverter.java | 5 +++-- .../domain/compiler/dto/ProblemInfoDto.java | 3 ++- .../domain/compiler/dto/ProblemResponseDto.java | 4 +++- .../api/TaveShot/domain/compiler/dto/TagDto.java | 16 ++++++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java index 278486b..cfc94d7 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java @@ -9,8 +9,9 @@ public static ProblemInfoDto responseToInfoDto(final ProblemResponseDto response return new ProblemInfoDto( response.getProblemId(), response.getTitleKo(), - response.getLevel() + response.getLevel(), + response.getTags() ); } -} +} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java index 918e1d2..b2c135a 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java @@ -16,5 +16,6 @@ public class ProblemInfoDto { private int problemId; private String titleKo; private int level; + private List tags; -} +} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java index df39ced..90d3452 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java @@ -14,4 +14,6 @@ public class ProblemResponseDto { private int problemId; private String titleKo; private int level; -} + private List tags; + +} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java new file mode 100644 index 0000000..3680d30 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java @@ -0,0 +1,16 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class TagDto { + private String key; + private int bojTagId; + private String name; +} \ No newline at end of file From 1065a75bab0a5a44fd7b8579cc717901b79b3148 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 5 Jan 2024 14:02:36 +0900 Subject: [PATCH 06/46] =?UTF-8?q?refactor:=20=EB=B9=84=EB=8F=99=EA=B8=B0?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=ED=83=80=EC=9E=85=20=EC=A0=81=EC=9A=A9=20(#2?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 7 +++--- .../compiler/service/CompilerService.java | 22 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 3cb8d82..6078ef5 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; @RestController @Slf4j @@ -19,8 +20,8 @@ public class CompilerController { private final CompilerService compilerService; @GetMapping - public SuccessResponse getProblemInfo(@RequestParam int problemId) { - ProblemInfoDto problemInfo = compilerService.getProblemInfo(problemId); - return new SuccessResponse<>(problemInfo); + public Mono> getProblemInfo(@RequestParam int problemId) { + return compilerService.getProblemInfo(problemId) + .map(SuccessResponse::new); } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index 2d8ac3d..c95b1bd 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -3,11 +3,17 @@ import com.api.TaveShot.domain.compiler.converter.CompilerConverter; import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; import com.api.TaveShot.domain.compiler.dto.ProblemResponseDto; +import com.api.TaveShot.global.exception.ApiException; +import com.api.TaveShot.global.exception.ErrorType; +import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClientException; import reactor.core.publisher.Mono; @Service +@Slf4j public class CompilerService { private final WebClient webClient; @@ -16,17 +22,17 @@ public CompilerService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("https://solved.ac/api/v3").build(); } - public ProblemInfoDto getProblemInfo(int problemId) { - Mono problemResponseMono = webClient.get() + public Mono getProblemInfo(@NotNull int problemId) { + return webClient.get() .uri(uriBuilder -> uriBuilder.path("/problem/show") - .queryParam("problemId",problemId) + .queryParam("problemId", problemId) .build()) .retrieve() - .bodyToMono(ProblemResponseDto.class); + .bodyToMono(ProblemResponseDto.class) + .map(CompilerConverter::responseToInfoDto) + .onErrorMap(WebClientException.class, e -> + new ApiException(ErrorType._WEB_CLIENT_ERROR)) + .switchIfEmpty(Mono.error(new ApiException(ErrorType._SOLVED_NOT_FOUND))); - ProblemResponseDto problemResponse = problemResponseMono.block(); - assert problemResponse != null; - return CompilerConverter.responseToInfoDto(problemResponse); } - } \ No newline at end of file From e8a6879021452e59a729d655c89d1a68ce72d906 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sat, 6 Jan 2024 04:16:22 +0900 Subject: [PATCH 07/46] =?UTF-8?q?feat:=20=EB=AC=B8=EC=A0=9C=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4=20=EA=B2=B0=EA=B3=BC=20=EB=B0=98=ED=99=98=20API=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=20=EC=B4=88=EA=B8=B0=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(=EC=A0=95=EC=83=81=20=EC=9D=91=EB=8B=B5=20X)=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 13 ++-- .../compiler/dto/CodeSubmissionDto.java | 16 ++++ .../compiler/dto/SubmissionResponseDto.java | 32 ++++++++ .../compiler/dto/SubmissionResultDto.java | 15 ++++ .../compiler/service/CompilerService.java | 78 +++++++++++++++++-- 5 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 6078ef5..0e556eb 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -1,15 +1,13 @@ package com.api.TaveShot.domain.compiler.controller; import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; +import com.api.TaveShot.domain.compiler.dto.CodeSubmissionDto; +import com.api.TaveShot.domain.compiler.dto.SubmissionResultDto; import com.api.TaveShot.domain.compiler.service.CompilerService; import com.api.TaveShot.global.success.SuccessResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; @RestController @@ -24,4 +22,9 @@ public Mono> getProblemInfo(@RequestParam int pr return compilerService.getProblemInfo(problemId) .map(SuccessResponse::new); } + + @PostMapping("/submit") + public Mono submitCode(@RequestBody CodeSubmissionDto submission) { + return compilerService.compileAndJudge(submission); + } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java new file mode 100644 index 0000000..278d137 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java @@ -0,0 +1,16 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Builder +public class CodeSubmissionDto { + private int problemId; + private String sourceCode; + private int compilerId; //Sphere Engine에서 지정한 언어별 컴파일러 ID + private String input; +} + diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java new file mode 100644 index 0000000..802be3a --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java @@ -0,0 +1,32 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@AllArgsConstructor +@Getter +@Builder +public class SubmissionResponseDto { + private int id; + private boolean executing; + private Result result; + + @Builder + @Getter + public static class Result { + private Status status; // 채점 상태 객체 + private double time; // 실행 시간 + private int memory; // 메모리 사용량 + private String output; // 프로그램의 출력 + private String stderr; // 표준 에러 출력 + private String cmpinfo; // 컴파일 정보 + + @Builder + @Getter + public static class Status { + private int code; // 채점 상태 코드 + private String name; // 채점 상태 이름 + } + } +} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java new file mode 100644 index 0000000..b5165e1 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java @@ -0,0 +1,15 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@AllArgsConstructor +@Getter +@Builder +public class SubmissionResultDto { + private boolean isSuccess; + private String message; +} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index c95b1bd..60f6cd7 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,29 +1,45 @@ package com.api.TaveShot.domain.compiler.service; import com.api.TaveShot.domain.compiler.converter.CompilerConverter; -import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; -import com.api.TaveShot.domain.compiler.dto.ProblemResponseDto; +import com.api.TaveShot.domain.compiler.dto.*; import com.api.TaveShot.global.exception.ApiException; import com.api.TaveShot.global.exception.ErrorType; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientException; +import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; + @Service @Slf4j public class CompilerService { - private final WebClient webClient; + private final WebClient solvedwebClient; + private final WebClient sphereEngineWebClient; + private final String sphereEngineAccessToken = "fb3a5fa53ca96f45c72c8d0eab9c8207"; public CompilerService(WebClient.Builder webClientBuilder) { - this.webClient = webClientBuilder.baseUrl("https://solved.ac/api/v3").build(); + this.solvedwebClient = webClientBuilder.baseUrl("https://solved.ac/api/v3").build(); + this.sphereEngineWebClient = webClientBuilder.baseUrl("https://5318779a.compilers.sphere-engine.com/api/v4") + .defaultHeader("Content-Type", "application/json") + .build(); } public Mono getProblemInfo(@NotNull int problemId) { - return webClient.get() + return solvedwebClient.get() .uri(uriBuilder -> uriBuilder.path("/problem/show") .queryParam("problemId", problemId) .build()) @@ -35,4 +51,56 @@ public Mono getProblemInfo(@NotNull int problemId) { .switchIfEmpty(Mono.error(new ApiException(ErrorType._SOLVED_NOT_FOUND))); } + + public Mono compileAndJudge(CodeSubmissionDto submission) { + return sphereEngineWebClient.post() + .uri(uriBuilder -> uriBuilder.path("/submissions") + .queryParam("access_token", sphereEngineAccessToken) + .build()) + .body(BodyInserters.fromValue(createRequestBody(submission))) + .retrieve() + .bodyToMono(SubmissionResponseDto.class) + .map(this::processSubmissionResponse); + } + + private Map createRequestBody(CodeSubmissionDto submission) { + Map body = new HashMap<>(); + body.put("source", submission.getSourceCode()); + body.put("compilerId", submission.getCompilerId()); + + if (submission.getInput() != null) { + body.put("input", submission.getInput()); + } + return body; + } + + private SubmissionResultDto processSubmissionResponse(SubmissionResponseDto response) { + + boolean isSuccess; + String message; + + if (response.getResult() != null && response.getResult().getStatus() != null) { + int statusCode = response.getResult().getStatus().getCode(); + if (statusCode == 15) { // 성공 + isSuccess = true; + message = "Success"; + } else if (statusCode == 11) { // 컴파일 에러 + isSuccess = false; + message = "Compilation Error"; + } else if (statusCode == 12) { // 런타임 에러 + isSuccess = false; + message = "Runtime Error"; + } else { // 기타 채점 결과 상태에 따른 처리 + isSuccess = false; + message = "Error: Unknown or unhandled error"; + } + } else { + // API가 결과를 반환하지 않았을 경우 + isSuccess = false; + message = "API response is missing the result data"; + } + + return new SubmissionResultDto(isSuccess, message); + } + } \ No newline at end of file From 944cfeceb810cd88a6b357a730d1fa22ac43a259 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Mon, 8 Jan 2024 16:22:16 +0900 Subject: [PATCH 08/46] =?UTF-8?q?refactor:=20POST=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=EB=A5=BC=20=EA=B8=B0=EB=B0=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20GET=20=EC=9A=94=EC=B2=AD=EC=9D=84=20=EC=88=98?= =?UTF-8?q?=ED=96=89=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD,=20co?= =?UTF-8?q?nverter=20=EB=B6=84=EB=A6=AC=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/converter/CompilerConverter.java | 30 ++++++ .../compiler/service/CompilerService.java | 96 ++++++++++--------- 2 files changed, 82 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java index cfc94d7..750e8c5 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java @@ -2,6 +2,8 @@ import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; import com.api.TaveShot.domain.compiler.dto.ProblemResponseDto; +import com.api.TaveShot.domain.compiler.dto.SubmissionResponseDto; +import com.api.TaveShot.domain.compiler.dto.SubmissionResultDto; public class CompilerConverter { @@ -14,4 +16,32 @@ public static ProblemInfoDto responseToInfoDto(final ProblemResponseDto response ); } + public static SubmissionResultDto responseToSubmissionResultDto(final SubmissionResponseDto details) { + boolean isSuccess = false; + String message = "Unknown"; + + if (details.getResult() != null && details.getResult().getStatus() != null) { + int statusCode = details.getResult().getStatus().getCode(); + switch (statusCode) { + case 15: // 성공 + isSuccess = true; + message = "Success"; + break; + case 11: // 컴파일 에러 + message = "Compilation Error"; + break; + case 12: // 런타임 에러 + message = "Runtime Error"; + break; + default: // 기타 오류 + message = "Error: Unknown or unhandled error"; + break; + } + } else { + message = "API response is missing the result data"; + } + + return new SubmissionResultDto(isSuccess, message); + } + } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index 60f6cd7..b9e1256 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -4,22 +4,21 @@ import com.api.TaveShot.domain.compiler.dto.*; import com.api.TaveShot.global.exception.ApiException; import com.api.TaveShot.global.exception.ErrorType; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; + import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientException; -import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; +import org.springframework.beans.factory.annotation.Value; + + -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; + +import java.time.Duration; import java.util.HashMap; import java.util.Map; @@ -29,15 +28,34 @@ public class CompilerService { private final WebClient solvedwebClient; private final WebClient sphereEngineWebClient; - private final String sphereEngineAccessToken = "fb3a5fa53ca96f45c72c8d0eab9c8207"; + + @Value("${compiler.token}") + private String sphereEngineAccessToken; public CompilerService(WebClient.Builder webClientBuilder) { this.solvedwebClient = webClientBuilder.baseUrl("https://solved.ac/api/v3").build(); this.sphereEngineWebClient = webClientBuilder.baseUrl("https://5318779a.compilers.sphere-engine.com/api/v4") .defaultHeader("Content-Type", "application/json") + .filter(logRequest()) + .filter(logResponse()) .build(); } + private ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + log.info("Request: {} {}", clientRequest.method(), clientRequest.url()); + return Mono.just(clientRequest); + }); + } + + private ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + log.info("Response: {} {}", clientResponse.statusCode(), clientResponse.headers().asHttpHeaders()); + return Mono.just(clientResponse); + }); + } + + // 문제 정보 가져오기 public Mono getProblemInfo(@NotNull int problemId) { return solvedwebClient.get() .uri(uriBuilder -> uriBuilder.path("/problem/show") @@ -52,55 +70,45 @@ public Mono getProblemInfo(@NotNull int problemId) { } + // 코드 컴파일 및 채점 결과 반환 public Mono compileAndJudge(CodeSubmissionDto submission) { + return submitCode(submission) + .flatMap(this::getSubmissionResult) + .delayElement(Duration.ofSeconds(10)); + } + + // Sphere Engine API에 코드 제출 + private Mono submitCode(CodeSubmissionDto submission) { + Map requestBody = createRequestBody(submission); + return sphereEngineWebClient.post() .uri(uriBuilder -> uriBuilder.path("/submissions") .queryParam("access_token", sphereEngineAccessToken) .build()) - .body(BodyInserters.fromValue(createRequestBody(submission))) + .body(BodyInserters.fromValue(requestBody)) .retrieve() .bodyToMono(SubmissionResponseDto.class) - .map(this::processSubmissionResponse); + .map(SubmissionResponseDto::getId); } + // 제출된 코드의 채점 결과 조회 + private Mono getSubmissionResult(int submissionId) { + return sphereEngineWebClient.get() + .uri(uriBuilder -> uriBuilder.path("/submissions/" + submissionId) + .queryParam("access_token", sphereEngineAccessToken) + .build()) + .retrieve() + .bodyToMono(SubmissionResponseDto.class) + .map(CompilerConverter::responseToSubmissionResultDto); + } + + // Sphere Engine API 요청을 위한 요청 본문 생성 private Map createRequestBody(CodeSubmissionDto submission) { Map body = new HashMap<>(); - body.put("source", submission.getSourceCode()); + body.put("source", submission.getSource()); body.put("compilerId", submission.getCompilerId()); - if (submission.getInput() != null) { - body.put("input", submission.getInput()); - } return body; } - private SubmissionResultDto processSubmissionResponse(SubmissionResponseDto response) { - - boolean isSuccess; - String message; - - if (response.getResult() != null && response.getResult().getStatus() != null) { - int statusCode = response.getResult().getStatus().getCode(); - if (statusCode == 15) { // 성공 - isSuccess = true; - message = "Success"; - } else if (statusCode == 11) { // 컴파일 에러 - isSuccess = false; - message = "Compilation Error"; - } else if (statusCode == 12) { // 런타임 에러 - isSuccess = false; - message = "Runtime Error"; - } else { // 기타 채점 결과 상태에 따른 처리 - isSuccess = false; - message = "Error: Unknown or unhandled error"; - } - } else { - // API가 결과를 반환하지 않았을 경우 - isSuccess = false; - message = "API response is missing the result data"; - } - - return new SubmissionResultDto(isSuccess, message); - } - } \ No newline at end of file From 73e82163d7c429b8a7a52287332640d8613bf58b Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Mon, 8 Jan 2024 16:22:54 +0900 Subject: [PATCH 09/46] =?UTF-8?q?refactor:=20api=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/dto/CodeSubmissionDto.java | 7 +-- .../compiler/dto/SubmissionResponseDto.java | 44 +++++++++++++++---- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java index 278d137..fb44184 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java @@ -8,9 +8,6 @@ @AllArgsConstructor @Builder public class CodeSubmissionDto { - private int problemId; - private String sourceCode; + private String source; private int compilerId; //Sphere Engine에서 지정한 언어별 컴파일러 ID - private String input; -} - +} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java index 802be3a..1c76dc1 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java @@ -4,29 +4,55 @@ import lombok.Builder; import lombok.Getter; +import java.util.Map; + @AllArgsConstructor @Getter @Builder public class SubmissionResponseDto { private int id; private boolean executing; + private String date; + private Compiler compiler; private Result result; + @Getter @Builder + public static class Compiler { + private int id; + private String name; + private Version version; + + @Getter + @Builder + public static class Version { + private int id; + private String name; + } + } + @Getter + @Builder public static class Result { - private Status status; // 채점 상태 객체 - private double time; // 실행 시간 - private int memory; // 메모리 사용량 - private String output; // 프로그램의 출력 - private String stderr; // 표준 에러 출력 - private String cmpinfo; // 컴파일 정보 + private Status status; + private double time; + private int memory; + private int signal; + private String signal_desc; + private Map streams; - @Builder @Getter + @Builder public static class Status { - private int code; // 채점 상태 코드 - private String name; // 채점 상태 이름 + private int code; + private String name; + } + + @Getter + @Builder + public static class Stream { + private int size; + private String uri; } } } From 511522b529f4516935a3edf3608ef0620c650153 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Mon, 8 Jan 2024 21:24:35 +0900 Subject: [PATCH 10/46] =?UTF-8?q?refactor:=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EA=B4=80=EB=A0=A8=20=EC=BD=94=EB=93=9C,?= =?UTF-8?q?=20=EC=BB=B4=ED=8C=8C=EC=9D=BC=EB=9F=AC=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=B6=84=EB=A6=AC=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/converter/CompilerConverter.java | 11 ---------- .../domain/compiler/dto/ProblemInfoDto.java | 21 ------------------- .../compiler/dto/ProblemResponseDto.java | 19 ----------------- .../TaveShot/domain/compiler/dto/TagDto.java | 16 -------------- 4 files changed, 67 deletions(-) delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java index 750e8c5..35de633 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java @@ -1,21 +1,10 @@ package com.api.TaveShot.domain.compiler.converter; -import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; -import com.api.TaveShot.domain.compiler.dto.ProblemResponseDto; import com.api.TaveShot.domain.compiler.dto.SubmissionResponseDto; import com.api.TaveShot.domain.compiler.dto.SubmissionResultDto; public class CompilerConverter { - public static ProblemInfoDto responseToInfoDto(final ProblemResponseDto response){ - return new ProblemInfoDto( - response.getProblemId(), - response.getTitleKo(), - response.getLevel(), - response.getTags() - ); - } - public static SubmissionResultDto responseToSubmissionResultDto(final SubmissionResponseDto details) { boolean isSuccess = false; String message = "Unknown"; diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java deleted file mode 100644 index b2c135a..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemInfoDto.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.api.TaveShot.domain.compiler.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -@Builder -public class ProblemInfoDto { - - private int problemId; - private String titleKo; - private int level; - private List tags; - -} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java deleted file mode 100644 index 90d3452..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.api.TaveShot.domain.compiler.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class ProblemResponseDto { - - private int problemId; - private String titleKo; - private int level; - private List tags; - -} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java deleted file mode 100644 index 3680d30..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/TagDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.api.TaveShot.domain.compiler.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -@Builder -public class TagDto { - private String key; - private int bojTagId; - private String name; -} \ No newline at end of file From f27ea39f585303fcdd87f93712c905408dd2f870 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 9 Jan 2024 03:12:02 +0900 Subject: [PATCH 11/46] =?UTF-8?q?feat:=20ProblemDto,=20ProblemService=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=EA=B5=AC=ED=98=84=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../domain/problem/dto/ProblemDto.java | 33 +++++++++++ .../problem/service/ProblemService.java | 57 +++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java create mode 100644 src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java diff --git a/build.gradle b/build.gradle index 31d7c8a..fe140f0 100644 --- a/build.gradle +++ b/build.gradle @@ -66,6 +66,8 @@ dependencies { // redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'io.lettuce:lettuce-core' + + implementation 'com.opencsv:opencsv:5.5.2' } tasks.named('bootBuildImage') { diff --git a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java new file mode 100644 index 0000000..b8cc31f --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java @@ -0,0 +1,33 @@ +package com.api.TaveShot.domain.problem.dto; + +import com.opencsv.bean.CsvBindByName; +import lombok.*; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ProblemDto { + + @CsvBindByName(column = "ID") + private String ID; + + @CsvBindByName(column = "Title") + private String Title; + + @CsvBindByName(column = "Description") + private String Description; + + @CsvBindByName(column = "Input Description") + private String inputDescription; + + @CsvBindByName(column = "Output Description") + private String outputDescription; + + @CsvBindByName(column = "Sample Input") + private String sampleInput; + + @CsvBindByName(column = "Sample Output") + private String sampleOutput; + +} diff --git a/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java new file mode 100644 index 0000000..e64f25b --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java @@ -0,0 +1,57 @@ +package com.api.TaveShot.domain.problem.service; + +import com.api.TaveShot.domain.problem.dto.ProblemDto; +import com.opencsv.bean.CsvToBean; +import com.opencsv.bean.CsvToBeanBuilder; +import com.opencsv.bean.HeaderColumnNameMappingStrategy; +import jakarta.annotation.PostConstruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service +public class ProblemService { + private static final Logger log = LoggerFactory.getLogger(ProblemService.class); + private Map problemMap; + + @PostConstruct + public void init() { + + Resource resource = new ClassPathResource("baekjoon_problems.csv"); + try (InputStream is = resource.getInputStream(); + Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { + + + HeaderColumnNameMappingStrategy strategy = new HeaderColumnNameMappingStrategy<>(); + strategy.setType(ProblemDto.class); + + CsvToBean csvToBean = new CsvToBeanBuilder(reader) + .withMappingStrategy(strategy) + .build(); + + + List problems = csvToBean.parse(); + + + problemMap = problems.stream() + .filter(problem -> problem.getID() != null) + .collect(Collectors.toMap(ProblemDto::getID, Function.identity(), (existing, replacement) -> existing)); + } catch (Exception e) { + log.error("Error loading problems from CSV", e); + } + } + + public ProblemDto getProblemById(String id) { + return problemMap.get(id); + } +} \ No newline at end of file From 54e3b6827e85d2e9bfde230c21e90858b804e2ab Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 9 Jan 2024 12:00:14 +0900 Subject: [PATCH 12/46] =?UTF-8?q?refactor:=20BOMInputStream=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=B4=20=EB=AC=B8=EC=A0=9C=20id=EA=B0=80=20null?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=BD=ED=9E=88=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ .../problem/service/ProblemService.java | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index fe140f0..45c516b 100644 --- a/build.gradle +++ b/build.gradle @@ -68,6 +68,8 @@ dependencies { implementation 'io.lettuce:lettuce-core' implementation 'com.opencsv:opencsv:5.5.2' + + implementation 'commons-io:commons-io:2.11.0' } tasks.named('bootBuildImage') { diff --git a/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java index e64f25b..bce3687 100644 --- a/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java +++ b/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java @@ -1,12 +1,12 @@ package com.api.TaveShot.domain.problem.service; import com.api.TaveShot.domain.problem.dto.ProblemDto; +import com.api.TaveShot.global.exception.ApiException; +import com.api.TaveShot.global.exception.ErrorType; import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; import com.opencsv.bean.HeaderColumnNameMappingStrategy; import jakarta.annotation.PostConstruct; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; @@ -18,18 +18,19 @@ import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +import org.apache.commons.io.input.BOMInputStream; @Service public class ProblemService { - private static final Logger log = LoggerFactory.getLogger(ProblemService.class); private Map problemMap; @PostConstruct public void init() { Resource resource = new ClassPathResource("baekjoon_problems.csv"); - try (InputStream is = resource.getInputStream(); - Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { + try (InputStream inputStream = resource.getInputStream(); + BOMInputStream bomInputStream = new BOMInputStream(inputStream); + Reader reader = new InputStreamReader(bomInputStream, StandardCharsets.UTF_8)) { HeaderColumnNameMappingStrategy strategy = new HeaderColumnNameMappingStrategy<>(); @@ -45,13 +46,17 @@ public void init() { problemMap = problems.stream() .filter(problem -> problem.getID() != null) - .collect(Collectors.toMap(ProblemDto::getID, Function.identity(), (existing, replacement) -> existing)); + .collect(Collectors.toUnmodifiableMap( + ProblemDto::getID, + Function.identity() + )); + } catch (Exception e) { - log.error("Error loading problems from CSV", e); + throw new ApiException(ErrorType._WEB_CLIENT_ERROR); } } - public ProblemDto getProblemById(String id) { return problemMap.get(id); } + } \ No newline at end of file From 573d35ee0952f3acfee8131b8fbdc78f0928058c Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 10 Jan 2024 16:25:52 +0900 Subject: [PATCH 13/46] =?UTF-8?q?refactor:=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EA=B0=92=20JSON=EC=9C=BC=EB=A1=9C=20=EC=A7=81=EC=A0=91=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20(=EC=97=AD=EC=8A=AC=EB=9E=98=EC=8B=9C=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EC=A0=9C=EA=B1=B0)=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/api/TaveShot/domain/problem/dto/ProblemDto.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java index b8cc31f..8753a12 100644 --- a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java @@ -1,5 +1,6 @@ package com.api.TaveShot.domain.problem.dto; +import com.fasterxml.jackson.annotation.JsonRawValue; import com.opencsv.bean.CsvBindByName; import lombok.*; @@ -9,25 +10,31 @@ @Builder public class ProblemDto { + @JsonRawValue @CsvBindByName(column = "ID") private String ID; + @JsonRawValue @CsvBindByName(column = "Title") private String Title; + @JsonRawValue @CsvBindByName(column = "Description") private String Description; + @JsonRawValue @CsvBindByName(column = "Input Description") private String inputDescription; + @JsonRawValue @CsvBindByName(column = "Output Description") private String outputDescription; + @JsonRawValue @CsvBindByName(column = "Sample Input") private String sampleInput; + @JsonRawValue @CsvBindByName(column = "Sample Output") private String sampleOutput; - } From 8c2682c40014121e8831bd64f0777f7b36379757 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 10 Jan 2024 16:28:53 +0900 Subject: [PATCH 14/46] =?UTF-8?q?refactor:=20getter=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EC=97=90=EC=84=9C=20JSON=20=EB=B3=80=ED=99=98=20->=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=EB=90=9C=20=EA=B2=B0=EA=B3=BC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/problem/dto/ProblemDto.java | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java index 8753a12..58eda6e 100644 --- a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java @@ -1,5 +1,6 @@ package com.api.TaveShot.domain.problem.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; import com.opencsv.bean.CsvBindByName; import lombok.*; @@ -10,31 +11,60 @@ @Builder public class ProblemDto { - @JsonRawValue @CsvBindByName(column = "ID") private String ID; - @JsonRawValue @CsvBindByName(column = "Title") private String Title; - @JsonRawValue @CsvBindByName(column = "Description") private String Description; - @JsonRawValue @CsvBindByName(column = "Input Description") private String inputDescription; - @JsonRawValue @CsvBindByName(column = "Output Description") private String outputDescription; - @JsonRawValue @CsvBindByName(column = "Sample Input") private String sampleInput; - @JsonRawValue @CsvBindByName(column = "Sample Output") private String sampleOutput; -} + + @JsonRawValue + public String getID(){ + return ID; + } + @JsonRawValue + public String getTitle(){ + return Title; + } + + @JsonRawValue + public String getDescription(){ + return Description; + } + + @JsonRawValue + public String getInputDescription(){ + return inputDescription; + } + + @JsonRawValue + public String getOutputDescription(){ + return outputDescription; + } + + @JsonRawValue + public String getSampleInput(){ + return sampleInput; + } + + @JsonRawValue + public String getSampleOutput(){ + return sampleOutput; + } + + +} \ No newline at end of file From c890a7eec0e63324e2be8812fa9eccce5de2a725 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Thu, 11 Jan 2024 04:08:38 +0900 Subject: [PATCH 15/46] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC,=20=EB=A9=94=EC=86=8C=EB=93=9C=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 16 +++---- .../{problem => compiler}/dto/ProblemDto.java | 2 +- .../compiler/service/CompilerService.java | 42 ------------------- .../service/ProblemService.java | 9 +++- 4 files changed, 17 insertions(+), 52 deletions(-) rename src/main/java/com/api/TaveShot/domain/{problem => compiler}/dto/ProblemDto.java (96%) rename src/main/java/com/api/TaveShot/domain/{problem => compiler}/service/ProblemService.java (87%) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 0e556eb..02e3321 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -1,26 +1,28 @@ package com.api.TaveShot.domain.compiler.controller; -import com.api.TaveShot.domain.compiler.dto.ProblemInfoDto; import com.api.TaveShot.domain.compiler.dto.CodeSubmissionDto; import com.api.TaveShot.domain.compiler.dto.SubmissionResultDto; import com.api.TaveShot.domain.compiler.service.CompilerService; +import com.api.TaveShot.domain.compiler.dto.ProblemDto; +import com.api.TaveShot.domain.compiler.service.ProblemService; import com.api.TaveShot.global.success.SuccessResponse; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; @RestController -@Slf4j @RequiredArgsConstructor @RequestMapping("/api/compile") public class CompilerController { private final CompilerService compilerService; - @GetMapping - public Mono> getProblemInfo(@RequestParam int problemId) { - return compilerService.getProblemInfo(problemId) - .map(SuccessResponse::new); + private final ProblemService problemService; + + @GetMapping("/problems/{id}") + public SuccessResponse getProblem(@PathVariable String id) { + ProblemDto problem = problemService.getProblemById(id); + return new SuccessResponse<>(problem); } @PostMapping("/submit") diff --git a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java similarity index 96% rename from src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java rename to src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 58eda6e..dd94891 100644 --- a/src/main/java/com/api/TaveShot/domain/problem/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -1,4 +1,4 @@ -package com.api.TaveShot.domain.problem.dto; +package com.api.TaveShot.domain.compiler.dto; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index b9e1256..c587c40 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -2,22 +2,12 @@ import com.api.TaveShot.domain.compiler.converter.CompilerConverter; import com.api.TaveShot.domain.compiler.dto.*; -import com.api.TaveShot.global.exception.ApiException; -import com.api.TaveShot.global.exception.ErrorType; - -import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClientException; import reactor.core.publisher.Mono; import org.springframework.beans.factory.annotation.Value; - - - - import java.time.Duration; import java.util.HashMap; import java.util.Map; @@ -26,49 +16,17 @@ @Slf4j public class CompilerService { - private final WebClient solvedwebClient; private final WebClient sphereEngineWebClient; @Value("${compiler.token}") private String sphereEngineAccessToken; public CompilerService(WebClient.Builder webClientBuilder) { - this.solvedwebClient = webClientBuilder.baseUrl("https://solved.ac/api/v3").build(); this.sphereEngineWebClient = webClientBuilder.baseUrl("https://5318779a.compilers.sphere-engine.com/api/v4") .defaultHeader("Content-Type", "application/json") - .filter(logRequest()) - .filter(logResponse()) .build(); } - private ExchangeFilterFunction logRequest() { - return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { - log.info("Request: {} {}", clientRequest.method(), clientRequest.url()); - return Mono.just(clientRequest); - }); - } - - private ExchangeFilterFunction logResponse() { - return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { - log.info("Response: {} {}", clientResponse.statusCode(), clientResponse.headers().asHttpHeaders()); - return Mono.just(clientResponse); - }); - } - - // 문제 정보 가져오기 - public Mono getProblemInfo(@NotNull int problemId) { - return solvedwebClient.get() - .uri(uriBuilder -> uriBuilder.path("/problem/show") - .queryParam("problemId", problemId) - .build()) - .retrieve() - .bodyToMono(ProblemResponseDto.class) - .map(CompilerConverter::responseToInfoDto) - .onErrorMap(WebClientException.class, e -> - new ApiException(ErrorType._WEB_CLIENT_ERROR)) - .switchIfEmpty(Mono.error(new ApiException(ErrorType._SOLVED_NOT_FOUND))); - - } // 코드 컴파일 및 채점 결과 반환 public Mono compileAndJudge(CodeSubmissionDto submission) { diff --git a/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java similarity index 87% rename from src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java rename to src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java index bce3687..54d613c 100644 --- a/src/main/java/com/api/TaveShot/domain/problem/service/ProblemService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java @@ -1,6 +1,6 @@ -package com.api.TaveShot.domain.problem.service; +package com.api.TaveShot.domain.compiler.service; -import com.api.TaveShot.domain.problem.dto.ProblemDto; +import com.api.TaveShot.domain.compiler.dto.ProblemDto; import com.api.TaveShot.global.exception.ApiException; import com.api.TaveShot.global.exception.ErrorType; import com.opencsv.bean.CsvToBean; @@ -56,6 +56,11 @@ public void init() { } } public ProblemDto getProblemById(String id) { + ProblemDto problem = problemMap.get(id); + + if (problem == null) { + throw new ApiException(ErrorType._SOLVED_INVALID_REQUEST); //에러 타입 수정 필요 + } return problemMap.get(id); } From becef36bb4d2cb8459c74d75c8175d3c29f978d8 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sat, 13 Jan 2024 22:34:36 +0900 Subject: [PATCH 16/46] =?UTF-8?q?refactor:=20CodeSubmissionDto=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java index fb44184..fe1d679 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java @@ -8,6 +8,7 @@ @AllArgsConstructor @Builder public class CodeSubmissionDto { - private String source; - private int compilerId; //Sphere Engine에서 지정한 언어별 컴파일러 ID + private String problemId; + private String language; + private String sourceCode; } \ No newline at end of file From a4ceccabeb0ca8e2aeaaa2fdd07c16c5d92a82a8 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sat, 13 Jan 2024 23:04:58 +0900 Subject: [PATCH 17/46] =?UTF-8?q?refactor:=20Controller,=20Service=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD=20(BOJ-AutoSubmit)=20(#?= =?UTF-8?q?28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 6 +- .../compiler/service/CompilerService.java | 64 ++++--------------- 2 files changed, 16 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 02e3321..68a1f1b 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -7,6 +7,7 @@ import com.api.TaveShot.domain.compiler.service.ProblemService; import com.api.TaveShot.global.success.SuccessResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; @@ -26,7 +27,8 @@ public SuccessResponse getProblem(@PathVariable String id) { } @PostMapping("/submit") - public Mono submitCode(@RequestBody CodeSubmissionDto submission) { - return compilerService.compileAndJudge(submission); + public SuccessResponse submitCode(@RequestBody CodeSubmissionDto submissionDto) { + compilerService.submitCode(submissionDto); + return new SuccessResponse<>("Submission successful"); // 이후에 변경 } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index c587c40..db2a6e3 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,72 +1,32 @@ package com.api.TaveShot.domain.compiler.service; - -import com.api.TaveShot.domain.compiler.converter.CompilerConverter; import com.api.TaveShot.domain.compiler.dto.*; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; -import org.springframework.beans.factory.annotation.Value; -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; + @Service @Slf4j public class CompilerService { - private final WebClient sphereEngineWebClient; - - @Value("${compiler.token}") - private String sphereEngineAccessToken; + private final WebClient webClient; public CompilerService(WebClient.Builder webClientBuilder) { - this.sphereEngineWebClient = webClientBuilder.baseUrl("https://5318779a.compilers.sphere-engine.com/api/v4") - .defaultHeader("Content-Type", "application/json") - .build(); - } - - - // 코드 컴파일 및 채점 결과 반환 - public Mono compileAndJudge(CodeSubmissionDto submission) { - return submitCode(submission) - .flatMap(this::getSubmissionResult) - .delayElement(Duration.ofSeconds(10)); + this.webClient = webClientBuilder.baseUrl("http://localhost:5000").build(); } - // Sphere Engine API에 코드 제출 - private Mono submitCode(CodeSubmissionDto submission) { - Map requestBody = createRequestBody(submission); - - return sphereEngineWebClient.post() - .uri(uriBuilder -> uriBuilder.path("/submissions") - .queryParam("access_token", sphereEngineAccessToken) - .build()) - .body(BodyInserters.fromValue(requestBody)) - .retrieve() - .bodyToMono(SubmissionResponseDto.class) - .map(SubmissionResponseDto::getId); - } - - // 제출된 코드의 채점 결과 조회 - private Mono getSubmissionResult(int submissionId) { - return sphereEngineWebClient.get() - .uri(uriBuilder -> uriBuilder.path("/submissions/" + submissionId) - .queryParam("access_token", sphereEngineAccessToken) - .build()) + public void submitCode(CodeSubmissionDto submissionDto) { + Mono response = webClient.post() + .uri("/submit-code") + .bodyValue(submissionDto) .retrieve() - .bodyToMono(SubmissionResponseDto.class) - .map(CompilerConverter::responseToSubmissionResultDto); - } - - // Sphere Engine API 요청을 위한 요청 본문 생성 - private Map createRequestBody(CodeSubmissionDto submission) { - Map body = new HashMap<>(); - body.put("source", submission.getSource()); - body.put("compilerId", submission.getCompilerId()); + .bodyToMono(String.class); - return body; + String result = response.block(); + if (result == null || result.contains("error")) { + throw new RuntimeException("Failed to submit code"); // 이후에 변경 + } } } \ No newline at end of file From fa8280609ec92eb694bd22c8774434f9b35649e1 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sun, 14 Jan 2024 17:29:58 +0900 Subject: [PATCH 18/46] =?UTF-8?q?refactor:=20Sphere=20Engine=20API=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EC=BD=94=EB=93=9C=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 11 ++- .../compiler/dto/CodeSubmissionDto.java | 10 ++- .../compiler/service/CompilerService.java | 88 ++++++++++++++++--- 3 files changed, 92 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 68a1f1b..7e4c420 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -27,8 +27,13 @@ public SuccessResponse getProblem(@PathVariable String id) { } @PostMapping("/submit") - public SuccessResponse submitCode(@RequestBody CodeSubmissionDto submissionDto) { - compilerService.submitCode(submissionDto); - return new SuccessResponse<>("Submission successful"); // 이후에 변경 + public Mono submitCode(@RequestBody CodeSubmissionDto submission) { + return compilerService.compileAndJudge(submission); } + +// @PostMapping("/submit") +// public SuccessResponse submitCode(@RequestBody CodeSubmissionDto submissionDto) { +// compilerService.submitCode(submissionDto); +// return new SuccessResponse<>("Submission successful"); // 이후에 변경 +// } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java index fe1d679..97f6784 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java @@ -8,7 +8,11 @@ @AllArgsConstructor @Builder public class CodeSubmissionDto { - private String problemId; - private String language; - private String sourceCode; + + private String source; + private int compilerId; //Sphere Engine에서 지정한 언어별 컴파일러 ID + +// private String problemId; +// private String language; +// private String sourceCode; } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index db2a6e3..18a45f3 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,32 +1,98 @@ package com.api.TaveShot.domain.compiler.service; +import com.api.TaveShot.domain.compiler.converter.CompilerConverter; import com.api.TaveShot.domain.compiler.dto.*; +import org.springframework.beans.factory.annotation.Value; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + @Service @Slf4j public class CompilerService { - private final WebClient webClient; + private final WebClient sphereEngineWebClient; + + @Value("${compiler.token}") + private String sphereEngineAccessToken; public CompilerService(WebClient.Builder webClientBuilder) { - this.webClient = webClientBuilder.baseUrl("http://localhost:5000").build(); + this.sphereEngineWebClient = webClientBuilder.baseUrl("https://5318779a.compilers.sphere-engine.com/api/v4") + .defaultHeader("Content-Type", "application/json") + .build(); + } + + + // 코드 컴파일 및 채점 결과 반환 + public Mono compileAndJudge(CodeSubmissionDto submission) { + return submitCode(submission) + .flatMap(this::waitForResult) + .flatMap(this::getSubmissionResult); + } + + private Mono waitForResult(int submissionId) { + // 결과가 준비될 때까지 일정 시간 기다립니다. + return Mono.just(submissionId) + .delayElement(Duration.ofSeconds(10)); // 10초 기다림 } - public void submitCode(CodeSubmissionDto submissionDto) { - Mono response = webClient.post() - .uri("/submit-code") - .bodyValue(submissionDto) + // Sphere Engine API에 코드 제출 + private Mono submitCode(CodeSubmissionDto submission) { + Map requestBody = createRequestBody(submission); + + return sphereEngineWebClient.post() + .uri(uriBuilder -> uriBuilder.path("/submissions") + .queryParam("access_token", sphereEngineAccessToken) + .build()) + .body(BodyInserters.fromValue(requestBody)) .retrieve() - .bodyToMono(String.class); + .bodyToMono(SubmissionResponseDto.class) + .map(SubmissionResponseDto::getId); + } - String result = response.block(); - if (result == null || result.contains("error")) { - throw new RuntimeException("Failed to submit code"); // 이후에 변경 - } + // 제출된 코드의 채점 결과 조회 + private Mono getSubmissionResult(int submissionId) { + return sphereEngineWebClient.get() + .uri(uriBuilder -> uriBuilder.path("/submissions/" + submissionId) + .queryParam("access_token", sphereEngineAccessToken) + .build()) + .retrieve() + .bodyToMono(SubmissionResponseDto.class) + .map(CompilerConverter::responseToSubmissionResultDto); } + // Sphere Engine API 요청을 위한 요청 본문 생성 + private Map createRequestBody(CodeSubmissionDto submission) { + Map body = new HashMap<>(); + body.put("source", submission.getSource()); + body.put("compilerId", submission.getCompilerId()); + + return body; + } + +// private final WebClient webClient; +// +// public CompilerService(WebClient.Builder webClientBuilder) { +// this.webClient = webClientBuilder.baseUrl("http://localhost:5000").build(); +// } +// +// public void submitCode(CodeSubmissionDto submissionDto) { +// Mono response = webClient.post() +// .uri("/submit-code") +// .bodyValue(submissionDto) +// .retrieve() +// .bodyToMono(String.class); +// +// String result = response.block(); +// if (result == null || result.contains("error")) { +// throw new RuntimeException("Failed to submit code"); // 이후에 변경 +// } +// } + } \ No newline at end of file From 1c288a3ec2ac27a04217f7df86431037c6e85409 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 16 Jan 2024 18:33:29 +0900 Subject: [PATCH 19/46] =?UTF-8?q?feat:=20=EB=B0=B1=EC=A4=80=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A7=81=ED=81=AC=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index dd94891..98b4a8f 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -66,5 +66,9 @@ public String getSampleOutput(){ return sampleOutput; } + public String getProblemUrl(){ + return "https://www.acmicpc.net/problem/" + this.ID; + } + } \ No newline at end of file From cac838916adca40ebb74486f9abc7716d24a8f3e Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 16 Jan 2024 18:40:35 +0900 Subject: [PATCH 20/46] =?UTF-8?q?feat:=20Sphere=20Engine=20API=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/converter/CompilerConverter.java | 36 ------- .../compiler/dto/CodeSubmissionDto.java | 18 ---- .../compiler/dto/SubmissionResponseDto.java | 58 ----------- .../compiler/dto/SubmissionResultDto.java | 15 --- .../compiler/service/CompilerService.java | 98 ------------------- 5 files changed, 225 deletions(-) delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java delete mode 100644 src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java deleted file mode 100644 index 35de633..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/CompilerConverter.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.api.TaveShot.domain.compiler.converter; - -import com.api.TaveShot.domain.compiler.dto.SubmissionResponseDto; -import com.api.TaveShot.domain.compiler.dto.SubmissionResultDto; - -public class CompilerConverter { - - public static SubmissionResultDto responseToSubmissionResultDto(final SubmissionResponseDto details) { - boolean isSuccess = false; - String message = "Unknown"; - - if (details.getResult() != null && details.getResult().getStatus() != null) { - int statusCode = details.getResult().getStatus().getCode(); - switch (statusCode) { - case 15: // 성공 - isSuccess = true; - message = "Success"; - break; - case 11: // 컴파일 에러 - message = "Compilation Error"; - break; - case 12: // 런타임 에러 - message = "Runtime Error"; - break; - default: // 기타 오류 - message = "Error: Unknown or unhandled error"; - break; - } - } else { - message = "API response is missing the result data"; - } - - return new SubmissionResultDto(isSuccess, message); - } - -} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java deleted file mode 100644 index 97f6784..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/CodeSubmissionDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.api.TaveShot.domain.compiler.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -@Getter -@AllArgsConstructor -@Builder -public class CodeSubmissionDto { - - private String source; - private int compilerId; //Sphere Engine에서 지정한 언어별 컴파일러 ID - -// private String problemId; -// private String language; -// private String sourceCode; -} \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java deleted file mode 100644 index 1c76dc1..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResponseDto.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.api.TaveShot.domain.compiler.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -import java.util.Map; - -@AllArgsConstructor -@Getter -@Builder -public class SubmissionResponseDto { - private int id; - private boolean executing; - private String date; - private Compiler compiler; - private Result result; - - @Getter - @Builder - public static class Compiler { - private int id; - private String name; - private Version version; - - @Getter - @Builder - public static class Version { - private int id; - private String name; - } - } - - @Getter - @Builder - public static class Result { - private Status status; - private double time; - private int memory; - private int signal; - private String signal_desc; - private Map streams; - - @Getter - @Builder - public static class Status { - private int code; - private String name; - } - - @Getter - @Builder - public static class Stream { - private int size; - private String uri; - } - } -} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java deleted file mode 100644 index b5165e1..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionResultDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.api.TaveShot.domain.compiler.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; - -import java.util.List; - -@AllArgsConstructor -@Getter -@Builder -public class SubmissionResultDto { - private boolean isSuccess; - private String message; -} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java deleted file mode 100644 index 18a45f3..0000000 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.api.TaveShot.domain.compiler.service; -import com.api.TaveShot.domain.compiler.converter.CompilerConverter; -import com.api.TaveShot.domain.compiler.dto.*; -import org.springframework.beans.factory.annotation.Value; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -import java.time.Duration; -import java.util.HashMap; -import java.util.Map; - - -@Service -@Slf4j -public class CompilerService { - - private final WebClient sphereEngineWebClient; - - @Value("${compiler.token}") - private String sphereEngineAccessToken; - - public CompilerService(WebClient.Builder webClientBuilder) { - this.sphereEngineWebClient = webClientBuilder.baseUrl("https://5318779a.compilers.sphere-engine.com/api/v4") - .defaultHeader("Content-Type", "application/json") - .build(); - } - - - // 코드 컴파일 및 채점 결과 반환 - public Mono compileAndJudge(CodeSubmissionDto submission) { - return submitCode(submission) - .flatMap(this::waitForResult) - .flatMap(this::getSubmissionResult); - } - - private Mono waitForResult(int submissionId) { - // 결과가 준비될 때까지 일정 시간 기다립니다. - return Mono.just(submissionId) - .delayElement(Duration.ofSeconds(10)); // 10초 기다림 - } - - // Sphere Engine API에 코드 제출 - private Mono submitCode(CodeSubmissionDto submission) { - Map requestBody = createRequestBody(submission); - - return sphereEngineWebClient.post() - .uri(uriBuilder -> uriBuilder.path("/submissions") - .queryParam("access_token", sphereEngineAccessToken) - .build()) - .body(BodyInserters.fromValue(requestBody)) - .retrieve() - .bodyToMono(SubmissionResponseDto.class) - .map(SubmissionResponseDto::getId); - } - - // 제출된 코드의 채점 결과 조회 - private Mono getSubmissionResult(int submissionId) { - return sphereEngineWebClient.get() - .uri(uriBuilder -> uriBuilder.path("/submissions/" + submissionId) - .queryParam("access_token", sphereEngineAccessToken) - .build()) - .retrieve() - .bodyToMono(SubmissionResponseDto.class) - .map(CompilerConverter::responseToSubmissionResultDto); - } - - // Sphere Engine API 요청을 위한 요청 본문 생성 - private Map createRequestBody(CodeSubmissionDto submission) { - Map body = new HashMap<>(); - body.put("source", submission.getSource()); - body.put("compilerId", submission.getCompilerId()); - - return body; - } - -// private final WebClient webClient; -// -// public CompilerService(WebClient.Builder webClientBuilder) { -// this.webClient = webClientBuilder.baseUrl("http://localhost:5000").build(); -// } -// -// public void submitCode(CodeSubmissionDto submissionDto) { -// Mono response = webClient.post() -// .uri("/submit-code") -// .bodyValue(submissionDto) -// .retrieve() -// .bodyToMono(String.class); -// -// String result = response.block(); -// if (result == null || result.contains("error")) { -// throw new RuntimeException("Failed to submit code"); // 이후에 변경 -// } -// } - -} \ No newline at end of file From ecefb9b29bcb9ddda175f9ecff4d1dc1cd2bc2c9 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 16 Jan 2024 18:40:46 +0900 Subject: [PATCH 21/46] =?UTF-8?q?feat:=20Sphere=20Engine=20API=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/controller/CompilerController.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 7e4c420..c4424f5 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -1,8 +1,5 @@ package com.api.TaveShot.domain.compiler.controller; -import com.api.TaveShot.domain.compiler.dto.CodeSubmissionDto; -import com.api.TaveShot.domain.compiler.dto.SubmissionResultDto; -import com.api.TaveShot.domain.compiler.service.CompilerService; import com.api.TaveShot.domain.compiler.dto.ProblemDto; import com.api.TaveShot.domain.compiler.service.ProblemService; import com.api.TaveShot.global.success.SuccessResponse; @@ -17,7 +14,6 @@ @RequestMapping("/api/compile") public class CompilerController { - private final CompilerService compilerService; private final ProblemService problemService; @GetMapping("/problems/{id}") @@ -26,14 +22,4 @@ public SuccessResponse getProblem(@PathVariable String id) { return new SuccessResponse<>(problem); } - @PostMapping("/submit") - public Mono submitCode(@RequestBody CodeSubmissionDto submission) { - return compilerService.compileAndJudge(submission); - } - -// @PostMapping("/submit") -// public SuccessResponse submitCode(@RequestBody CodeSubmissionDto submissionDto) { -// compilerService.submitCode(submissionDto); -// return new SuccessResponse<>("Submission successful"); // 이후에 변경 -// } } \ No newline at end of file From 5338084d35bd1b3ed23d42a7962e40357f436f5a Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 16 Jan 2024 23:36:09 +0900 Subject: [PATCH 22/46] =?UTF-8?q?feat:=20Python=EA=B3=BC=20API=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=EC=BD=94=EB=93=9C=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/dto/SubmissionRequestDto.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java new file mode 100644 index 0000000..69cebfe --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java @@ -0,0 +1,16 @@ +package com.api.TaveShot.domain.compiler.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class SubmissionRequestDto { + private String problemId; + private String language; + private String sourceCode; +} From c84249f9a6ad06a35d69cd74ddd65d3715fbe829 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 16 Jan 2024 23:36:30 +0900 Subject: [PATCH 23/46] =?UTF-8?q?feat:=20Python=EA=B3=BC=20API=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=EC=BD=94=EB=93=9C=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 14 ++++-- .../compiler/service/CompilerService.java | 43 +++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index c4424f5..930c102 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -1,13 +1,12 @@ package com.api.TaveShot.domain.compiler.controller; import com.api.TaveShot.domain.compiler.dto.ProblemDto; +import com.api.TaveShot.domain.compiler.dto.SubmissionRequestDto; +import com.api.TaveShot.domain.compiler.service.CompilerService; import com.api.TaveShot.domain.compiler.service.ProblemService; import com.api.TaveShot.global.success.SuccessResponse; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Mono; @RestController @RequiredArgsConstructor @@ -15,6 +14,7 @@ public class CompilerController { private final ProblemService problemService; + private final CompilerService compilerService; @GetMapping("/problems/{id}") public SuccessResponse getProblem(@PathVariable String id) { @@ -22,4 +22,12 @@ public SuccessResponse getProblem(@PathVariable String id) { return new SuccessResponse<>(problem); } + @PostMapping("/submit-code") + public String submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { + String problemId = submissionRequestDto.getProblemId(); + String language = submissionRequestDto.getLanguage(); + String sourceCode = submissionRequestDto.getSourceCode(); + + return compilerService.submitCode(problemId, language, sourceCode); + } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java new file mode 100644 index 0000000..f0d3291 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -0,0 +1,43 @@ +package com.api.TaveShot.domain.compiler.service; + +import org.springframework.stereotype.Service; +import org.springframework.http.*; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class CompilerService { + + private final String pythonServerUrl = "http://localhost:5000"; // 파이썬 서버 주소 + + public String submitCode(String problemId, String language, String sourceCode) { + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + // 사용자 입력 데이터를 JSON 형식으로 패키징 + Map requestData = new HashMap<>(); + requestData.put("problemId", problemId); + requestData.put("language", language); + requestData.put("sourceCode", sourceCode); + + HttpEntity> requestEntity = new HttpEntity<>(requestData, headers); + + // 파이썬 서버에 POST 요청 보내기 + ResponseEntity responseEntity = restTemplate.exchange( + pythonServerUrl + "/submit-code", + HttpMethod.POST, + requestEntity, + String.class); + + if (responseEntity.getStatusCode() == HttpStatus.OK) { + return responseEntity.getBody(); + } else { + return "Error occurred while submitting code."; + } + } + +} From 63d70bf904275c2980e461f87872926ac7d4d1c9 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 17 Jan 2024 23:36:21 +0900 Subject: [PATCH 24/46] =?UTF-8?q?feat:=20Python=20Flask=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 16 +++--- .../compiler/service/CompilerService.java | 50 +++++++++---------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 930c102..3352469 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -8,6 +8,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.util.Map; + @RestController @RequiredArgsConstructor @RequestMapping("/api/compile") @@ -22,12 +24,12 @@ public SuccessResponse getProblem(@PathVariable String id) { return new SuccessResponse<>(problem); } - @PostMapping("/submit-code") - public String submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { - String problemId = submissionRequestDto.getProblemId(); - String language = submissionRequestDto.getLanguage(); - String sourceCode = submissionRequestDto.getSourceCode(); - - return compilerService.submitCode(problemId, language, sourceCode); + @PostMapping("/submit") + public String submitCode(@RequestBody Map request) { + return compilerService.submitCode( + request.get("problemId"), + request.get("language"), + request.get("sourceCode") + ); } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index f0d3291..21c96f3 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,43 +1,39 @@ package com.api.TaveShot.domain.compiler.service; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; -import org.springframework.http.*; import org.springframework.web.client.RestTemplate; - import java.util.HashMap; import java.util.Map; @Service public class CompilerService { - private final String pythonServerUrl = "http://localhost:5000"; // 파이썬 서버 주소 - public String submitCode(String problemId, String language, String sourceCode) { RestTemplate restTemplate = new RestTemplate(); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - - // 사용자 입력 데이터를 JSON 형식으로 패키징 - Map requestData = new HashMap<>(); - requestData.put("problemId", problemId); - requestData.put("language", language); - requestData.put("sourceCode", sourceCode); - - HttpEntity> requestEntity = new HttpEntity<>(requestData, headers); - - // 파이썬 서버에 POST 요청 보내기 - ResponseEntity responseEntity = restTemplate.exchange( - pythonServerUrl + "/submit-code", - HttpMethod.POST, - requestEntity, - String.class); - - if (responseEntity.getStatusCode() == HttpStatus.OK) { - return responseEntity.getBody(); - } else { - return "Error occurred while submitting code."; + String submitUrl = "http://localhost:5000/submitCode"; + String resultUrl = "http://localhost:5000/result/"; + + // 요청 보내고 submission_id 받기 + Map requestMap = new HashMap<>(); + requestMap.put("problemId", problemId); + requestMap.put("language", language); + requestMap.put("sourceCode", sourceCode); + + ResponseEntity submitResponse = restTemplate.postForEntity(submitUrl, requestMap, Map.class); + String submissionId = (String) submitResponse.getBody().get("submission_id"); + + String result = "결과 처리 중"; + while (result.equals("결과 처리 중")) { + ResponseEntity resultResponse = restTemplate.getForEntity(resultUrl + submissionId, Map.class); + result = (String) resultResponse.getBody().get("result"); + try { + Thread.sleep(2000); // 2초 간격으로 확인 + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } + return result; } } From 1e8875aef542c27e06e8d947db03852843cfc4fd Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Thu, 18 Jan 2024 16:09:33 +0900 Subject: [PATCH 25/46] =?UTF-8?q?refactor:=20SubmissionRequestDto=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=9C=20=EC=BD=94=EB=93=9C=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/controller/CompilerController.java | 8 ++------ .../domain/compiler/service/CompilerService.java | 13 ++++--------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 3352469..2d7ffaf 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -25,11 +25,7 @@ public SuccessResponse getProblem(@PathVariable String id) { } @PostMapping("/submit") - public String submitCode(@RequestBody Map request) { - return compilerService.submitCode( - request.get("problemId"), - request.get("language"), - request.get("sourceCode") - ); + public String submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { + return compilerService.submitCode(submissionRequestDto); } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index 21c96f3..c08ef5c 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,5 +1,6 @@ package com.api.TaveShot.domain.compiler.service; +import com.api.TaveShot.domain.compiler.dto.SubmissionRequestDto; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @@ -9,18 +10,13 @@ @Service public class CompilerService { - public String submitCode(String problemId, String language, String sourceCode) { + public String submitCode(SubmissionRequestDto submissionRequestDto) { + RestTemplate restTemplate = new RestTemplate(); String submitUrl = "http://localhost:5000/submitCode"; String resultUrl = "http://localhost:5000/result/"; - // 요청 보내고 submission_id 받기 - Map requestMap = new HashMap<>(); - requestMap.put("problemId", problemId); - requestMap.put("language", language); - requestMap.put("sourceCode", sourceCode); - - ResponseEntity submitResponse = restTemplate.postForEntity(submitUrl, requestMap, Map.class); + ResponseEntity submitResponse = restTemplate.postForEntity(submitUrl, submissionRequestDto, Map.class); String submissionId = (String) submitResponse.getBody().get("submission_id"); String result = "결과 처리 중"; @@ -35,5 +31,4 @@ public String submitCode(String problemId, String language, String sourceCode) { } return result; } - } From 9f16a065123308872b33a40e10d65a8f71f52989 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Fri, 19 Jan 2024 21:57:16 +0900 Subject: [PATCH 26/46] =?UTF-8?q?feat:=20problemUrl=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/api/TaveShot/domain/compiler/dto/ProblemDto.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 98b4a8f..4fd7527 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -66,9 +66,4 @@ public String getSampleOutput(){ return sampleOutput; } - public String getProblemUrl(){ - return "https://www.acmicpc.net/problem/" + this.ID; - } - - } \ No newline at end of file From 76799f2f406084f31cdee8e12f4c7341047abc65 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sat, 20 Jan 2024 13:56:48 +0900 Subject: [PATCH 27/46] =?UTF-8?q?refactor:=20submitCode=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20SuccessResponse=EC=9C=BC=EB=A1=9C=20=EA=B0=90?= =?UTF-8?q?=EC=8B=B8=EA=B8=B0=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/controller/CompilerController.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 2d7ffaf..14c07e2 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -5,7 +5,13 @@ import com.api.TaveShot.domain.compiler.service.CompilerService; import com.api.TaveShot.domain.compiler.service.ProblemService; import com.api.TaveShot.global.success.SuccessResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import java.util.Map; @@ -25,7 +31,8 @@ public SuccessResponse getProblem(@PathVariable String id) { } @PostMapping("/submit") - public String submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { - return compilerService.submitCode(submissionRequestDto); + public SuccessResponse submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { + String result = compilerService.submitCode(submissionRequestDto); + return new SuccessResponse<>(result); } } \ No newline at end of file From 3e5728ee0ac7b1e779ffa09fa8271ddda53f1fab Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sat, 20 Jan 2024 14:04:55 +0900 Subject: [PATCH 28/46] =?UTF-8?q?feat:=20Swagger=20API=20documentation=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/controller/CompilerController.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 14c07e2..61672c8 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -24,12 +24,25 @@ public class CompilerController { private final ProblemService problemService; private final CompilerService compilerService; + @Operation(summary = "문제 정보 가져오기", description = "해당 문제 번호의 문제 정보들을 보여줍니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "문제 정보 가져오기 성공", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ProblemDto.class))) + }) @GetMapping("/problems/{id}") public SuccessResponse getProblem(@PathVariable String id) { ProblemDto problem = problemService.getProblemById(id); return new SuccessResponse<>(problem); } + @Operation(summary = "코드 컴파일링 및 채점", description = "해당 문제 풀이에 대한 채점 결과를 보여줍니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "채점 성공", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = String.class))) + }) + @PostMapping("/submit") public SuccessResponse submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { String result = compilerService.submitCode(submissionRequestDto); From 187d730071e7e47e24c99faa8d110fdecd1184cf Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sun, 21 Jan 2024 16:40:25 +0900 Subject: [PATCH 29/46] =?UTF-8?q?refactor:=20@NotEmpty,=20@Validated=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/compiler/controller/CompilerController.java | 3 ++- .../domain/compiler/dto/SubmissionRequestDto.java | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 61672c8..a40df17 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -12,6 +12,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.Map; @@ -44,7 +45,7 @@ public SuccessResponse getProblem(@PathVariable String id) { }) @PostMapping("/submit") - public SuccessResponse submitCode(@RequestBody SubmissionRequestDto submissionRequestDto) { + public SuccessResponse submitCode(@RequestBody @Validated SubmissionRequestDto submissionRequestDto) { String result = compilerService.submitCode(submissionRequestDto); return new SuccessResponse<>(result); } diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java index 69cebfe..8813608 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java @@ -1,5 +1,6 @@ package com.api.TaveShot.domain.compiler.dto; +import jakarta.validation.constraints.NotEmpty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -10,7 +11,14 @@ @NoArgsConstructor @Builder public class SubmissionRequestDto { + + @NotEmpty private String problemId; + + @NotEmpty private String language; + + @NotEmpty private String sourceCode; + } From 9d79066a18ab279250e5ade4c3a64c6dd0902986 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sun, 21 Jan 2024 17:58:31 +0900 Subject: [PATCH 30/46] =?UTF-8?q?refactor:=20=EC=A0=9C=EC=B6=9C=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EA=B0=80=20=EC=97=86=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EB=B2=88=ED=98=B8=EC=97=90=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EC=8B=9C(=EC=B1=84=EC=A0=90=20=EC=A4=80=EB=B9=84?= =?UTF-8?q?=20=EC=A4=91=EC=9D=B8=20=EB=AC=B8=EC=A0=9C)=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=A0=81=EC=9A=A9=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/service/CompilerService.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index c08ef5c..827f0d2 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,34 +1,43 @@ package com.api.TaveShot.domain.compiler.service; import com.api.TaveShot.domain.compiler.dto.SubmissionRequestDto; +import com.api.TaveShot.global.exception.ApiException; +import com.api.TaveShot.global.exception.ErrorType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; -import java.util.HashMap; import java.util.Map; @Service public class CompilerService { - public String submitCode(SubmissionRequestDto submissionRequestDto) { + private static final String SUBMIT_CODE_URL = "http://localhost:5000/submitCode"; + private static final String RESULT_URL = "http://localhost:5000/result/"; + private static final int MAX_ATTEMPTS = 10; + private static final long SLEEP_TIME_MILLIS = 5000; + public String submitCode(SubmissionRequestDto submissionRequestDto) { RestTemplate restTemplate = new RestTemplate(); - String submitUrl = "http://localhost:5000/submitCode"; - String resultUrl = "http://localhost:5000/result/"; - ResponseEntity submitResponse = restTemplate.postForEntity(submitUrl, submissionRequestDto, Map.class); + ResponseEntity submitResponse = restTemplate.postForEntity(SUBMIT_CODE_URL, submissionRequestDto, Map.class); String submissionId = (String) submitResponse.getBody().get("submission_id"); String result = "결과 처리 중"; - while (result.equals("결과 처리 중")) { - ResponseEntity resultResponse = restTemplate.getForEntity(resultUrl + submissionId, Map.class); + int attempts = 0; + while (result.equals("결과 처리 중") && attempts < MAX_ATTEMPTS) { + ResponseEntity resultResponse = restTemplate.getForEntity(RESULT_URL + submissionId, Map.class); result = (String) resultResponse.getBody().get("result"); + if (result.contains("채점이 준비되지 않아, 코드를 제출할 수 없습니다.")) { + throw new ApiException(ErrorType._SUBMIT_PAGE_NOT_FOUND); + } try { - Thread.sleep(2000); // 2초 간격으로 확인 + Thread.sleep(SLEEP_TIME_MILLIS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } + attempts++; } + return result; } } From cb9e42bedff176d41ad7f0a16fe4eb6b71f42d35 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sun, 21 Jan 2024 17:58:43 +0900 Subject: [PATCH 31/46] =?UTF-8?q?refactor:=20ErrorType=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TaveShot/domain/compiler/service/ProblemService.java | 2 +- .../java/com/api/TaveShot/global/exception/ErrorType.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java index 54d613c..a65eab8 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java @@ -59,7 +59,7 @@ public ProblemDto getProblemById(String id) { ProblemDto problem = problemMap.get(id); if (problem == null) { - throw new ApiException(ErrorType._SOLVED_INVALID_REQUEST); //에러 타입 수정 필요 + throw new ApiException(ErrorType._PROBLEM_NOT_FOUND); } return problemMap.get(id); } diff --git a/src/main/java/com/api/TaveShot/global/exception/ErrorType.java b/src/main/java/com/api/TaveShot/global/exception/ErrorType.java index 6375a55..40e7fd9 100644 --- a/src/main/java/com/api/TaveShot/global/exception/ErrorType.java +++ b/src/main/java/com/api/TaveShot/global/exception/ErrorType.java @@ -76,9 +76,13 @@ public enum ErrorType { _GITHUB_REPO_NOT_FOUND(NOT_FOUND, "GITHUB_4040", "요청한 GitHub 리포지토리를 찾을 수 없습니다."), _GITHUB_DESCRIPTION_NOT_FOUND(NOT_FOUND, "GITHUB_4041", "GitHub 리포지토리의 설명을 찾을 수 없습니다."), _GITHUB_SERVER_ERROR(INTERNAL_SERVER_ERROR, "GITHUB_5000", "GitHub API 서버에서 오류가 발생했습니다."), - _GITHUB_API_ERROR(INTERNAL_SERVER_ERROR, "GITHUB_5001", "GitHub API 요청 중 일반 오류가 발생했습니다."); + _GITHUB_API_ERROR(INTERNAL_SERVER_ERROR, "GITHUB_5001", "GitHub API 요청 중 일반 오류가 발생했습니다."), + // ------------------------------------------ Compile ------------------------------------------ + _PROBLEM_NOT_FOUND(NOT_FOUND, "PROBLEM_4040", "요청한 문제 번호를 찾을 수 없습니다."), + _SUBMIT_PAGE_NOT_FOUND(NOT_FOUND, "COMPILE_4040", "채점이 준비 되지 않아 코드를 제출할 수 없습니다.") + ; private final HttpStatus status; From 917d87944b074d393163599870ddde445a911c2b Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Sun, 21 Jan 2024 23:55:09 +0900 Subject: [PATCH 32/46] =?UTF-8?q?refactor:=20SUBMIT=5FPAGE=5FNOT=5FFOUND?= =?UTF-8?q?=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EB=82=B4=EC=9A=A9=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/api/TaveShot/global/exception/ErrorType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/global/exception/ErrorType.java b/src/main/java/com/api/TaveShot/global/exception/ErrorType.java index 40e7fd9..2816fa9 100644 --- a/src/main/java/com/api/TaveShot/global/exception/ErrorType.java +++ b/src/main/java/com/api/TaveShot/global/exception/ErrorType.java @@ -81,7 +81,7 @@ public enum ErrorType { // ------------------------------------------ Compile ------------------------------------------ _PROBLEM_NOT_FOUND(NOT_FOUND, "PROBLEM_4040", "요청한 문제 번호를 찾을 수 없습니다."), - _SUBMIT_PAGE_NOT_FOUND(NOT_FOUND, "COMPILE_4040", "채점이 준비 되지 않아 코드를 제출할 수 없습니다.") + _SUBMIT_PAGE_NOT_FOUND(NOT_FOUND, "COMPILE_4040", "아직 정답이 준비 되지 않아 코드를 제출할 수 없습니다.") ; From df41f6616a1c6c6102c706baa0ad014602e0011f Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Mon, 22 Jan 2024 12:47:21 +0900 Subject: [PATCH 33/46] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=B4=EC=8D=AC?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=B0=9B=EB=8A=94=20result=EC=97=90=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8=20=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=9E=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/TaveShot/domain/compiler/service/CompilerService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index 827f0d2..52eeeee 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -27,7 +27,7 @@ public String submitCode(SubmissionRequestDto submissionRequestDto) { while (result.equals("결과 처리 중") && attempts < MAX_ATTEMPTS) { ResponseEntity resultResponse = restTemplate.getForEntity(RESULT_URL + submissionId, Map.class); result = (String) resultResponse.getBody().get("result"); - if (result.contains("채점이 준비되지 않아, 코드를 제출할 수 없습니다.")) { + if (result.contains("정답이 준비되지 않아, 코드를 제출할 수 없습니다.")) { throw new ApiException(ErrorType._SUBMIT_PAGE_NOT_FOUND); } try { From 4d4ad4a0c8057b3de9e1d612a8abd5cd0df70d0d Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 23 Jan 2024 12:38:40 +0900 Subject: [PATCH 34/46] =?UTF-8?q?refactor:=20csv=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=84=20DB=EC=97=90=20=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94?= =?UTF-8?q?=20=EB=B0=A9=EB=B2=95=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/compiler/domain/BojProblem.java | 41 +++++++++++++ .../domain/compiler/dto/ProblemDto.java | 57 +++++-------------- 2 files changed, 54 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java new file mode 100644 index 0000000..84af2e0 --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java @@ -0,0 +1,41 @@ +package com.api.TaveShot.domain.compiler.domain; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.*; + +@Entity +@Table(name = "baekjoon_problems") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@AllArgsConstructor +@Builder +public class BojProblem { + @Id + @Column(name = "ID") + private String id; + + @Column(name = "Title") + private String title; + + @Column(name = "Description") + private String description; + + @Column(name = "InputDescription") + private String inputDescription; + + @Column(name = "OutputDescription") + private String outputDescription; + + @Column(name = "SampleInput") + private String sampleInput; + + @Column(name = "SampleOutput") + private String sampleOutput; + + @Column(name = "ImagesWithDescriptions") + private String imagesWithDescriptions; +} + diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 4fd7527..82a4fd4 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -11,59 +11,28 @@ @Builder public class ProblemDto { - @CsvBindByName(column = "ID") - private String ID; + @JsonProperty("ID") + private String id; - @CsvBindByName(column = "Title") - private String Title; + @JsonProperty("Title") + private String title; - @CsvBindByName(column = "Description") - private String Description; + @JsonProperty("Description") + private String description; - @CsvBindByName(column = "Input Description") + @JsonProperty("Input Description") private String inputDescription; - @CsvBindByName(column = "Output Description") + @JsonProperty("Output Description") private String outputDescription; - @CsvBindByName(column = "Sample Input") + @JsonProperty("Sample Input") private String sampleInput; - @CsvBindByName(column = "Sample Output") + @JsonProperty("Sample Output") private String sampleOutput; - @JsonRawValue - public String getID(){ - return ID; - } - @JsonRawValue - public String getTitle(){ - return Title; - } - - @JsonRawValue - public String getDescription(){ - return Description; - } - - @JsonRawValue - public String getInputDescription(){ - return inputDescription; - } - - @JsonRawValue - public String getOutputDescription(){ - return outputDescription; - } - - @JsonRawValue - public String getSampleInput(){ - return sampleInput; - } - - @JsonRawValue - public String getSampleOutput(){ - return sampleOutput; - } - + // JSON에 있는 "Images with Descriptions" 필드를 처리하기 위해 필드 추가 + @JsonProperty("Images with Descriptions") + private String imagesWithDescriptions; } \ No newline at end of file From 62c11dd34442edcfa5a818aa1c708c41ca41ed24 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 23 Jan 2024 12:40:46 +0900 Subject: [PATCH 35/46] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=82=B4=20csv=20=ED=8C=8C=EC=9D=BC=EC=9D=84=20cla?= =?UTF-8?q?ssPath=EB=A1=9C=20=EC=9D=BD=EC=96=B4=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20->=20DB=EC=97=90=EC=84=9C=20=EC=9D=BD?= =?UTF-8?q?=EC=96=B4=EC=98=A4=EB=8A=94=20=EB=B0=A9=EC=8B=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 2 - .../compiler/converter/ProblemConverter.java | 42 ++++++++++++ .../repository/ProblemRepository.java | 9 +++ .../compiler/service/ProblemService.java | 66 +++++-------------- 4 files changed, 66 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java create mode 100644 src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index a40df17..cba7045 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -15,8 +15,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.Map; - @RestController @RequiredArgsConstructor @RequestMapping("/api/compile") diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java new file mode 100644 index 0000000..2995b2e --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java @@ -0,0 +1,42 @@ +package com.api.TaveShot.domain.compiler.converter; + +import com.api.TaveShot.domain.compiler.domain.BojProblem; +import com.api.TaveShot.domain.compiler.dto.ProblemDto; +import org.springframework.stereotype.Component; + +@Component +public class ProblemConverter { + + public ProblemDto convertToDto(BojProblem bojProblem) { + if (bojProblem == null) { + return null; + } + + return ProblemDto.builder() + .id(bojProblem.getId()) + .title(bojProblem.getTitle()) + .description(bojProblem.getDescription()) + .inputDescription(bojProblem.getInputDescription()) + .outputDescription(bojProblem.getOutputDescription()) + .sampleInput(bojProblem.getSampleInput()) + .sampleOutput(bojProblem.getSampleOutput()) + .imagesWithDescriptions(bojProblem.getImagesWithDescriptions()) + .build(); + } + + public BojProblem convertToEntity(ProblemDto problemDto) { + if (problemDto == null) { + return null; + } + + return BojProblem.builder() + .id(problemDto.getId()) + .title(problemDto.getTitle()) + .description(problemDto.getDescription()) + .inputDescription(problemDto.getInputDescription()) + .outputDescription(problemDto.getOutputDescription()) + .sampleInput(problemDto.getSampleInput()) + .sampleOutput(problemDto.getSampleOutput()) + .build(); + } +} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java b/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java new file mode 100644 index 0000000..36dba8c --- /dev/null +++ b/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java @@ -0,0 +1,9 @@ +package com.api.TaveShot.domain.compiler.repository; + +import com.api.TaveShot.domain.compiler.domain.BojProblem; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProblemRepository extends JpaRepository { +} diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java index a65eab8..a9430ed 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java @@ -1,67 +1,31 @@ package com.api.TaveShot.domain.compiler.service; +import com.api.TaveShot.domain.compiler.converter.ProblemConverter; +import com.api.TaveShot.domain.compiler.domain.BojProblem; import com.api.TaveShot.domain.compiler.dto.ProblemDto; +import com.api.TaveShot.domain.compiler.repository.ProblemRepository; import com.api.TaveShot.global.exception.ApiException; import com.api.TaveShot.global.exception.ErrorType; -import com.opencsv.bean.CsvToBean; -import com.opencsv.bean.CsvToBeanBuilder; -import com.opencsv.bean.HeaderColumnNameMappingStrategy; -import jakarta.annotation.PostConstruct; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.apache.commons.io.input.BOMInputStream; + @Service public class ProblemService { - private Map problemMap; - - @PostConstruct - public void init() { - - Resource resource = new ClassPathResource("baekjoon_problems.csv"); - try (InputStream inputStream = resource.getInputStream(); - BOMInputStream bomInputStream = new BOMInputStream(inputStream); - Reader reader = new InputStreamReader(bomInputStream, StandardCharsets.UTF_8)) { - - - HeaderColumnNameMappingStrategy strategy = new HeaderColumnNameMappingStrategy<>(); - strategy.setType(ProblemDto.class); - - CsvToBean csvToBean = new CsvToBeanBuilder(reader) - .withMappingStrategy(strategy) - .build(); + private final ProblemRepository problemRepository; + private final ProblemConverter problemConverter; - List problems = csvToBean.parse(); - - - problemMap = problems.stream() - .filter(problem -> problem.getID() != null) - .collect(Collectors.toUnmodifiableMap( - ProblemDto::getID, - Function.identity() - )); - - } catch (Exception e) { - throw new ApiException(ErrorType._WEB_CLIENT_ERROR); - } + @Autowired + public ProblemService(ProblemRepository problemRepository, ProblemConverter problemConverter) { + this.problemRepository = problemRepository; + this.problemConverter = problemConverter; } + public ProblemDto getProblemById(String id) { - ProblemDto problem = problemMap.get(id); + BojProblem bojProblem = problemRepository.findById(id) + .orElseThrow(() -> new ApiException(ErrorType._PROBLEM_NOT_FOUND)); - if (problem == null) { - throw new ApiException(ErrorType._PROBLEM_NOT_FOUND); - } - return problemMap.get(id); + return problemConverter.convertToDto(bojProblem); } - } \ No newline at end of file From 8c7add65fef257f3fac0dc3f62c4bac04864eb20 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 23 Jan 2024 14:11:45 +0900 Subject: [PATCH 36/46] =?UTF-8?q?refactor:=20=EC=BB=AC=EB=9F=BC=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/compiler/domain/BojProblem.java | 27 ++++++++++--------- .../domain/compiler/dto/ProblemDto.java | 1 - 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java index 84af2e0..a9c1e2a 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java @@ -1,9 +1,6 @@ package com.api.TaveShot.domain.compiler.domain; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.*; @Entity @@ -13,29 +10,33 @@ @AllArgsConstructor @Builder public class BojProblem { + @Id - @Column(name = "ID") + @Column(name = "ID", columnDefinition = "TEXT") private String id; - @Column(name = "Title") + @Column(name = "Title", columnDefinition = "TEXT") private String title; + @Lob @Column(name = "Description") private String description; - @Column(name = "InputDescription") + @Lob + @Column(name = "Images with Descriptions") + private String imagesWithDescriptions; + + @Lob + @Column(name = "Input Description") private String inputDescription; - @Column(name = "OutputDescription") + @Column(name = "Output Description", columnDefinition = "TEXT") private String outputDescription; - @Column(name = "SampleInput") + @Column(name = "Sample Input", columnDefinition = "TEXT") private String sampleInput; - @Column(name = "SampleOutput") + @Column(name = "Sample Output", columnDefinition = "TEXT") private String sampleOutput; - @Column(name = "ImagesWithDescriptions") - private String imagesWithDescriptions; } - diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 82a4fd4..0f63f25 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -32,7 +32,6 @@ public class ProblemDto { @JsonProperty("Sample Output") private String sampleOutput; - // JSON에 있는 "Images with Descriptions" 필드를 처리하기 위해 필드 추가 @JsonProperty("Images with Descriptions") private String imagesWithDescriptions; } \ No newline at end of file From 56c4a23c7eb8424baf1ba0f7db3414edcf99a8f7 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 23 Jan 2024 16:17:54 +0900 Subject: [PATCH 37/46] =?UTF-8?q?feat:=20Images=20with=20Descriptions=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=20=EC=82=AD=EC=A0=9C=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TaveShot/domain/compiler/converter/ProblemConverter.java | 1 - .../com/api/TaveShot/domain/compiler/domain/BojProblem.java | 4 ---- .../java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java | 2 -- 3 files changed, 7 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java index 2995b2e..b9269d6 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java @@ -20,7 +20,6 @@ public ProblemDto convertToDto(BojProblem bojProblem) { .outputDescription(bojProblem.getOutputDescription()) .sampleInput(bojProblem.getSampleInput()) .sampleOutput(bojProblem.getSampleOutput()) - .imagesWithDescriptions(bojProblem.getImagesWithDescriptions()) .build(); } diff --git a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java index a9c1e2a..4ff2c17 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java @@ -22,10 +22,6 @@ public class BojProblem { @Column(name = "Description") private String description; - @Lob - @Column(name = "Images with Descriptions") - private String imagesWithDescriptions; - @Lob @Column(name = "Input Description") private String inputDescription; diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 0f63f25..8b5d2dd 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -32,6 +32,4 @@ public class ProblemDto { @JsonProperty("Sample Output") private String sampleOutput; - @JsonProperty("Images with Descriptions") - private String imagesWithDescriptions; } \ No newline at end of file From d3de18b94b258e4a38094cfacdf7f0e462199e8f Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 23 Jan 2024 19:02:20 +0900 Subject: [PATCH 38/46] =?UTF-8?q?feat:=20=EB=B0=B1=EC=A4=80=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A7=81=ED=81=AC=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80,?= =?UTF-8?q?=20=EC=BB=B4=ED=8C=8C=EC=9D=BC=EB=A7=81=20=EB=B0=8F=20=EC=B1=84?= =?UTF-8?q?=EC=A0=90=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/compiler/controller/CompilerController.java | 9 +++------ .../com/api/TaveShot/domain/compiler/dto/ProblemDto.java | 4 ++++ .../domain/compiler/dto/SubmissionRequestDto.java | 4 ++-- .../domain/compiler/service/CompilerService.java | 8 ++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index cba7045..8187546 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -1,8 +1,6 @@ package com.api.TaveShot.domain.compiler.controller; import com.api.TaveShot.domain.compiler.dto.ProblemDto; -import com.api.TaveShot.domain.compiler.dto.SubmissionRequestDto; -import com.api.TaveShot.domain.compiler.service.CompilerService; import com.api.TaveShot.domain.compiler.service.ProblemService; import com.api.TaveShot.global.success.SuccessResponse; import io.swagger.v3.oas.annotations.Operation; @@ -12,7 +10,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @RestController @@ -21,7 +18,7 @@ public class CompilerController { private final ProblemService problemService; - private final CompilerService compilerService; + //private final CompilerService compilerService; @Operation(summary = "문제 정보 가져오기", description = "해당 문제 번호의 문제 정보들을 보여줍니다.") @ApiResponses(value = { @@ -35,7 +32,7 @@ public SuccessResponse getProblem(@PathVariable String id) { return new SuccessResponse<>(problem); } - @Operation(summary = "코드 컴파일링 및 채점", description = "해당 문제 풀이에 대한 채점 결과를 보여줍니다.") + /*@Operation(summary = "코드 컴파일링 및 채점", description = "해당 문제 풀이에 대한 채점 결과를 보여줍니다.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "채점 성공", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, @@ -46,5 +43,5 @@ public SuccessResponse getProblem(@PathVariable String id) { public SuccessResponse submitCode(@RequestBody @Validated SubmissionRequestDto submissionRequestDto) { String result = compilerService.submitCode(submissionRequestDto); return new SuccessResponse<>(result); - } + }*/ } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 8b5d2dd..4cb5b81 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -32,4 +32,8 @@ public class ProblemDto { @JsonProperty("Sample Output") private String sampleOutput; + public String getProblemUrl(){ + return "https://www.acmicpc.net/problem/" + this.id; + } + } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java index 8813608..6034736 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/SubmissionRequestDto.java @@ -1,4 +1,4 @@ -package com.api.TaveShot.domain.compiler.dto; +/*package com.api.TaveShot.domain.compiler.dto; import jakarta.validation.constraints.NotEmpty; import lombok.AllArgsConstructor; @@ -21,4 +21,4 @@ public class SubmissionRequestDto { @NotEmpty private String sourceCode; -} +}*/ diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java index 52eeeee..07855bb 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/CompilerService.java @@ -1,4 +1,4 @@ -package com.api.TaveShot.domain.compiler.service; +/*package com.api.TaveShot.domain.compiler.service; import com.api.TaveShot.domain.compiler.dto.SubmissionRequestDto; import com.api.TaveShot.global.exception.ApiException; @@ -11,8 +11,8 @@ @Service public class CompilerService { - private static final String SUBMIT_CODE_URL = "http://localhost:5000/submitCode"; - private static final String RESULT_URL = "http://localhost:5000/result/"; + private static final String SUBMIT_CODE_URL = "http://43.202.52.177/submitCode"; + private static final String RESULT_URL = "http://43.202.52.177/result/"; private static final int MAX_ATTEMPTS = 10; private static final long SLEEP_TIME_MILLIS = 5000; @@ -40,4 +40,4 @@ public String submitCode(SubmissionRequestDto submissionRequestDto) { return result; } -} +}*/ From 7c1bc6fda92bc02155491a2e457e4eb3a8bd3962 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Tue, 23 Jan 2024 20:35:20 +0900 Subject: [PATCH 39/46] =?UTF-8?q?refactor:=20problemUrl=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/api/TaveShot/domain/compiler/dto/ProblemDto.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java index 4cb5b81..71b5b70 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/dto/ProblemDto.java @@ -32,8 +32,11 @@ public class ProblemDto { @JsonProperty("Sample Output") private String sampleOutput; + private String problemUrl; + public String getProblemUrl(){ - return "https://www.acmicpc.net/problem/" + this.id; + this.problemUrl = "https://www.acmicpc.net/problem/" + this.id; + return this.problemUrl; } } \ No newline at end of file From f1885109459f539f0549b9b3fb9ad2c497725301 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 13:27:52 +0900 Subject: [PATCH 40/46] =?UTF-8?q?refactor:=20table=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/api/TaveShot/domain/compiler/domain/BojProblem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java index 4ff2c17..4c3680b 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/domain/BojProblem.java @@ -4,7 +4,7 @@ import lombok.*; @Entity -@Table(name = "baekjoon_problems") +@Table(name = "bog_problems") @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @AllArgsConstructor From 8e14bbf3c46ad883fc393c6d13721ab98b53b08f Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 20:32:02 +0900 Subject: [PATCH 41/46] =?UTF-8?q?refactor:=20Converter=20static=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TaveShot/domain/compiler/converter/ProblemConverter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java index b9269d6..73f0084 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java @@ -7,7 +7,7 @@ @Component public class ProblemConverter { - public ProblemDto convertToDto(BojProblem bojProblem) { + public static ProblemDto convertToDto(BojProblem bojProblem) { if (bojProblem == null) { return null; } @@ -23,7 +23,7 @@ public ProblemDto convertToDto(BojProblem bojProblem) { .build(); } - public BojProblem convertToEntity(ProblemDto problemDto) { + public static BojProblem convertToEntity(ProblemDto problemDto) { if (problemDto == null) { return null; } From 46dabbd8af70586e3b4aaab22beebc5303a37680 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 20:39:36 +0900 Subject: [PATCH 42/46] =?UTF-8?q?refactor:=20@Repository=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TaveShot/domain/compiler/repository/ProblemRepository.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java b/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java index 36dba8c..f4e6633 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/repository/ProblemRepository.java @@ -2,8 +2,5 @@ import com.api.TaveShot.domain.compiler.domain.BojProblem; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository public interface ProblemRepository extends JpaRepository { } From 45906de973260496673149a62bcb0d7e57a8f374 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 21:29:25 +0900 Subject: [PATCH 43/46] =?UTF-8?q?refactor:=20Optional=EB=A1=9C?= =?UTF-8?q?=20=EA=B0=90=EC=8B=B8=EC=84=9C=20=EB=B0=98=ED=99=98=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CompilerController.java | 8 +-- .../compiler/converter/ProblemConverter.java | 54 +++++++++---------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index 8187546..a9e52ac 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @@ -27,9 +28,10 @@ public class CompilerController { schema = @Schema(implementation = ProblemDto.class))) }) @GetMapping("/problems/{id}") - public SuccessResponse getProblem(@PathVariable String id) { - ProblemDto problem = problemService.getProblemById(id); - return new SuccessResponse<>(problem); + public ResponseEntity> getProblem(@PathVariable String id) { + return problemService.getProblemById(id) + .map(problemDto -> ResponseEntity.ok(new SuccessResponse<>(problemDto))) + .orElseGet(() -> ResponseEntity.notFound().build()); } /*@Operation(summary = "코드 컴파일링 및 채점", description = "해당 문제 풀이에 대한 채점 결과를 보여줍니다.") diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java index 73f0084..9332995 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java @@ -4,38 +4,34 @@ import com.api.TaveShot.domain.compiler.dto.ProblemDto; import org.springframework.stereotype.Component; +import java.util.Optional; + @Component public class ProblemConverter { - public static ProblemDto convertToDto(BojProblem bojProblem) { - if (bojProblem == null) { - return null; - } - - return ProblemDto.builder() - .id(bojProblem.getId()) - .title(bojProblem.getTitle()) - .description(bojProblem.getDescription()) - .inputDescription(bojProblem.getInputDescription()) - .outputDescription(bojProblem.getOutputDescription()) - .sampleInput(bojProblem.getSampleInput()) - .sampleOutput(bojProblem.getSampleOutput()) - .build(); + public static Optional convertToDto(BojProblem bojProblem) { + return Optional.ofNullable(bojProblem) + .map(bp -> ProblemDto.builder() + .id(bp.getId()) + .title(bp.getTitle()) + .description(bp.getDescription()) + .inputDescription(bp.getInputDescription()) + .outputDescription(bp.getOutputDescription()) + .sampleInput(bp.getSampleInput()) + .sampleOutput(bp.getSampleOutput()) + .build()); } - public static BojProblem convertToEntity(ProblemDto problemDto) { - if (problemDto == null) { - return null; - } - - return BojProblem.builder() - .id(problemDto.getId()) - .title(problemDto.getTitle()) - .description(problemDto.getDescription()) - .inputDescription(problemDto.getInputDescription()) - .outputDescription(problemDto.getOutputDescription()) - .sampleInput(problemDto.getSampleInput()) - .sampleOutput(problemDto.getSampleOutput()) - .build(); + public static Optional convertToEntity(ProblemDto problemDto) { + return Optional.ofNullable(problemDto) + .map(pd -> BojProblem.builder() + .id(pd.getId()) + .title(pd.getTitle()) + .description(pd.getDescription()) + .inputDescription(pd.getInputDescription()) + .outputDescription(pd.getOutputDescription()) + .sampleInput(pd.getSampleInput()) + .sampleOutput(pd.getSampleOutput()) + .build()); } -} +} \ No newline at end of file From b7d9a877f1b860140f091cf976d29524fb14d8df Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 21:30:05 +0900 Subject: [PATCH 44/46] =?UTF-8?q?refactor:=20@RequiredArgsConstructor=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20@Autowired=20=EC=A0=9C=EA=B1=B0=20(?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=201=EA=B0=9C)=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compiler/service/ProblemService.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java index a9430ed..a57430a 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java @@ -6,26 +6,22 @@ import com.api.TaveShot.domain.compiler.repository.ProblemRepository; import com.api.TaveShot.global.exception.ApiException; import com.api.TaveShot.global.exception.ErrorType; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Optional; + @Service +@RequiredArgsConstructor public class ProblemService { private final ProblemRepository problemRepository; - private final ProblemConverter problemConverter; - - @Autowired - public ProblemService(ProblemRepository problemRepository, ProblemConverter problemConverter) { - this.problemRepository = problemRepository; - this.problemConverter = problemConverter; - } - public ProblemDto getProblemById(String id) { - BojProblem bojProblem = problemRepository.findById(id) + public Optional getProblemById(String id) { + return problemRepository.findById(id) + .map(ProblemConverter::convertToDto) .orElseThrow(() -> new ApiException(ErrorType._PROBLEM_NOT_FOUND)); - - return problemConverter.convertToDto(bojProblem); } } \ No newline at end of file From 0619ee117fda3a91026a32e288d36c89fdf18bfd Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 22:57:16 +0900 Subject: [PATCH 45/46] =?UTF-8?q?refactor:=20Optional=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EC=B6=B0=20=EC=88=98=EC=A0=95=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/compiler/controller/CompilerController.java | 7 +++---- .../TaveShot/domain/compiler/service/ProblemService.java | 7 ++++--- .../java/com/api/TaveShot/global/exception/ErrorType.java | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java index a9e52ac..255f007 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/controller/CompilerController.java @@ -28,10 +28,9 @@ public class CompilerController { schema = @Schema(implementation = ProblemDto.class))) }) @GetMapping("/problems/{id}") - public ResponseEntity> getProblem(@PathVariable String id) { - return problemService.getProblemById(id) - .map(problemDto -> ResponseEntity.ok(new SuccessResponse<>(problemDto))) - .orElseGet(() -> ResponseEntity.notFound().build()); + public SuccessResponse getProblem(@PathVariable String id) { + ProblemDto problemDto = problemService.getProblemById(id); + return new SuccessResponse<>(problemDto); } /*@Operation(summary = "코드 컴파일링 및 채점", description = "해당 문제 풀이에 대한 채점 결과를 보여줍니다.") diff --git a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java index a57430a..43b1900 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/service/ProblemService.java @@ -19,9 +19,10 @@ public class ProblemService { private final ProblemRepository problemRepository; - public Optional getProblemById(String id) { - return problemRepository.findById(id) - .map(ProblemConverter::convertToDto) + public ProblemDto getProblemById(String id) { + BojProblem bojProblem = problemRepository.findById(id) .orElseThrow(() -> new ApiException(ErrorType._PROBLEM_NOT_FOUND)); + + return ProblemConverter.convertToDto(bojProblem).orElseThrow(() -> new ApiException(ErrorType._PROBLEM_CONVERSION_ERROR)); } } \ No newline at end of file diff --git a/src/main/java/com/api/TaveShot/global/exception/ErrorType.java b/src/main/java/com/api/TaveShot/global/exception/ErrorType.java index d05d982..4f5b8c3 100644 --- a/src/main/java/com/api/TaveShot/global/exception/ErrorType.java +++ b/src/main/java/com/api/TaveShot/global/exception/ErrorType.java @@ -81,7 +81,8 @@ public enum ErrorType { // ------------------------------------------ Compile ------------------------------------------ _PROBLEM_NOT_FOUND(NOT_FOUND, "PROBLEM_4040", "요청한 문제 번호를 찾을 수 없습니다."), - _SUBMIT_PAGE_NOT_FOUND(NOT_FOUND, "COMPILE_4040", "아직 정답이 준비 되지 않아 코드를 제출할 수 없습니다.") + _SUBMIT_PAGE_NOT_FOUND(NOT_FOUND, "COMPILE_4040", "아직 정답이 준비 되지 않아 코드를 제출할 수 없습니다."), + _PROBLEM_CONVERSION_ERROR(INTERNAL_SERVER_ERROR, "PROBLEM_5002", "문제 정보 변환 중 오류가 발생했습니다.") ; From 65fedc2a7ebac8ac6d26b4478c43add4276aa113 Mon Sep 17 00:00:00 2001 From: hyeonbin Date: Wed, 24 Jan 2024 22:57:32 +0900 Subject: [PATCH 46/46] =?UTF-8?q?refactor:=20@Component=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/TaveShot/domain/compiler/converter/ProblemConverter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java index 9332995..0df502f 100644 --- a/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java +++ b/src/main/java/com/api/TaveShot/domain/compiler/converter/ProblemConverter.java @@ -6,7 +6,6 @@ import java.util.Optional; -@Component public class ProblemConverter { public static Optional convertToDto(BojProblem bojProblem) {