Skip to content

Commit

Permalink
[FEAT] 조건에 따른 아바타 대사 가져오기 구현 (#136)
Browse files Browse the repository at this point in the history
* [REPACKAGE] avatar/model -> avatar/domain 으로 패키지 이전

* [FEAT] 기본 아바타 대사 전략 구현

* [FEAT] 음식 조건 전략 구현

* [MIGRATION] sql: avatar 6번 대사 추가, 조건 변경 및 삽입문에서 id 제거

* [FEAT] RandomFoodProvider에서 반환하는 음식 종류 추가

* [FEAT] 아바타 대사 시간 조건 전략 구현

* [FEAT] 한국 음력 달력 변환기 구현

* [REFACTOR, FEAT] 대사 제공 서비스 리팩터링 및 음력 날짜에 따른 대사 제공 기능 구현
  • Loading branch information
05AM authored Jun 12, 2024
1 parent 80a19aa commit 069bf9c
Show file tree
Hide file tree
Showing 27 changed files with 474 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application;

import com.wakeUpTogetUp.togetUp.api.avatar.application.strategy.SpeechStrategy;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.Avatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeech;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeechCondition;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarTheme;
import com.wakeUpTogetUp.togetUp.api.avatar.dto.response.AvatarSpeechResponse;
import com.wakeUpTogetUp.togetUp.api.avatar.model.AvatarSpeech;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.AvatarRepository;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.AvatarSpeechRepository;
import com.wakeUpTogetUp.togetUp.api.avatar.util.KoreanLunarCalendar;
import com.wakeUpTogetUp.togetUp.api.avatar.util.LunarDate;
import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
import com.wakeUpTogetUp.togetUp.utils.mapper.EntityDtoMapper;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Random;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -13,25 +24,73 @@
@RequiredArgsConstructor
public class AvatarSpeechProvider {

private final AvatarSpeechRepository avatarSpeechRepository;
private final AvatarValidationService avatarValidationService;
private final UserAvatarValidationService userAvatarValidationService;
private final Random rand = new Random();

private final AvatarRepository avatarRepository;
private final AvatarSpeechRepository avatarSpeechRepository;

private final SpeechStrategyFactory speechStrategyFactory;

private final Random random = new Random();

public AvatarSpeechResponse getUserAvatarSpeech(int userId, int avatarId) {
userAvatarValidationService.validateUserAvatarActive(userId, avatarId);
AvatarSpeech avatarSpeech = getAvatarRandomSpeech(avatarId);
String speech = makeSpeechByCondition(getSpeechByAvatar(avatarId));

return EntityDtoMapper.INSTANCE.toAvatarSpeechResponse(speech);
}

private String makeSpeechByCondition(AvatarSpeech avatarSpeech) {
SpeechStrategy strategy = speechStrategyFactory.getStrategy(avatarSpeech.getCondition());
return strategy.makeSpeech(avatarSpeech);
}

return EntityDtoMapper.INSTANCE.toAvatarSpeechResponse(avatarSpeech);
private AvatarSpeech getSpeechByAvatar(int avatarId) {
Avatar avatar = avatarRepository.findById(avatarId)
.orElseThrow(() -> new BaseException(Status.AVATAR_NOT_FOUND));
AvatarTheme avatarTheme = AvatarTheme.valueOf(avatar.getTheme());

switch (avatarTheme) {
case ASTRONAUT_BEAR:
LocalDate today = LocalDate.now();
return getByAvatarAndLunarCondition(avatarId, today);

default:
return getRandomOneByAvatar(avatarId);
}
}
private AvatarSpeech getAvatarRandomSpeech(int avatarId) {
List<AvatarSpeech> avatarSpeeches = getSpeechesOfAvatar(avatarId);
int randomIndex = rand.nextInt(avatarSpeeches.size());

private AvatarSpeech getByAvatarAndLunarCondition(int avatarId, LocalDate today) {
Map<Integer, AvatarSpeechCondition> lunarConditions = Map.of(
1, AvatarSpeechCondition.NEW_MOON,
15, AvatarSpeechCondition.HALF_MOON,
30, AvatarSpeechCondition.FULL_MOON
);

LunarDate lunarDate = KoreanLunarCalendar.convert(today);
int lunarDay = lunarDate.getDay();
AvatarSpeechCondition condition = lunarConditions.get(lunarDay);

return condition != null ?
getByAvatarAndCondition(avatarId, condition) :
getRandomOneByAvatar(avatarId);
}

private AvatarSpeech getByAvatarAndCondition(int avatarId, AvatarSpeechCondition condition) {
return avatarSpeechRepository
.findByAvatarIdAndCondition(avatarId, condition)
.orElseThrow(() -> new BaseException(Status.GET_AVATAR_SPEECH_BY_CONDITION_FAIL));
}

private AvatarSpeech getRandomOneByAvatar(int avatarId) {
List<AvatarSpeech> avatarSpeeches = getAllByAvatar(avatarId);
int randomIndex = random.nextInt(avatarSpeeches.size());

return avatarSpeeches.get(randomIndex);
}

private List<AvatarSpeech> getSpeechesOfAvatar(int avatarId) {
private List<AvatarSpeech> getAllByAvatar(int avatarId) {
avatarValidationService.validateAvatarExist(avatarId);
return avatarSpeechRepository.findAllByAvatar_Id(avatarId);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application;

public interface RandomFoodProvider {

String getRandomFoodWord();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application;

import com.wakeUpTogetUp.togetUp.api.avatar.application.strategy.BasicSpeechStrategy;
import com.wakeUpTogetUp.togetUp.api.avatar.application.strategy.FoodSpeechStrategy;
import com.wakeUpTogetUp.togetUp.api.avatar.application.strategy.SpeechStrategy;
import com.wakeUpTogetUp.togetUp.api.avatar.application.strategy.TimeSpeechStrategy;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeechCondition;
import java.util.EnumMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class SpeechStrategyFactory {
private static final Map<AvatarSpeechCondition, SpeechStrategy> strategies = new EnumMap<>(AvatarSpeechCondition.class);
private final BasicSpeechStrategy basicSpeechStrategy;
private final FoodSpeechStrategy foodSpeechStrategy;
private final TimeSpeechStrategy timeSpeechStrategy;

@PostConstruct
public void init() {
strategies.put(AvatarSpeechCondition.DEFAULT, basicSpeechStrategy);
strategies.put(AvatarSpeechCondition.NONE, basicSpeechStrategy);
strategies.put(AvatarSpeechCondition.FOOD, foodSpeechStrategy);
strategies.put(AvatarSpeechCondition.TIME, timeSpeechStrategy);
}

public SpeechStrategy getStrategy(AvatarSpeechCondition condition) {
return strategies.getOrDefault(condition, new BasicSpeechStrategy());
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application;

import com.wakeUpTogetUp.togetUp.api.avatar.domain.Avatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.dto.response.UserAvatarResponse;
import com.wakeUpTogetUp.togetUp.api.avatar.model.Avatar;
import com.wakeUpTogetUp.togetUp.api.avatar.model.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.AvatarRepository;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.UserAvatarRepository;
import com.wakeUpTogetUp.togetUp.common.Status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import static com.wakeUpTogetUp.togetUp.common.Constant.DEFAULT_AVATAR_ID;

import com.wakeUpTogetUp.togetUp.api.avatar.application.model.UnlockAvatarResult;
import com.wakeUpTogetUp.togetUp.api.avatar.model.Avatar;
import com.wakeUpTogetUp.togetUp.api.avatar.model.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.Avatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.AvatarRepository;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.UserAvatarRepository;
import com.wakeUpTogetUp.togetUp.api.users.domain.User;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application;

import com.wakeUpTogetUp.togetUp.api.avatar.model.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.repository.UserAvatarRepository;
import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application.strategy;

import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeech;
import org.springframework.stereotype.Component;

@Component
public class BasicSpeechStrategy implements SpeechStrategy{

@Override
public String makeSpeech(AvatarSpeech avatarSpeech) {
return avatarSpeech.getSpeech();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application.strategy;

import com.wakeUpTogetUp.togetUp.api.avatar.application.RandomFoodProvider;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeech;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class FoodSpeechStrategy implements SpeechStrategy{

private final RandomFoodProvider randomFoodProvider;

@Override
public String makeSpeech(AvatarSpeech avatarSpeech) {
return String.format(avatarSpeech.getSpeech(), randomFoodProvider.getRandomFoodWord());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application.strategy;

import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeech;

public interface SpeechStrategy {

String makeSpeech(AvatarSpeech avatarSpeech);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.wakeUpTogetUp.togetUp.api.avatar.application.strategy;

import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeech;
import com.wakeUpTogetUp.togetUp.utils.DateTimeProvider;
import java.time.LocalDateTime;
import org.springframework.stereotype.Component;

@Component
public class TimeSpeechStrategy implements SpeechStrategy{

@Override
public String makeSpeech(AvatarSpeech avatarSpeech) {
LocalDateTime now = DateTimeProvider.getCurrentDateTimeInSeoul();
return String.format(avatarSpeech.getSpeech(), now.getHour(), now.getMinute());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wakeUpTogetUp.togetUp.api.avatar.model;
package com.wakeUpTogetUp.togetUp.api.avatar.domain;

import com.wakeUpTogetUp.togetUp.common.Status;
import com.wakeUpTogetUp.togetUp.exception.BaseException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wakeUpTogetUp.togetUp.api.avatar.model;
package com.wakeUpTogetUp.togetUp.api.avatar.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.wakeUpTogetUp.togetUp.api.avatar.domain;

public enum AvatarSpeechCondition {

DEFAULT,
NONE,
FOOD,
TIME,
NEW_MOON,
HALF_MOON,
FULL_MOON
;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wakeUpTogetUp.togetUp.api.avatar.model;
package com.wakeUpTogetUp.togetUp.api.avatar.domain;

import lombok.AccessLevel;
import lombok.Getter;
Expand All @@ -8,4 +8,5 @@
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public enum AvatarTheme {

ASTRONAUT_BEAR,
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.wakeUpTogetUp.togetUp.api.avatar.model;
package com.wakeUpTogetUp.togetUp.api.avatar.domain;

import com.wakeUpTogetUp.togetUp.api.users.domain.User;
import java.time.LocalDateTime;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.wakeUpTogetUp.togetUp.api.avatar.repository;

import com.wakeUpTogetUp.togetUp.api.avatar.model.Avatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.Avatar;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.wakeUpTogetUp.togetUp.api.avatar.repository;

import com.wakeUpTogetUp.togetUp.api.avatar.model.AvatarSpeech;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeech;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.AvatarSpeechCondition;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface AvatarSpeechRepository extends JpaRepository<AvatarSpeech, Integer> {

List<AvatarSpeech> findAllByAvatar_Id(int avatarId);

Optional<AvatarSpeech> findByAvatarIdAndCondition(Integer avatarId, AvatarSpeechCondition condition);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.wakeUpTogetUp.togetUp.api.avatar.repository;

import com.wakeUpTogetUp.togetUp.api.avatar.model.UserAvatar;
import com.wakeUpTogetUp.togetUp.api.avatar.domain.UserAvatar;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
Expand Down
Loading

0 comments on commit 069bf9c

Please sign in to comment.