From 3791b2b2383c9a13aa896b6cc821522d9f0a0ee4 Mon Sep 17 00:00:00 2001 From: Midorica Date: Fri, 3 Mar 2023 00:00:22 -0500 Subject: [PATCH] Adding Ongeki Bright Memory support --- core/data/schema/versions/SDDT_2_rollback.sql | 7 +++ core/data/schema/versions/SDDT_3_upgrade.sql | 27 +++++++++ readme.md | 2 +- titles/ongeki/base.py | 4 ++ titles/ongeki/brightmemory.py | 58 +++++++++++++++++++ titles/ongeki/const.py | 3 +- titles/ongeki/index.py | 6 +- titles/ongeki/schema/item.py | 40 +++++++++++++ titles/ongeki/schema/profile.py | 1 + titles/ongeki/schema/score.py | 3 + 10 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 core/data/schema/versions/SDDT_2_rollback.sql create mode 100644 core/data/schema/versions/SDDT_3_upgrade.sql create mode 100644 titles/ongeki/brightmemory.py diff --git a/core/data/schema/versions/SDDT_2_rollback.sql b/core/data/schema/versions/SDDT_2_rollback.sql new file mode 100644 index 0000000..5ddf1b6 --- /dev/null +++ b/core/data/schema/versions/SDDT_2_rollback.sql @@ -0,0 +1,7 @@ +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE ongeki_profile_data DROP COLUMN isDialogWatchedSuggestMemory; +ALTER TABLE ongeki_score_best DROP COLUMN platinumScoreMax; +ALTER TABLE ongeki_score_playlog DROP COLUMN platinumScore; +ALTER TABLE ongeki_score_playlog DROP COLUMN platinumScoreMax; +DROP TABLE IF EXISTS `ongeki_user_memorychapter`; +SET FOREIGN_KEY_CHECKS=1; diff --git a/core/data/schema/versions/SDDT_3_upgrade.sql b/core/data/schema/versions/SDDT_3_upgrade.sql new file mode 100644 index 0000000..26c5c30 --- /dev/null +++ b/core/data/schema/versions/SDDT_3_upgrade.sql @@ -0,0 +1,27 @@ +SET FOREIGN_KEY_CHECKS=0; + +ALTER TABLE ongeki_profile_data ADD COLUMN isDialogWatchedSuggestMemory BOOLEAN; +ALTER TABLE ongeki_score_best ADD COLUMN platinumScoreMax INTEGER; +ALTER TABLE ongeki_score_playlog ADD COLUMN platinumScore INTEGER; +ALTER TABLE ongeki_score_playlog ADD COLUMN platinumScoreMax INTEGER; + +CREATE TABLE ongeki_user_memorychapter ( + id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, + user INT NOT NULL, + chapterId INT NOT NULL, + gaugeId INT NOT NULL, + gaugeNum INT NOT NULL, + jewelCount INT NOT NULL, + isStoryWatched BOOLEAN NOT NULL, + isBossWatched BOOLEAN NOT NULL, + isDialogWatched BOOLEAN NOT NULL, + isEndingWatched BOOLEAN NOT NULL, + isClear BOOLEAN NOT NULL, + lastPlayMusicId INT NOT NULL, + lastPlayMusicLevel INT NOT NULL, + lastPlayMusicCategory INT NOT NULL, + UNIQUE KEY ongeki_user_memorychapter_uk (user, chapterId), + CONSTRAINT ongeki_user_memorychapter_ibfk_1 FOREIGN KEY (user) REFERENCES aime_user (id) ON DELETE CASCADE ON UPDATE CASCADE +); + +SET FOREIGN_KEY_CHECKS=1; diff --git a/readme.md b/readme.md index 1e05d5a..24440fc 100644 --- a/readme.md +++ b/readme.md @@ -16,7 +16,7 @@ Games listed below have been tested and confirmed working. Only game versions ol + All versions + Ongeki - + All versions up to Bright + + All versions up to Bright Memory + Wacca + Lily R diff --git a/titles/ongeki/base.py b/titles/ongeki/base.py index 8778645..3f6dc7a 100644 --- a/titles/ongeki/base.py +++ b/titles/ongeki/base.py @@ -787,6 +787,10 @@ class OngekiBase(): if "userChapterList" in upsert: for x in upsert["userChapterList"]: self.data.item.put_chapter(user_id, x) + + if "userMemoryChapterList" in upsert: + for x in upsert["userMemoryChapterList"]: + self.data.item.put_memorychapter(user_id, x) if "userItemList" in upsert: for x in upsert["userItemList"]: diff --git a/titles/ongeki/brightmemory.py b/titles/ongeki/brightmemory.py new file mode 100644 index 0000000..a99f806 --- /dev/null +++ b/titles/ongeki/brightmemory.py @@ -0,0 +1,58 @@ +from datetime import date, datetime, timedelta +from typing import Any, Dict +import pytz +import json + +from core.config import CoreConfig +from titles.ongeki.base import OngekiBase +from titles.ongeki.const import OngekiConstants +from titles.ongeki.config import OngekiConfig + +class OngekiBrightMemory(OngekiBase): + + def __init__(self, core_cfg: CoreConfig, game_cfg: OngekiConfig) -> None: + super().__init__(core_cfg, game_cfg) + self.version = OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY + + def handle_get_game_setting_api_request(self, data: Dict) -> Dict: + ret = super().handle_get_game_setting_api_request(data) + ret["gameSetting"]["dataVersion"] = "1.35.00" + ret["gameSetting"]["onlineDataVersion"] = "1.35.00" + ret["gameSetting"]["maxCountCharacter"] = 50 + ret["gameSetting"]["maxCountCard"] = 300 + ret["gameSetting"]["maxCountItem"] = 300 + ret["gameSetting"]["maxCountMusic"] = 50 + ret["gameSetting"]["maxCountMusicItem"] = 300 + ret["gameSetting"]["maxCountRivalMusic"] = 300 + return ret + + def handle_get_user_memory_chapter_api_request(self, data: Dict) -> Dict: + memories = self.data.item.get_memorychapters(data["userId"]) + if not memories: + return {"userId": data["userId"], "length":6, "userMemoryChapterList":[ + {"gaugeId":0, "isClear": False, "gaugeNum": 0, "chapterId": 70001, "jewelCount": 0, "isBossWatched": False, "isStoryWatched": False, "isDialogWatched": False, "isEndingWatched": False, "lastPlayMusicId": 0, "lastPlayMusicLevel": 0, "lastPlayMusicCategory": 0}, + {"gaugeId":0, "isClear": False, "gaugeNum": 0, "chapterId": 70002, "jewelCount": 0, "isBossWatched": False, "isStoryWatched": False, "isDialogWatched": False, "isEndingWatched": False, "lastPlayMusicId": 0, "lastPlayMusicLevel": 0, "lastPlayMusicCategory": 0}, + {"gaugeId":0, "isClear": False, "gaugeNum": 0, "chapterId": 70003, "jewelCount": 0, "isBossWatched": False, "isStoryWatched": False, "isDialogWatched": False, "isEndingWatched": False, "lastPlayMusicId": 0, "lastPlayMusicLevel": 0, "lastPlayMusicCategory": 0}, + {"gaugeId":0, "isClear": False, "gaugeNum": 0, "chapterId": 70004, "jewelCount": 0, "isBossWatched": False, "isStoryWatched": False, "isDialogWatched": False, "isEndingWatched": False, "lastPlayMusicId": 0, "lastPlayMusicLevel": 0, "lastPlayMusicCategory": 0}, + {"gaugeId":0, "isClear": False, "gaugeNum": 0, "chapterId": 70005, "jewelCount": 0, "isBossWatched": False, "isStoryWatched": False, "isDialogWatched": False, "isEndingWatched": False, "lastPlayMusicId": 0, "lastPlayMusicLevel": 0, "lastPlayMusicCategory": 0}, + {"gaugeId":0, "isClear": False, "gaugeNum": 0, "chapterId": 70099, "jewelCount": 0, "isBossWatched": False, "isStoryWatched": False, "isDialogWatched": False, "isEndingWatched": False, "lastPlayMusicId": 0, "lastPlayMusicLevel": 0, "lastPlayMusicCategory": 0} + ]} + + memory_chp = [] + for chp in memories: + tmp = chp._asdict() + tmp.pop("id") + tmp.pop("user") + memory_chp.append(tmp) + + return { + "userId": data["userId"], + "length": len(memory_chp), + "userMemoryChapterList": memory_chp + } + + def handle_get_game_music_release_state_api_request(self, data: Dict) -> Dict: + return { + "techScore": 0, + "cardNum": 0 + } \ No newline at end of file diff --git a/titles/ongeki/const.py b/titles/ongeki/const.py index da9614e..dd6c0f5 100644 --- a/titles/ongeki/const.py +++ b/titles/ongeki/const.py @@ -10,6 +10,7 @@ class OngekiConstants(): VER_ONGEKI_RED = 4 VER_ONGEKI_RED_PLUS = 5 VER_ONGEKI_BRIGHT = 6 + VER_ONGEKI_BRIGHT_MEMORY = 7 EVT_TYPES: Enum = Enum('EVT_TYPES', [ 'None', @@ -43,7 +44,7 @@ class OngekiConstants(): Lunatic = 10 VERSION_NAMES = ("ONGEKI", "ONGEKI+", "ONGEKI Summer", "ONGEKI Summer+", "ONGEKI Red", "ONGEKI Red+", - "ONGEKI Bright") + "ONGEKI Bright", "ONGEKI Bright Memory") @classmethod def game_ver_to_string(cls, ver: int): diff --git a/titles/ongeki/index.py b/titles/ongeki/index.py index d3b107e..c636659 100644 --- a/titles/ongeki/index.py +++ b/titles/ongeki/index.py @@ -17,6 +17,7 @@ from titles.ongeki.summerplus import OngekiSummerPlus from titles.ongeki.red import OngekiRed from titles.ongeki.redplus import OngekiRedPlus from titles.ongeki.bright import OngekiBright +from titles.ongeki.brightmemory import OngekiBrightMemory class OngekiServlet(): def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None: @@ -32,6 +33,7 @@ class OngekiServlet(): OngekiRed(core_cfg, self.game_cfg), OngekiRedPlus(core_cfg, self.game_cfg), OngekiBright(core_cfg, self.game_cfg), + OngekiBrightMemory(core_cfg, self.game_cfg), ] self.logger = logging.getLogger("ongeki") @@ -69,8 +71,10 @@ class OngekiServlet(): internal_ver = OngekiConstants.VER_ONGEKI_RED elif version >= 125 and version < 130: # Red Plus internal_ver = OngekiConstants.VER_ONGEKI_RED_PLUS - elif version >= 130 and version < 135: # Red Plus + elif version >= 130 and version < 135: # Bright internal_ver = OngekiConstants.VER_ONGEKI_BRIGHT + elif version >= 135 and version < 140: # Bright Memory + internal_ver = OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY if all(c in string.hexdigits for c in endpoint) and len(endpoint) == 32: # If we get a 32 character long hex string, it's a hash and we're diff --git a/titles/ongeki/schema/item.py b/titles/ongeki/schema/item.py index cc09fda..c3f8c7e 100644 --- a/titles/ongeki/schema/item.py +++ b/titles/ongeki/schema/item.py @@ -107,6 +107,27 @@ chapter = Table( mysql_charset='utf8mb4' ) +memorychapter = Table( + "ongeki_user_memorychapter", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("chapterId", Integer), + Column("gaugeId", Integer), + Column("gaugeNum", Integer), + Column("jewelCount", Integer), + Column("isStoryWatched", Boolean), + Column("isBossWatched", Boolean), + Column("isDialogWatched", Boolean), + Column("isEndingWatched", Boolean), + Column("isClear", Boolean), + Column("lastPlayMusicId", Integer), + Column("lastPlayMusicLevel", Integer), + Column("lastPlayMusicCategory", Integer), + UniqueConstraint("user", "chapterId", name="ongeki_user_memorychapter_uk"), + mysql_charset='utf8mb4' +) + item = Table( "ongeki_user_item", metadata, @@ -522,5 +543,24 @@ class OngekiItemData(BaseData): sql = select(boss).where(boss.c.user == aime_id) result = self.execute(sql) + if result is None: return None + return result.fetchall() + + def put_memorychapter(self, aime_id: int, memorychapter_data: Dict) -> Optional[int]: + memorychapter_data["user"] = aime_id + + sql = insert(memorychapter).values(**memorychapter_data) + conflict = sql.on_duplicate_key_update(**memorychapter_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_memorychapter: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def get_memorychapters(self, aime_id: int) -> Optional[List[Dict]]: + sql = select(memorychapter).where(memorychapter.c.user == aime_id) + + result = self.execute(sql) if result is None: return None return result.fetchall() \ No newline at end of file diff --git a/titles/ongeki/schema/profile.py b/titles/ongeki/schema/profile.py index bdff67d..26c79b5 100644 --- a/titles/ongeki/schema/profile.py +++ b/titles/ongeki/schema/profile.py @@ -78,6 +78,7 @@ profile = Table( Column("overDamageBattlePoint", Integer, server_default="0"), Column("bestBattlePoint", Integer, server_default="0"), Column("lastEmoneyBrand", Integer, server_default="0"), + Column("isDialogWatchedSuggestMemory", Boolean), UniqueConstraint("user", "version", name="ongeki_profile_profile_uk"), mysql_charset='utf8mb4' ) diff --git a/titles/ongeki/schema/score.py b/titles/ongeki/schema/score.py index 08a6a86..e526005 100644 --- a/titles/ongeki/schema/score.py +++ b/titles/ongeki/schema/score.py @@ -28,6 +28,7 @@ score_best = Table( Column("isLock", Boolean, nullable=False), Column("clearStatus", Boolean, nullable=False), Column("isStoryWatched", Boolean, nullable=False), + Column("platinumScoreMax", Integer), UniqueConstraint("user", "musicId", "level", name="ongeki_best_score_uk"), mysql_charset='utf8mb4' ) @@ -96,6 +97,8 @@ playlog = Table( Column("isAllBreak", Boolean), Column("playerRating", Integer), Column("battlePoint", Integer), + Column("platinumScore", Integer), + Column("platinumScoreMax", Integer), mysql_charset='utf8mb4' )