[O] Generalize card migration

pull/14/head
Azalea 2024-02-27 13:17:27 -05:00
parent b44121597f
commit 5166387f34
8 changed files with 54 additions and 64 deletions

View File

@ -3,6 +3,8 @@ package icu.samnyan.aqua.net
import ext.* import ext.*
import icu.samnyan.aqua.net.components.JWT import icu.samnyan.aqua.net.components.JWT
import icu.samnyan.aqua.net.utils.AquaNetProps import icu.samnyan.aqua.net.utils.AquaNetProps
import icu.samnyan.aqua.net.utils.GenericUserDataRepo
import icu.samnyan.aqua.net.utils.IGenericUserData
import icu.samnyan.aqua.net.utils.SUCCESS import icu.samnyan.aqua.net.utils.SUCCESS
import icu.samnyan.aqua.sega.general.dao.CardRepository import icu.samnyan.aqua.sega.general.dao.CardRepository
import icu.samnyan.aqua.sega.general.model.Card import icu.samnyan.aqua.sega.general.model.Card
@ -91,12 +93,42 @@ class CardController(
} }
} }
/**
* Migrate data from the card to the user's ghost card
*
* Assumption: The card is already linked to the user.
*/
suspend fun <T : IGenericUserData> migrateCard(repo: GenericUserDataRepo<T, *>, card: Card): Bool
{
// Check if data already exists in the user's ghost card
async { repo.findByCard(card.aquaUser!!.ghostCard) }?.let {
// Unbind the data from the card
it.card = null
async { repo.save(it) }
}
// Migrate data from the card to the user's ghost card
// An easy migration is to change the UserData card field to the user's ghost card
val data = async { repo.findByCard(card) } ?: return false
data.card = card.aquaUser!!.ghostCard
async { repo.save(data) }
return true
}
suspend fun getSummaryFor(repo: GenericUserDataRepo<*, *>, card: Card): Map<Str, Any>?
{
val data = async { repo.findByCard(card) } ?: return null
return mapOf(
"name" to data.userName,
"rating" to data.playerRating,
"lastLogin" to data.lastPlayDate,
)
}
@Service @Service
class CardGameService( class CardGameService(
val maimai: icu.samnyan.aqua.sega.maimai.dao.userdata.UserDataRepository,
val maimai2: icu.samnyan.aqua.sega.maimai2.dao.userdata.UserDataRepository, val maimai2: icu.samnyan.aqua.sega.maimai2.dao.userdata.UserDataRepository,
val chusan: icu.samnyan.aqua.sega.chusan.dao.userdata.UserDataRepository, val chusan: icu.samnyan.aqua.sega.chusan.dao.userdata.UserDataRepository,
val chunithm: icu.samnyan.aqua.sega.chunithm.dao.userdata.UserDataRepository,
val ongeki: icu.samnyan.aqua.sega.ongeki.dao.userdata.UserDataRepository, val ongeki: icu.samnyan.aqua.sega.ongeki.dao.userdata.UserDataRepository,
val diva: icu.samnyan.aqua.sega.diva.dao.userdata.PlayerProfileRepository, val diva: icu.samnyan.aqua.sega.diva.dao.userdata.PlayerProfileRepository,
) { ) {
@ -105,21 +137,9 @@ class CardGameService(
// An easy migration is to change the UserData card field to the user's ghost card // An easy migration is to change the UserData card field to the user's ghost card
games.forEach { game -> games.forEach { game ->
when (game) { when (game) {
"maimai" -> maimai.findByCard_ExtId(crd.extId).getOrNull()?.let { "maimai2" -> migrateCard(maimai2, crd)
maimai.save(it.apply { card = crd.aquaUser!!.ghostCard }) "chusan" -> migrateCard(chusan, crd)
} "ongeki" -> migrateCard(ongeki, crd)
"maimai2" -> maimai2.findByCardExtId(crd.extId).getOrNull()?.let {
maimai2.save(it.apply { card = crd.aquaUser!!.ghostCard })
}
"chusan" -> chusan.findByCard_ExtId(crd.extId).getOrNull()?.let {
chusan.save(it.apply { card = crd.aquaUser!!.ghostCard })
}
"chunithm" -> chunithm.findByCard_ExtId(crd.extId).getOrNull()?.let {
chunithm.save(it.apply { card = crd.aquaUser!!.ghostCard })
}
"ongeki" -> ongeki.findByCard_ExtId(crd.extId).getOrNull()?.let {
ongeki.save(it.apply { card = crd.aquaUser!!.ghostCard })
}
// TODO: diva // TODO: diva
// "diva" -> diva.findByPdId(card.extId.toInt()).getOrNull()?.let { // "diva" -> diva.findByPdId(card.extId.toInt()).getOrNull()?.let {
// it.pdId = card.aquaUser!!.ghostCard // it.pdId = card.aquaUser!!.ghostCard
@ -129,41 +149,9 @@ class CardGameService(
} }
suspend fun getSummary(card: Card) = async { mapOf( suspend fun getSummary(card: Card) = async { mapOf(
"maimai" to maimai.findByCard_ExtId(card.extId).getOrNull()?.let { "maimai2" to getSummaryFor(maimai2, card),
mapOf( "chusan" to getSummaryFor(chusan, card),
"name" to it.userName, "ongeki" to getSummaryFor(ongeki, card),
"rating" to it.playerRating,
"lastLogin" to it.lastPlayDate,
)
},
"maimai2" to maimai2.findByCardExtId(card.extId).getOrNull()?.let {
mapOf(
"name" to it.userName,
"rating" to it.playerRating,
"lastLogin" to it.lastPlayDate,
)
},
"chusan" to chusan.findByCard_ExtId(card.extId).getOrNull()?.let {
mapOf(
"name" to it.userName,
"rating" to it.playerRating,
"lastLogin" to it.lastPlayDate,
)
},
"chunithm" to chunithm.findByCard_ExtId(card.extId).getOrNull()?.let {
mapOf(
"name" to it.userName,
"rating" to it.playerRating,
"lastLogin" to it.lastPlayDate,
)
},
"ongeki" to ongeki.findByCard_ExtId(card.extId).getOrNull()?.let {
mapOf(
"name" to it.userName,
"rating" to it.playerRating,
"lastLogin" to it.lastPlayDate,
)
},
"diva" to diva.findByPdId(card.extId.toInt()).getOrNull()?.let { "diva" to diva.findByPdId(card.extId.toInt()).getOrNull()?.let {
mapOf( mapOf(
"name" to it.playerName, "name" to it.playerName,

View File

@ -6,6 +6,7 @@ import icu.samnyan.aqua.net.games.GenericGameSummary
import icu.samnyan.aqua.net.games.RankCount import icu.samnyan.aqua.net.games.RankCount
import icu.samnyan.aqua.net.games.TrendOut import icu.samnyan.aqua.net.games.TrendOut
import icu.samnyan.aqua.sega.general.model.Card import icu.samnyan.aqua.sega.general.model.Card
import org.springframework.data.jpa.repository.JpaRepository
data class TrendLog(val date: String, val rating: Int) data class TrendLog(val date: String, val rating: Int)
@ -39,10 +40,11 @@ interface IGenericUserData {
val lastPlayDate: Any val lastPlayDate: Any
val lastRomVersion: String val lastRomVersion: String
val totalScore: Long val totalScore: Long
var card: Card?
} }
interface GenericUserDataRepo { interface GenericUserDataRepo<T : IGenericUserData, ID> : JpaRepository<T, ID> {
fun findByCard(card: Card): IGenericUserData? fun findByCard(card: Card): T?
fun getRanking(rating: Int): Long fun getRanking(rating: Int): Long
} }
@ -63,7 +65,7 @@ interface GenericPlaylogRepo {
fun genericUserSummary( fun genericUserSummary(
u: AquaNetUser, u: AquaNetUser,
userDataRepo: GenericUserDataRepo, userDataRepo: GenericUserDataRepo<*, *>,
userPlaylogRepo: GenericPlaylogRepo, userPlaylogRepo: GenericPlaylogRepo,
shownRanks: List<Pair<Int, String>>, shownRanks: List<Pair<Int, String>>,
ratingComposition: Map<String, String>, ratingComposition: Map<String, String>,

View File

@ -13,7 +13,7 @@ import java.util.Optional;
* @author samnyan (privateamusement@protonmail.com) * @author samnyan (privateamusement@protonmail.com)
*/ */
@Repository("ChusanUserDataRepository") @Repository("ChusanUserDataRepository")
public interface UserDataRepository extends JpaRepository<UserData, Long>, GenericUserDataRepo { public interface UserDataRepository extends GenericUserDataRepo<UserData, Long> {
UserData findByCard(Card card); UserData findByCard(Card card);

View File

@ -14,6 +14,7 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ -126,7 +127,7 @@ import java.util.List;
"isNetBattleHost", "isNetBattleHost",
"netBattleEndState" }) "netBattleEndState" })
public class UserData implements Serializable, IGenericUserData { public class UserData implements Serializable, IGenericUserData {
@Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Id @Id
@ -137,7 +138,7 @@ public class UserData implements Serializable, IGenericUserData {
@JsonSerialize(using = AccessCodeSerializer.class) @JsonSerialize(using = AccessCodeSerializer.class)
@JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY) @JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY)
@OneToOne @OneToOne
@JoinColumn(name = "card_id") @JoinColumn(name = "card_id", unique = true)
private Card card; private Card card;
// Access code in card // Access code in card

View File

@ -3,7 +3,6 @@ package icu.samnyan.aqua.sega.maimai2.dao.userdata
import icu.samnyan.aqua.net.utils.GenericUserDataRepo import icu.samnyan.aqua.net.utils.GenericUserDataRepo
import icu.samnyan.aqua.sega.general.model.Card import icu.samnyan.aqua.sega.general.model.Card
import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
@ -11,7 +10,7 @@ import java.util.*
@Repository("Maimai2UserDataRepository") @Repository("Maimai2UserDataRepository")
interface UserDataRepository : JpaRepository<UserDetail, Long>, GenericUserDataRepo { interface UserDataRepository : GenericUserDataRepo<UserDetail, Long> {
override fun findByCard(card: Card): UserDetail? override fun findByCard(card: Card): UserDetail?
fun findByCardExtId(userId: Long): Optional<UserDetail> fun findByCardExtId(userId: Long): Optional<UserDetail>

View File

@ -26,8 +26,8 @@ class UserDetail(
@JsonSerialize(using = AccessCodeSerializer::class) @JsonSerialize(using = AccessCodeSerializer::class)
@JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY) @JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY)
@OneToOne @OneToOne
@JoinColumn(name = "aime_card_id") @JoinColumn(name = "aime_card_id", unique = true)
var card: Card? = null, override var card: Card? = null,
override var userName: String = "", override var userName: String = "",

View File

@ -13,7 +13,7 @@ import java.util.*
* @author samnyan (privateamusement@protonmail.com) * @author samnyan (privateamusement@protonmail.com)
*/ */
@Repository("OngekiUserDataRepository") @Repository("OngekiUserDataRepository")
interface UserDataRepository : JpaRepository<UserData, Long>, GenericUserDataRepo { interface UserDataRepository : GenericUserDataRepo<UserData, Long> {
fun findByCard_ExtIdIn(userIds: Collection<Long>): List<UserData> fun findByCard_ExtIdIn(userIds: Collection<Long>): List<UserData>
override fun findByCard(card: Card): UserData? override fun findByCard(card: Card): UserData?

View File

@ -33,7 +33,7 @@ public class UserData implements Serializable, IGenericUserData {
@JsonSerialize(using = AccessCodeSerializer.class) @JsonSerialize(using = AccessCodeSerializer.class)
@JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY) @JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY)
@OneToOne @OneToOne
@JoinColumn(name = "aime_card_id") @JoinColumn(name = "aime_card_id", unique = true)
private Card card; private Card card;
// Access code in card // Access code in card