Skip to content

Commit

Permalink
Merge pull request #335 from SWM-NM/feat/#331
Browse files Browse the repository at this point in the history
♻️ [FIX] 기존 시험 종료 오류 문제 및 테스트 시작 리펙토링 #331
  • Loading branch information
aj4941 authored Sep 21, 2023
2 parents e2e6707 + a4728a6 commit db2bde4
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public class SolvedCheckService {
public List<AttemptProblemDto> isSolvedCheck(TestCheckDto testCheckDto) {
Long testId = testCheckDto.getTestId();
String bojId = testCheckDto.getBojId();
checkAttemptedProblemResult(testId, bojId);
Tests test = testRepository.findById(testId)
.orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));
checkAttemptedProblemResult(test, bojId);
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(testId);
List<AttemptProblemDto> attemptProblemDtos = new ArrayList<>();
long number = 1;
Expand All @@ -51,9 +53,8 @@ public List<AttemptProblemDto> isSolvedCheck(TestCheckDto testCheckDto) {
}

@Transactional
public void checkAttemptedProblemResult(Long testId, String bojId) {
Tests test = testRepository.findById(testId).orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(testId);
public void checkAttemptedProblemResult(Tests test, String bojId) {
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(test.getTestId());

attemptProblems.stream()
.filter(attemptProblem -> !attemptProblem.getIsSolved())
Expand All @@ -68,6 +69,7 @@ public void checkAttemptedProblemResult(Long testId, String bojId) {
});
}


public boolean isSolvedProblem(AttemptProblem attemptProblem, String bojId) {
Problem problem = attemptProblem.getProblem();
Long bojProblemId = problem.getBojProblemId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ public class CalculateRatingService {

private final TestRepository testRepository;
@Transactional
public Long calculateTestRating(Member member, Long testId) {
public Long calculateTestRating(Member member, Tests test) {
List<AttemptProblem> attemptProblems
= attemptProblemRepository.findAttemptProblemsByTest_TestId(testId);
Tests test = testRepository.findById(testId)
.orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));
= attemptProblemRepository.findAttemptProblemsByTest_TestId(test.getTestId());
Integer problemCount = test.getProblemCount();
long rating = getRating(problemCount);
long addRating = 0L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,28 @@ public class TestExitService {
private final CalculateRatingService calculateRatingService;

private final SolvedCheckService solvedCheckService;

//Controller에서 사용되는 것
public List<AttemptProblemDto> testExit(TestCheckDto testCheckDto)
{
Long memberId = SecurityUtils.getCurrentMemberId();
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MorandiException(AuthErrorCode.MEMBER_NOT_FOUND));
Tests test = testRepository.findById(testCheckDto.getTestId())
.orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));
TestType testType = testTypeRepository.findTestTypeByTestTypename(test.getTestTypename())
.orElseThrow(() -> new MorandiException(TestTypeErrorCode.TEST_TYPE_NOT_FOUND));
return testExit(testCheckDto,member,test,testType);
}

