Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

퀘스트 API 추가 #39

Merged
merged 9 commits into from
Oct 1, 2024
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
34 changes: 34 additions & 0 deletions src/main/java/ku/user/domain/quest/controller/QuestController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ku.user.domain.quest.controller;

import jakarta.ws.rs.PATCH;
import ku.user.domain.quest.domain.Quest;
import ku.user.domain.quest.dto.request.PostUserQuestRequest;
import ku.user.domain.quest.dto.response.GetUserQuestsResponse;
import ku.user.domain.quest.dto.response.PostUserQuestResponse;
import ku.user.domain.quest.service.QuestService;
import ku.user.global.response.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
public class QuestController {

private final QuestService questService;

@GetMapping("/quests")
public ApiResponse<GetUserQuestsResponse> checkQuest(@RequestParam String email) {
Quest quest = questService.checkAndRefreshQuest(email);
GetUserQuestsResponse getUserQuestsResponse = GetUserQuestsResponse.toDto(quest);
return new ApiResponse<>(true, getUserQuestsResponse, null);
}

@PostMapping("/quests")
public ApiResponse<PostUserQuestResponse> solveQuest(@RequestParam String email, @RequestBody PostUserQuestRequest postUserQuestRequest) {
Quest quest = questService.solveQuestByEmail(postUserQuestRequest.getQuestIndex(), email);
PostUserQuestResponse postUserQuestResponse = PostUserQuestResponse.toDto(quest);
return new ApiResponse<>(true, postUserQuestResponse, null);
}


}
21 changes: 21 additions & 0 deletions src/main/java/ku/user/domain/quest/dao/QuestRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package ku.user.domain.quest.dao;

import feign.Param;
import ku.user.domain.quest.domain.Quest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import javax.swing.text.html.Option;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Optional;

