1. 기존 로직
[Controller]
@PostMapping("/signup")
public ResponseEntity signupCharacter(@AuthenticationPrincipal String username,
@RequestBody @Valid MemberDto memberDto) {
// 대표캐릭터와 연동된 캐릭터(api 검증)
List<Character> characterList = lostarkCharacterService.getCharacterList(memberDto);
// 재련재료 데이터 리스트로 거래소 데이터 호출
Map<String, Market> contentResource = marketService.getContentResource();
// 일일 숙제 통계 가져오기
Map<String, DayContent> dayContent = contentService.findDayContent();
for (Character character : characterList) {
// 일일숙제 예상 수익 계산(휴식 게이지 포함)
characterService.calculateDayTodo(character, contentResource, dayContent);
}
// Member 회원가입
memberDto.setUsername(username);
Member signupMember = memberService.createCharacter(memberDto, characterList);
// 결과 출력
MemberResponseDto responseDto = MemberResponseDto.builder()
.username(signupMember.getUsername())
.characters(signupMember.getCharacters().stream().map(
character -> character.getCharacterName()
+ " / " + character.getCharacterClassName()
+ " / Lv." + character.getItemLevel())
.collect(Collectors.toList()))
.build();
return new ResponseEntity(responseDto, HttpStatus.OK);
}
JWT를 통한 username(email), Body(MemberDto)로 로스트아크 apikey와 대표캐릭터명을 받는다.
[Service]
public List<Character> getCharacterList(MemberDto memberDto) {
try {
String encodeCharacterName = URLEncoder.encode(memberDto.getCharacterName(), StandardCharsets.UTF_8);
String link = "https://developer-lostark.game.onstove.com/characters/"+encodeCharacterName+"/siblings";
InputStreamReader inputStreamReader = apiService.lostarkGetApi(link, memberDto.getApiKey());
JSONParser parser = new JSONParser();
JSONArray jsonArray = (JSONArray) parser.parse(inputStreamReader);
// 1415이상만 필터링
JSONArray filteredArray = filterLevel(jsonArray);
JSONArray imageList = getCharacterImage(filteredArray, memberDto.getApiKey());
List<Character> characterList = new ArrayList<>();
for (Object o : imageList) {
JSONObject jsonObject = (JSONObject) o;
Character character = Character.builder()
.characterName(jsonObject.get("CharacterName").toString())
.characterLevel(Integer.parseInt(jsonObject.get("CharacterLevel").toString()))
.characterClassName(jsonObject.get("CharacterClassName").toString())
.serverName(jsonObject.get("ServerName").toString())
.itemLevel(Double.parseDouble(jsonObject.get("ItemMaxLevel").toString().replace(",", "")))
.characterImage(jsonObject.get("CharacterImage").toString())
.dayTodo(new DayTodo())
.build();
character.getDayTodo().createName(character.getItemLevel()); // 일일 숙제 이름 넣기
characterList.add(character);
}
//레벨순으로 정렬 후 리턴
AtomicInteger sortNumber = new AtomicInteger();
List<Character> sortedList = characterList.stream()
.sorted(Comparator.comparing(Character::getItemLevel).reversed()).collect(Collectors.toList())
.stream().map(character -> {
character.setSortNumber(sortNumber.getAndIncrement());
return character;
})
.collect(Collectors.toList());
return sortedList;
} catch (NullPointerException e) {
throw new RuntimeException(memberDto.getCharacterName() + " 은(는) 존재하지 않는 캐릭터 입니다.");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
- MemberDto값을 통해서 로스트아크 api로 캐릭터 정보를 불러온 후 Character 객체로 변경한다
- 여기서 아이템 레벨의 따라 일일 컨텐츠 이름(계몽1, 가르가디스 등등)의 이름을 넣는다.
[DayTodo]
public void createName(double itemLevel) {
if (itemLevel >= 1415) {
this.chaosName = "타락1";
this.guardianName = "데스칼루다";
}
if (itemLevel >= 1445) {
this.chaosName = "타락2";
this.guardianName = "데스칼루다";
}
if (itemLevel >= 1460) {
this.chaosName = "타락2";
this.guardianName = "쿤겔라니움";
}
if (itemLevel >= 1475) {
this.chaosName = "타락3";
this.guardianName = "쿤겔라니움";
}
if (itemLevel >= 1490) {
this.chaosName = "공허1";
this.guardianName = "칼엘리고스";
}
if (itemLevel >= 1520) {
this.chaosName = "공허2";
this.guardianName = "칼엘리고스";
}
if (itemLevel >= 1540) {
this.chaosName = "절망1";
this.guardianName = "하누마탄";
}
if (itemLevel >= 1560) {
this.chaosName = "절망2";
this.guardianName = "하누마탄";
}
if (itemLevel >= 1580) {
this.chaosName = "천공1";
this.guardianName = "소나벨";
}
if (itemLevel >= 1600) {
this.chaosName = "천공2";
this.guardianName = "소나벨";
}
if (itemLevel >= 1610) {
this.chaosName = "계몽1";
this.guardianName = "가르가디스";
}
}
문제 -> 새로운 컨텐츠들(계몽2, 베스칼 등등)이 추가되면 일일히 추가해서 빌드 후 배포를 해야한다.
2. 변경 로직
현재 일일컨텐츠 통계가 DB에 아래와 같은 형식으로 저장되어있다.
DayContent를 통으로 호출하지 않고 카오스던전, 가디언토벌 각각을 List로 호출한다.
List<DayContent> chaos = findDayContent(Category.카오스던전);
List<DayContent> guardian = findDayContent(Category.가디언토벌);
public List<DayContent> findDayContent(Category category) {
return contentRepository.findContentByCategoryOrderByLevelDesc(category);
}
아이템레벨 내림차순으로 정렬되어 있기때문에
현재 캐릭터 레벨보다 작은 컨텐츠중 가장 첫번째의 값을 가져온다.
for (Character character : characterList) {
DayTodo nameV2 = character.getDayTodo().createName_v2(chaos, guardian, character.getItemLevel());
}
public DayTodo createName_v2(List<DayContent> chaos, List<DayContent> guardian, double itemLevel) {
this.chaosName = chaos.stream().filter(dayContent -> dayContent.getLevel() <= itemLevel).findFirst().get().getName();
this.guardianName = guardian.stream().filter(dayContent -> dayContent.getLevel() <= itemLevel).findFirst().get().getName();
return this;
}
3. 테스트
@Test
@DisplayName("일일컨텐츠 이름 자동화")
void signupCharacter() {
//given
MemberDto memberDto = MemberDto.builder()
.characterName(chracterName)
.apiKey(apiKey)
.build();
List<DayContent> chaos = findDayContent(Category.카오스던전);
List<DayContent> guardian = findDayContent(Category.가디언토벌);
List<Character> characterList = lostarkCharacterService.getCharacterList_v2(memberDto, chaos, guardian);
// 일일 숙제 이름변경
for (Character character : characterList) {
if (character.getItemLevel() >= 1630.0) {
Assertions.assertThat(character.getDayTodo().getGuardianName()).isEqualTo("베스칼");
Assertions.assertThat(character.getDayTodo().getChaosName()).isEqualTo("계몽2");
}
if (character.getItemLevel() >= 1610.0 && character.getItemLevel() < 1630.0) {
Assertions.assertThat(character.getDayTodo().getGuardianName()).isEqualTo("가르가디스");
Assertions.assertThat(character.getDayTodo().getChaosName()).isEqualTo("계몽1");
}
if (character.getItemLevel() >= 1415.0 && character.getItemLevel() < 1420.0) {
Assertions.assertThat(character.getDayTodo().getGuardianName()).isEqualTo("데스칼루다");
Assertions.assertThat(character.getDayTodo().getChaosName()).isEqualTo("타락1");
}
}
}