From 7669f7d9a0e08123d020361ab6c5320d77ab642f Mon Sep 17 00:00:00 2001 From: Azalea <22280294+hykilpikonna@users.noreply.github.com> Date: Fri, 15 Mar 2024 01:26:52 -0400 Subject: [PATCH] [O] Refactor --- .../java/icu/samnyan/aqua/net/games/Chusan.kt | 18 +++----- .../icu/samnyan/aqua/net/games/Maimai2.kt | 18 +++----- .../java/icu/samnyan/aqua/net/games/Models.kt | 46 +++++++++++++++---- .../java/icu/samnyan/aqua/net/games/Ongeki.kt | 18 +++----- .../icu/samnyan/aqua/net/utils/GameHelper.kt | 43 +++-------------- 5 files changed, 63 insertions(+), 80 deletions(-) diff --git a/src/main/java/icu/samnyan/aqua/net/games/Chusan.kt b/src/main/java/icu/samnyan/aqua/net/games/Chusan.kt index c2a6a2b0..a7ecbc8b 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Chusan.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Chusan.kt @@ -3,31 +3,29 @@ 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.* import icu.samnyan.aqua.sega.chusan.dao.userdata.UserDataRepository import icu.samnyan.aqua.sega.chusan.dao.userdata.UserGeneralDataRepository import icu.samnyan.aqua.sega.chusan.dao.userdata.UserPlaylogRepository import org.springframework.web.bind.annotation.RestController -import kotlin.jvm.optionals.getOrNull @RestController @API("api/v2/game/chu3") class Chusan( val us: AquaUserServices, - val userPlaylogRepository: UserPlaylogRepository, - val userDataRepository: UserDataRepository, + override val playlogRepo: UserPlaylogRepository, + override val userDataRepo: UserDataRepository, val userGeneralDataRepository: UserGeneralDataRepository ): GameApiController("chu3") { override suspend fun trend(@RP username: Str): List = us.cardByName(username) { card -> - findTrend(userPlaylogRepository.findByUser_Card_ExtId(card.extId) + findTrend(playlogRepo.findByUser_Card_ExtId(card.extId) .map { TrendLog(it.playDate.toString(), it.playerRating) }) } // Only show > AAA rank - private val shownRanks = chu3Scores.filter { it.first >= 95 * 10000 } + override val shownRanks = chu3Scores.filter { it.first >= 95 * 10000 } override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card -> // Summary values: total plays, player rating, server-wide ranking @@ -39,14 +37,10 @@ class Chusan( "recent" to (extra["recent_rating_list"] ?: ""), ) - genericUserSummary(card, userDataRepository, userPlaylogRepository, shownRanks, ratingComposition) + genericUserSummary(card, ratingComposition) } - override suspend fun ranking() = genericRanking(userDataRepository, userPlaylogRepository) - - override suspend fun playlog(@RP id: Long) = userPlaylogRepository.findById(id).getOrNull() ?: (404 - "Playlog not found") - override suspend fun recent(@RP username: Str) = us.cardByName(username) { card -> - userPlaylogRepository.findByUser_Card_ExtId(card.extId) + playlogRepo.findByUser_Card_ExtId(card.extId) } } \ No newline at end of file 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 644ba2c5..ee0f0be8 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Maimai2.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Maimai2.kt @@ -3,31 +3,29 @@ 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.* 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 -import kotlin.jvm.optionals.getOrNull @RestController @API("api/v2/game/mai2") class Maimai2( val us: AquaUserServices, - val userPlaylogRepository: UserPlaylogRepository, - val userDataRepository: UserDataRepository, + override val playlogRepo: UserPlaylogRepository, + override val userDataRepo: UserDataRepository, val userGeneralDataRepository: UserGeneralDataRepository ): GameApiController("mai2") { override suspend fun trend(@RP username: Str): List = us.cardByName(username) { card -> - findTrend(userPlaylogRepository.findByUser_Card_ExtId(card.extId) + findTrend(playlogRepo.findByUser_Card_ExtId(card.extId) .map { TrendLog(it.playDate, it.afterRating) }) } // Only show > S rank - private val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 } + override val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 } override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card -> val extra = userGeneralDataRepository.findByUser_Card_ExtId(card.extId) @@ -38,14 +36,10 @@ class Maimai2( "best15" to (extra["recent_rating_new"] ?: "") ) - genericUserSummary(card, userDataRepository, userPlaylogRepository, shownRanks, ratingComposition) + genericUserSummary(card, ratingComposition) } - override suspend fun ranking() = genericRanking(userDataRepository, userPlaylogRepository) - - override suspend fun playlog(@RP id: Long) = userPlaylogRepository.findById(id).getOrNull() ?: (404 - "Playlog not found") - override suspend fun recent(@RP username: Str) = us.cardByName(username) { card -> - userPlaylogRepository.findByUser_Card_ExtId(card.extId) + playlogRepo.findByUser_Card_ExtId(card.extId) } } \ 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 ae94e30b..31d0f265 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Models.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Models.kt @@ -1,10 +1,9 @@ package icu.samnyan.aqua.net.games -import ext.API -import ext.JSON -import ext.RP -import icu.samnyan.aqua.net.utils.IGenericGamePlaylog +import ext.* +import icu.samnyan.aqua.net.utils.* import kotlinx.serialization.Serializable +import kotlin.jvm.optionals.getOrNull data class TrendOut(val date: String, val rating: Int, val plays: Int) @@ -70,14 +69,45 @@ abstract class GameApiController(name: String) { ?.mapKeys { it.key.toInt() } ?: emptyMap() + abstract val userDataRepo: GenericUserDataRepo<*, *> + abstract val playlogRepo: GenericPlaylogRepo + abstract val shownRanks: List> + @API("trend") abstract suspend fun trend(@RP username: String): List @API("user-summary") abstract suspend fun userSummary(@RP username: String): GenericGameSummary - @API("ranking") - abstract suspend fun ranking(): List - @API("playlog") - abstract suspend fun playlog(@RP id: Long): IGenericGamePlaylog @API("recent") abstract suspend fun recent(@RP username: String): List + + + private val rankingCache = mutableMapOf>>() + @API("ranking") + fun ranking(): List { + // Read from cache if we just computed it less than 2 minutes ago + val cacheKey = playlogRepo::class.java.name + rankingCache[cacheKey]?.let { (t, r) -> + if (millis() - t < 120_000) return r + } + + // TODO: pagination + val players = userDataRepo.findAll().sortedByDescending { it.playerRating } + return players.filter { it.card != null }.mapIndexed { i, user -> + val plays = playlogRepo.findByUserCardExtId(user.card!!.extId) + + GenericRankingPlayer( + rank = i + 1, + name = user.userName, + accuracy = plays.acc(), + rating = user.playerRating, + allPerfect = plays.count { it.isAllPerfect }, + fullCombo = plays.count { it.isFullCombo }, + lastSeen = user.lastPlayDate.toString(), + username = user.card!!.aquaUser?.username ?: "user${user.card!!.id}" + ) + }.also { rankingCache[cacheKey] = millis() to it } // Update the cache + } + + @API("playlog") + fun playlog(@RP id: Long): IGenericGamePlaylog = playlogRepo.findById(id).getOrNull() ?: (404 - "Playlog not found") } \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/net/games/Ongeki.kt b/src/main/java/icu/samnyan/aqua/net/games/Ongeki.kt index ebda6dc2..61b13016 100644 --- a/src/main/java/icu/samnyan/aqua/net/games/Ongeki.kt +++ b/src/main/java/icu/samnyan/aqua/net/games/Ongeki.kt @@ -1,29 +1,27 @@ package icu.samnyan.aqua.net.games import ext.API -import ext.minus import icu.samnyan.aqua.net.db.AquaUserServices import icu.samnyan.aqua.net.utils.* import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserDataRepository import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserGeneralDataRepository import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserPlaylogRepository import org.springframework.web.bind.annotation.RestController -import kotlin.jvm.optionals.getOrNull @RestController @API("api/v2/game/ongeki") class Ongeki( val us: AquaUserServices, - val userPlaylogRepository: UserPlaylogRepository, - val userDataRepository: UserDataRepository, + override val playlogRepo: UserPlaylogRepository, + override val userDataRepo: UserDataRepository, val userGeneralDataRepository: UserGeneralDataRepository ): GameApiController("ongeki") { override suspend fun trend(username: String) = us.cardByName(username) { card -> - findTrend(userPlaylogRepository.findByUser_Card_ExtId(card.extId) + findTrend(playlogRepo.findByUser_Card_ExtId(card.extId) .map { TrendLog(it.playDate, it.playerRating) }) } - private val shownRanks = ongekiScores.filter { it.first >= 950000 } + override val shownRanks = ongekiScores.filter { it.first >= 950000 } override suspend fun userSummary(username: String) = us.cardByName(username) { card -> // val extra = userGeneralDataRepository.findByUser_Card_ExtId(u.ghostCard.extId) @@ -31,14 +29,10 @@ class Ongeki( // TODO: Rating composition - genericUserSummary(card, userDataRepository, userPlaylogRepository, shownRanks, mapOf()) + genericUserSummary(card, mapOf()) } - override suspend fun ranking() = genericRanking(userDataRepository, userPlaylogRepository) - - override suspend fun playlog(id: Long) = userPlaylogRepository.findById(id).getOrNull() ?: (404 - "Playlog not found") - override suspend fun recent(username: String) = us.cardByName(username) { card -> - userPlaylogRepository.findByUser_Card_ExtId(card.extId) + playlogRepo.findByUser_Card_ExtId(card.extId) } } \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt b/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt index b39cf280..cb7c8f39 100644 --- a/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt +++ b/src/main/java/icu/samnyan/aqua/net/utils/GameHelper.kt @@ -1,13 +1,16 @@ package icu.samnyan.aqua.net.utils import ext.isoDate -import ext.millis import ext.minus -import icu.samnyan.aqua.net.games.* +import icu.samnyan.aqua.net.games.GameApiController +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 import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.repository.NoRepositoryBean import java.time.LocalDate +import java.util.* data class TrendLog(val date: String, val rating: Int) @@ -76,21 +79,19 @@ interface IGenericGamePlaylog { interface GenericPlaylogRepo { fun findByUserCardExtId(extId: Long): List + fun findById(id: Long): Optional } fun List.acc() = if (isEmpty()) 0.0 else sumOf { it.achievement }.toDouble() / size / 10000.0 fun GameApiController.genericUserSummary( card: Card, - 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(card) ?: (404 - "Game data not found") - val plays = userPlaylogRepo.findByUserCardExtId(card.extId) + val plays = playlogRepo.findByUserCardExtId(card.extId) // Detailed ranks: Find the number of each rank in each level category // map> @@ -134,33 +135,3 @@ fun GameApiController.genericUserSummary( recent = plays.sortedBy { it.userPlayDate.toString() }.takeLast(15).reversed() ) } - -val rankingCache = mutableMapOf>>() - -fun genericRanking( - userDataRepo: GenericUserDataRepo<*, *>, - userPlaylogRepo: GenericPlaylogRepo, -): List { - // Read from cache if we just computed it less than 2 minutes ago - val cacheKey = userPlaylogRepo::class.java.name - rankingCache[cacheKey]?.let { (t, r) -> - if (millis() - t < 120_000) return r - } - - // TODO: pagination - val players = userDataRepo.findAll().sortedByDescending { it.playerRating } - return players.filter { it.card != null }.mapIndexed { i, user -> - val plays = userPlaylogRepo.findByUserCardExtId(user.card!!.extId) - - GenericRankingPlayer( - rank = i + 1, - name = user.userName, - accuracy = plays.acc(), - rating = user.playerRating, - allPerfect = plays.count { it.isAllPerfect }, - fullCombo = plays.count { it.isFullCombo }, - lastSeen = user.lastPlayDate.toString(), - username = user.card!!.aquaUser?.username ?: "user${user.card!!.id}" - ) - }.also { rankingCache[cacheKey] = millis() to it } // Update the cache -}