[chuni] Save recent rating to database

[ongeki] Save recent rating to database
master
samnyan 2020-03-29 16:10:35 +09:00
parent 528b2f8b4d
commit 0cf510fb02
10 changed files with 223 additions and 20 deletions

View File

@ -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<Object> getGeneralData(@RequestParam String aimeId, @RequestParam String key) {
Optional<UserGeneralData> userGeneralDataOptional = userGeneralDataService.getByUserIdAndKey(aimeId,key);
return userGeneralDataOptional.<ResponseEntity<Object>>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;

View File

@ -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<UserGeneralData, Long> {
Optional<UserGeneralData> findByUserAndPropertyKey(UserData user, String key);
Optional<UserGeneralData> findByUser_Card_ExtIdAndPropertyKey(int extId, String key);
}

View File

@ -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<String, Object> request) throws JsonProcessingException {
String userId = (String) request.get("userId");
List<UserPlaylog> top = userPlaylogService.getRecent30Plays(userId);
List<UserRecentRating> rating = top.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1030000", log.getScore()))
.collect(Collectors.toList());
Optional<UserGeneralData> recentOptional = userGeneralDataService.getByUserIdAndKey(userId, "recent_rating_list");
List<UserRecentRating> 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<UserPlaylog> top = userPlaylogService.getRecent30Plays(userId);
ratingList = top.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1030000", log.getScore()))
.collect(Collectors.toList());
}
Map<String, Object> 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);

View File

@ -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<UserRecentRating> 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) {

View File

@ -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 = "";
}
}

View File

@ -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<UserGeneralData> getByUserAndKey(UserData user, String key) {
return userGeneralDataRepository.findByUserAndPropertyKey(user, key);
}
public Optional<UserGeneralData> getByUserIdAndKey(String userId, String key) {
return userGeneralDataRepository.findByUser_Card_ExtIdAndPropertyKey(Integer.parseInt(userId), key);
}
}

View File

@ -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<String, Object> request) throws JsonProcessingException {
Integer userId = (Integer) request.get("userId");
Pageable page = PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "id"));
List<UserPlaylog> playlogList = userPlaylogRepository.findByUser_Card_ExtId(userId, page).getContent();
List<UserRecentRating> ratingList = playlogList.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1000000", log.getTechScore()))
.collect(Collectors.toList());
Optional<UserGeneralData> recentOptional = userGeneralDataRepository.findByUser_Card_ExtIdAndPropertyKey(userId, "recent_rating_list");
List<UserRecentRating> 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<UserPlaylog> 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<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("userId", userId);

View File

@ -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.

View File

@ -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)
);

View File

@ -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
);