@Transactional
public List<AttemptProblemDto> testExit(TestCheckDto testCheckDto) {
Long testId = testCheckDto.getTestId();
public List<AttemptProblemDto> testExit(TestCheckDto testCheckDto,Member member,Tests test,TestType testType) {
String bojId = testCheckDto.getBojId();
Long testTypeId = testCheckDto.getTestTypeId();

solvedCheckService.checkAttemptedProblemResult(testId, bojId);
saveTestResult(testId, testTypeId);
solvedCheckService.checkAttemptedProblemResult(test, bojId);
saveTestResult(member,test, testType);

List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(testId);
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(test.getTestId());

List<AttemptProblemDto> attemptProblemDtos = new ArrayList<>();
long number = 1;
Expand All @@ -65,13 +77,9 @@ public List<AttemptProblemDto> testExit(TestCheckDto testCheckDto) {
}

@Transactional
public void saveTestResult(Long testId, Long testTypeId) {
Long memberId = SecurityUtils.getCurrentMemberId();
Member member = memberRepository.findById(memberId).orElseThrow(() -> new MorandiException(AuthErrorCode.MEMBER_NOT_FOUND));
Tests test = testRepository.findById(testId).orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));
TestType testType = testTypeRepository.findById(testTypeId).orElseThrow(() -> new MorandiException(TestTypeErrorCode.TEST_TYPE_NOT_FOUND));
public void saveTestResult(Member member,Tests test, TestType testType) {
test.setTestStatus(TestStatus.COMPLETED);
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAllByTest_TestId(testId);
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAllByTest_TestId(test.getTestId());
long correct = attemptProblems.stream()
.filter(AttemptProblem::getIsSolved)
.count();
Expand All @@ -81,8 +89,13 @@ public void saveTestResult(Long testId, Long testTypeId) {
testType.updateAverageCorrectAnswerRate(correct / total);

// 테스트 레이팅 저장
test.setTestRating(calculateRatingService.calculateTestRating(member, testId));
test.setTestRating(calculateRatingService.calculateTestRating(member, test));

member.setCurrentTestId(-1L);

// 테스트 결과 저장
testTypeRepository.save(testType);
testRepository.save(test);
memberRepository.save(member);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import org.springframework.data.jpa.repository.JpaRepository;
import swm_nm.morandi.domain.testExit.entity.TestType;

public interface TestTypeRepository extends JpaRepository<TestType, Long> {
import java.util.Optional;

public interface TestTypeRepository extends JpaRepository<TestType, Long> {
Optional<TestType> findTestTypeByTestTypename(String testTypename);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,9 @@ public class AddTestService {

private final TestRepository testRepository;

private final TestTypeRepository testTypeRepository;

private final MemberRepository memberRepository;

private final TestScheduler testScheduler;
@Transactional
public Tests startTestByTestTypeId(TestType testType, Member member) {

Tests test = Tests.builder()
.testDate(LocalDateTime.now()) // 테스트가 시작된 시간
.testTime(testType.getTestTime())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@
@Slf4j
public class SaveProblemsService {

private final MemberRepository memberRepository;

private final TestRepository testRepository;

private final ProblemRepository problemRepository;

private final AttemptProblemRepository attemptProblemRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package swm_nm.morandi.domain.testStart.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import swm_nm.morandi.domain.member.entity.Member;
import swm_nm.morandi.domain.testDuring.dto.TestCheckDto;
import swm_nm.morandi.domain.testExit.entity.TestType;
import swm_nm.morandi.domain.testExit.entity.Tests;
import swm_nm.morandi.domain.testExit.service.TestExitService;
import swm_nm.morandi.domain.testInfo.repository.TestRepository;
import swm_nm.morandi.domain.testInfo.repository.TestTypeRepository;
import swm_nm.morandi.global.exception.MorandiException;
import swm_nm.morandi.global.exception.errorcode.TestErrorCode;
import swm_nm.morandi.global.exception.errorcode.TestTypeErrorCode;

import java.time.Duration;
import java.time.LocalDateTime;

@Service
@RequiredArgsConstructor
public class TestProgressCheckService {

private final TestRepository testRepository;
private final TestTypeRepository testTypeRepository;
private final TestExitService testExitService;

private void extracted(Tests test) {
Duration duration = Duration.between(test.getTestDate(), LocalDateTime.now());
test.setRemainingTime(test.getTestTime() * 60 - duration.getSeconds());
}

private void extracted(TestType testType, Member member, Tests test) {
TestCheckDto testCheckDto = TestCheckDto.builder()
.testId(test.getTestId())
.testTypeId(testType.getTestTypeId())
.bojId(member.getBojId())
.build();
testExitService.testExit(testCheckDto,member,test,testType);
}

//TODO Redis 이용하여
// 현재 테스트가 진행중인지 확인하도록
public Tests isTestinProgress(Member member){
if (member.getCurrentTestId() == null)
member.setCurrentTestId(-1L);

// 현재 테스트가 진행중이라면
if (member.getCurrentTestId() != -1) {
Long currentTestId = member.getCurrentTestId();
Tests test = testRepository.findById(currentTestId).orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));

// 테스트 시작 시간과 현재 시간을 비교하여 남은 시간 계산
extracted(test);

if (test.getRemainingTime() > 0) { // 시간이 남았을경우 진행중인 테스트 반환
return test;//getTestStartResponseDto(currentTestId, test);
}
else { // 시간이 마감된 테스트 종료
TestType testType = testTypeRepository.findTestTypeByTestTypename(test.getTestTypename())
.orElseThrow(() -> new MorandiException(TestTypeErrorCode.TEST_TYPE_NOT_FOUND));
extracted(testType, member, test);
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,70 +40,56 @@
public class TestStartUseCase {

private final AddTestService addTestService;

private final GetProblemsService getProblemsService;

private final SaveProblemsService saveProblemsService;

private final TempCodeInitializer tempCodeInitializer;
private final MemberInfoService memberInfoService;
private final TestTypeRepository testTypeRepository;
private final TestProgressCheckService testProgressCheckService;

private final MemberRepository memberRepository;

private final TestRepository testRepository;

private final AttemptProblemRepository attemptProblemRepository;

private final ObjectMapper objectMapper;

private final MemberInfoService memberInfoService;

private final TestExitService testExitService;
//이미 테스트 중인지 확인

private final TestTypeRepository testTypeRepository;

public TestStartResponseDto getTestStartsData(Long testTypeId) {
Long memberId = SecurityUtils.getCurrentMemberId();
Member member = memberRepository.findById(memberId).orElseThrow(
() -> new MorandiException(MemberErrorCode.MEMBER_NOT_FOUND));

//TODO Redis 이용하여
// 현재 테스트가 진행중인지 확인하도록
if (member.getCurrentTestId() == null)
member.setCurrentTestId(-1L);

// 현재 테스트가 진행중이라면
if (member.getCurrentTestId() != -1) {
Long currentTestId = member.getCurrentTestId();
Tests test = testRepository.findById(currentTestId).orElseThrow(() -> new MorandiException(TestErrorCode.TEST_NOT_FOUND));

// 테스트 시작 시간과 현재 시간을 비교하여 남은 시간 계산
extracted(test);

if (test.getRemainingTime() > 0) { // 시간이 남았을경우 진행중인 테스트 반환
return getTestStartResponseDto(currentTestId, test);
}
else { // 시간이 마감된 테스트 종료
extracted(testTypeId, member, test);
}
//현재 테스트가 진행중인지 확인하도록
//이미 테스트 중인지 확인
Tests test = testProgressCheckService.isTestinProgress(member);
if(test!=null)
{
return getTestStartResponseDto(member.getCurrentTestId(), test);
}
// 현재 진행중인 테스트가 없을 경우 아래 로직 진행


TestType testType = testTypeRepository.findById(testTypeId).orElseThrow(() -> new MorandiException(TestTypeErrorCode.TEST_TYPE_NOT_FOUND));
Tests test = addTestService.startTestByTestTypeId(testType, member);
// 현재 진행중인 테스트가 없을 경우 테스트 타입에 맞는 테스트 시작
test = addTestService.startTestByTestTypeId(testType, member);

String bojId = memberInfoService.getMemberInfo().getBojId();
List<BojProblem> bojProblems = new ArrayList<>();

// 테스트 시작시 문제 가져오기
getProblemsService.getProblemsByTestType(testType, bojProblems);

// API로 문제 가져오기
getProblemsService.getProblemsByApi(testType, bojId, bojProblems);

// 테스트 시작시 문제 저장
saveProblemsService.saveAttemptProblems(member, test, bojProblems);

// 테스트 시작시 코드 캐시 초기화
tempCodeInitializer.initTempCodeCacheWhenTestStart(test);

TestStartResponseDto testStartResponseDto = getTestStartResponseDto(test, bojProblems);

return testStartResponseDto;

return getTestStartResponseDto(test, bojProblems);
}

private static TestStartResponseDto getTestStartResponseDto(Tests test, List<BojProblem> bojProblems) {
Expand All @@ -119,19 +105,6 @@ private static TestStartResponseDto getTestStartResponseDto(Tests test, List<Boj
.build();
}

private void extracted(Tests test) {
Duration duration = Duration.between(test.getTestDate(), LocalDateTime.now());
test.setRemainingTime(test.getTestTime() * 60 - duration.getSeconds());
}

private void extracted(Long testTypeId, Member member, Tests test) {
TestCheckDto testCheckDto = TestCheckDto.builder()
.testId(test.getTestId())
.testTypeId(testTypeId)
.bojId(member.getBojId())
.build();
testExitService.testExit(testCheckDto);
}
private TestStartResponseDto getTestStartResponseDto(Long currentTestId, Tests test) {
List<AttemptProblem> attemptProblems = attemptProblemRepository.findAttemptProblemsByTest_TestId(currentTestId);
List<Long> bojProblemIds = attemptProblems.stream().map(AttemptProblem::getProblem)
Expand All @@ -146,30 +119,4 @@ private TestStartResponseDto getTestStartResponseDto(Long currentTestId, Tests t
// 테스트 시작에 대한 ResponseDto 반환
return testStartResponseDto;
}

private boolean isSolvedProblem(AttemptProblem attemptProblem, String bojId) {
Problem problem = attemptProblem.getProblem();
Long bojProblemId = problem.getBojProblemId();
String apiURL = "https://solved.ac/api/v3/search/problem";
String query = apiURL + "/?query=" + "id:" + bojProblemId.toString() + "%26@" + bojId;

URI uri = URI.create(query);

WebClient webClient = WebClient.builder().build();
String jsonString = webClient.get()
.uri(uri)
.retrieve()
.bodyToMono(String.class)
.block();
try {
JsonNode jsonNode = objectMapper.readTree(jsonString);
JsonNode checkNode = jsonNode.get("count");
return checkNode.asLong() == 1L;

} catch (NullPointerException e) {
throw new RuntimeException("Node null 반환했습니다.");
} catch (JsonProcessingException e) {
throw new RuntimeException("json 파싱에 실패했습니다.");
}
}
}

0 comments on commit db2bde4

Please sign in to comment.