@@ -328,7 +313,7 @@ p.notice
opacity: 0.6
margin-top: 0
-.progress
+.progress
width: 100%
height: 10px
box-shadow: 0 0 1px 1px vars.$ov-lighter
@@ -463,10 +448,10 @@ p.notice
&.focused
filter: brightness(75%)
-.chuni-userbox
+.chuni-userbox
width: calc(100% - 20px)
height: 350px
-
+
display: flex
flex-direction: row
flex-wrap: wrap
diff --git a/AquaNet/src/libs/generalTypes.ts b/AquaNet/src/libs/generalTypes.ts
index d0d11942..99e72948 100644
--- a/AquaNet/src/libs/generalTypes.ts
+++ b/AquaNet/src/libs/generalTypes.ts
@@ -161,4 +161,4 @@ export interface ChusanMatchingOption {
matching: string
reflector: string
coop: string[]
-}
\ No newline at end of file
+}
diff --git a/AquaNet/src/libs/i18n/zh.ts b/AquaNet/src/libs/i18n/zh.ts
index 8eaae91e..dbc7e8ed 100644
--- a/AquaNet/src/libs/i18n/zh.ts
+++ b/AquaNet/src/libs/i18n/zh.ts
@@ -102,7 +102,7 @@ const zhHome: typeof EN_REF_HOME = {
'home.linkcard.account-card': "账户卡",
'home.linkcard.registered': "注册于",
'home.linkcard.lastused': "上次使用",
- 'home.linkcard.enter-info': "请输入以下信息",
+ 'home.linkcard.enter-info': "请输入以下信息,或将 aime.txt / felica.txt 文件拖放到此区域",
'home.linkcard.access-code': "卡背面的20位卡号 (如果没有, 请尝试在游戏中扫描您的卡, 并输入屏幕上显示的卡号)",
'home.linkcard.enter-sn1': "在您的手机",
'home.linkcard.enter-sn2': "上下载 NFC Tools 并扫描您的卡。然后输入显示的 SN 号。",
@@ -148,10 +148,14 @@ const zhSettings: typeof EN_REF_SETTINGS = {
'settings.fields.waccaInfiniteWp.desc': '将 WP 设置为 999999',
'settings.fields.waccaAlwaysVip.name': 'Wacca: 永久会员',
'settings.fields.waccaAlwaysVip.desc': '将 VIP 到期时间设置为 2077-01-01',
- 'settings.fields.chusanTeamName.name': '中二: 队伍名称',
+ 'settings.fields.chusanTeamName.name': '队伍名称',
'settings.fields.chusanTeamName.desc': '自定义显示在个人资料顶部的文本。',
- 'settings.fields.chusanInfinitePenguins.name': '中二: 无限企鹅',
+ 'settings.fields.chusanInfinitePenguins.name': '我是桐谷遥',
'settings.fields.chusanInfinitePenguins.desc': '将角色界限突破的企鹅雕像数量设置为 999。',
+ 'settings.fields.chusanMatchingReflector.name': '全国对战 Reflector',
+ 'settings.fields.chusanMatchingReflector.desc': '全国对战服务器的 UDP 反射服务器的 URL',
+ 'settings.fields.chusanMatchingServer.name': '全国对战服务器',
+ 'settings.fields.chusanMatchingServer.desc': '全国对战服务器的 URL',
'settings.fields.rounding.name': '分数舍入',
'settings.fields.rounding.desc': '把分数四舍五入到一位小数',
'settings.fields.optOutOfLeaderboard.name': '不参与排行榜',
@@ -168,10 +172,12 @@ const zhSettings: typeof EN_REF_SETTINGS = {
'settings.profile.unset': '未设置',
'settings.profile.unchanged': '未更改',
'settings.export': '导出玩家数据',
+ 'settings.cabNotice': '注意:下面这些设置只会影响你自己的机器,如果你是在其他人的机器上玩的话,请联系机主来改设置'
}
export const zhUserbox: typeof EN_REF_USERBOX = {
'userbox.header.general': '游戏设置',
+ 'userbox.header.matching': '全国对战',
'userbox.header.userbox': 'UserBox 设置',
'userbox.header.preview': 'UserBox 预览',
'userbox.nameplateId': '名牌',
@@ -189,7 +195,15 @@ export const zhUserbox: typeof EN_REF_USERBOX = {
'userbox.preview.notice': '「生存战略」:为了尊重版权,我们不会提供游戏内物品的图片。但是如果你认识其他愿意提供图床的人,在这里输入 URL 就可以显示出预览。',
'userbox.preview.url': '图床 URL',
'userbox.error.nodata': '未找到中二数据',
-
+
+ 'userbox.matching.select': '选择对战服务器',
+ 'userbox.matching.select.sub': '选择你想加入的跨服全国对战服务器',
+ 'userbox.matching.option.ui': '房间列表',
+ 'userbox.matching.option.guide': '教程',
+ 'userbox.matching.option.collab': '合作伙伴',
+ 'userbox.matching.custom.name': '自定义',
+ 'userbox.matching.custom.sub': '输入其他的匹配 URL',
+
'userbox.new.name': 'AquaBox',
'userbox.new.setup': '将 Chuni(Lumi 或更高版本)的游戏文件夹拖放到下方区域,以显示带有名牌和头像的 UserBox。所有文件都在浏览器中处理。',
'userbox.new.setup.processing_file': '正在处理文件',
diff --git a/AquaNet/src/libs/sdk.ts b/AquaNet/src/libs/sdk.ts
index 9b495f76..9761e99e 100644
--- a/AquaNet/src/libs/sdk.ts
+++ b/AquaNet/src/libs/sdk.ts
@@ -312,4 +312,6 @@ export const SETTING = {
post('/api/v2/settings/get', {}),
set: (key: string, value: any) =>
post('/api/v2/settings/set', { key, value: `${value}` }),
+ detailSet: (game: string, field: string, value: any) =>
+ post(`/api/v2/game/${game}/user-detail-set`, { field, value }),
}
diff --git a/AquaNet/src/libs/userbox/userbox.ts b/AquaNet/src/libs/userbox/userbox.ts
index 1a1a573a..6162105d 100644
--- a/AquaNet/src/libs/userbox/userbox.ts
+++ b/AquaNet/src/libs/userbox/userbox.ts
@@ -25,7 +25,7 @@ const validateDirectories = async (base: FileSystemDirectoryEntry, path: string)
let newDirectory = await getDirectory(directory, part).catch(_ => null);
if (newDirectory && isDirectory(newDirectory)) {
directory = newDirectory;
- } else
+ } else
return false;
};
return true
@@ -38,7 +38,7 @@ const getDirectoryFromPath = async (base: FileSystemDirectoryEntry, path: string
let newDirectory = await getDirectory(directory, part).catch(_ => null);
if (newDirectory && isDirectory(newDirectory)) {
directory = newDirectory;
- } else
+ } else
return null;
};
return directory;
@@ -81,7 +81,7 @@ const DIRECTORY_PATHS = ([
processName: "Surfboard Textures",
useFileName: true,
path: "surfboard",
- filter: (name: string) =>
+ filter: (name: string) =>
([
"CHU_UI_Common_Avatar_body_00.dds",
"CHU_UI_Common_Avatar_face_00.dds",
@@ -134,7 +134,7 @@ export const scanOptionFolder = async (optionFolder: FileSystemDirectoryEntry, p
let objectStore = transaction.objectStore('dds');
for (let object of data)
objectStore.put(object)
-
+
// await transaction completion
await new Promise(r => transaction.addEventListener("complete", r, {once: true}))
};
@@ -163,7 +163,7 @@ export function initializeDb() : Promise
{
export async function userboxFileProcess(folder: FileSystemEntry, progressUpdate: (progress: number, progressString: string) => void): Promise {
if (!isDirectory(folder))
return t("userbox.new.error.invalidFolder")
- if (!(await validateDirectories(folder, "bin/option")) || !(await validateDirectories(folder, "data/A000")))
+ if (!(await validateDirectories(folder, "bin/option")) && !(await validateDirectories(folder, "data/A000")))
return t("userbox.new.error.invalidFolder");
initializeDb();
@@ -179,4 +179,4 @@ export async function userboxFileProcess(folder: FileSystemEntry, progressUpdate
location.reload();
return null
-}
\ No newline at end of file
+}
diff --git a/AquaNet/src/pages/Home/LinkCard.svelte b/AquaNet/src/pages/Home/LinkCard.svelte
index 77ce9218..8c9e4dde 100644
--- a/AquaNet/src/pages/Home/LinkCard.svelte
+++ b/AquaNet/src/pages/Home/LinkCard.svelte
@@ -161,13 +161,10 @@
let inputAC = ""
let errorAC = ""
- function inputACChange(e: any) {
- e = e as InputEvent
+ function inputACChange() {
// Add spaces to the input
const old = inputAC
- if (e.inputType === "insertText" && inputAC.length % 5 === 4 && inputAC.length < 24)
- inputAC += " "
- inputAC = inputAC.slice(0, 24)
+ inputAC = inputAC.replace(/\D/g, '').replace(/(.{4})/g, '$1 ').replace(/ $/, '')
if (inputAC !== old) errorAC = ""
}
@@ -176,13 +173,10 @@
let inputSN = ""
let errorSN = ""
- function inputSNChange(e: any) {
- e = e as InputEvent
+ function inputSNChange() {
// Add colons to the input
const old = inputSN
- if (e.inputType === "insertText" && inputSN.length % 3 === 2 && inputSN.length < 23)
- inputSN += ":"
- inputSN = inputSN.toUpperCase().slice(0, 23)
+ inputSN = inputSN.toUpperCase().replace(/[^0-9A-F]/g, '').replace(/(.{2})/g, '$1:').replace(/:$/, '')
if (inputSN !== old) errorSN = ""
}
@@ -209,9 +203,29 @@
function isInput(e: KeyboardEvent) {
return e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey
}
+
+ async function dropFile(e: DragEvent) {
+ e.preventDefault()
+ e.stopPropagation()
+ const file = e.dataTransfer?.files[0]
+ if (!file) return
+ switch (file.name.toLowerCase()) {
+ case "aime.txt":
+ inputSN = ""
+ inputAC = await file.text()
+ inputACChange()
+ break
+ case "felica.txt":
+ inputAC = ""
+ inputSN = await file.text()
+ inputSNChange()
+ break
+ }
+ }
-
+
+
e.preventDefault()}>
{t('home.linkcard.cards')}
{t('home.linkcard.description')}:
diff --git a/AquaNet/src/pages/UserHome.svelte b/AquaNet/src/pages/UserHome.svelte
index 7e5a00f4..632ac016 100644
--- a/AquaNet/src/pages/UserHome.svelte
+++ b/AquaNet/src/pages/UserHome.svelte
@@ -195,7 +195,7 @@
{t('UserHome.ServerRank')}
- #{+d.user.serverRank.toLocaleString() + 1}
+ #{(d.user.serverRank + 1).toLocaleString()}
diff --git a/AquaNet/src/pages/Welcome.svelte b/AquaNet/src/pages/Welcome.svelte
index f01748c9..1af1ae4c 100644
--- a/AquaNet/src/pages/Welcome.svelte
+++ b/AquaNet/src/pages/Welcome.svelte
@@ -1,251 +1,255 @@
-
-
-
-
-
AquaNet
- {#if state === "home"}
-
- state = 'login'}>{t('welcome.btn-login')}
- state = 'signup'}>{t('welcome.btn-signup')}
-
- {:else if state === "login" || state === "signup"}
-
- {:else if state === "verify"}
-
- {verifyMsg}
- {#if !submitting}
- state = 'home'} transition:slide>{t('back')}
- {/if}
-
- {/if}
-
-
-
-
-
-
+
+
+
+
+
AquaNet
+ {#if state === "home"}
+
+ state = 'login'}>{t('welcome.btn-login')}
+ state = 'signup'}>{t('welcome.btn-signup')}
+
+ {:else if state === "login" || state === "signup"}
+
+ {:else if state === "verify"}
+
+ {verifyMsg}
+ {#if !submitting}
+ state = 'home'} transition:slide>{t('back')}
+ {/if}
+
+ {/if}
+
+
+
+
+
+
diff --git a/README.md b/README.md
index dc281483..d904f925 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Below is a list of games supported by this server.
| Game | Ver | Codename | Thanks to |
|----------------------------|------|---------------|--------------------------------------------|
| SDHD: CHUNITHM (Chusan) | 2.27 | LUMINOUS PLUS | [@rinsama](https://github.com/mxihan) |
-| SDEZ: MaiMai DX | 1.40 | BUDDiES | [@肥宅虾哥](https://github.com/FeiZhaixiage) |
+| SDEZ: MaiMai DX | 1.45 | BUDDiES PLUS | [@肥宅虾哥](https://github.com/FeiZhaixiage) |
| SDGA: MaiMai DX (International) | 1.45 | BUDDiES PLUS | [@Clansty](https://github.com/clansty) |
| SDED: Card Maker | 1.39 | | [@Becods](https://github.com/Becods) |
| SBZV: Project DIVA Arcade | 7.10 | Future Tone | |
diff --git a/build.gradle.kts b/build.gradle.kts
index f9a0b612..9abbc98a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -13,8 +13,8 @@ plugins {
kotlin("plugin.jpa") version ktVer
kotlin("plugin.serialization") version ktVer
kotlin("plugin.allopen") version ktVer
- id("io.freefair.lombok") version "8.11"
- id("org.springframework.boot") version "3.4.1"
+ id("io.freefair.lombok") version "8.6"
+ id("org.springframework.boot") version "3.2.3"
id("com.github.ben-manes.versions") version "0.51.0"
id("org.hibernate.orm") version "6.4.4.Final"
application
@@ -38,13 +38,13 @@ dependencies {
implementation("io.netty:netty-all")
implementation("org.apache.commons:commons-lang3:3.14.0")
implementation("org.apache.httpcomponents.client5:httpclient5")
- implementation("org.flywaydb:flyway-core:11.1.0")
- implementation("org.flywaydb:flyway-mysql:11.1.0")
+ implementation("org.flywaydb:flyway-core:10.10.0")
+ implementation("org.flywaydb:flyway-mysql:10.10.0")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
}
testImplementation("org.springframework.security:spring-security-test")
- implementation("net.logstash.logback:logstash-logback-encoder:8.0")
+ implementation("net.logstash.logback:logstash-logback-encoder:7.4")
// Metrics
implementation("org.springframework.boot:spring-boot-starter-actuator")
@@ -64,11 +64,11 @@ dependencies {
// =============================
// Network
- implementation("io.ktor:ktor-client-core:2.3.13")
- implementation("io.ktor:ktor-client-cio:2.3.13")
- implementation("io.ktor:ktor-client-content-negotiation:2.3.13")
- implementation("io.ktor:ktor-client-encoding:2.3.13")
- implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.13")
+ implementation("io.ktor:ktor-client-core:2.3.8")
+ implementation("io.ktor:ktor-client-cio:2.3.8")
+ implementation("io.ktor:ktor-client-content-negotiation:2.3.8")
+ implementation("io.ktor:ktor-client-encoding:2.3.8")
+ implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
// Somehow these are needed for ktor even though they're not in the documentation
@@ -76,16 +76,16 @@ dependencies {
runtimeOnly("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.8.0")
// Email
- implementation("org.simplejavamail:simple-java-mail:8.12.4")
- implementation("org.simplejavamail:spring-module:8.12.4")
+ implementation("org.simplejavamail:simple-java-mail:8.6.3")
+ implementation("org.simplejavamail:spring-module:8.6.3")
// GeoIP
- implementation("com.maxmind.geoip2:geoip2:4.2.1")
+ implementation("com.maxmind.geoip2:geoip2:4.2.0")
// JWT Authentication
- implementation("io.jsonwebtoken:jjwt-api:0.12.6")
- runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.6")
- runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.6")
+ implementation("io.jsonwebtoken:jjwt-api:0.12.5")
+ runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.5")
+ runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.5")
// Content validation
implementation("org.apache.tika:tika-core:2.9.1")
@@ -94,8 +94,7 @@ dependencies {
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.0")
// Serialization
- // DO NOT UPDATE THIS TO >2.18.0: https://github.com/FasterXML/jackson-module-kotlin/issues/874
- implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.3")
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
// Testing
testImplementation("io.kotest:kotest-runner-junit5-jvm:5.8.1")
diff --git a/config/application.properties b/config/application.properties
index 807b8ec1..0340d592 100644
--- a/config/application.properties
+++ b/config/application.properties
@@ -53,9 +53,6 @@ game.chusan.reflector-url=http://reflector.naominet.live:18080/
## This sets the matching server url.
## When this is set, we will sync with the external matching url so that we can match with more players.
game.chusan.external-matching=https://chu3-match.sega.ink/
-## When this is set to true, we will proxy all matching requests sent to the external matching server.
-## This option enhances security by masking the user ID and keychip.
-game.chusan.proxied-matching=false
## This enables user use login bonus function if set to true.
## NOTE: THIS IS NOT TESTED, it's implemented by someone very inexperienced and might not work.
game.chusan.loginbonus-enable=false
diff --git a/docs/chu3-national-matching.md b/docs/chu3-national-matching.md
new file mode 100644
index 00000000..b5cbc1a0
--- /dev/null
+++ b/docs/chu3-national-matching.md
@@ -0,0 +1,79 @@
+# Chunithm National Matching Guide
+
+The national matching game mode allows up to 4 players on any server (YES, ANY SERVER) to play together.
+In this game mode, for example, you can play with RinNET or Missless players as well.
+This is a guide on how to set up your client for national matching.
+
+This is tested on Chusan 2.27.
+
+## Pre-requisites
+
+- Play the normal game at least once so that you have a profile on the server.
+- NAT Type must not be Symmetric ([Check here](https://www.checkmynat.com/))
+- Your firewall must be turned off (or [add a rule that allows chusanApp](#firewall-rules))
+
+## Setting Up
+
+
+
+1. Go to the AquaNet website and set your matching server to "Yukiotoko"
+ (To go to the settings page, click on the gear icon in the top right corner of your profile, switch to chuni tab, scroll down, click "Select Matching Server")
+2. Make sure you use [Dniel97's open-source segatools](https://gitea.tendokyu.moe/Dniel97/SEGAguide/wiki/SDHD)
+ If you're using fufubot segatools, please override it with Dniel97's version (don't forget to update `segatools.ini`).
+3. Patch your `chusanApp.exe` using [Two-Torial's open-source patcher](https://patcher.two-torial.xyz/)
+ (Make sure you disable "Set all timer to 999", enable "No encryption", "No TLS", "Patch for head-to-head play")
+4. Add the option [ARRR](https://pixeldrain.com/u/D2jjN3of).
+ If you're playing with friends, make sure they have the same options as you.
+5. Pet your cat 🐈
+6. Launch!
+
+
+### Firewall Rules
+
+Below is a simple command to add firewall rules for Chunithm.
+
+```shell
+@echo off
+set /p gamedirectory = Make sure this is run as admin and enter game path (e.g. C:\SegaGames\Chunithm\bin\chusanApp.exe)\n
+netsh advfirewall firewall add rule name="Chunithm National Matching Inbound" dir=in action=allow profile=any program="%gamedirectory%" enable=yes
+netsh advfirewall firewall add rule name="Chunithm National Matching Outbound" dir=out action=allow profile=any program="%gamedirectory%" enable=yes
+```
+
+## Troubleshooting
+
+**Q: Game crashes when entering match mode**
+
+Make sure you are using Dniel97's segatools.
+
+**Q: After matching, timer shows 999 seconds and nobody can start**
+
+Make sure you have patched your `chusanApp.exe` correctly.
+
+**Q: Online battle icon gray / "Unable to select after the event time"**
+
+Make sure your time zone is set to JST (UTC+9).
+
+**Q: This window show up when joining.**
+
+
+
+If there is only one player, then yea it's because there are not enough players.
+Otherwise, it's because one of the players has a bad network environment (e.g. Symmetric NAT).
+Try again with someone who played this mode before, if it still doesn't work, then it's probably you.
+
+**Q: Why did I play two of the same songs in a row?**
+
+When other people picked a song that you don't have, the game will play the same song as the previous one.
+Make sure you have up-to-date options in your game.
+(Or they might have selected a custom chart, in that case there's not much you can do)
+
+## How to Play
+
+When you enter the matching mode, it will assign to you a matching room if other people are online, or create a new room otherwise.
+Then, after four people are present or after a specific amount of time has passed, the game will start.
+Everyone will be asked to pick a song at the start, even though your song might not be the first one to be played.
+After songs are picked, other players will play the song on the SAME DIFFICULTY as what you picked.
+(So be a nice person and don't pick 15 if there are new players alright? 🥺)
+
+If there are less than 4 players when the timer runs out, the game will fill in the empty slots with bots.
+The bots will randomly select a song (mostly under Lv10).
diff --git a/docs/img/chu3-matching-error.png b/docs/img/chu3-matching-error.png
new file mode 100644
index 00000000..6bb0a43c
Binary files /dev/null and b/docs/img/chu3-matching-error.png differ
diff --git a/docs/img/chu3-matching.png b/docs/img/chu3-matching.png
new file mode 100644
index 00000000..6604f515
Binary files /dev/null and b/docs/img/chu3-matching.png differ
diff --git a/src/main/java/ext/Ext.kt b/src/main/java/ext/Ext.kt
index 9671ac8b..0fdcfe53 100644
--- a/src/main/java/ext/Ext.kt
+++ b/src/main/java/ext/Ext.kt
@@ -6,6 +6,8 @@ import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*
import jakarta.persistence.Query
+import jakarta.servlet.http.HttpServletRequest
+import jakarta.servlet.http.HttpServletResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.apache.tika.Tika
@@ -16,6 +18,7 @@ import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity.BodyBuilder
import org.springframework.web.bind.annotation.*
import java.lang.reflect.Field
+import java.nio.charset.StandardCharsets
import java.nio.file.Path
import java.security.MessageDigest
import java.time.LocalDate
@@ -44,6 +47,19 @@ typealias JavaSerializable = java.io.Serializable
typealias JDict = Map
typealias MutJDict = MutableMap
+fun HttpServletRequest.details() = mapOf(
+ "method" to method,
+ "uri" to requestURI,
+ "query" to queryString,
+ "remote" to remoteAddr,
+ "headers" to headerNames.asSequence().associateWith { getHeader(it) }
+)
+
+fun HttpServletResponse.details() = mapOf(
+ "status" to status,
+ "headers" to headerNames.asSequence().associateWith { getHeader(it) },
+)
+
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER)
@Retention(AnnotationRetention.RUNTIME)
annotation class Doc(
@@ -120,6 +136,7 @@ fun LocalDateTime.isoDateTime() = format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
fun String.isoDateTime() = LocalDateTime.parse(this, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
val URL_SAFE_DT = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")
fun LocalDateTime.urlSafeStr() = format(URL_SAFE_DT)
+val DATE_2018 = LocalDateTime.parse("2018-01-01T00:00:00")
val ALT_DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
fun Str.asDateTime() = try { LocalDateTime.parse(this, DateTimeFormatter.ISO_LOCAL_DATE_TIME) }
@@ -173,17 +190,22 @@ val Any?.truthy get() = when (this) {
fun ls(vararg args: T) = args.toList()
inline fun arr(vararg args: T) = arrayOf(*args)
operator fun Map.plus(map: Map) =
- (if (this is MutableMap) this else toMutableMap()).apply { putAll(map) }
+ (if (this is MutableMap) this else mut).apply { putAll(map) }
operator fun MutableMap.plusAssign(map: Map) { putAll(map) }
fun Map.vNotNull(): Map = filterValues { it != null }.mapValues { it.value!! }
fun MutableList.popAll(list: List) = list.also { removeAll(it) }
fun MutableList.popAll(vararg items: T) = popAll(items.toList())
inline fun Iterable.mapApply(block: T.() -> Unit) = map { it.apply(block) }
+inline fun Iterable.mapApplyI(block: T.(Int) -> Unit) = mapIndexed { i, e -> e.apply { block(i) } }
@Suppress("UNCHECKED_CAST")
fun Map.recursiveNotNull(): Map = mapNotNull { (k, v) ->
k to if (v is Map<*, *>) (v as Map).recursiveNotNull() else v
}.toMap() as Map
+val List.mut get() = toMutableList()
+val Map.mut get() = toMutableMap()
+val Set.mut get() = toMutableSet()
+
// Optionals
operator fun Optional.invoke(): T? = orElse(null)
fun Optional.expect(message: Str = "Value is not present") = orElseGet { (400 - message) }
@@ -195,6 +217,7 @@ fun Str.center(width: Int, padChar: Char = ' ') = padStart((length + width) / 2,
fun Str.splitLines() = replace("\r\n", "\n").split('\n')
@OptIn(ExperimentalStdlibApi::class)
fun Str.md5() = MD5.digest(toByteArray(Charsets.UTF_8)).toHexString()
+fun Str.fromChusanUsername() = String(this.toByteArray(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)
// Coroutine
suspend fun async(block: suspend kotlinx.coroutines.CoroutineScope.() -> T): T = withContext(Dispatchers.IO) { block() }
diff --git a/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/v2/ApiChuniV2PlayerDataController.java b/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/v2/ApiChuniV2PlayerDataController.java
deleted file mode 100644
index d92fc4b2..00000000
--- a/src/main/java/icu/samnyan/aqua/api/controller/sega/game/chuni/v2/ApiChuniV2PlayerDataController.java
+++ /dev/null
@@ -1,316 +0,0 @@
-package icu.samnyan.aqua.api.controller.sega.game.chuni.v2;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import icu.samnyan.aqua.api.model.MessageResponse;
-import icu.samnyan.aqua.api.model.ReducedPageResponse;
-import icu.samnyan.aqua.api.model.resp.sega.chuni.v2.RecentResp;
-import icu.samnyan.aqua.api.model.resp.sega.chuni.v2.external.Chu3DataExport;
-import icu.samnyan.aqua.api.util.ApiMapper;
-import icu.samnyan.aqua.sega.chusan.model.userdata.*;
-import icu.samnyan.aqua.sega.chusan.service.*;
-import icu.samnyan.aqua.sega.general.service.CardService;
-import lombok.AllArgsConstructor;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Sort;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.*;
-
-/**
- * For all aimeId parameter, should use String
- * @author samnyan (privateamusement@protonmail.com)
- */
-@RestController
-@RequestMapping("api/game/chuni/v2")
-@ConditionalOnProperty(prefix = "aquaviewer.api", name = "enabled", havingValue = "true")
-@AllArgsConstructor
-public class ApiChuniV2PlayerDataController {
-
- private static final Logger logger = LoggerFactory.getLogger(ApiChuniV2PlayerDataController.class);
-
- private final ApiMapper mapper;
-
- private final CardService cardService;
-
- private final UserActivityService userActivityService;
- private final UserCharacterService userCharacterService;
- private final UserChargeService userChargeService;
- private final UserCourseService userCourseService;
- private final UserDataService userDataService;
- private final UserDuelService userDuelService;
- private final UserGameOptionService userGameOptionService;
- private final UserItemService userItemService;
- private final UserMapAreaService userMapAreaService;
- private final UserMusicDetailService userMusicDetailService;
- private final UserPlaylogService userPlaylogService;
- private final UserGeneralDataService userGeneralDataService;
-
- @PutMapping("profile/username")
- public Chu3UserData updateName(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setUserName((String) request.get("userName"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/romversion")
- public Chu3UserData updateRomVersion(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setLastRomVersion((String) request.get("romVersion"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/dataversion")
- public Chu3UserData updateDataVersion(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setLastDataVersion((String) request.get("dataVersion"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/plate")
- public Chu3UserData updatePlate(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setNameplateId((Integer) request.get("nameplateId"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/frame")
- public Chu3UserData updateFrame(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setFrameId((Integer) request.get("frameId"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/trophy")
- public Chu3UserData updateTrophy(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setTrophyId((Integer) request.get("trophyId"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/mapicon")
- public Chu3UserData updateMapIcon(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setMapIconId((Integer) request.get("mapiconId"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/sysvoice")
- public Chu3UserData updateSystemVoice(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- profile.setVoiceId((Integer) request.get("voiceId"));
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/avatar")
- public Chu3UserData updateAvatar(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- int category = (Integer) request.get("category");
- switch (category) {
- case 1:
- profile.setAvatarWear((Integer) request.get("accId"));
- break;
- case 2:
- profile.setAvatarHead((Integer) request.get("accId"));
- break;
- case 3:
- profile.setAvatarFace((Integer) request.get("accId"));
- break;
- case 4:
- profile.setAvatarSkin((Integer) request.get("accId"));
- break;
- case 5:
- profile.setAvatarItem((Integer) request.get("accId"));
- break;
- case 6:
- profile.setAvatarFront((Integer) request.get("accId"));
- break;
- case 7:
- profile.setAvatarBack((Integer) request.get("accId"));
- break;
- }
-
- return userDataService.saveUserData(profile);
- }
-
- @PutMapping("profile/privacy")
- public ResponseEntity updatePrivacy(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- UserGameOption option = userGameOptionService.getByUser(profile).orElseThrow();
- int privacy = (Integer) request.get("privacy");
- if (privacy != 1 && privacy != 0) {
- return ResponseEntity.badRequest().body(new MessageResponse("Wrong data"));
- }
- option.setPrivacy(privacy);
- return ResponseEntity.ok(userDataService.saveUserData(profile));
- }
-
- @GetMapping("recent")
- public ReducedPageResponse getRecentPlay(@RequestParam String aimeId,
- @RequestParam(required = false, defaultValue = "0") int page,
- @RequestParam(required = false, defaultValue = "10") int size) {
- Page playLogs = userPlaylogService.getRecentPlays(aimeId, PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "userPlayDate")));
- return new ReducedPageResponse<>(mapper.convert(playLogs.getContent(), new TypeReference<>() {
- }), playLogs.getPageable().getPageNumber(), playLogs.getTotalPages(), playLogs.getTotalElements());
- }
-
- @GetMapping("song/{id}")
- public List getSongDetail(@RequestParam String aimeId, @PathVariable int id) {
- return userMusicDetailService.getByUserIdAndMusicId(aimeId, id);
- }
-
- @GetMapping("song/{id}/{level}")
- public List getLevelPlaylog(@RequestParam String aimeId, @PathVariable int id, @PathVariable int level) {
- return userPlaylogService.getByUserIdAndMusicIdAndLevel(aimeId, id, level);
- }
-
- @GetMapping("song/{id}/isfavorite")
- public boolean getSongFavorite(@RequestParam String aimeId, @PathVariable String id) {
- Optional favOptional;
- favOptional = userGeneralDataService.getByUserIdAndKey(aimeId, "favorite_music");
- if(favOptional.isPresent()) {
- String val = favOptional.get().getPropertyValue();
- if(StringUtils.isNotBlank(val) && val.contains(",")) {
- String[] records = val.split(",");
- for (String record : records) {
- if (record.equals(id)) return true;
- }
- }
- }
- return false;
- }
-
- @PutMapping("song/{id}/favorite")
- public void updateSongFavorite(@RequestParam String aimeId, @PathVariable String id) {
- Chu3UserData profile = userDataService.getUserByExtId(aimeId).orElseThrow();
- UserGeneralData userGeneralData = userGeneralDataService.getByUserAndKey(profile, "favorite_music")
- .orElseGet(() -> new UserGeneralData(profile, "favorite_music"));
- List favoriteSongs = new LinkedList(Arrays.asList(userGeneralData.getPropertyValue().split(",")));
-
- if(!favoriteSongs.remove(id))
- {
- favoriteSongs.add(id);
- }
-
- StringBuilder sb = new StringBuilder();
- favoriteSongs.forEach(favSong -> {
- if(!favSong.isEmpty()) sb.append(favSong).append(",");
- });
-
- userGeneralData.setPropertyValue(sb.toString());
- userGeneralDataService.save(userGeneralData);
- }
-
- @GetMapping("character")
- public ReducedPageResponse getCharacter(@RequestParam String aimeId,
- @RequestParam(required = false, defaultValue = "0") int page,
- @RequestParam(required = false, defaultValue = "10") int size) {
- Page characters = userCharacterService.getByUserId(aimeId, page, size);
- return new ReducedPageResponse<>(characters.getContent(), characters.getPageable().getPageNumber(), characters.getTotalPages(), characters.getTotalElements());
- }
-
- @PostMapping("character")
- public ResponseEntity updateCharacter(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- Integer characterId = (Integer) request.get("characterId");
- Optional characterOptional = userCharacterService.getByUserAndCharacterId(profile, characterId);
- UserCharacter character;
- if(characterOptional.isPresent()) {
- character = characterOptional.get();
- } else {
- character = new UserCharacter(profile);
- character.setCharacterId(characterId);
- }
- if(request.containsKey("level")) {
- character.setLevel((Integer) request.get("level"));
- }
-
- return ResponseEntity.ok(userCharacterService.save(character));
- }
-
- @GetMapping("course")
- public List getCourse(@RequestParam String aimeId) {
- return userCourseService.getByUserId(aimeId);
- }
-
- @GetMapping("duel")
- public List getDuel(@RequestParam String aimeId) {
- return userDuelService.getByUserId(aimeId);
- }
-
- @GetMapping("item")
- public ReducedPageResponse getItem(@RequestParam String aimeId,
- @RequestParam(required = false, defaultValue = "0") int page,
- @RequestParam(required = false, defaultValue = "10") int size) {
- Page items = userItemService.getByUserId(aimeId, page, size);
- return new ReducedPageResponse<>(items.getContent(), items.getPageable().getPageNumber(), items.getTotalPages(), items.getTotalElements());
- }
-
- @GetMapping("item/{itemKind}")
- public List getItemByKind(@RequestParam String aimeId, @PathVariable int itemKind) {
- return userItemService.getByUserAndItemKind(aimeId, itemKind);
- }
-
- @PostMapping("item")
- public ResponseEntity updateItem(@RequestBody Map request) {
- Chu3UserData profile = userDataService.getUserByExtId((String) request.get("aimeId")).orElseThrow();
- Integer itemId = (Integer) request.get("itemId");
- Integer itemKind = (Integer) request.get("itemKind");
- Optional itemOptional = userItemService.getByUserAndItemIdAndKind(profile, itemId,itemKind);
- UserItem item;
- if(itemOptional.isPresent()) {
- item = itemOptional.get();
- } else {
- item = new UserItem(profile);
- item.setItemId(itemId);
- item.setItemKind(itemKind);
- }
- if(request.containsKey("stock")) {
- item.setStock((Integer) request.get("stock"));
- }
- return ResponseEntity.ok(userItemService.save(item));
- }
-
- @GetMapping("general")
- public ResponseEntity getGeneralData(@RequestParam String aimeId, @RequestParam String key) {
- Optional userGeneralDataOptional = userGeneralDataService.getByUserIdAndKey(aimeId,key);
- return userGeneralDataOptional.>map(ResponseEntity::ok)
- .orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND).body(new MessageResponse("User or value not found.")));
- }
-
- @GetMapping("export")
- public ResponseEntity exportAllUserData(@RequestParam String aimeId) {
- Chu3DataExport data = new Chu3DataExport();
- try {
- data.setGameId("SDHD");
- data.setUserData(userDataService.getUserByExtId(aimeId).orElseThrow());
- data.setUserActivityList(userActivityService.getByUserId(aimeId));
- data.setUserCharacterList(userCharacterService.getByUserId(aimeId));
- data.setUserChargeList(userChargeService.getByUserId(aimeId));
- data.setUserCourseList(userCourseService.getByUserId(aimeId));
- data.setUserDuelList(userDuelService.getByUserId(aimeId));
- data.setUserGameOption(userGameOptionService.getByUserId(aimeId).orElseThrow());
- data.setUserItemList(userItemService.getByUserId(aimeId));
- data.setUserMapList(userMapAreaService.getByUserId(aimeId));
- data.setUserMusicDetailList(userMusicDetailService.getByUserId(aimeId));
- data.setUserPlaylogList(userPlaylogService.getByUserId(aimeId));
- } catch (NoSuchElementException e) {
- return ResponseEntity.status(HttpStatus.NOT_FOUND)
- .body(new MessageResponse("User not found"));
- } catch (Exception e) {
- return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
- .body(new MessageResponse("Error during data export. Reason: " + e.getMessage()));
- }
- // Set filename
- HttpHeaders headers = new HttpHeaders();
- headers.set("content-disposition", "attachment; filename=chusan_" + aimeId + "_exported.json");
- return new ResponseEntity<>(data, headers, HttpStatus.OK);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/net/Bot.kt b/src/main/java/icu/samnyan/aqua/net/Bot.kt
index c7f0bd5b..96b9b8d6 100644
--- a/src/main/java/icu/samnyan/aqua/net/Bot.kt
+++ b/src/main/java/icu/samnyan/aqua/net/Bot.kt
@@ -57,11 +57,11 @@ class BotController(
us.cardRepo.findByExtId(cardId.long)(),
us.cardRepo.findByLuid(cardId)(),
us.cardRepo.findById(cardId.long)(),
- ).toMutableList()
+ ).mut
cards += cards.flatMap {
(it.aquaUser?.cards ?: emptyList()) + listOfNotNull(it.aquaUser?.ghostCard)
}
- cards = cards.distinctBy { it.id }.toMutableList()
+ cards = cards.distinctBy { it.id }.mut
return cards.map { card ->
// Find all games played by this card
diff --git a/src/main/java/icu/samnyan/aqua/net/Safety.kt b/src/main/java/icu/samnyan/aqua/net/Safety.kt
index ecf6bf6a..04588caf 100644
--- a/src/main/java/icu/samnyan/aqua/net/Safety.kt
+++ b/src/main/java/icu/samnyan/aqua/net/Safety.kt
@@ -1,6 +1,7 @@
package icu.samnyan.aqua.net
import ext.HTTP
+import ext.mut
import ext.toJson
import icu.samnyan.aqua.net.games.BaseEntity
import io.ktor.client.call.*
@@ -54,8 +55,8 @@ class AquaNetSafetyService(
*/
suspend fun isSafeBatch(rawContents: List): List {
val contents = rawContents.map { Normalizer.normalize(it, Normalizer.Form.NFKC) }
- val origMap = safety.findAll().associateBy { it.content }.toMutableMap()
- val map = safety.findAll().associateBy { it.content.lowercase().trim() }.toMutableMap()
+ val origMap = safety.findAll().associateBy { it.content }.mut
+ val map = safety.findAll().associateBy { it.content.lowercase().trim() }.mut
// Process unseen content with OpenAI
val news = contents.filter { it.lowercase().trim() !in map && it !in contents }.map { inp ->
diff --git a/src/main/java/icu/samnyan/aqua/net/db/AquaGameOptions.kt b/src/main/java/icu/samnyan/aqua/net/db/AquaGameOptions.kt
index 4dae0883..7e7022e1 100644
--- a/src/main/java/icu/samnyan/aqua/net/db/AquaGameOptions.kt
+++ b/src/main/java/icu/samnyan/aqua/net/db/AquaGameOptions.kt
@@ -37,6 +37,12 @@ class AquaGameOptions(
@SettingField("chu3")
var chusanInfinitePenguins: Boolean = false,
+
+ @SettingField("chu3-matching")
+ var chusanMatchingServer: String = "",
+
+ @SettingField("chu3-matching")
+ var chusanMatchingReflector: String = "",
)
interface AquaGameOptionsRepo : JpaRepository
diff --git a/src/main/java/icu/samnyan/aqua/net/games/GameApiController.kt b/src/main/java/icu/samnyan/aqua/net/games/GameApiController.kt
index 59152ba2..e37d2569 100644
--- a/src/main/java/icu/samnyan/aqua/net/games/GameApiController.kt
+++ b/src/main/java/icu/samnyan/aqua/net/games/GameApiController.kt
@@ -24,6 +24,7 @@ abstract class GameApiController(val name: String, userDataClass:
abstract val playlogRepo: GenericPlaylogRepo<*>
abstract val shownRanks: List>
abstract val settableFields: Map Unit>
+ open val gettableFields: Set = setOf()
@API("trend")
abstract suspend fun trend(@RP username: String): List
@@ -110,7 +111,8 @@ abstract class GameApiController(val name: String, userDataClass:
fun playlog(@RP id: Long): IGenericGamePlaylog = playlogRepo.findById(id).getOrNull() ?: (404 - "Playlog not found")
val userDetailFields by lazy { userDataClass.gettersMap().let { vm ->
- settableFields.map { (k, _) -> k to (vm[k] ?: error("Field $k not found")) }.toMap()
+ (settableFields.keys.toSet() + gettableFields)
+ .associateWith { k -> (vm[k] ?: error("Field $k not found")) }
} }
@API("user-detail")
@@ -144,13 +146,13 @@ abstract class GameApiController(val name: String, userDataClass:
plays.forEach { play ->
val lvl = musicMapping[play.musicId]?.notes?.getOrNull(if (play.level == 10) 0 else play.level)?.lv ?: return@forEach
shownRanks.find { (s, _) -> play.achievement > s }?.let { (_, v) ->
- val ranks = detailedRanks.getOrPut(lvl.toInt()) { rankMap.toMutableMap() }
+ val ranks = detailedRanks.getOrPut(lvl.toInt()) { rankMap.mut }
ranks[v] = ranks[v]!! + 1
}
}
// Collapse detailed ranks to get non-detailed ranks map
- val ranks = shownRanks.associate { (_, v) -> v to 0 }.toMutableMap().also { ranks ->
+ val ranks = shownRanks.associate { (_, v) -> v to 0 }.mut.also { ranks ->
plays.forEach { play ->
shownRanks.find { (s, _) -> play.achievement > s }?.let { (_, v) -> ranks[v] = ranks[v]!! + 1 }
}
diff --git a/src/main/java/icu/samnyan/aqua/net/games/GameHelper.kt b/src/main/java/icu/samnyan/aqua/net/games/GameHelper.kt
index 0bd09f87..7bed80c0 100644
--- a/src/main/java/icu/samnyan/aqua/net/games/GameHelper.kt
+++ b/src/main/java/icu/samnyan/aqua/net/games/GameHelper.kt
@@ -2,6 +2,7 @@ package icu.samnyan.aqua.net.games
import ext.isoDate
import ext.minus
+import ext.mut
import java.time.LocalDate
const val LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
@@ -20,7 +21,7 @@ fun usernameCheck(chars: String): (IUserData, String) -> Unit = { u, v ->
u.userName = v
if (v.isBlank()) { 400 - "Username cannot be blank" }
if (v.length > 8) { 400 - "Username too long" }
- v.find { it !in chars }?.let { 400 - "Invalid character '$it' in username" }
+// v.find { it !in chars }?.let { 400 - "Invalid character '$it' in username" }
}
fun toFullWidth(input: String): String {
@@ -60,7 +61,7 @@ fun findTrend(log: List): List {
val trend = d.distinctBy { it.date }
.map { TrendOut(it.date, maxRating[it.date] ?: 0,
playCounts[it.date] ?: 0) }
- .sortedBy { it.date }.toMutableList()
+ .sortedBy { it.date }.mut
// Fill in the missing dates (min date and current date)
trend[0].let { if (it.date > minDate) trend.add(0, TrendOut(minDate, 0, 0)) }
diff --git a/src/main/java/icu/samnyan/aqua/net/games/chu3/Chusan.kt b/src/main/java/icu/samnyan/aqua/net/games/chu3/Chusan.kt
index a72fc24c..13102502 100644
--- a/src/main/java/icu/samnyan/aqua/net/games/chu3/Chusan.kt
+++ b/src/main/java/icu/samnyan/aqua/net/games/chu3/Chusan.kt
@@ -38,6 +38,7 @@ class Chusan(
"avatarFront" to { u, v -> u.avatarFront = v.int },
"avatarBack" to { u, v -> u.avatarBack = v.int },
) }
+ override val gettableFields: Set = setOf("level", "playerRating", "characterId")
override suspend fun userSummary(@RP username: Str, @RP token: String?) = us.cardByName(username) { card ->
// Summary values: total plays, player rating, server-wide ranking
@@ -61,15 +62,4 @@ class Chusan(
val u = userDataRepo.findByCard(it.ghostCard) ?: (404 - "Game data not found")
mapOf("user" to u, "items" to rp.userItem.findAllByUser(u))
}
-
- @API("user-box-all-items")
- fun userBoxAllItems() = allItems
- val allItems by lazy { mapOf(
- "nameplate" to rp.gameNamePlate.findAll(),
- "frame" to rp.gameFrame.findAll(),
- "trophy" to rp.gameTrophy.findAll(),
- "mapicon" to rp.gameMapIcon.findAll(),
- "sysvoice" to rp.gameSystemVoice.findAll(),
- "avatar" to rp.gameAvatarAcc.findAll(),
- ) }
}
diff --git a/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt b/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt
index cbab54ed..03113c50 100644
--- a/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt
+++ b/src/main/java/icu/samnyan/aqua/net/games/mai2/Maimai2.kt
@@ -26,9 +26,7 @@ class Maimai2(
// Only show > S rank
override val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 }
override val settableFields: Map Unit> by lazy {
- mapOf(
- "userName" to usernameCheck(SEGA_USERNAME_CAHRS),
- )
+ mapOf("userName" to usernameCheck(SEGA_USERNAME_CAHRS))
}
override suspend fun userSummary(@RP username: Str, @RP token: String?) = us.cardByName(username) { card ->
@@ -127,7 +125,7 @@ class Maimai2(
user = repos.userData.findByCardExtId(myCard.extId).orElse(null) ?: (404 - "User not found")
propertyKey = "favorite_rival"
}
- val myRivalList = myRival.propertyValue.split(',').filter { it.isNotEmpty() }.toMutableSet()
+ val myRivalList = myRival.propertyValue.split(',').filter { it.isNotEmpty() }.mut
if (isAdd && myRivalList.size >= 4) {
(400 - "Rival list is full")
diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDB.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDB.kt
index 40b691c9..216393cf 100644
--- a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDB.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDB.kt
@@ -2,9 +2,9 @@ package icu.samnyan.aqua.sega.aimedb
import ext.toHex
import icu.samnyan.aqua.net.db.AquaUserServices
+import icu.samnyan.aqua.sega.allnet.AllNetProps
import icu.samnyan.aqua.sega.general.model.Card
import icu.samnyan.aqua.sega.general.service.CardService
-import icu.samnyan.aqua.sega.allnet.AllNetProps
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufUtil
import io.netty.buffer.Unpooled
@@ -67,7 +67,8 @@ class AimeDB(
logger.info("AimeDB /${handler.name} : (game ${base.gameId}, keychip ${base.keychipId})")
// Check keychip
- if (!us.validKeychip(base.keychipId)) {
+ // We do not check for type 0x13 because of a bug in duolinguo.dll
+ if (!us.validKeychip(base.keychipId) && type != 0x13) {
if (allNetProps.keychipPermissiveForTesting) {
logger.warn("> Accepted invalid keychip ${base.keychipId} in permissive mode")
} else {
diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNet.kt b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNet.kt
index f7375110..d02fd4be 100644
--- a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNet.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNet.kt
@@ -139,7 +139,7 @@ class AllNet(
val ver = reqMap["ver"] ?: "1.0"
val formatVer = reqMap["format_ver"] ?: ""
- val resp = props.map.toMutableMap() + mapOf(
+ val resp = props.map.mut + mapOf(
"uri" to switchUri(localAddr, localPort, gameId, ver, session),
"host" to props.host.ifBlank { localAddr },
)
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt
index aab260a3..ecf317e0 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt
@@ -4,9 +4,10 @@ import ext.*
import icu.samnyan.aqua.net.db.AquaUserServices
import icu.samnyan.aqua.net.utils.simpleDescribe
import icu.samnyan.aqua.sega.allnet.TokenChecker
-import icu.samnyan.aqua.sega.chusan.handler.*
+import icu.samnyan.aqua.sega.chusan.handler.chusanInit
import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
-import icu.samnyan.aqua.sega.general.*
+import icu.samnyan.aqua.sega.general.MeowApi
+import icu.samnyan.aqua.sega.general.RequestContext
import icu.samnyan.aqua.sega.util.jackson.BasicMapper
import icu.samnyan.aqua.sega.util.jackson.StringMapper
import icu.samnyan.aqua.spring.Metrics
@@ -14,7 +15,6 @@ import jakarta.servlet.http.HttpServletRequest
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.RestController
import kotlin.collections.set
-import kotlin.reflect.full.declaredMemberProperties
/**
* @author samnyan (privateamusement@protonmail.com)
@@ -23,12 +23,6 @@ import kotlin.reflect.full.declaredMemberProperties
@RestController
@API(value = ["/g/chu3/{version}/ChuniServlet", "/g/chu3/{version}"])
class ChusanController(
- val gameLogin: GameLoginHandler,
- val upsertUserAll: UpsertUserAllHandler,
- val cmUpsertUserGacha: CMUpsertUserGachaHandler,
- val cmUpsertUserPrintSubtract: CMUpsertUserPrintSubtractHandler,
- val cmUpsertUserPrintCancel: CMUpsertUserPrintCancelHandler,
-
val mapper: StringMapper,
val cmMapper: BasicMapper,
val db: Chu3Repos,
@@ -41,23 +35,12 @@ class ChusanController(
}) {
val log = LoggerFactory.getLogger(ChusanController::class.java)
- // Below are code related to handling the handlers
- val externalHandlers = mutableListOf("GameLoginApi", "UpsertUserAllApi",
- "CMUpsertUserGachaApi", "CMUpsertUserPrintCancelApi", "CMUpsertUserPrintSubtractApi")
-
val noopEndpoint = setOf("UpsertClientBookkeepingApi", "UpsertClientDevelopApi", "UpsertClientErrorApi",
"UpsertClientSettingApi", "UpsertClientTestmodeApi", "CreateTokenApi", "RemoveTokenApi", "UpsertClientUploadApi",
"PrinterLoginApi", "PrinterLogoutApi", "Ping", "GameLogoutApi", "RemoveMatchingMemberApi")
init { chusanInit() }
-
- val members = this::class.declaredMemberProperties
- val handlers: Map = initH + externalHandlers.associateWith { api ->
- val name = api.replace("Api", "").lowercase()
- (members.find { it.name.lowercase() == name } ?: members.find { it.name.lowercase() == name.replace("cm", "") })
- ?.let { (it.call(this) as BaseHandler).toSpecial() }
- ?: throw IllegalArgumentException("Chu3: No handler found for $api")
- }
+ val handlers = initH
@API("/{endpoint}", "/MatchingServer/{endpoint}")
fun handle(@PV endpoint: Str, @RB data: MutableMap, @PV version: Str, req: HttpServletRequest): Any {
@@ -72,6 +55,8 @@ class ChusanController(
}
if (api.startsWith("CM") && api !in handlers) api = api.removePrefix("CM")
+ val token = TokenChecker.getCurrentSession()?.token?.substring(0, 6) ?: "NO-TOKEN"
+ log.info("Chu3 < $api : ${data.toJson()} : [$token]")
if (api !in noopEndpoint && !handlers.containsKey(api)) {
log.warn("Chu3 > $api not found")
@@ -84,8 +69,6 @@ class ChusanController(
log.info("Chu3 > $api no-op")
return """{"returnCode":"1"}"""
}
- val token = TokenChecker.getCurrentSession()?.token?.substring(0, 6) ?: "NO-TOKEN"
- log.info("Chu3 < $api : ${data.toJson()} : [$token]")
return try {
Metrics.timer("aquadx_chusan_api_latency", "api" to api).recordCallable {
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanProps.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanProps.kt
index f4bce972..c94b0786 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanProps.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanProps.kt
@@ -10,5 +10,4 @@ class ChusanProps {
var loginBonusEnable = false
var externalMatching: String? = null
var reflectorUrl: String? = null
- var proxiedMatching: Boolean = false
}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserGachaHandler.java b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserGachaHandler.java
deleted file mode 100644
index 2f052a07..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserGachaHandler.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.handler;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserCardPrintStateRepo;
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserGachaRepo;
-import icu.samnyan.aqua.sega.general.BaseHandler;
-import icu.samnyan.aqua.sega.chusan.model.gamedata.GameGachaCard;
-import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserGacha;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserGacha;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem;
-import icu.samnyan.aqua.sega.chusan.service.UserDataService;
-import icu.samnyan.aqua.sega.chusan.service.UserItemService;
-import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
-import lombok.AllArgsConstructor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.time.LocalDateTime;
-import java.util.*;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@AllArgsConstructor
-@Component("ChusanCMUpsertUserGachaHandler")
-public class CMUpsertUserGachaHandler implements BaseHandler {
-
- private static final Logger logger = LoggerFactory.getLogger(CMUpsertUserGachaHandler.class);
- private final Chu3UserCardPrintStateRepo userCardPrintStateRepository;
- private final Chu3UserGachaRepo userGachaRepository;
- private final UserDataService userDataService;
- private final UserItemService userItemService;
- private final BasicMapper mapper;
-
- @Override
- public Object handle(Map request) throws JsonProcessingException {
- String userId = String.valueOf(request.get("userId"));
- int gachaId = ((Number) request.get("gachaId")).intValue();
- int placeId = ((Number) request.get("placeId")).intValue();
-
- UpsertUserGacha upsertUserGacha = mapper.convert(request.get("cmUpsertUserGacha"), UpsertUserGacha.class);
- List userCardPrintStateList = new ArrayList<>();
- Chu3UserData userData;
-
- Optional userOptional = userDataService.getUserByExtId(userId);
- if (userOptional.isPresent()) {
- userData = userOptional.get();
- } else {
- logger.error("User not found. userId: {}", userId);
- return null;
- }
-
- if (upsertUserGacha.getGameGachaCardList() != null) {
- for (GameGachaCard gameGachaCard : upsertUserGacha.getGameGachaCardList()) {
- UserCardPrintState userCardPrintState = new UserCardPrintState();
- userCardPrintState.setHasCompleted(false);
- userCardPrintState.setLimitDate(LocalDateTime.of(2029, 01, 01, 0, 0));
- userCardPrintState.setPlaceId(placeId);
- userCardPrintState.setCardId(gameGachaCard.getCardId());
- userCardPrintState.setGachaId(gachaId);
- userCardPrintState.setUser(userData);
- userCardPrintStateRepository.save(userCardPrintState);
- }
- }
-
- List userItemListToSave = new ArrayList<>();
- List userItemList = upsertUserGacha.getUserItemList();
-
- userItemList.forEach(newUserItem -> {
- int itemId = newUserItem.getItemId();
- int itemKind = newUserItem.getItemKind();
-
- Optional userItemOptional = userItemService.getByUserAndItemIdAndKind(userData, itemId, itemKind);
- UserItem userItem = userItemOptional.orElseGet(() -> new UserItem(userData));
-
- newUserItem.setId(userItem.getId());
- newUserItem.setUser(userItem.getUser());
-
- userItemListToSave.add(newUserItem);
- });
- userItemService.saveAll(userItemListToSave);
-
- if (upsertUserGacha.getUserGacha() != null) {
- UserGacha newUserGacha = upsertUserGacha.getUserGacha();
- newUserGacha.setUser(userData);
- userGachaRepository.save(newUserGacha);
- }
-
- userCardPrintStateList = userCardPrintStateRepository.findByUserAndGachaIdAndHasCompleted(userData, gachaId, false);
- Map resultMap = new LinkedHashMap<>();
- resultMap.put("returnCode", 1);
- resultMap.put("apiName", "CMUpsertUserGachaApi");
- resultMap.put("userCardPrintStateList", userCardPrintStateList);
-
- return resultMap;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserPrintCancelHandler.java b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserPrintCancelHandler.java
deleted file mode 100644
index 33717613..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserPrintCancelHandler.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.handler;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserCardPrintStateRepo;
-import icu.samnyan.aqua.sega.general.BaseHandler;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState;
-import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Component("ChusanCMUpsertUserPrintCancelHandler")
-public class CMUpsertUserPrintCancelHandler implements BaseHandler {
-
- private static final Logger logger = LoggerFactory.getLogger(CMUpsertUserPrintCancelHandler.class);
- private final Chu3UserCardPrintStateRepo userCardPrintStateRepository;
- private final BasicMapper mapper;
-
- @Autowired
- public CMUpsertUserPrintCancelHandler(Chu3UserCardPrintStateRepo userCardPrintStateRepository, BasicMapper mapper) {
- this.userCardPrintStateRepository = userCardPrintStateRepository;
- this.mapper = mapper;
- }
-
- @Override
- public String handle(Map request) throws JsonProcessingException {
- String userId = String.valueOf(request.get("userId"));
- List orderIdList = mapper.convert(request.get("orderIdList"), new TypeReference>() {});
-
- for (Integer orderId : orderIdList) {
- Optional userCardPrintStateOptional = userCardPrintStateRepository.findById(orderId.longValue());
- if (userCardPrintStateOptional.isPresent()) {
- UserCardPrintState newUserCardPrintState = userCardPrintStateOptional.get();
- newUserCardPrintState.setHasCompleted(true);
- userCardPrintStateRepository.save(newUserCardPrintState);
- }
- }
-
- Map resultMap = new LinkedHashMap<>();
- resultMap.put("returnCode", 1);
- resultMap.put("apiName", "CMUpsertUserPrintCancelApi");
-
- String json = mapper.write(resultMap);
- logger.info("Response: " + json);
- return json;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserPrintSubtractHandler.java b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserPrintSubtractHandler.java
deleted file mode 100644
index b46bba73..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/CMUpsertUserPrintSubtractHandler.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.handler;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserCardPrintStateRepo;
-import icu.samnyan.aqua.sega.general.BaseHandler;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem;
-import icu.samnyan.aqua.sega.chusan.service.UserDataService;
-import icu.samnyan.aqua.sega.chusan.service.UserItemService;
-import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
-import lombok.AllArgsConstructor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.*;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@AllArgsConstructor
-@Component("ChusanCMUpsertUserPrintSubtractHandler")
-public class CMUpsertUserPrintSubtractHandler implements BaseHandler {
-
- private static final Logger logger = LoggerFactory.getLogger(CMUpsertUserPrintSubtractHandler.class);
- private final Chu3UserCardPrintStateRepo userCardPrintStateRepository;
- private final UserItemService userItemService;
- private final UserDataService userDataService;
- private final BasicMapper mapper;
-
- @Override
- public String handle(Map request) throws JsonProcessingException {
- String userId = String.valueOf(request.get("userId"));
- UserCardPrintState userCardPrintState = mapper.convert(request.get("userCardPrintState"), UserCardPrintState.class);
- List userItemList = mapper.convert(request.get("userItemList"), new TypeReference>() {});
-
- Chu3UserData userData;
-
- Optional userOptional = userDataService.getUserByExtId(userId);
- if (userOptional.isPresent()) {
- userData = userOptional.get();
- } else {
- logger.error("User not found. userId: {}", userId);
- return null;
- }
-
- List userItemListToSave = new ArrayList<>();
-
- userItemList.forEach(newUserItem -> {
- int itemId = newUserItem.getItemId();
- int itemKind = newUserItem.getItemKind();
-
- Optional userItemOptional = userItemService.getByUserAndItemIdAndKind(userData, itemId, itemKind);
- UserItem userItem = userItemOptional.orElseGet(() -> new UserItem(userData));
-
- newUserItem.setId(userItem.getId());
- newUserItem.setUser(userItem.getUser());
-
- userItemListToSave.add(newUserItem);
- });
- userItemService.saveAll(userItemListToSave);
-
- Optional userCardPrintStateOptional = userCardPrintStateRepository.findById(userCardPrintState.getId());
- if (userCardPrintStateOptional.isPresent()) {
- UserCardPrintState newUserCardPrintState = userCardPrintStateOptional.get();
- newUserCardPrintState.setHasCompleted(true);
- userCardPrintStateRepository.save(newUserCardPrintState);
- }
-
- Map resultMap = new LinkedHashMap<>();
- resultMap.put("returnCode", 1);
- resultMap.put("apiName", "CMUpsertUserPrintSubtractApi");
-
- String json = mapper.write(resultMap);
- logger.info("Response: " + json);
- return json;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt
similarity index 69%
rename from src/main/java/icu/samnyan/aqua/sega/chusan/ChusanApis.kt
rename to src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt
index a5541874..44d2adc5 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanApis.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt
@@ -1,9 +1,10 @@
-package icu.samnyan.aqua.sega.chusan
+package icu.samnyan.aqua.sega.chusan.handler
import ext.*
+import icu.samnyan.aqua.sega.allnet.TokenChecker
+import icu.samnyan.aqua.sega.chusan.ChusanController
+import icu.samnyan.aqua.sega.chusan.ChusanData
import icu.samnyan.aqua.sega.chusan.model.request.UserCMissionResp
-import icu.samnyan.aqua.sega.chusan.model.response.data.UserEmoney
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharge
import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem
import icu.samnyan.aqua.sega.chusan.model.userdata.UserMusicDetail
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
@@ -12,6 +13,8 @@ import java.time.format.DateTimeFormatter
@Suppress("UNCHECKED_CAST")
fun ChusanController.chusanInit() {
matchingApiInit()
+ cmApiInit()
+ upsertApiInit()
// Stub handlers
"GetGameRanking" { """{"type":"${data["type"]}","length":"0","gameRankingList":[]}""" }
@@ -25,11 +28,18 @@ fun ChusanController.chusanInit() {
"GetUserRegion" { """{"userId":"${data["userId"]}","length":"0","userRegionList":[]}""" }
"GetUserPrintedCard" { """{"userId":"${data["userId"]}","length":0,"nextIndex":-1,"userPrintedCardList":[]}""" }
"GetUserSymbolChatSetting" { """{"userId":"${data["userId"]}","length":"0","symbolChatInfoList":[]}""" }
- "GetUserNetBattleData" { """{"userId":"${data["userId"]}","userNetBattleData":{"recentNBSelectMusicList":[],"recentNBMusicList":[]}}""" }
- "GetUserNetBattleRankingInfo" { """{"userId":"${data["userId"]}","length":"0","userNetBattleRankingInfoList":{}}""" }
- "CMUpsertUserPrint" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintApi"}""" }
- "CMUpsertUserPrintlog" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintlogApi"}""" }
+ // Net battle data
+ "GetUserNetBattleData" api@ {
+ val u = db.userData.findByCard_ExtId(uid)() ?: return@api null
+ val misc = db.userMisc.findSingleByUser(u)()
+ val recent = db.netBattleLog.findTop20ByUserOrderByIdDesc(u)
+ mapOf("userId" to uid, "userNetBattleData" to mapOf(
+ "recentNBSelectMusicList" to (misc?.recentNbSelect ?: empty),
+ "recentNBMusicList" to recent.map { it.toDict(u.userName) },
+ ))
+ }
+ "GetUserNetBattleRankingInfo" { """{"userId":"${data["userId"]}","length":"0","userNetBattleRankingInfoList":{}}""" }
// User handlers
"GetUserData" {
@@ -57,7 +67,6 @@ fun ChusanController.chusanInit() {
"GetUserCMission" {
parsing { UserCMissionResp().apply {
- userId = uid
missionId = parsing { data["missionId"]!!.int }
} }.apply {
db.userCMission.findByUser_Card_ExtIdAndMissionId(uid, missionId)()?.let {
@@ -92,7 +101,7 @@ fun ChusanController.chusanInit() {
data["nextIndex"] = rawIndex % 10000000000L
mapOf("itemKind" to kind) grabs {
// TODO: All unlock
- val items = db.userItem.findAllByUser_Card_ExtIdAndItemKind(uid, kind).toMutableList()
+ val items = db.userItem.findAllByUser_Card_ExtIdAndItemKind(uid, kind).mut
// Check game options
db.userData.findByCard_ExtId(uid)()?.card?.aquaUser?.gameOptions?.let {
@@ -112,14 +121,12 @@ fun ChusanController.chusanInit() {
"GetUserFavoriteItem".pagedWithKind("userFavoriteItemList") {
val kind = parsing { data["kind"]!!.int }
mapOf("kind" to kind) grabs {
- // TODO: Actually store this info at UpsertUserAll
- val fav = when (kind) {
- 1 -> "favorite_music"
- 3 -> "favorite_chara"
- else -> null
- }?.let { db.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(uid, it)() }?.propertyValue
-
- fav?.ifBlank { null }?.split(",")?.map { it.int } ?: emptyList()
+ val misc = db.userMisc.findSingleByUser_Card_ExtId(uid)()
+ when (kind) {
+ 1 -> misc?.favMusic ?: empty
+ 3 -> empty // TODO: Favorite character
+ else -> empty
+ }.map { mapOf("id" to it) }
}
}
@@ -147,7 +154,7 @@ fun ChusanController.chusanInit() {
// Compatibility: Older chusan uses boolean for isSuccess
fun checkAncient(d: List) =
data["version"]?.double?.let { if (it >= 2.15) d else d.map {
- d.toJson().jsonMap().toMutableMap().apply { this["isSuccess"] = this["isSuccess"].truthy }
+ d.toJson().jsonMap().mut.apply { this["isSuccess"] = this["isSuccess"].truthy }
} } ?: d
db.userMusicDetail.findByUser_Card_ExtId(uid).groupBy { it.musicId }
@@ -193,19 +200,16 @@ fun ChusanController.chusanInit() {
// Special thanks to skogaby
// Hardcode so that the reboot time always started 3 hours ago and ended 2 hours ago
val fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss")
-
- // Get the request url as te address
- val addr = (req.getHeader("wrapper original url") ?: req.requestURL.toString())
- .removeSuffix("GetGameSettingApi").removeSuffix("ChuniServlet/")
val now = jstNow()
- val matching = if (!props.externalMatching.isNullOrBlank() && !props.proxiedMatching) mapOf(
- "matchingUri" to props.externalMatching,
- "matchingUriX" to props.externalMatching,
- ) else mapOf(
- "matchingUri" to addr,
- "matchingUriX" to addr
- )
+ // Set the matching & reflector to the one set in the game options, or the external matching server
+ val opts = TokenChecker.getCurrentSession()?.user?.gameOptions
+ val matching = opts?.chusanMatchingServer?.ifBlank { null } ?:
+ props.externalMatching?.ifBlank { null } ?:
+ (req.getHeader("wrapper original url") ?: req.requestURL.toString())
+ .removeSuffix("GetGameSettingApi").removeSuffix("ChuniServlet/")
+ val reflector = opts?.chusanMatchingReflector?.ifBlank { null } ?:
+ props.reflectorUrl
mapOf(
"gameSetting" to mapOf(
@@ -223,39 +227,70 @@ fun ChusanController.chusanInit() {
"matchEndTime" to now.plusHours(7).format(fmt),
"matchTimeLimit" to 10,
"matchErrorLimit" to 10,
- "matchingUri" to addr,
- "matchingUriX" to addr,
- "udpHolePunchUri" to props.reflectorUrl,
- "reflectorUri" to props.reflectorUrl,
- ) + matching,
+ "matchingUri" to matching.ensureEndingSlash(),
+ "matchingUriX" to matching.ensureEndingSlash(),
+ "udpHolePunchUri" to reflector?.ensureEndingSlash(),
+ "reflectorUri" to reflector?.ensureEndingSlash(),
+ ),
"isDumpUpload" to false,
"isAou" to false
)
}
- // Upserts
- "UpsertUserChargelog" {
- val charge = parsing { mapper.convert(data["userCharge"] as JDict) }
- charge.user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
- charge.id = db.userCharge.findByUser_Card_ExtIdAndChargeId(uid, charge.chargeId)?.id ?: 0
- db.userCharge.save(charge)
- """{"returnCode":"1"}"""
- }
-
// Static
"GetGameEvent" static { db.gameEvent.findByEnable(true).let { mapOf("type" to 1, "length" to it.size, "gameEventList" to it) } }
"GetGameCharge" static { db.gameCharge.findAll().let { mapOf("length" to it.size, "gameChargeList" to it) } }
"GetGameGacha" static { db.gameGacha.findAll().let { mapOf("length" to it.size, "gameGachaList" to it, "registIdList" to empty) } }
"GetGameMapAreaCondition" static { ChusanData.mapAreaCondition }
- // CardMaker (TODO: Somebody test this, I don't have a card maker)
- "CMGetUserData" {
- val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
- user.userEmoney = UserEmoney()
- mapOf("userId" to uid, "userData" to user, "userEmoney" to user.userEmoney)
- }
- "CMGetUserPreview" {
- val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
- mapOf("userName" to user.userName, "level" to user.level, "medal" to user.medal, "lastDataVersion" to user.lastDataVersion, "isLogin" to false)
+ // TODO: Test login bonus
+ "GameLogin" {
+// fun process() {
+// val u = db.userData.findByCard_ExtId(uid)() ?: return
+// db.userData.save(u.apply { lastLoginDate = LocalDateTime.now() })
+//
+// if (!props.loginBonusEnable) return
+// val bonusList = db.gameLoginBonusPresets.findLoginBonusPresets(1, 1)
+//
+// bonusList.forEach { preset ->
+// // Check if a user already has some progress and if not, add the login bonus entry
+// val bonus = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)()
+// ?: UserLoginBonus(1, uid.int, preset.id).let { db.userLoginBonus.save(it) }
+// if (bonus.isFinished) return@forEach
+//
+// // last login is 24 hours+ ago
+// if (bonus.lastUpdateDate.toEpochSecond(ZoneOffset.ofHours(0)) <
+// (LocalDateTime.now().minusHours(24).toEpochSecond(ZoneOffset.ofHours(0)))
+// ) {
+// var bCount = bonus.bonusCount + 1
+// val lastUpdate = LocalDateTime.now()
+// val allLoginBonus = db.gameLoginBonus.findGameLoginBonus(1, preset.id)
+// .ifEmpty { return@forEach }
+// val maxNeededDays = allLoginBonus[0].needLoginDayCount
+//
+// // if all items are redeemed, then don't show the login bonuses.
+// var finished = false
+// if (bCount > maxNeededDays) {
+// if (preset.id < 3000) bCount = 1
+// else finished = true
+// }
+// db.gameLoginBonus.findByRequiredDays(1, preset.id, bCount)()?.let {
+// db.userItem.save(UserItem(6, it.presentId, it.itemNum).apply { user = u })
+// }
+// val toSave = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)()
+// ?: UserLoginBonus().apply { user = uid.int; presetId = preset.id; version = 1 }
+//
+// db.userLoginBonus.save(toSave.apply {
+// bonusCount = bCount
+// lastUpdateDate = lastUpdate
+// isWatched = false
+// isFinished = finished
+// })
+// }
+// }
+// }
+// process()
+
+ """{"returnCode":"1"}"""
}
}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt
new file mode 100644
index 00000000..ad983f78
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt
@@ -0,0 +1,99 @@
+package icu.samnyan.aqua.sega.chusan.handler
+
+import com.fasterxml.jackson.core.type.TypeReference
+import ext.*
+import icu.samnyan.aqua.sega.chusan.ChusanController
+import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserGacha
+import icu.samnyan.aqua.sega.chusan.model.request.UserEmoney
+import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState
+import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem
+import java.time.LocalDateTime
+
+fun ChusanController.cmApiInit() {
+ "CMUpsertUserPrint" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintApi"}""" }
+ "CMUpsertUserPrintlog" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintlogApi"}""" }
+
+ // CardMaker (TODO: Somebody test this, I don't have a card maker)
+ "CMGetUserData" {
+ val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
+ user.userEmoney = UserEmoney()
+ mapOf("userId" to uid, "userData" to user, "userEmoney" to user.userEmoney)
+ }
+
+ "CMGetUserPreview" {
+ val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
+ mapOf("userName" to user.userName, "level" to user.level, "medal" to user.medal, "lastDataVersion" to user.lastDataVersion, "isLogin" to false)
+ }
+
+ "CMUpsertUserGacha" api@ {
+ val (gachaId, placeId) = parsing { data["gachaId"]!!.int to data["placeId"]!!.int }
+
+ val u = db.userData.findByCard_ExtId(uid)() ?: return@api null
+ val upsertUserGacha = parsing { mapper.convert(data["cmUpsertUserGacha"], UpsertUserGacha::class.java) }
+
+ upsertUserGacha.gameGachaCardList?.let { lst ->
+ db.userCardPrintState.saveAll(lst.map {
+ UserCardPrintState(
+ hasCompleted = false,
+ limitDate = LocalDateTime.of(2029, 1, 1, 0, 0),
+ placeId = placeId,
+ cardId = it.cardId,
+ gachaId = gachaId
+ ).apply { user = u }
+ })
+ }
+
+ upsertUserGacha.userItemList?.let {
+ db.userItem.saveAll(it.mapApply {
+ user = u
+ id = db.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0
+ })
+ }
+
+ upsertUserGacha.userGacha?.let {
+ it.user = u
+ db.userGacha.save(it)
+ }
+
+ mapOf(
+ "returnCode" to 1,
+ "apiName" to "CMUpsertUserGachaApi",
+ "userCardPrintStateList" to db.userCardPrintState.findByUserAndGachaIdAndHasCompleted(u, gachaId, false)
+ )
+ }
+
+ "CMUpsertUserPrintCancel" {
+ val orderIdList: List = cmMapper.convert(data["orderIdList"], object : TypeReference>() {})
+
+ db.userCardPrintState.saveAll(orderIdList.mapNotNull {
+ // TODO: The original code by Eori writes findById but I don't think that is correct...
+ db.userCardPrintState.findById(it)()?.apply {
+ hasCompleted = true
+ }
+ })
+
+ mapOf("returnCode" to 1, "apiName" to "CMUpsertUserPrintCancelApi")
+ }
+
+ "CMUpsertUserPrintSubtract" api@ {
+ val userCardPrintState = cmMapper.convert(data["userCardPrintState"], UserCardPrintState::class.java)
+ val userItemList = cmMapper.convert(data["userItemList"], object : TypeReference>() {})
+
+ val u = db.userData.findByCard_ExtId(uid)() ?: return@api null
+
+ db.userItem.saveAll(
+ userItemList.mapApply {
+ id = db.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0
+ user = u
+ }
+ )
+
+ // TODO: I also doubt this is correct... it shouldn't be ID
+ db.userCardPrintState.findById(userCardPrintState.id)()?.apply {
+ hasCompleted = true
+ db.userCardPrintState.save(this)
+ }
+
+ mapOf("returnCode" to 1, "apiName" to "CMUpsertUserPrintSubtractApi")
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanMatchingApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanMatchingApis.kt
similarity index 52%
rename from src/main/java/icu/samnyan/aqua/sega/chusan/ChusanMatchingApis.kt
rename to src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanMatchingApis.kt
index 25b9d4e0..87eaabb3 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanMatchingApis.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanMatchingApis.kt
@@ -1,15 +1,27 @@
@file:Suppress("UNCHECKED_CAST")
-package icu.samnyan.aqua.sega.chusan
+package icu.samnyan.aqua.sega.chusan.handler
-import ext.*
-import icu.samnyan.aqua.sega.chusan.model.response.data.MatchingWaitState
+import ext.JDict
+import ext.int
+import ext.millis
+import ext.parsing
+import icu.samnyan.aqua.sega.chusan.ChusanController
+import icu.samnyan.aqua.sega.chusan.model.request.MatchingWaitState
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3MatchingMemberReq
+import kotlin.collections.MutableList
+import kotlin.collections.find
+import kotlin.collections.indices
+import kotlin.collections.listOf
+import kotlin.collections.map
+import kotlin.collections.mapOf
+import kotlin.collections.mutableListOf
+import kotlin.collections.mutableMapOf
+import kotlin.collections.set
fun ChusanController.matchingApiInit() {
if (props.externalMatching.isNullOrBlank()) serverOnlyMatching()
- else if (props.proxiedMatching) proxyMatching()
}
/**
@@ -56,49 +68,3 @@ fun ChusanController.serverOnlyMatching() {
)
}
}
-
-/**
- * Matching implementation
- */
-fun ChusanController.proxyMatching() {
- val ext = props.externalMatching!!
-
- // ID Cache is used to obfuscate the user ID
- val processedCache = mutableSetOf()
- val idCache = mutableMapOf()
-
- fun Chu3MatchingMemberReq.checkFromAquaDX(): Boolean {
- if (userId in idCache) return true
- if (userId in processedCache) return false
-
- // Check if this user is from our server
- val user = db.userData.findByCard_ExtId(userId)()
- if (user == null) {
- // User is from another server, check if they have been checked in
- if (db.matchingMember.existsByUserIdAndUserName(userId, userName)) {
- // Check in
- db.matchingMember.save(this)
- log.info("[Matching] User $userId ($userName) not found, checking in.")
- }
- processedCache.add(userId)
- }
- else {
- // Is from our server, obfuscate the user ID to enhance security
- val randomId = (0..Int.MAX_VALUE).random().toLong()
- idCache[randomId] = userId
- userId = randomId
- log.info("[Matching] User $userId ($userName) is from our server, obfuscated to $randomId.")
- }
- return user != null
- }
-
- "BeginMatching" {
- val member = parsing { mapper.convert(data["matchingMemberInfo"] as JDict) }
- member.checkFromAquaDX()
-
- // Forward BeginMatching to external server
-// val res =
- }
-
- TODO("The external matching API is not implemented yet.")
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt
new file mode 100644
index 00000000..e8bb3664
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt
@@ -0,0 +1,162 @@
+package icu.samnyan.aqua.sega.chusan.handler
+
+import ext.*
+import icu.samnyan.aqua.sega.chusan.ChusanController
+import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserAll
+import icu.samnyan.aqua.sega.chusan.model.userdata.*
+import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
+
+@Suppress("UNCHECKED_CAST")
+fun ChusanController.upsertApiInit() {
+ "UpsertUserChargelog" {
+ val charge = parsing { mapper.convert(data["userCharge"] as JDict) }
+ charge.user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
+ charge.id = db.userCharge.findByUser_Card_ExtIdAndChargeId(uid, charge.chargeId)?.id ?: 0
+ db.userCharge.save(charge)
+ """{"returnCode":"1"}"""
+ }
+
+ "UpsertUserAll" api@ {
+ val req = mapper.convert(data["upsertUserAll"], UpsertUserAll::class.java)
+
+ req.run {
+ // UserData
+ val oldUser = db.userData.findByCard_ExtId(uid)()
+ val u = (userData?.get(0) ?: return@api null).apply {
+ id = oldUser?.id ?: 0
+ card = oldUser?.card ?: us.cardRepo.findByExtId(uid).expect("Card not found")
+ userName = userName.fromChusanUsername()
+ userNameEx = ""
+ }.also { db.userData.saveAndFlush(it) }
+
+ versionHelper[u.lastClientId] = u.lastDataVersion
+
+ // Set users
+ listOfNotNull(
+ userPlaylogList, userGameOption, userMapAreaList, userCharacterList, userItemList,
+ userMusicDetailList, userActivityList, userChargeList, userCourseList, userDuelList,
+ userNetBattlelogList
+ ).flatten().forEach { it.user = u }
+
+ // Ratings
+ fun Iterable.str() = joinToString(",") { "${it.musicId}:${it.difficultId}:${it.score}" }
+
+ ls(
+ userRecentRatingList to "recent_rating_list", userRatingBaseList to "rating_base_list",
+ userRatingBaseHotList to "rating_hot_list", userRatingBaseNextList to "rating_next_list",
+ ).filter { it.first != null }.forEach { (list, key) ->
+ val d = db.userGeneralData.findByUserAndPropertyKey(u, key)()
+ ?: UserGeneralData().apply { user = u; propertyKey = key }
+ db.userGeneralData.save(d.apply { propertyValue = list!!.str() })
+ }
+
+ val misc = db.userMisc.findSingleByUser(u)() ?: Chu3UserMisc().apply { user = u }
+
+ // Favorites
+ userFavoriteMusicList?.filter { it.musicId != -1 }?.ifEmpty { null }?.let { list ->
+ misc.favMusic = list.map { it.musicId }.mut
+ }
+
+ // Net battle data
+ userNetBattleData?.getOrNull(0)?.let {
+ misc.recentNbSelect = it.recentNBSelectMusicList.map { it.musicId }.mut
+ }
+
+ // Add the battle log songs to misc
+ if (userNetBattlelogList != null) {
+ val music = userMusicDetailList?.map { it.musicId } ?: emptyList()
+ misc.recentNbMusic = (misc.recentNbMusic + music).distinct().takeLast(10).mut
+ }
+ db.userMisc.save(misc)
+
+ // Playlog
+ userPlaylogList?.let { db.userPlaylog.saveAll(it) }
+ userNetBattlelogList?.let { db.netBattleLog.saveAll(it.mapApplyI { i ->
+ userPlaylogList?.getOrNull(i)?.let {
+ musicId = it.musicId
+ difficultyId = it.level
+ score = it.score
+ }
+
+ selectUserName = selectUserName.fromChusanUsername()
+ opponentUserName1 = opponentUserName1.fromChusanUsername()
+ opponentUserName2 = opponentUserName2.fromChusanUsername()
+ opponentUserName3 = opponentUserName3.fromChusanUsername()
+ }) }
+
+ // List data
+ userGameOption?.get(0)?.let { obj ->
+ db.userGameOption.saveAndFlush(obj.apply {
+ id = db.userGameOption.findSingleByUser(u)()?.id ?: 0 }) }
+
+ userMapAreaList?.let { list ->
+ db.userMap.saveAll(list.distinctBy { it.mapAreaId }.mapApply {
+ id = db.userMap.findByUserAndMapAreaId(u, mapAreaId)?.id ?: 0 }) }
+
+ userCharacterList?.let { list ->
+ db.userCharacter.saveAll(list.distinctBy { it.characterId }.mapApply {
+ id = db.userCharacter.findByUserAndCharacterId(u, characterId)?.id ?: 0 }) }
+
+ userItemList?.let { list ->
+ db.userItem.saveAll(list.distinctBy { it.itemId to it.itemKind }.mapApply {
+ id = db.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0 }) }
+
+ userMusicDetailList?.let { list ->
+ db.userMusicDetail.saveAll(list.distinctBy { it.musicId to it.level }.mapApply {
+ id = db.userMusicDetail.findByUserAndMusicIdAndLevel(u, musicId, level)?.id ?: 0 }) }
+
+ userActivityList?.let { list ->
+ db.userActivity.saveAll(list.distinctBy { it.activityId to it.kind }.mapApply {
+ id = db.userActivity.findByUserAndActivityIdAndKind(u, activityId, kind)?.id ?: 0 }) }
+
+ userChargeList?.let { list ->
+ db.userCharge.saveAll(list.distinctBy { it.chargeId }.mapApply {
+ id = db.userCharge.findByUserAndChargeId(u, chargeId)()?.id ?: 0 }) }
+
+ userCourseList?.let { list ->
+ db.userCourse.saveAll(list.distinctBy { it.courseId }.mapApply {
+ id = db.userCourse.findByUserAndCourseId(u, courseId)?.id ?: 0 }) }
+
+ userDuelList?.let { list ->
+ db.userDuel.saveAll(list.distinctBy { it.duelId }.mapApply {
+ id = db.userDuel.findByUserAndDuelId(u, duelId)?.id ?: 0 }) }
+
+ // Need testing
+// userLoginBonusList?.let { list ->
+// db.userLoginBonus.saveAll(list.distinctBy { it["presetId"] as String }.map {
+// val id = it["presetId"]!!.int
+// (db.userLoginBonus.findLoginBonus(uid.int, 1, id)() ?: UserLoginBonus()).apply {
+// user = u.id.toInt()
+// presetId = id
+// lastUpdateDate = LocalDateTime.now()
+// isWatched = true
+// }
+// })
+// }
+
+ req.userCMissionList?.forEach { d ->
+ (db.userCMission.findByUser_Card_ExtIdAndMissionId(uid, d.missionId)()
+ ?: UserCMission().apply {
+ missionId = d.missionId
+ user = u
+ }
+ ).apply { point = d.point }.also { db.userCMission.save(it) }
+
+ d.userCMissionProgressList?.forEach inner@ { p ->
+ (db.userCMissionProgress.findByUser_Card_ExtIdAndMissionIdAndOrder(uid, d.missionId, p.order)()
+ ?: UserCMissionProgress().apply {
+ missionId = d.missionId
+ order = p.order
+ user = u
+ }
+ ).apply {
+ progress = p.progress
+ stage = p.stage
+ }.also { db.userCMissionProgress.save(it) }
+ }
+ }
+ }
+
+ """{"returnCode":1}"""
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/GameLoginHandler.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/GameLoginHandler.kt
deleted file mode 100644
index a83a2723..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/GameLoginHandler.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.handler
-
-import ext.int
-import ext.invoke
-import ext.long
-import icu.samnyan.aqua.sega.chusan.ChusanProps
-import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserLoginBonus
-import icu.samnyan.aqua.sega.general.BaseHandler
-import lombok.AllArgsConstructor
-import org.springframework.stereotype.Component
-import java.time.LocalDateTime
-import java.time.ZoneOffset
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@AllArgsConstructor
-@Component("ChusanGameLoginHandler")
-class GameLoginHandler(
- val props: ChusanProps,
- val db: Chu3Repos
-) : BaseHandler {
-
- override fun handle(request: Map): Any? {
- val uid = request["userId"]!!.long
- fun process() {
- val u = db.userData.findByCard_ExtId(uid)() ?: return
- db.userData.save(u.apply { lastLoginDate = LocalDateTime.now() })
-
- if (!props.loginBonusEnable) return
- val bonusList = db.gameLoginBonusPresets.findLoginBonusPresets(1, 1)
-
- bonusList.forEach { preset ->
- // Check if a user already has some progress and if not, add the login bonus entry
- val bonus = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)()
- ?: UserLoginBonus(1, uid.int, preset.id).let { db.userLoginBonus.save(it) }
- if (bonus.isFinished) return@forEach
-
- // last login is 24 hours+ ago
- if (bonus.lastUpdateDate.toEpochSecond(ZoneOffset.ofHours(0)) <
- (LocalDateTime.now().minusHours(24).toEpochSecond(ZoneOffset.ofHours(0)))
- ) {
- var bCount = bonus.bonusCount + 1
- val lastUpdate = LocalDateTime.now()
- val allLoginBonus = db.gameLoginBonus.findGameLoginBonus(1, preset.id)
- .ifEmpty { return@forEach }
- val maxNeededDays = allLoginBonus[0].needLoginDayCount
-
- // if all items are redeemed, then don't show the login bonuses.
- var finished = false
- if (bCount > maxNeededDays) {
- if (preset.id < 3000) bCount = 1
- else finished = true
- }
- db.gameLoginBonus.findByRequiredDays(1, preset.id, bCount)()?.let {
- db.userItem.save(UserItem(u).apply {
- itemId = it.presentId
- itemKind = 6
- stock = it.itemNum
- isValid = true
- })
- }
- val toSave = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)()
- ?: UserLoginBonus().apply { user = uid.int; presetId = preset.id; version = 1 }
-
- db.userLoginBonus.save(toSave.apply {
- bonusCount = bCount
- lastUpdateDate = lastUpdate
- isWatched = false
- isFinished = finished
- })
- }
- }
- }
- process()
-
- return """{"returnCode":"1"}"""
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/UpsertUserAllHandler.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/UpsertUserAllHandler.kt
deleted file mode 100644
index bab81dae..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/UpsertUserAllHandler.kt
+++ /dev/null
@@ -1,153 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.handler
-
-import ext.*
-import icu.samnyan.aqua.sega.chusan.ChusanVersionHelper
-import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
-import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserAll
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCMission
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCMissionProgress
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserGeneralData
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserLoginBonus
-import icu.samnyan.aqua.sega.general.BaseHandler
-import icu.samnyan.aqua.sega.general.dao.CardRepository
-import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
-import icu.samnyan.aqua.sega.util.jackson.StringMapper
-import lombok.AllArgsConstructor
-import org.springframework.stereotype.Component
-import java.nio.charset.StandardCharsets
-import java.time.LocalDateTime
-
-/**
- * The handler for save user data. Only send in the end of the session.
- *
- * @author samnyan (privateamusement@protonmail.com)
- */
-@AllArgsConstructor
-@Component("ChusanUpsertUserAllHandler")
-class UpsertUserAllHandler(
- val mapper: StringMapper,
- val rp: Chu3Repos,
- val cardRepo: CardRepository,
- val versionHelper: ChusanVersionHelper,
-) : BaseHandler {
- val logger = logger()
-
- override fun handle(request: Map): Any? {
- val ext = request["userId"]?.long ?: return null
- val req = mapper.convert(request["upsertUserAll"], UpsertUserAll::class.java)
-
- req.run {
- // UserData
- val oldUser = rp.userData.findByCard_ExtId(ext)()
- val u = (userData?.get(0) ?: return null).apply {
- id = oldUser?.id ?: 0
- card = oldUser?.card ?: cardRepo.findByExtId(ext).expect("Card not found")
- userName = String(userName.toByteArray(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)
- userNameEx = ""
- }.also { rp.userData.saveAndFlush(it) }
-
- versionHelper[u.lastClientId] = u.lastDataVersion
-
- // Set users
- listOfNotNull(
- userPlaylogList, userGameOption, userMapAreaList, userCharacterList, userItemList,
- userMusicDetailList, userActivityList, userChargeList, userCourseList, userDuelList,
- ).flatten().forEach { it.user = u }
-
- // Ratings
- fun Iterable.str() = joinToString(",") { "${it.musicId}:${it.difficultId}:${it.score}" }
-
- ls(
- userRecentRatingList to "recent_rating_list", userRatingBaseList to "rating_base_list",
- userRatingBaseHotList to "rating_hot_list", userRatingBaseNextList to "rating_next_list",
- ).filter { it.first != null }.forEach { (list, key) ->
- val d = rp.userGeneralData.findByUserAndPropertyKey(u, key)()
- ?: UserGeneralData().apply { user = u; propertyKey = key }
- rp.userGeneralData.save(d.apply { propertyValue = list!!.str() })
- }
-
- userFavoriteMusicList?.let { list ->
- val d = rp.userGeneralData.findByUserAndPropertyKey(u, "favorite_music")()
- ?: UserGeneralData().apply { user = u; propertyKey = "favorite_music" }
- rp.userGeneralData.save(d.apply { propertyValue = list.joinToString(",") { it.musicId.toString() } })
- }
-
- // Playlog
- userPlaylogList?.let { rp.userPlaylog.saveAll(it) }
-
- // List data
- userGameOption?.get(0)?.let { obj ->
- rp.userGameOption.saveAndFlush(obj.apply {
- id = rp.userGameOption.findSingleByUser(u)()?.id ?: 0 }) }
-
- userMapAreaList?.let { list ->
- rp.userMap.saveAll(list.distinctBy { it.mapAreaId }.mapApply {
- id = rp.userMap.findByUserAndMapAreaId(u, mapAreaId)?.id ?: 0 }) }
-
- userCharacterList?.let { list ->
- rp.userCharacter.saveAll(list.distinctBy { it.characterId }.mapApply {
- id = rp.userCharacter.findByUserAndCharacterId(u, characterId)?.id ?: 0 }) }
-
- userItemList?.let { list ->
- rp.userItem.saveAll(list.distinctBy { it.itemId to it.itemKind }.mapApply {
- id = rp.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0 }) }
-
- userMusicDetailList?.let { list ->
- rp.userMusicDetail.saveAll(list.distinctBy { it.musicId to it.level }.mapApply {
- id = rp.userMusicDetail.findByUserAndMusicIdAndLevel(u, musicId, level)?.id ?: 0 }) }
-
- userActivityList?.let { list ->
- rp.userActivity.saveAll(list.distinctBy { it.activityId to it.kind }.mapApply {
- id = rp.userActivity.findByUserAndActivityIdAndKind(u, activityId, kind)?.id ?: 0 }) }
-
- userChargeList?.let { list ->
- rp.userCharge.saveAll(list.distinctBy { it.chargeId }.mapApply {
- id = rp.userCharge.findByUserAndChargeId(u, chargeId)()?.id ?: 0 }) }
-
- userCourseList?.let { list ->
- rp.userCourse.saveAll(list.distinctBy { it.courseId }.mapApply {
- id = rp.userCourse.findByUserAndCourseId(u, courseId)?.id ?: 0 }) }
-
- userDuelList?.let { list ->
- rp.userDuel.saveAll(list.distinctBy { it.duelId }.mapApply {
- id = rp.userDuel.findByUserAndDuelId(u, duelId)?.id ?: 0 }) }
-
- // Need testing
- userLoginBonusList?.let { list ->
- rp.userLoginBonus.saveAll(list.distinctBy { it["presetId"] as String }.map {
- val id = it["presetId"]!!.int
- (rp.userLoginBonus.findLoginBonus(ext.int, 1, id)() ?: UserLoginBonus()).apply {
- user = u.id.toInt()
- presetId = id
- lastUpdateDate = LocalDateTime.now()
- isWatched = true
- }
- })
- }
-
- req.userCMissionList?.forEach { d ->
- (rp.userCMission.findByUser_Card_ExtIdAndMissionId(ext, d.missionId)()
- ?: UserCMission().apply {
- missionId = d.missionId
- user = u
- }
- ).apply { point = d.point }.also { rp.userCMission.save(it) }
-
- d.userCMissionProgressList?.forEach inner@ { p ->
- (rp.userCMissionProgress.findByUser_Card_ExtIdAndMissionIdAndOrder(ext, d.missionId, p.order)()
- ?: UserCMissionProgress().apply {
- missionId = d.missionId
- order = p.order
- user = u
- }
- ).apply {
- progress = p.progress
- stage = p.stage
- }.also { rp.userCMissionProgress.save(it) }
- }
- }
- }
-
- return """{"returnCode":1}"""
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3GameData.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3GameData.kt
new file mode 100644
index 00000000..2397e94e
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3GameData.kt
@@ -0,0 +1,94 @@
+package icu.samnyan.aqua.sega.chusan.model
+
+import com.fasterxml.jackson.annotation.JsonIgnore
+import com.fasterxml.jackson.annotation.JsonProperty
+import icu.samnyan.aqua.net.games.BaseEntity
+import jakarta.persistence.*
+import java.time.LocalDateTime
+
+
+// BaseEntity does not expose id to json, but IdExposedEntity does
+@MappedSuperclass
+class IdExposedEntity {
+ @Id
+ var id: Long = 0
+}
+
+@Entity(name = "ChusanGameCharge")
+@Table(name = "chusan_game_charge")
+class GameCharge: BaseEntity() {
+ var orderId = 0
+
+ @Column(unique = true)
+ var chargeId = 0
+ var price = 0
+ var startDate: LocalDateTime? = null
+ var endDate: LocalDateTime? = null
+ var salePrice = 0
+ var saleStartDate: LocalDateTime? = null
+ var saleEndDate: LocalDateTime? = null
+}
+
+@Entity(name = "ChusanGameEvent")
+@Table(name = "chusan_game_event")
+class GameEvent: IdExposedEntity() {
+ val type = 0
+ val startDate: LocalDateTime? = null
+ val endDate: LocalDateTime? = null
+
+ @JsonIgnore
+ val enable = false
+}
+
+@Entity(name = "ChusanGameGacha")
+@Table(name = "chusan_game_gacha")
+class GameGacha : IdExposedEntity() {
+ 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? = null
+ var endDate: LocalDateTime? = null
+ var noticeStartDate: LocalDateTime? = null
+ var noticeEndDate: LocalDateTime? = null
+}
+
+@Entity(name = "ChusanGameGachaCard")
+@Table(name = "chusan_game_gacha_card")
+class GameGachaCard : IdExposedEntity() {
+ var gachaId = 0
+ var cardId = 0
+ var rarity = 0
+ var weight = 0
+
+ @JsonProperty("isPickup")
+ var isPickup = false
+}
+
+@Entity(name = "ChusanGameLoginBonus")
+@Table(name = "chusan_game_login_bonus")
+class GameLoginBonus : IdExposedEntity() {
+ 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
+}
+
+@Entity(name = "ChusanGameLoginBonusPreset")
+@Table(name = "chusan_game_login_bonus_preset")
+class GameLoginBonusPreset : IdExposedEntity() {
+ var version = 0
+ var presetName: String? = null
+ var isEnabled = false
+}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3Repos.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3Repos.kt
index 1afb875b..4396b026 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3Repos.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/Chu3Repos.kt
@@ -5,7 +5,6 @@ package icu.samnyan.aqua.sega.chusan.model
import icu.samnyan.aqua.net.games.GenericPlaylogRepo
import icu.samnyan.aqua.net.games.GenericUserDataRepo
import icu.samnyan.aqua.net.games.IUserRepo
-import icu.samnyan.aqua.sega.chusan.model.gamedata.*
import icu.samnyan.aqua.sega.chusan.model.userdata.*
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
@@ -37,7 +36,7 @@ interface Chu3UserLoginBonusRepo : JpaRepository {
value = "select * from chusan_user_login_bonus where user = ?1 and version = ?2 and preset_id = ?3 limit 1",
nativeQuery = true
)
- fun findLoginBonus(userId: Int, version: Int, presetId: Int): Optional
+ fun findLoginBonus(userId: Int, version: Int, presetId: Long): Optional
}
interface Chu3UserActivityRepo : Chu3UserLinked {
@@ -128,13 +127,11 @@ interface Chu3UserCMissionProgressRepo : Chu3UserLinked {
fun findByUser_Card_ExtIdAndMissionIdAndOrder(extId: Long, missionId: Int, order: Int): Optional
}
-interface Chu3MatchingMemberRepo : JpaRepository {
- fun existsByUserIdAndUserName(userId: Long, userName: String): Boolean
+interface Chu3NetBattleLogRepo : Chu3UserLinked {
+ fun findTop20ByUserOrderByIdDesc(user: Chu3UserData): List
}
-interface Chu3GameAvatarAccRepo : JpaRepository
-
-interface Chu3GameCharacterRepo : JpaRepository
+interface Chu3UserMiscRepo : Chu3UserLinked
interface Chu3GameChargeRepo : JpaRepository
@@ -142,15 +139,13 @@ interface Chu3GameEventRepo : JpaRepository {
fun findByEnable(enable: Boolean): List
}
-interface Chu3GameFrameRepo : JpaRepository
-
interface Chu3GameGachaCardRepo : JpaRepository {
fun findAllByGachaId(gachaId: Int): List
}
interface Chu3GameGachaRepo : JpaRepository
-interface Chu3GameLoginBonusPresetsRepo : JpaRepository {
+interface Chu3GameLoginBonusPresetsRepo : JpaRepository {
@Query(
value = "select * from chusan_game_login_bonus_preset where version = ?1 and is_enabled = ?2",
nativeQuery = true
@@ -172,18 +167,6 @@ interface Chu3GameLoginBonusRepo : JpaRepository {
fun findByRequiredDays(version: Int, presetId: Int, requiredDays: Int): Optional
}
-interface Chu3GameMapIconRepo : JpaRepository
-
-interface Chu3GameMusicRepo : JpaRepository {
- fun findByMusicId(musicId: Int): Optional
-}
-
-interface Chu3GameNamePlateRepo : JpaRepository
-
-interface Chu3GameSystemVoiceRepo : JpaRepository
-
-interface Chu3GameTrophyRepo : JpaRepository
-
@Component
class Chu3Repos(
val userLoginBonus: Chu3UserLoginBonusRepo,
@@ -203,19 +186,12 @@ class Chu3Repos(
val userPlaylog: Chu3UserPlaylogRepo,
val userCMission: Chu3UserCMissionRepo,
val userCMissionProgress: Chu3UserCMissionProgressRepo,
- val matchingMember: Chu3MatchingMemberRepo,
- val gameAvatarAcc: Chu3GameAvatarAccRepo,
- val gameCharacter: Chu3GameCharacterRepo,
+ val netBattleLog: Chu3NetBattleLogRepo,
+ val userMisc: Chu3UserMiscRepo,
val gameCharge: Chu3GameChargeRepo,
val gameEvent: Chu3GameEventRepo,
- val gameFrame: Chu3GameFrameRepo,
val gameGachaCard: Chu3GameGachaCardRepo,
val gameGacha: Chu3GameGachaRepo,
val gameLoginBonusPresets: Chu3GameLoginBonusPresetsRepo,
- val gameLoginBonus: Chu3GameLoginBonusRepo,
- val gameMapIcon: Chu3GameMapIconRepo,
- val gameMusic: Chu3GameMusicRepo,
- val gameNamePlate: Chu3GameNamePlateRepo,
- val gameSystemVoice: Chu3GameSystemVoiceRepo,
- val gameTrophy: Chu3GameTrophyRepo
+ val gameLoginBonus: Chu3GameLoginBonusRepo
)
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/AvatarAcc.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/AvatarAcc.java
deleted file mode 100644
index aac2b1cf..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/AvatarAcc.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "AvatarAcc")
-@Table(name = "chusan_avatar")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class AvatarAcc implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-
- private int category;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Character.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Character.java
deleted file mode 100644
index 9d21930e..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Character.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanCharacter")
-@Table(name = "chusan_game_character")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Character implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-
- private String releaseTag;
-
- private String worksName;
-
- private String illustratorName;
-
- private String addImages;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Frame.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Frame.java
deleted file mode 100644
index 1926f7db..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Frame.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanFrame")
-@Table(name = "chusan_frame")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Frame implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameCharge.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameCharge.java
deleted file mode 100644
index 07c630a1..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameCharge.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanGameCharge")
-@Table(name = "chusan_game_charge")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameCharge implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @JsonIgnore
- private long id;
-
- private int orderId;
-
- @Column(unique = true)
- private int chargeId;
-
- private int price;
-
- private LocalDateTime startDate;
-
- private LocalDateTime endDate;
-
- private int salePrice;
-
- private LocalDateTime saleStartDate;
-
- private LocalDateTime saleEndDate;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameEvent.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameEvent.java
deleted file mode 100644
index 1d4c38bd..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameEvent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanGameEvent")
-@Table(name = "chusan_game_event")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameEvent implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private int id;
-
- private int type;
-
- private LocalDateTime startDate;
-
- private LocalDateTime endDate;
-
- @JsonIgnore
- private boolean enable;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameGacha.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameGacha.java
deleted file mode 100644
index 62aefdef..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameGacha.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanGameGacha")
-@Table(name = "chusan_game_gacha")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameGacha implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @JsonIgnore
- private int id;
- private int gachaId;
- private String gachaName;
- private int type;
- private int kind; // 0
- @JsonProperty("isCeiling")
- private boolean isCeiling;
- private int ceilingCnt;
- private int changeRateCnt1;
- private int changeRateCnt2;
- private LocalDateTime startDate;
- private LocalDateTime endDate;
- private LocalDateTime noticeStartDate;
- private LocalDateTime noticeEndDate;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameGachaCard.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameGachaCard.java
deleted file mode 100644
index 50104f82..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameGachaCard.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanGameGachaCard")
-@Table(name = "chusan_game_gacha_card")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameGachaCard implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @JsonIgnore
- private int id;
- private int gachaId;
- private int cardId;
- private int rarity;
- private int weight;
- @JsonProperty("isPickup")
- private boolean isPickup;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameLoginBonus.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameLoginBonus.java
deleted file mode 100644
index 764e4836..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameLoginBonus.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-@Entity(name = "ChusanGameLoginBonus")
-@Table(name = "chusan_game_login_bonus")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameLoginBonus implements Serializable {
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @JsonIgnore
- private int id;
- private int version;
- private int presetId;
- private int loginBonusId;
- private String loginBonusName;
- private int presentId;
- private String presentName;
- private int itemNum;
- private int needLoginDayCount;
- private int loginBonusCategoryType;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameLoginBonusPreset.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameLoginBonusPreset.java
deleted file mode 100644
index 8e9754b5..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/GameLoginBonusPreset.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-@Entity(name = "ChusanGameLoginBonusPreset")
-@Table(name = "chusan_game_login_bonus_preset")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameLoginBonusPreset implements Serializable {
- // No one cares about chuni lol
- // Maimai and Ongeki all got their login bonus but nothing for chunithm
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @JsonIgnore
- private int id;
- private int version;
- private String presetName;
- private boolean isEnabled;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Genre.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Genre.java
deleted file mode 100644
index 7f2b3336..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Genre.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-public enum Genre {
- POPS_ANIME("POPS & ANIME"),
- GAME("GAME"),
- NICONICO("niconico"),
- TOUHOU("東方Project"),
- RESERVE2("Reserve2"),
- ORIGINAL("Original"),
- VARIETY("Variety"),
- IRODORI("イロドリミドリ"),
- KOTONOHA("言ノ葉Project"),
- GEKICHUMA("ゲキマイ");
-
- private String displayName;
-
- Genre(String displayName) {
- this.displayName = displayName;
- }
-
- public String displayName() {
- return displayName;
- }
-
- @Override
- public String toString() {
- return displayName;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Level.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Level.java
deleted file mode 100644
index fc4b7722..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Level.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanMusicLevel")
-@Table(name = "chusan_music_level")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Level implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @JsonIgnore
- private long id;
-
- @JsonIgnore
- @ManyToOne
- @JoinColumn(name = "music_id")
- private Music music;
-
- private boolean enable;
-
- private int level;
-
- private int levelDecimal;
-
- private int diff;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/MapIcon.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/MapIcon.java
deleted file mode 100644
index 5ae64743..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/MapIcon.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanMapIcon")
-@Table(name = "chusan_mapicon")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class MapIcon implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Music.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Music.java
deleted file mode 100644
index ba17ce4f..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Music.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-import java.util.Map;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanMusic")
-@Table(name = "chusan_music")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Music implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private int musicId;
-
- private String name;
-
- private String sortName;
-
- private String artistName;
-
- private Genre genre;
-
- private String releaseVersion;
-
- @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "music")
- @MapKey(name = "diff")
- private Map levels;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/NamePlate.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/NamePlate.java
deleted file mode 100644
index 0874e20a..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/NamePlate.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanNamePlate")
-@Table(name = "chusan_nameplate")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class NamePlate implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/SystemVoice.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/SystemVoice.java
deleted file mode 100644
index 7032c927..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/SystemVoice.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanSystemVoice")
-@Table(name = "chusan_voice")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class SystemVoice implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Trophy.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Trophy.java
deleted file mode 100644
index 078af200..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/gamedata/Trophy.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.gamedata;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanTrophy")
-@Table(name = "chusan_trophy")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Trophy implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Id
- private long id;
-
- private String name;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/MatchingWaitState.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/MatchingWaitState.kt
similarity index 86%
rename from src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/MatchingWaitState.kt
rename to src/main/java/icu/samnyan/aqua/sega/chusan/model/request/MatchingWaitState.kt
index 42c1f0da..8614c37f 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/MatchingWaitState.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/MatchingWaitState.kt
@@ -1,4 +1,4 @@
-package icu.samnyan.aqua.sega.chusan.model.response.data
+package icu.samnyan.aqua.sega.chusan.model.request
import com.fasterxml.jackson.annotation.JsonProperty
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3MatchingMemberReq
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserAll.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserAll.kt
index 3931aaa2..99be8f6f 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserAll.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserAll.kt
@@ -5,7 +5,6 @@ import icu.samnyan.aqua.sega.chusan.model.userdata.*
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
class UserCMissionResp {
- var userId: Long? = 0
var missionId = 0
var point = 0
var userCMissionProgressList: List? = null
@@ -16,6 +15,28 @@ class FavNewMusic(
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 = 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 UpsertUserAll(
var userData: List? = null,
var userGameOption: List? = null,
@@ -28,16 +49,17 @@ class UpsertUserAll(
var userChargeList: List? = null,
var userCourseList: List? = null,
var userDuelList: List? = null,
- var userTeamPoint: List? = null,
+ // TODO: Actually implement team
+ var userTeamPoint: List? = null,
var userRatingBaseHotList: List? = null,
var userRatingBaseList: List? = null,
var userRatingBaseNextList: List? = null,
var userLoginBonusList: List? = null,
var userMapAreaList: List? = null,
var userOverPowerList: List? = null,
- var userNetBattlelogList: List? = null,
+ var userNetBattlelogList: List? = null,
var userEmoneyList: List? = null,
- var userNetBattleData: List? = null,
+ var userNetBattleData: List? = null,
var userCMissionList: List? = null,
var userFavoriteMusicList: List? = null,
)
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserGacha.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserGacha.java
deleted file mode 100644
index 5e8c2aba..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserGacha.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.request;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import icu.samnyan.aqua.sega.chusan.model.gamedata.GameGachaCard;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserGacha;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.springframework.lang.Nullable;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UpsertUserGacha implements Serializable {
-
- @Nullable
- private Chu3UserData userData;
-
- @Nullable
- private UserGacha userGacha;
-
- @Nullable
- private List userCharacterList;
-
- @Nullable
- private List userCardList;
-
- @Nullable
- private List gameGachaCardList;
-
- @Nullable
- private List userItemList;
-
- @Nullable
- @JsonProperty("isNewCharacterList")
- private String isNewCharacterList;
-
- @Nullable
- @JsonProperty("isNewCardList")
- private String isNewCardList;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserGacha.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserGacha.kt
new file mode 100644
index 00000000..92c3ab39
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UpsertUserGacha.kt
@@ -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.UserGacha
+import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem
+import java.io.Serializable
+
+class UpsertUserGacha : Serializable {
+ var userData: Chu3UserData? = null
+ var userGacha: UserGacha? = null
+ var userCharacterList: List? = null
+ var userCardList: List? = null
+ var gameGachaCardList: List? = null
+ var userItemList: List? = null
+
+ @JsonProperty("isNewCharacterList")
+ var isNewCharacterList: String? = null
+ @JsonProperty("isNewCardList")
+ var isNewCardList: String? = null
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UserEmoney.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UserEmoney.kt
new file mode 100644
index 00000000..c3b47267
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/request/UserEmoney.kt
@@ -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
+)
+
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/GameRanking.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/GameRanking.java
deleted file mode 100644
index b58834d1..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/GameRanking.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.response.data;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class GameRanking {
- private int id;
- private long point;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/SymbolChatInfo.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/SymbolChatInfo.java
deleted file mode 100644
index fd4c9b21..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/SymbolChatInfo.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.response.data;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class SymbolChatInfo {
-
- private int sceneId;
- private int symbolChatId;
- private int orderId;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/UserEmoney.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/UserEmoney.java
deleted file mode 100644
index 9517e9b4..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/UserEmoney.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.response.data;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserEmoney {
-
- private int type = 0;
- private int emoneyCredit = 69;
- private int emoneyBrand = 2;
- private int ext1 = 0;
- private int ext2 = 0;
- private int ext3 = 0;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/UserFavorite.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/UserFavorite.java
deleted file mode 100644
index 596286d7..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/response/data/UserFavorite.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.response.data;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserFavorite {
-
- private int id;
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3MatchingMember.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3MatchingMember.kt
index 2c64e57e..fd3a40c5 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3MatchingMember.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3MatchingMember.kt
@@ -1,13 +1,8 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
import com.fasterxml.jackson.annotation.JsonProperty
-import icu.samnyan.aqua.net.games.BaseEntity
-import jakarta.persistence.Entity
-import jakarta.persistence.Table
-@Entity(name = "ChusanMatchingMember")
-@Table(name = "chusan_matching_member")
-class Chu3MatchingMember : BaseEntity() {
+open class Chu3MatchingMember {
var userId: Long = 0
var regionId = 0
var placeId = 0
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3NetBattleLog.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3NetBattleLog.kt
new file mode 100644
index 00000000..3d6e15e6
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3NetBattleLog.kt
@@ -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)
+ )
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserData.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserData.kt
index 1d7af85c..b357c9e5 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserData.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserData.kt
@@ -6,7 +6,7 @@ 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.chusan.model.response.data.UserEmoney
+import icu.samnyan.aqua.sega.chusan.model.request.UserEmoney
import icu.samnyan.aqua.sega.general.model.Card
import icu.samnyan.aqua.sega.util.jackson.AccessCodeSerializer
import jakarta.persistence.*
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserEntity.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserEntity.kt
index c86edc01..a45722f1 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserEntity.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserEntity.kt
@@ -8,9 +8,9 @@ import jakarta.persistence.ManyToOne
import jakarta.persistence.MappedSuperclass
@MappedSuperclass
-open class Chu3UserEntity : BaseEntity(), IUserEntity {
+class Chu3UserEntity : BaseEntity(), IUserEntity {
@JsonIgnore
@ManyToOne
@JoinColumn(name = "user_id")
- public override var user: Chu3UserData = Chu3UserData()
+ override var user: Chu3UserData = Chu3UserData()
}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserMisc.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserMisc.kt
new file mode 100644
index 00000000..c767cb1f
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/Chu3UserMisc.kt
@@ -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 = mutableListOf(),
+
+ @Convert(converter = IntegerListConverter::class)
+ var recentNbMusic: MutableList = mutableListOf(),
+
+ @Convert(converter = IntegerListConverter::class)
+ var favMusic: MutableList = mutableListOf()
+): Chu3UserEntity()
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserActivity.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserActivity.kt
index 5a1f8b6c..ef5d527b 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserActivity.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserActivity.kt
@@ -8,9 +8,7 @@ import jakarta.persistence.UniqueConstraint
@Entity(name = "ChusanUserActivity")
@Table(name = "chusan_user_activity", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "kind", "activity_id"])])
-class UserActivity(user: Chu3UserData) : Chu3UserEntity() {
- init { this.user = user }
-
+class UserActivity : Chu3UserEntity() {
var kind = 0
@JsonProperty("id")
@Column(name = "activity_id")
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCMission.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCMission.kt
index 674fee72..e8c8c70b 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCMission.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCMission.kt
@@ -1,15 +1,11 @@
package icu.samnyan.aqua.sega.chusan.model.userdata
-import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Table
@Entity(name = "ChusanUserCMission")
@Table(name = "chusan_user_cmission")
class UserCMission : Chu3UserEntity() {
- @Column(name = "mission_id")
var missionId = 0
-
- @Column(name = "point")
var point = 0
}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCardPrintState.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCardPrintState.kt
index 51759369..faa2e1d6 100644
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCardPrintState.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCardPrintState.kt
@@ -6,10 +6,11 @@ import java.time.LocalDateTime
@Entity(name = "ChusanUserCardPrintState")
@Table(name = "chusan_user_print_state")
-class UserCardPrintState : Chu3UserEntity() {
- var hasCompleted = false
- var limitDate: LocalDateTime = LocalDateTime.now()
- var placeId = 0
- var cardId = 0
- var gachaId = 0
-}
+class UserCardPrintState(
+ var hasCompleted: Boolean = false,
+ var limitDate: LocalDateTime = LocalDateTime.now(),
+ var placeId: Int = 0,
+ var cardId: Int = 0,
+ var gachaId: Int = 0
+) : Chu3UserEntity()
+
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharacter.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharacter.java
deleted file mode 100644
index aff9f1d1..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharacter.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserCharacter")
-@Table(name = "chusan_user_character", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "character_id"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonPropertyOrder({"characterId", "playCount", "level", "friendshipExp", "isValid", "isNewMark", "exMaxLv", "assignIllust", "param1", "param2"})
-public class UserCharacter extends Chu3UserEntity {
- @Column(name = "character_id")
- private int characterId;
-
- private int playCount = 0;
-
- private int level = 1;
-
- private int friendshipExp = 0;
-
- @JsonProperty("isValid")
- private boolean isValid = true;
-
- @JsonProperty("isNewMark")
- private boolean isNewMark = true;
-
- private int exMaxLv = 0;
-
- private int assignIllust = 0;
-
- private int param1 = 0;
-
- private int param2 = 0;
-
- public UserCharacter(Chu3UserData userData) {
- setUser(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharacter.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharacter.kt
new file mode 100644
index 00000000..ce55c47a
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharacter.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharge.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharge.java
deleted file mode 100644
index cc8dc528..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharge.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserCharge")
-@Table(name = "chusan_user_charge", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "charge_id"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonPropertyOrder({"chargeId", "stock", "purchaseDate", "validDate", "param1", "param2", "paramDate"})
-public class UserCharge extends Chu3UserEntity {
- @Column(name = "charge_id")
- private int chargeId;
-
- private int stock;
-
- private LocalDateTime purchaseDate;
-
- private LocalDateTime validDate;
-
- private int param1;
-
- private int param2;
-
- private LocalDateTime paramDate;
-
- public UserCharge(Chu3UserData user) {
- setUser(user);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharge.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharge.kt
new file mode 100644
index 00000000..a6a206ed
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCharge.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCourse.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCourse.java
deleted file mode 100644
index 1dc46d51..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCourse.java
+++ /dev/null
@@ -1,71 +0,0 @@
-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 lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserCourse")
-@Table(name = "chusan_user_course", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "course_id"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class UserCourse extends Chu3UserEntity {
- @Column(name = "course_id")
- private int courseId;
-
- private int classId;
-
- private int playCount;
-
- private int theoryCount;
-
- private int scoreMax;
-
- @JsonProperty("isFullCombo")
- private boolean isFullCombo;
-
- @JsonProperty("isAllJustice")
- private boolean isAllJustice;
-
- @JsonProperty("isSuccess")
- private boolean isSuccess;
-
- private int scoreRank;
-
- private int eventId;
-
- private LocalDateTime lastPlayDate;
-
- private int param1;
-
- private int param2;
-
- private int param3;
-
- private int param4;
-
- private int orderId;
-
- private int playerRating;
-
- @JsonProperty("isClear")
- private boolean isClear;
-
- public UserCourse(Chu3UserData userData) {
- setUser(userData);
- }
-
- public UserCourse(int classId) {
- this.classId = classId;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCourse.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCourse.kt
new file mode 100644
index 00000000..1d92cecb
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserCourse.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserDuel.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserDuel.java
deleted file mode 100644
index 33cc6f9b..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserDuel.java
+++ /dev/null
@@ -1,46 +0,0 @@
-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 lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserDuel")
-@Table(name = "chusan_user_duel", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "duel_id"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class UserDuel extends Chu3UserEntity {
- @Column(name = "duel_id")
- private int duelId;
-
- private int progress;
-
- private int point;
-
- @JsonProperty("isClear")
- private boolean isClear;
-
- private LocalDateTime lastPlayDate;
-
- private int param1;
-
- private int param2;
-
- private int param3;
-
- private int param4;
-
- public UserDuel(Chu3UserData userData) {
- setUser(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserDuel.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserDuel.kt
new file mode 100644
index 00000000..bb270f94
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserDuel.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGacha.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGacha.java
deleted file mode 100644
index 5ad4c0d4..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGacha.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserGacha")
-@Table(name = "chusan_user_gacha", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "gacha_id"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class UserGacha extends Chu3UserEntity {
- @Column(name = "gacha_id")
- private int gachaId;
-
- private int totalGachaCnt;
-
- private int ceilingGachaCnt;
-
- private int dailyGachaCnt;
-
- private int fiveGachaCnt;
-
- private int elevenGachaCnt;
-
- private LocalDateTime dailyGachaDate;
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGacha.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGacha.kt
new file mode 100644
index 00000000..f75856a3
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGacha.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGameOption.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGameOption.java
deleted file mode 100644
index 8fc09020..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGameOption.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserGameOption")
-@Table(name = "chusan_user_game_option")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonPropertyOrder({
- "bgInfo",
- "fieldColor",
- "guideSound",
- "soundEffect",
- "guideLine",
- "speed",
- "optionSet",
- "matching",
- "judgePos",
- "rating",
- "judgeCritical",
- "judgeJustice",
- "judgeAttack",
- "headphone",
- "playerLevel",
- "successTap",
- "successExTap",
- "successSlideHold",
- "successAir",
- "successFlick",
- "successSkill",
- "successTapTimbre",
- "privacy",
- "mirrorFumen",
- "selectMusicFilterLv",
- "sortMusicFilterLv",
- "sortMusicGenre",
- "categoryDetail",
- "judgeTimingOffset",
- "playTimingOffset",
- "fieldWallPosition",
- "resultVoiceShort",
- "notesThickness",
- "judgeAppendSe",
- "trackSkip",
- "hardJudge",
- "speed_120",
- "fieldWallPosition_120",
- "playTimingOffset_120",
- "judgeTimingOffset_120",
- "ext1",
- "ext2",
- "ext3",
- "ext4",
- "ext5",
- "ext6",
- "ext7",
- "ext8",
- "ext9",
- "ext10"
-})
-public class UserGameOption extends Chu3UserEntity {
-
- private int bgInfo;
-
- private int fieldColor;
-
- private int guideSound;
-
- private int soundEffect;
-
- private int guideLine;
-
- private int speed;
-
- private int optionSet;
-
- private int matching;
-
- private int judgePos;
-
- private int rating;
-
- private int judgeCritical;
-
- private int judgeJustice;
-
- private int judgeAttack;
-
- private int headphone;
-
- private int playerLevel;
-
- private int successTap;
-
- private int successExTap;
-
- private int successSlideHold;
-
- private int successAir;
-
- private int successFlick;
-
- private int successSkill;
-
- private int successTapTimbre;
-
- private int privacy;
-
- private int mirrorFumen;
-
- private int selectMusicFilterLv;
-
- private int sortMusicFilterLv;
-
- private int sortMusicGenre;
-
- private int categoryDetail;
-
- private int judgeTimingOffset;
-
- private int playTimingOffset;
-
- private int fieldWallPosition;
-
- private int resultVoiceShort;
-
- private int notesThickness;
-
- private int judgeAppendSe;
-
- private int trackSkip;
-
- private int hardJudge;
-
- private int speed_120;
-
- private int fieldWallPosition_120;
-
- private int playTimingOffset_120;
-
- private int judgeTimingOffset_120;
-
- private int ext1;
-
- private int ext2;
-
- private int ext3;
-
- private int ext4;
-
- private int ext5;
-
- private int ext6;
-
- private int ext7;
-
- private int ext8;
-
- private int ext9;
-
- private int ext10;
-
- public UserGameOption(Chu3UserData userData) {
- setUser(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGameOption.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGameOption.kt
new file mode 100644
index 00000000..53bbd421
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGameOption.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGeneralData.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGeneralData.java
deleted file mode 100644
index 9597947a..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGeneralData.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * This is for storing the other data that doesn't need to save it in a separate table
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserGeneralData")
-@Table(name = "chusan_user_general_data")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class UserGeneralData extends Chu3UserEntity {
- private String propertyKey;
-
- @Column(columnDefinition = "TEXT")
- private String propertyValue;
-
- public UserGeneralData(Chu3UserData userData, String key) {
- setUser(userData);
- this.propertyKey = key;
- this.propertyValue = "";
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGeneralData.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGeneralData.kt
new file mode 100644
index 00000000..be7cbf0e
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserGeneralData.kt
@@ -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()
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserItem.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserItem.java
deleted file mode 100644
index 4febb59b..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserItem.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserItem")
-@Table(name = "chusan_user_item", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "item_id", "item_kind"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonPropertyOrder({"itemKind", "itemId", "stock", "isValid"})
-public class UserItem extends Chu3UserEntity {
- // Kind ,Type
- @Column(name = "item_kind")
- private int itemKind;
-
- @Column(name = "item_id")
- private int itemId;
-
- private int stock = 1;
-
- @JsonProperty("isValid")
- private boolean isValid = true;
-
- public UserItem(Chu3UserData userData) {
- setUser(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserItem.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserItem.kt
new file mode 100644
index 00000000..94fd554f
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserItem.kt
@@ -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 UserItem(
+ var itemKind: Int = 0,
+ var itemId: Int = 0,
+ var stock: Int = 1,
+ @JsonProperty("isValid")
+ var isValid: Boolean = true
+) : Chu3UserEntity()
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserLoginBonus.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserLoginBonus.java
deleted file mode 100644
index 623094c7..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserLoginBonus.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import icu.samnyan.aqua.net.games.BaseEntity;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-@Entity(name = "ChusanUserLoginBonus")
-@Table(name = "chusan_user_login_bonus")
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserLoginBonus extends BaseEntity {
- private int version;
- private int user;
- private int presetId;
- private int bonusCount;
- private LocalDateTime lastUpdateDate;
- private boolean isWatched;
- private boolean isFinished;
-
- public UserLoginBonus(int version, int user, int presetId) {
- this.version = version;
- this.user = user;
- this.presetId = presetId;
- this.bonusCount = 0;
- this.lastUpdateDate = LocalDateTime.parse("2018-01-01T00:00:00");
- this.isWatched = false;
- this.isFinished = false;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserLoginBonus.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserLoginBonus.kt
new file mode 100644
index 00000000..996da40f
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserLoginBonus.kt
@@ -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()
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMap.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMap.java
deleted file mode 100644
index d1562a3b..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMap.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserMapArea")
-@Table(name = "chusan_user_map_area", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "map_area_id"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonPropertyOrder({
- "mapAreaId",
- "position",
- "isClear",
- "rate",
- "statusCount",
- "remainGridCount",
- "isLocked"
-})
-public class UserMap extends Chu3UserEntity {
- @Column(name = "map_area_id")
- private int mapAreaId;
-
- private int position;
-
- @JsonProperty("isClear")
- private boolean isClear;
-
- private int rate;
-
- private int statusCount;
-
- private int remainGridCount;
-
- @JsonProperty("isLocked")
- private boolean isLocked;
-
- public UserMap(Chu3UserData userData) {
- setUser(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMap.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMap.kt
new file mode 100644
index 00000000..271b060b
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMap.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMusicDetail.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMusicDetail.java
deleted file mode 100644
index 00beb1ce..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMusicDetail.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.model.userdata;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import icu.samnyan.aqua.sega.util.jackson.BooleanToIntegerDeserializer;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserMusicDetail")
-@Table(name = "chusan_user_music_detail", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "music_id", "level"})})
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonPropertyOrder({
- "musicId",
- "level",
- "playCount",
- "scoreMax",
- "missCount",
- "maxComboCount",
- "isFullCombo",
- "isAllJustice",
- "isSuccess",
- "fullChain",
- "maxChain",
- "isLock",
- "theoryCount",
- "ext1"
-})
-public class UserMusicDetail extends Chu3UserEntity {
- @Column(name = "music_id")
- private int musicId;
-
- private int level;
-
- private int playCount;
-
- private int scoreMax;
-
- private int missCount;
-
- private int maxComboCount;
-
- @JsonProperty("isFullCombo")
- private boolean isFullCombo;
-
- @JsonProperty("isAllJustice")
- private boolean isAllJustice;
-
- @JsonDeserialize(using = BooleanToIntegerDeserializer.class)
- @JsonProperty("isSuccess")
- private int isSuccess;
-
- private int fullChain;
-
- private int maxChain;
-
- private int scoreRank;
-
- @JsonProperty("isLock")
- private boolean isLock;
-
- private int theoryCount;
-
- private int ext1;
-
- public UserMusicDetail(Chu3UserData userData) {
- setUser(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMusicDetail.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMusicDetail.kt
new file mode 100644
index 00000000..14884f48
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserMusicDetail.kt
@@ -0,0 +1,45 @@
+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.sega.util.jackson.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() {
+ 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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserPlaylog.java b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserPlaylog.java
deleted file mode 100644
index d8162950..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserPlaylog.java
+++ /dev/null
@@ -1,167 +0,0 @@
-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 lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Entity(name = "ChusanUserPlaylog")
-@Table(name = "chusan_user_playlog")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class UserPlaylog extends Chu3UserEntity implements IGenericGamePlaylog {
- private String romVersion;
-
- private int orderId;
-
- private int sortNumber;
-
- private int placeId;
-
- private LocalDateTime playDate;
-
- private LocalDateTime userPlayDate;
-
- private int musicId;
-
- private int level;
-
- private int customId;
-
- private long playedUserId1;
-
- private long playedUserId2;
-
- private long playedUserId3;
-
- private String playedUserName1;
-
- private String playedUserName2;
-
- private String playedUserName3;
-
- private int playedMusicLevel1;
-
- private int playedMusicLevel2;
-
- private int playedMusicLevel3;
-
- private int playedCustom1;
-
- private int playedCustom2;
-
- private int playedCustom3;
-
- private int track;
-
- private int score;
-
- @Column(name = "\"rank\"")
- private int rank;
-
- private int maxCombo;
-
- private int maxChain;
-
- private int rateTap;
-
- private int rateHold;
-
- private int rateSlide;
-
- private int rateAir;
-
- private int rateFlick;
-
- private int judgeGuilty;
-
- private int judgeAttack;
-
- private int judgeJustice;
-
- private int judgeCritical;
-
- private int judgeHeaven;
-
- private int eventId;
-
- private int playerRating;
-
- @JsonProperty("isNewRecord")
- private boolean isNewRecord;
-
- @JsonProperty("isFullCombo")
- private boolean isFullCombo;
-
- private int fullChainKind;
-
- @JsonProperty("isAllJustice")
- private boolean isAllJustice;
-
- @JsonProperty("isContinue")
- private boolean isContinue;
-
- @JsonProperty("isFreeToPlay")
- private boolean isFreeToPlay;
-
- private int characterId;
-
- private int charaIllustId;
-
- private int skillId;
-
- private int playKind;
-
- @JsonProperty("isClear")
- private boolean isClear;
-
- private int skillLevel;
-
- private int skillEffect;
-
- private String placeName;
-
- private int commonId;
-
- // SUN
- private int regionId;
-
- private int machineType;
-
- // SUN PLUS
- private int ticketId;
-
- public UserPlaylog(Chu3UserData userData) {
- setUser(userData);
- }
-
- @Override
- public int getAchievement() {
- return score;
- }
-
- @Override
- public int getAfterRating() {
- return playerRating;
- }
-
- @Override
- public int getBeforeRating() {
- return playerRating; // TODO: Get before rating
- }
-
- @Override
- public boolean isAllPerfect() {
- return isAllJustice;
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserPlaylog.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserPlaylog.kt
new file mode 100644
index 00000000..00bf15df
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserPlaylog.kt
@@ -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
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/GameLoginBonusPresetService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/GameLoginBonusPresetService.java
deleted file mode 100644
index ea579989..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/GameLoginBonusPresetService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3GameLoginBonusPresetsRepo;
-import icu.samnyan.aqua.sega.chusan.model.gamedata.GameLoginBonusPreset;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service("ChusanGameLoginBonusPresetService")
-public class GameLoginBonusPresetService {
- private final Chu3GameLoginBonusPresetsRepo gameLoginBonusPresetsRepository;
-
- @Autowired
- public GameLoginBonusPresetService(Chu3GameLoginBonusPresetsRepo gameLoginBonusPresetsRepository){
- this.gameLoginBonusPresetsRepository = gameLoginBonusPresetsRepository;
- }
-
- public List getGameLoginBonusPresets(int version){
- return this.gameLoginBonusPresetsRepository.findLoginBonusPresets(version, 1);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/GameLoginBonusService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/GameLoginBonusService.java
deleted file mode 100644
index f20c813e..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/GameLoginBonusService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3GameLoginBonusRepo;
-import icu.samnyan.aqua.sega.chusan.model.gamedata.GameLoginBonus;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-@Service("ChusanGameLoginBonusService")
-public class GameLoginBonusService {
- private final Chu3GameLoginBonusRepo gameLoginBonusRepository;
-
- @Autowired
- public GameLoginBonusService(Chu3GameLoginBonusRepo gameLoginBonusRepository){
- this.gameLoginBonusRepository = gameLoginBonusRepository;
- }
-
- public List getAllGameLoginBonus(int presetId){
- return this.gameLoginBonusRepository.findGameLoginBonus(1, presetId);
- }
-
- public Optional getGameLoginBonusByDay(int presetId, int day){
- return this.gameLoginBonusRepository.findByRequiredDays(1, presetId, day);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserActivityService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserActivityService.java
deleted file mode 100644
index d616fb6b..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserActivityService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserActivityRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserActivity;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserActivityService")
-public class UserActivityService {
-
- private final Chu3UserActivityRepo userActivityRepository;
-
- @Autowired
- public UserActivityService(Chu3UserActivityRepo userActivityRepository) {
- this.userActivityRepository = userActivityRepository;
- }
-
- public List getByUserId(String userId) {
- return userActivityRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserCharacterService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserCharacterService.java
deleted file mode 100644
index 37503da1..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserCharacterService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserCharacterRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharacter;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserCharacterService")
-public class UserCharacterService {
-
- private final Chu3UserCharacterRepo userCharacterRepository;
-
- @Autowired
- public UserCharacterService(Chu3UserCharacterRepo userCharacterRepository) {
- this.userCharacterRepository = userCharacterRepository;
- }
-
- public UserCharacter save(UserCharacter userCharacter) {
- return userCharacterRepository.save(userCharacter);
- }
-
- public List saveAll(Iterable userCharacter) {
- return userCharacterRepository.saveAll(userCharacter);
- }
-
- public List getByUserId(String userId) {
- return userCharacterRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-
- public Page getByUserId(String userId, int pageNumber, int maxCount) {
- Pageable pageable = PageRequest.of(pageNumber, maxCount);
- return userCharacterRepository.findByUser_Card_ExtId(Long.parseLong(userId), pageable);
- }
-
- public Optional getByUserAndCharacterId(Chu3UserData user, int characterId) {
- return userCharacterRepository.findTopByUserAndCharacterIdOrderByIdDesc(user, characterId);
- }
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserChargeService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserChargeService.java
deleted file mode 100644
index 1abfb80c..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserChargeService.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserChargeRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharge;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserChargeService")
-public class UserChargeService {
-
- private final Chu3UserChargeRepo userChargeRepository;
-
- public UserChargeService(Chu3UserChargeRepo userChargeRepository) {
- this.userChargeRepository = userChargeRepository;
- }
-
- public UserCharge save(UserCharge userCharge) {
- return userChargeRepository.save(userCharge);
- }
-
- public List saveAll(List newUserChargeList) {
- return userChargeRepository.saveAll(newUserChargeList);
- }
-
- public List getByUserId(String userId) {
- return userChargeRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-
- public Optional getByUserAndChargeId(Chu3UserData user, int chargeId) {
- return userChargeRepository.findByUserAndChargeId(user, chargeId);
- }
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserCourseService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserCourseService.java
deleted file mode 100644
index 00459404..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserCourseService.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserCourseRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserCourse;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserCourseService")
-public class UserCourseService {
-
- private final Chu3UserCourseRepo userCourseRepository;
-
- @Autowired
- public UserCourseService(Chu3UserCourseRepo userCourseRepository) {
- this.userCourseRepository = userCourseRepository;
- }
-
- public UserCourse save(UserCourse userCourse) {
- return userCourseRepository.save(userCourse);
- }
-
- public List saveAll(Iterable userMusicDetail) {
- return userCourseRepository.saveAll(userMusicDetail);
- }
-
- public List getByUserId(String userId) {
- return userCourseRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-
- public Page getByUserId(String userId, int pageNum, int maxCount) {
- Pageable page = PageRequest.of(pageNum, maxCount);
- return userCourseRepository.findByUser_Card_ExtId(Long.parseLong(userId), page);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserDataService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserDataService.java
deleted file mode 100644
index ff9477bd..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserDataService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserDataRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.general.model.Card;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDateTime;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserDataService")
-public class UserDataService {
-
- private final Chu3UserDataRepo userDataRepository;
-
- @Autowired
- public UserDataService(Chu3UserDataRepo userDataRepository) {
- this.userDataRepository = userDataRepository;
- }
-
- public Chu3UserData saveUserData(Chu3UserData userData) {
- return userDataRepository.save(userData);
- }
-
- public Optional getUserByExtId(String aimeId) {
- return userDataRepository.findByCard_ExtId(Long.parseLong(aimeId));
- }
-
- public void updateLoginTime(Chu3UserData userData) {
- userData.setLastLoginDate(LocalDateTime.now());
- userDataRepository.save(userData);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserDuelService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserDuelService.java
deleted file mode 100644
index 43552acd..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserDuelService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserDuelRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserDuel;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserDuelService")
-public class UserDuelService {
-
- private final Chu3UserDuelRepo userDuelRepository;
-
- @Autowired
- public UserDuelService(Chu3UserDuelRepo userDuelRepository) {
- this.userDuelRepository = userDuelRepository;
- }
-
- public List getByUserId(String userId) {
- return userDuelRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGachaService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGachaService.java
deleted file mode 100644
index d59d6416..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGachaService.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserGachaRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserGacha;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserGachaService")
-public class UserGachaService {
-
- private final Chu3UserGachaRepo userGachaRepository;
-
- public UserGachaService(Chu3UserGachaRepo userGachaRepository) {
- this.userGachaRepository = userGachaRepository;
- }
-
- public UserGacha save(UserGacha userGacha) {
- return userGachaRepository.save(userGacha);
- }
-
- public List saveAll(List newUserGachaList) {
- return userGachaRepository.saveAll(newUserGachaList);
- }
-
- public List getByUserId(String userId) {
- return userGachaRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGameOptionService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGameOptionService.java
deleted file mode 100644
index 3e618cb5..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGameOptionService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserGameOptionRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserGameOption;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanGameOptionService")
-public class UserGameOptionService {
-
- private final Chu3UserGameOptionRepo userGameOptionRepository;
-
- @Autowired
- public UserGameOptionService(Chu3UserGameOptionRepo userGameOptionRepository) {
- this.userGameOptionRepository = userGameOptionRepository;
- }
-
- public UserGameOption save(UserGameOption userGameOption) {
- return userGameOptionRepository.save(userGameOption);
- }
-
- public Optional getByUser(Chu3UserData user) {
- return userGameOptionRepository.findSingleByUser(user);
- }
-
- public Optional getByUserId(String userId) {
- return userGameOptionRepository.findSingleByUser_Card_ExtId(Long.parseLong(userId));
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGeneralDataService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGeneralDataService.java
deleted file mode 100644
index 614fe680..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserGeneralDataService.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserGeneralDataRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserGeneralData;
-import org.springframework.stereotype.Service;
-
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserGeneralDataService")
-public class UserGeneralDataService {
-
- private final Chu3UserGeneralDataRepo userGeneralDataRepository;
-
- public UserGeneralDataService(Chu3UserGeneralDataRepo userGeneralDataRepository) {
- this.userGeneralDataRepository = userGeneralDataRepository;
- }
-
- public UserGeneralData save(UserGeneralData userGeneralData) {
- return userGeneralDataRepository.save(userGeneralData);
- }
-
- public Optional getByUserAndKey(Chu3UserData user, String key) {
- return userGeneralDataRepository.findByUserAndPropertyKey(user, key);
- }
-
- public Optional getByUserIdAndKey(String userId, String key) {
- return userGeneralDataRepository.findByUser_Card_ExtIdAndPropertyKey(Long.parseLong(userId), key);
- }
-
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserItemService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserItemService.java
deleted file mode 100644
index 7f257ab6..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserItemService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserItemRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Service;
-
-import java.util.Comparator;
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserItemService")
-public class UserItemService {
- private final Chu3UserItemRepo userItemRepository;
-
- @Autowired
- public UserItemService(Chu3UserItemRepo userItemRepository) {
- this.userItemRepository = userItemRepository;
- }
-
- public UserItem save(UserItem userItem) {
- return userItemRepository.save(userItem);
- }
-
- public List saveAll(Iterable userItem) {
- return userItemRepository.saveAll(userItem);
- }
-
- public List getByUserId(String userId) {
- List userItemList = userItemRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- userItemList.sort(Comparator.comparingInt(UserItem::getItemId));
- return userItemList;
- }
-
- public Optional getByUserAndItemIdAndKind(Chu3UserData user, int itemId, int itemKind) {
- return userItemRepository.findTopByUserAndItemIdAndItemKindOrderByIdDesc(user, itemId, itemKind);
- }
-
- public Page getByUserAndItemKind(String userId, int kind, int pageNumber, int maxCount) {
- Pageable page = PageRequest.of(pageNumber, maxCount);
- return userItemRepository.findAllByUser_Card_ExtIdAndItemKind(Long.parseLong(userId), kind, page);
- }
-
- public List getByUserAndItemKind(String userId, int kind) {
- List userItemList = userItemRepository.findAllByUser_Card_ExtIdAndItemKind(Long.parseLong(userId), kind);
- userItemList.sort(Comparator.comparingInt(UserItem::getItemId));
- return userItemList;
- }
-
- public Page getByUserId(String userId, int page, int size) {
- return userItemRepository.findByUser_Card_ExtId(Long.parseLong(userId), PageRequest.of(page, size));
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserLoginBonusService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserLoginBonusService.java
deleted file mode 100644
index 0f661729..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserLoginBonusService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserLoginBonusRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserLoginBonus;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-@Service("ChusanUserLoginBonusService")
-public class UserLoginBonusService {
- private final Chu3UserLoginBonusRepo chusanUserLoginBonusRepository;
-
- @Autowired
- public UserLoginBonusService(Chu3UserLoginBonusRepo chusanUserLoginBonusRepository){
- this.chusanUserLoginBonusRepository = chusanUserLoginBonusRepository;
- }
-
- public Optional getUserLoginBonus(int userId, int preset_id){
- return this.chusanUserLoginBonusRepository.findLoginBonus(userId, 1, preset_id);
- }
-
- public List getAllUserLoginBonus(int userId){
- return this.chusanUserLoginBonusRepository.findAllLoginBonus(userId, 1, 0);
- }
-
- public void saveUserLoginBonus(UserLoginBonus userLoginBonus){
- this.chusanUserLoginBonusRepository.save(userLoginBonus);
- }
-
- public void saveAll(Iterable userLoginBonuses) {
- this.chusanUserLoginBonusRepository.saveAll(userLoginBonuses);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserMapAreaService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserMapAreaService.java
deleted file mode 100644
index e7300e7e..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserMapAreaService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserMapRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserMap;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserMapAreaService")
-public class UserMapAreaService {
-
- private final Chu3UserMapRepo userMapRepository;
-
- @Autowired
- public UserMapAreaService(Chu3UserMapRepo userMapRepository) {
- this.userMapRepository = userMapRepository;
- }
-
- public List getByUserId(String userId) {
- return userMapRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserMusicDetailService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserMusicDetailService.java
deleted file mode 100644
index a115ff06..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserMusicDetailService.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserMusicDetailRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserMusicDetail;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserMusicDetailService")
-public class UserMusicDetailService {
-
- private final Chu3UserMusicDetailRepo userMusicDetailRepository;
-
- @Autowired
- public UserMusicDetailService(Chu3UserMusicDetailRepo userMusicDetailRepository) {
- this.userMusicDetailRepository = userMusicDetailRepository;
- }
-
- public List getByUserId(String userId) {
- return userMusicDetailRepository.findByUser_Card_ExtId(Long.parseLong(userId));
- }
-
- public Page getByUserId(String userId, Pageable page) {
- return userMusicDetailRepository.findByUser_Card_ExtId(Long.parseLong(userId), page);
- }
-
- public List getByUserIdAndMusicId(String userId, int musicId) {
- return userMusicDetailRepository.findByUser_Card_ExtIdAndMusicId(Long.parseLong(userId), musicId);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserPlaylogService.java b/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserPlaylogService.java
deleted file mode 100644
index 6d3d664c..00000000
--- a/src/main/java/icu/samnyan/aqua/sega/chusan/service/UserPlaylogService.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package icu.samnyan.aqua.sega.chusan.service;
-
-import icu.samnyan.aqua.sega.chusan.model.Chu3UserPlaylogRepo;
-import icu.samnyan.aqua.sega.chusan.model.userdata.UserPlaylog;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * @author samnyan (privateamusement@protonmail.com)
- */
-@Service("ChusanUserPlaylogService")
-public class UserPlaylogService {
-
- private final Chu3UserPlaylogRepo userPlaylogRepository;
-
- @Autowired
- public UserPlaylogService(Chu3UserPlaylogRepo userPlaylogRepository) {
- this.userPlaylogRepository = userPlaylogRepository;
- }
-
- public Page getRecentPlays(String userId, Pageable page) {
- return userPlaylogRepository.findByUserCardExtId(Long.parseLong(userId), page);
- }
-
- public List getRecent30Plays(String userId) {
- Pageable page = PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "userPlayDate"));
- return userPlaylogRepository.findByUser_Card_ExtIdAndLevelNot(Long.parseLong(userId), 5, page);
- }
-
- public List getByUserId(String userId) {
- return userPlaylogRepository.findByUserCardExtId(Long.parseLong(userId));
- }
-
- public List getByUserIdAndMusicIdAndLevel(String userId, int id, int level) {
- return userPlaylogRepository.findByUser_Card_ExtIdAndMusicIdAndLevel(Long.parseLong(userId), id, level);
- }
-}
diff --git a/src/main/java/icu/samnyan/aqua/sega/general/BaseHandler.kt b/src/main/java/icu/samnyan/aqua/sega/general/BaseHandler.kt
index 50726065..1b0d6e88 100644
--- a/src/main/java/icu/samnyan/aqua/sega/general/BaseHandler.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/general/BaseHandler.kt
@@ -62,7 +62,7 @@ abstract class MeowApi(val serialize: (String, Any?) -> String) {
}
else pageCache[cacheKey] = millis() to list
- (mapOf("userId" to uid, "length" to lst.size, "nextIndex" to iAfter, key to lst) + add).toMutableMap()
+ (mapOf("userId" to uid, "length" to lst.size, "nextIndex" to iAfter, key to lst) + add).mut
.also { p.post?.invoke(it) }
}
fun String.paged(key: String, fn: PagedHandler) = pagedWithKind(key) { PagedProcessor(null, fn) }
diff --git a/src/main/java/icu/samnyan/aqua/sega/general/IntegerListConverter.kt b/src/main/java/icu/samnyan/aqua/sega/general/IntegerListConverter.kt
index ad047057..74adde13 100644
--- a/src/main/java/icu/samnyan/aqua/sega/general/IntegerListConverter.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/general/IntegerListConverter.kt
@@ -1,11 +1,12 @@
package icu.samnyan.aqua.sega.general
+import ext.ls
import jakarta.persistence.AttributeConverter
import jakarta.persistence.Converter
@Converter
class IntegerListConverter : AttributeConverter, String> {
override fun convertToDatabaseColumn(lst: List?) = lst?.joinToString(";") ?: ""
- override fun convertToEntityAttribute(str: String?) = if (str.isNullOrBlank()) mutableListOf() else
- str.split(';').map { it.toInt() }.toMutableList()
+ override fun convertToEntityAttribute(str: String?) = if (str.isNullOrBlank()) ls() else
+ str.split(';').map { it.toInt() }
}
diff --git a/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.kt b/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.kt
index 4bae4d60..fd39d901 100644
--- a/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.kt
@@ -1,6 +1,9 @@
package icu.samnyan.aqua.sega.general.filter
+import ext.details
import ext.logger
+import ext.toJson
+import icu.samnyan.aqua.sega.allnet.TokenChecker
import icu.samnyan.aqua.sega.util.ZLib
import jakarta.servlet.FilterChain
import jakarta.servlet.http.HttpServletRequest
@@ -35,9 +38,22 @@ class CompressionFilter : OncePerRequestFilter() {
}
// Handle request
- val result = ContentCachingResponseWrapper(resp).run {
- chain.doFilter(CompressRequestWrapper(req, reqSrc), this)
- ZLib.compress(contentAsByteArray).let { if (isDfi) b64e.encode(it) else it }
+ val respW = ContentCachingResponseWrapper(resp)
+ val result = try {
+ chain.doFilter(CompressRequestWrapper(req, reqSrc), respW)
+ ZLib.compress(respW.contentAsByteArray).let { if (isDfi) b64e.encode(it) else it }
+ } finally {
+ if (respW.status != 200) {
+ val details = mapOf(
+ "req" to req.details(),
+ "resp" to respW.details(),
+ "body" to reqSrc.toString(Charsets.UTF_8),
+ "result" to respW.contentAsByteArray.toString(Charsets.UTF_8),
+ "token" to TokenChecker.getCurrentSession()?.token
+ ).toJson()
+
+ log.error("HTTP ${respW.status}: $details")
+ }
}
// Write response
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2ServletController.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2ServletController.kt
index 030d1c69..6834233a 100644
--- a/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2ServletController.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2ServletController.kt
@@ -319,17 +319,17 @@ class Maimai2ServletController(
"GetUserScoreRankingApi", "UpsertClientBookkeepingApi", "UpsertClientSettingApi",
"UpsertClientTestmodeApi", "UpsertClientUploadApi", "Ping", "RemoveTokenApi", "CMLoginApi", "CMLogoutApi",
"CMUpsertBuyCardApi", "GetGameSettingApi", "GetGameKaleidxScopeApi", "GetGameMusicScoreApi",
- "GetUserKaleidxScopeApi", "GetUserNewItemApi", "GetUserNewItemListApi").toMutableList()
+ "GetUserKaleidxScopeApi", "GetUserNewItemApi", "GetUserNewItemListApi").mut
- val noopEndpoint = endpointList.popAll("GetUserScoreRankingApi", "UpsertClientBookkeepingApi",
+ val noopEndpoint = setOf("GetUserScoreRankingApi", "UpsertClientBookkeepingApi",
"UpsertClientSettingApi", "UpsertClientTestmodeApi", "UpsertClientUploadApi", "Ping", "RemoveTokenApi",
"CMLoginApi", "CMLogoutApi", "CMUpsertBuyCardApi", "UserLogoutApi", "GetGameMapAreaConditionApi",
- "UpsertUserChargelogApi")
+ "UpsertUserChargelogApi").also { endpointList.removeAll(it) }
val staticEndpoint = mapOf(
"CreateTokenApi" to """{"Bearer":"meow"}""",
"CMUpsertUserPrintlogApi" to """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678"}""",
- ).also { endpointList.popAll(it.keys.toList()) }
+ ).also { endpointList.removeAll(it.keys.toSet()) }
val members = this::class.declaredMemberProperties
val handlers: Map = endpointList.associateWith { api ->
@@ -363,7 +363,7 @@ class Maimai2ServletController(
return try {
Metrics.timer("aquadx_maimai2_api_latency", "api" to api).recordCallable {
handlers[api]!!.handle(request).let { if (it is String) it else it.toJson() }.also {
- if (api !in setOf("GetUserItemApi", "GetGameEventApi"))
+ if (api !in setOf("GetUserItemApi", "GetGameEventApi", "GetUserPortraitApi"))
logger.info("Mai2 > $api : $it")
}
}
diff --git a/src/main/java/icu/samnyan/aqua/sega/wacca/WaccaServer.kt b/src/main/java/icu/samnyan/aqua/sega/wacca/WaccaServer.kt
index c5cb14e4..a1496ab2 100644
--- a/src/main/java/icu/samnyan/aqua/sega/wacca/WaccaServer.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/wacca/WaccaServer.kt
@@ -196,7 +196,7 @@ fun WaccaServer.init() {
"user/status/GetDetail" api@ { _, (uid) ->
val u = user(uid) ?: return@api "[]"
val o = options(u)
- val items = rp.item.findByUser(u).groupBy { it.type }.toMutableMap()
+ val items = rp.item.findByUser(u).groupBy { it.type }.mut
val scores = rp.bestScore.findByUser(u)
val scoreMap = scores.associateBy { it.musicId to it.level }
val gates = rp.gate.findByUser(u)
@@ -343,7 +343,7 @@ fun WaccaServer.init() {
?: WcUserScore().apply { user = u; musicId = pl.musicId; level = pl.level }).apply {
grades[WaccaGrades.valueMap[pl.grade]?.ordinal ?: (400 - "Grade ${pl.grade} invalid")]++
- clears = clears.zip(pl.clears()) { a, b -> a + b }.toMutableList()
+ clears = clears.zip(pl.clears()) { a, b -> a + b }.mut
achievement = max(achievement, pl.achievement)
bestCombo = max(bestCombo, pl.maxCombo)
lowestMissCt = min(lowestMissCt, pl.judgements[3])
@@ -425,7 +425,7 @@ fun WaccaServer.init() {
"user/status/update" empty { req, (uid, playType, items, isContinue, isFirstPlayFree, itemsUsed, lastSong) ->
val u = user(uid) ?: (404 - "User not found")
- u.lastSongInfo = (lastSong as List).toMutableList()
+ u.lastSongInfo = (lastSong as List).mut
afterPlay(u, items as List>, playType.int(), req.appVersion)
}
@@ -462,7 +462,7 @@ fun WaccaServer.init() {
clearStatus = clearType.int() // 0..3: Fail, Blue, Silver, Gold
clearSongCt = clearCt.int()
playCt++
- if (scores.sum() > s.songScores.sum()) songScores = scores.toMutableList()
+ if (scores.sum() > s.songScores.sum()) songScores = scores.mut
})
if (dan.int() > u.danLevel || (dan.int() == u.danLevel && clearType.int() > u.danType)) {
diff --git a/src/main/java/icu/samnyan/aqua/sega/wacca/model/db/WaccaUserModels.kt b/src/main/java/icu/samnyan/aqua/sega/wacca/model/db/WaccaUserModels.kt
index bc68ea9e..349e3e17 100644
--- a/src/main/java/icu/samnyan/aqua/sega/wacca/model/db/WaccaUserModels.kt
+++ b/src/main/java/icu/samnyan/aqua/sega/wacca/model/db/WaccaUserModels.kt
@@ -101,7 +101,7 @@ class WcUserScore : WaccaUserEntity() {
var clears: MutableList = mutableListOf(0, 0, 0, 0, 0) // Played, Clear, Full Combo, Missless, All Marv
@Convert(converter = IntegerListConverter::class)
- var grades: MutableList = (1..13).map { 0 }.toMutableList() // From D to SSS+
+ var grades: MutableList = (1..13).map { 0 }.mut // From D to SSS+
var bestCombo = 0
var lowestMissCt = Int.MAX_VALUE
var rating = 0
diff --git a/src/main/resources/db/migration/mariadb/V1000_26__chusan_matching.sql b/src/main/resources/db/migration/mariadb/V1000_26__chusan_matching.sql
new file mode 100644
index 00000000..4e872945
--- /dev/null
+++ b/src/main/resources/db/migration/mariadb/V1000_26__chusan_matching.sql
@@ -0,0 +1,2 @@
+ALTER TABLE aqua_game_options ADD chusan_matching_server VARCHAR(200) NULL;
+ALTER TABLE aqua_game_options ADD chusan_matching_reflector VARCHAR(200) NULL;
diff --git a/src/main/resources/db/migration/mariadb/V1000_27__chusan_net_battle_log.sql b/src/main/resources/db/migration/mariadb/V1000_27__chusan_net_battle_log.sql
new file mode 100644
index 00000000..97342bba
--- /dev/null
+++ b/src/main/resources/db/migration/mariadb/V1000_27__chusan_net_battle_log.sql
@@ -0,0 +1,52 @@
+CREATE TABLE chusan_net_battle_log
+(
+ id BIGINT AUTO_INCREMENT NOT NULL,
+ user_id BIGINT NULL,
+ room_id BIGINT NOT NULL,
+ track INT NOT NULL,
+ music_id INT NOT NULL,
+ difficulty_id INT NOT NULL,
+ score INT NOT NULL,
+ select_user_id BIGINT NOT NULL,
+ select_user_name VARCHAR(64) NULL,
+ opponent_user_id1 BIGINT NOT NULL,
+ opponent_user_id2 BIGINT NOT NULL,
+ opponent_user_id3 BIGINT NOT NULL,
+ opponent_user_name1 VARCHAR(64) NULL,
+ opponent_user_name2 VARCHAR(64) NULL,
+ opponent_user_name3 VARCHAR(64) NULL,
+ opponent_region_id1 INT NOT NULL,
+ opponent_region_id2 INT NOT NULL,
+ opponent_region_id3 INT NOT NULL,
+ opponent_rating1 INT NOT NULL,
+ opponent_rating2 INT NOT NULL,
+ opponent_rating3 INT NOT NULL,
+ opponent_battle_rank_id1 INT NOT NULL,
+ opponent_battle_rank_id2 INT NOT NULL,
+ opponent_battle_rank_id3 INT NOT NULL,
+ opponent_class_emblem_medal1 INT NOT NULL,
+ opponent_class_emblem_medal2 INT NOT NULL,
+ opponent_class_emblem_medal3 INT NOT NULL,
+ opponent_class_emblem_base1 INT NOT NULL,
+ opponent_class_emblem_base2 INT NOT NULL,
+ opponent_class_emblem_base3 INT NOT NULL,
+ opponent_score1 INT NOT NULL,
+ opponent_score2 INT NOT NULL,
+ opponent_score3 INT NOT NULL,
+ opponent_chara_illust_id1 INT NOT NULL,
+ opponent_chara_illust_id2 INT NOT NULL,
+ opponent_chara_illust_id3 INT NOT NULL,
+ opponent_chara_lv1 INT NOT NULL,
+ opponent_chara_lv2 INT NOT NULL,
+ opponent_chara_lv3 INT NOT NULL,
+ opponent_rating_effect_color_id1 INT NOT NULL,
+ opponent_rating_effect_color_id2 INT NOT NULL,
+ opponent_rating_effect_color_id3 INT NOT NULL,
+ battle_rule_id INT NOT NULL,
+ month_po_long INT NOT NULL,
+ event_po_long INT NOT NULL,
+ CONSTRAINT pk_chusan_net_battle_log PRIMARY KEY (id)
+);
+
+ALTER TABLE chusan_net_battle_log
+ ADD CONSTRAINT FK_CHUSAN_NET_BATTLE_LOG_ON_USER FOREIGN KEY (user_id) REFERENCES chusan_user_data (id);
diff --git a/src/main/resources/db/migration/mariadb/V1000_28__chusan_drops_database.sql b/src/main/resources/db/migration/mariadb/V1000_28__chusan_drops_database.sql
new file mode 100644
index 00000000..8764d312
--- /dev/null
+++ b/src/main/resources/db/migration/mariadb/V1000_28__chusan_drops_database.sql
@@ -0,0 +1,9 @@
+DROP TABLE chusan_avatar;
+DROP TABLE chusan_frame;
+DROP TABLE chusan_mapicon;
+DROP TABLE chusan_nameplate;
+DROP TABLE chusan_voice;
+DROP TABLE chusan_trophy;
+DROP TABLE chusan_music;
+DROP TABLE chusan_music_level;
+DROP TABLE chusan_game_character;
diff --git a/src/main/resources/db/migration/mariadb/V1000_29__chusan_favorite_music_fix.sql b/src/main/resources/db/migration/mariadb/V1000_29__chusan_favorite_music_fix.sql
new file mode 100644
index 00000000..f45951fe
--- /dev/null
+++ b/src/main/resources/db/migration/mariadb/V1000_29__chusan_favorite_music_fix.sql
@@ -0,0 +1,3 @@
+DELETE FROM chusan_user_general_data WHERE property_key = 'favorite_music' AND property_value = '-1';
+DELETE FROM chusan_user_general_data WHERE property_key = 'favorite_music' AND property_value = '0';
+DELETE FROM chusan_user_general_data WHERE property_key = 'favorite_music' AND property_value = '';
diff --git a/src/main/resources/db/migration/mariadb/V1000_30__chusan_user_misc.sql b/src/main/resources/db/migration/mariadb/V1000_30__chusan_user_misc.sql
new file mode 100644
index 00000000..d75433f2
--- /dev/null
+++ b/src/main/resources/db/migration/mariadb/V1000_30__chusan_user_misc.sql
@@ -0,0 +1,17 @@
+CREATE TABLE chusan_user_misc
+(
+ id BIGINT AUTO_INCREMENT NOT NULL,
+ user_id BIGINT NULL,
+ recent_nb_select VARCHAR(1023) NULL,
+ recent_nb_music VARCHAR(1023) NULL,
+ fav_music VARCHAR(1023) NULL,
+ CONSTRAINT pk_chusanusermisc PRIMARY KEY (id)
+);
+
+ALTER TABLE chusan_user_misc
+ ADD CONSTRAINT FK_CHUSANUSERMISC_ON_USER FOREIGN KEY (user_id) REFERENCES chusan_user_data (id);
+
+ALTER TABLE chusan_user_misc
+ ADD CONSTRAINT UNQ_CHUSANUSERMISC_ON_USER UNIQUE (user_id);
+
+DROP TABLE chusan_matching_member