-
Notifications
You must be signed in to change notification settings - Fork 0
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
[Feat] sologame 기록 저장 #27
Changes from all commits
fa29ab9
0c1c08d
0841c5b
eca5499
70033b9
06fb221
70b2622
c7e82c2
70bd5b7
b8dfe5d
406f0ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package ku.user.domain.Ranking.controller; | ||
|
||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import ku.user.domain.Ranking.domain.SteppingStonesScore; | ||
import ku.user.domain.Ranking.dto.request.SaveRhythmRequest; | ||
import ku.user.domain.Ranking.dto.request.SaveSteppingRequest; | ||
import ku.user.domain.Ranking.dto.response.SaveRhythmResponse; | ||
import ku.user.domain.Ranking.dto.response.SaveSteppingResponse; | ||
import ku.user.domain.Ranking.service.RhythmScoreService; | ||
import ku.user.global.response.ApiResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
public class RhythmScoreController { | ||
private final RhythmScoreService rhythmScoreService; | ||
|
||
// 저장 | ||
@PostMapping("/rhythm") | ||
public ApiResponse<SaveRhythmResponse> saveStepping(@RequestBody SaveRhythmRequest saveSteppingRequest){ | ||
RhythmScore rhythmScore = SaveRhythmRequest.toEntity(saveSteppingRequest); | ||
RhythmScore savedScore = rhythmScoreService.saveScore(rhythmScore); | ||
SaveRhythmResponse response = SaveRhythmResponse.fromEntity(savedScore); | ||
|
||
return new ApiResponse<>(true, response, null); | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package ku.user.domain.Ranking.controller; | ||
|
||
import ku.user.domain.Ranking.domain.SteppingStonesScore; | ||
import ku.user.domain.Ranking.dto.request.SaveSteppingRequest; | ||
import ku.user.domain.Ranking.dto.response.SaveSteppingResponse; | ||
import ku.user.domain.Ranking.service.SteppingStonesScoreService; | ||
import ku.user.global.response.ApiResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
public class SteppingStonesScoreController { | ||
private final SteppingStonesScoreService steppingStonesScoreService; | ||
// 저장 | ||
@PostMapping("/stepping") | ||
public ApiResponse<SaveSteppingResponse> saveStepping(@RequestBody SaveSteppingRequest saveSteppingRequest){ | ||
SteppingStonesScore steppingStonesScore = SaveSteppingRequest.toEntity(saveSteppingRequest); | ||
SteppingStonesScore savedScore = steppingStonesScoreService.saveScore(steppingStonesScore); | ||
SaveSteppingResponse response = SaveSteppingResponse.fromEntity(savedScore); | ||
|
||
return new ApiResponse<>(true, response, null); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package ku.user.domain.Ranking.domain; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.*; | ||
import org.hibernate.annotations.CreationTimestamp; | ||
|
||
import java.time.LocalDateTime; | ||
// 점수, 캐릭터명, 날짜, 재화 | ||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor | ||
@Builder | ||
@Getter | ||
@Table(name = "rhythm_scores") | ||
public class RhythmScore { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "nickname", nullable = false, length = 50) | ||
private String nickName; | ||
|
||
@Column(nullable = false) | ||
private int score; | ||
|
||
@Column(name = "created_at", nullable = false, updatable = false) | ||
@CreationTimestamp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이건 처음 보네요 |
||
private LocalDateTime createdAt; | ||
|
||
@Setter | ||
@Enumerated(EnumType.STRING) | ||
@Column(name = "status", nullable = false) | ||
private Status status = Status.ACTIVE; | ||
|
||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1주일에 대한 랭킹 제공이라면 게임 전적에 대한 랭킹 포함 여부를 결정하는 enum으로 이해했어요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저거는 사용자가 캐릭터를 삭제할 경우 기록에서 표시하기 위한 필드였습니다. 랭킹에 대해서는 고민하고 있는 부분이 있는데 회의에서 이야기 하도록 하겠습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package ku.user.domain.Ranking.domain; | ||
|
||
public enum Status { | ||
ACTIVE("활성화"), | ||
INACTIVE("비활성화"); | ||
|
||
private final String description; | ||
|
||
Status(String description) { | ||
this.description = description; | ||
} | ||
|
||
public String getDescription() { | ||
return description; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package ku.user.domain.Ranking.domain; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.*; | ||
import org.hibernate.annotations.CreationTimestamp; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Entity | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor | ||
@Builder | ||
@Getter | ||
@Table(name = "stepping_stones_score") | ||
public class SteppingStonesScore { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(name = "nickname", nullable = false, length = 50) | ||
private String nickName; | ||
|
||
@Column(nullable = false) | ||
private int score; | ||
|
||
@Column(nullable = false) | ||
private int coin; | ||
|
||
@Column(name = "created_at", nullable = false, updatable = false) | ||
@CreationTimestamp | ||
private LocalDateTime createdAt; | ||
|
||
@Setter | ||
@Enumerated(EnumType.STRING) | ||
@Column(name = "status", nullable = false) | ||
private Status status = Status.ACTIVE; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package ku.user.domain.Ranking.dto.request; | ||
|
||
import jakarta.validation.constraints.Min; | ||
import jakarta.validation.constraints.NotBlank; | ||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import ku.user.domain.Ranking.domain.Status; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class SaveRhythmRequest { | ||
@NotBlank(message = "닉네임은 필수 항목") | ||
private String nickName; | ||
|
||
@Min(value = 0, message = "점수는 0 이상이어야 합니다.") | ||
private int score; | ||
|
||
|
||
public static RhythmScore toEntity(SaveRhythmRequest saveRhythmRequest){ | ||
return RhythmScore.builder() | ||
.nickName(saveRhythmRequest.getNickName()) | ||
.score(saveRhythmRequest.getScore()) | ||
.status(Status.ACTIVE) | ||
.build(); | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package ku.user.domain.Ranking.dto.request; | ||
|
||
import jakarta.validation.constraints.Min; | ||
import jakarta.validation.constraints.NotBlank; | ||
import ku.user.domain.Ranking.domain.Status; | ||
import ku.user.domain.Ranking.domain.SteppingStonesScore; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
public class SaveSteppingRequest { | ||
@NotBlank(message = "닉네임은 필수 항목") | ||
private String nickName; | ||
|
||
@Min(value = 0, message = "점수는 0 이상이어야 합니다.") | ||
private int score; | ||
|
||
@Min(value = 0, message = "코인은 0 이상이어야 합니다.") | ||
private int coin; | ||
|
||
public static SteppingStonesScore toEntity(SaveSteppingRequest saveSteppingRequest){ | ||
return SteppingStonesScore.builder() | ||
.nickName(saveSteppingRequest.getNickName()) | ||
.score(saveSteppingRequest.getScore()) | ||
.coin(saveSteppingRequest.getCoin()) | ||
.status(Status.ACTIVE) | ||
.build(); | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package ku.user.domain.Ranking.dto.response; | ||
|
||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import ku.user.domain.Ranking.domain.SteppingStonesScore; | ||
|
||
public record SaveRhythmResponse(Long id, String nickName, int score) { | ||
public static SaveRhythmResponse fromEntity(RhythmScore rhythmScore) { | ||
return new SaveRhythmResponse( | ||
rhythmScore.getId(), | ||
rhythmScore.getNickName(), | ||
rhythmScore.getScore() | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package ku.user.domain.Ranking.dto.response; | ||
|
||
import ku.user.domain.Ranking.domain.SteppingStonesScore; | ||
|
||
public record SaveSteppingResponse(Long id, String nickName, int score, int coin) { | ||
public static SaveSteppingResponse fromEntity(SteppingStonesScore steppingStonesScore) { | ||
return new SaveSteppingResponse( | ||
steppingStonesScore.getId(), | ||
steppingStonesScore.getNickName(), | ||
steppingStonesScore.getScore(), | ||
steppingStonesScore.getCoin() | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package ku.user.domain.Ranking.infrastructure; | ||
|
||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@Repository | ||
public interface RhythmScoreRepository extends JpaRepository<RhythmScore,Long> { | ||
List<RhythmScore> findRhythmScoresByNickName(String nickname); | ||
|
||
Optional<RhythmScore> findTopByNickNameOrderByScoreDesc(String nickName); | ||
|
||
List<RhythmScore> findByNickNameAndCreatedAtBetween(String nickName, LocalDateTime startDate, LocalDateTime endDate); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package ku.user.domain.Ranking.infrastructure; | ||
|
||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import ku.user.domain.Ranking.domain.SteppingStonesScore; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@Repository | ||
public interface SteppingScoreRepository extends JpaRepository<SteppingStonesScore,Long> { | ||
List<SteppingStonesScore> findSteppingStonesScoresByNickName(String nickname); | ||
|
||
Optional<SteppingStonesScore> findTopByNickNameOrderByScoreDesc(String nickName); | ||
|
||
List<SteppingStonesScore> findByNickNameAndCreatedAtBetween(String nickName, LocalDateTime startDate, LocalDateTime endDate); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package ku.user.domain.Ranking.service; | ||
|
||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import ku.user.domain.Ranking.domain.Status; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
public interface RhythmScoreService { | ||
// 생성 | ||
RhythmScore saveScore(RhythmScore rhythmScore); | ||
|
||
// 조회(해당 캐릭터의 모든 기록) | ||
List<RhythmScore> findScoresByNickName(String nickName); | ||
|
||
// 조회(해당 캐릭터의 특정 날짜 기록) | ||
List<RhythmScore> findScoresByNickNameAndDate(String nickName, LocalDateTime startDate, LocalDateTime endDate); | ||
|
||
// 캐릭터 삭제 | ||
void updateScoreStatus(String nickName); | ||
|
||
// 해당 캐릭터의 최고 기록 | ||
RhythmScore findHighestScoreByNickName(String nickName); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package ku.user.domain.Ranking.service; | ||
|
||
import ku.user.domain.Ranking.domain.RhythmScore; | ||
import ku.user.domain.Ranking.domain.Status; | ||
import ku.user.domain.Ranking.infrastructure.RhythmScoreRepository; | ||
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 RhythmScoreServiceImpl implements RhythmScoreService{ | ||
private final RhythmScoreRepository repository; | ||
|
||
@Transactional | ||
public RhythmScore saveScore(RhythmScore rhythmScore) { | ||
return repository.save(rhythmScore); | ||
} | ||
|
||
|
||
public List<RhythmScore> findScoresByNickName(String nickName) { | ||
List<RhythmScore> scores = repository.findRhythmScoresByNickName(nickName); | ||
return scores; | ||
} | ||
|
||
|
||
public List<RhythmScore> findScoresByNickNameAndDate(String nickName, LocalDateTime startDate, LocalDateTime endDate) { | ||
return repository.findByNickNameAndCreatedAtBetween(nickName, startDate, endDate); | ||
} | ||
|
||
@Transactional | ||
public void updateScoreStatus(String nickName) { | ||
List<RhythmScore> scores = repository.findRhythmScoresByNickName(nickName); | ||
|
||
if (scores.isEmpty()) { | ||
throw new IllegalArgumentException("해당 닉네임의 기록은 존재하지 않음: " + nickName); | ||
} | ||
|
||
boolean hasActiveRecord = false; | ||
for (RhythmScore score : scores) { | ||
if (score.getStatus() == Status.ACTIVE) { | ||
score.setStatus(Status.INACTIVE); | ||
hasActiveRecord = true; | ||
} | ||
} | ||
|
||
if (!hasActiveRecord) { | ||
System.out.println("이미 비활성화 되어 있는 캐릭터입니다."); | ||
return; | ||
} | ||
|
||
repository.saveAll(scores); | ||
} | ||
|
||
|
||
public RhythmScore findHighestScoreByNickName(String nickName) { | ||
Optional<RhythmScore> optionalScore = repository.findTopByNickNameOrderByScoreDesc(nickName); | ||
return optionalScore.orElse(null); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
restful API에서는 rhythms으로 하지 않나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그게 더 맞을거 같네요