from typing import Dict, List, Optional from sqlalchemy import Table, Column, UniqueConstraint from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, Float from sqlalchemy.schema import ForeignKey from sqlalchemy.sql import select from sqlalchemy.dialects.mysql import insert from core.data.schema import BaseData, metadata score_best = Table( "ongeki_score_best", metadata, Column("id", Integer, primary_key=True, nullable=False), Column( "user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False, ), Column("musicId", Integer, nullable=False), Column("level", Integer, nullable=False), Column("playCount", Integer, nullable=False), Column("techScoreMax", Integer, nullable=False), Column("techScoreRank", Integer, nullable=False), Column("battleScoreMax", Integer, nullable=False), Column("battleScoreRank", Integer, nullable=False), Column("maxComboCount", Integer, nullable=False), Column("maxOverKill", Float, nullable=False), Column("maxTeamOverKill", Float, nullable=False), Column("isFullBell", Boolean, nullable=False), Column("isFullCombo", Boolean, nullable=False), Column("isAllBreake", Boolean, nullable=False), 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", ) playlog = Table( "ongeki_score_playlog", metadata, Column("id", Integer, primary_key=True, nullable=False), Column( "user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False, ), Column("sortNumber", Integer), Column("placeId", Integer), Column("placeName", String(255)), Column("playDate", TIMESTAMP), Column("userPlayDate", TIMESTAMP), Column("musicId", Integer), Column("level", Integer), Column("playKind", Integer), Column("eventId", Integer), Column("eventName", String(255)), Column("eventPoint", Integer), Column("playedUserId1", Integer), Column("playedUserId2", Integer), Column("playedUserId3", Integer), Column("playedUserName1", String(8)), Column("playedUserName2", String(8)), Column("playedUserName3", String(8)), Column("playedMusicLevel1", Integer), Column("playedMusicLevel2", Integer), Column("playedMusicLevel3", Integer), Column("cardId1", Integer), Column("cardId2", Integer), Column("cardId3", Integer), Column("cardLevel1", Integer), Column("cardLevel2", Integer), Column("cardLevel3", Integer), Column("cardAttack1", Integer), Column("cardAttack2", Integer), Column("cardAttack3", Integer), Column("bossCharaId", Integer), Column("bossLevel", Integer), Column("bossAttribute", Integer), Column("clearStatus", Integer), Column("techScore", Integer), Column("techScoreRank", Integer), Column("battleScore", Integer), Column("battleScoreRank", Integer), Column("maxCombo", Integer), Column("judgeMiss", Integer), Column("judgeHit", Integer), Column("judgeBreak", Integer), Column("judgeCriticalBreak", Integer), Column("rateTap", Integer), Column("rateHold", Integer), Column("rateFlick", Integer), Column("rateSideTap", Integer), Column("rateSideHold", Integer), Column("bellCount", Integer), Column("totalBellCount", Integer), Column("damageCount", Integer), Column("overDamage", Integer), Column("isTechNewRecord", Boolean), Column("isBattleNewRecord", Boolean), Column("isOverDamageNewRecord", Boolean), Column("isFullCombo", Boolean), Column("isFullBell", Boolean), Column("isAllBreak", Boolean), Column("playerRating", Integer), Column("battlePoint", Integer), Column("platinumScore", Integer), Column("platinumScoreMax", Integer), mysql_charset="utf8mb4", ) tech_count = Table( "ongeki_score_tech_count", metadata, Column("id", Integer, primary_key=True, nullable=False), Column( "user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False, ), Column("levelId", Integer, nullable=False), Column("allBreakCount", Integer), Column("allBreakPlusCount", Integer), UniqueConstraint("user", "levelId", name="ongeki_tech_count_uk"), mysql_charset="utf8mb4", ) class OngekiScoreData(BaseData): async def get_tech_count(self, aime_id: int) -> Optional[List[Dict]]: sql = select(tech_count).where(tech_count.c.user == aime_id) result = self.execute(sql) if result is None: return None return result.fetchall() async def put_tech_count(self, aime_id: int, tech_count_data: Dict) -> Optional[int]: tech_count_data["user"] = aime_id sql = insert(tech_count).values(**tech_count_data) conflict = sql.on_duplicate_key_update(**tech_count_data) result = await self.execute(conflict) if result is None: self.logger.warning(f"put_tech_count: Failed to update! aime_id: {aime_id}") return None return result.lastrowid async def get_best_scores(self, aime_id: int) -> Optional[List[Dict]]: sql = select(score_best).where(score_best.c.user == aime_id) result = await self.execute(sql) if result is None: return None return result.fetchall() async def get_best_score( self, aime_id: int, song_id: int, chart_id: int = None ) -> Optional[List[Dict]]: return [] async def put_best_score(self, aime_id: int, music_detail: Dict) -> Optional[int]: music_detail["user"] = aime_id sql = insert(score_best).values(**music_detail) conflict = sql.on_duplicate_key_update(**music_detail) result = await self.execute(conflict) if result is None: self.logger.warning(f"put_best_score: Failed to add score! aime_id: {aime_id}") return None return result.lastrowid async def put_playlog(self, aime_id: int, playlog_data: Dict) -> Optional[int]: playlog_data["user"] = aime_id sql = insert(playlog).values(**playlog_data) result = await self.execute(sql) if result is None: self.logger.warning(f"put_playlog: Failed to add playlog! aime_id: {aime_id}") return None return result.lastrowid