public interface QuestRepository extends JpaRepository<Quest,Long> {
@Query("SELECT q FROM Quest q WHERE q.userId = :userId AND q.createdAt = :createdAt")
Optional<Quest> findQuestByUserIdAndCompletionDate(@Param("userId") Long userId, @Param("createdAt") LocalDate createdAt);

Optional<Quest> findByUserId(Long userId);
/*@Query("SELECT q FROM Quest q WHERE q.userId = :userId AND DATE(q.createdAt) = CURRENT_DATE")
Optional<Quest> findQuestByUserIdAndToday(@Param("userId") Long userId);*/

}
55 changes: 55 additions & 0 deletions src/main/java/ku/user/domain/quest/domain/Quest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ku.user.domain.quest.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.relational.core.sql.In;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
@Getter
@Table(name = "quests")
public class Quest {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private Long userId;

private Integer quest1;
private LocalDateTime quest1CompletedAt;

private Integer quest2;
private LocalDateTime quest2CompletedAt;

private Integer quest3;
private LocalDateTime quest3CompletedAt;

private LocalDate createdAt;

public static Quest from(Long userId, List<Integer> randomQuestNumber) {
return Quest.builder()
.userId(userId)
.quest1(randomQuestNumber.get(0))
.quest2(randomQuestNumber.get(1))
.quest3(randomQuestNumber.get(2))
.createdAt(LocalDate.now())
.build();
}

public void solve(Integer questIndex) {
if (quest1.equals(questIndex))
quest1CompletedAt = LocalDateTime.now();
if (quest2.equals(questIndex))
quest2CompletedAt = LocalDateTime.now();
if (quest3.equals(questIndex))
quest3CompletedAt = LocalDateTime.now();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ku.user.domain.quest.dto.request;

import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@Getter
public class PostUserQuestRequest {

private Integer questIndex;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ku.user.domain.quest.dto.response;

import ku.user.domain.quest.domain.Quest;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;


@Builder
public record GetUserQuestsResponse (int firstQuestIndex,
int secondQuestIndex,
int thirdQuestIndex,
Boolean firstQuestClear,
Boolean secondQuestClear,
Boolean thirdQuestClear){

public static GetUserQuestsResponse toDto(Quest quest){
return GetUserQuestsResponse.builder()
.firstQuestIndex(quest.getQuest1())
.secondQuestIndex(quest.getQuest2())
.thirdQuestIndex(quest.getQuest3())
.firstQuestClear(quest.getQuest1CompletedAt() != null)
.secondQuestClear(quest.getQuest2CompletedAt() != null)
.thirdQuestClear(quest.getQuest3CompletedAt() != null)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ku.user.domain.quest.dto.response;

import ku.user.domain.quest.domain.Quest;
import lombok.Builder;

@Builder
public record PostUserQuestResponse(int firstQuestIndex,
int secondQuestIndex,
int thirdQuestIndex,
Boolean firstQuestClear,
Boolean secondQuestClear,
Boolean thirdQuestClear) {
public static PostUserQuestResponse toDto(Quest quest){
return PostUserQuestResponse.builder()
.firstQuestIndex(quest.getQuest1())
.secondQuestIndex(quest.getQuest2())
.thirdQuestIndex(quest.getQuest3())
.firstQuestClear(quest.getQuest1CompletedAt() != null)
.secondQuestClear(quest.getQuest2CompletedAt() != null)
.thirdQuestClear(quest.getQuest3CompletedAt() != null)
.build();
}
}
78 changes: 78 additions & 0 deletions src/main/java/ku/user/domain/quest/service/QuestService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package ku.user.domain.quest.service;

import ku.user.domain.quest.dao.QuestRepository;
import ku.user.domain.quest.domain.Quest;
import ku.user.domain.quest.util.QuestUtil;
import ku.user.domain.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class QuestService {

private final QuestRepository questRepository;
private final UserService userService;

@Transactional
public Quest save(Quest quest){
return questRepository.save(quest);
}

@Transactional
public Quest findByUserId(Long userId){
return questRepository.findByUserId(userId).get();
}

/**
* 유저의 퀘스트를 조회한다.(가능하면 갱신한다)
*
* @param email
* @return quest
*/
@Transactional
public Quest checkAndRefreshQuest(String email) {
Long userId = userService.getByEmail(email).getId();
LocalDate localDate = LocalDate.now();
Optional<Quest> questOptional = questRepository.findQuestByUserIdAndCompletionDate(userId, localDate);
if(questOptional.isEmpty()){
return createDailyQuest(userId);
}
return questOptional.get();
//return questOptional.orElseGet(() -> createDailyQuest(userId));
}

/**
* 새로운 퀘스트를 생성한다
* @param userId
* @return quest
*/
@Transactional
public Quest createDailyQuest(Long userId) {
List<Integer> randomQuestNumber = QuestUtil.getRandomQuests(3);
Quest quest = Quest.from(userId, randomQuestNumber);
return save(quest);
}

/**
* 퀘스트를 해결한다
* @param questIndex 퀘스트 번호
* @param email
* @return
*/
@Transactional
public Quest solveQuestByEmail(Integer questIndex, String email) {
Long userId = userService.getByEmail(email).getId();
Quest findQuest = findByUserId(userId);
findQuest.solve(questIndex);
return findQuest;
}


}
28 changes: 28 additions & 0 deletions src/main/java/ku/user/domain/quest/util/QuestUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ku.user.domain.quest.util;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;

public class QuestUtil {

private QuestUtil() {
}

public static int QUEST_COUNT = 3;
private static final ThreadLocalRandom random = ThreadLocalRandom.current();

public static Integer getRandomQuest() {
return random.nextInt(QUEST_COUNT);
}

public static List<Integer> getRandomQuests(int count) {
Set<Integer> set = new HashSet<>();
while(set.size()<count){
Integer randomQuest = getRandomQuest() + 1;
set.add(randomQuest);
}
return set.stream().toList();
}
}
18 changes: 3 additions & 15 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,18 @@ spring:
name: user-service

datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${DB_HOST}:3306/kutaverse
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver

# driver-class-name: org.h2.Driver
# url: jdbc:h2:mem:test # 로컬에서 H2 메모리 DB 사용
# username: sa
# password:

h2:
console:
enabled: true
settings:
web-allow-others: true
path: /h2-console

jpa:
database-platform: org.hibernate.dialect.H2Dialect
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: update # DB 초기화 전략
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
show_sql: true
generate-ddl: true
Expand Down
Loading