Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main/java/com/back/domain/tag/tag/dto/TagResponse.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.back.domain.tag.tag.dto;

public record TagResponse(String code, String label) {}
import java.util.List;

public record TagResponse(String code, String label, List<String> difficulties) {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,31 @@
import java.util.Optional;

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

import com.back.domain.problem.problem.enums.DifficultyLevel;
import com.back.domain.tag.tag.entity.Tag;

public interface TagRepository extends JpaRepository<Tag, Long> {
interface TagDifficultyView {
String getTagName();

DifficultyLevel getDifficulty();
}

List<Tag> findAllByOrderByNameAsc();

Optional<Tag> findByName(String name);

@Query("""
select t.name as tagName, p.difficulty as difficulty
from ProblemTagConnect ptc
join ptc.tag t
join ptc.problem p
where t.name is not null
and trim(t.name) <> ''
group by t.name, p.difficulty
order by t.name asc
""")
List<TagDifficultyView> findTagDifficulties();
}
27 changes: 26 additions & 1 deletion src/main/java/com/back/domain/tag/tag/service/TagService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.back.domain.tag.tag.service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.back.domain.problem.problem.enums.DifficultyLevel;
import com.back.domain.tag.tag.dto.TagResponse;
import com.back.domain.tag.tag.repository.TagRepository;

Expand All @@ -15,14 +19,35 @@
@Transactional(readOnly = true)
public class TagService {

private static final List<DifficultyLevel> DIFFICULTY_ORDER =
List.of(DifficultyLevel.EASY, DifficultyLevel.MEDIUM, DifficultyLevel.HARD);

private final TagRepository tagRepository;

public List<TagResponse> getTags() {
Map<String, Set<DifficultyLevel>> difficultyByTag = tagRepository.findTagDifficulties().stream()
.filter(row -> row.getTagName() != null && row.getDifficulty() != null)
.filter(row -> !row.getTagName().trim().isBlank())
.collect(Collectors.groupingBy(
row -> row.getTagName().trim(),
Collectors.mapping(TagRepository.TagDifficultyView::getDifficulty, Collectors.toSet())));

return tagRepository.findAllByOrderByNameAsc().stream()
.map(tag -> tag.getName() == null ? null : tag.getName().trim())
.filter(name -> name != null && !name.isBlank())
.distinct()
.map(name -> new TagResponse(name, name))
.map(name -> new TagResponse(name, name, toDifficultyNames(difficultyByTag.get(name))))
.toList();
}

private List<String> toDifficultyNames(Set<DifficultyLevel> levels) {
if (levels == null || levels.isEmpty()) {
return List.of();
}

return DIFFICULTY_ORDER.stream()
.filter(levels::contains)
.map(DifficultyLevel::name)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class TagControllerTest {
@Test
@DisplayName("태그 컨트롤러는 서비스 결과를 그대로 반환한다")
void getTags_returnsServiceResult() {
List<TagResponse> response = List.of(new TagResponse("array", "array"), new TagResponse("graph", "graph"));
List<TagResponse> response = List.of(
new TagResponse("array", "array", List.of("EASY")),
new TagResponse("graph", "graph", List.of("MEDIUM", "HARD")));

when(tagService.getTags()).thenReturn(response);

Expand Down
18 changes: 16 additions & 2 deletions src/test/java/com/back/domain/tag/tag/service/TagServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import com.back.domain.problem.problem.enums.DifficultyLevel;
import com.back.domain.tag.tag.dto.TagResponse;
import com.back.domain.tag.tag.entity.Tag;
import com.back.domain.tag.tag.repository.TagRepository;
Expand All @@ -19,20 +20,33 @@ class TagServiceTest {
private final TagService tagService = new TagService(tagRepository);

@Test
@DisplayName("태그 목록 조회 시 code/label을 태그 이름으로 반환한다")
@DisplayName("태그 목록 조회 시 code/label과 난이도 목록을 함께 반환한다")
void getTags_returnsTagList() {
Tag arrayTag = mock(Tag.class);
Tag graphTag = mock(Tag.class);
Tag blankTag = mock(Tag.class);
TagRepository.TagDifficultyView arrayEasy = mock(TagRepository.TagDifficultyView.class);
TagRepository.TagDifficultyView arrayHard = mock(TagRepository.TagDifficultyView.class);
TagRepository.TagDifficultyView graphMedium = mock(TagRepository.TagDifficultyView.class);

when(arrayTag.getName()).thenReturn("array");
when(graphTag.getName()).thenReturn("graph");
when(blankTag.getName()).thenReturn(" ");
when(arrayEasy.getTagName()).thenReturn("array");
when(arrayEasy.getDifficulty()).thenReturn(DifficultyLevel.EASY);
when(arrayHard.getTagName()).thenReturn("array");
when(arrayHard.getDifficulty()).thenReturn(DifficultyLevel.HARD);
when(graphMedium.getTagName()).thenReturn("graph");
when(graphMedium.getDifficulty()).thenReturn(DifficultyLevel.MEDIUM);

when(tagRepository.findAllByOrderByNameAsc()).thenReturn(List.of(arrayTag, graphTag, blankTag));
when(tagRepository.findTagDifficulties()).thenReturn(List.of(arrayEasy, arrayHard, graphMedium));

List<TagResponse> response = tagService.getTags();

assertThat(response).containsExactly(new TagResponse("array", "array"), new TagResponse("graph", "graph"));
assertThat(response)
.containsExactly(
new TagResponse("array", "array", List.of("EASY", "HARD")),
new TagResponse("graph", "graph", List.of("MEDIUM")));
}
}
Loading