[F] Wacca user/status/getDetail

pull/29/head
Azalea 2024-03-28 07:05:32 -04:00
parent bb9bfd6396
commit d6fc60e02b
5 changed files with 46 additions and 26 deletions

View File

@ -102,7 +102,10 @@ inline fun <reified T> resJson(name: Str, warn: Boolean = true) = resStr(name)?.
fun millis() = System.currentTimeMillis() fun millis() = System.currentTimeMillis()
val DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd") val DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd")
fun LocalDate.isoDate() = format(DATE_FORMAT) fun LocalDate.isoDate() = format(DATE_FORMAT)
fun String.isoDate() = DATE_FORMAT.parse(this, LocalDate::from)
fun LocalDate.toDate() = Date(atStartOfDay().toInstant(java.time.ZoneOffset.UTC).toEpochMilli())
fun LocalDateTime.isoDateTime() = format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) fun LocalDateTime.isoDateTime() = format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
fun String.isoDateTime() = LocalDateTime.parse(this, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
val URL_SAFE_DT = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss") val URL_SAFE_DT = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")
fun LocalDateTime.urlSafeStr() = format(URL_SAFE_DT) fun LocalDateTime.urlSafeStr() = format(URL_SAFE_DT)
@ -114,6 +117,7 @@ catch (e: Exception) { null } }
val Calendar.year get() = get(Calendar.YEAR) val Calendar.year get() = get(Calendar.YEAR)
val Calendar.month get() = get(Calendar.MONTH) + 1 val Calendar.month get() = get(Calendar.MONTH) + 1
val Calendar.day get() = get(Calendar.DAY_OF_MONTH) val Calendar.day get() = get(Calendar.DAY_OF_MONTH)
val Date.sec get() = time / 1000
// Encodings // Encodings
fun Long.toHex(len: Int = 16): Str = "0x${this.toString(len).padStart(len, '0').uppercase()}" fun Long.toHex(len: Int = 16): Str = "0x${this.toString(len).padStart(len, '0').uppercase()}"

View File

