From 0b29ac00a781a97b2968151947450a229e90f556 Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:54:31 -0500 Subject: [PATCH] [+] Generalize game trend & summary apis --- .../icu/samnyan/aqua/net/games/Maimai2.kt | 72 ++------ .../java/icu/samnyan/aqua/net/games/Models.kt | 3 +- .../icu/samnyan/aqua/net/utils/GameHelper.kt | 105 ++++++++++++ .../icu/samnyan/aqua/net/utils/GameScoring.kt | 33 ++++ .../dao/userdata/UserDataRepository.kt | 7 +- .../dao/userdata/UserPlaylogRepository.java | 3 +- .../handler/impl/GetUserPreviewHandler.java | 2 +- .../handler/impl/UpsertUserAllHandler.java | 2 +- .../maimai2/model/userdata/UserDetail.java | 156 ----------------- .../sega/maimai2/model/userdata/UserDetail.kt | 160 ++++++++++++++++++ .../maimai2/model/userdata/UserPlaylog.java | 10 +- 11 files changed, 331 insertions(+), 222 deletions(-) create mode 100644 src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt create mode 100644 src/main/java/icu/samnyan/aqua/net/utils/GameScoring.kt delete mode 100644 src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.java create mode 100644 src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.kt diff --git a/src/main/java/icu/samnyan/aqua/net/games/Maimai2.kt b/src/main/java/icu/samnyan/aqua/net/games/Maimai2.kt index bb322fb6..9437981f 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Maimai2.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Maimai2.kt @@ -3,15 +3,18 @@ package icu.samnyan.aqua.net.games import ext.API import ext.RP import ext.Str -import ext.minus import icu.samnyan.aqua.net.db.AquaUserServices +import icu.samnyan.aqua.net.utils.TrendLog +import icu.samnyan.aqua.net.utils.findTrend +import icu.samnyan.aqua.net.utils.genericUserSummary +import icu.samnyan.aqua.net.utils.mai2Scores import icu.samnyan.aqua.sega.maimai2.dao.userdata.UserDataRepository import icu.samnyan.aqua.sega.maimai2.dao.userdata.UserGeneralDataRepository import icu.samnyan.aqua.sega.maimai2.dao.userdata.UserPlaylogRepository import org.springframework.web.bind.annotation.RestController @RestController -@API("api/v2/game/maimai2") +@API("api/v2/game/mai2") class Maimai2( val us: AquaUserServices, val userPlaylogRepository: UserPlaylogRepository, @@ -20,69 +23,22 @@ class Maimai2( ): GameApiController { override fun trend(@RP username: Str): List = us.byName(username) { u -> - // O(n log n) sort - val d = userPlaylogRepository.findByUser_Card_ExtId(u.ghostCard.extId).sortedBy { it.playDate }.toList() - - // Precompute the play counts for each date in O(n) - val playCounts = d.groupingBy { it.playDate }.eachCount() - - // Find the max afterRating on each date - val maxRating = d.groupingBy { it.playDate }.fold(0) { acc, e -> maxOf(acc, e.afterRating) } - - // Use the precomputed play counts - d.distinctBy { it.playDate } - .map { TrendOut(it.playDate, maxRating[it.playDate] ?: 0, - playCounts[it.playDate] ?: 0) } - .sortedBy { it.date } + findTrend(userPlaylogRepository.findByUser_Card_ExtId(u.ghostCard.extId) + .map { TrendLog(it.playDate, it.afterRating) }) } - private val shownRanks = listOf( - 100.5 to "SSS+", - 100.0 to "SSS", - 99.5 to "SS+", - 99.0 to "SS", - 98.0 to "S+", - 97.0 to "S").map { (k, v) -> (k * 10000).toInt() to v } + // Only show > S rank + private val shownRanks = mai2Scores.filter { it.first >= 97 } override fun userSummary(@RP username: Str) = us.byName(username) { u -> - // Summary values: total plays, player rating, server-wide ranking - // number of each rank, max combo, number of full combo, number of all perfect - val user = userDataRepository.findByCard(u.ghostCard) ?: (404 - "User not found") - val plays = userPlaylogRepository.findByUser_Card_ExtId(u.ghostCard.extId) val extra = userGeneralDataRepository.findByUser_Card_ExtId(u.ghostCard.extId) .associate { it.propertyKey to it.propertyValue } - // O(6n) ranks algorithm: Loop through the entire list of plays, - // count the number of each rank - val ranks = shownRanks.associate { (_, v) -> v to 0 }.toMutableMap() - plays.forEach { - shownRanks.find { (s, _) -> it.achievement > s }?.let { (_, v) -> ranks[v] = ranks[v]!! + 1 } - } - - GenericGameSummary( - name = user.userName, - iconId = user.iconId, - serverRank = userDataRepository.getRanking(user.playerRating), - accuracy = plays.sumOf { it.achievement }.toDouble() / plays.size, - rating = user.playerRating, - ratingHighest = user.highestRating, - ranks = ranks.map { (k, v) -> RankCount(k, v) }, - maxCombo = plays.maxOf { it.maxCombo }, - fullCombo = plays.count { it.totalCombo == it.maxCombo }, - allPerfect = plays.count { it.achievement == 1010000 }, - totalScore = user.totalDeluxscore, - plays = plays.size, - totalPlayTime = plays.count() * 3L, // TODO: Give a better estimate - joined = user.firstPlayDate, - lastSeen = user.lastPlayDate, - lastVersion = user.lastRomVersion, - ratingComposition = mapOf( - "best35" to (extra["recent_rating"] ?: ""), - "best15" to (extra["recent_rating_new"] ?: "") - ), - recent = plays.sortedBy { it.playDate }.takeLast(15).map { - GenericGamePlaylog(it.playDate, it.achievement, it.maxCombo, it.totalCombo) - } + val ratingComposition = mapOf( + "best35" to (extra["recent_rating"] ?: ""), + "best15" to (extra["recent_rating_new"] ?: "") ) + + genericUserSummary(u, userDataRepository, userPlaylogRepository, shownRanks, ratingComposition) } } \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/net/games/Models.kt b/src/main/java/icu/samnyan/aqua/net/games/Models.kt index c93fd688..19461680 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Models.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Models.kt @@ -8,7 +8,8 @@ data class GenericGamePlaylog( val playDate: String, val achievement: Int, val maxCombo: Int, - val totalCombo: Int + val totalCombo: Int, + val afterRating: Int ) data class RankCount(val name: String, val count: Int) diff --git a/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt b/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt new file mode 100644 index 00000000..0fdfff78 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt @@ -0,0 +1,105 @@ +package icu.samnyan.aqua.net.utils + +import ext.minus +import icu.samnyan.aqua.net.db.AquaNetUser +import icu.samnyan.aqua.net.games.GenericGamePlaylog +import icu.samnyan.aqua.net.games.GenericGameSummary +import icu.samnyan.aqua.net.games.RankCount +import icu.samnyan.aqua.net.games.TrendOut +import icu.samnyan.aqua.sega.general.model.Card + +data class TrendLog(val date: String, val rating: Int) + +/** + * Find the trend of a user's rating + */ +fun findTrend(log: List): List { + // O(n log n) + val d = log.sortedBy { it.date }.toList() + + // Precompute the play counts for each date in O(n) + val playCounts = d.groupingBy { it.date }.eachCount() + + // Find the max afterRating on each date + val maxRating = d.groupingBy { it.date }.fold(0) { acc, e -> maxOf(acc, e.rating) } + + // Use the precomputed play counts + return d.distinctBy { it.date } + .map { TrendOut(it.date, maxRating[it.date] ?: 0, + playCounts[it.date] ?: 0) } + .sortedBy { it.date } +} + +// Here are some interfaces to generalize across multiple games +interface IGenericUserData { + val userName: String + val iconId: Int + val playerRating: Int + val highestRating: Int + val firstPlayDate: Any + val lastPlayDate: Any + val lastRomVersion: String + val totalScore: Long +} + +interface GenericUserDataRepo { + fun findByCard(card: Card): IGenericUserData? + fun getRanking(rating: Int): Long +} + +interface IGenericGamePlaylog { + val date: Any + val achievement: Int + val maxCombo: Int + val totalCombo: Int + val afterRating: Int +} + +interface GenericPlaylogRepo { + fun findByUserCardExtId(extId: Long): List +} + +fun genericUserSummary( + u: AquaNetUser, + userDataRepo: GenericUserDataRepo, + userPlaylogRepo: GenericPlaylogRepo, + shownRanks: List>, + ratingComposition: Map, +): GenericGameSummary { + // Summary values: total plays, player rating, server-wide ranking + // number of each rank, max combo, number of full combo, number of all perfect + val user = userDataRepo.findByCard(u.ghostCard) ?: (404 - "User not found") + val plays = userPlaylogRepo.findByUserCardExtId(u.ghostCard.extId) + + // O(6n) ranks algorithm: Loop through the entire list of plays, + // count the number of each rank + val ranks = shownRanks.associate { (_, v) -> v to 0 }.toMutableMap() + plays.forEach { + shownRanks.find { (s, _) -> it.achievement > s }?.let { (_, v) -> ranks[v] = ranks[v]!! + 1 } + } + + return GenericGameSummary( + name = user.userName, + iconId = user.iconId, + serverRank = userDataRepo.getRanking(user.playerRating), + accuracy = plays.sumOf { it.achievement }.toDouble() / plays.size, + rating = user.playerRating, + ratingHighest = user.highestRating, + ranks = ranks.map { (k, v) -> RankCount(k, v) }, + maxCombo = plays.maxOf { it.maxCombo }, + fullCombo = plays.count { it.totalCombo == it.maxCombo }, + allPerfect = plays.count { it.achievement == 1010000 }, + totalScore = user.totalScore, + plays = plays.size, + totalPlayTime = plays.count() * 3L, // TODO: Give a better estimate + joined = user.firstPlayDate.toString(), + lastSeen = user.lastPlayDate.toString(), + lastVersion = user.lastRomVersion, + ratingComposition = ratingComposition, + recent = plays.sortedBy { it.date.toString() }.takeLast(15).map { + GenericGamePlaylog(it.date.toString(), it.achievement, it.maxCombo, it.totalCombo, it.afterRating) + } + ) +} + + diff --git a/src/main/java/icu/samnyan/aqua/net/utils/GameScoring.kt b/src/main/java/icu/samnyan/aqua/net/utils/GameScoring.kt new file mode 100644 index 00000000..fcd06362 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/net/utils/GameScoring.kt @@ -0,0 +1,33 @@ +package icu.samnyan.aqua.net.utils + + +val mai2Scores = listOf( + 100.5 to "SSS+", + 100.0 to "SSS", + 99.5 to "SS+", + 99.0 to "SS", + 98.0 to "S+", + 97.0 to "S", + 94.0 to "AAA", + 90.0 to "AA", + 80.0 to "A", + 75.0 to "BBB", + 70.0 to "BB", + 60.0 to "B", + 50.0 to "C", + 0.0 to "D", +).map { (k, v) -> (k * 10000).toInt() to v } + +val chu3Scores = listOf( + 100.75 to "SSS", + 100.0 to "SS", + 97.5 to "S", + 95.0 to "AAA", + 92.5 to "AA", + 90.0 to "A", + 80.0 to "BBB", + 70.0 to "BB", + 60.0 to "B", + 50.0 to "C", + 0.0 to "D", +).map { (k, v) -> (k * 10000).toInt() to v } \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.kt index 8acce5a5..903db09f 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.kt @@ -1,5 +1,6 @@ package icu.samnyan.aqua.sega.maimai2.dao.userdata +import icu.samnyan.aqua.net.utils.GenericUserDataRepo import icu.samnyan.aqua.sega.general.model.Card import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail import org.springframework.data.jpa.repository.JpaRepository @@ -10,8 +11,8 @@ import java.util.* @Repository("Maimai2UserDataRepository") -interface UserDataRepository : JpaRepository { - fun findByCard(card: Card): UserDetail? +interface UserDataRepository : JpaRepository, GenericUserDataRepo { + override fun findByCard(card: Card): UserDetail? fun findByCardExtId(userId: Long): Optional @@ -19,5 +20,5 @@ interface UserDataRepository : JpaRepository { fun deleteByCard(card: Card) @Query("select count(*) from Maimai2UserData where playerRating > :rating") - fun getRanking(rating: Int): Long + override fun getRanking(rating: Int): Long } diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserPlaylogRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserPlaylogRepository.java index 4ca79e42..dce766f0 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserPlaylogRepository.java +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserPlaylogRepository.java @@ -1,5 +1,6 @@ package icu.samnyan.aqua.sega.maimai2.dao.userdata; +import icu.samnyan.aqua.net.utils.GenericPlaylogRepo; import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail; import icu.samnyan.aqua.sega.maimai2.model.userdata.UserPlaylog; @@ -15,7 +16,7 @@ import org.springframework.transaction.annotation.Transactional; * @author samnyan (privateamusement@protonmail.com) */ @Repository("Maimai2UserPlaylogRepository") -public interface UserPlaylogRepository extends JpaRepository { +public interface UserPlaylogRepository extends JpaRepository, GenericPlaylogRepo { List findByUser_Card_ExtId(long userId); diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserPreviewHandler.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserPreviewHandler.java index 24eeecde..d9a4c297 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserPreviewHandler.java +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetUserPreviewHandler.java @@ -61,7 +61,7 @@ public class GetUserPreviewHandler implements BaseHandler { resp.setPartnerId(user.getPartnerId()); resp.setFrameId(user.getFrameId()); resp.setTotalAwake(user.getTotalAwake()); - resp.setIsNetMember(user.getIsNetMember()); + resp.setIsNetMember(user.isNetMember()); resp.setDailyBonusDate(user.getDailyBonusDate()); if (userOptionOptional.isPresent()) { UserOption option = userOptionOptional.get(); diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/UpsertUserAllHandler.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/UpsertUserAllHandler.java index 541525c3..d3f7081f 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/UpsertUserAllHandler.java +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/UpsertUserAllHandler.java @@ -103,7 +103,7 @@ public class UpsertUserAllHandler implements BaseHandler { newUserData.setUserName(userName); // Set isNetMember value to 1, which enables some in-game features. - newUserData.setIsNetMember(1); + newUserData.setNetMember(1); userDataRepository.saveAndFlush(newUserData); } diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.java deleted file mode 100644 index b93c5997..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.java +++ /dev/null @@ -1,156 +0,0 @@ -package icu.samnyan.aqua.sega.maimai2.model.userdata; - -import java.io.Serializable; -import java.util.List; - -import jakarta.persistence.*; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -import icu.samnyan.aqua.sega.util.jackson.AccessCodeSerializer; -import icu.samnyan.aqua.sega.general.model.Card; -import icu.samnyan.aqua.sega.maimai2.util.IntegerListConverter; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Entity(name = "Maimai2UserData") -@Table(name = "maimai2_user_detail") -@Data -@AllArgsConstructor -@NoArgsConstructor -public class UserDetail implements Serializable { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @JsonIgnore - private long id; - - @JsonSerialize(using = AccessCodeSerializer.class) - @JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY) - @OneToOne - @JoinColumn(name = "aime_card_id") - private Card card; - - private String userName; - @JsonInclude - @Transient - private String friendCode = ""; - private int isNetMember; - @JsonInclude - @Transient - private int nameplateId = 0; - private int iconId; - @JsonInclude - @Transient - private int trophyId = 0; - private int plateId; - private int titleId; - private int partnerId; - private int frameId; - private int selectMapId; - private int totalAwake; - private int gradeRating; - private int musicRating; - private int playerRating; - private int highestRating; - private int gradeRank; - private int classRank; - private int courseRank; - - @Convert(converter = IntegerListConverter.class) - private List charaSlot; // Entries: 5 - - @Convert(converter = IntegerListConverter.class) - private List charaLockSlot; // Entries: 5 - - private long contentBit; - private int playCount; - private String eventWatchedDate; - private String lastGameId; - private String lastRomVersion; - private String lastDataVersion; - private String lastLoginDate; - private String lastPlayDate; - private int lastPlayCredit; - private int lastPlayMode; - private int lastPlaceId; - private String lastPlaceName; - private int lastAllNetId; - private int lastRegionId; - private String lastRegionName; - private String lastClientId; - private String lastCountryCode; - private int lastSelectEMoney; - private int lastSelectTicket; - private int lastSelectCourse; - private int lastCountCourse; - private String firstGameId; - private String firstRomVersion; - private String firstDataVersion; - private String firstPlayDate; - private String compatibleCmVersion; - private String dailyBonusDate; - private String dailyCourseBonusDate; - private String lastPairLoginDate; - private String lastTrialPlayDate; - private int playVsCount; - private int playSyncCount; - private int winCount; - private int helpCount; - private int comboCount; - private long totalDeluxscore; - private long totalBasicDeluxscore; - private long totalAdvancedDeluxscore; - private long totalExpertDeluxscore; - private long totalMasterDeluxscore; - private long totalReMasterDeluxscore; - @JsonInclude - @Transient - private long totalHiscore = 0; - @JsonInclude - @Transient - private long totalBasicHighscore = 0; - @JsonInclude - @Transient - private long totalAdvancedHighscore = 0; - @JsonInclude - @Transient - private long totalExpertHighscore = 0; - @JsonInclude - @Transient - private long totalMasterHighscore = 0; - @JsonInclude - @Transient - private long totalReMasterHighscore = 0; - private int totalSync; - private int totalBasicSync; - private int totalAdvancedSync; - private int totalExpertSync; - private int totalMasterSync; - private int totalReMasterSync; - private long totalAchievement; - private long totalBasicAchievement; - private long totalAdvancedAchievement; - private long totalExpertAchievement; - private long totalMasterAchievement; - private long totalReMasterAchievement; - private long playerOldRating; - private long playerNewRating; - private int banState; - private long dateTime; - @JsonInclude - @Transient - private int cmLastEmoneyBrand = 2; - @JsonInclude - @Transient - private int cmLastEmoneyCredit = 69; - private int mapStock; -} diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.kt new file mode 100644 index 00000000..d13e5bf2 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserDetail.kt @@ -0,0 +1,160 @@ +package icu.samnyan.aqua.sega.maimai2.model.userdata + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import ext.Str +import icu.samnyan.aqua.net.utils.IGenericUserData +import icu.samnyan.aqua.sega.general.model.Card +import icu.samnyan.aqua.sega.maimai2.util.IntegerListConverter +import icu.samnyan.aqua.sega.util.jackson.AccessCodeSerializer +import jakarta.persistence.* +import java.io.Serializable + +/** + * @author samnyan (privateamusement@protonmail.com) + */ +@Entity(name = "Maimai2UserData") +@Table(name = "maimai2_user_detail") +class UserDetail( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @JsonIgnore + var id: Long = 0, + + @JsonSerialize(using = AccessCodeSerializer::class) + @JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY) + @OneToOne + @JoinColumn(name = "aime_card_id") + var card: Card? = null, + + override var userName: String = "", + + @JsonInclude + @Transient + var friendCode: Str = "", + var isNetMember: Int = 0, + + @JsonInclude + @Transient + var nameplateId: Int = 0, + override var iconId: Int = 0, + + @JsonInclude + @Transient + var trophyId: Int = 0, + var plateId: Int = 0, + var titleId: Int = 0, + var partnerId: Int = 0, + var frameId: Int = 0, + var selectMapId: Int = 0, + var totalAwake: Int = 0, + var gradeRating: Int = 0, + var musicRating: Int = 0, + override var playerRating: Int = 0, + override var highestRating: Int = 0, + var gradeRank: Int = 0, + var classRank: Int = 0, + var courseRank: Int = 0, + + @Convert(converter = IntegerListConverter::class) + var charaSlot: List? = null, // Entries: 5 + + @Convert(converter = IntegerListConverter::class) + var charaLockSlot: List? = null, // Entries: 5 + + var contentBit: Long = 0, + var playCount: Int = 0, + var eventWatchedDate: String = "", + var lastGameId: String = "", + override var lastRomVersion: String = "", + var lastDataVersion: String = "", + var lastLoginDate: String = "", + override var lastPlayDate: String = "", + var lastPlayCredit: Int = 0, + var lastPlayMode: Int = 0, + var lastPlaceId: Int = 0, + var lastPlaceName: String = "", + var lastAllNetId: Int = 0, + var lastRegionId: Int = 0, + var lastRegionName: String = "", + var lastClientId: String = "", + var lastCountryCode: String = "", + var lastSelectEMoney: Int = 0, + var lastSelectTicket: Int = 0, + var lastSelectCourse: Int = 0, + var lastCountCourse: Int = 0, + var firstGameId: String = "", + var firstRomVersion: String = "", + var firstDataVersion: String = "", + override var firstPlayDate: String = "", + var compatibleCmVersion: String = "", + var dailyBonusDate: String = "", + var dailyCourseBonusDate: String = "", + var lastPairLoginDate: String = "", + var lastTrialPlayDate: String = "", + var playVsCount: Int = 0, + var playSyncCount: Int = 0, + var winCount: Int = 0, + var helpCount: Int = 0, + var comboCount: Int = 0, + var totalDeluxscore: Long = 0, + var totalBasicDeluxscore: Long = 0, + var totalAdvancedDeluxscore: Long = 0, + var totalExpertDeluxscore: Long = 0, + var totalMasterDeluxscore: Long = 0, + var totalReMasterDeluxscore: Long = 0, + + @JsonInclude + @Transient + var totalHiscore: Long = 0, + + @JsonInclude + @Transient + var totalBasicHighscore: Long = 0, + + @JsonInclude + @Transient + var totalAdvancedHighscore: Long = 0, + + @JsonInclude + @Transient + var totalExpertHighscore: Long = 0, + + @JsonInclude + @Transient + var totalMasterHighscore: Long = 0, + + @JsonInclude + @Transient + var totalReMasterHighscore: Long = 0, + var totalSync: Int = 0, + var totalBasicSync: Int = 0, + var totalAdvancedSync: Int = 0, + var totalExpertSync: Int = 0, + var totalMasterSync: Int = 0, + var totalReMasterSync: Int = 0, + var totalAchievement: Long = 0, + var totalBasicAchievement: Long = 0, + var totalAdvancedAchievement: Long = 0, + var totalExpertAchievement: Long = 0, + var totalMasterAchievement: Long = 0, + var totalReMasterAchievement: Long = 0, + var playerOldRating: Long = 0, + var playerNewRating: Long = 0, + var banState: Int = 0, + var dateTime: Long = 0, + + @JsonInclude + @Transient + var cmLastEmoneyBrand: Int = 2, + + @JsonInclude + @Transient + var cmLastEmoneyCredit: Int = 69, + var mapStock: Int = 0, +) : Serializable, IGenericUserData { + override val totalScore: Long + get() = totalDeluxscore +} diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserPlaylog.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserPlaylog.java index 157e45c5..6a70b945 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserPlaylog.java +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserPlaylog.java @@ -2,11 +2,14 @@ package icu.samnyan.aqua.sega.maimai2.model.userdata; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import icu.samnyan.aqua.net.utils.IGenericGamePlaylog; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import jakarta.persistence.*; +import org.jetbrains.annotations.NotNull; + import java.io.Serializable; /** @@ -17,7 +20,7 @@ import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor -public class UserPlaylog implements Serializable { +public class UserPlaylog implements Serializable, IGenericGamePlaylog { private static final long serialVersionUID = 1L; @@ -255,4 +258,9 @@ public class UserPlaylog implements Serializable { private int extNum2; + @NotNull + @Override + public Object getDate() { + return playDate; + } }