mirror of https://github.com/hykilpikonna/AquaDX
[chuni] Fix music score missing again
[ongeki] Fix music score missing againpull/1/head
parent
0c8f19d370
commit
14dec1e3e3
|
@ -0,0 +1,85 @@
|
||||||
|
package icu.samnyan.aqua.api.controller.sega.manage;
|
||||||
|
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.model.gamedata.Level;
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.model.gamedata.Music;
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserMusicDetail;
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.service.GameMusicService;
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.service.UserDataService;
|
||||||
|
import icu.samnyan.aqua.sega.chunithm.service.UserMusicDetailService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author samnyan (privateamusement@protonmail.com)
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("api/manage/chuni/amazon")
|
||||||
|
public class ApiAmazonManageController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ApiAmazonManageController.class);
|
||||||
|
|
||||||
|
private final UserDataService userDataService;
|
||||||
|
|
||||||
|
private final UserMusicDetailService userMusicDetailService;
|
||||||
|
|
||||||
|
private final GameMusicService gameMusicService;
|
||||||
|
|
||||||
|
public ApiAmazonManageController(UserDataService userDataService, UserMusicDetailService userMusicDetailService, GameMusicService gameMusicService) {
|
||||||
|
this.userDataService = userDataService;
|
||||||
|
this.userMusicDetailService = userMusicDetailService;
|
||||||
|
this.gameMusicService = gameMusicService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A request to fill fake score to all chart. only use for testing
|
||||||
|
* @param aimeId The internal id of a card
|
||||||
|
* @return Run result status
|
||||||
|
*/
|
||||||
|
// @PostMapping("fill")
|
||||||
|
public ResponseEntity<Object> fillMockData(@RequestParam String aimeId) {
|
||||||
|
UserData profile = userDataService.getUserByExtId(aimeId).orElseThrow();
|
||||||
|
List<Music> musicList = gameMusicService.getAll();
|
||||||
|
List<UserMusicDetail> detailList = new ArrayList<>();
|
||||||
|
musicList.forEach(x -> {
|
||||||
|
Collection<Level> levels = x.getLevels().values();
|
||||||
|
levels.forEach(l -> {
|
||||||
|
Optional<UserMusicDetail> userMusicDetailOptional = userMusicDetailService.getByUserAndMusicIdAndLevel(profile, x.getMusicId(), l.getDiff());
|
||||||
|
if (userMusicDetailOptional.isEmpty()) {
|
||||||
|
UserMusicDetail temp = new UserMusicDetail(
|
||||||
|
x.getMusicId(),
|
||||||
|
l.getDiff(),
|
||||||
|
1,
|
||||||
|
980000,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
5,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
8,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
temp.setUser(profile);
|
||||||
|
detailList.add(temp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
userMusicDetailService.saveAll(detailList);
|
||||||
|
return ResponseEntity.ok("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -91,6 +91,6 @@ public class AimeDbRequestHandler extends ChannelInboundHandlerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
super.channelInactive(ctx);
|
super.channelInactive(ctx);
|
||||||
logger.info("Connection closed");
|
logger.debug("Connection closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,12 @@ import icu.samnyan.aqua.sega.chunithm.model.userdata.UserMusicDetail;
|
||||||
import icu.samnyan.aqua.sega.chunithm.service.GameMusicService;
|
import icu.samnyan.aqua.sega.chunithm.service.GameMusicService;
|
||||||
import icu.samnyan.aqua.sega.chunithm.service.UserMusicDetailService;
|
import icu.samnyan.aqua.sega.chunithm.service.UserMusicDetailService;
|
||||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||||
|
import icu.samnyan.aqua.spring.data.OffsetPageRequest;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -41,11 +43,14 @@ public class GetUserMusicHandler implements BaseHandler {
|
||||||
@Override
|
@Override
|
||||||
public String handle(Map<String, Object> request) throws JsonProcessingException {
|
public String handle(Map<String, Object> request) throws JsonProcessingException {
|
||||||
String userId = (String) request.get("userId");
|
String userId = (String) request.get("userId");
|
||||||
int nextIndex = Integer.parseInt((String) request.get("nextIndex"));
|
int currentIndex = Integer.parseInt((String) request.get("nextIndex"));
|
||||||
int maxCount = Integer.parseInt((String) request.get("maxCount"));
|
int maxCount = Integer.parseInt((String) request.get("maxCount"));
|
||||||
int pageNum = nextIndex / maxCount;
|
if(currentIndex < 0) {
|
||||||
|
currentIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Page<UserMusicDetail> dbPage = userMusicDetailService.getByUser(userId,pageNum,maxCount);
|
Page<UserMusicDetail> dbPage = userMusicDetailService
|
||||||
|
.getByUser(userId, OffsetPageRequest.of(currentIndex, maxCount, Sort.by("musicId")));
|
||||||
|
|
||||||
|
|
||||||
// Convert to result format
|
// Convert to result format
|
||||||
|
@ -64,13 +69,25 @@ public class GetUserMusicHandler implements BaseHandler {
|
||||||
list.setLength(list.getUserMusicDetailList().size());
|
list.setLength(list.getUserMusicDetailList().size());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Remove the last music id if the result length is the same as maxCount,
|
||||||
|
// to prevent a music id split across multiple page, which will cause some
|
||||||
|
// problem with the game.
|
||||||
|
int lastListSize = 0;
|
||||||
|
if(dbPage.getNumberOfElements() >= maxCount) {
|
||||||
|
// Get last key
|
||||||
|
int lastMusicId = userMusicMap.keySet().stream().reduce((a, b) -> b).orElseThrow();
|
||||||
|
List<UserMusicDetail> lastList = userMusicMap.get(lastMusicId).getUserMusicDetailList();
|
||||||
|
lastListSize = lastList.size();
|
||||||
|
// Remove last one from map
|
||||||
|
userMusicMap.remove(lastMusicId);
|
||||||
|
}
|
||||||
|
|
||||||
long currentIndex = maxCount * pageNum + dbPage.getNumberOfElements();
|
long nextIndex = currentIndex + dbPage.getNumberOfElements() - lastListSize;
|
||||||
|
|
||||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||||
resultMap.put("userId", userId);
|
resultMap.put("userId", userId);
|
||||||
resultMap.put("length", userMusicMap.size());
|
resultMap.put("length", userMusicMap.size());
|
||||||
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : currentIndex);
|
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : nextIndex);
|
||||||
resultMap.put("userMusicList", userMusicMap.values());
|
resultMap.put("userMusicList", userMusicMap.values());
|
||||||
|
|
||||||
String json = mapper.write(resultMap);
|
String json = mapper.write(resultMap);
|
||||||
|
|
|
@ -37,8 +37,7 @@ public class UserMusicDetailService {
|
||||||
return userMusicDetailRepository.findByUser_Card_ExtId(Integer.parseInt(userId));
|
return userMusicDetailRepository.findByUser_Card_ExtId(Integer.parseInt(userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<UserMusicDetail> getByUser(String userId, int pageNum, int maxCount) {
|
public Page<UserMusicDetail> getByUser(String userId, Pageable page) {
|
||||||
Pageable page = PageRequest.of(pageNum, maxCount);
|
|
||||||
return userMusicDetailRepository.findByUser_Card_ExtId(Integer.parseInt(userId), page);
|
return userMusicDetailRepository.findByUser_Card_ExtId(Integer.parseInt(userId), page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,17 @@ import icu.samnyan.aqua.sega.ongeki.handler.BaseHandler;
|
||||||
import icu.samnyan.aqua.sega.ongeki.model.response.data.UserMusicListItem;
|
import icu.samnyan.aqua.sega.ongeki.model.response.data.UserMusicListItem;
|
||||||
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserMusicDetail;
|
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserMusicDetail;
|
||||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||||
|
import icu.samnyan.aqua.spring.data.OffsetPageRequest;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,10 +42,13 @@ public class GetUserMusicHandler implements BaseHandler {
|
||||||
public String handle(Map<String, Object> request) throws JsonProcessingException {
|
public String handle(Map<String, Object> request) throws JsonProcessingException {
|
||||||
Integer userId = (Integer) request.get("userId");
|
Integer userId = (Integer) request.get("userId");
|
||||||
Integer maxCount = (Integer) request.get("maxCount");
|
Integer maxCount = (Integer) request.get("maxCount");
|
||||||
Integer nextIndex = (Integer) request.get("nextIndex");
|
Integer currentIndex = (Integer) request.get("nextIndex");
|
||||||
int pageNum = nextIndex / maxCount;
|
if(currentIndex < 0) {
|
||||||
|
currentIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Page<UserMusicDetail> dbPage = userMusicDetailRepository.findByUser_Card_ExtId(userId, PageRequest.of(pageNum, maxCount));
|
Page<UserMusicDetail> dbPage = userMusicDetailRepository
|
||||||
|
.findByUser_Card_ExtId(userId, OffsetPageRequest.of(currentIndex, maxCount, Sort.by("musicId")));
|
||||||
|
|
||||||
Map<Integer, UserMusicListItem> userMusicMap = new LinkedHashMap<>();
|
Map<Integer, UserMusicListItem> userMusicMap = new LinkedHashMap<>();
|
||||||
dbPage.getContent().forEach(userMusicDetail -> {
|
dbPage.getContent().forEach(userMusicDetail -> {
|
||||||
|
@ -58,12 +63,23 @@ public class GetUserMusicHandler implements BaseHandler {
|
||||||
list.setLength(list.getUserMusicDetailList().size());
|
list.setLength(list.getUserMusicDetailList().size());
|
||||||
});
|
});
|
||||||
|
|
||||||
long currentIndex = maxCount * pageNum + dbPage.getNumberOfElements();
|
// Someone report that ongeki also has the score missing problem
|
||||||
|
int lastListSize = 0;
|
||||||
|
if(dbPage.getNumberOfElements() >= maxCount) {
|
||||||
|
// Get last key
|
||||||
|
int lastMusicId = userMusicMap.keySet().stream().reduce((a, b) -> b).orElseThrow();
|
||||||
|
List<UserMusicDetail> lastList = userMusicMap.get(lastMusicId).getUserMusicDetailList();
|
||||||
|
lastListSize = lastList.size();
|
||||||
|
// Remove last one from map
|
||||||
|
userMusicMap.remove(lastMusicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
long nextIndex = currentIndex + dbPage.getNumberOfElements() - lastListSize;
|
||||||
|
|
||||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||||
resultMap.put("userId", userId);
|
resultMap.put("userId", userId);
|
||||||
resultMap.put("length", userMusicMap.size());
|
resultMap.put("length", userMusicMap.size());
|
||||||
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : currentIndex);
|
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : nextIndex);
|
||||||
resultMap.put("userMusicList", userMusicMap.values());
|
resultMap.put("userMusicList", userMusicMap.values());
|
||||||
|
|
||||||
String json = mapper.write(resultMap);
|
String json = mapper.write(resultMap);
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package icu.samnyan.aqua.spring.data;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Somehow spring boot jpa doesn't provide a class to use offset to to the pagination
|
||||||
|
* @author samnyan (privateamusement@protonmail.com)
|
||||||
|
*/
|
||||||
|
public class OffsetPageRequest implements Pageable, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final int offset;
|
||||||
|
private final int limit;
|
||||||
|
private final Sort sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link OffsetPageRequest} with sort parameters applied.
|
||||||
|
*
|
||||||
|
* @param offset offset of the request index, must not be negative.
|
||||||
|
* @param limit the size of the page to be returned, must be greater than 0.
|
||||||
|
* @param sort must not be {@literal null}, use {@link Sort#unsorted()} instead.
|
||||||
|
*/
|
||||||
|
public OffsetPageRequest(int offset, int limit, Sort sort) {
|
||||||
|
|
||||||
|
if (offset < 0) {
|
||||||
|
throw new IllegalArgumentException("Offset must not be less than zero!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit < 1) {
|
||||||
|
throw new IllegalArgumentException("Limit must not be less than one!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.notNull(sort, "Sort must not be null!");
|
||||||
|
|
||||||
|
this.offset = offset;
|
||||||
|
this.limit = limit;
|
||||||
|
this.sort = sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OffsetPageRequest of(int page, int size) {
|
||||||
|
return of(page, size, Sort.unsorted());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OffsetPageRequest of(int page, int size, Sort sort) {
|
||||||
|
return new OffsetPageRequest(page, size, sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#getPageNumber()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getPageNumber() {
|
||||||
|
return offset / limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#getPageSize()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getPageSize() {
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#getOffset()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#getSort()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Sort getSort() {
|
||||||
|
return sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#next()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Pageable next() {
|
||||||
|
return new OffsetPageRequest(Math.toIntExact(getOffset() + getPageSize()), getPageSize(), getSort());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#previousOrFirst()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Pageable previousOrFirst() {
|
||||||
|
return hasPrevious() ? new OffsetPageRequest(Math.toIntExact(getOffset() - getPageSize()), getPageSize(), getSort()) : this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.domain.Pageable#first()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Pageable first() {
|
||||||
|
return new OffsetPageRequest(0, getPageSize(), getSort());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPrevious() {
|
||||||
|
return offset > limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#hashCode()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
|
||||||
|
result = prime * result + offset;
|
||||||
|
result = prime * result + limit;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#equals(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object obj) {
|
||||||
|
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OffsetPageRequest other = (OffsetPageRequest) obj;
|
||||||
|
return this.offset == other.offset && this.limit == other.limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue