[M] Move packages

This commit is contained in:
Azalea 2024-03-19 21:02:24 -04:00
parent 3c6d6ff702
commit faf1945933
5 changed files with 166 additions and 161 deletions

View File

@ -22,9 +22,12 @@ import java.nio.file.Path
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import kotlin.reflect.KCallable
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.jvmErasure
typealias RP = RequestParam typealias RP = RequestParam
typealias RB = RequestBody typealias RB = RequestBody
@ -50,6 +53,7 @@ fun <T : Any> KClass<T>.vars() = memberProperties.mapNotNull { it as? KMutablePr
fun <T : Any> KClass<T>.varsMap() = vars().associateBy { it.name } fun <T : Any> KClass<T>.varsMap() = vars().associateBy { it.name }
fun <T : Any> KClass<T>.getters() = java.methods.filter { it.name.startsWith("get") } fun <T : Any> KClass<T>.getters() = java.methods.filter { it.name.startsWith("get") }
fun <T : Any> KClass<T>.gettersMap() = getters().associateBy { it.name.removePrefix("get").decapitalize() } fun <T : Any> KClass<T>.gettersMap() = getters().associateBy { it.name.removePrefix("get").decapitalize() }
infix fun KCallable<*>.returns(type: KClass<*>) = returnType.jvmErasure.isSubclassOf(type)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <C, T: Any> KMutableProperty1<C, T>.setCast(obj: C, value: String) = set(obj, when (returnType.classifier) { fun <C, T: Any> KMutableProperty1<C, T>.setCast(obj: C, value: String) = set(obj, when (returnType.classifier) {
String::class -> value String::class -> value

View File

@ -1,47 +1,48 @@
package icu.samnyan.aqua.net.games package icu.samnyan.aqua.net.games.chu3
import ext.API import ext.API
import ext.RP import ext.RP
import ext.Str import ext.Str
import ext.minus import ext.minus
import icu.samnyan.aqua.net.db.AquaUserServices import icu.samnyan.aqua.net.db.AquaUserServices
import icu.samnyan.aqua.net.utils.* import icu.samnyan.aqua.net.games.*
import icu.samnyan.aqua.sega.chusan.model.* import icu.samnyan.aqua.net.utils.*
import icu.samnyan.aqua.sega.chusan.model.userdata.UserData import icu.samnyan.aqua.sega.chusan.model.*
import org.springframework.web.bind.annotation.RestController import icu.samnyan.aqua.sega.chusan.model.userdata.UserData
import org.springframework.web.bind.annotation.RestController
@RestController
@API("api/v2/game/chu3") @RestController
class Chusan( @API("api/v2/game/chu3")
override val us: AquaUserServices, class Chusan(
override val playlogRepo: Chu3UserPlaylogRepo, override val us: AquaUserServices,
override val userDataRepo: Chu3UserDataRepo, override val playlogRepo: Chu3UserPlaylogRepo,
val userGeneralDataRepository: Chu3UserGeneralDataRepo, override val userDataRepo: Chu3UserDataRepo,
): GameApiController<UserData>("chu3", UserData::class) { val userGeneralDataRepository: Chu3UserGeneralDataRepo,
override suspend fun trend(@RP username: Str): List<TrendOut> = us.cardByName(username) { card -> ): GameApiController<UserData>("chu3", UserData::class) {
findTrend(playlogRepo.findByUserCardExtId(card.extId) override suspend fun trend(@RP username: Str): List<TrendOut> = us.cardByName(username) { card ->
.map { TrendLog(it.playDate.toString(), it.playerRating) }) findTrend(playlogRepo.findByUserCardExtId(card.extId)
} .map { TrendLog(it.playDate.toString(), it.playerRating) })
}
// Only show > AAA rank
override val shownRanks = chu3Scores.filter { it.first >= 95 * 10000 } // Only show > AAA rank
override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf( override val shownRanks = chu3Scores.filter { it.first >= 95 * 10000 }
"userName" to { u, v -> u.setUserName(v) override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf(
if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" } "userName" to { u, v -> u.setUserName(v)
}, if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
) } },
) }
override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card ->
// Summary values: total plays, player rating, server-wide ranking override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card ->
// number of each rank, max combo, number of full combo, number of all perfect // Summary values: total plays, player rating, server-wide ranking
val extra = userGeneralDataRepository.findByUser_Card_ExtId(card.extId) // number of each rank, max combo, number of full combo, number of all perfect
.associate { it.propertyKey to it.propertyValue } val extra = userGeneralDataRepository.findByUser_Card_ExtId(card.extId)
.associate { it.propertyKey to it.propertyValue }
val ratingComposition = mapOf(
"recent" to (extra["recent_rating_list"] ?: ""), val ratingComposition = mapOf(
) "recent" to (extra["recent_rating_list"] ?: ""),
)
genericUserSummary(card, ratingComposition)
} genericUserSummary(card, ratingComposition)
}
} }

View File

@ -1,75 +1,71 @@
package icu.samnyan.aqua.net.games package icu.samnyan.aqua.net.games.mai2
import ext.API import ext.*
import ext.RP import icu.samnyan.aqua.api.model.resp.sega.maimai2.external.Maimai2DataExport
import ext.Str import icu.samnyan.aqua.net.db.AquaUserServices
import ext.minus import icu.samnyan.aqua.net.games.*
import icu.samnyan.aqua.api.model.resp.sega.maimai2.external.Maimai2DataExport import icu.samnyan.aqua.net.utils.*
import icu.samnyan.aqua.net.db.AquaUserServices import icu.samnyan.aqua.sega.maimai2.model.*
import icu.samnyan.aqua.net.utils.* import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail
import icu.samnyan.aqua.sega.maimai2.model.* import org.springframework.web.bind.annotation.RestController
import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail import java.lang.reflect.Field
import org.springframework.web.bind.annotation.RestController import java.util.*
import java.lang.reflect.Field import kotlin.reflect.full.declaredMembers
import java.util.*
import kotlin.reflect.full.declaredMembers @RestController
import kotlin.reflect.full.isSubclassOf @API("api/v2/game/mai2")
import kotlin.reflect.jvm.jvmErasure class Maimai2(
override val us: AquaUserServices,
@RestController override val playlogRepo: Mai2UserPlaylogRepo,
@API("api/v2/game/mai2") override val userDataRepo: Mai2UserDataRepo,
class Maimai2( val userGeneralDataRepository: Mai2UserGeneralDataRepo,
override val us: AquaUserServices, val repos: Mai2Repos
override val playlogRepo: Mai2UserPlaylogRepo, ): GameApiController<UserDetail>("mai2", UserDetail::class) {
override val userDataRepo: Mai2UserDataRepo, override suspend fun trend(@RP username: Str): List<TrendOut> = us.cardByName(username) { card ->
val userGeneralDataRepository: Mai2UserGeneralDataRepo, findTrend(playlogRepo.findByUserCardExtId(card.extId)
val repos: Mai2Repos .map { TrendLog(it.playDate, it.afterRating) })
): GameApiController<UserDetail>("mai2", UserDetail::class) { }
override suspend fun trend(@RP username: Str): List<TrendOut> = us.cardByName(username) { card ->
findTrend(playlogRepo.findByUserCardExtId(card.extId) // Only show > S rank
.map { TrendLog(it.playDate, it.afterRating) }) override val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 }
} override val settableFields: Map<String, (UserDetail, String) -> Unit> by lazy { mapOf(
"userName" to { u, v -> u.userName = v
// Only show > S rank if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
override val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 } },
override val settableFields: Map<String, (UserDetail, String) -> Unit> by lazy { mapOf( ) }
"userName" to { u, v -> u.userName = v
if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" } override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card ->
}, val extra = userGeneralDataRepository.findByUser_Card_ExtId(card.extId)
) } .associate { it.propertyKey to it.propertyValue }
override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card -> val ratingComposition = mapOf(
val extra = userGeneralDataRepository.findByUser_Card_ExtId(card.extId) "best35" to (extra["recent_rating"] ?: ""),
.associate { it.propertyKey to it.propertyValue } "best15" to (extra["recent_rating_new"] ?: "")
)
val ratingComposition = mapOf(
"best35" to (extra["recent_rating"] ?: ""), genericUserSummary(card, ratingComposition)
"best15" to (extra["recent_rating_new"] ?: "") }
)
// Use reflection to get all properties in Mai2Repos with matching names in Maimai2DataExport
genericUserSummary(card, ratingComposition) var exportFields: Map<Field, UserLinked<*>> = listOf(*Maimai2DataExport::class.java.declaredFields)
} .filter { it.name !in arrayOf("gameId", "userData") }
.associateWith { Mai2Repos::class.declaredMembers
// Use reflection to get all properties in Mai2Repos with matching names in Maimai2DataExport .filter { f -> f returns UserLinked::class }
var exportFields: Map<Field, UserLinked<*>> = listOf(*Maimai2DataExport::class.java.declaredFields) .firstOrNull { f -> f.name == it.name || f.name == it.name.replace("List", "") }
.filter { it.name !in arrayOf("gameId", "userData") } ?.call(repos) as UserLinked<*>? ?: error("No matching field found for ${it.name}")
.associateWith { Mai2Repos::class.declaredMembers }
.filter { f -> f.returnType.jvmErasure.isSubclassOf(UserLinked::class) }
.firstOrNull { f -> f.name == it.name || f.name == it.name.replace("List", "") } @API("export")
?.call(repos) as UserLinked<*>? ?: error("No matching field found for ${it.name}") fun exportAllUserData(@RP token: Str) = us.jwt.auth(token) { u ->
} try {
Maimai2DataExport().apply {
@API("export") gameId = "SDEZ"
fun exportAllUserData(@RP token: Str) = us.jwt.auth(token) { u -> userData = repos.userData.findByCard(u.ghostCard) ?: (404 - "User not found")
try { exportFields.forEach { (f, u) ->
Maimai2DataExport().apply { f.set(this, if (f.type == List::class.java) u.findByUser(userData)
gameId = "SDEZ" else u.findSingleByUser(userData).orElse(null))
userData = repos.userData.findByCard(u.ghostCard) ?: (404 - "User not found") }
exportFields.forEach { (f, u) -> }
f.set(this, if (f.type == List::class.java) u.findByUser(userData) } catch (e: Exception) { 500 - "Error during data export. Reason: ${e.message}" }
else u.findSingleByUser(userData).orElse(null)) }
}
}
} catch (e: Exception) { 500 - "Error during data export. Reason: ${e.message}" }
}
} }

