[M] Move common models to shared

This commit is contained in:
Azalea
2026-03-29 13:08:12 -04:00
parent 3dbb0095bf
commit 0985f73753
104 changed files with 844 additions and 842 deletions
+23
View File
@@ -2,6 +2,8 @@ plugins {
kotlin("jvm")
kotlin("plugin.jpa")
kotlin("plugin.serialization")
kotlin("kapt")
id("org.hibernate.orm") version "6.4.4.Final"
}
dependencies {
@@ -11,9 +13,30 @@ dependencies {
api("com.fasterxml.jackson.core:jackson-databind:2.17.0")
api("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.0")
// QueryDSL
implementation("io.github.openfeign.querydsl:querydsl-jpa:6.10.1")
kapt("io.github.openfeign.querydsl:querydsl-apt:6.10.1:jpa")
// Core libraries
api("org.slf4j:slf4j-api:2.0.12")
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
api("org.jetbrains.kotlin:kotlin-reflect:2.1.10")
// Hibernate enhancement requires the core library in shared as well
implementation("org.hibernate.orm:hibernate-core:6.4.4.Final")
}
hibernate {
enhancement {
enableLazyInitialization = true
enableAssociationManagement = false
enableExtendedEnhancement = false
}
}
sourceSets {
main {
java.srcDir("${layout.buildDirectory.get()}/generated/source/kapt/main")
}
}
@@ -0,0 +1,18 @@
package icu.samnyan.aqua.net
import jakarta.persistence.*
import java.io.Serializable
@Entity
@Table(name = "aqua_net_safety")
class Safety(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
@Column(nullable = false, unique = true, length = 64)
var safetyId: String = "",
@Column(nullable = false)
var status: Int = 0
) : Serializable
@@ -0,0 +1,23 @@
package icu.samnyan.aqua.net.db
import jakarta.persistence.*
import java.io.Serializable
import java.time.Instant
@Entity
@Table(name = "aqua_net_email_confirmation")
class EmailConfirmation(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
@ManyToOne
@JoinColumn(name = "auId")
var aquaNetUser: AquaNetUser = AquaNetUser(),
@Column(nullable = false, unique = true)
var token: String = "",
@Column(nullable = false)
var createdAt: Instant = Instant.now()
) : Serializable
@@ -0,0 +1,23 @@
package icu.samnyan.aqua.net.db
import jakarta.persistence.*
import java.io.Serializable
import java.time.Instant
@Entity
@Table(name = "aqua_net_email_reset_password")
class ResetPassword(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
@ManyToOne
@JoinColumn(name = "auId")
var aquaNetUser: AquaNetUser = AquaNetUser(),
@Column(nullable = false, unique = true)
var token: String = "",
@Column(nullable = false)
var createdAt: Instant = Instant.now()
) : Serializable
@@ -0,0 +1,75 @@
package icu.samnyan.aqua.net.db
import com.fasterxml.jackson.annotation.JsonIgnore
import ext.SettingField
import jakarta.persistence.*
import java.io.Serializable
@Entity
@Table(name = "aqua_net_game_options")
class AquaGameOptions(
@Id @JsonIgnore
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
@SettingField("mai2") @Column(name = "mai2_unlock_music")
var mai2UnlockMusic: Boolean = false,
@SettingField("mai2") @Column(name = "mai2_unlock_chara")
var mai2UnlockChara: Boolean = false,
@SettingField("mai2") @Column(name = "mai2_unlock_chara_max_level")
var mai2UnlockCharaMaxLevel: Boolean = false,
@SettingField("mai2") @Column(name = "mai2_unlock_partners")
var mai2UnlockPartners: Boolean = false,
@SettingField("mai2") @Column(name = "mai2_unlock_collectables")
var mai2UnlockCollectables: Boolean = false,
@SettingField("mai2") @Column(name = "mai2_unlock_tickets")
var mai2UnlockTickets: Boolean = false,
@SettingField("wacca")
var waccaUnlockMusic: Boolean = false,
@SettingField("wacca")
var waccaUnlockPlates: Boolean = false,
@SettingField("wacca")
var waccaUnlockCollectables: Boolean = false,
@SettingField("wacca")
var waccaUnlockTickets: Boolean = false,
@SettingField("wacca")
var waccaInfiniteWp: Boolean = false,
@SettingField("wacca")
var waccaAlwaysVip: Boolean = false,
@SettingField("chu3")
var chusanTeamName: String = "",
@SettingField("chu3")
var chusanInfinitePenguins: Boolean = false,
@SettingField("chu3-matching")
var chusanMatchingServer: String = "",
@SettingField("chu3-matching")
var chusanMatchingReflector: String = "",
@SettingField("chu3-linked-verse")
var chusanLvUnlockAll: Boolean = false,
@SettingField("chu3-linked-verse")
var chusanLvDifficulty: Int = 1,
@SettingField("chu3-matching-chat")
var chusanSymbolChat1: Int? = null,
@SettingField("chu3-matching-chat")
var chusanSymbolChat2: Int? = null,
@SettingField("chu3-matching-chat")
var chusanSymbolChat3: Int? = null,
@SettingField("chu3-matching-chat")
var chusanSymbolChat4: Int? = null,
@SettingField("mai2")
var enableMusicRank: Boolean = true,
@SettingField("ongeki")
var ongekiInfiniteKaika: Boolean = false,
@SettingField("profile")
var countryOverride: String = "",
) : Serializable
@@ -0,0 +1,24 @@
package icu.samnyan.aqua.net.db
import jakarta.persistence.*
import java.io.Serializable
import java.time.Instant
import java.util.*
fun getTokenExpiry() = Instant.now().plusSeconds(7 * 86400)
@Entity
@Table(name = "aqua_net_session")
class SessionToken(
@Id
@Column(nullable = false)
var token: String = UUID.randomUUID().toString(),
// Token creation time
@Column(nullable = false)
var expiry: Instant = getTokenExpiry(),
@ManyToOne
@JoinColumn(name = "auId", referencedColumnName = "auId")
var aquaNetUser: AquaNetUser = AquaNetUser()
) : Serializable
@@ -0,0 +1,94 @@
package icu.samnyan.aqua.net.db
import com.fasterxml.jackson.annotation.JsonIgnore
import ext.*
import icu.samnyan.aqua.sega.allnet.KeychipSession
import icu.samnyan.aqua.sega.general.model.Card
import jakarta.persistence.*
import java.io.Serializable
import kotlin.reflect.KFunction
import kotlin.reflect.KMutableProperty
@Entity
class AquaNetUser(
@JsonIgnore
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var auId: Long = 0,
@Column(nullable = false, unique = true, length = 32)
var username: String = "",
// Login credentials
@Column(nullable = false, unique = true)
var email: String = "",
@JsonIgnore
@Column(nullable = false)
var pwHash: String = "",
@Column(nullable = true, length = 32)
var displayName: String = "",
// Country code at most 3 characters
@Column(length = 3)
var country: String = "",
// Region code at most 2 characters
@Column(length = 2)
var region: String = "",
// Last login time
var lastLogin: Long = 0L,
// Registration time
var regTime: Long = 0L,
// Profile fields
var profileLocation: String? = "",
var profileBio: String? = "",
var profilePicture: String? = "",
var optOutOfLeaderboard: Boolean = false,
// Email confirmation
var emailConfirmed: Boolean = false,
@OneToOne(cascade = [CascadeType.ALL])
@JoinColumn(name = "ghostCard", unique = true, nullable = false)
var ghostCard: Card = Card(),
// One user can have multiple cards
@OneToMany(mappedBy = "aquaUser", cascade = [CascadeType.ALL])
var cards: MutableList<Card> = mutableListOf(),
// Each user can have one keychip (if the user owns a cabinet)
@JsonIgnore
@Column(nullable = true, length = 32, unique = true)
var keychip: Str? = null,
// Each user's keychip can have multiple sessions
@JsonIgnore
@OneToMany(mappedBy = "user", cascade = [CascadeType.ALL])
var keychipSessions: MutableList<KeychipSession> = mutableListOf(),
@OneToOne(cascade = [CascadeType.ALL])
@JoinColumn(name = "gameOptions", unique = true, nullable = true)
var gameOptions: AquaGameOptions? = null,
) : Serializable {
val computedName get() = displayName.ifEmpty { username }
val publicFields get() = mapOf(
"username" to username,
"displayName" to displayName,
"country" to country,
"regTime" to regTime,
"profileLocation" to profileLocation,
"profileBio" to profileBio,
"profilePicture" to profilePicture,
)
}
data class SettingField(
val name: Str,
val checker: KFunction<*>,
val setter: KMutableProperty.Setter<*>,
)
@@ -0,0 +1,123 @@
package icu.samnyan.aqua.net.games
import com.fasterxml.jackson.annotation.JsonIgnore
import ext.JACKSON
import ext.JavaSerializable
import icu.samnyan.aqua.sega.general.model.Card
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.MappedSuperclass
import kotlinx.serialization.Serializable
data class TrendOut(val date: String, val rating: Int, val plays: Int)
data class RankCount(val name: String, val count: Int)
data class GenericGameSummary(
val name: String,
val aquaUser: Map<String, Any?>?,
val serverRank: Long,
val accuracy: Double,
val rating: Int,
val ratingHighest: Int,
val ranks: List<RankCount>,
val detailedRanks: Map<Int, Map<String, Int>>,
val maxCombo: Int,
val fullCombo: Int,
val allPerfect: Int,
val totalScore: Long,
val plays: Int,
val totalPlayTime: Long,
val joined: String,
val lastSeen: String,
val lastVersion: String,
val lastPlayedHost: String? = null,
val ratingComposition: Map<String, Any>,
val recent: List<IGenericGamePlaylog>,
val rival: Boolean?,
val favorites: List<Int>?
)
data class GenericRankingPlayer(
var rank: Int,
val name: String,
val username: String?,
val accuracy: Double,
val rating: Int,
val allPerfect: Int,
val fullCombo: Int,
val lastSeen: String
)
@Serializable
data class GenericMusicMeta(
val name: String?,
val ver: String,
val notes: List<GenericNoteMeta>
)
@Serializable
data class GenericNoteMeta(
val lv: Double?,
)
@Serializable
data class GenericItemMeta(
val name: String? = null,
val disable: Boolean? = null,
val ver: String? = null
)
// Here are some interfaces to generalize across multiple games
interface IUserData {
val id: Long
var userName: String
val playerRating: Int
val highestRating: Int
val firstPlayDate: Any
val lastPlayDate: Any
val lastRomVersion: String
val totalScore: Long
var card: Card?
val lastClientId: String?
}
interface IGenericGamePlaylog {
val user: IUserData
val musicId: Int
val level: Int
val userPlayDate: Any
val achievement: Int
val maxCombo: Int
val isFullCombo: Boolean
val beforeRating: Int
val afterRating: Int
val isAllPerfect: Boolean
}
interface IGenericUserMusic {
val musicId: Int
}
interface IUserEntity<UserModel: IUserData> {
var id: Long
var user: UserModel
}
interface IExportClass<UserModel: IUserData> {
var gameId: String
var userData: UserModel
}
@MappedSuperclass
open class BaseEntity(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
open var id: Long = 0
) : JavaSerializable {
override fun toString() = JACKSON.writeValueAsString(this)
}
data class ImportResult(val errors: List<String>, val warnings: List<String>, val json: String)
@@ -0,0 +1,20 @@
package icu.samnyan.aqua.sega.allnet
import icu.samnyan.aqua.net.db.AquaNetUser
import jakarta.persistence.*
import java.io.Serializable
@Entity
@Table(name = "allnet_keychips")
class Keychip(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0,
@Column(nullable = false, unique = true, length = 32)
var keychipId: String = "",
@ManyToOne
@JoinColumn(name = "auId")
var user: AquaNetUser? = null
) : Serializable
@@ -0,0 +1,34 @@
package icu.samnyan.aqua.sega.allnet
import icu.samnyan.aqua.net.db.AquaNetUser
import jakarta.persistence.*
import java.security.SecureRandom
@Entity
@Table(name = "allnet_keychip_sessions", indexes = [
Index(name = "idx_last_use", columnList = "lastUse")
])
class KeychipSession(
@ManyToOne
@JoinColumn(name = "au_id")
var user: AquaNetUser? = null,
@Column(length = 4)
val gameId: String,
@Id
@Column(length = 32)
val token: String = genUrlSafeToken(32),
@Column(nullable = false)
var lastUse: Long = System.currentTimeMillis()
)
val urlSafeChars = ('a'..'z') + ('A'..'Z') + ('0'..'9') + listOf('-', '_', '.', '~')
fun genUrlSafeToken(length: Int): String {
val random = SecureRandom()
return (1..length)
.map { urlSafeChars[random.nextInt(urlSafeChars.size)] }
.joinToString("")
}
@@ -0,0 +1,82 @@
package icu.samnyan.aqua.sega.chusan.model
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import java.time.LocalDateTime
class GameCharge {
var orderId = 0
var chargeId = 0
var price = 0
var startDate: LocalDateTime? = LocalDateTime.of(2019, 1, 1, 0, 0, 0)
var endDate: LocalDateTime? = LocalDateTime.of(2099, 1, 1, 0, 0, 0)
var salePrice = 0
var saleStartDate: LocalDateTime? = LocalDateTime.of(2019, 1, 1, 0, 0, 0)
var saleEndDate: LocalDateTime? = LocalDateTime.of(2099, 1, 1, 0, 0, 0)
}
class GameEvent {
var id: Long = 0
val type = 0
val startDate: LocalDateTime? = LocalDateTime.of(2019, 1, 1, 0, 0, 0)
val endDate: LocalDateTime? = LocalDateTime.of(2099, 1, 1, 0, 0, 0)
@JsonIgnore
val enable = false
}
class GameGacha {
var gachaId = 0
var gachaName: String? = null
var type = 0
var kind = 0
@JsonProperty("isCeiling")
var isCeiling = false
var ceilingCnt = 0
var changeRateCnt1 = 0
var changeRateCnt2 = 0
var startDate: LocalDateTime? = LocalDateTime.of(2019, 1, 1, 0, 0, 0)
var endDate: LocalDateTime? = LocalDateTime.of(2099, 1, 1, 0, 0, 0)
var noticeStartDate: LocalDateTime? = LocalDateTime.of(2019, 1, 1, 0, 0, 0)
var noticeEndDate: LocalDateTime? = LocalDateTime.of(2099, 1, 1, 0, 0, 0)
}
class GameGachaCard {
var id: Long = 0
var gachaId = 0
var cardId = 0
var rarity = 0
var weight = 0
@JsonProperty("isPickup")
var isPickup = false
}
class GameLoginBonus {
var id: Long = 0
var version = 0
var presetId = 0
var loginBonusId = 0
var loginBonusName: String? = null
var presentId = 0
var presentName: String? = null
var itemNum = 0
var needLoginDayCount = 0
var loginBonusCategoryType = 0
}
class GameLoginBonusPreset {
var id: Long = 0
var version = 0
var presetName: String? = null
var isEnabled = false
}
class GameLinkedVerse {
var id: Long = 0
var musicId = 0
var name: String? = null
var startDate: LocalDateTime? = LocalDateTime.of(2019, 1, 1, 0, 0, 0)
var endDate: LocalDateTime? = LocalDateTime.of(2099, 1, 1, 0, 0, 0)
}
@@ -0,0 +1,68 @@
package icu.samnyan.aqua.sega.chusan.model.request
import ext.JDict
import icu.samnyan.aqua.sega.chusan.model.userdata.*
import icu.samnyan.aqua.sega.general.model.UserRecentRating
class UserCMissionResp {
var missionId = 0
var point = 0
var userCMissionProgressList: List<UserCMissionProgress>? = null
}
class FavNewMusic(
var musicId: Int = 0,
var orderId: Int = 0,
)
class UpsertTeamPoint(
// userId exists here, but it should not be used
// So I will not include it in the data class
var teamId: Long = 0,
var orderId: Int = 0,
var teamPoint: Long = 0,
var aggrDate: String = "",
)
data class UpsertNetBattleData(
val recentNBSelectMusicList: List<MusicIdWrapper> = emptyList(),
val isRankUpChallengeFailed: Boolean = false,
val highestBattleRankId: Long = 0,
val battleIconId: Long = 0,
val battleIconNum: Long = 0,
val avatarEffectPoint: Long = 0,
)
data class MusicIdWrapper(
val musicId: Int = 0,
)
class Chu3UserAll(
var userData: List<Chu3UserData>? = null,
var userGameOption: List<UserGameOption>? = null,
var userCharacterList: List<UserCharacter>? = null,
var userItemList: List<Chu3UserItem>? = null,
var userMusicDetailList: List<UserMusicDetail>? = null,
var userActivityList: List<Chu3UserActivity>? = null,
var userRecentRatingList: List<UserRecentRating>? = null,
var userPlaylogList: List<UserPlaylog>? = null,
var userChargeList: List<UserCharge>? = null,
var userCourseList: List<UserCourse>? = null,
var userDuelList: List<UserDuel>? = null,
// TODO: Actually implement team
var userTeamPoint: List<UpsertTeamPoint>? = null,
var userRatingBaseHotList: List<UserRecentRating>? = null,
var userRatingBaseList: List<UserRecentRating>? = null,
var userRatingBaseNextList: List<UserRecentRating>? = null,
var userRatingBaseNewList: List<UserRecentRating>? = null,
var userLoginBonusList: List<JDict>? = null,
var userMapAreaList: List<UserMap>? = null,
var userOverPowerList: List<JDict>? = null,
var userNetBattlelogList: List<Chu3NetBattleLog>? = null,
var userEmoneyList: List<JDict>? = null,
var userNetBattleData: List<UpsertNetBattleData>? = null,
var userCMissionList: List<UserCMissionResp>? = null,
var userFavoriteMusicList: List<FavNewMusic>? = null,
var userUnlockChallengeList: List<Chu3UserChallenge>? = null,
var userLinkedVerseList: List<Chu3UserLinkedVerse>? = null
)
@@ -0,0 +1,13 @@
package icu.samnyan.aqua.sega.chusan.model.request
import com.fasterxml.jackson.annotation.JsonProperty
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3MatchingMemberReq
class MatchingWaitState(
var matchingMemberInfoList: List<Chu3MatchingMemberReq> = listOf(),
@JsonProperty("isFinish")
var isFinish: Boolean = false,
var restMSec: Int = 120,
var pollingInterval: Int = 1,
)
@@ -0,0 +1,22 @@
package icu.samnyan.aqua.sega.chusan.model.request
import com.fasterxml.jackson.annotation.JsonProperty
import icu.samnyan.aqua.sega.chusan.model.GameGachaCard
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserItem
import icu.samnyan.aqua.sega.chusan.model.userdata.UserGacha
import java.io.Serializable
class UpsertUserGacha : Serializable {
var userData: Chu3UserData? = null
var userGacha: UserGacha? = null
var userCharacterList: List<Any>? = null
var userCardList: List<Any>? = null
var gameGachaCardList: List<GameGachaCard>? = null
var userItemList: List<Chu3UserItem>? = null
@JsonProperty("isNewCharacterList")
var isNewCharacterList: String? = null
@JsonProperty("isNewCardList")
var isNewCardList: String? = null
}
@@ -0,0 +1,11 @@
package icu.samnyan.aqua.sega.chusan.model.request
class UserEmoney(
var type: Int = 0,
var emoneyCredit: Int = 69,
var emoneyBrand: Int = 2,
var ext1: Int = 0,
var ext2: Int = 0,
var ext3: Int = 0
)
@@ -0,0 +1,57 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
open class Chu3MatchingMember {
var userId: Long = 0
var regionId = 0
var placeId = 0
var userName: String = ""
var playerRating = 0
var battleRankId = 0
var battleCorrection = 0
var battleRatingAvg = 0
var optRatingId = 0
var ratingEffectColorId = 0
var trophyId = 0
var nameplateId = 0
var emblemMedal = 0
var emblemBase = 0
var characterId = 0
var characterRank = 0
var skillId = 0
var skillLv = 0
var skillIdForChara = 0
@JsonProperty("isJoinTeam")
var isJoinTeam = false
var teamName: String? = null
var teamRank = 0
var messageId = 0
var clientId: String? = null
var romVersion: String? = null
var dataVersion: String? = null
var errCnt = 0
var hostErrCnt = 0
var joinTime = 0
}
class AvatarEquip {
var wearID = 0
var headID = 0
var faceID = 0
var skinID = 0
var itemID = 0
var frontID = 0
var backID = 0
}
class GenreGraph {
var genreId = 0
var musicCount = 0
}
class Chu3MatchingMemberReq : Chu3MatchingMember() {
var avatarEquip: AvatarEquip? = null
var genreGraphList: List<GenreGraph>? = null
}
@@ -0,0 +1,76 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
@Entity(name = "ChusanNetBattleLog")
@Table(name = "chusan_net_battle_log")
class Chu3NetBattleLog(
var roomId: Long = 0,
var track: Int = 0,
// From playlog
var musicId: Int = 0,
var difficultyId: Int = 0,
var score: Int = 0,
var selectUserId: Long = 0,
var selectUserName: String = "",
var opponentUserId1: Long = 0,
var opponentUserId2: Long = 0,
var opponentUserId3: Long = 0,
var opponentUserName1: String = "",
var opponentUserName2: String = "",
var opponentUserName3: String = "",
var opponentRegionId1: Int = 0,
var opponentRegionId2: Int = 0,
var opponentRegionId3: Int = 0,
var opponentRating1: Int = 0,
var opponentRating2: Int = 0,
var opponentRating3: Int = 0,
var opponentBattleRankId1: Int = 0,
var opponentBattleRankId2: Int = 0,
var opponentBattleRankId3: Int = 0,
var opponentClassEmblemMedal1: Int = 0,
var opponentClassEmblemMedal2: Int = 0,
var opponentClassEmblemMedal3: Int = 0,
var opponentClassEmblemBase1: Int = 0,
var opponentClassEmblemBase2: Int = 0,
var opponentClassEmblemBase3: Int = 0,
var opponentScore1: Int = 0,
var opponentScore2: Int = 0,
var opponentScore3: Int = 0,
var opponentCharaIllustId1: Int = 0,
var opponentCharaIllustId2: Int = 0,
var opponentCharaIllustId3: Int = 0,
var opponentCharaLv1: Int = 0,
var opponentCharaLv2: Int = 0,
var opponentCharaLv3: Int = 0,
var opponentRatingEffectColorId1: Int = 0,
var opponentRatingEffectColorId2: Int = 0,
var opponentRatingEffectColorId3: Int = 0,
var battleRuleId: Int = 0,
var monthPoLong: Int = 0,
var eventPoLong: Int = 0
) : Chu3UserEntity() {
// musicId, difficultyId, userName, score, memberName{1-3}, memberScore{1-3}, selectedMemberNum
fun toDict(username: String) = mapOf(
"musicId" to musicId,
"difficultyId" to difficultyId,
"score" to score,
"userName" to username,
"memberName1" to opponentUserName1,
"memberScore1" to opponentScore1,
"memberName2" to opponentUserName2,
"memberScore2" to opponentScore2,
"memberName3" to opponentUserName3,
"memberScore3" to opponentScore3,
"selectedMemberNum" to listOf(
true,
selectUserId == opponentUserId1,
selectUserId == opponentUserId2,
selectUserId == opponentUserId3
).lastIndexOf(true)
)
}
@@ -0,0 +1,21 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserActivity")
@Table(name = "chusan_user_activity", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "kind", "activity_id"])])
class Chu3UserActivity : Chu3UserEntity() {
var kind = 0
@JsonProperty("id")
@Column(name = "activity_id")
var activityId = 0
var sortNumber = 0
var param1 = 0
var param2 = 0
var param3 = 0
var param4 = 0
}
@@ -0,0 +1,18 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserChallenge")
@Table(name = "chusan_user_challenge", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "unlock_challenge_id"])])
class Chu3UserChallenge : Chu3UserEntity() {
var unlockChallengeId = 0
var status = 0
var clearCourseId = 0
var conditionType = 0
var score = 0
var life = 0
var clearDate = "" // len 20 YYYY-MM-DD HH:MM:SS
}
@@ -0,0 +1,170 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.net.games.IUserData
import icu.samnyan.aqua.sega.chusan.model.request.UserEmoney
import icu.samnyan.aqua.sega.general.model.Card
import icu.samnyan.aqua.sega.util.AccessCodeSerializer
import jakarta.persistence.*
import java.io.IOException
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
class FlexibleDateTimeDeserializer : JsonDeserializer<LocalDateTime?>() {
@Throws(IOException::class)
public override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): LocalDateTime {
return LocalDateTime.parse(p.getText(), FORMATTER)
}
companion object {
// Card Maker needs the date ending with ".0" and chunithm sends the dates without it so we need a flexible parser
private val FORMATTER: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.S]")
}
}
@Entity(name = "ChusanUserData")
@Table(name = "chusan_user_data")
class Chu3UserData : BaseEntity(), IUserData {
@JsonSerialize(using = AccessCodeSerializer::class)
@JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "card_id", unique = true)
override var card: Card? = null
override var userName: String = ""
var level = 0
var reincarnationNum = 0
var exp: String = ""
var point: Long = 0
var totalPoint: Long = 0
var playCount = 0
var multiPlayCount = 0
override var playerRating: Int = 0
override var highestRating: Int = 0
var nameplateId = 0
var frameId = 0
var characterId = 0
var trophyId = 0
var playedTutorialBit = 0
var firstTutorialCancelNum = 0
var masterTutorialCancelNum = 0
var totalMapNum = 0
var totalHiScore: Long = 0
var totalBasicHighScore: Long = 0
var totalAdvancedHighScore: Long = 0
var totalExpertHighScore: Long = 0
var totalMasterHighScore: Long = 0
var totalUltimaHighScore: Long = 0
@JsonDeserialize(using = FlexibleDateTimeDeserializer::class)
var eventWatchedDate: LocalDateTime = LocalDateTime.now()
var friendCount = 0
var firstGameId: String = ""
var firstRomVersion: String = ""
var firstDataVersion: String = ""
@JsonDeserialize(using = FlexibleDateTimeDeserializer::class)
override var firstPlayDate: LocalDateTime = LocalDateTime.now()
var lastGameId: String = ""
override var lastRomVersion: String = ""
var lastDataVersion: String = ""
@JsonIgnore
var lastLoginDate: LocalDateTime = LocalDateTime.now()
@JsonDeserialize(using = FlexibleDateTimeDeserializer::class)
override var lastPlayDate: LocalDateTime = LocalDateTime.now()
var lastPlaceId = 0
var lastPlaceName: String = ""
var lastRegionId: String = ""
var lastRegionName: String = ""
var lastAllNetId: String = ""
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
override var lastClientId: String = ""
var lastCountryCode: String = ""
var userNameEx: String = ""
var compatibleCmVersion: String = ""
var medal = 0
var mapIconId = 0
var voiceId = 0
var avatarWear = 0
var avatarHead = 0
var avatarFace = 0
var avatarSkin = 0
var avatarItem = 0
var avatarFront = 0
var avatarBack = 0
var classEmblemBase = 0
var classEmblemMedal = 0
var stockedGridCount = 0
var exMapLoopCount = 0
var netBattlePlayCount = 0
var netBattleWinCount = 0
var netBattleLoseCount = 0
var netBattleConsecutiveWinCount = 0
var charaIllustId = 0
var skillId = 0
var stageId = 0
var overPowerPoint = 0
var overPowerRate = 0
var overPowerLowerRank = 0
var avatarPoint = 0
var battleRankId = 0
var battleRankPoint = 0
var eliteRankPoint = 0
var netBattle1stCount = 0
var netBattle2ndCount = 0
var netBattle3rdCount = 0
var netBattle4thCount = 0
var netBattleCorrection = 0
var netBattleErrCnt = 0
var netBattleHostErrCnt = 0
var battleRewardStatus = 0
var battleRewardIndex = 0
var battleRewardCount = 0
var ext1 = 0
var ext2 = 0
var ext3 = 0
var ext4 = 0
var ext5 = 0
var ext6 = 0
var ext7 = 0
var ext8 = 0
var ext9 = 0
var ext10 = 0
var extStr1: String = ""
var extStr2: String = ""
var extLong1: Long = 0
var extLong2: Long = 0
@JsonInclude
@Transient
var rankUpChallengeResults: List<Any>? = null
// When serialized, this field should be "isNetBattleHost", not "netBattleHost"
@JsonProperty("isNetBattleHost")
var isNetBattleHost = false
var netBattleEndState = 0
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
var userEmoney: UserEmoney? = null
// VERSE
var trophyIdSub1 = 0
var trophyIdSub2 = 0
override val totalScore get() = totalHiScore
}
@@ -0,0 +1,16 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.net.games.IUserEntity
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.MappedSuperclass
@MappedSuperclass
open class Chu3UserEntity : BaseEntity(), IUserEntity<Chu3UserData> {
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id")
override var user: Chu3UserData = Chu3UserData()
}
@@ -0,0 +1,16 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserItem")
@Table(name = "chusan_user_item", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "item_id", "item_kind"])])
class Chu3UserItem(
var itemKind: Int = 0,
var itemId: Int = 0,
var stock: Int = 1,
@JsonProperty("isValid")
var isValid: Boolean = true
) : Chu3UserEntity()
@@ -0,0 +1,28 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
import java.time.LocalDateTime
@Entity(name = "ChusanUserLinkedVerse")
@Table(name = "chusan_user_linked_verse", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "linked_verse_id"])])
class Chu3UserLinkedVerse : Chu3UserEntity() {
var linkedVerseId = 0
var clearCourseId = 0
var clearCourseLevel = 0
var clearDate: LocalDateTime = LocalDateTime.now()
var clearUserId1: Long = 0
var clearUserId2: Long = 0
var clearUserId3: Long = 0
var clearUserName0 = ""
var clearUserName1 = ""
var clearUserName2 = ""
var clearUserName3 = ""
var isFirstClear = false
var numClear = 0
var statusOpen = 0
var statusUnlock = 0
var progress: String = ""
}
@@ -0,0 +1,18 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import icu.samnyan.aqua.sega.general.IntegerListConverter
import jakarta.persistence.Convert
import jakarta.persistence.Entity
@Entity(name = "ChusanUserMisc")
class Chu3UserMisc(
@Convert(converter = IntegerListConverter::class)
var recentNbSelect: MutableList<Int> = mutableListOf(),
@Convert(converter = IntegerListConverter::class)
var recentNbMusic: MutableList<Int> = mutableListOf(),
@Convert(converter = IntegerListConverter::class)
var favMusic: MutableList<Int> = mutableListOf()
): Chu3UserEntity()
@@ -0,0 +1,11 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
@Entity(name = "ChusanUserCMission")
@Table(name = "chusan_user_cmission")
class UserCMission : Chu3UserEntity() {
var missionId = 0
var point = 0
}
@@ -0,0 +1,19 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserCMissionProgress")
@Table(name = "chusan_user_cmission_progress", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "mission_id", "order"])])
class UserCMissionProgress : Chu3UserEntity() {
@Column(name = "mission_id")
@JsonIgnore
var missionId = 0
@Column(name = "`order`")
var order = 0
var stage = 0
var progress = 0
}
@@ -0,0 +1,19 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.Entity
import jakarta.persistence.Table
import java.time.LocalDateTime
@Entity(name = "ChusanUserCardPrintState")
@Table(name = "chusan_user_print_state")
class UserCardPrintState(
var hasCompleted: Boolean = false,
@JsonIgnore
var limitDate: LocalDateTime = LocalDateTime.now(),
var placeId: Int = 0,
var cardId: Int = 0,
var gachaId: Int = 0
) : Chu3UserEntity()
@@ -0,0 +1,25 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserCharacter")
@Table(name = "chusan_user_character", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "character_id"])])
class UserCharacter : Chu3UserEntity() {
@Column(name = "character_id")
var characterId = 0
var playCount = 0
var level = 1
var friendshipExp = 0
@JsonProperty("isValid")
var isValid = true
@JsonProperty("isNewMark")
var isNewMark = true
var exMaxLv = 0
var assignIllust = 0
var param1 = 0
var param2 = 0
}
@@ -0,0 +1,18 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
import java.time.LocalDateTime
@Entity(name = "ChusanUserCharge")
@Table(name = "chusan_user_charge", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "charge_id"])])
class UserCharge : Chu3UserEntity() {
var chargeId = 0
var stock = 0
var purchaseDate: LocalDateTime? = null
var validDate: LocalDateTime? = null
var param1 = 0
var param2 = 0
var paramDate: LocalDateTime? = null
}
@@ -0,0 +1,33 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
import java.time.LocalDateTime
@Entity(name = "ChusanUserCourse")
@Table(name = "chusan_user_course", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "course_id"])])
class UserCourse : Chu3UserEntity() {
var courseId = 0
var classId = 0
var playCount = 0
var theoryCount = 0
var scoreMax = 0
@JsonProperty("isFullCombo")
var isFullCombo = false
@JsonProperty("isAllJustice")
var isAllJustice = false
@JsonProperty("isSuccess")
var isSuccess = false
var scoreRank = 0
var eventId = 0
var lastPlayDate: LocalDateTime? = null
var param1 = 0
var param2 = 0
var param3 = 0
var param4 = 0
var orderId = 0
var playerRating = 0
@JsonProperty("isClear")
var isClear = false
}
@@ -0,0 +1,23 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
import java.time.LocalDateTime
@Entity(name = "ChusanUserDuel")
@Table(name = "chusan_user_duel", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "duel_id"])])
class UserDuel : Chu3UserEntity() {
@Column(name = "duel_id")
var duelId = 0
var progress = 0
var point = 0
@JsonProperty("isClear")
var isClear = false
var lastPlayDate: LocalDateTime? = null
var param1 = 0
var param2 = 0
var param3 = 0
var param4 = 0
}
@@ -0,0 +1,17 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
import java.time.LocalDateTime
@Entity(name = "ChusanUserGacha")
@Table(name = "chusan_user_gacha")
class UserGacha : Chu3UserEntity() {
var gachaId = 0
var totalGachaCnt = 0
var ceilingGachaCnt = 0
var dailyGachaCnt = 0
var fiveGachaCnt = 0
var elevenGachaCnt = 0
var dailyGachaDate: LocalDateTime? = null
}
@@ -0,0 +1,58 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
@Entity(name = "ChusanUserGameOption")
@Table(name = "chusan_user_game_option")
class UserGameOption : Chu3UserEntity() {
var bgInfo = 0
var fieldColor = 0
var guideSound = 0
var soundEffect = 0
var guideLine = 0
var speed = 0
var optionSet = 0
var matching = 0
var judgePos = 0
var rating = 0
var judgeCritical = 0
var judgeJustice = 0
var judgeAttack = 0
var headphone = 0
var playerLevel = 0
var successTap = 0
var successExTap = 0
var successSlideHold = 0
var successAir = 0
var successFlick = 0
var successSkill = 0
var successTapTimbre = 0
var privacy = 0
var mirrorFumen = 0
var selectMusicFilterLv = 0
var sortMusicFilterLv = 0
var sortMusicGenre = 0
var categoryDetail = 0
var judgeTimingOffset = 0
var playTimingOffset = 0
var fieldWallPosition = 0
var resultVoiceShort = 0
var notesThickness = 0
var judgeAppendSe = 0
var trackSkip = 0
var hardJudge = 0
var speed_120 = 0
var fieldWallPosition_120 = 0
var playTimingOffset_120 = 0
var judgeTimingOffset_120 = 0
var ext1 = 0
var ext2 = 0
var ext3 = 0
var ext4 = 0
var ext5 = 0
var ext6 = 0
var ext7 = 0
var ext8 = 0
var ext9 = 0
var ext10 = 0
}
@@ -0,0 +1,13 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
@Entity(name = "ChusanUserGeneralData")
@Table(name = "chusan_user_general_data")
class UserGeneralData(
@Column(columnDefinition = "TEXT")
var propertyValue: String = "",
var propertyKey: String = "",
) : Chu3UserEntity()
@@ -0,0 +1,20 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import ext.DATE_2018
import icu.samnyan.aqua.net.games.BaseEntity
import jakarta.persistence.Entity
import jakarta.persistence.Table
import java.time.LocalDateTime
@Entity(name = "ChusanUserLoginBonus")
@Table(name = "chusan_user_login_bonus")
class UserLoginBonus(
var version: Int = 0,
// TODO: Fix this (should be User linked)
var user: Int = 0,
var presetId: Int = 0,
var bonusCount: Int = 0,
var lastUpdateDate: LocalDateTime = DATE_2018,
var isWatched: Boolean = false, // TODO: Check if this should be "watched" or "isWatched" in json
var isFinished: Boolean = false,
) : BaseEntity()
@@ -0,0 +1,23 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserMapArea")
@Table(name = "chusan_user_map_area", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "map_area_id"])])
class UserMap : Chu3UserEntity() {
var mapAreaId = 0
var position = 0
@JsonProperty("isClear")
var isClear = false
var rate = 0
var statusCount = 0
var remainGridCount = 0
@JsonProperty("isLocked")
var isLocked = false
}
@@ -0,0 +1,46 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import icu.samnyan.aqua.net.games.IGenericUserMusic
import icu.samnyan.aqua.sega.util.BooleanToIntegerDeserializer
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Entity(name = "ChusanUserMusicDetail")
@Table(
name = "chusan_user_music_detail",
uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "music_id", "level"])]
)
class UserMusicDetail : Chu3UserEntity(), IGenericUserMusic {
override var musicId = 0
var level = 0
var playCount = 0
var scoreMax = 0
var missCount = 0
var maxComboCount = 0
@JsonProperty("isFullCombo")
var isFullCombo = false
@JsonProperty("isAllJustice")
var isAllJustice = false
@JsonDeserialize(using = BooleanToIntegerDeserializer::class)
@JsonProperty("isSuccess")
var isSuccess = 0
var fullChain = 0
var maxChain = 0
var scoreRank = 0
@JsonProperty("isLock")
var isLock = false
var theoryCount = 0
var ext1 = 0
}
@@ -0,0 +1,81 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
import icu.samnyan.aqua.net.games.IGenericGamePlaylog
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
import java.time.LocalDateTime
@Entity(name = "ChusanUserPlaylog")
@Table(name = "chusan_user_playlog")
class UserPlaylog : Chu3UserEntity(), IGenericGamePlaylog {
var romVersion: String? = null
var orderId = 0
var sortNumber = 0
var placeId = 0
var playDate: LocalDateTime? = null
override var userPlayDate: LocalDateTime = LocalDateTime.now()
override var musicId: Int = 0
override var level: Int = 0
var customId = 0
var playedUserId1: Long = 0
var playedUserId2: Long = 0
var playedUserId3: Long = 0
var playedUserName1: String? = null
var playedUserName2: String? = null
var playedUserName3: String? = null
var playedMusicLevel1 = 0
var playedMusicLevel2 = 0
var playedMusicLevel3 = 0
var playedCustom1 = 0
var playedCustom2 = 0
var playedCustom3 = 0
var track = 0
var score = 0
@Column(name = "\"rank\"")
var rank = 0
override var maxCombo: Int = 0
var maxChain = 0
var rateTap = 0
var rateHold = 0
var rateSlide = 0
var rateAir = 0
var rateFlick = 0
var judgeGuilty = 0
var judgeAttack = 0
var judgeJustice = 0
var judgeCritical = 0
var judgeHeaven = 0
var eventId = 0
var playerRating = 0
@JsonProperty("isNewRecord")
var isNewRecord = false
@JsonProperty("isFullCombo")
override var isFullCombo: Boolean = false
var fullChainKind = 0
@JsonProperty("isAllJustice")
var isAllJustice = false
@JsonProperty("isContinue")
var isContinue = false
@JsonProperty("isFreeToPlay")
var isFreeToPlay = false
var characterId = 0
var charaIllustId = 0
var skillId = 0
var playKind = 0
@JsonProperty("isClear")
var isClear = false
var skillLevel = 0
var skillEffect = 0
var placeName: String? = null
var commonId = 0
var regionId = 0
var machineType = 0
var ticketId = 0
override val achievement: Int get() = score
override val afterRating: Int get() = playerRating
override val beforeRating: Int get() = playerRating // TODO: Implement this
override val isAllPerfect: Boolean get() = isAllJustice
}
@@ -0,0 +1,14 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import jakarta.persistence.Entity
import jakarta.persistence.Table
import jakarta.persistence.UniqueConstraint
import java.time.LocalDate
@Entity(name = "ChusanUserRegions")
@Table(name = "chusan_user_regions", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "region_id"])])
class UserRegions : Chu3UserEntity() {
var regionId = 0
var playCount = 1
var created: String = LocalDate.now().toString()
}
@@ -0,0 +1,142 @@
package icu.samnyan.aqua.sega.diva.model
import java.time.ZonedDateTime
/**
* Data format from <url>https://dev.s-ul.eu/mikumiku/minime/wikis/home</url>
*
* @author samnyan (privateamusement@protonmail.com)
*/
open class BaseRequest {
var game_id: String = "" // Game Id
var place_id: String = "" // Place Id
var time_stamp: ZonedDateTime = ZonedDateTime.now() // Timestamp
}
open class PdRequest : BaseRequest() {
var pd_id: Long = 0
}
class StageResultRequest : PdRequest() {
var hp_vol: Int = 0
var btn_se_vol: Boolean = false
var btn_se_vol2: Int = 0
var sldr_se_vol2: Int = 0
var nxt_pv_id: Int = 0
var nxt_dffclty: Int = 0
var nxt_edtn: Int = 0
var sort_kind: Int = 0
var game_type: Int = 0
var stg_difficulty: IntArray = intArrayOf()
var stg_edtn: IntArray = intArrayOf()
var stg_ply_pv_id: IntArray = intArrayOf()
var stg_scrpt_ver: IntArray = intArrayOf()
var stg_score: IntArray = intArrayOf()
var stg_chllng_kind: IntArray = intArrayOf()
var stg_chllng_result: IntArray = intArrayOf()
var stg_clr_kind: IntArray = intArrayOf()
var stg_vcld_pts: IntArray = intArrayOf()
var stg_cool_cnt: IntArray = intArrayOf()
var stg_cool_pct: IntArray = intArrayOf()
var stg_fine_cnt: IntArray = intArrayOf()
var stg_fine_pct: IntArray = intArrayOf()
var stg_safe_cnt: IntArray = intArrayOf()
var stg_safe_pct: IntArray = intArrayOf()
var stg_sad_cnt: IntArray = intArrayOf()
var stg_sad_pct: IntArray = intArrayOf()
var stg_wt_wg_cnt: IntArray = intArrayOf()
var stg_wt_wg_pct: IntArray = intArrayOf()
var stg_max_cmb: IntArray = intArrayOf()
var stg_chance_tm: IntArray = intArrayOf()
var stg_sm_hl: IntArray = intArrayOf()
var stg_atn_pnt: IntArray = intArrayOf()
var stg_skin_id: IntArray = intArrayOf()
var stg_btn_se: IntArray = intArrayOf()
var stg_btn_se_vol: IntArray = intArrayOf()
var stg_sld_se: IntArray = intArrayOf()
var stg_chn_sld_se: IntArray = intArrayOf()
var stg_sldr_tch_se: IntArray = intArrayOf()
var stg_mdl_id: IntArray = intArrayOf()
var stg_cpt_rslt: IntArray = intArrayOf()
var stg_sld_scr: IntArray = intArrayOf()
var stg_vcl_chg: IntArray = intArrayOf()
var stg_c_itm_id: IntArray = intArrayOf()
var stg_rgo: IntArray = intArrayOf()
var stg_ss_num: IntArray = intArrayOf()
var cr_cid: Int = 0
var cr_tv: Int = 0
var cr_if: Int = 0
var cr_sp: Array<String?> = arrayOf()
}
class StageStartRequest : PdRequest() {
var stg_ply_pv_id: IntArray = intArrayOf()
}
class StartRequest : PdRequest() {
}
class StoreSsRequest : PdRequest() {
var ss_mdl_id: IntArray = intArrayOf()
var ss_c_itm_id: IntArray = intArrayOf()
}
class SpendCreditRequest : PdRequest() {
}
class ShopExitRequest : PdRequest() {
var use_pv_mdl_eqp = 0
var ply_pv_id = 0
var mdl_eqp_cmn_ary: IntArray = intArrayOf()
var c_itm_eqp_cmn_ary: IntArray = intArrayOf()
var ms_itm_flg_cmn_ary: IntArray = intArrayOf()
var mdl_eqp_pv_ary: IntArray = intArrayOf()
var c_itm_eqp_pv_ary: IntArray = intArrayOf()
var ms_itm_flg_pv_ary: IntArray = intArrayOf()
}
class RegistrationRequest : BaseRequest() {
var idm: String = ""
var aime_id: Long = 0
var player_name: String = ""
}
class PsRankingRequest : BaseRequest() {
var rnk_ps_pv_id_lst: IntArray = intArrayOf()
var rnk_ps_idx = 0
}
class PreStartRequest : BaseRequest() {
var idm: String = ""
var aime_id: Long = 0
}
class PdUnlockRequest : PdRequest() {
}
class GetPvPdRequest : PdRequest() {
var difficulty = 0
var pd_pv_id_lst: IntArray = intArrayOf()
}
class ChangePasswdRequest : PdRequest() {
var new_passwd: String = ""
}
class ChangeNameRequest : PdRequest() {
var player_name: String = ""
}
class CardProcedureRequest : BaseRequest() {
var aime_id: Long = 0
}
class BuyModuleRequest : PdRequest() {
var mdl_id = 0
}
class BuyCstmzItmRequest : PdRequest() {
var cstmz_itm_id = 0
}
@@ -0,0 +1,599 @@
@file:Suppress("unused")
package icu.samnyan.aqua.sega.diva.model
import icu.samnyan.aqua.sega.diva.model.common.*
import icu.samnyan.aqua.sega.diva.util.URIEncoder
import java.time.LocalDateTime
class CardProcedureResponse {
var cd_adm_result: Result?
var chg_name_price = 100
var accept_idx = 0
var pd_id: Long = 0
var player_name: String? = null
var lv_num: Int? = null
var lv_pnt: Int? = null
var lv_str: String? = null
var lv_efct_id: Int? = null
var lv_plt_id: Int? = null
var vcld_pts: Int? = null
var passwd_stat: PassStat? = null
constructor(
cd_adm_result: Result?,
chg_name_price: Int,
accept_idx: Int,
pd_id: Long,
player_name: String?,
lv_num: Int?,
lv_pnt: Int?,
lv_str: String?,
lv_efct_id: Int?,
lv_plt_id: Int?,
vcld_pts: Int?,
passwd_stat: PassStat?
) {
this.cd_adm_result = cd_adm_result
this.chg_name_price = chg_name_price
this.accept_idx = accept_idx
this.pd_id = pd_id
this.player_name = player_name
this.lv_num = lv_num
this.lv_pnt = lv_pnt
this.lv_str = lv_str
this.lv_efct_id = lv_efct_id
this.lv_plt_id = lv_plt_id
this.vcld_pts = vcld_pts
this.passwd_stat = passwd_stat
}
constructor(cd_adm_result: Result?) {
this.cd_adm_result = cd_adm_result
}
}
class ChangeNameResponse(
var cd_adm_result: Result?,
var accept_idx: Int,
var pd_id: Long,
var player_name: String?
)
class ChangePasswdResponse(var cd_adm_result: Result?, var accept_idx: Int, var pd_id: Long)
class RegistrationResponse(var cd_adm_result: Result?, var pd_id: Long)
class ContestInfoResponse(var ci_lut: LocalDateTime?, var ci_str: String?)
class FestaInfoResponse(
var fi_id: String?,
var fi_name: String?,
var fi_kind: String?,
var fi_difficulty: String?,
var fi_pv_id_lst: String?,
var fi_attr: String?,
var fi_add_vp: String?,
var fi_mul_vp: String?,
var fi_st: String?,
var fi_et: String?,
var fi_lut: String?
)
class NvRankingResponse(
var rnk_nv_tag_str: String?,
var rnk_nv_ts: LocalDateTime?,
var rnk_nv_data: String?,
var rnk_nv_lut: LocalDateTime?
)
class PsRankingResponse(
var rnk_ps_lut: LocalDateTime?,
var rnk_ps_ts: LocalDateTime?,
var rnk_ps_dffclty: Int,
var rnk_ps_pv_id: String?,
var rnk_ps_edtn1: String?,
var rnk_ps_edtn2: String?,
var rnk_ps_edtn3: String?,
var rnk_ps_scr1: String?,
var rnk_ps_scr2: String?,
var rnk_ps_scr3: String?,
var rnk_ps_nm1: String?,
var rnk_ps_nm2: String?,
var rnk_ps_nm3: String?
)
class PvListResponse(var pvl_lut: LocalDateTime?, var pv_lst: String?)
class ShopCatalogResponse(var shp_ctlg_lut: LocalDateTime?, var shp_ctlg: String?)
class BuyCstmzItmResponse {
var shp_rslt: Result?
var cstmz_itm_id = 0
var cstmz_itm_have: String? = null
var vcld_pts = 0
constructor(shp_rslt: Result?, cstmz_itm_id: Int, cstmz_itm_have: String?, vcld_pts: Int) {
this.shp_rslt = shp_rslt
this.cstmz_itm_id = cstmz_itm_id
this.cstmz_itm_have = cstmz_itm_have
this.vcld_pts = vcld_pts
}
constructor(shp_rslt: Result?) {
this.shp_rslt = shp_rslt
}
}
class BuyModuleResponse {
var shp_rslt: Result?
var mdl_id = 0
var mdl_have: String? = null
var vcld_pts = 0
constructor(shp_rslt: Result?, mdl_id: Int, mdl_have: String?, vcld_pts: Int) {
this.shp_rslt = shp_rslt
this.mdl_id = mdl_id
this.mdl_have = mdl_have
this.vcld_pts = vcld_pts
}
constructor(shp_rslt: Result?) {
this.shp_rslt = shp_rslt
}
}
class GetPvPdResponse(var pd_by_pv_id: String?, var pdddt_flg: Boolean?, var pdddt_tm: String?)
class ShopExitResponse(var shp_rslt: Result?)
class StageResultResponse {
var chllng_kind = 0
var lv_num_old = 0
var lv_pnt_old = 0
var lv_num = 0
var lv_pnt = 0
var lv_str: String? = null
var lv_efct_id = 0
var lv_plt_id = 0
var vcld_pts = 0
var prsnt_vcld_pts = 0
var cnp_cid = 0
var cnp_var = 0
var cnp_sp: String? = null
var crwd_kind: String? = "-1,-1,-1"
var crwd_varue: String? = "-1,-1,-1"
var crwd_str_0: String? = "***,***,***"
var crwd_str_1: String? = "***,***,***"
var cerwd_kind = -1
var cerwd_varue = -1
var cerwd_str_0: String? = "***"
var cerwd_str_1: String? = "***"
var ttl_str_ary: String? = "xxx"
var ttl_plt_id_ary: String? = "-1,-1,-1,-1,-1"
var ttl_desc_ary: String? = "xxx"
var skin_id_ary: String? = "xxx"
var skin_name_ary: String? = "xxx"
var skin_illust_ary: String? = "xxx"
var skin_desc_ary: String? = "xxx"
var pdddt_flg = 0
var pdddt_tm: LocalDateTime? = null
var nblss_ltt_stts = -1
var nblss_ltt_tckt = -1
var nblss_ltt_is_opn = 0
var nblss_ltt_prz = 0
var nblss_ltt_nxt_stts = 0
var nblss_ltt_nxt_tckt = -1
var my_qst_id: String? = null
var my_qst_r_qid: String? = null
var my_qst_r_knd: String? = null
var my_qst_r_vl: String? = null
var my_qst_r_nflg: String? = null
var my_ccd_r_qid: String? = null
var my_ccd_r_hnd: String? = null
var my_ccd_r_vp: String? = null
constructor()
constructor(
chllng_kind: Int,
lv_num_old: Int,
lv_pnt_old: Int,
lv_num: Int,
lv_pnt: Int,
lv_str: String?,
lv_efct_id: Int,
lv_plt_id: Int,
vcld_pts: Int,
prsnt_vcld_pts: Int,
cnp_cid: Int,
cnp_var: Int,
cnp_sp: String?,
crwd_kind: String?,
crwd_varue: String?,
crwd_str_0: String?,
crwd_str_1: String?,
cerwd_kind: Int,
cerwd_varue: Int,
cerwd_str_0: String?,
cerwd_str_1: String?,
ttl_str_ary: String?,
ttl_plt_id_ary: String?,
ttl_desc_ary: String?,
skin_id_ary: String?,
skin_name_ary: String?,
skin_illust_ary: String?,
skin_desc_ary: String?,
pdddt_flg: Int,
pdddt_tm: LocalDateTime?,
nblss_ltt_stts: Int,
nblss_ltt_tckt: Int,
nblss_ltt_is_opn: Int,
nblss_ltt_prz: Int,
nblss_ltt_nxt_stts: Int,
nblss_ltt_nxt_tckt: Int,
my_qst_id: String?,
my_qst_r_qid: String?,
my_qst_r_knd: String?,
my_qst_r_vl: String?,
my_qst_r_nflg: String?,
my_ccd_r_qid: String?,
my_ccd_r_hnd: String?,
my_ccd_r_vp: String?
) {
this.chllng_kind = chllng_kind
this.lv_num_old = lv_num_old
this.lv_pnt_old = lv_pnt_old
this.lv_num = lv_num
this.lv_pnt = lv_pnt
this.lv_str = lv_str
this.lv_efct_id = lv_efct_id
this.lv_plt_id = lv_plt_id
this.vcld_pts = vcld_pts
this.prsnt_vcld_pts = prsnt_vcld_pts
this.cnp_cid = cnp_cid
this.cnp_var = cnp_var
this.cnp_sp = cnp_sp
this.crwd_kind = crwd_kind
this.crwd_varue = crwd_varue
this.crwd_str_0 = crwd_str_0
this.crwd_str_1 = crwd_str_1
this.cerwd_kind = cerwd_kind
this.cerwd_varue = cerwd_varue
this.cerwd_str_0 = cerwd_str_0
this.cerwd_str_1 = cerwd_str_1
this.ttl_str_ary = ttl_str_ary
this.ttl_plt_id_ary = ttl_plt_id_ary
this.ttl_desc_ary = ttl_desc_ary
this.skin_id_ary = skin_id_ary
this.skin_name_ary = skin_name_ary
this.skin_illust_ary = skin_illust_ary
this.skin_desc_ary = skin_desc_ary
this.pdddt_flg = pdddt_flg
this.pdddt_tm = pdddt_tm
this.nblss_ltt_stts = nblss_ltt_stts
this.nblss_ltt_tckt = nblss_ltt_tckt
this.nblss_ltt_is_opn = nblss_ltt_is_opn
this.nblss_ltt_prz = nblss_ltt_prz
this.nblss_ltt_nxt_stts = nblss_ltt_nxt_stts
this.nblss_ltt_nxt_tckt = nblss_ltt_nxt_tckt
this.my_qst_id = my_qst_id
this.my_qst_r_qid = my_qst_r_qid
this.my_qst_r_knd = my_qst_r_knd
this.my_qst_r_vl = my_qst_r_vl
this.my_qst_r_nflg = my_qst_r_nflg
this.my_ccd_r_qid = my_ccd_r_qid
this.my_ccd_r_hnd = my_ccd_r_hnd
this.my_ccd_r_vp = my_ccd_r_vp
}
}
class PreStartResponse {
var ps_result: PreStartResult?
var accept_idx: Int? = null
var nblss_ltt_stts: Int? = null
var nblss_ltt_tckt: Int? = null
var nblss_ltt_is_opn: Int? = null
var pd_id: Long = 0
var player_name: String? = null
var sort_kind: SortMode? = null
var lv_num: Int? = null
var lv_pnt: Int? = null
var lv_str: String? = null
var lv_efct_id: Int? = null
var lv_plt_id: Int? = null
var mdl_eqp_ary: String? = null
var mdl_eqp_tm: LocalDateTime? = null
var skn_eqp: Int? = null
var btn_se_eqp: Int? = null
var sld_se_eqp: Int? = null
var chn_sld_se_eqp: Int? = null
var sldr_tch_se_eqp: Int? = null
var vcld_pts: Int? = null
var passwd_stat: PassStat? = null
constructor(ps_result: PreStartResult?) {
this.ps_result = ps_result
}
constructor(
ps_result: PreStartResult?,
accept_idx: Int?,
pd_id: Long,
player_name: String?,
sort_kind: SortMode?,
lv_num: Int?,
lv_pnt: Int?,
lv_str: String?,
lv_efct_id: Int?,
lv_plt_id: Int?,
mdl_eqp_ary: String?,
mdl_eqp_tm: LocalDateTime?,
skn_eqp: Int?,
btn_se_eqp: Int?,
sld_se_eqp: Int?,
chn_sld_se_eqp: Int?,
sldr_tch_se_eqp: Int?,
vcld_pts: Int?,
passwd_stat: PassStat?
) {
this.ps_result = ps_result
this.accept_idx = accept_idx
this.nblss_ltt_stts = -1
this.nblss_ltt_tckt = -1
this.nblss_ltt_is_opn = -1
this.pd_id = pd_id
this.player_name = player_name
this.sort_kind = sort_kind
this.lv_num = lv_num
this.lv_pnt = lv_pnt
this.lv_str = lv_str
this.lv_efct_id = lv_efct_id
this.lv_plt_id = lv_plt_id
this.mdl_eqp_ary = mdl_eqp_ary
this.mdl_eqp_tm = mdl_eqp_tm
this.skn_eqp = skn_eqp
this.btn_se_eqp = btn_se_eqp
this.sld_se_eqp = sld_se_eqp
this.chn_sld_se_eqp = chn_sld_se_eqp
this.sldr_tch_se_eqp = sldr_tch_se_eqp
this.vcld_pts = vcld_pts
this.passwd_stat = passwd_stat
}
}
class PingResponse(ping_b_msg: String?, ping_m_msg: String?) {
var ping_b_msg: String? = URIEncoder.encode("Server Running No other news")
var ping_m_msg: String? = URIEncoder.encode("Network Service Running")
var atnd_lut: String? = null
var fi_lut: String? = null
var ci_lut: String? = null
var qi_lut: String? = null
var pvl_lut: String? = null
var pdcl_lut: String? = null
var pnml_lut: String? = null
var cinml_lut: String? = null
var rwl_lut: String? = null
var bdlol_lut: String? = null
var shp_ctlg_lut: String? = null
var cstmz_itm_ctlg_lut: String? = null
var ngwl_lut: String? = null
var rnk_nv_lut: String? = null
var rnk_ps_lut: String? = null
var bi_lut: String? = null
var cpi_lut: String? = null
var p_std_hc_lut: String? = null
var p_std_i_n_lut: String? = null
var req_inv_cmd_num: String? = null
var req_inv_cmd_prm1: String? = null
var req_inv_cmd_prm2: String? = null
var req_inv_cmd_prm3: String? = null
var req_inv_cmd_prm4: String? = null
var pow_save_flg = false
var nblss_dnt_p = 0
var nblss_ltt_rl_vp = 0
var nblss_ex_ltt_flg = 0
var nblss_dnt_st_tm: String? = null
var nblss_dnt_ed_tm: String? = null
var nblss_ltt_st_tm: String? = null
var nblss_ltt_ed_tm: String? = null
init {
this.ping_b_msg = ping_b_msg
this.ping_m_msg = ping_m_msg
}
}
class SpendCreditResponse(
var cmpgn_rslt: String?,
var cmpgn_rslt_num: Int,
var vcld_pts: Int,
var lv_str: String?,
var lv_efct_id: Int,
var lv_plt_id: Int
)
class StartResponse(
var pd_id: Long,
start_result: Result?,
accept_idx: Int,
start_idx: Int,
player_name: String?,
hp_vol: Int,
btn_se_vol: Boolean,
btn_se_vol2: Int,
sldr_se_vol2: Int,
sort_kind: SortMode?,
lv_num: Int,
lv_pnt: Int,
lv_str: String?,
lv_efct_id: Int,
lv_plt_id: Int,
mdl_eqp_ary: String?,
c_itm_eqp_ary: String?,
ms_itm_flg_ary: String?,
mdl_eqp_tm: LocalDateTime?,
mdl_have: String?,
cstmz_itm_have: String?,
use_pv_mdl_eqp: Boolean,
use_mdl_pri: Boolean,
use_pv_skn_eqp: Boolean,
use_pv_btn_se_eqp: Boolean,
use_pv_sld_se_eqp: Boolean,
use_pv_chn_sld_se_eqp: Boolean,
use_pv_sldr_tch_se_eqp: Boolean,
vcld_pts: Int,
nxt_pv_id: Int,
nxt_dffclty: Difficulty?,
nxt_edtn: Edition?,
cv_cid: String?,
cv_sc: String?,
cv_rr: String?,
cv_bv: String?,
cv_bf: String?,
cnp_cid: Int,
cnp_var: Int,
cnp_rr: ContestBorder?,
cnp_sp: String?,
my_lst_0: String?,
my_lst_1: String?,
my_lst_2: String?,
my_lst_3: String?,
my_lst_4: String?,
dsp_clr_brdr: String?,
dsp_intrm_rnk: Boolean,
dsp_clr_sts: Boolean,
clr_sts: String?,
rgo_sts: Boolean,
my_qst_id: String?,
my_qst_sts: String?,
my_qst_prgrs: String?,
my_qst_et: String?,
p_std_ie_have: String?,
p_std_se_have: String?
) {
var start_result: Result? = Result.SUCCESS
var accept_idx: Int
var start_idx: Int
var player_name: String?
var hp_vol = 100
var btn_se_vol = true
var btn_se_vol2 = 100
var sldr_se_vol2 = 10
var sort_kind: SortMode? = SortMode.RELEASE_DATE
var lv_num: Int
var lv_pnt: Int
var lv_str: String?
var lv_efct_id: Int
var lv_plt_id: Int
var mdl_eqp_ary: String?
var c_itm_eqp_ary: String?
var ms_itm_flg_ary: String?
var mdl_eqp_tm: LocalDateTime? = LocalDateTime.now()
var mdl_have: String? = Const.ALL_HAVE
var cstmz_itm_have: String? = Const.ALL_HAVE
var use_pv_mdl_eqp = false
var use_mdl_pri = false
var use_pv_skn_eqp = false
var use_pv_btn_se_eqp = false
var use_pv_sld_se_eqp = false
var use_pv_chn_sld_se_eqp = false
var use_pv_sldr_tch_se_eqp = false
var vcld_pts = 300
var nxt_pv_id = -1
var nxt_dffclty: Difficulty? = Difficulty.NORMAL
var nxt_edtn: Edition? = Edition.ORIGINAL
// Contest play history, array of 4
var cv_cid: String?
var cv_sc: String?
var cv_rr: String?
var cv_bv: String?
var cv_bf: String?
// Contest now playing id, return -1 if no current playing contest
var cnp_cid = -1
var cnp_var = 0
var cnp_rr: ContestBorder? = ContestBorder.NONE
var cnp_sp: String? = ""
var my_lst_0: String?
var my_lst_1: String?
var my_lst_2: String?
var my_lst_3: String? // Unused
var my_lst_4: String? // Unused
var dsp_clr_brdr: String?
var dsp_intrm_rnk: Boolean
var dsp_clr_sts: Boolean
var clr_sts: String?
var rgo_sts: Boolean
var my_qst_id: String?
var my_qst_sts: String?
var my_qst_prgrs: String?
var my_qst_et: String?
var p_std_ie_have: String? = Const.ALL_NOT_HAVE
var p_std_se_have: String? = Const.ALL_NOT_HAVE
init {
this.start_result = start_result
this.accept_idx = accept_idx
this.start_idx = start_idx
this.player_name = player_name
this.hp_vol = hp_vol
this.btn_se_vol = btn_se_vol
this.btn_se_vol2 = btn_se_vol2
this.sldr_se_vol2 = sldr_se_vol2
this.sort_kind = sort_kind
this.lv_num = lv_num
this.lv_pnt = lv_pnt
this.lv_str = lv_str
this.lv_efct_id = lv_efct_id
this.lv_plt_id = lv_plt_id
this.mdl_eqp_ary = mdl_eqp_ary
this.c_itm_eqp_ary = c_itm_eqp_ary
this.ms_itm_flg_ary = ms_itm_flg_ary
this.mdl_eqp_tm = mdl_eqp_tm
this.mdl_have = mdl_have
this.cstmz_itm_have = cstmz_itm_have
this.use_pv_mdl_eqp = use_pv_mdl_eqp
this.use_mdl_pri = use_mdl_pri
this.use_pv_skn_eqp = use_pv_skn_eqp
this.use_pv_btn_se_eqp = use_pv_btn_se_eqp
this.use_pv_sld_se_eqp = use_pv_sld_se_eqp
this.use_pv_chn_sld_se_eqp = use_pv_chn_sld_se_eqp
this.use_pv_sldr_tch_se_eqp = use_pv_sldr_tch_se_eqp
this.vcld_pts = vcld_pts
this.nxt_pv_id = nxt_pv_id
this.nxt_dffclty = nxt_dffclty
this.nxt_edtn = nxt_edtn
this.cv_cid = cv_cid
this.cv_sc = cv_sc
this.cv_rr = cv_rr
this.cv_bv = cv_bv
this.cv_bf = cv_bf
this.cnp_cid = cnp_cid
this.cnp_var = cnp_var
this.cnp_rr = cnp_rr
this.cnp_sp = cnp_sp
this.my_lst_0 = my_lst_0
this.my_lst_1 = my_lst_1
this.my_lst_2 = my_lst_2
this.my_lst_3 = my_lst_3
this.my_lst_4 = my_lst_4
this.dsp_clr_brdr = dsp_clr_brdr
this.dsp_intrm_rnk = dsp_intrm_rnk
this.dsp_clr_sts = dsp_clr_sts
this.clr_sts = clr_sts
this.rgo_sts = rgo_sts
this.my_qst_id = my_qst_id
this.my_qst_sts = my_qst_sts
this.my_qst_prgrs = my_qst_prgrs
this.my_qst_et = my_qst_et
this.p_std_ie_have = p_std_ie_have
this.p_std_se_have = p_std_se_have
}
}
@@ -0,0 +1,8 @@
package icu.samnyan.aqua.sega.diva.model
/**
* @author samnyan (privateamusement@protonmail.com)
*/
interface Internalizable {
fun toInternal(): String?
}
@@ -0,0 +1,9 @@
package icu.samnyan.aqua.sega.diva.model.common
object Const {
const val ALL_NOT_HAVE: String =
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
const val ALL_HAVE: String =
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
const val NULL_QUEST: String = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
}
@@ -0,0 +1,10 @@
package icu.samnyan.aqua.sega.diva.model.common
class ContestProgress(
var pvId: Int = 0,
var hardness: Int = 0,
var edition: Int = 0,
var stars: Int = 0,
var scores: Int = 0,
var version: Int = 0
)
@@ -0,0 +1,6 @@
package icu.samnyan.aqua.sega.diva.model.common
class LevelInfo(
var levelNumber: Int = 0,
var levelExp: Int = 0,
)
@@ -0,0 +1,146 @@
package icu.samnyan.aqua.sega.diva.model.common
import com.fasterxml.jackson.annotation.JsonValue
enum class SortMode(@get:JsonValue val value: Int) {
COMPLEXITY(0),
NAME(1),
RELEASE_DATE(2),
MY_LIST_A(3),
MY_LIST_B(4),
MY_LIST_C(5);
companion object {
fun fromValue(i: Int): SortMode {
for (sortMode in entries) {
if (sortMode.value == i) return sortMode
}
return RELEASE_DATE
}
}
}
enum class StartMode {
PRE_START,
START,
CARD_PROCEDURE
}
enum class Result(@get:JsonValue val value: Int) {
FAILED(0),
SUCCESS(1)
}
enum class PreStartResult(@get:JsonValue val value: Int) {
SUCCESS(1),
FAILED(0),
CARD_TOO_NEW(-1),
ALREADY_PLAYING(-2),
NEW_REGISTRATION(-3),
CARD_BANNED(-4)
}
enum class PassStat(@get:JsonValue val value: Int) {
MISS(0),
SET(1),
RESET(2),
REISSUE(3)
}
enum class FestaKind(@get:JsonValue val value: Int) {
PINK_FESTA(0),
GREEN_FESTA(1)
}
enum class Edition(@get:JsonValue val value: Int) {
ORIGINAL(0),
EXTRA(1);
companion object {
fun fromValue(i: Int): Edition {
for (edition in entries) {
if (edition.value == i) return edition
}
return ORIGINAL
}
}
}
enum class Difficulty(@get:JsonValue val value: Int) {
UNDEFINED(-1),
EASY(0),
NORMAL(1),
HARD(2),
EXTREME(3);
companion object {
fun fromValue(i: Int): Difficulty {
for (difficulty in entries) {
if (difficulty.value == i) return difficulty
}
return UNDEFINED
}
}
}
enum class ContestStageLimit(@get:JsonValue val value: Int) {
UNLIMITED(0),
LIMITED(1)
}
enum class ContestNormaType(@get:JsonValue val value: Int) {
SCORE(0),
PERCENTAGE(1),
COOL_PERCENTAGE(2)
}
enum class ContestLeague(@get:JsonValue val value: Int) {
BEGINNER(0),
INTERMEDIATE(1),
ADVANCED(2),
PROFESSIONAL(3)
}
enum class ContestBorder(@get:JsonValue val value: Int) {
NONE(-1),
BRONZE(0),
SILVER(1),
GOLD(2)
}
enum class ClearResult(@get:JsonValue val value: Int) {
NO_CLEAR(-1),
MISS_TAKE(0),
CHEAP(1),
STANDARD(2),
GREAT(3),
EXCELLENT(4),
PERFECT(5);
companion object {
fun fromValue(i: Int): ClearResult {
for (clearResult in entries) {
if (clearResult.value == i) return clearResult
}
return NO_CLEAR
}
}
}
enum class ChallengeKind(@get:JsonValue val value: Int) {
UNDEFINED(-1),
CLEAR(0),
GREAT(1),
EXCELLENT(2),
PERFECT(3),
COMPLETED(4);
companion object {
fun fromValue(i: Int): ChallengeKind {
for (challengeKind in entries) {
if (challengeKind.value == i) return challengeKind
}
return UNDEFINED
}
}
}
@@ -0,0 +1,49 @@
package icu.samnyan.aqua.sega.diva.model.common.collection
import ext.csv
import icu.samnyan.aqua.sega.diva.model.Internalizable
class ClearSet {
var clear = 0
var great = 0
var excellent = 0
var perfect = 0
fun addClear() {
this.clear += 1
}
fun addGreat() {
this.clear += 1
this.great += 1
}
fun addExcellent() {
this.clear += 1
this.great += 1
this.excellent += 1
}
fun addPerfect() {
this.clear += 1
this.great += 1
this.excellent += 1
this.perfect += 1
}
}
class ClearTally : Internalizable {
val easy = ClearSet()
val normal = ClearSet()
val hard = ClearSet()
val extreme = ClearSet()
val extraExtreme = ClearSet()
override fun toInternal() = listOf(
easy.clear, easy.great, easy.excellent, easy.perfect,
normal.clear, normal.great, normal.excellent, normal.perfect,
hard.clear, hard.great, hard.excellent, hard.perfect,
extreme.clear, extreme.great, extreme.excellent, extreme.perfect,
extraExtreme.clear, extraExtreme.great, extraExtreme.excellent, extraExtreme.perfect
).csv
}
@@ -0,0 +1,52 @@
package icu.samnyan.aqua.sega.diva.model.common.collection
import icu.samnyan.aqua.sega.diva.model.db.gamedata.Festa
import icu.samnyan.aqua.sega.diva.util.DivaTime.getString
import icu.samnyan.aqua.sega.diva.util.URIEncoder.encode
class FestaCollection {
var firstFesta = Festa()
var secondFesta = Festa()
constructor(festas: MutableList<Festa>) {
if (festas.size >= 2) {
this.firstFesta = festas.get(0)
this.secondFesta = festas.get(1)
} else if (festas.size == 1) {
this.firstFesta = festas.get(0)
}
}
val ids: String
get() = this.firstFesta.id.toString() + "," + this.secondFesta.id
val names: String
get() = encode(this.firstFesta.name) + "," + encode(this.secondFesta.name)
val kinds: String
get() = this.firstFesta.kind.value.toString() + "," + this.secondFesta.kind.value
val diffs: String
get() = this.firstFesta.difficulty.value.toString() + "," + this.secondFesta.difficulty.value
val pvIds: String
get() = this.firstFesta.pvList + "," + this.secondFesta.pvList
val attr: String
get() = this.firstFesta.attributes + "," + this.secondFesta.attributes
val addVps: String
get() = this.firstFesta.addVP.toString() + "," + this.secondFesta.addVP
val vpMultipliers: String
get() = this.firstFesta.vpMultiplier.toString() + "," + this.secondFesta.vpMultiplier
val starts: String
get() = getString(this.firstFesta.start) + "," + getString(this.secondFesta.start)
val ends: String
get() = getString(this.firstFesta.end) + "," + getString(this.secondFesta.end)
val lastUpdateTime: String
get() = getString(if (this.firstFesta.createDate.isBefore(this.secondFesta.createDate)) this.firstFesta.createDate else this.secondFesta.createDate)
}
@@ -0,0 +1,26 @@
package icu.samnyan.aqua.sega.diva.model.common.collection
import icu.samnyan.aqua.sega.diva.model.common.Edition
import icu.samnyan.aqua.sega.diva.model.db.userdata.PlayerPvRecord
class PsRankingCollection(pvId: Int, edition: Edition, list: MutableList<PlayerPvRecord>) {
var first: PlayerPvRecord
var second: PlayerPvRecord
var third: PlayerPvRecord
init {
this.first = PlayerPvRecord(pvId, edition)
this.second = PlayerPvRecord(pvId, edition)
this.third = PlayerPvRecord(pvId, edition)
if (list.size >= 1) {
this.first = list[0]
}
if (list.size >= 2) {
this.second = list.get(1)
}
if (list.size >= 3) {
this.third = list.get(2)
}
}
}
@@ -0,0 +1,108 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import ext.csv
import icu.samnyan.aqua.sega.diva.model.common.ContestLeague
import icu.samnyan.aqua.sega.diva.model.common.ContestNormaType
import icu.samnyan.aqua.sega.diva.util.DivaTime
import icu.samnyan.aqua.sega.diva.util.URIEncoder
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaContest")
@Table(name = "diva_contest")
class Contest : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id = 0
var enable = false
var startTime: LocalDateTime = LocalDateTime.now()
var endTime: LocalDateTime = LocalDateTime.now()
var name: String = ""
var description: String = ""
@Enumerated(EnumType.STRING)
var league: ContestLeague = ContestLeague.BEGINNER
var stars = 0
var minComplexity = 0
var maxComplexity = 0
var stages = 0
var stageLimit: String = ""
@Enumerated(EnumType.STRING)
var normaType: ContestNormaType = ContestNormaType.SCORE
var bronzeBorders = 0
var sliverBorders = 0
var goldBorders = 0
var pvList: String = ""
var pvDiffList: String = ""
var bronzeContestReward: String = ""
var sliverContestReward: String = ""
var goldContestReward: String = ""
var contestEntryReward: String = ""
constructor()
val string: String
get() {
val list = mutableListOf<Any>(
this.id,
DivaTime.format(this.startTime),
DivaTime.format(this.endTime),
URIEncoder.encode(this.name),
URIEncoder.encode(this.description),
this.league.value,
this.stars,
this.stages,
this.stageLimit,
this.normaType.value,
this.bronzeBorders,
this.sliverBorders,
this.goldBorders
)
for (i in 1..20) {
if (pvList.isBlank() || !pvList.contains(":")) {
list.addAll(listOf(-1, -1))
if (i == 1) {
list.add(this.minComplexity)
list.add(this.maxComplexity)
} else {
list.add(-2)
list.add(-2)
}
list.addAll(listOf(-1, -2, "7fffffffffffffffffffffffffffffff"))
} else {
val groups = pvList.split(',').dropLastWhile { it.isEmpty() }.toTypedArray()
if (groups.size < i) {
list.addAll(listOf(-1, -1, -2, -2, -1, -2, "7fffffffffffffffffffffffffffffff"))
} else {
val ids = groups[i - 1].split(':').dropLastWhile { it.isEmpty() }.toTypedArray()
list.add(ids[0])
list.add(ids[1])
if (pvDiffList.isBlank() || !pvDiffList.contains(":")) {
list.add(this.minComplexity)
list.add(this.maxComplexity)
list.add(-1)
} else {
val diffList = pvDiffList.split(',').dropLastWhile { it.isEmpty() }.toTypedArray()
if (diffList.size < i) {
list.add(this.minComplexity)
list.add(this.maxComplexity)
list.add(-1)
} else {
val diff = diffList[i - 1].split(':').dropLastWhile { it.isEmpty() }.toTypedArray()
list.add(diff[1])
list.add(diff[2])
list.add(diff[0])
}
}
list.add(-2)
list.add("7fffffffffffffffffffffffffffffff")
}
}
}
return list.csv
}
}
@@ -0,0 +1,33 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity(name = "DivaPvLevel")
@Table(name = "diva_pv_info_level")
class Difficulty {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
var id: Long = 0
@JsonIgnore
@ManyToOne
@JoinColumn(name = "pv_id")
var pv: Pv = Pv()
var edition = 0
var level: String = ""
var version = 0
var diff: String = ""
constructor(id: Long, pv: Pv, edition: Int, level: String, version: Int, diff: String) {
this.id = id
this.pv = pv
this.edition = edition
this.level = level
this.version = version
this.diff = diff
}
constructor()
}
@@ -0,0 +1,24 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import icu.samnyan.aqua.sega.diva.model.Internalizable
import icu.samnyan.aqua.sega.diva.util.DivaTime
import icu.samnyan.aqua.sega.diva.util.URIEncoder
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaCustomize")
@Table(name = "diva_customize")
class DivaCustomize : Serializable, Internalizable {
@Id
var id = 0
var name: String = ""
var price = 0
var releaseDate: LocalDateTime = LocalDateTime.now()
var endDate: LocalDateTime = LocalDateTime.now()
var sortOrder = 0
override fun toInternal() = "$id,0,${URIEncoder.encode(name)},$price,${DivaTime.format(releaseDate)},${DivaTime.format(endDate)},$sortOrder"
}
@@ -0,0 +1,24 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import icu.samnyan.aqua.sega.diva.model.Internalizable
import icu.samnyan.aqua.sega.diva.util.DivaTime
import icu.samnyan.aqua.sega.diva.util.URIEncoder
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaModule")
@Table(name = "diva_module")
class DivaModule : Serializable, Internalizable {
@Id
var id = 0
var name: String = ""
var price = 0
var releaseDate: LocalDateTime = LocalDateTime.now()
var endDate: LocalDateTime = LocalDateTime.now()
var sortOrder = 0
override fun toInternal() = "$id,0,${URIEncoder.encode(name)},$price,${DivaTime.format(releaseDate)},${DivaTime.format(endDate)},$sortOrder"
}
@@ -0,0 +1,30 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import icu.samnyan.aqua.sega.diva.model.common.Difficulty
import icu.samnyan.aqua.sega.diva.model.common.FestaKind
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaFesta")
@Table(name = "diva_festa")
class Festa : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id = -1
var enable = true
var name: String = "xxx"
@Enumerated(EnumType.STRING)
var kind: FestaKind = FestaKind.PINK_FESTA
@Enumerated(EnumType.STRING)
var difficulty: Difficulty = Difficulty.UNDEFINED
var pvList: String = "ALL"
var attributes: String = "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
var addVP: Int = 0
var vpMultiplier: Int = 1
var start: LocalDateTime = LocalDateTime.of(2005, 1, 1, 0, 0)
var end: LocalDateTime = LocalDateTime.of(2005, 1, 1, 0, 0)
var createDate: LocalDateTime = LocalDateTime.of(2005, 1, 1, 0, 0)
}
@@ -0,0 +1,23 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import jakarta.persistence.*
import java.io.Serializable
@Entity(name = "DivaPvInfo")
@Table(name = "diva_pv_info")
class Pv : Serializable {
@Id
var pvId: Int = 0
var bpm: Int = 0
var songName: String = ""
var songNameEng: String = ""
var songNameReading: String = ""
var arranger: String = ""
var lyrics: String = ""
var music: String = ""
var performerNumber: Int = 0
@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.LAZY, mappedBy = "pv")
@MapKey(name = "diff")
var difficulty: MutableMap<String, Difficulty> = mutableMapOf()
}
@@ -0,0 +1,27 @@
package icu.samnyan.aqua.sega.diva.model.db.gamedata
import icu.samnyan.aqua.sega.diva.model.common.Difficulty
import icu.samnyan.aqua.sega.diva.model.common.Edition
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaPvEntry")
@Table(name = "diva_pv_entry")
class PvEntry : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
var pvId = 0
@Enumerated(EnumType.STRING)
var difficulty: Difficulty = Difficulty.NORMAL
var version = 0
@Enumerated(EnumType.STRING)
var edition: Edition = Edition.ORIGINAL
var demoStart: LocalDateTime = LocalDateTime.now()
var demoEnd: LocalDateTime = LocalDateTime.now()
var playableStart: LocalDateTime = LocalDateTime.now()
var playableEnd: LocalDateTime = LocalDateTime.now()
}
@@ -0,0 +1,64 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import icu.samnyan.aqua.sega.diva.model.common.StartMode
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaGameSession")
@Table(name = "diva_game_session")
class GameSession : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
var acceptId = 0
@OneToOne
@JoinColumn(name = "pd_id", unique = true)
var pdId: PlayerProfile = PlayerProfile()
@Enumerated(EnumType.STRING)
var startMode: StartMode = StartMode.START
var startTime: LocalDateTime = LocalDateTime.now()
var lastUpdateTime: LocalDateTime = LocalDateTime.now()
var stageIndex: Int = 0
var stageResultIndex: Int = 0
var lastPvId: Int = 0
var levelNumber: Int = 0
var levelExp: Int = 0
var oldLevelNumber: Int = 0
var oldLevelExp: Int = 0
var vp: Int = 0
constructor(
acceptId: Int,
pdId: PlayerProfile,
startMode: StartMode,
startTime: LocalDateTime,
lastUpdateTime: LocalDateTime,
stageIndex: Int,
stageResultIndex: Int,
lastPvId: Int,
levelNumber: Int,
levelExp: Int,
oldLevelNumber: Int,
oldLevelExp: Int,
vp: Int
) {
this.acceptId = acceptId
this.pdId = pdId
this.startMode = startMode
this.startTime = startTime
this.lastUpdateTime = lastUpdateTime
this.stageIndex = stageIndex
this.stageResultIndex = stageResultIndex
this.lastPvId = lastPvId
this.levelNumber = levelNumber
this.levelExp = levelExp
this.oldLevelNumber = oldLevelNumber
this.oldLevelExp = oldLevelExp
this.vp = vp
}
constructor()
}
@@ -0,0 +1,152 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import icu.samnyan.aqua.sega.diva.model.common.ChallengeKind
import icu.samnyan.aqua.sega.diva.model.common.ClearResult
import icu.samnyan.aqua.sega.diva.model.common.Difficulty
import icu.samnyan.aqua.sega.diva.model.common.Edition
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaPlayLog")
@Table(name = "diva_play_log")
class PlayLog : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
@JsonIgnore
var pdId: PlayerProfile = PlayerProfile()
var pvId = 0
@Enumerated(EnumType.STRING)
var difficulty: Difficulty = Difficulty.NORMAL
@Enumerated(EnumType.STRING)
var edition: Edition = Edition.ORIGINAL
var scriptVer = 0
var score = 0
@Enumerated(EnumType.STRING)
var challengeKind: ChallengeKind = ChallengeKind.UNDEFINED
var challengeResult = 0
@Enumerated(EnumType.STRING)
var clearResult: ClearResult = ClearResult.NO_CLEAR
var vp = 0
var coolCount = 0
var coolPercent = 0
var fineCount = 0
var finePercent = 0
var safeCount = 0
var safePercent = 0
var sadCount = 0
var sadPercent = 0
var wrongCount = 0
var wrongPercent = 0
var maxCombo = 0
var chanceTime = 0
var holdScore = 0
var attainPoint = 0
var skinId = 0
var buttonSe = 0
var buttonSeVol = 0
var sliderSe = 0
var ChainSlideSe = 0
var SliderTouchSe = 0
var modules: String = ""
var stageCompletion = 0
var slideScore = 0
var isVocalChange = 0
var customizeItems: String = ""
// String customizeItemFlags;
var rhythmGameOptions: String = ""
var screenShotCount = -1
var dateTime: LocalDateTime = LocalDateTime.now()
constructor(
pdId: PlayerProfile,
pvId: Int,
difficulty: Difficulty,
edition: Edition,
scriptVer: Int,
score: Int,
challengeKind: ChallengeKind,
challengeResult: Int,
clearResult: ClearResult,
vp: Int,
coolCount: Int,
coolPercent: Int,
fineCount: Int,
finePercent: Int,
safeCount: Int,
safePercent: Int,
sadCount: Int,
sadPercent: Int,
wrongCount: Int,
wrongPercent: Int,
maxCombo: Int,
chanceTime: Int,
holdScore: Int,
attainPoint: Int,
skinId: Int,
buttonSe: Int,
buttonSeVol: Int,
sliderSe: Int,
chainSlideSe: Int,
sliderTouchSe: Int,
modules: String,
stageCompletion: Int,
slideScore: Int,
isVocalChange: Int,
customizeItems: String,
rhythmGameOptions: String,
screenShotCount: Int,
dateTime: LocalDateTime
) {
this.pdId = pdId
this.pvId = pvId
this.difficulty = difficulty
this.edition = edition
this.scriptVer = scriptVer
this.score = score
this.challengeKind = challengeKind
this.challengeResult = challengeResult
this.clearResult = clearResult
this.vp = vp
this.coolCount = coolCount
this.coolPercent = coolPercent
this.fineCount = fineCount
this.finePercent = finePercent
this.safeCount = safeCount
this.safePercent = safePercent
this.sadCount = sadCount
this.sadPercent = sadPercent
this.wrongCount = wrongCount
this.wrongPercent = wrongPercent
this.maxCombo = maxCombo
this.chanceTime = chanceTime
this.holdScore = holdScore
this.attainPoint = attainPoint
this.skinId = skinId
this.buttonSe = buttonSe
this.buttonSeVol = buttonSeVol
this.sliderSe = sliderSe
ChainSlideSe = chainSlideSe
SliderTouchSe = sliderTouchSe
this.modules = modules
this.stageCompletion = stageCompletion
this.slideScore = slideScore
this.isVocalChange = isVocalChange
this.customizeItems = customizeItems
this.rhythmGameOptions = rhythmGameOptions
this.screenShotCount = screenShotCount
this.dateTime = dateTime
}
constructor()
}
@@ -0,0 +1,35 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import icu.samnyan.aqua.sega.diva.model.common.ContestBorder
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaPlayerContest")
@Table(name = "diva_player_contest", uniqueConstraints = [UniqueConstraint(columnNames = ["pd_id", "contest_id"])])
class PlayerContest : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
var pdId: PlayerProfile = PlayerProfile()
@Column(name = "contest_id")
var contestId = 0
var startCount = 0
@Enumerated(EnumType.STRING)
var resultRank: ContestBorder = ContestBorder.NONE
var bestValue = -1
var flag = -1
var lastUpdateTime: LocalDateTime = LocalDateTime.now()
constructor(pdId: PlayerProfile, contestId: Int) {
this.pdId = pdId
this.contestId = contestId
}
constructor()
}
@@ -0,0 +1,26 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import jakarta.persistence.*
import java.io.Serializable
@Entity(name = "DivaPlayerCustomize")
@Table(name = "diva_player_customize", uniqueConstraints = [UniqueConstraint(columnNames = ["pd_id", "customize_id"])])
class PlayerCustomize : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
var pdId: PlayerProfile = PlayerProfile()
@Column(name = "customize_id")
var customizeId = 0
constructor(profile: PlayerProfile, customizeId: Int) {
this.pdId = profile
this.customizeId = customizeId
}
constructor()
}
@@ -0,0 +1,30 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
import java.io.Serializable
@Entity(name = "DivaPlayerInventory")
@Table(name = "diva_player_inventory", uniqueConstraints = [UniqueConstraint(columnNames = ["pd_id", "value", "type"])])
class PlayerInventory : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
@JsonIgnore
var pdId: PlayerProfile = PlayerProfile()
var value: String = ""
// Type: (1: Skin, 2: Call sign plate, 3: Call sign)
var type: String = ""
constructor(pdId: PlayerProfile, value: String, type: String) {
this.pdId = pdId
this.value = value
this.type = type
}
constructor()
}
@@ -0,0 +1,26 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import jakarta.persistence.*
import java.io.Serializable
@Entity(name = "DivaPlayerModule")
@Table(name = "diva_player_module", uniqueConstraints = [UniqueConstraint(columnNames = ["pd_id", "module_id"])])
class PlayerModule : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
var pdId: PlayerProfile = PlayerProfile()
@Column(name = "module_id")
var moduleId = 0
constructor(profile: PlayerProfile, moduleId: Int) {
this.pdId = profile
this.moduleId = moduleId
}
constructor()
}
@@ -0,0 +1,225 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import icu.samnyan.aqua.sega.diva.model.common.*
import icu.samnyan.aqua.sega.diva.util.DivaStringUtils.getDummyString
import jakarta.persistence.*
import java.io.Serializable
import java.time.LocalDateTime
@Entity(name = "DivaPlayerProfile")
@Table(name = "diva_player_profile")
class PlayerProfile : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@Column(unique = true)
var pdId: Long = 0
var playerName: String = "xxx"
var vocaloidPoints = 300
var level = 1
var levelExp = 0
var levelTitle: String = "xxx"
var plateId = -1
var plateEffectId = -1
@Enumerated(EnumType.STRING)
var passwordStatus: PassStat = PassStat.MISS
@JsonIgnore
var password: String = "**********"
/**
* Game play customize
*/
var preferPerPvModule = true
var preferCommonModule = false
var usePerPvSkin = false
var usePerPvButtonSe = false
var usePerPvSliderSe = false
var usePerPvChainSliderSe = false
var usePerPvTouchSliderSe = false
var commonModule: String = "-999,-999,-999"
var commonCustomizeItems: String = "-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999"
var commonModuleSetTime: LocalDateTime = LocalDateTime.now()
var moduleSelectItemFlag: String = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
// -1 is disable
var commonSkin = -1
/**
* Sound Setting
*/
var headphoneVolume = 100
var buttonSeOn = true
var buttonSeVolume = 100
var sliderSeVolume = 100
var buttonSe = -1
var chainSlideSe = -1
var slideSe = -1
var sliderTouchSe = -1
/**
* View Setting
*/
@Enumerated(EnumType.STRING)
var sortMode: SortMode = SortMode.RELEASE_DATE
@JsonIgnore
var nextPvId = -1
@JsonIgnore
@Enumerated(EnumType.STRING)
var nextDifficulty: Difficulty = Difficulty.NORMAL
@JsonIgnore
@Enumerated(EnumType.STRING)
var nextEdition: Edition = Edition.ORIGINAL
var showInterimRanking = true
var showClearStatus = true
var showGreatBorder = true
var showExcellentBorder = true
var showRivalBorder = true
var showRgoSetting = true
@JsonIgnore
var contestNowPlayingEnable = false
@JsonIgnore
var contestNowPlayingId = -1
// Contest now playing progress
@JsonIgnore
var contestNowPlayingValue = -1
@JsonIgnore
@Enumerated(EnumType.STRING)
var contestNowPlayingResultRank: ContestBorder = ContestBorder.NONE
// This store the current progress of contest
@JsonIgnore
var contestNowPlayingSpecifier: String = ""
/**
* MyList, comma separate string
*/
var myList0: String = getDummyString("-1", 40)
var myList1: String = getDummyString("-1", 40)
var myList2: String = getDummyString("-1", 40)
@JsonIgnore
var rivalPdId: Long = -1
constructor(pdId: Long, playerName: String) {
this.pdId = pdId
this.playerName = playerName
}
constructor(
id: Long,
pdId: Long,
playerName: String,
vocaloidPoints: Int,
level: Int,
levelExp: Int,
levelTitle: String,
plateId: Int,
plateEffectId: Int,
passwordStatus: PassStat,
password: String,
preferPerPvModule: Boolean,
preferCommonModule: Boolean,
usePerPvSkin: Boolean,
usePerPvButtonSe: Boolean,
usePerPvSliderSe: Boolean,
usePerPvChainSliderSe: Boolean,
usePerPvTouchSliderSe: Boolean,
commonModule: String,
commonCustomizeItems: String,
commonModuleSetTime: LocalDateTime,
moduleSelectItemFlag: String,
commonSkin: Int,
headphoneVolume: Int,
buttonSeOn: Boolean,
buttonSeVolume: Int,
sliderSeVolume: Int,
buttonSe: Int,
chainSlideSe: Int,
slideSe: Int,
sliderTouchSe: Int,
sortMode: SortMode,
nextPvId: Int,
nextDifficulty: Difficulty,
nextEdition: Edition,
showInterimRanking: Boolean,
showClearStatus: Boolean,
showGreatBorder: Boolean,
showExcellentBorder: Boolean,
showRivalBorder: Boolean,
showRgoSetting: Boolean,
contestNowPlayingEnable: Boolean,
contestNowPlayingId: Int,
contestNowPlayingValue: Int,
contestNowPlayingResultRank: ContestBorder,
contestNowPlayingSpecifier: String,
myList0: String,
myList1: String,
myList2: String,
rivalPdId: Long
) {
this.id = id
this.pdId = pdId
this.playerName = playerName
this.vocaloidPoints = vocaloidPoints
this.level = level
this.levelExp = levelExp
this.levelTitle = levelTitle
this.plateId = plateId
this.plateEffectId = plateEffectId
this.passwordStatus = passwordStatus
this.password = password
this.preferPerPvModule = preferPerPvModule
this.preferCommonModule = preferCommonModule
this.usePerPvSkin = usePerPvSkin
this.usePerPvButtonSe = usePerPvButtonSe
this.usePerPvSliderSe = usePerPvSliderSe
this.usePerPvChainSliderSe = usePerPvChainSliderSe
this.usePerPvTouchSliderSe = usePerPvTouchSliderSe
this.commonModule = commonModule
this.commonCustomizeItems = commonCustomizeItems
this.commonModuleSetTime = commonModuleSetTime
this.moduleSelectItemFlag = moduleSelectItemFlag
this.commonSkin = commonSkin
this.headphoneVolume = headphoneVolume
this.buttonSeOn = buttonSeOn
this.buttonSeVolume = buttonSeVolume
this.sliderSeVolume = sliderSeVolume
this.buttonSe = buttonSe
this.chainSlideSe = chainSlideSe
this.slideSe = slideSe
this.sliderTouchSe = sliderTouchSe
this.sortMode = sortMode
this.nextPvId = nextPvId
this.nextDifficulty = nextDifficulty
this.nextEdition = nextEdition
this.showInterimRanking = showInterimRanking
this.showClearStatus = showClearStatus
this.showGreatBorder = showGreatBorder
this.showExcellentBorder = showExcellentBorder
this.showRivalBorder = showRivalBorder
this.showRgoSetting = showRgoSetting
this.contestNowPlayingEnable = contestNowPlayingEnable
this.contestNowPlayingId = contestNowPlayingId
this.contestNowPlayingValue = contestNowPlayingValue
this.contestNowPlayingResultRank = contestNowPlayingResultRank
this.contestNowPlayingSpecifier = contestNowPlayingSpecifier
this.myList0 = myList0
this.myList1 = myList1
this.myList2 = myList2
this.rivalPdId = rivalPdId
}
constructor()
}
@@ -0,0 +1,36 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
import java.io.Serializable
@Entity(name = "DivaPlayerPvCustomize")
@Table(name = "diva_player_pv_customize", uniqueConstraints = [UniqueConstraint(columnNames = ["pd_id", "pv_id"])])
class PlayerPvCustomize : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
@JsonIgnore
var pdId: PlayerProfile = PlayerProfile()
@Column(name = "pv_id")
var pvId = -1
var module: String = "-999,-999,-999"
var customize: String = "-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999"
var customizeFlag: String = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
var skin = -1
var buttonSe = -1
var slideSe = -1
var chainSlideSe = -1
var sliderTouchSe = -1
constructor(pdId: PlayerProfile, pvId: Int) {
this.pdId = pdId
this.pvId = pvId
}
constructor()
}
@@ -0,0 +1,58 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import icu.samnyan.aqua.sega.diva.model.common.ChallengeKind
import icu.samnyan.aqua.sega.diva.model.common.ClearResult
import icu.samnyan.aqua.sega.diva.model.common.Difficulty
import icu.samnyan.aqua.sega.diva.model.common.Edition
import jakarta.persistence.*
import java.io.Serializable
@Entity(name = "DivaPlayerPvRecord")
@Table(
name = "diva_player_pv_record",
uniqueConstraints = [UniqueConstraint(columnNames = ["pd_id", "pv_id", "edition", "difficulty"])]
)
class PlayerPvRecord : Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
@JsonIgnore
var pdId: PlayerProfile = PlayerProfile()
@Column(name = "pv_id")
var pvId = -1
@Enumerated(EnumType.STRING)
var edition: Edition = Edition.ORIGINAL
@Enumerated(EnumType.STRING)
var difficulty: Difficulty = Difficulty.NORMAL
@Enumerated(EnumType.STRING)
var result: ClearResult = ClearResult.NO_CLEAR
var maxScore = -1
var maxAttain = -1
@Enumerated(EnumType.STRING)
var challengeKind: ChallengeKind = ChallengeKind.UNDEFINED
var rgoPurchased: String = "0,0,0"
var rgoPlayed: String = "0,0,0"
constructor(pvId: Int, edition: Edition) {
this.pvId = pvId
this.edition = edition
}
constructor(pdId: PlayerProfile, pvId: Int, edition: Edition, difficulty: Difficulty) {
this.pdId = pdId
this.pvId = pvId
this.edition = edition
this.difficulty = difficulty
}
constructor()
}
@@ -0,0 +1,29 @@
package icu.samnyan.aqua.sega.diva.model.db.userdata
import jakarta.persistence.*
@Entity(name = "DivaPlayerScreenShot")
@Table(name = "diva_player_screen_shot")
class PlayerScreenShot {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@ManyToOne
@JoinColumn(name = "pd_id")
var pdId: PlayerProfile = PlayerProfile()
var pvId: Long = 0
var fileName: String = ""
var moduleList: String = ""
var customizeList: String = ""
constructor(pdId: PlayerProfile, fileName: String, pvId: Long, moduleList: String, customizeList: String) {
this.pdId = pdId
this.fileName = fileName
this.pvId = pvId
this.moduleList = moduleList
this.customizeList = customizeList
}
constructor()
}
@@ -0,0 +1,35 @@
package icu.samnyan.aqua.sega.diva.util
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
object DivaStringUtils {
@JvmStatic
fun getDummyString(content: String, length: Int) = ",".repeat(length).removeSuffix(",")
}
object DivaTime {
val now get() = getString(LocalDateTime.now())
@JvmStatic
fun getString(time: LocalDateTime) = URIEncoder.encode(format(time))
@JvmStatic
fun format(time: LocalDateTime) = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.0").format(time)
}
class DivaDateTimeSerializer(t: Class<LocalDateTime>? = null) : StdSerializer<LocalDateTime>(t) {
override fun serialize(value: LocalDateTime, gen: JsonGenerator, provider: SerializerProvider) {
gen.writeString(DivaTime.getString(value))
}
}
object URIEncoder {
@JvmStatic
fun encode(str: String) = URLEncoder.encode(str, StandardCharsets.UTF_8).replace("\\+".toRegex(), "%20")
}
@@ -0,0 +1,12 @@
package icu.samnyan.aqua.sega.general
import ext.ls
import jakarta.persistence.AttributeConverter
import jakarta.persistence.Converter
@Converter
class IntegerListConverter : AttributeConverter<List<Int>, String> {
override fun convertToDatabaseColumn(lst: List<Int>?) = lst?.joinToString(";") ?: ""
override fun convertToEntityAttribute(str: String?) = if (str.isNullOrBlank()) ls() else
str.split(';').map { it.toInt() }
}
@@ -0,0 +1,85 @@
package icu.samnyan.aqua.sega.general.model
import com.fasterxml.jackson.annotation.JsonIgnore
import icu.samnyan.aqua.net.db.AquaNetUser
import jakarta.persistence.*
import java.time.LocalDateTime
enum class CardStatus {
NORMAL,
// Reserved for future use
NORMAL_MIGRATED_TO_MINATO_AND_THEN_CLEARED,
NORMAL_RESERVED_2,
NORMAL_RESERVED_3,
NORMAL_RESERVED_4,
NORMAL_RESERVED_5,
NORMAL_RESERVED_6,
NORMAL_RESERVED_7,
NORMAL_RESERVED_8,
NORMAL_RESERVED_9,
// Deleted statuses
OVERWRITTEN,
DELETED,
MIGRATED_TO_MINATO;
/**
* Returns true if card status is in any NORMAL state
*/
val isNormal get() = this.ordinal in NORMAL.ordinal..NORMAL_RESERVED_9.ordinal
}
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Entity(name = "SegaCard")
@Table(name = "sega_card")
class Card(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
val id: Long = 0,
// An external id (THIS IS UINT32!!!!)
// IDK why samnyan used Long, Games cannot parse the full int64 value and will cast it to uint32
@Column(name = "ext_id", unique = true, nullable = false)
@JsonIgnore // Sensitive information
var extId: Long = 0,
// Access Code
@Column(unique = true, nullable = false)
var luid: String = "",
@Column(name = "register_time", nullable = false)
var registerTime: LocalDateTime = LocalDateTime.now(),
@Column(name = "access_time", nullable = false)
var accessTime: LocalDateTime = registerTime,
// Defines the AquaNet user that this card is bound to
@ManyToOne
@JoinColumn(name = "net_user_id")
@JsonIgnore
var aquaUser: AquaNetUser? = null,
// Whether the card is a ghost card
var isGhost: Boolean = false,
// Unfortunately some people decide to cheat and upload all perfect scores :(
// This will not affect gameplay behavior, but will hide the user from ranking
var rankingBanned: Boolean = false,
@Enumerated(EnumType.ORDINAL)
var status: CardStatus = CardStatus.NORMAL,
) {
@Suppress("unused") // Used by serialization
val isLinked get() = aquaUser != null
/**
* Returns ghost card if this card is a ghost card, otherwise returns this card
*/
fun maybeGhost() = aquaUser?.ghostCard ?: this
}
fun Card.sensitiveInfo() = mapOf("id" to id, "extId" to extId, "luid" to luid)
@@ -0,0 +1,22 @@
package icu.samnyan.aqua.sega.general.model
import icu.samnyan.aqua.net.games.BaseEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
@Entity
@Table(name = "sega_card_timestamp")
class CardTimestamp : BaseEntity() {
@Column(name = "card_id")
var cardId: Long = 0
@Column(name = "game_id")
var gameId: String = ""
@Column(name = "created_at")
var createdAt: Long = 0
@Column(name = "updated_at")
var updatedAt: Long = 0
}
@@ -0,0 +1,27 @@
package icu.samnyan.aqua.sega.general.model
import jakarta.persistence.*
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Entity(name = "ServerPropertyEntry")
@Table(name = "property")
class PropertyEntry {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long = 0
@Column(unique = true)
var propertyKey: String = ""
@Column(columnDefinition = "TEXT")
var propertyValue: String = ""
constructor(propertyKey: String, propertyValue: String) {
this.propertyKey = propertyKey
this.propertyValue = propertyValue
}
constructor()
}
@@ -0,0 +1,10 @@
package icu.samnyan.aqua.sega.general.model
class UserRecentRating(
val musicId: Int = 0,
val difficultId: Int = 0,
val romVersionCode: String = "",
val score: Int = 0
) {
override fun toString() = "$musicId:$difficultId:$score"
}
@@ -0,0 +1,32 @@
package icu.samnyan.aqua.sega.maimai2.model
import com.fasterxml.jackson.annotation.JsonIgnore
class Mai2GameEvent {
@JsonIgnore(false)
var id = 0L
var type = 0
var startDate: String? = "2019-01-01 00:00:00.000000"
var endDate: String? = "2099-01-01 00:00:00.000000"
@JsonIgnore
var enable = false
var disableArea = ""
}
class Mai2GameCharge {
var chargeId = 0L
var orderId = 0L
var price = 0
var startDate: String? = "2019-01-01 00:00:00.000000"
var endDate: String? = "2099-01-01 00:00:00.000000"
}
class Mai2GameSellingCard {
var cardId = 0L
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"
}
@@ -0,0 +1,13 @@
package icu.samnyan.aqua.sega.maimai2.model
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserRate
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserUdemae
class UserRating {
var rating = 0
var ratingList: List<Mai2UserRate> = emptyList()
var newRatingList: List<Mai2UserRate> = emptyList()
var nextRatingList: List<Mai2UserRate> = emptyList()
var nextNewRatingList: List<Mai2UserRate> = emptyList()
var udemae: Mai2UserUdemae = Mai2UserUdemae()
}
@@ -0,0 +1,12 @@
package icu.samnyan.aqua.sega.maimai2.model
class UserRivalMusic(
var musicId: Int,
var userRivalMusicDetailList: MutableList<UserRivalMusicDetail> = mutableListOf()
)
class UserRivalMusicDetail(
var level: Int,
var achievement: Int,
var deluxscoreMax: Int
)
@@ -0,0 +1,53 @@
package icu.samnyan.aqua.sega.maimai2.model.request
import icu.samnyan.aqua.sega.maimai2.model.UserRating
import icu.samnyan.aqua.sega.maimai2.model.userdata.*
class Mai2UpsertUserAll(
var userId: Long,
var upsertUserAll: Mai2UserAll
)
class Mai2UserAll {
var userData: List<Mai2UserDetail> = emptyList()
var userOption: List<Mai2UserOption>? = null
var userExtend: List<Mai2UserExtend>? = null
var userCharacterList: List<Mai2UserCharacter>? = null
var userGhost: List<Mai2UserGhost>? = null
var userMapList: List<Mai2UserMap>? = null
var userLoginBonusList: List<Mai2UserLoginBonus>? = null
var userRatingList: List<UserRating>? = null
var userItemList: List<Mai2UserItem>? = null
var userMusicDetailList: List<Mai2UserMusicDetail>? = null
var userCourseList: List<Mai2UserCourse>? = null
var userFriendSeasonRankingList: List<Mai2UserFriendSeasonRanking>? = null
var userChargeList: List<Mai2UserCharge>? = null
var userFavoriteList: List<Mai2UserFavorite>? = null
var userActivityList: List<Mai2UserActivity>? = null
var userGamePlaylogList: List<Map<String, Any>>? = null
var userFavoritemusicList: List<Mai2UserFavoriteItem>? = null
var userKaleidxScopeList: List<Mai2UserKaleidx>? = null
var userIntimateList: List<Mai2UserIntimate>? = null
var isNewCharacterList: String? = null
var isNewMapList: String? = null
var isNewLoginBonusList: String? = null
var isNewItemList: String? = null
var isNewMusicDetailList: String? = null
var isNewCourseList: String? = null
var isNewFavoriteList: String? = null
var isNewFriendSeasonRankingList: String? = null
var isNewFavoritemusicList: String? = null
var isNewKaleidxScopeList: String? = null
}
class Mai2UserFavoriteItem {
var orderId = 0
var id = 0
}
class Mai2UserActivity {
var playList: List<Mai2UserAct> = emptyList()
var musicList: List<Mai2UserAct> = emptyList()
}
@@ -0,0 +1,25 @@
package icu.samnyan.aqua.sega.maimai2.model.request
class Mai2UserPhoto {
var orderId = 0
var userId: Long = 0
var divNumber = 0
var divLength = 0
var divData: String? = null
var placeId = 0
var clientId: String? = null
var uploadDate: String? = null
var playlogId: Long = 0
var trackNo = 0
}
class Mai2UserPortrait {
var userId: Long = 0
var divNumber = 0
var divLength = 0
var divData: String? = null
var placeId = 0
var clientId: String = ""
var uploadDate: String = "1970-01-01 09:00:00.0"
var fileName: String = "portrait.jpg"
}
@@ -0,0 +1,162 @@
package icu.samnyan.aqua.sega.maimai2.model.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.net.games.IUserData
import icu.samnyan.aqua.sega.general.IntegerListConverter
import icu.samnyan.aqua.sega.general.model.Card
import icu.samnyan.aqua.sega.util.AccessCodeSerializer
import jakarta.persistence.*
@Entity(name = "Maimai2UserData")
@Table(name = "maimai2_user_detail")
class Mai2UserDetail(
@get:JsonSerialize(using = AccessCodeSerializer::class)
@get:JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "aime_card_id", unique = true)
override var card: Card? = null,
override var userName: String = "",
@JsonInclude
@Transient
var friendCode: String = "",
var isNetMember: Int = 1,
@JsonInclude
@Transient
var nameplateId: Int = 0,
var iconId: Int = 0,
@JsonInclude
@Transient
var trophyId: Int = 0,
var plateId: Int = 0,
var titleId: Int = 0,
var partnerId: Int = 0,
var frameId: Int = 0,
var selectMapId: Int = 0,
var totalAwake: Int = 0,
var gradeRating: Int = 0,
var musicRating: Int = 0,
override var playerRating: Int = 0,
override var highestRating: Int = 0,
var gradeRank: Int = 0,
var classRank: Int = 0,
var courseRank: Int = 0,
@Convert(converter = IntegerListConverter::class)
var charaSlot: List<Int>? = null, // Entries: 5
@Convert(converter = IntegerListConverter::class)
var charaLockSlot: List<Int>? = null, // Entries: 5
var contentBit: Long = 0,
var playCount: Int = 0,
var eventWatchedDate: String = "",
var lastGameId: String = "",
override var lastRomVersion: String = "",
var lastDataVersion: String = "",
var lastLoginDate: String = "",
override var lastPlayDate: String = "",
var lastPlayCredit: Int = 0,
var lastPlayMode: Int = 0,
var lastPlaceId: Int = 0,
var lastPlaceName: String = "",
var lastAllNetId: Int = 0,
var lastRegionId: Int = 0,
var lastRegionName: String = "",
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
override var lastClientId: String = "",
var lastCountryCode: String = "",
var lastSelectEMoney: Int = 0,
var lastSelectTicket: Int = 0,
var lastSelectCourse: Int = 0,
var lastCountCourse: Int = 0,
var firstGameId: String = "",
var firstRomVersion: String = "",
var firstDataVersion: String = "",
override var firstPlayDate: String = "",
var compatibleCmVersion: String = "",
var dailyBonusDate: String = "",
var dailyCourseBonusDate: String = "",
var lastPairLoginDate: String = "",
var lastTrialPlayDate: String = "",
var playVsCount: Int = 0,
var playSyncCount: Int = 0,
var winCount: Int = 0,
var helpCount: Int = 0,
var comboCount: Int = 0,
var totalDeluxscore: Long = 0,
var totalBasicDeluxscore: Long = 0,
var totalAdvancedDeluxscore: Long = 0,
var totalExpertDeluxscore: Long = 0,
var totalMasterDeluxscore: Long = 0,
var totalReMasterDeluxscore: Long = 0,
@JsonInclude
@Transient
var totalHiscore: Long = 0,
@JsonInclude
@Transient
var totalBasicHighscore: Long = 0,
@JsonInclude
@Transient
var totalAdvancedHighscore: Long = 0,
@JsonInclude
@Transient
var totalExpertHighscore: Long = 0,
@JsonInclude
@Transient
var totalMasterHighscore: Long = 0,
@JsonInclude
@Transient
var totalReMasterHighscore: Long = 0,
var totalSync: Int = 0,
var totalBasicSync: Int = 0,
var totalAdvancedSync: Int = 0,
var totalExpertSync: Int = 0,
var totalMasterSync: Int = 0,
var totalReMasterSync: Int = 0,
var totalAchievement: Long = 0,
var totalBasicAchievement: Long = 0,
var totalAdvancedAchievement: Long = 0,
var totalExpertAchievement: Long = 0,
var totalMasterAchievement: Long = 0,
var totalReMasterAchievement: Long = 0,
var playerOldRating: Long = 0,
var playerNewRating: Long = 0,
var banState: Int = 0,
var dateTime: Long = 0,
@JsonInclude
@Transient
var cmLastEmoneyBrand: Int = 2,
@JsonInclude
@Transient
var cmLastEmoneyCredit: Int = 69,
var mapStock: Int = 0,
// MaiMile
var point: Int = 0,
var totalPoint: Int = 0,
// TODO: Make these non-nullable with default value
var currentPlayCount: Int? = 0,
var renameCredit: Int? = 0
) : BaseEntity(), IUserData {
@get:JsonIgnore
override val totalScore: Long
get() = totalDeluxscore
}
@@ -0,0 +1,565 @@
@file:Suppress("unused")
package icu.samnyan.aqua.sega.maimai2.model.userdata
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import ext.toJson
import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.net.games.IGenericGamePlaylog
import icu.samnyan.aqua.net.games.IGenericUserMusic
import icu.samnyan.aqua.net.games.IUserEntity
import icu.samnyan.aqua.sega.general.IntegerListConverter
import jakarta.persistence.*
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@MappedSuperclass
open class Mai2UserEntity : BaseEntity(), IUserEntity<Mai2UserDetail> {
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id")
override var user: Mai2UserDetail = Mai2UserDetail()
}
@Table(name = "maimai2_user_npc_encount")
@Entity
class Mai2MapEncountNpc : Mai2UserEntity() {
var npcId = 0
var musicId = 0
@JsonIgnore
@ManyToOne(cascade = [CascadeType.ALL])
@JoinColumn(name = "extend_id")
var userExtend: Mai2UserExtend? = null
}
@Table(name = "maimai2_user_activity")
@Entity
class Mai2UserAct : Mai2UserEntity() {
var kind = 0
@JsonProperty("id")
var activityId = 0
var sortNumber: Long = 0
var param1 = 0
var param2 = 0
var param3 = 0
var param4 = 0
}
@Table(name = "maimai2_user_card")
@Entity
class Mai2UserCard : Mai2UserEntity() {
var cardId: Int = 0
var cardTypeId: Int = 0
var charaId: Int = 0
var mapId: Int = 0
var startDate: String = ""
var endDate: String = ""
}
@Table(name = "maimai2_user_character")
@Entity
class Mai2UserCharacter : Mai2UserEntity() {
var characterId = 0
@JsonInclude
@Transient
var point = 0
@JsonInclude
@Transient
var count = 0
var level = 0
@JsonInclude
@Transient
var nextAwake = 0
@JsonInclude
@Transient
var nextAwakePercent = 0
@JsonInclude
@Transient
var favorite = false
var awakening = 0
var useCount = 0
}
@Table(name = "maimai2_user_charge", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "charge_id"])])
@Entity
class Mai2UserCharge : Mai2UserEntity() {
@Column(name = "charge_id")
var chargeId = 0
var stock = 0
var purchaseDate: String = ""
var validDate: String = ""
}
@Table(name = "maimai2_user_course")
@Entity
class Mai2UserCourse : Mai2UserEntity() {
var courseId = 0
var isLastClear = false
var totalRestlife = 0
var totalAchievement = 0
var totalDeluxscore = 0
var playCount = 0
var clearDate: String = ""
var lastPlayDate: String = ""
var bestAchievement = 0
var bestAchievementDate: String = ""
var bestDeluxscore = 0
var bestDeluxscoreDate: String = ""
}
@Table(name = "maimai2_user_extend")
@Entity
class Mai2UserExtend : Mai2UserEntity() {
var selectMusicId = 0
var selectDifficultyId = 0
var categoryIndex = 0
var musicIndex = 0
var extraFlag = 0
var selectScoreType = 0
var extendContentBit: Long = 0
var isPhotoAgree = false
var isGotoCodeRead = false
var selectResultDetails = false
var sortCategorySetting = 0 //enum SortTabID
var sortMusicSetting = 0 //enum SortMusicID
var playStatusSetting = 0 //enum PlaystatusTabID
var selectResultScoreViewType = 0
@Convert(converter = IntegerListConverter::class)
var selectedCardList: List<Int> = ArrayList()
@OneToMany(mappedBy = "userExtend", targetEntity = Mai2MapEncountNpc::class)
var encountMapNpcList: List<Mai2MapEncountNpc> = ArrayList()
}
@Table(name = "maimai2_user_favorite")
@Entity
class Mai2UserFavorite : Mai2UserEntity() {
@JsonProperty("userId")
var favUserId: Long = 0
var itemKind = 0
@Convert(converter = IntegerListConverter::class)
var itemIdList: List<Int> = ArrayList()
}
@Table(name = "maimai2_user_friend_season_ranking")
@Entity
class Mai2UserFriendSeasonRanking : Mai2UserEntity() {
var seasonId = 0
var point = 0
@Column(name = "\"rank\"")
var rank = 0
var rewardGet = false
var userName: String = ""
var recordDate: String = ""
}
/**
* This is for storing some data only use in aqua
* @author samnyan (privateamusement@protonmail.com)
*/
@Table(name = "maimai2_user_general_data")
@Entity
class Mai2UserGeneralData : Mai2UserEntity() {
var propertyKey = ""
@Column(columnDefinition = "TEXT")
var propertyValue = ""
}
class Mai2UserGhost {
var name: String = ""
var iconId = 0
var plateId = 0
var titleId = 0
var rate = 0
var udemaeRate = 0
var courseRank = 0
var classRank = 0
var classValue = 0
var playDatetime: String = ""
var shopId = 0
var regionCode = 0
var typeId = 0
var musicId = 0
var difficulty = 0
var version = 0
var resultBitList: List<Byte>? = null
var resultNum = 0
var achievement = 0
}
@Table(name = "maimai2_user_item")
@Entity
class Mai2UserItem : Mai2UserEntity() {
var itemKind = 0
var itemId = 0
var stock = 0
var isValid = false
}
@Suppress("EnumEntryName")
enum class Mai2ItemKind(val id: Int) {
plate(1),
title(2),
icon(3),
musicUnlock(5),
musicMasterUnlock(6),
musicRemasterUnlock(7),
musicStrongUnlock(8),
chara(9),
partner(10),
frame(11),
ticket(12);
companion object {
val ALL: Map<Int, Mai2ItemKind> = Mai2ItemKind::class.java.enumConstants.associateBy { it.id }
}
}
@Table(name = "maimai2_user_login_bonus")
@Entity
class Mai2UserLoginBonus : Mai2UserEntity() {
var bonusId = 0
var point = 0
var isCurrent = false
var isComplete = false
}
@Table(name = "maimai2_user_map")
@Entity
class Mai2UserMap : Mai2UserEntity() {
var mapId = 0
var distance = 0
var isLock = false
var isClear = false
var isComplete = false
}
@Table(name = "maimai2_user_music_detail")
@Entity
class Mai2UserMusicDetail : Mai2UserEntity(), IGenericUserMusic {
override var musicId = 0
var level = 0
var playCount = 0
var achievement = 0
var comboStatus = 0
var syncStatus = 0
var deluxscoreMax = 0
var scoreRank = 0
var extNum1 = 0
}
@Table(name = "maimai2_user_option")
@Entity
class Mai2UserOption : Mai2UserEntity() {
var optionKind = 0
var noteSpeed = 0
var slideSpeed = 0
var touchSpeed = 0
var tapDesign = 0
var holdDesign = 0
var slideDesign = 0
var starType = 0
var outlineDesign = 0
var noteSize = 0
var slideSize = 0
var touchSize = 0
var starRotate = 0
var dispCenter = 0
var dispChain = 0
var dispRate = 0
var dispBar = 0
var touchEffect = 0
var submonitorAnimation = 0
var submonitorAchive = 0
var submonitorAppeal = 0
var matching = 0
var trackSkip = 0
var brightness = 0
var mirrorMode = 0
var dispJudge = 0
var dispJudgePos = 0
var dispJudgeTouchPos = 0
var adjustTiming = 0
var judgeTiming = 0
var ansVolume = 0
var tapHoldVolume = 0
var criticalSe = 0
var tapSe = 0
var breakSe = 0
var breakVolume = 0
var exSe = 0
var exVolume = 0
var slideSe = 0
var slideVolume = 0
var touchHoldVolume = 0
var damageSeVolume = 0
var headPhoneVolume = 0
var sortTab = 0
var sortMusic = 0
var outFrameType = 0
var breakSlideVolume = 0
var touchVolume = 0
}
@Table(name = "maimai2_user_playlog")
@Entity
class Mai2UserPlaylog : Mai2UserEntity(), IGenericGamePlaylog {
var orderId = 0
var playlogId: Long = 0
var version = 0
var placeId = 0
var placeName: String = ""
var loginDate: Long = 0
var playDate: String = ""
override var userPlayDate: String = ""
var type = 0
override var musicId: Int = 0
override var level: Int = 0
var trackNo = 0
var vsMode = 0
var vsUserName: String = ""
var vsStatus = 0
var vsUserRating = 0
var vsUserAchievement = 0
var vsUserGradeRank = 0
var vsRank = 0
var playerNum = 0
var playedUserId1: Long = 0
var playedUserName1: String = ""
var playedMusicLevel1 = 0
var playedUserId2: Long = 0
var playedUserName2: String = ""
var playedMusicLevel2 = 0
var playedUserId3: Long = 0
var playedUserName3: String = ""
var playedMusicLevel3 = 0
var characterId1 = 0
var characterLevel1 = 0
var characterAwakening1 = 0
var characterId2 = 0
var characterLevel2 = 0
var characterAwakening2 = 0
var characterId3 = 0
var characterLevel3 = 0
var characterAwakening3 = 0
var characterId4 = 0
var characterLevel4 = 0
var characterAwakening4 = 0
var characterId5 = 0
var characterLevel5 = 0
var characterAwakening5 = 0
override var achievement: Int = 0
var deluxscore = 0
var scoreRank = 0
// Maximum continuous combo that the player achieved in this play.
override var maxCombo: Int = 0
// Maximum achievable combo in the song.
var totalCombo = 0
var maxSync = 0
var totalSync = 0
var tapCriticalPerfect = 0
var tapPerfect = 0
var tapGreat = 0
var tapGood = 0
var tapMiss = 0
var holdCriticalPerfect = 0
var holdPerfect = 0
var holdGreat = 0
var holdGood = 0
var holdMiss = 0
var slideCriticalPerfect = 0
var slidePerfect = 0
var slideGreat = 0
var slideGood = 0
var slideMiss = 0
var touchCriticalPerfect = 0
var touchPerfect = 0
var touchGreat = 0
var touchGood = 0
var touchMiss = 0
var breakCriticalPerfect = 0
var breakPerfect = 0
var breakGreat = 0
var breakGood = 0
var breakMiss = 0
var isTap = false
var isHold = false
var isSlide = false
var isTouch = false
var isBreak = false
var isCriticalDisp = false
var isFastLateDisp = false
var fastCount = 0
var lateCount = 0
var isAchieveNewRecord = false
var isDeluxscoreNewRecord = false
var comboStatus = 0
var syncStatus = 0
var isClear = false
override var beforeRating: Int = 0
override var afterRating: Int = 0
var beforeGrade = 0
var afterGrade = 0
var afterGradeRank = 0
var beforeDeluxRating = 0
var afterDeluxRating = 0
var isPlayTutorial = false
var isEventMode = false
var isFreedomMode = false
var playMode = 0
var isNewFree = false
var trialPlayAchievement = 0
var extNum1 = 0 // StartLife * 10000 + Life
var extNum2 = 0 // Course ID
var extNum4 = 0 // Select Category
var extBool1 = false // Utage Coop
var extBool2 = false // Random Select
var extBool3 = false // Track Skip
override val isFullCombo: Boolean
get() = maxCombo == totalCombo
override val isAllPerfect: Boolean
get() = tapMiss + tapGood + tapGreat == 0 &&
holdMiss + holdGood + holdGreat == 0 &&
slideMiss + slideGood + slideGreat == 0 &&
touchMiss + touchGood + touchGreat == 0 &&
breakMiss + breakGood + breakGreat == 0
}
fun main(args: Array<String>) {
println(Mai2UserPlaylog().toJson())
}
@Table(name = "maimai2_user_print_detail")
@Entity
class Mai2UserPrintDetail : Mai2UserEntity() {
var orderId: Long = 0
var printNumber = 0
var printDate: String = ""
var serialId: String = ""
var placeId = 0
var clientId: String = ""
var printerSerialId: String = ""
@ManyToOne
@JoinColumn(name = "user_card_id")
var userCard: Mai2UserCard? = null
var cardRomVersion = 0
var isHolograph = false
var printOption1 = false
var printOption2 = false
var printOption3 = false
var printOption4 = false
var printOption5 = false
var printOption6 = false
var printOption7 = false
var printOption8 = false
var printOption9 = false
var printOption10 = false
var created: String = ""
}
data class Mai2UserRate(
var musicId: Int = 0,
var level: Int = 0,
var romVersion: Int = 0,
var achievement: Int = 0,
)
@Table(name = "maimai2_user_udemae")
@Entity
class Mai2UserUdemae : Mai2UserEntity() {
var rate = 0
var maxRate = 0
var classValue = 0
var maxClassValue = 0
var totalWinNum = 0
var totalLoseNum = 0
var maxWinNum = 0
var maxLoseNum = 0
var winNum = 0
var loseNum = 0
var npcTotalWinNum = 0
var npcTotalLoseNum = 0
var npcMaxWinNum = 0
var npcMaxLoseNum = 0
var npcWinNum = 0
var npcLoseNum = 0
}
@Table(name = "maimai2_user_kaleidx")
@Entity
class Mai2UserKaleidx : Mai2UserEntity() {
var gateId = 1
var isGateFound = true
var isKeyFound = true
var isClear = false
var totalRestLife = 0
var totalAchievement = 0
var totalDeluxscore = 0
var bestAchievement = 0
var bestDeluxscore = 0
@JsonSerialize(using = MaimaiDateSerializer::class)
var bestAchievementDate: LocalDateTime? = null
@JsonSerialize(using = MaimaiDateSerializer::class)
var bestDeluxscoreDate: LocalDateTime? = null
var playCount = 0
@JsonSerialize(using = MaimaiDateSerializer::class)
var clearDate: LocalDateTime? = null
@JsonSerialize(using = MaimaiDateSerializer::class)
var lastPlayDate: LocalDateTime? = null
var isInfoWatched = false
}
@Table(name = "maimai2_user_intimate")
@Entity
class Mai2UserIntimate : Mai2UserEntity() {
var partnerId = 1;
var intimateLevel = 0;
var intimateCountRewarded = 0;
}
@Entity(name = "Maimai2UserRegions")
@Table(
name = "maimai2_user_regions",
uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "region_id"])]
)
class UserRegions : Mai2UserEntity() {
var regionId = 0
var playCount = 1
var created: String = LocalDate.now().toString()
}
val MAIMAI_DATETIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.0")
class MaimaiDateSerializer : JsonSerializer<LocalDateTime>() {
override fun serialize(v: LocalDateTime, j: JsonGenerator, s: SerializerProvider) {
j.writeString(v.format(MAIMAI_DATETIME))
}
}
@@ -0,0 +1,50 @@
package icu.samnyan.aqua.sega.ongeki.model
import com.fasterxml.jackson.annotation.JsonValue
enum class OgkGpProductID(@get:JsonValue val value: Int) {
A_Credit1(0),
A_Credit2(1),
A_Credit3(2),
B_Credit1(3),
B_Credit2(4),
B_Credit3(5),
End(6)
}
enum class OgkIdListType {
Invalid,
NgMusic,
Recommend;
@JsonValue
fun toValue() = ordinal
}
enum class OgkItemType {
None,
Card,
NamePlate,
Trophy,
LimitBreakItem,
AlmightyJewel,
Money,
Music,
ProfileVoice,
Present,
ChapterJewel,
GachaTicket,
KaikaItem,
ExpUpItem,
IntimateUpItem,
BookItem,
SystemVoice,
Costume,
Medal,
Attachment,
UnlockItem,
Max;
@JsonValue
fun toValue() = ordinal
}
@@ -0,0 +1,108 @@
package icu.samnyan.aqua.sega.ongeki.model
import com.fasterxml.jackson.annotation.JsonProperty
class GameCard {
var cardId: Long = 0
var name: String = ""
var nickName: String = ""
var attribute: String = ""
var charaId = 0
var school: String = ""
var gakunen: String = ""
var rarity: String = ""
// csv
var levelParam: String = ""
var skillId = 0
var choKaikaSkillId = 0
var cardNumber: String = ""
var version: String = ""
}
class GameChara {
var name: String = ""
var cv: String = ""
var modelId = 0
}
class GameEvent {
var id: Long = 0
}
class GameMusic {
var id: Long = 0
var name: String = ""
var sortName: String = ""
var artistName: String = ""
var genre: String = ""
var bossCardId = 0
var bossLevel = 0
var level0: String = ""
var level1: String = ""
var level2: String = ""
var level3: String = ""
var level4: String = ""
}
class GamePoint {
var id: Long = 0
var type: OgkGpProductID = OgkGpProductID.A_Credit1
var cost: Int = 0
val startDate = "2000-01-01 05:00:00.0"
val endDate = "2099-01-01 05:00:00.0"
}
class GamePresent {
var id: Long = 0
var presentName: String = ""
var rewardId: Int = 0 // count
var stock: Int = 0 // acquisitionCondition
var message: String = ""
val startDate = "2000-01-01 05:00:00.0"
val endDate = "2099-01-01 05:00:00.0"
}
class GameReward {
var id: Long = 0
var itemKind: OgkItemType = OgkItemType.None
var itemId = 0
}
class GameSkill {
var id: Long = 0
var name: String = ""
var category: String = ""
var info: String = ""
}
class GameGachaCard {
var cardId: Long = 0
var gachaId: Long = 0
var rarity: Int = 0
var weight: Int = 0
@JsonProperty("isPickup")
var isPickup: Boolean = false
@JsonProperty("isSelect")
var isSelect: Boolean = false
}
class GameGacha {
var gachaId: Long = 0
var gachaName: String = ""
var type: Int = 0
var kind: Int = 0
var maxSelectPoint: Int = 0
var ceilingCnt: Int = 0
var changeRateCnt1: Int = 0
var changeRateCnt2: Int = 0
var startDate: String = "2020-01-01 00:00:00"
var endDate: String = "2099-01-01 00:00:00"
var noticeStartDate: String = "2020-01-01 00:00:00"
var noticeEndDate: String = "2099-01-01 00:00:00"
var convertEndDate: String = "2099-01-01 00:00:00"
@JsonProperty("isCeiling")
var isCeiling: Boolean = false
}
@@ -0,0 +1,44 @@
package icu.samnyan.aqua.sega.ongeki.model
class OngekiCMUpsertUserGacha {
var userData: List<UserData>? = null
var userCharacterList: List<UserCharacter>? = null
var userCardList: List<UserCard>? = null
var gameGachaCardList: List<GameGachaCard>? = null
var userItemList: List<UserItem>? = null
// These are strings with as many 1s as new elements are present
var isNewCharacterList: String? = null
var isNewCardList: String? = null
var isNewItemList: String? = null
}
class OngekiCMUpsertAll {
var userData: List<UserData>? = null
var userActivityList: List<UserActivity>? = null
var userCharacterList: List<UserCharacter>? = null
var userCardList: List<UserCard>? = null
var userItemList: List<UserItem>? = null
// These are strings with as many 1s as new elements are given
var isNewCharacterList: String? = null
var isNewCardList: String? = null
var isNewItemList: String? = null
}
class OngekiCMUpsertUserSelectGacha {
var userData: List<UserData>? = null
var userCharacterList: List<UserCharacter>? = null
var userCardList: List<UserCard>? = null
// These are strings with as many 1s as new elements are given
var isNewCharacterList: String? = null
var isNewCardList: String? = null
}
class OngekiCMSelectGachaLog {
var gachaId: Long = 0
var useSelectPoint: Int = 0
var convertType: Int = 0
var convertItem: Int = 0
}
@@ -0,0 +1,84 @@
package icu.samnyan.aqua.sega.ongeki.model
import icu.samnyan.aqua.sega.general.model.UserRecentRating
class OngekiUpsertUserAll {
var userData: List<UserData>? = null
var userOption: List<UserOption>? = null
var userPlaylogList: List<UserPlaylog>? = null
var userJewelboostlogList: List<Map<String, Any>>? = null
var userSessionlogList: List<Map<String, Any>>? = null
var userActivityList: List<UserActivity>? = null
var userRecentRatingList: List<UserRecentRating>? = null
var userBpBaseList: List<UserRecentRating>? = null
var userRatingBaseBestNewList: List<UserRecentRating>? = null
var userRatingBaseBestList: List<UserRecentRating>? = null
var userRatingBaseHotList: List<UserRecentRating>? = null
var userRatingBaseNextNewList: List<UserRecentRating>? = null
var userRatingBaseNextList: List<UserRecentRating>? = null
var userRatingBaseHotNextList: List<UserRecentRating>? = null
var userMusicDetailList: List<UserMusicDetail>? = null
var userCharacterList: List<UserCharacter>? = null
var userCardList: List<UserCard>? = null
var userDeckList: List<UserDeck>? = null
var userTrainingRoomList: List<UserTrainingRoom>? = null
var userStoryList: List<UserStory>? = null
var userChapterList: List<UserChapter>? = null
var userMemoryChapterList: List<UserMemoryChapter>? = null
var userItemList: List<UserItem>? = null
var userMusicItemList: List<UserMusicItem>? = null
var userLoginBonusList: List<UserLoginBonus>? = null
var userEventPointList: List<UserEventPoint>? = null
var userMissionPointList: List<UserMissionPoint>? = null
var userRatinglogList: List<Map<String, Any>>? = null
var userBossList: List<UserBoss>? = null
var userTechCountList: List<UserTechCount>? = null
var userScenarioList: List<UserScenario>? = null
var userTradeItemList: List<UserTradeItem>? = null
var userEventMusicList: List<UserEventMusic>? = null
var userTechEventList: List<UserTechEvent>? = null
var userKopList: List<UserKop>? = null
var clientSystemInfo: Map<String, Any>? = null
var isNewMusicDetailList: String? = null
var isNewCharacterList: String? = null
var isNewCardList: String? = null
var isNewDeckList: String? = null
var isNewTrainingRoomList: String? = null
var isNewStoryList: String? = null
var isNewChapterList: String? = null
var isNewMemoryChapterList: String? = null
var isNewItemList: String? = null
var isNewMusicItemList: String? = null
var isNewLoginBonusList: String? = null
var isNewEventPointList: String? = null
var isNewMissionPointList: String? = null
var isNewRatinglogList: String? = null
var isNewBossList: String? = null
var isNewTechCountList: String? = null
var isNewScenarioList: String? = null
var isNewTradeItemList: String? = null
var isNewEventMusicList: String? = null
var isNewTechEventList: String? = null
var isNewKopList: String? = null
// Re:Fresh
var userNewRatingBasePScoreList: List<OngekiFumenScore>? = null
var userNewRatingBaseBestList: List<OngekiFumenScore>? = null
var userNewRatingBaseBestNewList: List<OngekiFumenScore>? = null
var userNewRatingBaseNextPScoreList: List<OngekiFumenScore>? = null
var userNewRatingBaseNextBestList: List<OngekiFumenScore>? = null
var userNewRatingBaseNextBestNewList: List<OngekiFumenScore>? = null
var userEventMap: UserEventMap? = null
}
class OngekiFumenScore(
var musicId: Int = 0,
var difficultId: Int = 0,
var romVersionCode: String? = null,
var score: Int = 0,
var platinumScoreMax: Int = 0,
var platinumScoreStar: Int = 0,
) {
override fun toString() = "${musicId}:${difficultId}:${score}:${platinumScoreStar}:${platinumScoreMax}"
}
@@ -0,0 +1,544 @@
package icu.samnyan.aqua.sega.ongeki.model
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import icu.samnyan.aqua.net.games.*
import icu.samnyan.aqua.sega.general.model.Card
import icu.samnyan.aqua.sega.util.AccessCodeSerializer
import jakarta.persistence.*
import java.time.LocalDate
import java.time.LocalDateTime
@MappedSuperclass
open class OngekiUserEntity : BaseEntity(), IUserEntity<UserData> {
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id")
override var user: UserData = UserData()
}
@Entity(name = "OngekiUserData")
@Table(name = "ongeki_user_data")
class UserData : IUserData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore
override var id: Long = 0
@JsonSerialize(using = AccessCodeSerializer::class)
@JsonProperty(value = "accessCode", access = JsonProperty.Access.READ_ONLY)
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "aime_card_id", unique = true)
override var card: Card? = null
// Access code in card
override var userName: String = ""
var level = 0
var reincarnationNum = 0
var exp: Long = 0
var point: Long = 0
var totalPoint: Long = 0
var playCount = 0
var jewelCount = 0
var totalJewelCount = 0
var medalCount = 0
override var playerRating: Int = 0
override var highestRating: Int = 0
var battlePoint = 0
var bestBattlePoint = 0
var overDamageBattlePoint = 0
var isDialogWatchedSuggestMemory = false
var nameplateId = 0
var trophyId = 0
var cardId = 0
var characterId = 0
var characterVoiceNo = 0
var tabSetting = 0
var tabSortSetting = 0
var cardCategorySetting = 0
var cardSortSetting = 0
var rivalScoreCategorySetting = 0
var playedTutorialBit = 0
var firstTutorialCancelNum = 0
var sumTechHighScore: Long = 0
var sumTechBasicHighScore: Long = 0
var sumTechAdvancedHighScore: Long = 0
var sumTechExpertHighScore: Long = 0
var sumTechMasterHighScore: Long = 0
var sumTechLunaticHighScore: Long = 0
var sumBattleHighScore: Long = 0
var sumBattleBasicHighScore: Long = 0
var sumBattleAdvancedHighScore: Long = 0
var sumBattleExpertHighScore: Long = 0
var sumBattleMasterHighScore: Long = 0
var sumBattleLunaticHighScore: Long = 0
var eventWatchedDate: String = ""
var cmEventWatchedDate: String = ""
var firstGameId: String = ""
var firstRomVersion: String = ""
var firstDataVersion: String = ""
override var firstPlayDate: String = ""
var lastGameId: String = ""
override var lastRomVersion: String = ""
var lastDataVersion: String = ""
var compatibleCmVersion: String = ""
override var lastPlayDate: String = ""
var lastPlaceId = 0
var lastPlaceName: String = ""
var lastRegionId = 0
var lastRegionName: String = ""
var lastAllNetId = 0
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
override var lastClientId: String = ""
var lastUsedDeckId = 0
var lastPlayMusicLevel = 0
var lastEmoneyBrand = 0
// Re:Fresh
var shizukuCount = 0
var newPlayerRating = 0
var newHighestRating = 0
var sumPlatinumScoreStar = 0
var sumBasicPlatinumScoreStar = 0
var sumAdvancedPlatinumScoreStar = 0
var sumExpertPlatinumScoreStar = 0
var sumMasterPlatinumScoreStar = 0
var sumLunaticPlatinumScoreStar = 0
override val totalScore get() = sumTechHighScore
}
@Entity(name = "OngekiUserActivity")
@Table(
name = "ongeki_user_activity",
uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "kind", "activity_id"])]
)
class UserActivity : OngekiUserEntity() {
var kind = 0
@JsonProperty("id")
@Column(name = "activity_id")
var activityId = 0
var sortNumber = 0
var param1 = 0
var param2 = 0
var param3 = 0
var param4 = 0
}
@Entity(name = "OngekiUserBoss")
@Table(name = "ongeki_user_boss")
class UserBoss : OngekiUserEntity() {
var musicId = 0
var damage = 0
var isClear = false
var eventId = 0
}
@Entity(name = "OngekiUserCard")
@Table(name = "ongeki_user_card")
class UserCard: OngekiUserEntity() {
var cardId = -1
var digitalStock = 1
var analogStock = 0
var level = 0
var maxLevel = 10
var exp = 0
var printCount = 0
var useCount = 0
var isNew = true
var kaikaDate = "0000-00-00 00:00:00.0"
var choKaikaDate = "0000-00-00 00:00:00.0"
var skillId = 0
var isAcquired = true
var created = "0000-00-00 00:00:00.0"
}
@Entity(name = "OngekiUserChapter")
@Table(name = "ongeki_user_chapter")
class UserChapter : OngekiUserEntity() {
var chapterId = 0
var jewelCount = 0
var lastPlayMusicCategory = 0
var lastPlayMusicId = 0
var lastPlayMusicLevel = 0
var isStoryWatched = false
var isClear = false
var skipTiming1 = 0
var skipTiming2 = 0
}
@Entity(name = "OngekiUserCharacter")
@Table(name = "ongeki_user_character")
class UserCharacter : OngekiUserEntity() {
var characterId = 0
var costumeId = 0
var attachmentId = 0
var playCount = 0
var intimateLevel = 0
var intimateCount = 0
var intimateCountRewarded = 0
var intimateCountDate: String = ""
var isNew = false
}
@Entity(name = "OngekiUserDeck")
@Table(name = "ongeki_user_deck")
class UserDeck : OngekiUserEntity() {
var deckId = 0
var cardId1 = 0
var cardId2 = 0
var cardId3 = 0
}
@Entity(name = "OngekiUserEventMusic")
@Table(name = "ongeki_user_event_music")
class UserEventMusic : OngekiUserEntity() {
var eventId = 0
var type = 0
var musicId = 0
var level = 0
var techScoreMax = 0
var platinumScoreMax = 0
var techRecordDate: String = ""
var isTechNewRecord: Boolean = false
}
@Entity(name = "OngekiUserEventPoint")
@Table(name = "ongeki_user_event_point")
class UserEventPoint : OngekiUserEntity() {
var eventId = 0
var point: Long = 0
var isRankingRewarded = false
}
@Entity(name = "OngekiUserGeneralData")
@Table(name = "ongeki_user_general_data")
class UserGeneralData : OngekiUserEntity() {
var propertyKey = ""
@Column(columnDefinition = "TEXT")
var propertyValue = ""
}
@Entity(name = "OngekiUserItem")
@Table(name = "ongeki_user_item")
class UserItem : OngekiUserEntity() {
var itemKind = 0
var itemId = 0
var stock = 0
var isValid = false
}
@Entity(name = "OngekiUserKop")
@Table(name = "ongeki_user_kop")
class UserKop : OngekiUserEntity() {
var authKey: String = ""
var kopId = 0
var areaId = 0
var totalTechScore = 0
var totalPlatinumScore = 0
var techRecordDate: String = ""
var isTotalTechNewRecord = false
}
@Entity(name = "OngekiUserLoginBonus")
@Table(name = "ongeki_user_login_bonus")
class UserLoginBonus : OngekiUserEntity() {
var bonusId = 0
var bonusCount = 0
var lastUpdateDate: String = ""
}
@Entity(name = "OngekiUserMemoryChapter")
@Table(name = "ongeki_user_memory_chapter")
class UserMemoryChapter : OngekiUserEntity() {
var chapterId = 0
var jewelCount = 0
var lastPlayMusicCategory = 0
var lastPlayMusicId = 0
var lastPlayMusicLevel = 0
var isDialogWatched = false
var isStoryWatched = false
var isBossWatched = false
var isClear = false
var gaugeId = 0
var gaugeNum = 0
// Re:Fresh
var isEndingWatched = false
}
@Entity(name = "OngekiUserMissionPoint")
@Table(name = "ongeki_user_mission_point")
class UserMissionPoint : OngekiUserEntity() {
var eventId = 0
var point: Long = 0
}
@Entity(name = "OngekiUserMusicDetail")
@Table(name = "ongeki_user_music_detail")
class UserMusicDetail : OngekiUserEntity(), IGenericUserMusic {
override var musicId: Int = 0
var level = 0
var playCount = 0
var techScoreMax = 0
var techScoreRank = 0
var battleScoreMax = 0
var battleScoreRank = 0
var platinumScoreMax = 0
var maxComboCount = 0
var maxOverKill = 0
var maxTeamOverKill = 0
var isFullBell = false
var isFullCombo = false
var isAllBreake = false
var isLock = false
var clearStatus = 0
var isStoryWatched = false
// Re:Fresh
var platinumScoreStar = 0
}
@Entity(name = "OngekiUserMusicItem")
@Table(name = "ongeki_user_music_item")
class UserMusicItem : OngekiUserEntity() {
var musicId = 0
var status = 0
}
@Entity(name = "OngekiUserOption")
@Table(name = "ongeki_user_option")
class UserOption : OngekiUserEntity() {
var optionSet = 0
var speed = 0
var mirror = 0
var judgeTiming = 0
var judgeAdjustment = 0
var abort = 0
var stealthField = 0
var tapSound = 0
var volGuide = 0
var volAll = 0
var volTap = 0
var volCrTap = 0
var volHold = 0
var volSide = 0
var volFlick = 0
var volBell = 0
var volEnemy = 0
var volSkill = 0
var volDamage = 0
var colorField = 0
var colorLaneBright = 0
var colorWallBright = 0
var colorLane = 0
var colorSide = 0
var effectDamage = 0
var effectPos = 0
var judgeDisp = 0
var judgePos = 0
var judgeBreak = 0
var judgeHit = 0
var platinumBreakDisp = 0
var judgeCriticalBreak = 0
var matching = 0
var dispPlayerLv = 0
var dispRating = 0
var dispBP = 0
var headphone = 0
// Re:Fresh
var effectAttack = 0
}
@Entity(name = "OngekiUserPlaylog")
@Table(name = "ongeki_user_playlog")
class UserPlaylog : OngekiUserEntity(), IGenericGamePlaylog {
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id")
override var user: UserData = UserData()
var sortNumber = 0
var placeId = 0
var placeName: String = ""
var playDate: String = ""
override var userPlayDate: String = ""
override var musicId: Int = 0
override var level: Int = 0
var playKind = 0
var eventId = 0
var eventName: String = ""
var eventPoint = 0
var playedUserId1 = 0
var playedUserId2 = 0
var playedUserId3 = 0
var playedUserName1: String = ""
var playedUserName2: String = ""
var playedUserName3: String = ""
var playedMusicLevel1 = 0
var playedMusicLevel2 = 0
var playedMusicLevel3 = 0
var cardId1 = 0
var cardId2 = 0
var cardId3 = 0
var cardLevel1 = 0
var cardLevel2 = 0
var cardLevel3 = 0
var cardAttack1 = 0
var cardAttack2 = 0
var cardAttack3 = 0
var bossCharaId = 0
var bossLevel = 0
var bossAttribute = 0
var clearStatus = 0
var techScore = 0
var techScoreRank = 0
var battleScore = 0
var battleScoreRank = 0
var platinumScore = 0
override var maxCombo: Int = 0
var judgeMiss = 0
var judgeHit = 0
var judgeBreak = 0
var judgeCriticalBreak = 0
var rateTap = 0
var rateHold = 0
var rateFlick = 0
var rateSideTap = 0
var rateSideHold = 0
var bellCount = 0
var totalBellCount = 0
var damageCount = 0
var overDamage = 0
var isTechNewRecord = false
var isBattleNewRecord = false
var isOverDamageNewRecord = false
override var isFullCombo: Boolean = false
var isFullBell = false
var isAllBreak: Boolean = false
var playerRating: Int = 0
var battlePoint = 0
override val isAllPerfect get() = isAllBreak
override val beforeRating get() = playerRating
override val afterRating get() = playerRating
override val achievement get() = techScore
}
@Entity(name = "OngekiUserRival")
@Table(name = "ongeki_user_rival")
class UserRival : OngekiUserEntity() {
@JoinColumn(name = "rival_user_ext_id")
@JsonProperty("rivalUserId")
var rivalUserExtId: Long = 0
}
@Entity(name = "OngekiUserScenario")
@Table(name = "ongeki_user_scenario")
class UserScenario : OngekiUserEntity() {
var scenarioId = 0
var playCount = 0
}
@Entity(name = "OngekiUserStory")
@Table(name = "ongeki_user_story")
class UserStory : OngekiUserEntity() {
var storyId = 0
var lastChapterId = 0
var jewelCount = 0
var lastPlayMusicId = 0
var lastPlayMusicCategory = 0
var lastPlayMusicLevel = 0
}
@Entity(name = "OngekiUserTechCount")
@Table(name = "ongeki_user_tech_count")
class UserTechCount : OngekiUserEntity() {
var levelId = 0
var allBreakCount = 0
var allBreakPlusCount = 0
}
@Entity(name = "OngekiUserTechEvent")
@Table(name = "ongeki_user_tech_event")
class UserTechEvent : OngekiUserEntity() {
var eventId = 0
var totalTechScore = 0
var totalPlatinumScore = 0
var techRecordDate: String = ""
var isRankingRewarded = false
var isTotalTechNewRecord = false
}
@Entity(name = "OngekiUserTradeItem")
@Table(name = "ongeki_user_trade_item")
class UserTradeItem : OngekiUserEntity() {
var chapterId = 0
var tradeItemId = 0
var tradeCount = 0
}
@Entity(name = "OngekiTrainingRoom")
@Table(name = "ongeki_user_training_room")
class UserTrainingRoom : OngekiUserEntity() {
var authKey: String = ""
var roomId: Int = 0
var cardId: Int = 0
var valueDate: String = ""
}
// Re:Fresh
@Entity(name = "OngekiUserEventMap")
@Table(name = "ongeki_user_event_map")
class UserEventMap : OngekiUserEntity() {
var eventId = 0
var mapId = 0
var mapData: String? = null
var totalPoint = 0
var totalUsePoint = 0
}
@Entity(name = "OngekiUserSkin")
@Table(name = "ongeki_user_skin")
class UserSkin : OngekiUserEntity() {
// TODO: should be updated on net when changing skin
var isValid = false
var deckId = 0
var cardId1 = 0
var cardId2 = 0
var cardId3 = 0
}
@Entity(name = "OngekiUserRegions")
@Table(
name = "ongeki_user_regions",
uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "region_id"])]
)
class UserRegions : OngekiUserEntity() {
var regionId = 0
var playCount = 1
var created: String = LocalDate.now().toString()
}
@Entity(name="OngekiUserGacha")
@Table(
name = "ongeki_user_gacha",
uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "gacha_id"])]
)
class UserGacha : OngekiUserEntity() {
var gachaId:Long = 0
var totalGachaCnt = 0
var ceilingGachaCnt = 0
var selectPoint = 0
var useSelectPoint = 0
var dailyGachaCnt = 0
var fiveGachaCnt = 0
var elevenGachaCnt = 0
var dailyGachaDate: String = LocalDateTime.now().toString()
}
@@ -0,0 +1,47 @@
package icu.samnyan.aqua.sega.util
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import ext.int
import icu.samnyan.aqua.sega.general.model.Card
import java.time.ZonedDateTime
class AccessCodeSerializer @JvmOverloads constructor(t: Class<Card>? = null) : StdSerializer<Card>(t) {
override fun serialize(value: Card, gen: JsonGenerator, provider: SerializerProvider) {
gen.writeString(value.luid)
}
}
class BooleanToIntegerDeserializer : JsonDeserializer<Int>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = when (p.currentToken) {
JsonToken.VALUE_STRING -> when (val str = p.valueAsString.lowercase()) {
"true" -> 1
"false" -> 0
else -> str.int
}
JsonToken.VALUE_NUMBER_INT -> p.intValue
JsonToken.VALUE_TRUE -> 1
JsonToken.VALUE_FALSE -> 0
else -> throw UnsupportedOperationException("Cannot deserialize to boolean int")
}
}
class BooleanNumberSerializer @JvmOverloads constructor(t: Class<Boolean>? = null) : StdSerializer<Boolean>(t) {
override fun serialize(value: Boolean, gen: JsonGenerator, provider: SerializerProvider) {
gen.writeNumber(if (value) 1 else 0)
}
}
class BooleanNumberDeserializer : JsonDeserializer<Boolean>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = "0" != p.text
}
class ZonedDateTimeDeserializer : JsonDeserializer<ZonedDateTime>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = ZonedDateTime.parse(p.text)
}
@@ -0,0 +1,129 @@
package icu.samnyan.aqua.sega.wacca
import icu.samnyan.aqua.sega.wacca.model.db.WaccaUser
import icu.samnyan.aqua.sega.wacca.model.db.WcUserItem
enum class WaccaGrades(val value: Int) {
D(1),
C(2),
B(3),
A(4),
AA(5),
AAA(6),
S(7),
S_PLUS(11),
SS(8),
SS_PLUS(12),
SSS(9),
SSS_PLUS(13),
MASTER(10);
companion object {
val valueMap = entries.associateBy { it.value }
}
}
enum class WaccaDifficulty(val value: Int) {
NORMAL(1),
HARD(2),
EXPERT(3),
INFERNO(4);
operator fun invoke() = value
}
enum class WaccaItemType(val type: Int) {
XP(1),
WP(2),
MUSIC_UNLOCK(3),
MUSIC_DIFFICULTY_UNLOCK(4),
TITLE(5),
ICON(6),
TROPHY(7),
SKILL(8),
TICKET(9),
NOTE_COLOR(10),
NOTE_SOUND(11),
BAHT_DO_NOT_SEND(12),
BOOST_BADGE(13),
GATE_POINT(14),
NAVIGATOR(15),
USER_PLATE(16),
TOUCH_EFFECT(17);
operator fun invoke() = type
operator fun invoke(u: WaccaUser, id: Int, p1: Long = 0, p2: Long = 0, p3: Long = 0) =
WcUserItem(type = this(), itemId = id, p1 = p1, p2 = p2, p3 = p3).apply { user = u }
}
enum class WaccaOptionType(val id: Int, val default: Int) {
NOTE_SPEED(1, 5), // 1.0 - 6.0
FIELD_MASK(2, 0), // 0-4
NOTE_SOUND(3, 105001), // ID
NOTE_COLOR(4, 203001), // ID
BGM_VOLUME(5, 10), // 0-100 increments of 10
BG_VIDEO(7, 0), // ask, on, or off
MIRROR(101, 0), // none or left+right swap
JUDGE_DISPLAY_POS(102, 0), // center, under, over, top or off
JUDGE_DETAIL_DISPLAY(103, 0), // on or off
MEASURE_GUIDELINES(105, 1), // on or off
GUIDELINE_MASK(106, 1), // 0 - 5
JUDGE_LINE_TIMING_ADJUST(108, 10), // -10 - 10
NOTE_DESIGN(110, 3), // 1 - 5
BONUS_EFFECT(114, 1), // on or off
CHARA_VOICE(115, 1), // "usually" or none
SCORE_DISPLAY_METHOD(116, 0), // add or subtract
GIVE_UP(117, 0), // off, no touch, can't achieve s, ss, sss, pb
GUIDELINE_SPACING(118, 1), // none, or a-g type
CENTER_DISPLAY(119, 1), // none, combo, score add, score sub, s ss sss pb boarder
RANKING_DISPLAY(120, 1), // on or off
STAGE_UP_ICON_DISPLAY(121, 1), // on or off
RATING_DISPLAY(122, 1), // on or off
PLAYER_LEVEL_DISPLAY(123, 1), // on or off
TOUCH_EFFECT(124, 1), // on or off
GUIDE_SOUND_VOL(125, 30), // 0-100 increments of 10
TOUCH_NOTE_VOL(126, 80), // 0-100 increments of 10
HOLD_NOTE_VOL(127, 80), // 0
SLIDE_NOTE_VOL(128, 80), // 0
SNAP_NOTE_VOL(129, 80), // 0
CHAIN_NOTE_VOL(130, 80), // 0
BONUS_NOTE_VOL(131, 80), // 0
GATE_SKIP(132, 0), // on
KEY_BEAM_DISPLAY(133, 1), // on
LEFT_SLIDE_NOTE_COLOR(201, 4), // red
RIGHT_SLIDE_NOTE_COLOR(202, 3), // red
FORWARD_SLIDE_NOTE_COLOR(203, 1), // red
BACK_SLIDE_NOTE_COLOR(204, 2), // red
MASTER_VOL(1001, 3), // 0
SET_TITLE_ID(1002, 104001), // ID
SET_ICON_ID(1003, 102001), // ID
SET_NAV_ID(1004, 310001), // ID
SET_PLATE_ID(1005, 211001), // ID
}
val waccaRatingMult = linkedMapOf(
990_000 to 4.0,
980_000 to 3.75,
970_000 to 3.5,
960_000 to 3.25,
950_000 to 3.0,
940_000 to 2.75,
920_000 to 2.5,
900_000 to 2.0,
850_000 to 1.5,
800_000 to 1.0,
700_000 to 0.8,
600_000 to 0.7,
500_000 to 0.6,
400_000 to 0.5,
300_000 to 0.4,
200_000 to 0.3,
100_000 to 0.2,
1 to 0.1,
0 to 0.0
)
fun waccaRating(score: Int, level: Double): Int {
val mult = waccaRatingMult.entries.firstOrNull { score >= it.key }?.value ?: 0.0
return (level * mult * 10).toInt()
}
@@ -0,0 +1,10 @@
package icu.samnyan.aqua.sega.wacca.model
open class BaseRequest {
var requestNo: Int = 0
var appVersion: String = ""
var boardId: String = ""
var chipId: String = ""
var params: List<Any> = mutableListOf()
}
@@ -0,0 +1,74 @@
package icu.samnyan.aqua.sega.wacca.model.db
import ext.isoDate
import ext.ls
import ext.sec
import ext.toDate
import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.net.games.IUserData
import icu.samnyan.aqua.sega.general.IntegerListConverter
import icu.samnyan.aqua.sega.general.model.Card
import jakarta.persistence.*
import java.util.*
/**
* General user information
*/
@Entity @Table(name = "wacca_user")
class WaccaUser : BaseEntity(), IUserData {
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "aime_card_id", unique = true)
override var card: Card? = Card()
@Column(length = 8)
override var userName = ""
var xp = 0
var wp = 500
var wpTotal = 500
var wpSpent = 0
var danType = 0
var danLevel = 0
@Convert(converter = IntegerListConverter::class)
var titles: MutableList<Int> = mutableListOf(0, 0, 0)
override var playerRating = 0
override var highestRating = 0
@Temporal(TemporalType.TIMESTAMP)
var vipExpireTime: Date = Date(0)
var alwaysVip = false
var loginCount = 0
var loginCountDays = 0
var loginCountDaysConsec = 0
var loginCountToday = 0
@Convert(converter = IntegerListConverter::class)
var playCounts: MutableList<Int> = mutableListOf(0, 0, 0, 0, 0)
@Convert(converter = IntegerListConverter::class)
var friendViews: MutableList<Int> = mutableListOf(0, 0, 0)
@Column(length = 50)
override var lastClientId = ""
@Column(length = 50)
override var lastRomVersion = "1.0.0"
@Convert(converter = IntegerListConverter::class)
var lastSongInfo: MutableList<Int> = mutableListOf(0, 0, 0, 0, 0)
@Temporal(TemporalType.TIMESTAMP)
var lastConsecDate: Date = Date(0)
@Temporal(TemporalType.TIMESTAMP)
override var lastPlayDate: Date = Date()
@Temporal(TemporalType.TIMESTAMP)
override var firstPlayDate: Date = Date()
var gateTutorialFlags: String = "[[1, 0], [2, 0], [3, 0], [4, 0], [5, 0]]"
@Convert(converter = IntegerListConverter::class)
var favoriteSongs: MutableList<Int> = mutableListOf()
override var totalScore = 0L
fun lStatus() = ls(card?.extId,
userName, 1, xp, danLevel, danType, moddedWp, ls(0, 0, 0), loginCount, loginCountDays,
(loginCount - 1).coerceAtLeast(0), loginCountDaysConsec, moddedVipExpire.sec, loginCountToday, this.playerRating
)
val moddedVipExpire get() =
if (card?.aquaUser?.gameOptions?.waccaAlwaysVip == true) "2077-01-01".isoDate().toDate()
else vipExpireTime
val moddedWp get() = if (card?.aquaUser?.gameOptions?.waccaInfiniteWp == true) 999999 else wp
}
@@ -0,0 +1,157 @@
package icu.samnyan.aqua.sega.wacca.model.db
import com.fasterxml.jackson.annotation.JsonIgnore
import ext.*
import icu.samnyan.aqua.net.games.BaseEntity
import icu.samnyan.aqua.net.games.IGenericGamePlaylog
import icu.samnyan.aqua.net.games.IGenericUserMusic
import icu.samnyan.aqua.sega.general.IntegerListConverter
import icu.samnyan.aqua.sega.wacca.WaccaItemType
import icu.samnyan.aqua.sega.wacca.WaccaItemType.*
import jakarta.persistence.*
import java.util.*
typealias UC = UniqueConstraint
/**
* Base entity for all wacca user-related entities
*/
@MappedSuperclass
open class WaccaUserEntity : BaseEntity() {
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id")
open var user: WaccaUser = WaccaUser()
}
/**
* In-game option key-value storage
*/
@Entity @Table(name = "wacca_user_option", uniqueConstraints = [UC("", ["user_id", "opt_id"])])
class WcUserOption(
var optId: Int = 0,
var value: Int = 0
) : WaccaUserEntity()
@Entity @Table(name = "wacca_user_bingo", uniqueConstraints = [UC("", ["user_id", "page_number"])])
class WcUserBingo : WaccaUserEntity() {
var pageNumber = 0
var pageProgress = ""
}
/**
* The user here is the sender of the friend request.
*/
@Entity @Table(name = "wacca_friend", uniqueConstraints = [UC("", ["user_id", "with"])])
class WcUserFriend : WaccaUserEntity() {
@ManyToOne @JoinColumn(name = "with")
var with: WaccaUser = WaccaUser()
var isAccepted = false
}
@Entity @Table(name = "wacca_user_gate", uniqueConstraints = [UC("", ["user_id", "gate_id"])])
class WcUserGate : WaccaUserEntity() {
var gateId = 0
var page = 1
var progress = 0
var loops = 0
@Temporal(TemporalType.TIMESTAMP)
var lastUsed = Date(0)
var missionFlag = 0
var totalPoints = 0
fun ls() = ls(gateId, 1, page, progress, loops, lastUsed.sec, missionFlag)
}
@Entity @Table(name = "wacca_user_item", uniqueConstraints = [UC("", ["user_id", "item_id", "type"])])
class WcUserItem(
var type: Int = 0,
// Item prop represents different things based on the item type
var itemId: Int = 0,
var p1: Long = 0L,
var p2: Long = 0L,
var p3: Long = 0L,
@Temporal(TemporalType.TIMESTAMP)
var acquiredDate: Date = Date(),
) : WaccaUserEntity() {
fun ls() = when (type) {
MUSIC_UNLOCK() -> ls(itemId, p1, 0, acquiredDate.sec) // songId, diff, acquireDate, unlockDate
ICON() -> ls(itemId, 1, p1, acquiredDate.sec) // id, type, uses, acquiredDate
TROPHY() -> ls(itemId, p1, p2, p3) // id, season, progress, badgeType
SKILL() -> ls(itemId, p1, p2, p3) // skillType, level, flag, badge
TICKET() -> ls(id, itemId, p1) // userTicketId, ticketId, expire
NAVIGATOR() -> ls(itemId, 1, acquiredDate.sec, p1, p1) // id, type, acquiredDate, uses, usesToday
// Generic: title, note colors, note sounds, plates, touch effects
else -> ls(itemId, 1, acquiredDate.sec) // id, type, acquireDate
}
infix fun isType(t: WaccaItemType) = type == t()
}
@Entity @Table(name = "wacca_user_score", uniqueConstraints = [UC("", ["user_id", "music_id", "level"])])
class WcUserScore : WaccaUserEntity(), IGenericUserMusic {
override var musicId = 0
var level = 0 // aka difficulty
var achievement = 0
@Convert(converter = IntegerListConverter::class)
var clears: MutableList<Int> = mutableListOf(0, 0, 0, 0, 0) // Played, Clear, Full Combo, Missless, All Marv
@Convert(converter = IntegerListConverter::class)
var grades: MutableList<Int> = (1..13).map { 0 }.mut // From D to SSS+
var bestCombo = 0
var lowestMissCt = Int.MAX_VALUE
var rating = 0
fun ls() = ls(musicId, level, clears, clears, grades, achievement, bestCombo, lowestMissCt, 1, rating)
fun lsMusicUpdate() = ls(musicId, level, clears, clears, grades, achievement, lowestMissCt, 0, 1, rating)
}
@Entity @Table(name = "wacca_user_playlog", uniqueConstraints = [UC("", ["user_id", "music_id", "level", "user_play_date"])])
class WcUserPlayLog : WaccaUserEntity(), IGenericGamePlaylog {
override var musicId = 0
override var level = 0
var levelConst = 0.0
override var achievement = 0
@Convert(converter = IntegerListConverter::class)
var judgements: MutableList<Int> = mutableListOf(0, 0, 0, 0) // Marv, Great, Good, Miss
override var maxCombo = 0
var grade = 0
var isClear = false
var isMissless = false
override var isFullCombo = false
override var isAllPerfect = false
var giveUp = false
var skillPt = 0
var fastCt = 0
var lateCt = 0
var newRecord = false
override var beforeRating = 0
override var afterRating = 0
@Temporal(TemporalType.TIMESTAMP)
override var userPlayDate = Date()
fun clears() = ls(1, +isClear, +isFullCombo, +isMissless, +isAllPerfect)
companion object {
val keys = ls("musicId", "level", "levelConst", "achievement", "judgements", "maxCombo", "grade", "clear", "missless", "isFullCombo", "isAllPerfect", "giveUp", "skillPt", "fastCt", "lateCt", "newRecord")
fun parse(l: List<*>) = JACKSON.parse<WcUserPlayLog>(keys.zip(l).toMap())
}
}
@Entity @Table(name = "wacca_user_stageup", uniqueConstraints = [UC("", ["user_id", "stage_id"])])
class WcUserStageUp : WaccaUserEntity() {
var stageId = 0
var clearStatus = 0
var clearSongCt = 0
@Convert(converter = IntegerListConverter::class)
var songScores = mutableListOf(0, 0, 0)
var playCt = 0
fun ls(danLevel: Int) = ls(stageId, danLevel, clearStatus, clearSongCt, songScores, 1)
}