From 3d95a84739c73e3bed3121fbda4f985e61c2a39f Mon Sep 17 00:00:00 2001 From: alexay7 <43906716+alexay7@users.noreply.github.com> Date: Thu, 21 Aug 2025 22:19:25 +0200 Subject: [PATCH] feat: Add prefecture modification support (#170) --- .../settings/GeneralGameSettings.svelte | 27 ++++----- .../components/settings/RegionSelector.svelte | 59 +++++++++++++++++++ AquaNet/src/libs/generalTypes.ts | 1 + AquaNet/src/libs/i18n/en_ref.ts | 6 +- AquaNet/src/libs/i18n/zh.ts | 8 +++ AquaNet/src/libs/sdk.ts | 2 + .../icu/samnyan/aqua/net/UserRegistrar.kt | 19 +++++- .../icu/samnyan/aqua/net/db/AquaNetUser.kt | 4 ++ .../icu/samnyan/aqua/sega/allnet/AllNet.kt | 6 ++ .../aqua/sega/chusan/handler/ChusanApis.kt | 6 ++ .../sega/chusan/handler/ChusanUpsertApis.kt | 19 ++++++ .../aqua/sega/chusan/model/Chu3Repos.kt | 5 ++ .../sega/chusan/model/userdata/UserRegions.kt | 14 +++++ .../samnyan/aqua/sega/maimai2/Maimai2Apis.kt | 34 ++++++++++- .../samnyan/aqua/sega/maimai2/model/Repos.kt | 7 ++- .../maimai2/model/userdata/UserEntities.kt | 18 +++++- .../samnyan/aqua/sega/ongeki/OngekiApis.kt | 6 ++ .../samnyan/aqua/sega/ongeki/OngekiRepos.kt | 5 ++ .../aqua/sega/ongeki/OngekiUpsertAllApi.kt | 22 +++++++ .../sega/ongeki/model/OngekiUserEntities.kt | 12 ++++ .../resources/db/80/V1000_56__prefectures.sql | 38 ++++++++++++ 21 files changed, 294 insertions(+), 24 deletions(-) create mode 100644 AquaNet/src/components/settings/RegionSelector.svelte create mode 100644 src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserRegions.kt create mode 100644 src/main/resources/db/80/V1000_56__prefectures.sql diff --git a/AquaNet/src/components/settings/GeneralGameSettings.svelte b/AquaNet/src/components/settings/GeneralGameSettings.svelte index 07146fd1..d400792e 100644 --- a/AquaNet/src/components/settings/GeneralGameSettings.svelte +++ b/AquaNet/src/components/settings/GeneralGameSettings.svelte @@ -4,6 +4,7 @@ import GameSettingFields from "./GameSettingFields.svelte"; import { t, ts } from "../../libs/i18n"; import useLocalStorage from "../../libs/hooks/useLocalStorage.svelte"; + import RegionSelector from "./RegionSelector.svelte"; const rounding = useLocalStorage("rounding", true); @@ -22,6 +23,11 @@ +
+
+ {ts("settings.regionNotice")} +
+ diff --git a/AquaNet/src/components/settings/RegionSelector.svelte b/AquaNet/src/components/settings/RegionSelector.svelte new file mode 100644 index 00000000..e2f74711 --- /dev/null +++ b/AquaNet/src/components/settings/RegionSelector.svelte @@ -0,0 +1,59 @@ + + +
+ + +
+ + + + diff --git a/AquaNet/src/libs/generalTypes.ts b/AquaNet/src/libs/generalTypes.ts index 5dd4cd12..715722b0 100644 --- a/AquaNet/src/libs/generalTypes.ts +++ b/AquaNet/src/libs/generalTypes.ts @@ -19,6 +19,7 @@ export interface AquaNetUser { email: string displayName: string country: string + region:string lastLogin: number regTime: number profileLocation: string diff --git a/AquaNet/src/libs/i18n/en_ref.ts b/AquaNet/src/libs/i18n/en_ref.ts index 6213df51..eb9b9ab5 100644 --- a/AquaNet/src/libs/i18n/en_ref.ts +++ b/AquaNet/src/libs/i18n/en_ref.ts @@ -195,7 +195,11 @@ export const EN_REF_SETTINGS = { 'settings.export': 'Export Player Data', 'settings.batchManualExport': "Export in Batch Manual (for Tachi)", 'settings.cabNotice': "Note: These settings will only affect your own cab/setup. If you're playing on someone else's setup, please contact them to change these settings.", - 'settings.gameNotice': "These only apply to Mai and Wacca." + 'settings.gameNotice': "These only apply to Mai and Wacca.", + 'settings.regionNotice': "These only apply to Mai, Ongeki and Chuni.", + 'settings.regionSelector.title': "Prefecture Selector", + 'settings.regionSelector.desc': "Select the region where you want the game to think you are playing", + 'settings.regionSelector.select': "Select Prefecture", } export const EN_REF_USERBOX = { diff --git a/AquaNet/src/libs/i18n/zh.ts b/AquaNet/src/libs/i18n/zh.ts index de3c0236..a56eefda 100644 --- a/AquaNet/src/libs/i18n/zh.ts +++ b/AquaNet/src/libs/i18n/zh.ts @@ -208,6 +208,14 @@ const zhSettings: typeof EN_REF_SETTINGS = { 'settings.batchManualExport': "导出 Batch Manual 格式(用于 Tachi)", 'settings.cabNotice': '注意:下面这些设置只会影响你自己的机器,如果你是在其他人的机器上玩的话,请联系机主来改设置', 'settings.gameNotice': "这些设置仅对舞萌和华卡生效。", + // AI + 'settings.regionNotice': "这些设置仅适用于舞萌、音击和中二。", + // AI + 'settings.regionSelector.title': "地区选择器", + // AI + 'settings.regionSelector.desc': "选择游戏中显示的地区", + // AI + 'settings.regionSelector.select': "选择地区", } export const zhUserbox: typeof EN_REF_USERBOX = { diff --git a/AquaNet/src/libs/sdk.ts b/AquaNet/src/libs/sdk.ts index 38ae98e6..c6e36a72 100644 --- a/AquaNet/src/libs/sdk.ts +++ b/AquaNet/src/libs/sdk.ts @@ -196,6 +196,8 @@ export const USER = { }, isLoggedIn, ensureLoggedIn, + changeRegion: (regionId: number) => + post('/api/v2/user/change-region', { regionId }), } export const USERBOX = { diff --git a/src/main/java/icu/samnyan/aqua/net/UserRegistrar.kt b/src/main/java/icu/samnyan/aqua/net/UserRegistrar.kt index d2f39e78..bf9aed47 100644 --- a/src/main/java/icu/samnyan/aqua/net/UserRegistrar.kt +++ b/src/main/java/icu/samnyan/aqua/net/UserRegistrar.kt @@ -161,7 +161,7 @@ class UserRegistrar( // Check if user exists, treat as email / username val user = async { userRepo.findByEmailIgnoreCase(email) ?: userRepo.findByUsernameIgnoreCase(email) } ?: return SUCCESS // obviously dont tell them if the email exists or not - + // Check if email is verified if (!user.emailConfirmed && emailProps.enable) 400 - "Email not verified" @@ -179,7 +179,7 @@ class UserRegistrar( // Send a password reset email emailService.sendPasswordReset(user) - + return SUCCESS } @@ -189,7 +189,7 @@ class UserRegistrar( @RP token: Str, @RP password: Str, request: HttpServletRequest ) : Any { - + // Find the reset token val reset = async { resetPasswordRepo.findByToken(token) } @@ -302,4 +302,17 @@ class UserRegistrar( SUCCESS } + + @API("/change-region") + @Doc("Change the region of the user.", "Success message") + suspend fun changeRegion(@RP token: Str, @RP regionId: Str) = jwt.auth(token) { u -> + // Check if the region is valid (between 1 and 47) + val r = regionId.toIntOrNull() ?: (400 - "Invalid region") + if (r !in 1..47) 400 - "Invalid region" + async { + userRepo.save(u.apply { region = r.toString() }) + } + + SUCCESS + } } diff --git a/src/main/java/icu/samnyan/aqua/net/db/AquaNetUser.kt b/src/main/java/icu/samnyan/aqua/net/db/AquaNetUser.kt index 17b90ed6..8651f41a 100644 --- a/src/main/java/icu/samnyan/aqua/net/db/AquaNetUser.kt +++ b/src/main/java/icu/samnyan/aqua/net/db/AquaNetUser.kt @@ -43,6 +43,10 @@ class AquaNetUser( @Column(length = 3) var country: String = "", + // Region code at most 2 characters + @Column(length = 2) + var region: String = "", + // Last login time var lastLogin: Long = 0L, 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 00a88c86..c0c6a6b4 100644 --- a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNet.kt +++ b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNet.kt @@ -103,6 +103,7 @@ class AllNet( // encode UTF-8, format_ver 3, hops 1, token 2010451813 val reqMap = decodeAllNet(dataStream.readAllBytes()) val serial = reqMap["serial"] ?: "" + var region = props.map.mut["region0"] ?: "1" logger.info("AllNet /PowerOn : $reqMap") var session: String? = null @@ -114,6 +115,10 @@ class AllNet( if (u != null) { // Create a new session for the user logger.info("> Keychip authenticated: ${u.auId} ${u.computedName}") + // If the user defined its own region apply it + if (u.region.isNotBlank()) { + region = u.region + } session = keychipSessionService.new(u, reqMap["game_id"] ?: "").token } @@ -140,6 +145,7 @@ class AllNet( val resp = props.map.mut + mapOf( "uri" to switchUri(here, localPort, gameId, ver, session), "host" to props.host.ifBlank { here }, + "region0" to region ) // Different responses for different versions diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt index b8a55e4a..af9ef82d 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt @@ -288,6 +288,12 @@ fun ChusanController.chusanInit() { ) } + "GetUserRegion" { + db.userRegions.findByUser_Card_ExtId(uid) + .map { mapOf("regionId" to it.regionId, "playCount" to it.playCount) } + .let { mapOf("userId" to uid, "userRegionList" to it) } + } + // Game settings "GetGameSetting" { val version = data["version"].toString() 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 index ccbe9f45..fd07ac29 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt @@ -29,6 +29,25 @@ fun ChusanController.upsertApiInit() { userNameEx = "" }.also { db.userData.saveAndFlush(it) } + // Only save if it is a valid region and the user has played at least a song + if (req.userPlaylogList?.isNotEmpty() == true) { + val region = req.userPlaylogList!![0].regionId + + val userRegion = db.userRegions.findByUserIdAndRegionId(u.id, region) + if (userRegion.isPresent) { + userRegion.get().apply { + playCount += 1 + db.userRegions.save(this) + } + } else { + db.userRegions.save(UserRegions().apply { + user = u + regionId = region + playCount = 1 + }) + } + } + versionHelper[u.lastClientId] = u.lastDataVersion // Set users 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 936c316f..adf1a16c 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 @@ -174,6 +174,10 @@ interface Chu3GameLoginBonusRepo : JpaRepository { fun findByRequiredDays(version: Int, presetId: Int, requiredDays: Int): Optional } +interface Chu3UserRegionsRepo: Chu3UserLinked { + fun findByUserIdAndRegionId(userId: Long, regionId: Int): Optional +} + @Component class Chu3Repos( val userLoginBonus: Chu3UserLoginBonusRepo, @@ -191,6 +195,7 @@ class Chu3Repos( val userMap: Chu3UserMapRepo, val userMusicDetail: Chu3UserMusicDetailRepo, val userPlaylog: Chu3UserPlaylogRepo, + val userRegions: Chu3UserRegionsRepo, val userCMission: Chu3UserCMissionRepo, val userCMissionProgress: Chu3UserCMissionProgressRepo, val netBattleLog: Chu3NetBattleLogRepo, diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserRegions.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserRegions.kt new file mode 100644 index 00000000..84fdf608 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/model/userdata/UserRegions.kt @@ -0,0 +1,14 @@ +package icu.samnyan.aqua.sega.chusan.model.userdata + +import jakarta.persistence.Entity +import jakarta.persistence.Table +import jakarta.persistence.UniqueConstraint +import java.time.LocalDate + +@Entity(name = "ChusanUserRegions") +@Table(name = "chusan_user_regions", uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "region_id"])]) +class UserRegions : Chu3UserEntity() { + var regionId = 0 + var playCount = 0 + var created: String = LocalDate.now().toString() +} diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2Apis.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2Apis.kt index b5e4609b..014bda83 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2Apis.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/Maimai2Apis.kt @@ -7,6 +7,7 @@ import icu.samnyan.aqua.sega.general.model.CardStatus import icu.samnyan.aqua.sega.maimai2.model.UserRivalMusic import icu.samnyan.aqua.sega.maimai2.model.UserRivalMusicDetail import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserKaleidx +import icu.samnyan.aqua.sega.maimai2.model.userdata.UserRegions import java.time.LocalDate fun Maimai2ServletController.initApis() { @@ -134,6 +135,31 @@ fun Maimai2ServletController.initApis() { res["returnCode"] = 0 } + // Get regionId from request + val region = data["regionId"] as? Int + + // Only save if it is a valid region and the user has played at least a song + if (region!=null && region > 0 && d != null) { + val userRegion = db.userRegions.findByUserIdAndRegionId(uid, region) + if (userRegion.isPresent) { + userRegion.get().apply { + playCount += 1 + db.userRegions.save(this) + } + } else { + logger().info("user: $d") + logger().info("region: $region") + +// Create a new user region row + // Crea una nueva fila de región de usuario + db.userRegions.save(UserRegions().apply { + user = d + regionId = region + playCount = 1 + }) + } + } + res } @@ -178,13 +204,19 @@ fun Maimai2ServletController.initApis() { mapOf("userId" to uid, "rivalId" to rivalId, "nextIndex" to 0, "userRivalMusicList" to res.values) } + "GetUserRegion" { + logger().info("Getting user regions for user $uid") + db.userRegions.findByUser_Card_ExtId(uid) + .map { mapOf("regionId" to it.regionId, "playCount" to it.playCount) } + .let { mapOf("userId" to uid, "userRegionList" to it) } + } + "GetUserIntimate".unpaged { val u = db.userData.findByCardExtId(uid)() ?: (404 - "User not found") db.userIntimate.findByUser(u) } // Empty List Handlers - "GetUserRegion".unpaged { empty } "GetUserGhost".unpaged { empty } "GetUserFriendBonus" { mapOf("userId" to uid, "returnCode" to 0, "getMiles" to 0) } "GetTransferFriend" { mapOf("userId" to uid, "transferFriendList" to empty) } diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/Repos.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/Repos.kt index 3718971b..0263bdc9 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/Repos.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/Repos.kt @@ -127,6 +127,10 @@ interface Mai2GameEventRepo : JpaRepository { interface Mai2GameSellingCardRepo : JpaRepository +interface Mai2UserRegionsRepo: Mai2UserLinked { + fun findByUserIdAndRegionId(userId: Long, regionId: Int): Optional +} + @Component class Mai2Repos( val mapEncountNpc: Mai2MapEncountNpcRepo, @@ -152,5 +156,6 @@ class Mai2Repos( val userIntimate: MAi2UserIntimateRepo, val gameCharge: Mai2GameChargeRepo, val gameEvent: Mai2GameEventRepo, - val gameSellingCard: Mai2GameSellingCardRepo + val gameSellingCard: Mai2GameSellingCardRepo, + val userRegions: Mai2UserRegionsRepo, ) diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserEntities.kt b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserEntities.kt index 211a1011..47548f88 100644 --- a/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserEntities.kt +++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/model/userdata/UserEntities.kt @@ -21,6 +21,7 @@ import java.time.format.DateTimeFormatter import com.fasterxml.jackson.databind.JsonSerializer import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.core.JsonGenerator +import java.time.LocalDate @MappedSuperclass open class Mai2UserEntity : BaseEntity(), IUserEntity { @@ -451,9 +452,9 @@ class Mai2UserPlaylog : Mai2UserEntity(), IGenericGamePlaylog { get() = maxCombo == totalCombo override val isAllPerfect: Boolean - get() = tapMiss + tapGood + tapGreat == 0 && - holdMiss + holdGood + holdGreat == 0 && - slideMiss + slideGood + slideGreat == 0 && + get() = tapMiss + tapGood + tapGreat == 0 && + holdMiss + holdGood + holdGreat == 0 && + slideMiss + slideGood + slideGreat == 0 && touchMiss + touchGood + touchGreat == 0 && breakMiss + breakGood + breakGreat == 0 } @@ -551,6 +552,17 @@ class Mai2UserIntimate : Mai2UserEntity() { var intimateCountRewarded = 0; } +@Entity(name = "Maimai2UserRegions") +@Table( + name = "maimai2_user_regions", + uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "region_id"])] +) +class UserRegions : Mai2UserEntity() { + var regionId = 0 + var playCount = 0 + var created: String = LocalDate.now().toString() +} + val MAIMAI_DATETIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.0") class MaimaiDateSerializer : JsonSerializer() { override fun serialize(v: LocalDateTime, j: JsonGenerator, s: SerializerProvider) { diff --git a/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiApis.kt b/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiApis.kt index 41bf4a8d..947c9083 100644 --- a/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiApis.kt +++ b/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiApis.kt @@ -69,4 +69,10 @@ fun OngekiController.ongekiInit() { "GetClientTestmode" { empty.staticLst("clientTestmodeList") + mapOf("placeId" to data["placeId"]) } + + "GetUserRegion" { + db.regions.findByUser_Card_ExtId(uid) + .map { mapOf("regionId" to it.regionId, "playCount" to it.playCount) } + .staticLst("userRegionList") + mapOf("userId" to uid) + } } \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiRepos.kt b/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiRepos.kt index 28a41842..a9af626a 100644 --- a/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiRepos.kt +++ b/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiRepos.kt @@ -147,6 +147,10 @@ interface OgkUserTrainingRoomRepo : OngekiUserLinked { fun findByUserAndRoomId(user: UserData, roomId: Int): Optional } +interface OgkUserRegionsRepo: OngekiUserLinked { + fun findByUserIdAndRegionId(userId: Long, regionId: Int): Optional +} + // Re:Fresh interface OgkUserEventMapRepo : OngekiUserLinked interface OgkUserSkinRepo : OngekiUserLinked @@ -190,6 +194,7 @@ class OngekiUserRepos( val trainingRoom: OgkUserTrainingRoomRepo, val eventMap: OgkUserEventMapRepo, val skin: OgkUserSkinRepo, + val regions: OgkUserRegionsRepo, ) @Component diff --git a/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiUpsertAllApi.kt b/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiUpsertAllApi.kt index ed38ad93..ed25e9e1 100644 --- a/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiUpsertAllApi.kt +++ b/src/main/java/icu/samnyan/aqua/sega/ongeki/OngekiUpsertAllApi.kt @@ -1,11 +1,13 @@ package icu.samnyan.aqua.sega.ongeki +import ext.int import ext.invoke import ext.mapApply import ext.minus import icu.samnyan.aqua.sega.ongeki.model.OngekiUpsertUserAll import icu.samnyan.aqua.sega.ongeki.model.UserData import icu.samnyan.aqua.sega.ongeki.model.UserGeneralData +import icu.samnyan.aqua.sega.ongeki.model.UserRegions fun OngekiController.initUpsertAll() { @@ -33,6 +35,26 @@ fun OngekiController.initUpsertAll() { db.data.save(this) } ?: oldUser ?: return@api null + // User region + val region = data["regionId"]?.int ?: 0 + + // Only save if it is a valid region and the user has played at least a song + if (region > 0 && all.userPlaylogList?.isNotEmpty() == true) { + val userRegion = db.regions.findByUserIdAndRegionId(u.id, region) + if (userRegion.isPresent) { + userRegion.get().apply { + playCount += 1 + db.regions.save(this) + } + } else { + db.regions.save(UserRegions().apply { + user = u + regionId = region + playCount = 1 + }) + } + } + all.run { // Set users listOfNotNull( diff --git a/src/main/java/icu/samnyan/aqua/sega/ongeki/model/OngekiUserEntities.kt b/src/main/java/icu/samnyan/aqua/sega/ongeki/model/OngekiUserEntities.kt index 59fadaef..5b4f8752 100644 --- a/src/main/java/icu/samnyan/aqua/sega/ongeki/model/OngekiUserEntities.kt +++ b/src/main/java/icu/samnyan/aqua/sega/ongeki/model/OngekiUserEntities.kt @@ -7,6 +7,7 @@ import icu.samnyan.aqua.net.games.* import icu.samnyan.aqua.sega.general.model.Card import icu.samnyan.aqua.sega.util.jackson.AccessCodeSerializer import jakarta.persistence.* +import java.time.LocalDate @MappedSuperclass class OngekiUserEntity : BaseEntity(), IUserEntity { @@ -511,4 +512,15 @@ class UserSkin : OngekiUserEntity() { var cardId1 = 0 var cardId2 = 0 var cardId3 = 0 +} + +@Entity(name = "OngekiUserRegions") +@Table( + name = "ongeki_user_regions", + uniqueConstraints = [UniqueConstraint(columnNames = ["user_id", "regionId"])] +) +class UserRegions : OngekiUserEntity() { + var regionId = 0 + var playCount = 0 + var created: String = LocalDate.now().toString() } \ No newline at end of file diff --git a/src/main/resources/db/80/V1000_56__prefectures.sql b/src/main/resources/db/80/V1000_56__prefectures.sql new file mode 100644 index 00000000..c3e0b9e8 --- /dev/null +++ b/src/main/resources/db/80/V1000_56__prefectures.sql @@ -0,0 +1,38 @@ +CREATE TABLE chusan_user_regions +( + id BIGINT AUTO_INCREMENT NOT NULL, + user_id BIGINT NULL, + region_id INT NOT NULL, + play_count INT NOT NULL DEFAULT 1, + created VARCHAR(355), + PRIMARY KEY (id), + CONSTRAINT fk_chusanregions_on_chusan_user_Data FOREIGN KEY (user_id) REFERENCES chusan_user_data (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT unq_chusanregions_on_region_user UNIQUE (user_id, region_id) +); + +CREATE TABLE ongeki_user_regions +( + id BIGINT AUTO_INCREMENT NOT NULL, + user_id BIGINT NULL, + region_id INT NOT NULL, + play_count INT NOT NULL DEFAULT 1, + created VARCHAR(355), + PRIMARY KEY (id), + CONSTRAINT fk_ongekiregions_on_aqua_net_user FOREIGN KEY (user_id) REFERENCES aqua_net_user (au_id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT unq_ongekiregions_on_region_user UNIQUE (user_id, region_id) +); + +CREATE TABLE maimai2_user_regions +( + id BIGINT AUTO_INCREMENT NOT NULL, + user_id BIGINT NULL, + region_id INT NOT NULL, + play_count INT NOT NULL DEFAULT 1, + created VARCHAR(355), + PRIMARY KEY (id), + CONSTRAINT fk_maimai2regions_on_user_Details FOREIGN KEY (user_id) REFERENCES maimai2_user_detail (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT unq_maimai2regions_on_region_user UNIQUE (user_id, region_id) +); + +ALTER TABLE aqua_net_user +ADD COLUMN region VARCHAR(2) NOT NULL DEFAULT '1'; \ No newline at end of file