View File

@ -1,41 +1,45 @@
package icu.samnyan.aqua.net.games package icu.samnyan.aqua.net.games.ongeki
import ext.API import ext.API
import ext.minus import ext.minus
import icu.samnyan.aqua.net.db.AquaUserServices import icu.samnyan.aqua.net.db.AquaUserServices
import icu.samnyan.aqua.net.utils.* import icu.samnyan.aqua.net.games.GameApiController
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserDataRepository import icu.samnyan.aqua.net.games.TrendLog
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserGeneralDataRepository import icu.samnyan.aqua.net.games.USERNAME_CHARS
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserPlaylogRepository import icu.samnyan.aqua.net.games.findTrend
import icu.samnyan.aqua.sega.ongeki.model.userdata.UserData import icu.samnyan.aqua.net.utils.*
import org.springframework.web.bind.annotation.RestController import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserDataRepository
import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserGeneralDataRepository
@RestController import icu.samnyan.aqua.sega.ongeki.dao.userdata.UserPlaylogRepository
@API("api/v2/game/ongeki") import icu.samnyan.aqua.sega.ongeki.model.userdata.UserData
class Ongeki( import org.springframework.web.bind.annotation.RestController
override val us: AquaUserServices,
override val playlogRepo: UserPlaylogRepository, @RestController
override val userDataRepo: UserDataRepository, @API("api/v2/game/ongeki")
val userGeneralDataRepository: UserGeneralDataRepository class Ongeki(
): GameApiController<UserData>("ongeki", UserData::class) { override val us: AquaUserServices,
override suspend fun trend(username: String) = us.cardByName(username) { card -> override val playlogRepo: UserPlaylogRepository,
findTrend(playlogRepo.findByUser_Card_ExtId(card.extId) override val userDataRepo: UserDataRepository,
.map { TrendLog(it.playDate, it.playerRating) }) val userGeneralDataRepository: UserGeneralDataRepository
} ): GameApiController<UserData>("ongeki", UserData::class) {
override suspend fun trend(username: String) = us.cardByName(username) { card ->
override val shownRanks = ongekiScores.filter { it.first >= 950000 } findTrend(playlogRepo.findByUser_Card_ExtId(card.extId)
override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf( .map { TrendLog(it.playDate, it.playerRating) })
"userName" to { u, v -> u.setUserName(v) }
if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
}, override val shownRanks = ongekiScores.filter { it.first >= 950000 }
) } override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf(
"userName" to { u, v -> u.setUserName(v)
override suspend fun userSummary(username: String) = us.cardByName(username) { card -> if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
// val extra = userGeneralDataRepository.findByUser_Card_ExtId(u.ghostCard.extId) },
// .associate { it.propertyKey to it.propertyValue } ) }
// TODO: Rating composition override suspend fun userSummary(username: String) = us.cardByName(username) { card ->
// val extra = userGeneralDataRepository.findByUser_Card_ExtId(u.ghostCard.extId)
genericUserSummary(card, mapOf()) // .associate { it.propertyKey to it.propertyValue }
}
// TODO: Rating composition
genericUserSummary(card, mapOf())
}
} }

View File

@ -1,6 +1,6 @@
package icu.samnyan.aqua.sega.maimai2.handler.impl package icu.samnyan.aqua.sega.maimai2.handler.impl
import icu.samnyan.aqua.net.games.Maimai2 import icu.samnyan.aqua.net.games.mai2.Maimai2
import icu.samnyan.aqua.sega.general.dao.CardRepository import icu.samnyan.aqua.sega.general.dao.CardRepository
import icu.samnyan.aqua.sega.maimai2.handler.BaseHandler import icu.samnyan.aqua.sega.maimai2.handler.BaseHandler
import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos