[ongeki,api] support ongeki rival

pull/1/head
Mikira Sora 2022-12-17 11:50:36 +00:00 committed by Dom Eori
parent 9a80592e38
commit da793e9881
21 changed files with 461 additions and 21 deletions

View File

@ -45,6 +45,8 @@ game.chusan.team-name=
## The version of your client. Match this with DataConfig.xml file in latest option. (only if bright memory and up)
## For example, if DataConfig.xml says "<major>1</major>, <minor>35</minor>, <release>1</release>" then this need to be 1.35.01
game.ongeki.version=1.05.00
## Limit rival list size for per user, it will be unlimited if this value <= 0 (CAUTION!).
game.ongeki.rival.rivals-max-count=10
## Maimai DX
## Set this true if you are using old version of Splash network patch and have no other choice.

View File

@ -2,6 +2,7 @@ package icu.samnyan.aqua.api.controller.sega.game.ongeki;
import com.fasterxml.jackson.core.type.TypeReference;
import icu.samnyan.aqua.api.model.MessageResponse;
import icu.samnyan.aqua.api.model.ObjectMessageResponse;
import icu.samnyan.aqua.api.model.ReducedPageResponse;
import icu.samnyan.aqua.api.model.resp.sega.ongeki.ProfileResp;
import icu.samnyan.aqua.api.model.resp.sega.ongeki.external.ExternalUserData;
@ -13,7 +14,9 @@ import icu.samnyan.aqua.sega.general.service.CardService;
import icu.samnyan.aqua.sega.ongeki.dao.gamedata.GameCardRepository;
import icu.samnyan.aqua.sega.ongeki.dao.userdata.*;
import icu.samnyan.aqua.sega.ongeki.model.gamedata.GameCard;
import icu.samnyan.aqua.sega.ongeki.model.response.data.UserRivalData;
import icu.samnyan.aqua.sega.ongeki.model.userdata.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
@ -61,6 +64,7 @@ public class ApiOngekiPlayerDataController {
private final UserEventMusicRepository userEventMusicRepository;
private final UserTechEventRepository userTechEventRepository;
private final UserKopRepository userKopRepository;
private final UserRivalDataRepository userRivalDataRepository;
private final UserMemoryChapterRepository userMemoryChapterRepository;
@ -72,7 +76,7 @@ public class ApiOngekiPlayerDataController {
private final GameCardRepository gameCardRepository;
public ApiOngekiPlayerDataController(ApiMapper mapper, CardService cardService, UserActivityRepository userActivityRepository, UserCardRepository userCardRepository, UserChapterRepository userChapterRepository, UserCharacterRepository userCharacterRepository, UserDataRepository userDataRepository, UserDeckRepository userDeckRepository, UserEventPointRepository userEventPointRepository, UserItemRepository userItemRepository, UserLoginBonusRepository userLoginBonusRepository, UserMissionPointRepository userMissionPointRepository, UserMusicDetailRepository userMusicDetailRepository, UserMusicItemRepository userMusicItemRepository, UserOptionRepository userOptionRepository, UserPlaylogRepository userPlaylogRepository, UserStoryRepository userStoryRepository, UserTrainingRoomRepository userTrainingRoomRepository, UserGeneralDataRepository userGeneralDataRepository, GameCardRepository gameCardRepository, UserTradeItemRepository userTradeItemRepository, UserEventMusicRepository userEventMusicRepository, UserTechEventRepository userTechEventRepository, UserKopRepository userKopRepository, UserMemoryChapterRepository userMemoryChapterRepository, UserScenarioRepository userScenarioRepository, UserBossRepository userBossRepository, UserTechCountRepository userTechCountRepository) {
public ApiOngekiPlayerDataController(ApiMapper mapper, CardService cardService, UserRivalDataRepository userRivalDataRepository, UserActivityRepository userActivityRepository, UserCardRepository userCardRepository, UserChapterRepository userChapterRepository, UserCharacterRepository userCharacterRepository, UserDataRepository userDataRepository, UserDeckRepository userDeckRepository, UserEventPointRepository userEventPointRepository, UserItemRepository userItemRepository, UserLoginBonusRepository userLoginBonusRepository, UserMissionPointRepository userMissionPointRepository, UserMusicDetailRepository userMusicDetailRepository, UserMusicItemRepository userMusicItemRepository, UserOptionRepository userOptionRepository, UserPlaylogRepository userPlaylogRepository, UserStoryRepository userStoryRepository, UserTrainingRoomRepository userTrainingRoomRepository, UserGeneralDataRepository userGeneralDataRepository, GameCardRepository gameCardRepository, UserTradeItemRepository userTradeItemRepository, UserEventMusicRepository userEventMusicRepository, UserTechEventRepository userTechEventRepository, UserKopRepository userKopRepository, UserMemoryChapterRepository userMemoryChapterRepository, UserScenarioRepository userScenarioRepository, UserBossRepository userBossRepository, UserTechCountRepository userTechCountRepository) {
this.mapper = mapper;
this.cardService = cardService;
this.userActivityRepository = userActivityRepository;
@ -101,6 +105,7 @@ public class ApiOngekiPlayerDataController {
this.userScenarioRepository = userScenarioRepository;
this.userBossRepository = userBossRepository;
this.userTechCountRepository = userTechCountRepository;
this.userRivalDataRepository = userRivalDataRepository;
}
@GetMapping("profile")
@ -334,6 +339,51 @@ public class ApiOngekiPlayerDataController {
return userPlaylogRepository.findByUser_Card_ExtIdAndMusicIdAndLevel(aimeId, id, level);
}
@GetMapping("rival")
public List<UserRivalData> getRival(@RequestParam long aimeId) {
var rivalUserIds = userRivalDataRepository.findByUser_Card_ExtId(aimeId)
.stream()
.map(x -> x.getRivalUserId())
.collect(Collectors.toList());
var rivalDataList = userDataRepository.findByCard_ExtIdIn(rivalUserIds)
.stream()
.map(x -> new UserRivalData(x.getCard().getExtId().longValue(), x.getUserName()))
.collect(Collectors.toList());
return rivalDataList;
}
@DeleteMapping("rival")
public MessageResponse deleteRival(@RequestParam long aimeId, @RequestParam long rivalAimeId) {
userRivalDataRepository.removeByUser_Card_ExtIdAndRivalUserId(aimeId, rivalAimeId);
return new MessageResponse();
}
@PostMapping("rival")
public ObjectMessageResponse<UserRivalData> addRival(@RequestParam long aimeId, @RequestParam long rivalAimeId, @Value("${game.ongeki.rival.rivals-max-count:10}") long addMaxCount) {
//check limit
if (addMaxCount >= 0 && userRivalDataRepository.findByUser_Card_ExtId(aimeId).size() >= addMaxCount) {
return new ObjectMessageResponse<>(String.format("Size of rival list is limited in %d", addMaxCount));
}
var userOpt = userDataRepository.findByCard_ExtId(aimeId);
if (userOpt.isEmpty())
return new ObjectMessageResponse<>("Current user isn't ongeki player.");
var user = userOpt.get();
var rivalUserOpt = userDataRepository.findByCard_ExtId(rivalAimeId);
if (rivalUserOpt.isEmpty())
return new ObjectMessageResponse<>("Rival user isn't ongeki player.");
var rivalUser = rivalUserOpt.get();
var rival = new UserRival();
rival.setUser(user);
rival.setRivalUserId(rivalUser.getCard().getExtId());
userRivalDataRepository.save(rival);
return new ObjectMessageResponse<>(new UserRivalData(rivalUser.getCard().getExtId(), rivalUser.getUserName()));
}
@GetMapping("options")
public UserOption getOptions(@RequestParam long aimeId) {
return userOptionRepository.findByUser_Card_ExtId(aimeId).orElseThrow();
@ -376,6 +426,7 @@ public class ApiOngekiPlayerDataController {
data.setUserScenarioList(userScenarioRepository.findByUser_Card_ExtId(aimeId));
data.setUserBossList(userBossRepository.findByUser_Card_ExtId(aimeId));
data.setUserTechCountList(userTechCountRepository.findByUser_Card_ExtId(aimeId));
data.setUserRivalList(userRivalDataRepository.findByUser_Card_ExtId(aimeId));
} catch (NoSuchElementException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new MessageResponse("User not found"));
@ -454,6 +505,8 @@ public class ApiOngekiPlayerDataController {
userBossRepository.flush();
userTechCountRepository.deleteByUser(existUserData.get());
userTechCountRepository.flush();
userRivalDataRepository.deleteByUser(existUserData.get());
userRivalDataRepository.flush();
userDataRepository.deleteByCard(card);
userDataRepository.flush();
@ -539,6 +592,9 @@ public class ApiOngekiPlayerDataController {
userTechCountRepository.saveAll(Optional.ofNullable(data.getUserTechCountList()).orElse(Collections.emptyList()).stream()
.peek(x -> x.setUser(userData)).collect(Collectors.toList()));
userRivalDataRepository.saveAll(Optional.ofNullable(data.getUserRivalList()).orElse(Collections.emptyList()).stream()
.peek(x -> x.setUser(userData)).collect(Collectors.toList()));
return ResponseEntity.ok(new MessageResponse("Import successfully, aimeId: " + card.getExtId()));
}

View File

@ -0,0 +1,29 @@
package icu.samnyan.aqua.api.model;
import icu.samnyan.aqua.api.model.MessageResponse;
public class ObjectMessageResponse<T> extends MessageResponse {
private T data;
public ObjectMessageResponse(String message) {
super(message);
}
public ObjectMessageResponse(T data) {
super();
setData(data);
}
public ObjectMessageResponse(T data, String message) {
super(message);
setData(data);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* @author samnyan (privateamusement@protonmail.com)
@ -40,4 +41,5 @@ public class OngekiDataExport {
private List<UserScenario> userScenarioList;
private List<UserBoss> userBossList;
private List<UserTechCount> userTechCountList;
private List<UserRival> userRivalList;
}

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* @author samnyan (privateamusement@protonmail.com)
@ -40,4 +41,5 @@ public class OngekiDataImport {
private List<UserScenario> userScenarioList;
private List<UserBoss> userBossList;
private List<UserTechCount> userTechCountList;
private List<UserRival> userRivalList;
}

View File

@ -51,6 +51,7 @@ public class OngekiController {
private final GetUserRegionHandler getUserRegionHandler;
private final GetUserRivalHandler getUserRivalHandler;
private final GetUserRivalMusicHandler getUserRivalMusicHandler;
private final GetUserRivalDataHandler getUserRivalDataHandler;
private final GetUserScenarioHandler getUserScenarioHandler;
private final GetUserStoryHandler getUserStoryHandler;
private final GetUserTechCountHandler getUserTechCountHandler;
@ -65,7 +66,7 @@ public class OngekiController {
private final GetGameMusicReleaseStateHandler getGameMusicReleaseStateHandler;
@Autowired
public OngekiController(GetGameEventHandler getGameEventHandler, GetGameIdlistHandler getGameIdlistHandler, GetGameMessageHandler getGameMessageHandler, GetGamePointHandler getGamePointHandler, GetGamePresentHandler getGamePresentHandler, GetGameRankingHandler getGameRankingHandler, GetGameRewardHandler getGameRewardHandler, GetGameSettingHandler getGameSettingHandler, GetUserActivityHandler getUserActivityHandler, GetUserBossHandler getUserBossHandler, GetUserBpBaseHandler getUserBpBaseHandler, GetUserCardHandler getUserCardHandler, GetUserChapterHandler getUserChapterHandler, GetUserCharacterHandler getUserCharacterHandler, GetUserDataHandler getUserDataHandler, GetUserDeckByKeyHandler getUserDeckByKeyHandler, GetUserEventPointHandler getUserEventPointHandler, GetUserEventRankingHandler getUserEventRankingHandler, GetUserItemHandler getUserItemHandler, GetUserLoginBonusHandler getUserLoginBonusHandler, GetUserMissionPointHandler getUserMissionPointHandler, GetUserMusicHandler getUserMusicHandler, GetUserMusicItemHandler getUserMusicItemHandler, GetUserOptionHandler getUserOptionHandler, GetUserPreviewHandler getUserPreviewHandler, GetUserRatinglogListHandler getUserRatinglogListHandler, GetUserRecentRatingHandler getUserRecentRatingHandler, GetUserRegionHandler getUserRegionHandler, GetUserRivalHandler getUserRivalHandler, GetUserRivalMusicHandler getUserRivalMusicHandler, GetUserScenarioHandler getUserScenarioHandler, GetUserStoryHandler getUserStoryHandler, GetUserTechCountHandler getUserTechCountHandler, GetUserTrainingRoomByKeyHandler getUserTrainingRoomByKeyHandler, UpsertUserAllHandler upsertUserAllHandler, GetGameTechMusicHandler getGameTechMusicHandler, GetUserTechEventHandler getUserTechEventHandler, GetUserTechEventRankingHandler getUserTechEventRankingHandler, GetUserEventMusicHandler getUserEventMusicHandler, GetUserTradeItemHandler getUserTradeItemHandler, GetUserKopHandler getUserKopHandler, GetClientBookkeepingHandler getClientBookkeepingHandler, GetClientTestmodeHandler getClientTestmodeHandler, GetGameMusicReleaseStateHandler getGameMusicReleaseStateHandler, GetUserMemoryChapterHandler getUserMemoryChapterHandler) {
public OngekiController(GetGameEventHandler getGameEventHandler, GetGameIdlistHandler getGameIdlistHandler, GetGameMessageHandler getGameMessageHandler, GetGamePointHandler getGamePointHandler, GetGamePresentHandler getGamePresentHandler, GetGameRankingHandler getGameRankingHandler, GetGameRewardHandler getGameRewardHandler, GetGameSettingHandler getGameSettingHandler, GetUserActivityHandler getUserActivityHandler, GetUserBossHandler getUserBossHandler, GetUserBpBaseHandler getUserBpBaseHandler, GetUserCardHandler getUserCardHandler, GetUserChapterHandler getUserChapterHandler, GetUserCharacterHandler getUserCharacterHandler, GetUserDataHandler getUserDataHandler, GetUserDeckByKeyHandler getUserDeckByKeyHandler, GetUserEventPointHandler getUserEventPointHandler, GetUserEventRankingHandler getUserEventRankingHandler, GetUserItemHandler getUserItemHandler, GetUserLoginBonusHandler getUserLoginBonusHandler, GetUserMissionPointHandler getUserMissionPointHandler, GetUserMusicHandler getUserMusicHandler, GetUserMusicItemHandler getUserMusicItemHandler, GetUserOptionHandler getUserOptionHandler, GetUserPreviewHandler getUserPreviewHandler, GetUserRatinglogListHandler getUserRatinglogListHandler, GetUserRecentRatingHandler getUserRecentRatingHandler, GetUserRegionHandler getUserRegionHandler, GetUserRivalHandler getUserRivalHandler, GetUserRivalMusicHandler getUserRivalMusicHandler, GetUserScenarioHandler getUserScenarioHandler, GetUserStoryHandler getUserStoryHandler, GetUserTechCountHandler getUserTechCountHandler, GetUserTrainingRoomByKeyHandler getUserTrainingRoomByKeyHandler, UpsertUserAllHandler upsertUserAllHandler, GetGameTechMusicHandler getGameTechMusicHandler, GetUserTechEventHandler getUserTechEventHandler, GetUserTechEventRankingHandler getUserTechEventRankingHandler, GetUserEventMusicHandler getUserEventMusicHandler, GetUserTradeItemHandler getUserTradeItemHandler, GetUserKopHandler getUserKopHandler, GetClientBookkeepingHandler getClientBookkeepingHandler, GetClientTestmodeHandler getClientTestmodeHandler, GetGameMusicReleaseStateHandler getGameMusicReleaseStateHandler, GetUserMemoryChapterHandler getUserMemoryChapterHandler, GetUserRivalDataHandler getUserRivalDataHandler) {
this.getGameEventHandler = getGameEventHandler;
this.getGameIdlistHandler = getGameIdlistHandler;
this.getGameMessageHandler = getGameMessageHandler;
@ -97,6 +98,7 @@ public class OngekiController {
this.getUserRegionHandler = getUserRegionHandler;
this.getUserRivalHandler = getUserRivalHandler;
this.getUserRivalMusicHandler = getUserRivalMusicHandler;
this.getUserRivalDataHandler = getUserRivalDataHandler;
this.getUserScenarioHandler = getUserScenarioHandler;
this.getUserStoryHandler = getUserStoryHandler;
this.getUserTechCountHandler = getUserTechCountHandler;
@ -308,13 +310,11 @@ public class OngekiController {
return getUserRivalHandler.handle(request);
}
// seems same as GetUserRivalApi
@PostMapping("GetUserRivalDataApi")
public String getUserRivalData(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
return getUserRivalHandler.handle(request);
return getUserRivalDataHandler.handle(request);
}
// dummy for now
@PostMapping("GetUserRivalMusicApi")
public String getUserRivalMusic(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
return getUserRivalMusicHandler.handle(request);

View File

@ -6,6 +6,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
/**
@ -13,6 +15,7 @@ import java.util.Optional;
*/
@Repository("OngekiUserDataRepository")
public interface UserDataRepository extends JpaRepository<UserData, Long> {
List<UserData> findByCard_ExtIdIn(Collection<Long> userIds);
Optional<UserData> findByCard(Card card);

View File

@ -0,0 +1,24 @@
package icu.samnyan.aqua.sega.ongeki.dao.userdata;
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserData;
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserRival;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author dp (privateamusement@protonmail.com)
*/
@Repository("OngekiUserRivalDataRepository")
public interface UserRivalDataRepository extends JpaRepository<UserRival, Long> {
List<UserRival> findByUser_Card_ExtId(long userId);
@Transactional
void removeByUser_Card_ExtIdAndRivalUserId(long userId,long rivalUserId);
@Transactional
void deleteByUser(UserData user);
}

View File

@ -0,0 +1,63 @@
package icu.samnyan.aqua.sega.ongeki.handler.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserDataRepository;
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserRivalDataRepository;
import icu.samnyan.aqua.sega.ongeki.handler.BaseHandler;
import icu.samnyan.aqua.sega.ongeki.model.response.data.UserRivalData;
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author GEEKiDoS (geek_ds@foxmail.com)
*/
@Component("OngekiGetUserRivalDataHandler")
public class GetUserRivalDataHandler implements BaseHandler {
private static final Logger logger = LoggerFactory.getLogger(GetUserRivalDataHandler.class);
private final BasicMapper mapper;
private final UserRivalDataRepository userRivalDataRepository;
private final UserDataRepository userDataRepository;
@Autowired
public GetUserRivalDataHandler(BasicMapper mapper, UserRivalDataRepository userRivalDataRepository, UserDataRepository userDataRepository) {
this.mapper = mapper;
this.userRivalDataRepository = userRivalDataRepository;
this.userDataRepository = userDataRepository;
}
@Override
public String handle(Map<String, Object> request) throws JsonProcessingException {
var userRivalId = ((Number) request.get("userId")).longValue();
var userRivalList = ((Collection<HashMap<String,Object>>)request.get("userRivalList"))
.stream()
.map(x->((Number)x.get("rivalUserId")).longValue())
.collect(Collectors.toList());
Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("userId", userRivalId);
var userInfos = userDataRepository
.findByCard_ExtIdIn(userRivalList)
.stream()
.map(x -> new UserRivalData(x.getCard().getExtId().longValue(), x.getUserName()))
.toArray();
resultMap.put("length", userInfos.length);
resultMap.put("userRivalDataList", userInfos);
String json = mapper.write(resultMap);
logger.info("Response: " + json);
return json;
}
}

View File

@ -1,6 +1,7 @@
package icu.samnyan.aqua.sega.ongeki.handler.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserRivalDataRepository;
import icu.samnyan.aqua.sega.ongeki.handler.BaseHandler;
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
import org.slf4j.Logger;
@ -20,10 +21,12 @@ public class GetUserRivalHandler implements BaseHandler {
private static final Logger logger = LoggerFactory.getLogger(GetUserRivalHandler.class);
private final BasicMapper mapper;
private final UserRivalDataRepository userRivalDataRepository;
@Autowired
public GetUserRivalHandler(BasicMapper mapper) {
public GetUserRivalHandler(BasicMapper mapper, UserRivalDataRepository userRivalDataRepository) {
this.mapper = mapper;
this.userRivalDataRepository = userRivalDataRepository;
}
@Override
@ -32,8 +35,10 @@ public class GetUserRivalHandler implements BaseHandler {
Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("userId", userRivalId);
resultMap.put("length", 0);
resultMap.put("userRivalList", new List[]{});
var result = userRivalDataRepository.findByUser_Card_ExtId(userRivalId);//.stream().map(x->x.getUser().getCard().getExtId()).toArray();
resultMap.put("length", result.size());
resultMap.put("userRivalList", result);
String json = mapper.write(resultMap);

View File

@ -1,16 +1,19 @@
package icu.samnyan.aqua.sega.ongeki.handler.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserMusicDetailRepository;
import icu.samnyan.aqua.sega.ongeki.handler.BaseHandler;
import icu.samnyan.aqua.sega.ongeki.model.response.data.UserRivalMusic;
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
import icu.samnyan.aqua.spring.data.OffsetPageRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @author GEEKiDoS (geek_ds@foxmail.com)
@ -20,26 +23,57 @@ public class GetUserRivalMusicHandler implements BaseHandler {
private static final Logger logger = LoggerFactory.getLogger(GetUserRivalMusicHandler.class);
private final BasicMapper mapper;
private final UserMusicDetailRepository userMusicDetailRepository;
@Autowired
public GetUserRivalMusicHandler(BasicMapper mapper) {
public GetUserRivalMusicHandler(BasicMapper mapper, UserMusicDetailRepository userMusicDetailRepository) {
this.mapper = mapper;
this.userMusicDetailRepository = userMusicDetailRepository;
}
@Override
public String handle(Map<String, Object> request) throws JsonProcessingException {
var userId = (long)request.get("userId");
var rivalUserId = (int)request.get("rivalUserId");
/* var nextIndex = (int)request.get("nextIndex");
var maxCount = (int)request.get("maxCount"); */
var userId = ((Number) request.get("userId")).longValue();
var rivalUserId = ((Number) request.get("rivalUserId")).longValue();
var nextIndex = ((Number) request.get("nextIndex")).intValue();
var maxCount = ((Number) request.get("maxCount")).intValue();
//fix maxCount and sort by musicId so that we could fetch entity music with full fumen diffs.
var fixedMaxCount = maxCount + (maxCount % 5 == 0 ? 0 : 5);
var sorter = Sort.by(Sort.Direction.ASC, "musicId");
var groupedMusicDetailsItor = userMusicDetailRepository
.findByUser_Card_ExtId(rivalUserId, OffsetPageRequest.of(nextIndex, fixedMaxCount, sorter))
.stream()
.collect(Collectors.groupingBy(x -> x.getMusicId()))
.values()
.stream()
.map(x -> new UserRivalMusic(x,x.size()))
.iterator();
var filterMusicDetails = new ArrayList<UserRivalMusic>();
var actualReadCount = 0;
while(groupedMusicDetailsItor.hasNext()){
var musicDetail = groupedMusicDetailsItor.next();
if (musicDetail.getLength() + actualReadCount > maxCount)
break;
filterMusicDetails.add(musicDetail);
actualReadCount += musicDetail.getLength();
}
var respNextIndex = nextIndex + actualReadCount;
if (filterMusicDetails.size() <= 0)
respNextIndex = 0; //nofity client that All music details had been sent (for this rival).
else
filterMusicDetails.sort(Comparator.comparingInt(a -> a.getUserRivalMusicDetailList().get(0).getMusicId()));
Map<String, Object> resultMap = new LinkedHashMap<>();
resultMap.put("userId", userId);
resultMap.put("rivalUserId", rivalUserId);
resultMap.put("length", 0);
resultMap.put("nextIndex", 0);
resultMap.put("userRivalMusicList", new List[]{});
resultMap.put("length", filterMusicDetails.size());
resultMap.put("nextIndex", respNextIndex);
resultMap.put("userRivalMusicList", filterMusicDetails);
String json = mapper.write(resultMap);

View File

@ -27,5 +27,5 @@ public class GameSetting {
private int maxCountItem;
private int maxCountMusic;
private int maxCountMusicItem;
private int macCountRivalMusic;
private int maxCountRivalMusic;
}

View File

@ -0,0 +1,16 @@
package icu.samnyan.aqua.sega.ongeki.model.response.data;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRivalData {
private long rivalUserId;
private String rivalUserName;
}

View File

@ -0,0 +1,19 @@
package icu.samnyan.aqua.sega.ongeki.model.response.data;
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserMusicDetail;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRivalMusic {
private List<UserMusicDetail> userRivalMusicDetailList;
private int length;
}

View File

@ -0,0 +1,38 @@
package icu.samnyan.aqua.sega.ongeki.model.userdata;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import icu.samnyan.aqua.sega.util.jackson.UserIdSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Entity(name = "OngekiUserRival")
@Table(name = "ongeki_user_rival")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserRival implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
private long id;
@ManyToOne
@JsonIgnore
@JoinColumn(name = "user_id")
private UserData user;
@JoinColumn(name = "rival_user_id")
@JsonProperty("rivalUserId")
private long rivalUserId;
}

View File

@ -0,0 +1,27 @@
package icu.samnyan.aqua.sega.util.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserData;
import java.io.IOException;
/**
* @author samnyan (privateamusement@protonmail.com)
*/
public class UserIdSerializer extends StdSerializer<UserData> {
public UserIdSerializer() {
this(null);
}
public UserIdSerializer(Class<UserData> t) {
super(t);
}
@Override
public void serialize(UserData value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeNumber(value.getCard().getExtId());
}
}

View File

@ -0,0 +1,32 @@
-- --------------------------------------------------------
-- 主机: 127.0.0.1
-- 服务器版本: 10.10.2-MariaDB - mariadb.org binary distribution
-- 服务器操作系统: Win64
-- HeidiSQL 版本: 11.3.0.6295
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-- 导出 表 aqua.ongeki_user_rival 结构
CREATE TABLE IF NOT EXISTS `ongeki_user_rival` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`rival_user_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ongeki_user_rival_uq` (`user_id`,`rival_user_id`),
KEY `FK__ongeki_user_data_2` (`rival_user_id`),
CONSTRAINT `FK__ongeki_user_data` FOREIGN KEY (`user_id`) REFERENCES `ongeki_user_data` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `FK__ongeki_user_data_2` FOREIGN KEY (`rival_user_id`) REFERENCES `ongeki_user_data` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 数据导出被取消选择。
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;

View File

@ -0,0 +1,32 @@
-- --------------------------------------------------------
-- 主机: 127.0.0.1
-- 服务器版本: 10.10.2-MariaDB - mariadb.org binary distribution
-- 服务器操作系统: Win64
-- HeidiSQL 版本: 11.3.0.6295
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-- 导出 表 aqua.ongeki_user_rival 结构
CREATE TABLE IF NOT EXISTS `ongeki_user_rival` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`rival_user_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ongeki_user_rival_uq` (`user_id`,`rival_user_id`),
KEY `FK__ongeki_user_data_2` (`rival_user_id`),
CONSTRAINT `FK__ongeki_user_data` FOREIGN KEY (`user_id`) REFERENCES `ongeki_user_data` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `FK__ongeki_user_data_2` FOREIGN KEY (`rival_user_id`) REFERENCES `ongeki_user_data` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- 数据导出被取消选择。
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;

View File

@ -0,0 +1,9 @@
CREATE TABLE "ongeki_user_rival" (
"id" INTEGER NOT NULL,
"rival_user_id" BIGINT,
"user_id" BIGINT,
FOREIGN KEY("user_id") REFERENCES "ongeki_user_data"("id") ON DELETE CASCADE,
FOREIGN KEY("rival_user_id") REFERENCES "ongeki_user_data"("id") ON DELETE CASCADE,
PRIMARY KEY("id" AUTOINCREMENT),
CONSTRAINT "ongeki_user_rival_uq" UNIQUE("user_id","rival_user_id") ON CONFLICT REPLACE
);

View File

@ -3,6 +3,7 @@ package icu.samnyan.aqua.sega.ongeki.dao.userdata;
import icu.samnyan.aqua.sega.general.dao.CardRepository;
import icu.samnyan.aqua.sega.general.model.Card;
import icu.samnyan.aqua.sega.ongeki.model.userdata.*;
import icu.samnyan.aqua.util.CardHelper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
@ -63,6 +64,8 @@ class OngekiRepositoryTest {
private UserTechCountRepository userTechCountRepository;
@Autowired
private UserTrainingRoomRepository userTrainingRoomRepository;
@Autowired
private UserRivalDataRepository userRivalDataRepository;
@Test
void userData_SaveLoad() {
@ -337,10 +340,35 @@ class OngekiRepositoryTest {
assertThat(aL).hasSize(2);
}
@Test
void userRivalData_SaveLoad() {
var u = getNewRandomValidUser();
var r1 = getNewRandomValidUser();
var r2 = getNewRandomValidUser();
var r3 = getNewRandomValidUser();
userRivalDataRepository.saveAll(List.of(
getUserRival(u, r1),
getUserRival(u, r2),
getUserRival(r1, r2),
getUserRival(r2, u)
));
var all = userRivalDataRepository.findAll();
assertThat(all).hasSize(4);
var find = userRivalDataRepository.findByUser_Card_ExtId(u.getCard().getExtId());
assertThat(find).hasSize(2);
}
private UserData getUser(Card c) {
return new UserData(-1, c, "Hello", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "2020", "2020", "SDDT", "1.00.00", "1.00.00", "2020", "SDDT", "1.00.00", "1.00.00", "", "2020", 0, "0", 0, "123", 0, "A000000", 0, 0, 0);
}
private UserData getNewRandomValidUser() {
return userDataRepository.save(getUser(cardRepository.save(CardHelper.getRandomCard())));
}
private UserActivity getActivity(UserData u, Integer activityId) {
return new UserActivity(-1, u, 1, activityId, 0, 0, 0, 0, 0);
}
@ -416,4 +444,8 @@ class OngekiRepositoryTest {
private UserTrainingRoom getTrainingRoom(UserData u, Integer roomId) {
return new UserTrainingRoom(-1, u, "", roomId, 1, "");
}
private UserRival getUserRival(UserData user, UserData rival) {
return new UserRival(0, user, rival.getCard().getExtId());
}
}

View File

@ -3,15 +3,30 @@ package icu.samnyan.aqua.util;
import icu.samnyan.aqua.sega.general.model.Card;
import java.time.LocalDateTime;
import java.util.Random;
/**
* @author sam_nya (privateamusement@protonmail.com)
*/
public class CardHelper {
private static Random rand = new Random();
public static Card getCard() {
var now = LocalDateTime.now();
return new Card(1L, 114514L, "01145141919810000000", now, now);
}
public static Card getRandomCard() {
var now = LocalDateTime.now();
var luid = "";
for (int i = 0; i < "01145141919810028570".length(); i++)
luid += rand.nextInt(10);
var extId = 0L;
for (int i = 0; i < "114514".length(); i++)
extId = extId * 10 + rand.nextInt(10);
return new Card(0, extId, luid, now, now);
}
}