Skip to content

Commit

Permalink
feat: 방비교 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
JINU-CHANG committed Jul 25, 2024
1 parent f44b0f4 commit 943753e
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,36 @@ public static boolean contains(int id) {
.anyMatch(category -> category.id == id);
}

// 2. 뱃지 부여
public static List<Badge> getBadges(List<ChecklistQuestion> questions) {
return Arrays.stream(values())
.filter(category -> category.calculateTotalScore(questions) >= 80)
.map(Category::getBadge)
.toList();
}

// 1. 총점 : score * 100 / maxScore
public int calculateTotalScore(List<ChecklistQuestion> questions) {
List<ChecklistQuestion> filteredQuestions = filterQuestion(questions);

if (filteredQuestions.isEmpty()) {
return 0;
}

int maxScore = Grade.calculateMaxScore(filteredQuestions.size());
int score = filteredQuestions.stream()
.mapToInt(question -> Grade.getScore(question.getAnswer()))
.sum();

return score * 100 / maxScore;
}

private List<ChecklistQuestion> filterQuestion(List<ChecklistQuestion> questions) {
return questions.stream()
.filter(checklistQuestion -> questionIds.contains(checklistQuestion.getQuestionId()))
.toList();
}

public int getId() {
return id;
}
Expand All @@ -47,25 +77,4 @@ public String getDescription() {
public Set<Integer> getQuestionIds() {
return questionIds;
}

public static List<Badge> getBadges(List<ChecklistQuestion> questions) {
return Arrays.stream(values())
.filter(category -> {
Set<Integer> questionIds = category.questionIds;
List<ChecklistQuestion> categoryQuestions = questions.stream()
.filter(checklistQuestion -> questionIds.contains(checklistQuestion.getQuestionId()))
.toList();
if (categoryQuestions.isEmpty()) {
return false;
}
int maxScore = Grade.calculateMaxScore(categoryQuestions.size());
int score = categoryQuestions.stream()
.mapToInt(question -> Grade.getScore(question.getAnswer()))
.sum();

return (score * 100 / maxScore) >= 80;
})
.map(Category::getBadge)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package com.bang_ggood.checklist.controller;

import com.bang_ggood.checklist.dto.ChecklistCreateRequest;
import com.bang_ggood.checklist.dto.UserChecklistsPreviewResponse;
import com.bang_ggood.checklist.dto.ChecklistQuestionsResponse;
import com.bang_ggood.checklist.dto.ChecklistsComparisonReadResponse;
import com.bang_ggood.checklist.dto.UserChecklistsPreviewResponse;
import com.bang_ggood.checklist.service.ChecklistService;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.net.URI;
import java.util.List;

@RestController
public class ChecklistController {
Expand All @@ -36,4 +39,9 @@ public ResponseEntity<UserChecklistsPreviewResponse> readUserChecklistsPreview()
public ResponseEntity<ChecklistQuestionsResponse> readChecklistQuestions() {
return ResponseEntity.ok(checklistService.readChecklistQuestions());
}

@GetMapping("/checklists/comparison")
public ResponseEntity<ChecklistsComparisonReadResponse> readChecklistsComparison(@RequestParam("id")List<Long> checklistIds) {
return ResponseEntity.ok(checklistService.readChecklistsComparison(checklistIds));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ public String getRoomAddress() {
return room.getAddress();
}

public Integer getRoomFloor() { return room.getFloor(); }

public String getRoomStation() { return room.getStation(); }

public Integer getRoomWalkingTime() { return room.getWalkingTime(); }

public Integer getDeposit() {
return deposit;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.bang_ggood.checklist.dto;

public record CategoryScoreReadResponse(
Integer categoryId, String categoryName, Integer score
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.bang_ggood.checklist.dto;

import com.bang_ggood.checklist.domain.Checklist;
import java.util.List;

public record ChecklistComparisonReadResponse(
Long checklistId, String roomName, String address,
Integer floor, Integer deposit, Integer rent,
Integer contractTerm, String station, Integer walkingTime,
Integer optionCount, Integer score,
List<CategoryScoreReadResponse> categories
) {
public static ChecklistComparisonReadResponse of(Checklist checklist, int checklistOptionCount, int checklistScore, List<CategoryScoreReadResponse> categoryScores) {
return new ChecklistComparisonReadResponse(
checklist.getId(),
checklist.getRoomName(),
checklist.getRoomAddress(),
checklist.getRoomFloor(),
checklist.getDeposit(),
checklist.getRent(),
checklist.getContractTerm(),
checklist.getRoomStation(),
checklist.getRoomWalkingTime(),
checklistOptionCount,
checklistScore,
categoryScores
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.bang_ggood.checklist.dto;

import java.util.List;

public record ChecklistsComparisonReadResponse(List<ChecklistComparisonReadResponse> checklists) {
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.bang_ggood.checklist.repository;

import com.bang_ggood.checklist.domain.Checklist;
import com.bang_ggood.checklist.domain.ChecklistOption;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ChecklistOptionRepository extends JpaRepository<ChecklistOption, Long> {

Integer countByChecklist(Checklist checklist);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
public interface ChecklistRepository extends JpaRepository<Checklist, Long> {

List<Checklist> findByUser(User user);
List<Checklist> findByUserAndIdIn(User user, List<Long> checklistIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
import com.bang_ggood.checklist.domain.Option;
import com.bang_ggood.checklist.domain.Questionlist;
import com.bang_ggood.checklist.dto.BadgeResponse;
import com.bang_ggood.checklist.dto.CategoryScoreReadResponse;
import com.bang_ggood.checklist.dto.ChecklistComparisonReadResponse;
import com.bang_ggood.checklist.dto.ChecklistCreateRequest;
import com.bang_ggood.checklist.dto.ChecklistInfo;
import com.bang_ggood.checklist.dto.ChecklistQuestionsResponse;
import com.bang_ggood.checklist.dto.ChecklistsComparisonReadResponse;
import com.bang_ggood.checklist.dto.QuestionCreateRequest;
import com.bang_ggood.checklist.dto.QuestionResponse;
import com.bang_ggood.checklist.dto.UserChecklistPreviewResponse;
Expand All @@ -26,6 +29,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -147,7 +151,7 @@ private List<BadgeResponse> createBadges(List<ChecklistQuestion> questions) {
.toList();
}

public ChecklistQuestionsResponse readChecklistQuestions () {
public ChecklistQuestionsResponse readChecklistQuestions() {
List<CategoryQuestionsResponse> categoryQuestionsResponses = new ArrayList<>();
for (Category category : Category.values()) {
CategoryQuestionsResponse categoryQuestionsResponse =
Expand All @@ -167,4 +171,51 @@ private List<QuestionResponse> readChecklistQuestion(Category category) {
.forEach(questionResponses::add);
return questionResponses;
}

@Transactional
public ChecklistsComparisonReadResponse readChecklistsComparison(List<Long> checklistIds) {
User user = new User(1L, "방끗");

List<ChecklistComparisonReadResponse> responses = checklistRepository.findByUserAndIdIn(user, checklistIds)
.stream()
.map(checklist -> {
// 카테고리별 총점
List<CategoryScoreReadResponse> categoryScores = calculateCategoryScores(checklist);

// 체크리스트 총점
int checklistScore = calculateChecklistScore(categoryScores);

// 옵션 개수
int checklistOptionCount = checklistOptionRepository.countByChecklist(checklist);

return ChecklistComparisonReadResponse.of(
checklist, checklistOptionCount, checklistScore, categoryScores);})
.sorted(Comparator.comparing(ChecklistComparisonReadResponse::score).reversed())
.toList();

return new ChecklistsComparisonReadResponse(responses);
}

private List<CategoryScoreReadResponse> calculateCategoryScores(Checklist checklist) {
List<CategoryScoreReadResponse> categoryScores = new ArrayList<>();

for (Category category : Category.values()) {
int categoryScore = category.calculateTotalScore(checklist.getQuestions());
if (categoryScore != 0) {
categoryScores.add(new CategoryScoreReadResponse(
category.getId(),
category.getDescription(),
categoryScore
));
}
}

return categoryScores;
}

private int calculateChecklistScore(List<CategoryScoreReadResponse> categoryScores) {
return categoryScores.stream()
.mapToInt(CategoryScoreReadResponse::score)
.sum() / categoryScores.size();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public ResponseEntity<ExceptionResponse> handleBangggoodException(BangggoodExcep
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ExceptionResponse> handleRuntimeException(HttpServletRequest request) {
public ResponseEntity<ExceptionResponse> handleRuntimeException(RuntimeException runtimeException, HttpServletRequest request) {
runtimeException.printStackTrace();
ExceptionResponse response = new ExceptionResponse(
request.getMethod(),
request.getRequestURI(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.bang_ggood.category.domain;

import com.bang_ggood.checklist.domain.ChecklistQuestion;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.List;

import static com.bang_ggood.category.domain.Category.CLEAN;
import static com.bang_ggood.category.domain.Category.SECURITY;
import static org.assertj.core.api.Assertions.assertThat;

class CategoryTest {

@DisplayName("뱃지 부여 : 카테고리 총점이 80점 이상일 때")
Expand All @@ -24,7 +27,7 @@ void getBadges() {
List<Badge> badges = Category.getBadges(questions);

// then
Assertions.assertThat(badges).containsExactly(Badge.CLEAN);
assertThat(badges).containsExactly(Badge.CLEAN);
}

@DisplayName("뱃지 미부여 : 카테고리 총점이 80점 미만일 때")
Expand All @@ -43,6 +46,40 @@ void getBadges_NoBadges() {
List<Badge> badges = Category.getBadges(questions);

// then
Assertions.assertThat(badges).isEmpty();
assertThat(badges).isEmpty();
}

@DisplayName("카테고리 총점수 계산 성공")
@Test
void calculateTotalScore() {
// given
List<ChecklistQuestion> questions = List.of(new ChecklistQuestion(null, 1, "GOOD"),
new ChecklistQuestion(null, 2, "GOOD"),
new ChecklistQuestion(null, 3, "GOOD"),
new ChecklistQuestion(null, 4, "BAD"),
new ChecklistQuestion(null, 5, "BAD"));

// when
int totalScore = CLEAN.calculateTotalScore(questions);

// then
assertThat(totalScore).isEqualTo(( 11 * 100 / 15));
}

@DisplayName("카테고리 총점수 계산 성공 : 해당 카테고리에 대한 답변이 없을 경우")
@Test
void calculateTotalScore_WhenCategoryDoesNotMatch() {
// given
List<ChecklistQuestion> questions = List.of(new ChecklistQuestion(null, 1, "GOOD"),
new ChecklistQuestion(null, 2, "GOOD"),
new ChecklistQuestion(null, 3, "GOOD"),
new ChecklistQuestion(null, 4, "BAD"),
new ChecklistQuestion(null, 5, "BAD"));

// when
int totalScore = SECURITY.calculateTotalScore(questions);

// then
assertThat(totalScore).isZero();
}
}

0 comments on commit 943753e

Please sign in to comment.