[api] Add chunithm profile export and import

[general] Rename some method name and add more docs
This commit is contained in:
samnyan
2020-03-28 17:38:23 +09:00
parent 067c806674
commit 9a4ca3a612
32 changed files with 484 additions and 119 deletions

View File

@@ -1,7 +1,7 @@
package icu.samnyan.aqua.api.controller.sega;
import icu.samnyan.aqua.sega.general.dao.CardRepository;
import icu.samnyan.aqua.sega.general.model.Card;
import icu.samnyan.aqua.sega.general.service.CardService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -11,20 +11,21 @@ import java.util.Map;
import java.util.Optional;
/**
* General Aime actions endpoint
* @author samnyan (privateamusement@protonmail.com)
*/
@RestController
@RequestMapping("api/sega/aime")
public class ApiAimeController {
private final CardRepository cardRepository;
private final CardService cardService;
public ApiAimeController(CardRepository cardRepository) {
this.cardRepository = cardRepository;
public ApiAimeController(CardService cardService) {
this.cardService = cardService;
}
@PostMapping("getByAccessCode")
public Optional<Card> getByAccessCode(@RequestBody Map<String, String> request) {
return cardRepository.findByLuid(request.get("accessCode").replaceAll("-","").replaceAll(" ",""));
return cardService.getCardByAccessCode(request.get("accessCode").replaceAll("-", "").replaceAll(" ", ""));
}
}

View File

@@ -6,22 +6,28 @@ import icu.samnyan.aqua.api.model.ReducedPageResponse;
import icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.ProfileResp;
import icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.RatingItem;
import icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.RecentResp;
import icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.external.ChuniDataExport;
import icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.external.ChuniDataImport;
import icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.external.ExternalUserData;
import icu.samnyan.aqua.api.util.ApiMapper;
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.*;
import icu.samnyan.aqua.sega.chunithm.service.*;
import icu.samnyan.aqua.sega.general.model.Card;
import icu.samnyan.aqua.sega.general.service.CardService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -31,24 +37,45 @@ import java.util.stream.Collectors;
@RequestMapping("api/game/chuni/amazon")
public class ApiAmazonController {
private static final Logger logger = LoggerFactory.getLogger(ApiAmazonController.class);
private final ApiMapper mapper;
private final UserDataService userDataService;
private final UserPlaylogService userPlaylogService;
private final UserMusicDetailService userMusicDetailService;
private final CardService cardService;
private final UserActivityService userActivityService;
private final UserCharacterService userCharacterService;
private final UserChargeService userChargeService;
private final UserCourseService userCourseService;
private final UserDataService userDataService;
private final UserDataExService userDataExService;
private final UserDuelService userDuelService;
private final UserGameOptionService userGameOptionService;
private final UserGameOptionExService userGameOptionExService;
private final UserItemService userItemService;
private final UserMapService userMapService;
private final UserMusicDetailService userMusicDetailService;
private final UserPlaylogService userPlaylogService;
private final GameMusicService gameMusicService;
@Autowired
public ApiAmazonController(ApiMapper mapper, UserDataService userDataService, UserPlaylogService userPlaylogService, UserMusicDetailService userMusicDetailService, UserCourseService userCourseService, UserGameOptionService userGameOptionService, 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, GameMusicService gameMusicService) {
this.mapper = mapper;
this.cardService = cardService;
this.userActivityService = userActivityService;
this.userCharacterService = userCharacterService;
this.userChargeService = userChargeService;
this.userDataService = userDataService;
this.userDataExService = userDataExService;
this.userGameOptionExService = userGameOptionExService;
this.userMapService = userMapService;
this.userPlaylogService = userPlaylogService;
this.userMusicDetailService = userMusicDetailService;
this.userCourseService = userCourseService;
this.userDuelService = userDuelService;
this.userGameOptionService = userGameOptionService;
this.userItemService = userItemService;
this.gameMusicService = gameMusicService;
}
@@ -67,7 +94,7 @@ public class ApiAmazonController {
public ProfileResp getProfile(@RequestParam String aimeId) {
ProfileResp resp = mapper.convert(userDataService.getUserByExtId(aimeId).orElseThrow(), new TypeReference<>() {
});
UserCourse course = userCourseService.getByUser(aimeId)
UserCourse course = userCourseService.getByUserId(aimeId)
.stream()
.filter(UserCourse::isClear)
.max(Comparator.comparingInt(UserCourse::getClassId))
@@ -168,12 +195,115 @@ public class ApiAmazonController {
@GetMapping("song/{id}")
public List<UserMusicDetail> getSongDetail(@RequestParam String aimeId, @PathVariable int id) {
return userMusicDetailService.getByUserAndMusicId(aimeId, id);
return userMusicDetailService.getByUserIdAndMusicId(aimeId, id);
}
@GetMapping("song/{id}/{level}")
public List<UserPlaylog> getLevelPlaylog(@RequestParam String aimeId, @PathVariable int id, @PathVariable int level) {
return userPlaylogService.getByUserAndMusicIdAndLevel(aimeId, id, level);
return userPlaylogService.getByUserIdAndMusicIdAndLevel(aimeId, id, level);
}
@GetMapping("export")
public ResponseEntity<Object> exportAllUserData(@RequestParam String aimeId) {
ChuniDataExport data = new ChuniDataExport();
try {
data.setUserData(userDataService.getUserByExtId(aimeId).orElseThrow());
data.setUserActivityList(userActivityService.getByUserId(aimeId));
data.setUserCharacterList(userCharacterService.getByUserId(aimeId));
data.setUserChargeList(userChargeService.getByUserId(aimeId));
data.setUserCourseList(userCourseService.getByUserId(aimeId));
data.setUserDataEx(userDataExService.getByExtId(aimeId).orElseThrow());
data.setUserDuelList(userDuelService.getByUserId(aimeId));
data.setUserGameOption(userGameOptionService.getByUserId(aimeId).orElseThrow());
data.setUserGameOptionEx(userGameOptionExService.getByUserId(aimeId).orElseThrow());
data.setUserItemList(userItemService.getByUserId(aimeId));
data.setUserMapList(userMapService.getByUserId(aimeId));
data.setUserMusicDetailList(userMusicDetailService.getByUserId(aimeId));
data.setUserPlaylogList(userPlaylogService.getByUserId(aimeId));
} catch (NoSuchElementException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new MessageResponse("User not found"));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new MessageResponse("Error during data export. Reason: " + e.getMessage()));
}
// Set filename
HttpHeaders headers = new HttpHeaders();
headers.set("content-disposition", "attachment; filename=" + aimeId + "_exported.json");
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
@PostMapping("import")
public ResponseEntity<Object> importAllUserData(@RequestBody ChuniDataImport data) {
ExternalUserData exUser = data.getUserData();
Optional<Card> cardOptional = cardService.getCardByAccessCode(exUser.getAccessCode());
Card card;
if (cardOptional.isPresent()) {
if (userDataService.getUserByCard(cardOptional.get()).isPresent()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new MessageResponse("This card already has a chunithm profile."));
} else {
card = cardOptional.get();
}
} else {
card = cardService.registerByAccessCode(exUser.getAccessCode());
}
UserData userData = mapper.convert(exUser, new TypeReference<>() {
});
userData.setCard(card);
userDataService.saveAndFlushUserData(userData);
List<UserActivity> userActivityList = data.getUserActivityList();
userActivityList.forEach(x -> x.setUser(userData));
userActivityService.saveAll(userActivityList);
List<UserCharacter> userCharacterList = data.getUserCharacterList();
userCharacterList.forEach(x -> x.setUser(userData));
userCharacterService.saveAll(userCharacterList);
List<UserCharge> userChargeList = data.getUserChargeList();
userCharacterList.forEach(x -> x.setUser(userData));
userChargeService.saveAll(userChargeList);
List<UserCourse> userCourseList = data.getUserCourseList();
userCourseList.forEach(x -> x.setUser(userData));
userCourseService.saveAll(userCourseList);
UserDataEx userDataEx = data.getUserDataEx();
userDataEx.setUser(userData);
userDataExService.save(userDataEx);
List<UserDuel> userDuelList = data.getUserDuelList();
userDuelList.forEach(x -> x.setUser(userData));
userDuelService.saveAll(userDuelList);
UserGameOption userGameOption = data.getUserGameOption();
userGameOption.setUser(userData);
userGameOptionService.save(userGameOption);
UserGameOptionEx userGameOptionEx = data.getUserGameOptionEx();
userGameOptionEx.setUser(userData);
userGameOptionExService.save(userGameOptionEx);
List<UserItem> userItemList = data.getUserItemList();
userItemList.forEach(x -> x.setUser(userData));
userItemService.saveAll(userItemList);
List<UserMap> userMapList = data.getUserMapList();
userMapList.forEach(x -> x.setUser(userData));
userMapService.saveAll(userMapList);
List<UserMusicDetail> userMusicDetailList = data.getUserMusicDetailList();
userMusicDetailList.forEach(x -> x.setUser(userData));
userMusicDetailService.saveAll(userMusicDetailList);
List<UserPlaylog> userPlaylogList = data.getUserPlaylogList();
userPlaylogList.forEach(x -> x.setUser(userData));
userPlaylogService.saveAll(userPlaylogList);
return ResponseEntity.ok(new MessageResponse("Import successfully, aimeId: " + card.getExtId()));
}
private int calculateRating(int levelBase, int score) {

View File

@@ -0,0 +1,31 @@
package icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.external;
import icu.samnyan.aqua.sega.chunithm.model.userdata.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* This class is use for exporting CHUNITHM profile
* @author samnyan (privateamusement@protonmail.com)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChuniDataExport {
private UserData userData;
private List<UserActivity> userActivityList;
private List<UserCharacter> userCharacterList;
private List<UserCharge> userChargeList;
private List<UserCourse> userCourseList;
private UserDataEx userDataEx;
private List<UserDuel> userDuelList;
private UserGameOption userGameOption;
private UserGameOptionEx userGameOptionEx;
private List<UserItem> userItemList;
private List<UserMap> userMapList;
private List<UserMusicDetail> userMusicDetailList;
private List<UserPlaylog> userPlaylogList;
}

View File

@@ -0,0 +1,31 @@
package icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.external;
import icu.samnyan.aqua.sega.chunithm.model.userdata.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* This class is use for importing CHUNITHM profile
* @author samnyan (privateamusement@protonmail.com)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChuniDataImport {
private ExternalUserData userData;
private List<UserActivity> userActivityList;
private List<UserCharacter> userCharacterList;
private List<UserCharge> userChargeList;
private List<UserCourse> userCourseList;
private UserDataEx userDataEx;
private List<UserDuel> userDuelList;
private UserGameOption userGameOption;
private UserGameOptionEx userGameOptionEx;
private List<UserItem> userItemList;
private List<UserMap> userMapList;
private List<UserMusicDetail> userMusicDetailList;
private List<UserPlaylog> userPlaylogList;
}

View File

@@ -0,0 +1,118 @@
package icu.samnyan.aqua.api.model.resp.sega.chuni.amazon.external;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* This class is use for exported UserData class. Using access code as identifier
* @author samnyan (privateamusement@protonmail.com)
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExternalUserData {
// Access Code of the card
private String accessCode;
private String userName;
private LocalDateTime lastLoginDate;
private boolean isWebJoin;
private String webLimitDate;
private int level;
private int reincarnationNum;
private String exp;
private long point;
private long totalPoint;
private int playCount;
private int multiPlayCount;
private int multiWinCount;
private int requestResCount;
private int acceptResCount;
private int successResCount;
private int playerRating;
private int highestRating;
private int nameplateId;
private int frameId;
private int characterId;
private int trophyId;
private int playedTutorialBit;
private int firstTutorialCancelNum;
private int masterTutorialCancelNum;
private int totalRepertoireCount;
private int totalMapNum;
private long totalHiScore;
private long totalBasicHighScore;
private long totalAdvancedHighScore;
private long totalExpertHighScore;
private long totalMasterHighScore;
private LocalDateTime eventWatchedDate;
private int friendCount;
@JsonProperty("isMaimai")
private boolean isMaimai;
private String firstGameId;
private String firstRomVersion;
private String firstDataVersion;
private LocalDateTime firstPlayDate;
private String lastGameId;
private String lastRomVersion;
private String lastDataVersion;
private LocalDateTime lastPlayDate;
private int lastPlaceId;
private String lastPlaceName;
private String lastRegionId;
private String lastRegionName;
private String lastAllNetId;
private String lastClientId;
}