@ -8,6 +8,7 @@ import icu.samnyan.aqua.sega.wacca.WaccaOptionType.SET_TITLE_ID
import icu.samnyan.aqua.sega.wacca.model.BaseRequest import icu.samnyan.aqua.sega.wacca.model.BaseRequest
import icu.samnyan.aqua.sega.wacca.model.db.WaccaRepos import icu.samnyan.aqua.sega.wacca.model.db.WaccaRepos
import icu.samnyan.aqua.sega.wacca.model.db.WaccaUser import icu.samnyan.aqua.sega.wacca.model.db.WaccaUser
import icu.samnyan.aqua.sega.wacca.model.db.WcUserGate
import io.ktor.client.utils.* import io.ktor.client.utils.*
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
@ -24,6 +25,7 @@ class WaccaServer(val rp: WaccaRepos, val cardRepo: CardRepository) {
val log = logger() val log = logger()
val season = 3 val season = 3
val enabledGates = 1..24
init { init() } init { init() }
@ -145,13 +147,19 @@ fun WaccaServer.init() {
val scores = rp.bestScore.findByUser(u) val scores = rp.bestScore.findByUser(u)
val gates = rp.gate.findByUser(u) val gates = rp.gate.findByUser(u)
val bingo = rp.bingo.findByUser(u).firstOrNull() val bingo = rp.bingo.findByUser(u).firstOrNull()
val go = u.card.aquaUser?.gameOptions
// TODO: make this and vip configurable
u.wp = 999999
u.run { ls("status" - lStatus(), u.run { ls("status" - lStatus(),
"options" - o.map { (k, v) -> ls(k, v) }, "options" - o.map { (k, v) -> ls(k, v) },
"seasonalPlayModeCounts" - (ls(playcountSingle, playcountMultiVs, playcountMultiCoop, playcountStageup, playcountTimeFree) "seasonalPlayModeCounts" - (ls(playcountSingle, playcountMultiVs, playcountMultiCoop, playcountStageup, playcountTimeFree)
.mapIndexed { i, it -> ls(season, i + 1, it) } + ls(0, 1, 1)), .mapIndexed { i, it -> ls(season, i + 1, it) } + ls(ls(0, 1, 1))),
"items" - ls(MUSIC_UNLOCK, TITLE, ICON, TROPHY, SKILL, TICKET, NOTE_COLOR, NOTE_SOUND, NAVIGATOR, USER_PLATE, TOUCH_EFFECT) "items" - ls(MUSIC_UNLOCK, TITLE, ICON, TROPHY, SKILL, TICKET, NOTE_COLOR, NOTE_SOUND, NAVIGATOR, USER_PLATE, TOUCH_EFFECT).map {
.map { items[it()]?.map { it.ls() } }, if (it == TICKET && go?.unlockTickets == true) (0..4).map { ls(it, 106002, 0) }
else items[it()]?.map { it.ls() } ?: empty
},
"scores" - scores.map { it.ls() }, "scores" - scores.map { it.ls() },
"songPlayStatus" - ls(lastSongId, 1), "songPlayStatus" - ls(lastSongId, 1),
"seasonInfo" - ls(xp, wpTotal, wpSpent, scores.sumOf { it.score }, "seasonInfo" - ls(xp, wpTotal, wpSpent, scores.sumOf { it.score },
@ -163,9 +171,11 @@ fun WaccaServer.init() {
"favorites" - rp.favoriteSong.findByUser(u).map { it.songId }, "favorites" - rp.favoriteSong.findByUser(u).map { it.songId },
"stoppedSongIds" - empty, "stoppedSongIds" - empty,
"events" - empty, "events" - empty,
"gate" - gates.map { it.ls() }, "gate" - gates.associateBy { it.gateId }.let { gateMap -> enabledGates.map {
gateMap[it]?.ls() ?: WcUserGate().apply { gateId = it }.ls()
} },
"lastSongInfo" - ls(lastSongId, lastSongDifficulty, lastFolderOrder, lastFolderId, lastSongOrder), "lastSongInfo" - ls(lastSongId, lastSongDifficulty, lastFolderOrder, lastFolderId, lastSongOrder),
"gateTutorialFlags" - (gateTutorialFlags ?: "[]").jsonArray().map { it as Array<*> }.map { ls(it[0], it[1]?.long()) }, "gateTutorialFlags" - gateTutorialFlags.jsonArray(),
"gatchaInfo" - empty, "gatchaInfo" - empty,
"friendList" - empty, "friendList" - empty,
"bingoStatus" - ls( "bingoStatus" - ls(

View File

@ -1,6 +1,9 @@
package icu.samnyan.aqua.sega.wacca.model.db package icu.samnyan.aqua.sega.wacca.model.db
import ext.isoDate
import ext.ls import ext.ls
import ext.sec
import ext.toDate
import icu.samnyan.aqua.net.games.BaseEntity import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.sega.general.model.Card import icu.samnyan.aqua.sega.general.model.Card
import jakarta.persistence.* import jakarta.persistence.*
@ -29,7 +32,7 @@ class WaccaUser : BaseEntity() {
var title2 = 0 var title2 = 0
var rating = 0 var rating = 0
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
var vipExpireTime: Date = Date(0) var vipExpireTime: Date = "2077-01-01".isoDate().toDate()
var alwaysVip = false var alwaysVip = false
var loginCount = 0 var loginCount = 0
var loginCountConsec = 0 var loginCountConsec = 0
@ -52,9 +55,9 @@ class WaccaUser : BaseEntity() {
var lastFolderId = 0 var lastFolderId = 0
var lastSongOrder = 0 var lastSongOrder = 0
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
var lastLoginDate: Date = Date(0) var lastLoginDate: Date = Date()
var gateTutorialFlags: String? = null var gateTutorialFlags: String = "[[1, 0], [2, 0], [3, 0], [4, 0], [5, 0]]"
fun lStatus() = ls(card.extId, username, 1, xp, danLevel, danType, wp, ls(0, 0, 0), loginCount, loginCountDays, fun lStatus() = ls(card.extId, username, 1, xp, danLevel, danType, wp, ls(0, 0, 0), loginCount, loginCountDays,
loginCountConsec, loginCountDaysConsec, vipExpireTime, loginCountToday, rating) loginCountConsec, loginCountDaysConsec, vipExpireTime.sec, loginCountToday, rating)
} }

View File

@ -2,6 +2,7 @@ package icu.samnyan.aqua.sega.wacca.model.db
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import ext.ls import ext.ls
import ext.sec
import icu.samnyan.aqua.net.games.BaseEntity import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.sega.wacca.WaccaItemType import icu.samnyan.aqua.sega.wacca.WaccaItemType
import icu.samnyan.aqua.sega.wacca.WaccaItemType.* import icu.samnyan.aqua.sega.wacca.WaccaItemType.*
@ -55,7 +56,7 @@ class WcUserFavoriteSong : WaccaUserEntity() {
@Entity @Table(name = "wacca_user_gate", uniqueConstraints = [UC("", ["user_id", "gate_id"])]) @Entity @Table(name = "wacca_user_gate", uniqueConstraints = [UC("", ["user_id", "gate_id"])])
class WcUserGate : WaccaUserEntity() { class WcUserGate : WaccaUserEntity() {
var gateId = 0 var gateId = 0
var page = 0 var page = 1
var progress = 0 var progress = 0
var loops = 0 var loops = 0
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
@ -63,7 +64,7 @@ class WcUserGate : WaccaUserEntity() {
var missionFlag = 0 var missionFlag = 0
var totalPoints = 0 var totalPoints = 0
fun ls() = ls(gateId, page, progress, loops, lastUsed, missionFlag) fun ls() = ls(gateId, 1, page, progress, loops, lastUsed, missionFlag)
} }
@Entity @Table(name = "wacca_user_item", uniqueConstraints = [UC("", ["user_id", "item_id", "type"])]) @Entity @Table(name = "wacca_user_item", uniqueConstraints = [UC("", ["user_id", "item_id", "type"])])
@ -80,15 +81,15 @@ class WcUserItem(
var acquiredDate: Date = Date(), var acquiredDate: Date = Date(),
) : WaccaUserEntity() { ) : WaccaUserEntity() {
fun ls() = when (type) { fun ls() = when (type) {
MUSIC_UNLOCK() -> ls(itemId, p1, acquiredDate, acquiredDate) // songId, diff, acquireDate, unlockDate MUSIC_UNLOCK() -> ls(itemId, p1, acquiredDate.sec, acquiredDate.sec) // songId, diff, acquireDate, unlockDate
ICON() -> ls(itemId, type, p1, acquiredDate) // id, type, uses, acquiredDate ICON() -> ls(itemId, 1, p1, acquiredDate.sec) // id, type, uses, acquiredDate
TROPHY() -> ls(itemId, p1, p2, p3) // id, season, progress, badgeType TROPHY() -> ls(itemId, p1, p2, p3) // id, season, progress, badgeType
SKILL() -> ls(itemId, p1, p2, p3) // skillType, level, flag, badge SKILL() -> ls(itemId, p1, p2, p3) // skillType, level, flag, badge
TICKET() -> ls(id, itemId, p1) // userTicketId, ticketId, expire TICKET() -> ls(id, itemId, p1) // userTicketId, ticketId, expire
NAVIGATOR() -> ls(itemId, type, acquiredDate, p1, p2) // id, type, acquiredDate, uses, usesToday NAVIGATOR() -> ls(itemId, 1, acquiredDate.sec, p1, p2) // id, type, acquiredDate, uses, usesToday
// Generic: title, note colors, note sounds, plates, touch effects // Generic: title, note colors, note sounds, plates, touch effects
else -> ls(itemId, type, acquiredDate) // id, type, acquireDate else -> ls(itemId, 1, acquiredDate.sec) // id, type, acquireDate
} }
infix fun isType(t: WaccaItemType) = type == t() infix fun isType(t: WaccaItemType) = type == t()

View File

@ -29,19 +29,16 @@ class WaccaTest : StringSpec({
} }
infix fun List<Any?>.exp(expected: List<Any?>) { infix fun List<Any?>.exp(expected: List<Any?>) {
expected.size shouldBe size // Replace all timestamps as null
for (i in indices) { val start = millis().toString().substring(0..3)
val a = this[i] val lst = this.toJson().replace(Regex("""$start\d{6}(?=[], ])"""), "null").jsonArray()
when (val b = expected[i]) { lst shouldBe expected
null -> {} // Use null to ignore the value
is List<*> -> a as List<Any> exp b as List<Any>
else -> a shouldBe b
}
}
} }
infix fun List<Any?>.exp(json: String) = exp(json.jsonArray()) infix fun List<Any?>.exp(json: String) = exp(json.jsonArray())
System.getProperty("kotest.assertions.collection.print.size", "1000")
beforeTest { beforeTest {
if (uid == 0L) uid = registerUser() if (uid == 0L) uid = registerUser()
} }
@ -62,12 +59,12 @@ class WaccaTest : StringSpec({
"user/status/get #1" { "user/status/get #1" {
post("user/status/get", """["$uid"]""").res exp post("user/status/get", """["$uid"]""").res exp
"""[[0, "", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 0, 0, 0], 104001, 102001, 1, [2, "1.0.0"], []]""" """[[0, "", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 3376684800, 0, 0], 104001, 102001, 1, [2, "1.0.0"], []]"""
} }
"user/status/create #1" { "user/status/create #1" {
post("user/status/create", """["$uid", "AZA"]""").res exp post("user/status/create", """["$uid", "AZA"]""").res exp
"""[[$uid, "AZA", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 0, 0, 0]]""" """[[$uid, "AZA", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 3376684800, 0, 0]]"""
} }
"user/status/login Guest" { "user/status/login Guest" {
@ -79,4 +76,9 @@ class WaccaTest : StringSpec({
post("user/status/login", "[$uid]").res exp post("user/status/login", "[$uid]").res exp
"[[], [], [], 0, [2077, 1, 1, 1, [], []], null, []]" "[[], [], [], 0, [2077, 1, 1, 1, [], []], null, []]"
} }
"user/status/getDetail #1" {
post("user/status/getDetail", "[$uid]").res exp
"""[[$uid, "AZA", 1, 0, 0, 0, 999999, [0, 0, 0], 1, 0, 0, 0, 3376684800, 1, 0], [], [[3, 1, 0], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0], [0, 1, 1]], [[], [[104001, 1, null], [104002, 1, null], [104003, 1, null], [104005, 1, null]], [[102001, 1, 0, null], [102002, 1, 0, null]], [], [], [], [[103001, 1, null], [203001, 1, null]], [[105001, 1, null], [205005, 1, null]], [[210001, 1, null, 0, 0], [210002, 1, null, 0, 0], [210054, 1, null, 0, 0], [210055, 1, null, 0, 0], [210056, 1, null, 0, 0], [210057, 1, null, 0, 0], [210058, 1, null, 0, 0], [210059, 1, null, 0, 0], [210060, 1, null, 0, 0], [210061, 1, null, 0, 0], [310001, 1, null, 0, 0], [310002, 1, null, 0, 0]], [[211001, 1, null]], [[312000, 1, null], [312001, 1, null]]], [], [0, 1], [0, 0, 0, 0, 4, 2, 0, 2, 2, 1, 0], [[0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0]], null, [], [], [], [[1, 1, 1, 0, 0, 0, 0], [2, 1, 1, 0, 0, 0, 0], [3, 1, 1, 0, 0, 0, 0], [4, 1, 1, 0, 0, 0, 0], [5, 1, 1, 0, 0, 0, 0], [6, 1, 1, 0, 0, 0, 0], [7, 1, 1, 0, 0, 0, 0], [8, 1, 1, 0, 0, 0, 0], [9, 1, 1, 0, 0, 0, 0], [10, 1, 1, 0, 0, 0, 0], [11, 1, 1, 0, 0, 0, 0], [12, 1, 1, 0, 0, 0, 0], [13, 1, 1, 0, 0, 0, 0], [14, 1, 1, 0, 0, 0, 0], [15, 1, 1, 0, 0, 0, 0], [16, 1, 1, 0, 0, 0, 0], [17, 1, 1, 0, 0, 0, 0], [18, 1, 1, 0, 0, 0, 0], [19, 1, 1, 0, 0, 0, 0], [20, 1, 1, 0, 0, 0, 0], [21, 1, 1, 0, 0, 0, 0], [22, 1, 1, 0, 0, 0, 0], [23, 1, 1, 0, 0, 0, 0], [24, 1, 1, 0, 0, 0, 0]], [0, 0, 0, 0, 0], [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0]], [], [], [0, []]]"""
}
}) })