feat: no longer stub maimai magical

This commit is contained in:
asterisk727
2026-09-25 12:49:14 -05:00
parent 55b47a3c02
commit c1d3f61b00
11 changed files with 200 additions and 5 deletions
@@ -7,6 +7,11 @@ import icu.samnyan.aqua.sega.general.model.CardStatus
import icu.samnyan.aqua.sega.maimai2.model.UserRivalMusic
import icu.samnyan.aqua.sega.maimai2.model.UserRivalMusicDetail
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserKaleidx
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2ItemKind
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserItem
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserPass
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserTicketLimitDate
import icu.samnyan.aqua.sega.maimai2.model.userdata.MAIMAI_DATETIME
import icu.samnyan.aqua.sega.maimai2.model.userdata.UserRegions
import java.time.LocalDate
import kotlin.random.Random
@@ -55,7 +60,81 @@ fun Maimai2ServletController.initApis() {
// Maimai only request for event type 1
"GetGameEvent" static { mapOf("type" to 1, "gameEventList" to db.gameEvent.findAll()) }
"GetGameCharge" static { db.gameCharge.findAll().let { mapOf("length" to it.size, "gameChargeList" to it) } }
"GetGameCharge" static {
db.gameCharge.findAll().let {
mapOf(
"length" to it.size,
"gameChargeList" to it,
"gamePassChargeList" to db.gamePassCharge.findAll()
)
}
}
"GetGameSellingPassPack" static {
mapOf("gameSellingPassPackList" to db.gameSellingPassPack.findAll())
}
"GetUserPass" {
db.userData.findByCardExtId(uid) ?: (404 - "User not found")
mapOf("userId" to uid, "userPassList" to db.userPass.findByUser_Card_ExtId(uid))
}
"GetUserTicketLimitDate" {
db.userData.findByCardExtId(uid) ?: (404 - "User not found")
mapOf("userTicketLimitDateList" to db.userTicketLimitDate.findByUser_Card_ExtId(uid))
}
"UserPassModeEnter" static { mapOf("returnCode" to 1) }
"UserPassModeExit" static { mapOf("returnCode" to 1) }
"UpsertUserPassMode" {
val user = db.userData.findByCardExtId(uid) ?: (404 - "User not found")
val pass = (data["userPassList"] as List<*>).first() as Map<*, *>
val passTypeId = (pass["passTypeId"] as Number).toInt()
val passPackId = (pass["passPackId"] as Number).toInt()
val passCharaId = (pass["passCharaId"] as Number).toInt()
val now = jstNow()
val startDate = now.format(MAIMAI_DATETIME)
val endDate = now.plusDays(14).format(MAIMAI_DATETIME)
// store the new pass
val storedPass = (db.userPass.findByUserAndPassTypeId(user, passTypeId) ?: Mai2UserPass()).apply {
this.user = user
this.passTypeId = passTypeId
this.passPackId = passPackId
this.passCharaId = passCharaId
this.startDate = startDate
this.endDate = endDate
}
db.userPass.save(storedPass)
// attempt to give user ticket 40001 (+1 track ticket) up to a max of 10
val ticketId = 40001
val ticket = (db.userItem.findByUserAndItemKindAndItemId(user, Mai2ItemKind.ticket.id, ticketId)
?: Mai2UserItem().apply {
this.user = user
itemKind = Mai2ItemKind.ticket.id
itemId = ticketId
}).apply {
stock = (stock + 1).coerceAtMost(10)
isValid = true
}
db.userItem.save(ticket)
// set expiry date for newly granted ticket
val limit = (db.userTicketLimitDate.findByUserAndItemId(user, ticketId)
?: Mai2UserTicketLimitDate().apply { this.user = user; itemId = ticketId }).apply {
limitDate = endDate
}
db.userTicketLimitDate.save(limit)
mapOf(
"returnCode" to 1,
"userPassList" to db.userPass.findByUser_Card_ExtId(uid),
"userItemList" to listOf(ticket),
"userTicketLimitDateList" to db.userTicketLimitDate.findByUser_Card_ExtId(uid)
)
}
"GetUserOption" { mapOf(
"userId" to uid,
@@ -383,14 +462,19 @@ fun Maimai2ServletController.initApis() {
"aggrDate" to ""
) }
"GetUserCircleData" static { mapOf(
"GetUserCircleData" {
mapOf(
"userId" to uid,
"circleId" to 0,
"circleName" to "一緒に歌おう!",
"isPlace" to false,
"circleClass" to 0,
"lastLoginDate" to "",
"mapBonusId" to 0,
"lastMapBonusDate" to (db.userData.findByCardExtId(uid)?.lastMapBonusDate ?: ""),
"circlePointRankingList" to empty
) }
)
}
"GetUserCircleChallenge" { mapOf(
"userId" to uid,
@@ -75,7 +75,7 @@ class UpsertUserAllHandler(
listOfNotNull(
userExtend, userOption, userCharacterList, userMapList, userLoginBonusList, userItemList,
userMusicDetailList, userCourseList, userFriendSeasonRankingList, userFavoriteList,
userKaleidxScopeList, userIntimateList, upsertUserAll.userPlaylogList
userKaleidxScopeList, userIntimateList, userTicketLimitDateList, upsertUserAll.userPlaylogList
)
}.flatten().forEach { it.user = u }
@@ -142,6 +142,17 @@ class UpsertUserAllHandler(
repos.userIntimate.saveAll(lst.mapApply {
id = repos.userIntimate.findByUserAndPartnerId(u, partnerId)?.id ?: 0 }) }
req.userTicketLimitDateList?.unique { it.itemId }?.let { lst ->
repos.userTicketLimitDate.saveAll(lst.mapApply {
id = repos.userTicketLimitDate.findByUserAndItemId(u, itemId)?.id ?: 0
})
}
req.userCircleData?.lastMapBonusDate?.let {
u.lastMapBonusDate = it
repos.userData.save(u)
}
// Added on SDGA 1.65 / SDGB 1.53
upsertUserAll.userPlaylogList?.let(repos.userPlaylog::saveAll)
@@ -20,6 +20,22 @@ class Mai2GameCharge {
var endDate: String? = "2029-01-01 00:00:00.000000"
}
class Mai2GamePassCharge {
var orderId: Long = 0
var passTypeId = 0
var price = 0
var startDate: String? = "2019-01-01 00:00:00.000000"
var endDate: String? = "2099-01-01 00:00:00.000000"
}
class Mai2GameSellingPassPack {
var passPackId = 0
var startDate: String? = "2019-01-01 00:00:00.000000"
var endDate: String? = "2099-01-01 00:00:00.000000"
var noticeStartDate: String? = "2019-01-01 00:00:00.000000"
var noticeEndDate: String? = "2099-01-01 00:00:00.000000"
}
class Mai2GameSellingCard {
var cardId = 0L
var startDate: String? = "2019-01-01 00:00:00.000000"
@@ -42,6 +42,14 @@ interface Mai2UserCharacterRepo : Mai2UserLinked<Mai2UserCharacter> {
interface Mai2UserChargeRepo : Mai2UserLinked<Mai2UserCharge>
interface Mai2UserPassRepo : Mai2UserLinked<Mai2UserPass> {
fun findByUserAndPassTypeId(user: Mai2UserDetail, passTypeId: Int): Mai2UserPass?
}
interface Mai2UserTicketLimitDateRepo : Mai2UserLinked<Mai2UserTicketLimitDate> {
fun findByUserAndItemId(user: Mai2UserDetail, itemId: Int): Mai2UserTicketLimitDate?
}
interface Mai2UserCourseRepo : Mai2UserLinked<Mai2UserCourse> {
fun findByUserAndCourseId(user: Mai2UserDetail, courseId: Int): Mai2UserCourse?
}
@@ -130,6 +138,8 @@ class Mai2Repos(
val userCard: Mai2UserCardRepo,
val userCharacter: Mai2UserCharacterRepo,
val userCharge: Mai2UserChargeRepo,
val userPass: Mai2UserPassRepo,
val userTicketLimitDate: Mai2UserTicketLimitDateRepo,
val userCourse: Mai2UserCourseRepo,
val userData: Mai2UserDataRepo,
val userExtend: Mai2UserExtendRepo,
@@ -150,6 +160,8 @@ class Mai2Repos(
val gameData: GameDataService
) {
val gameCharge = StaticRepo(gameData.mai2Charges) { it.orderId }
val gamePassCharge = StaticRepo(gameData.mai2PassCharges) { it.passTypeId.toLong() }
val gameSellingPassPack = StaticRepo(gameData.mai2SellingPassPacks) { it.passPackId.toLong() }
val gameEvent = StaticRepo(gameData.mai2Events) { it.id }
val gameSellingCard = StaticRepo(gameData.mai2SellingCards) { it.cardId }
}
@@ -30,6 +30,8 @@ class Mai2UserAll {
var userFavoritemusicList: List<Mai2UserFavoriteItem>? = null
var userKaleidxScopeList: List<Mai2UserKaleidx>? = null
var userIntimateList: List<Mai2UserIntimate>? = null
var userTicketLimitDateList: List<Mai2UserTicketLimitDate>? = null
var userCircleData: Mai2UserCircleData? = null
var isNewCharacterList: String? = null
var isNewMapList: String? = null
var isNewLoginBonusList: String? = null
@@ -42,6 +44,11 @@ class Mai2UserAll {
var isNewKaleidxScopeList: String? = null
}
class Mai2UserCircleData {
var lastLoginDate: String = ""
var lastMapBonusDate: String = ""
}
class Mai2UserFavoriteItem {
var orderId = 0
var id = 0
@@ -52,4 +59,3 @@ class Mai2UserActivity {
var musicList: List<Mai2UserAct> = emptyList()
}
@@ -87,6 +87,7 @@ class Mai2UserDetail(
var dailyCourseBonusDate: String = "",
var lastPairLoginDate: String = "",
var lastTrialPlayDate: String = "",
var lastMapBonusDate: String = "",
var playVsCount: Int = 0,
var playSyncCount: Int = 0,
var winCount: Int = 0,
@@ -111,6 +111,25 @@ class Mai2UserCharge : Mai2UserEntity() {
var validDate: String = ""
}
@Table(name = "maimai2_user_pass", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "pass_type_id"])])
@Entity
class Mai2UserPass : Mai2UserEntity() {
var passTypeId = 0
var passPackId = 0
var passCharaId = 0
var mapId = 0
var startDate: String = ""
var endDate: String = ""
}
@Table(name = "maimai2_user_ticket_limit_date", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "item_id"])])
@Entity
class Mai2UserTicketLimitDate : Mai2UserEntity() {
var itemId = 0
var limitDate: String = ""
var lastUsedDate: String = ""
}
@Table(name = "maimai2_user_course")
@Entity
class Mai2UserCourse : Mai2UserEntity() {
@@ -13,6 +13,8 @@ import icu.samnyan.aqua.sega.chusan.model.GameLoginBonus as Chu3GameLoginBonus
import icu.samnyan.aqua.sega.chusan.model.GameLoginBonusPreset as Chu3GameLoginBonusPreset
import icu.samnyan.aqua.sega.maimai2.model.Mai2GameCharge
import icu.samnyan.aqua.sega.maimai2.model.Mai2GameEvent
import icu.samnyan.aqua.sega.maimai2.model.Mai2GamePassCharge
import icu.samnyan.aqua.sega.maimai2.model.Mai2GameSellingPassPack
import icu.samnyan.aqua.sega.maimai2.model.Mai2GameSellingCard
import icu.samnyan.aqua.sega.ongeki.model.GameCard as OgkGameCard
import icu.samnyan.aqua.sega.ongeki.model.GameChara as OgkGameChara
@@ -55,6 +57,8 @@ class GameDataService() {
// maimai2
lateinit var mai2Events: List<Mai2GameEvent>
lateinit var mai2Charges: List<Mai2GameCharge>
lateinit var mai2PassCharges: List<Mai2GamePassCharge>
lateinit var mai2SellingPassPacks: List<Mai2GameSellingPassPack>
lateinit var mai2SellingCards: List<Mai2GameSellingCard>
lateinit var mai2GameEncryption: List<GameEncryptionKey>
@@ -88,6 +92,8 @@ class GameDataService() {
fun load() {
mai2Events = load("maimai2", "game_event.json")
mai2Charges = load("maimai2", "game_charge.json")
mai2PassCharges = load("maimai2", "game_pass_charge.json")
mai2SellingPassPacks = load("maimai2", "game_selling_pass_pack.json")
mai2SellingCards = load("maimai2", "game_selling_card.json")
mai2GameEncryption = load(game = "maimai2", file = "game_encryption.json")
@@ -0,0 +1,4 @@
[
{"orderId": 0, "passTypeId": 2, "price": 2, "startDate": "2026-09-17 00:00:00.000000", "endDate": "2099-01-01 00:00:00.000000"},
{"orderId": 0, "passTypeId": 3, "price": 3, "startDate": "2026-09-17 00:00:00.000000", "endDate": "2099-01-01 00:00:00.000000"}
]
@@ -0,0 +1,5 @@
[
{"passPackId": 7001, "startDate": "2026-09-17 00:00:00.000000", "endDate": "2026-11-06 00:00:00.000000", "noticeStartDate": "2026-09-03 00:00:00.000000", "noticeEndDate": "2026-11-06 00:00:00.000000"},
{"passPackId": 7002, "startDate": "2026-11-06 00:00:00.000000", "endDate": "2027-01-08 00:00:00.000000", "noticeStartDate": "2026-10-23 00:00:00.000000", "noticeEndDate": "2027-01-08 00:00:00.000000"},
{"passPackId": 7003, "startDate": "2027-01-08 00:00:00.000000", "endDate": "2099-01-01 00:00:00.000000", "noticeStartDate": "2026-12-25 00:00:00.000000", "noticeEndDate": "2099-01-01 00:00:00.000000"}
]
@@ -0,0 +1,31 @@
ALTER TABLE maimai2_user_detail
ADD COLUMN last_map_bonus_date VARCHAR(64) NOT NULL DEFAULT '';
CREATE TABLE maimai2_user_pass
(
id BIGINT AUTO_INCREMENT NOT NULL,
user_id BIGINT NOT NULL,
pass_type_id INT NOT NULL,
pass_pack_id INT NOT NULL,
pass_chara_id INT NOT NULL,
map_id INT NOT NULL DEFAULT 0,
start_date VARCHAR(64) NOT NULL DEFAULT '',
end_date VARCHAR(64) NOT NULL DEFAULT '',
CONSTRAINT pk_maimai2_user_pass PRIMARY KEY (id),
CONSTRAINT uc_maimai2_user_pass_type UNIQUE (user_id, pass_type_id),
CONSTRAINT fk_maimai2_user_pass_user FOREIGN KEY (user_id)
REFERENCES maimai2_user_detail (id) ON DELETE CASCADE
);
CREATE TABLE maimai2_user_ticket_limit_date
(
id BIGINT AUTO_INCREMENT NOT NULL,
user_id BIGINT NOT NULL,
item_id INT NOT NULL,
limit_date VARCHAR(64) NOT NULL DEFAULT '',
last_used_date VARCHAR(64) NOT NULL DEFAULT '',
CONSTRAINT pk_maimai2_user_ticket_limit_date PRIMARY KEY (id),
CONSTRAINT uc_maimai2_user_ticket_limit_date_item UNIQUE (user_id, item_id),
CONSTRAINT fk_maimai2_user_ticket_limit_date_user FOREIGN KEY (user_id)
REFERENCES maimai2_user_detail (id) ON DELETE CASCADE
);