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
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.runimo.runimo.common.response.SuccessResponse;
import org.runimo.runimo.hatch.service.dto.HatchEggResponse;
import org.runimo.runimo.hatch.exception.HatchHttpResponseCode;
import org.runimo.runimo.hatch.service.dto.HatchEggResponse;
import org.runimo.runimo.hatch.service.usecase.HatchUsecase;
import org.runimo.runimo.user.controller.UserId;
import org.springframework.http.HttpStatus;
Expand Down
25 changes: 8 additions & 17 deletions src/main/java/org/runimo/runimo/hatch/service/HatchClient.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package org.runimo.runimo.hatch.service;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.runimo.runimo.hatch.exception.HatchException;
import org.runimo.runimo.hatch.exception.HatchHttpResponseCode;
import org.runimo.runimo.hatch.service.strategy.EqualRandom;
import org.runimo.runimo.hatch.service.strategy.HatchRandomStrategy;
import org.runimo.runimo.item.domain.EggType;
import org.runimo.runimo.item.repository.EggTypeRepository;
import org.runimo.runimo.runimo.domain.RunimoDefinition;
import org.runimo.runimo.runimo.domain.runimo_type.RunimoType;
import org.runimo.runimo.runimo.repository.RunimoDefinitionRepository;
import org.springframework.stereotype.Service;

Expand All @@ -18,12 +17,13 @@
public class HatchClient {

private final RunimoDefinitionRepository runimoDefinitionRepository;
private final EggTypeRepository eggTypeRepository;

public RunimoDefinition getRandomRunimoDefinition(EggType eggType) {
HatchContext hatchContext = new HatchContext();

// 나올 수 있는 전체 러니모 풀 생성
List<RunimoType> runimoTypePool = generateRunimoTypePool(eggType);
List<Long> runimoTypePool = generateRunimoPoolCoveringLowerLevel(eggType);

// 부화 확률 전략 생성
HatchRandomStrategy hatchRandomStrategy = new EqualRandom(runimoTypePool.size());
Expand All @@ -33,24 +33,15 @@ public RunimoDefinition getRandomRunimoDefinition(EggType eggType) {
hatchContext.setHatchContext(runimoTypePool);

// 부화
RunimoType chosenRunimoType = hatchContext.execute();
Long chosenRunimoId = hatchContext.execute();

RunimoDefinition runimoDefinition = runimoDefinitionRepository.findByCode(
chosenRunimoType.getCode())
return runimoDefinitionRepository.findById(chosenRunimoId)
.orElseThrow(() -> HatchException.of(
HatchHttpResponseCode.HATCH_RUNIMO_NOT_FOUND_INTERNAL_ERROR));

return runimoDefinition;
}

private List<RunimoType> generateRunimoTypePool(EggType eggType) {
int eggEndIdx = eggType.ordinal();
EggRunimo[] eggRunimos = EggRunimo.values();

List<RunimoType> runimoTypes = new ArrayList<>();
for (int i = 0; i <= eggEndIdx; i++) {
runimoTypes.addAll(List.of(eggRunimos[i].getRunimoTypes()));
}
return runimoTypes;
private List<Long> generateRunimoPoolCoveringLowerLevel(EggType eggType) {
List<EggType> eggTypes = eggTypeRepository.findEggTypeByLevelLessThan(eggType.getLevel());
return runimoDefinitionRepository.findIdInEggTypes(eggTypes);
}
}
11 changes: 5 additions & 6 deletions src/main/java/org/runimo/runimo/hatch/service/HatchContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@

import java.util.List;
import org.runimo.runimo.hatch.service.strategy.HatchRandomStrategy;
import org.runimo.runimo.runimo.domain.runimo_type.RunimoType;

public class HatchContext {

private List<RunimoType> runimoTypePool;
private List<Long> runimoPool;
private HatchRandomStrategy hatchRandomStrategy;

public RunimoType execute() {
public Long execute() {
int chosenIdx = hatchRandomStrategy.generateNumber();
return runimoTypePool.get(chosenIdx);
return runimoPool.get(chosenIdx);
}

public void setHatchContext(List<RunimoType> runimoTypePool) {
this.runimoTypePool = runimoTypePool;
public void setHatchContext(List<Long> runimoIdPool) {
this.runimoPool = runimoIdPool;
}

public void setHatchStrategy(HatchRandomStrategy hatchRandomStrategy) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

public class EqualRandom implements HatchRandomStrategy {

private final SecureRandom secureRandom = new SecureRandom(); // TODO : 빈으로 관리?
private final SecureRandom secureRandom = new SecureRandom();

private int size;
private final int size;

public EqualRandom(int size) {
this.size = size;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.runimo.runimo.hatch.service.usecase;

import lombok.RequiredArgsConstructor;
import org.runimo.runimo.hatch.service.dto.HatchEggResponse;
import org.runimo.runimo.hatch.exception.HatchException;
import org.runimo.runimo.hatch.exception.HatchHttpResponseCode;
import org.runimo.runimo.hatch.service.HatchClient;
import org.runimo.runimo.hatch.service.dto.HatchEggResponse;
import org.runimo.runimo.item.domain.Egg;
import org.runimo.runimo.item.service.ItemFinder;
import org.runimo.runimo.runimo.domain.Runimo;
Expand Down
17 changes: 11 additions & 6 deletions src/main/java/org/runimo/runimo/item/domain/Egg.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -18,10 +19,10 @@
@DiscriminatorValue("EGG")
public class Egg extends Item {

public static final Egg EMPTY = new Egg(EMPTYFIELD, EMPTYFIELD, EMPTYFIELD, EMPTYFIELD, null,
0L);
@Column(name = "egg_type")
@Enumerated(EnumType.STRING)
public static final Egg EMPTY = new Egg(EMPTYFIELD, EMPTYFIELD, EMPTYFIELD, EMPTYFIELD,
EggType.EMPTY, 0L);
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "egg_type_id", referencedColumnName = "id")
private EggType eggType;
@Column(name = "hatch_require_amount")
private Long hatchRequireAmount;
Expand All @@ -33,4 +34,8 @@ public Egg(String itemCode, String name, String description, String imgUrl, EggT
this.eggType = eggType;
this.hatchRequireAmount = hatchRequireAmount;
}

public boolean isEmpty() {
return this == EMPTY;
}
}
57 changes: 41 additions & 16 deletions src/main/java/org/runimo/runimo/item/domain/EggType.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,55 @@
package org.runimo.runimo.item.domain;

import java.util.Arrays;
import java.util.List;
import static org.runimo.runimo.common.GlobalConsts.EMPTYFIELD;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.runimo.runimo.common.BaseEntity;

@Table(name = "egg_type")
@Entity
@Getter
public enum EggType {
MADANG("A100", "마당", 0L),
FOREST("A101", "숲", 30000L),
// GRASSLAND("A102", "초원", 50000L),
;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class EggType extends BaseEntity {

private final String code;
private final String name;
private final Long requiredDistanceInMeters;
public static final EggType EMPTY = new EggType(EMPTYFIELD, EMPTYFIELD, 0L, 0);

@Column(name = "name", nullable = false)
private String name;
@Column(name = "code", nullable = false)
private String code;
@Column(name = "required_distance_in_meters", nullable = false)
private Long requiredDistanceInMeters;
@Column(name = "level", nullable = false)
private Integer level;

EggType(String code, String name, Long requiredDistanceInMeters) {
this.code = code;
@Builder
private EggType(String name, String code, Long requiredDistanceInMeters, Integer level) {
this.name = name;
this.code = code;
if (requiredDistanceInMeters < 0) {
throw new IllegalArgumentException("알의 요구 거리(미터)는 0보다 작을 수 없습니다.");
}
this.requiredDistanceInMeters = requiredDistanceInMeters;
if (level < 0) {
throw new IllegalArgumentException("알의 레벨은 0보다 작을 수 없습니다.");
}
this.level = level;
}

public static List<EggType> getUnLockedEggTypes(final Long distance) {
return Arrays.stream(EggType.values())
.filter(type -> type.requiredDistanceInMeters < distance)
.toList();
public static EggType of(String name, String code, Long requiredDistanceInMeters,
Integer level) {
return EggType.builder()
.name(name)
.code(code)
.requiredDistanceInMeters(requiredDistanceInMeters)
.level(level)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.runimo.runimo.item.repository;

import java.util.List;
import org.runimo.runimo.item.domain.EggType;
import org.springframework.data.jpa.repository.JpaRepository;

public interface EggTypeRepository extends JpaRepository<EggType, Long> {

List<EggType> findAllByOrderByIdAsc();

List<EggType> findEggTypeByRequiredDistanceInMetersLessThanEqual(Long totalDistanceInMeters);

List<EggType> findEggTypeByLevelLessThan(Integer level);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public interface ItemRepository extends JpaRepository<Item, Long> {
@Query("select i.id from Item i")
List<Long> findAllItemIds();

@Query("select e from Egg e where e.eggType = :eggtype")
Optional<Egg> findByEggType(EggType eggtype);
@Query("select e from Egg e where e.eggType = :eggType")
Optional<Egg> findByEggType(EggType eggType);
}
3 changes: 2 additions & 1 deletion src/main/java/org/runimo/runimo/item/service/EggFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
@RequiredArgsConstructor
public class EggFactory {

private static final Long GREETING_EGG_ID = 1L;
private final ItemFinder itemFinder;
private final EggTypeRandomGenerator eggTypeRandomGenerator;

public Egg createGreetingEgg() {
return itemFinder.findEggByEggType(EggType.MADANG)
return (Egg) itemFinder.findById(GREETING_EGG_ID)
.orElseThrow(RuntimeException::new);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public RewardResponse claimReward(RewardClaimCommand command) {
Egg grantedEgg = rewardEgg(command);
Long grantedLoveAmount = loveGrantService.grantLoveToUserWithDistance(runningRecord);
runningRecord.reward(command.userId());
return new RewardResponse(grantedEgg.getItemCode(), grantedEgg.getEggType(),
return new RewardResponse(!grantedEgg.isEmpty(), grantedEgg.getItemCode(),
grantedEgg.getEggType().getName(),
grantedLoveAmount);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.runimo.runimo.rewards.service.dto;

import org.runimo.runimo.item.domain.EggType;

public record RewardResponse(
Boolean isRewarded,
String eggCode,
EggType eggType,
String eggType,
Long lovePointAmount
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.RequiredArgsConstructor;
import org.runimo.runimo.item.domain.Egg;
import org.runimo.runimo.item.domain.EggType;
import org.runimo.runimo.item.repository.EggTypeRepository;
import org.runimo.runimo.item.service.EggFactory;
import org.runimo.runimo.user.domain.User;
import org.runimo.runimo.user.service.UserItemProcessor;
Expand All @@ -19,6 +20,7 @@ public class EggGrantService {
private static final Long DEFAULT_REWARD_EGG_AMOUNT = 1L;
private final EggFactory eggFactory;
private final UserItemProcessor userItemProcessor;
private final EggTypeRepository eggTypeRepository;

@Transactional
public void grantGreetingEggToUser(User user) {
Expand All @@ -31,7 +33,7 @@ public void grantGreetingEggToUser(User user) {

@Transactional
public Egg grantRandomEggToUser(User user) {
List<EggType> unLockedEggTypes = EggType.getUnLockedEggTypes(
List<EggType> unLockedEggTypes = eggTypeRepository.findEggTypeByRequiredDistanceInMetersLessThanEqual(
user.getTotalDistanceInMeters());
Egg grantedEgg = eggFactory.createEggRandomly(unLockedEggTypes);
userItemProcessor.updateItemQuantity(user.getId(), grantedEgg.getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
Expand All @@ -30,8 +31,8 @@ public class RunimoDefinition extends BaseEntity {
@Column(name = "img_url")
private String imgUrl;

@Enumerated(EnumType.STRING)
@Column(name = "egg_type", nullable = false)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "egg_type_id", nullable = false)
private EggType type;

@Builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import java.util.Optional;
import org.runimo.runimo.item.domain.EggType;
import org.runimo.runimo.runimo.domain.RunimoDefinition;
import org.runimo.runimo.runimo.service.dto.RunimoTypeSimpleModel;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -12,8 +13,16 @@ public interface RunimoDefinitionRepository extends JpaRepository<RunimoDefiniti
Optional<RunimoDefinition> findByCode(String runimoCode);

@Query("""
select new org.runimo.runimo.runimo.service.dto.RunimoTypeSimpleModel(rd.name, rd.imgUrl, rd.code, rd.type, rd.description)
from RunimoDefinition rd
select rd.id from RunimoDefinition rd
where rd.type in :eggTypes
""")
List<RunimoTypeSimpleModel> findAllToSimpleModel();
List<Long> findIdInEggTypes(List<EggType> eggTypes);

@Query("""
select new org.runimo.runimo.runimo.service.dto.RunimoTypeSimpleModel(
rd.type.id, rd.code, rd.name, rd.imgUrl, rd.description
) from RunimoDefinition rd
where rd.type in :eggTypes
""")
List<RunimoTypeSimpleModel> findRunimoSimpleTypeModelByType(List<EggType> eggTypes);
}
Loading
Loading