diff --git a/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/amazon/ApiAmazonController.java b/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/amazon/ApiAmazonController.java index fb0bb0a..f6a4d3b 100644 --- a/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/amazon/ApiAmazonController.java +++ b/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/amazon/ApiAmazonController.java @@ -56,11 +56,12 @@ public class ApiAmazonController { private final UserMapService userMapService; private final UserMusicDetailService userMusicDetailService; private final UserPlaylogService userPlaylogService; + private final UserGeneralDataService userGeneralDataService; private final GameMusicService gameMusicService; @Autowired - public ApiAmazonController(ApiMapper mapper, CardService cardService, UserActivityService userActivityService, UserCharacterService userCharacterService, UserChargeService userChargeService, UserDataService userDataService, UserDataExService userDataExService, UserGameOptionExService userGameOptionExService, UserMapService userMapService, UserPlaylogService userPlaylogService, UserMusicDetailService userMusicDetailService, UserCourseService userCourseService, UserDuelService userDuelService, UserGameOptionService userGameOptionService, UserItemService userItemService, GameMusicService gameMusicService) { + public ApiAmazonController(ApiMapper mapper, CardService cardService, UserActivityService userActivityService, UserCharacterService userCharacterService, UserChargeService userChargeService, UserDataService userDataService, UserDataExService userDataExService, UserGameOptionExService userGameOptionExService, UserMapService userMapService, UserPlaylogService userPlaylogService, UserMusicDetailService userMusicDetailService, UserCourseService userCourseService, UserDuelService userDuelService, UserGameOptionService userGameOptionService, UserItemService userItemService, UserGeneralDataService userGeneralDataService, GameMusicService gameMusicService) { this.mapper = mapper; this.cardService = cardService; this.userActivityService = userActivityService; @@ -76,6 +77,7 @@ public class ApiAmazonController { this.userDuelService = userDuelService; this.userGameOptionService = userGameOptionService; this.userItemService = userItemService; + this.userGeneralDataService = userGeneralDataService; this.gameMusicService = gameMusicService; } @@ -306,6 +308,13 @@ public class ApiAmazonController { return ResponseEntity.ok(new MessageResponse("Import successfully, aimeId: " + card.getExtId())); } + @GetMapping("general") + public ResponseEntity getGeneralData(@RequestParam String aimeId, @RequestParam String key) { + Optional userGeneralDataOptional = userGeneralDataService.getByUserIdAndKey(aimeId,key); + return userGeneralDataOptional.>map(ResponseEntity::ok) + .orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse("User or value not found."))); + } + private int calculateRating(int levelBase, int score) { if (score >= 1007500) return levelBase + 200; if (score >= 1005000) return levelBase + 150 + (score - 1005000) * 10 / 500; diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/dao/userdata/UserGeneralDataRepository.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/dao/userdata/UserGeneralDataRepository.java new file mode 100644 index 0000000..683c2d7 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/dao/userdata/UserGeneralDataRepository.java @@ -0,0 +1,20 @@ +package icu.samnyan.aqua.sega.chunithm.dao.userdata; + +import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData; +import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGeneralData; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +/** + * @author samnyan (privateamusement@protonmail.com) + */ +@Repository("ChuniUserGeneralDataRepository") +public interface UserGeneralDataRepository extends JpaRepository { + + Optional findByUserAndPropertyKey(UserData user, String key); + + Optional findByUser_Card_ExtIdAndPropertyKey(int extId, String key); + +} diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java index 737389d..753512d 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java +++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/GetUserRecentRatingHandler.java @@ -2,18 +2,19 @@ package icu.samnyan.aqua.sega.chunithm.handler.impl; import com.fasterxml.jackson.core.JsonProcessingException; import icu.samnyan.aqua.sega.chunithm.handler.BaseHandler; +import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGeneralData; +import icu.samnyan.aqua.sega.chunithm.service.UserGeneralDataService; import icu.samnyan.aqua.sega.general.model.response.UserRecentRating; import icu.samnyan.aqua.sega.chunithm.model.userdata.UserPlaylog; import icu.samnyan.aqua.sega.chunithm.service.UserPlaylogService; import icu.samnyan.aqua.sega.util.jackson.StringMapper; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -29,25 +30,48 @@ public class GetUserRecentRatingHandler implements BaseHandler { private final StringMapper mapper; private final UserPlaylogService userPlaylogService; + private final UserGeneralDataService userGeneralDataService; @Autowired - public GetUserRecentRatingHandler(StringMapper mapper, UserPlaylogService userPlaylogService) { + public GetUserRecentRatingHandler(StringMapper mapper, UserPlaylogService userPlaylogService, UserGeneralDataService userGeneralDataService) { this.mapper = mapper; this.userPlaylogService = userPlaylogService; + this.userGeneralDataService = userGeneralDataService; } @Override public String handle(Map request) throws JsonProcessingException { String userId = (String) request.get("userId"); - List top = userPlaylogService.getRecent30Plays(userId); - List rating = top.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1030000", log.getScore())) - .collect(Collectors.toList()); + Optional recentOptional = userGeneralDataService.getByUserIdAndKey(userId, "recent_rating_list"); + + List ratingList; + if(recentOptional.isPresent()) { + ratingList = new LinkedList<>(); + String val = recentOptional.get().getPropertyValue(); + if(StringUtils.isNotBlank(val) && val.contains(",")) { + String[] records = val.split(","); + for (String record : + records) { + String[] value = record.split(":"); + ratingList.add(new UserRecentRating( + Integer.parseInt(value[0]), + Integer.parseInt(value[1]), + "1030000", + Integer.parseInt(value[2]) + )); + } + } + } else { + List top = userPlaylogService.getRecent30Plays(userId); + ratingList = top.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1030000", log.getScore())) + .collect(Collectors.toList()); + } Map resultMap = new LinkedHashMap<>(); resultMap.put("userId", userId); - resultMap.put("length", rating.size()); - resultMap.put("userRecentRatingList", rating); + resultMap.put("length", ratingList.size()); + resultMap.put("userRecentRatingList", ratingList); String json = mapper.write(resultMap); logger.info("Response: " + json); diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/UpsertUserAllHandler.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/UpsertUserAllHandler.java index afcb0d4..4fb5499 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/UpsertUserAllHandler.java +++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/handler/impl/UpsertUserAllHandler.java @@ -7,6 +7,7 @@ import icu.samnyan.aqua.sega.chunithm.model.response.CodeResp; import icu.samnyan.aqua.sega.chunithm.model.userdata.*; import icu.samnyan.aqua.sega.chunithm.service.*; import icu.samnyan.aqua.sega.general.model.Card; +import icu.samnyan.aqua.sega.general.model.response.UserRecentRating; import icu.samnyan.aqua.sega.general.service.CardService; import icu.samnyan.aqua.sega.util.jackson.StringMapper; import org.slf4j.Logger; @@ -44,9 +45,10 @@ public class UpsertUserAllHandler implements BaseHandler { private final UserDataExService userDataExService; private final UserCourseService userCourseService; private final UserDuelService userDuelService; + private final UserGeneralDataService userGeneralDataService; @Autowired - public UpsertUserAllHandler(StringMapper mapper, CardService cardService, UserDataService userDataService, UserCharacterService userCharacterService, UserGameOptionService userGameOptionService, UserGameOptionExService userGameOptionExService, UserMapService userMapService, UserItemService userItemService, UserMusicDetailService userMusicDetailService, UserActivityService userActivityService, UserPlaylogService userPlaylogService, UserChargeService userChargeService, UserDataExService userDataExService, UserCourseService userCourseService, UserDuelService userDuelService) { + public UpsertUserAllHandler(StringMapper mapper, CardService cardService, UserDataService userDataService, UserCharacterService userCharacterService, UserGameOptionService userGameOptionService, UserGameOptionExService userGameOptionExService, UserMapService userMapService, UserItemService userItemService, UserMusicDetailService userMusicDetailService, UserActivityService userActivityService, UserPlaylogService userPlaylogService, UserChargeService userChargeService, UserDataExService userDataExService, UserCourseService userCourseService, UserDuelService userDuelService, UserGeneralDataService userGeneralDataService) { this.mapper = mapper; this.cardService = cardService; this.userDataService = userDataService; @@ -62,6 +64,7 @@ public class UpsertUserAllHandler implements BaseHandler { this.userDataExService = userDataExService; this.userCourseService = userCourseService; this.userDuelService = userDuelService; + this.userGeneralDataService = userGeneralDataService; } @@ -232,6 +235,23 @@ public class UpsertUserAllHandler implements BaseHandler { } // userRecentRatingList + if(upsertUserAll.getUserRecentRatingList() != null) { + List userRecentRatingList = upsertUserAll.getUserRecentRatingList(); + + StringBuilder sb = new StringBuilder(); + userRecentRatingList.forEach(userRecentRating -> { + sb.append(userRecentRating.getMusicId()).append(":"); + sb.append(userRecentRating.getDifficultId()).append(":"); + sb.append(userRecentRating.getScore()).append(","); + }); + if(sb.length() > 0) { + sb.deleteCharAt(sb.length() - 1); + } + UserGeneralData userGeneralData = userGeneralDataService.getByUserAndKey(newUserData, "recent_rating_list") + .orElseGet(() -> new UserGeneralData(newUserData, "recent_rating_list")); + userGeneralData.setPropertyValue(sb.toString()); + userGeneralDataService.save(userGeneralData); + } // userChargeList if (upsertUserAll.getUserChargeList() != null) { diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/model/userdata/UserGeneralData.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/model/userdata/UserGeneralData.java new file mode 100644 index 0000000..c81cefa --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/model/userdata/UserGeneralData.java @@ -0,0 +1,43 @@ +package icu.samnyan.aqua.sega.chunithm.model.userdata; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * This is for storing the other data that doesn't need to save it in a separate table + * @author samnyan (privateamusement@protonmail.com) + */ +@Entity(name = "ChuniUserGeneralData") +@Table(name = "chuni_user_general_data") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserGeneralData implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @JsonIgnore + private long id; + + @JsonIgnore + @ManyToOne + @JoinColumn(name = "user_id") + private UserData user; + + private String propertyKey; + + private String propertyValue; + + public UserGeneralData(UserData userData, String key) { + this.user = userData; + this.propertyKey = key; + this.propertyValue = ""; + } +} diff --git a/src/main/java/icu/samnyan/aqua/sega/chunithm/service/UserGeneralDataService.java b/src/main/java/icu/samnyan/aqua/sega/chunithm/service/UserGeneralDataService.java new file mode 100644 index 0000000..affc1b9 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/chunithm/service/UserGeneralDataService.java @@ -0,0 +1,34 @@ +package icu.samnyan.aqua.sega.chunithm.service; + +import icu.samnyan.aqua.sega.chunithm.dao.userdata.UserGeneralDataRepository; +import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData; +import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGeneralData; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +/** + * @author samnyan (privateamusement@protonmail.com) + */ +@Service("ChuniUserGeneralDataService") +public class UserGeneralDataService { + + private final UserGeneralDataRepository userGeneralDataRepository; + + public UserGeneralDataService(UserGeneralDataRepository userGeneralDataRepository) { + this.userGeneralDataRepository = userGeneralDataRepository; + } + + public UserGeneralData save(UserGeneralData userGeneralData) { + return userGeneralDataRepository.save(userGeneralData); + } + + public Optional getByUserAndKey(UserData user, String key) { + return userGeneralDataRepository.findByUserAndPropertyKey(user, key); + } + + public Optional getByUserIdAndKey(String userId, String key) { + return userGeneralDataRepository.findByUser_Card_ExtIdAndPropertyKey(Integer.parseInt(userId), key); + } + +} diff --git a/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/GetUserRecentRatingHandler.java b/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/GetUserRecentRatingHandler.java index 11c0060..721f356 100644 --- a/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/GetUserRecentRatingHandler.java +++ b/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/GetUserRecentRatingHandler.java @@ -2,10 +2,13 @@ package icu.samnyan.aqua.sega.ongeki.handler.impl; import com.fasterxml.jackson.core.JsonProcessingException; import icu.samnyan.aqua.sega.general.model.response.UserRecentRating; +import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserGeneralDataRepository; import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserPlaylogRepository; import icu.samnyan.aqua.sega.ongeki.handler.BaseHandler; +import icu.samnyan.aqua.sega.ongeki.model.userdata.UserGeneralData; import icu.samnyan.aqua.sega.ongeki.model.userdata.UserPlaylog; import icu.samnyan.aqua.sega.util.jackson.BasicMapper; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -14,9 +17,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Component; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -30,11 +31,13 @@ public class GetUserRecentRatingHandler implements BaseHandler { private final BasicMapper mapper; private final UserPlaylogRepository userPlaylogRepository; + private final UserGeneralDataRepository userGeneralDataRepository; @Autowired - public GetUserRecentRatingHandler(BasicMapper mapper, UserPlaylogRepository userPlaylogRepository) { + public GetUserRecentRatingHandler(BasicMapper mapper, UserPlaylogRepository userPlaylogRepository, UserGeneralDataRepository userGeneralDataRepository) { this.mapper = mapper; this.userPlaylogRepository = userPlaylogRepository; + this.userGeneralDataRepository = userGeneralDataRepository; } @@ -42,10 +45,31 @@ public class GetUserRecentRatingHandler implements BaseHandler { public String handle(Map request) throws JsonProcessingException { Integer userId = (Integer) request.get("userId"); - Pageable page = PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "id")); - List playlogList = userPlaylogRepository.findByUser_Card_ExtId(userId, page).getContent(); - List ratingList = playlogList.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1000000", log.getTechScore())) - .collect(Collectors.toList()); + Optional recentOptional = userGeneralDataRepository.findByUser_Card_ExtIdAndPropertyKey(userId, "recent_rating_list"); + + List ratingList; + if(recentOptional.isPresent()) { + ratingList = new LinkedList<>(); + String val = recentOptional.get().getPropertyValue(); + if(StringUtils.isNotBlank(val) && val.contains(",")) { + String[] records = val.split(","); + for (String record : + records) { + String[] value = record.split(":"); + ratingList.add(new UserRecentRating( + Integer.parseInt(value[0]), + Integer.parseInt(value[1]), + "1000000", + Integer.parseInt(value[2]) + )); + } + } + } else { + Pageable page = PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "id")); + List playlogList = userPlaylogRepository.findByUser_Card_ExtId(userId, page).getContent(); + ratingList = playlogList.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1000000", log.getTechScore())) + .collect(Collectors.toList()); + } Map resultMap = new LinkedHashMap<>(); resultMap.put("userId", userId); diff --git a/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/UpsertUserAllHandler.java b/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/UpsertUserAllHandler.java index 510a03b..4834975 100644 --- a/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/UpsertUserAllHandler.java +++ b/src/main/java/icu/samnyan/aqua/sega/ongeki/handler/impl/UpsertUserAllHandler.java @@ -159,7 +159,10 @@ public class UpsertUserAllHandler implements BaseHandler { } // UserRecentRatingList - // This doesn't need to save. It can get from playlog + // This thing still need to save to solve the rating drop + if (upsertUserAll.containsKey("userRecentRatingList")) { + this.saveGeneralData(upsertUserAll, newUserData, "userRecentRatingList", "recent_rating_list"); + } /* * The rating and battle point calculation is little bit complex. diff --git a/src/main/resources/db/migration/mysql/V19__add_chuni_general_data.sql b/src/main/resources/db/migration/mysql/V19__add_chuni_general_data.sql new file mode 100644 index 0000000..86f97e0 --- /dev/null +++ b/src/main/resources/db/migration/mysql/V19__add_chuni_general_data.sql @@ -0,0 +1,12 @@ +create table chuni_user_general_data +( + id bigint auto_increment + primary key, + property_key varchar(255) not null, + property_value text not null, + user_id bigint null, + constraint UK2up23a6n1ghlf5gewa4tm5f2d + unique (user_id, property_key), + constraint FK2dkb8agh5ye1f15g5hbcv63uj + foreign key (user_id) references chuni_user_data (id) +); \ No newline at end of file diff --git a/src/main/resources/db/migration/sqlite/V19__add_chuni_general_data.sql b/src/main/resources/db/migration/sqlite/V19__add_chuni_general_data.sql new file mode 100644 index 0000000..7ff7734 --- /dev/null +++ b/src/main/resources/db/migration/sqlite/V19__add_chuni_general_data.sql @@ -0,0 +1,14 @@ +CREATE TABLE chuni_user_general_data +( + id INTEGER, + property_key VARCHAR NOT NULL, + property_value VARCHAR NOT NULL, + user_id BIGINT REFERENCES chuni_user_data (id) ON DELETE CASCADE, + PRIMARY KEY ( + id + ), + CONSTRAINT chuni_user_general_data_uq UNIQUE ( + property_key, + user_id + ) ON CONFLICT REPLACE +); \ No newline at end of file