diff --git a/core/data/alembic/versions/16f34bf7b968_mai2_kaleidx_scope_support.py b/core/data/alembic/versions/5d7b38996e67_mai2_prism_support.py similarity index 61% rename from core/data/alembic/versions/16f34bf7b968_mai2_kaleidx_scope_support.py rename to core/data/alembic/versions/5d7b38996e67_mai2_prism_support.py index b8baa1a..64416ae 100644 --- a/core/data/alembic/versions/16f34bf7b968_mai2_kaleidx_scope_support.py +++ b/core/data/alembic/versions/5d7b38996e67_mai2_prism_support.py @@ -1,8 +1,8 @@ -"""Mai2 Kaleidx Scope Support +"""Mai2 PRiSM support -Revision ID: 16f34bf7b968 -Revises: d0f1c7fa9505 -Create Date: 2025-04-02 07:06:15.829591 +Revision ID: 5d7b38996e67 +Revises: 1d0014d35220 +Create Date: 2025-04-04 06:28:24.898912 """ from alembic import op @@ -10,15 +10,25 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '16f34bf7b968' -down_revision = 'd0f1c7fa9505' +revision = '5d7b38996e67' +down_revision = '1d0014d35220' branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('mai2_score_kaleidx_scope', + op.create_table('mai2_static_kaleidxscope_condition', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('conditionId', sa.Integer(), nullable=True), + sa.Column('conditionName', sa.String(length=255), nullable=True), + sa.Column('songId', sa.Integer(), nullable=True), + sa.Column('songName', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('conditionId', 'conditionName', 'songId', 'songName', name='mai2_static_kaleidxscope_uk'), + mysql_charset='utf8mb4' + ) + op.create_table('mai2_score_kaleidxscope', sa.Column('id', sa.Integer(), nullable=False), sa.Column('user', sa.Integer(), nullable=False), sa.Column('gateId', sa.Integer(), nullable=True), @@ -41,10 +51,13 @@ def upgrade(): sa.UniqueConstraint('user', 'gateId', name='mai2_score_best_uk'), mysql_charset='utf8mb4' ) + op.add_column('mai2_playlog', sa.Column('extBool2', sa.Boolean(), nullable=True, server_default=sa.text("NULL"))) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('mai2_score_kaleidx_scope') + op.drop_column('mai2_playlog', 'extBool2') + op.drop_table('mai2_score_kaleidxscope') + op.drop_table('mai2_static_kaleidxscope_condition') # ### end Alembic commands ### diff --git a/titles/mai2/prism.py b/titles/mai2/prism.py index 5db7c8a..409132c 100644 --- a/titles/mai2/prism.py +++ b/titles/mai2/prism.py @@ -49,6 +49,22 @@ class Mai2Prism(Mai2BuddiesPlus): } async def handle_get_user_kaleidx_scope_api_request(self, data: Dict) -> Dict: + # kaleidxscope keyget condition judgement + # player may get key before GateFound + for gate in range(1,7): + condition_list = await self.data.static.get_kaleidxscope_condition(gate) + if not condition_list: + continue + condition_satisfy = 0 + for condition in condition_list: + score_list = await self.data.score.get_best_scores(user_id=data["userId"], song_id=condition[3]) + if score_list: + condition_satisfy = condition_satisfy + 1 + if len(condition_list) == condition_satisfy: + new_kaleidxscope = {'gateId': gate, "isKeyFound": True} + await self.data.score.put_user_kaleidxscope(data["userId"], new_kaleidxscope) + + kaleidxscope = await self.data.score.get_user_kaleidxscope_list(data["userId"]) if kaleidxscope is None: diff --git a/titles/mai2/read.py b/titles/mai2/read.py index d9450ac..7bbd33f 100644 --- a/titles/mai2/read.py +++ b/titles/mai2/read.py @@ -48,8 +48,12 @@ class Mai2Reader(BaseReader): self.logger.info(f"Read from {dir}") await self.get_events(f"{dir}/event") await self.disable_events(f"{dir}/information", f"{dir}/scoreRanking") - await self.read_music(f"{dir}/music") + #await self.read_music(f"{dir}/music") await self.read_tickets(f"{dir}/ticket") + + if self.version >= Mai2Constants.VER_MAIMAI_DX_PRISM: + for dir in data_dirs: + await self.read_kaleidxscope_condition(f"{dir}/kaleidxScopeKeyCondition") else: if not os.path.exists(f"{self.bin_dir}/tables"): @@ -341,3 +345,31 @@ class Mai2Reader(BaseReader): if scores is None or text is None: return # TODO + + + async def read_kaleidxscope_condition(self, base_dir: str) -> None : + self.logger.info(f"Reading KaleidxScope Key Conditions from {base_dir}...") + + for root, dirs, files in os.walk(base_dir): + for dir in dirs: + if os.path.exists(f"{root}/{dir}/KaleidxScopeKeyCondition.xml"): + with open(f"{root}/{dir}/KaleidxScopeKeyCondition.xml", encoding="utf-8") as f: + troot = ET.fromstring(f.read()) + + condition_id = int(troot.find("name").find("id").text) + condition_name = troot.find("name").find("str").text + + music_list = troot.find("musicIds").find("list") + for music in music_list.findall("StringID"): + music_id = int(music.find("id").text) + music_name = music.find("str").text + + await self.data.static.put_kaleidxscope_condition( + condition_id, + condition_name, + music_id, + music_name + ) + self.logger.info( + f"Add music {music_id} for condition {condition_id}" + ) \ No newline at end of file diff --git a/titles/mai2/schema/static.py b/titles/mai2/schema/static.py index ddba0f8..3fe6391 100644 --- a/titles/mai2/schema/static.py +++ b/titles/mai2/schema/static.py @@ -71,6 +71,17 @@ cards = Table( mysql_charset="utf8mb4", ) +kaleidxscope_condition = Table( + "mai2_static_kaleidxscope_condition", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("conditionId", Integer), + Column("conditionName", String(255)), + Column("songId", Integer), + Column("songName", String(255)), + UniqueConstraint("conditionId", "conditionName", "songId", "songName", name="mai2_static_kaleidxscope_uk"), + mysql_charset="utf8mb4", +) class Mai2StaticData(BaseData): async def put_game_event( @@ -264,3 +275,35 @@ class Mai2StaticData(BaseData): result = await self.execute(event.update(event.c.id == table_id).values(enabled=is_enable, startDate = start_date)) if not result: self.logger.error(f"Failed to update event {table_id} - {is_enable} {start_date}") + + # new in prism + async def put_kaleidxscope_condition( + self, + condition_id: int, + condition_name: str, + music_id: int, + music_name: str + ) -> Optional[int]: + sql = insert(kaleidxscope_condition).values( + conditionId = condition_id, + conditionName = condition_name, + songId = music_id, + songName = music_name, + ) + + + conflict = sql.on_duplicate_key_update(conditionName=condition_name, songName=music_name) + + result = await self.execute(conflict) + if result is None: + self.logger.warning( + f"put_kaleidxscope_condition: Failed to insert kaleidxScope Key Condition! conditionID {condition_id} songId {music_id}" + ) + return result.lastrowid + + async def get_kaleidxscope_condition(self, condition_id: int) -> None: + sql = kaleidxscope_condition.select(kaleidxscope_condition.c.conditionId == condition_id) + result = await self.execute(sql) + if result is None: + return None + return result.fetchall() \ No newline at end of file