diff --git a/core/data/schema/versions/SDEZ_6_rollback.sql b/core/data/schema/versions/SDEZ_6_rollback.sql new file mode 100644 index 0000000..0ca7036 --- /dev/null +++ b/core/data/schema/versions/SDEZ_6_rollback.sql @@ -0,0 +1 @@ +DROP TABLE aime.mai2_profile_consec_logins; diff --git a/core/data/schema/versions/SDEZ_7_upgrade.sql b/core/data/schema/versions/SDEZ_7_upgrade.sql new file mode 100644 index 0000000..20f3c70 --- /dev/null +++ b/core/data/schema/versions/SDEZ_7_upgrade.sql @@ -0,0 +1,9 @@ +CREATE TABLE `mai2_profile_consec_logins` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user` int(11) NOT NULL, + `version` int(11) NOT NULL, + `logins` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `mai2_profile_consec_logins_uk` (`user`,`version`), + CONSTRAINT `mai2_profile_consec_logins_ibfk_1` FOREIGN KEY (`user`) REFERENCES `aime_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; \ No newline at end of file diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index f4fec94..0b522aa 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -129,30 +129,31 @@ Config file is located in `config/cxb.yaml`. | Game Code | Version ID | Version Name | |-----------|------------|-------------------------| -| SDEZ | 0 | maimai DX | -| SDEZ | 1 | maimai DX PLUS | -| SDEZ | 2 | maimai DX Splash | -| SDEZ | 3 | maimai DX Splash PLUS | -| SDEZ | 4 | maimai DX Universe | -| SDEZ | 5 | maimai DX Universe PLUS | -| SDEZ | 6 | maimai DX Festival | + For versions pre-dx -| Game Code | Version ID | Version Name | -|-----------|------------|----------------------| -| SBXL | 1000 | maimai | -| SBXL | 1001 | maimai PLUS | -| SBZF | 1002 | maimai GreeN | -| SBZF | 1003 | maimai GreeN PLUS | -| SDBM | 1004 | maimai ORANGE | -| SDBM | 1005 | maimai ORANGE PLUS | -| SDCQ | 1006 | maimai PiNK | -| SDCQ | 1007 | maimai PiNK PLUS | -| SDDK | 1008 | maimai MURASAKI | -| SDDK | 1009 | maimai MURASAKI PLUS | -| SDDZ | 1010 | maimai MILK | -| SDDZ | 1011 | maimai MILK PLUS | -| SDEY | 1012 | maimai FiNALE | +| Game Code | Version ID | Version Name | +|-----------|------------|-------------------------| +| SBXL | 0 | maimai | +| SBXL | 1 | maimai PLUS | +| SBZF | 2 | maimai GreeN | +| SBZF | 3 | maimai GreeN PLUS | +| SDBM | 4 | maimai ORANGE | +| SDBM | 5 | maimai ORANGE PLUS | +| SDCQ | 6 | maimai PiNK | +| SDCQ | 7 | maimai PiNK PLUS | +| SDDK | 8 | maimai MURASAKI | +| SDDK | 9 | maimai MURASAKI PLUS | +| SDDZ | 10 | maimai MILK | +| SDDZ | 11 | maimai MILK PLUS | +| SDEY | 12 | maimai FiNALE | +| SDEZ | 13 | maimai DX | +| SDEZ | 14 | maimai DX PLUS | +| SDEZ | 15 | maimai DX Splash | +| SDEZ | 16 | maimai DX Splash PLUS | +| SDEZ | 17 | maimai DX Universe | +| SDEZ | 18 | maimai DX Universe PLUS | +| SDEZ | 19 | maimai DX Festival | ### Importer diff --git a/titles/mai2/__init__.py b/titles/mai2/__init__.py index 7063ee6..2fa3874 100644 --- a/titles/mai2/__init__.py +++ b/titles/mai2/__init__.py @@ -16,4 +16,4 @@ game_codes = [ Mai2Constants.GAME_CODE_GREEN, Mai2Constants.GAME_CODE, ] -current_schema_version = 6 +current_schema_version = 7 diff --git a/titles/mai2/base.py b/titles/mai2/base.py index a53e416..9f1ffaf 100644 --- a/titles/mai2/base.py +++ b/titles/mai2/base.py @@ -140,6 +140,7 @@ class Mai2Base: def handle_user_login_api_request(self, data: Dict) -> Dict: profile = self.data.profile.get_profile_detail(data["userId"], self.version) + consec = self.data.profile.get_consec_login(data["userId"], self.version) if profile is not None: lastLoginDate = profile["lastLoginDate"] @@ -150,12 +151,32 @@ class Mai2Base: else: loginCt = 0 lastLoginDate = "2017-12-05 07:00:00.0" + + if consec is None or not consec: + consec_ct = 1 + + else: + lastlogindate_ = datetime.strptime(profile["lastLoginDate"], "%Y-%m-%d %H:%M:%S.%f").timestamp() + today_midnight = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp() + yesterday_midnight = today_midnight - 86400 + + if lastlogindate_ < today_midnight: + consec_ct = consec['logins'] + 1 + self.data.profile.add_consec_login(data["userId"], self.version) + + elif lastlogindate_ < yesterday_midnight: + consec_ct = 1 + self.data.profile.reset_consec_login(data["userId"], self.version) + + else: + consec_ct = consec['logins'] + return { "returnCode": 1, "lastLoginDate": lastLoginDate, "loginCount": loginCt, - "consecutiveLoginCount": 0, # We don't really have a way to track this... + "consecutiveLoginCount": consec_ct, # Number of consecutive days we've logged in. } def handle_upload_user_playlog_api_request(self, data: Dict) -> Dict: @@ -747,3 +768,9 @@ class Mai2Base: "nextIndex": next_index, "userMusicList": [{"userMusicDetailList": music_detail_list}], } + + def handle_upload_user_portrait_api_request(self, data: Dict) -> Dict: + self.logger.debug(data) + + def handle_upload_user_photo_api_request(self, data: Dict) -> Dict: + self.logger.debug(data) \ No newline at end of file diff --git a/titles/mai2/read.py b/titles/mai2/read.py index a7e10de..4ff401d 100644 --- a/titles/mai2/read.py +++ b/titles/mai2/read.py @@ -37,7 +37,7 @@ class Mai2Reader(BaseReader): def read(self) -> None: data_dirs = [] - if self.version < Mai2Constants.VER_MAIMAI: + if self.version >= Mai2Constants.VER_MAIMAI_DX: if self.bin_dir is not None: data_dirs += self.get_data_directories(self.bin_dir) @@ -52,7 +52,6 @@ class Mai2Reader(BaseReader): self.read_tickets(f"{dir}/ticket") else: - self.logger.warn("Pre-DX Readers are not yet implemented!") if not os.path.exists(f"{self.bin_dir}/tables"): self.logger.error(f"tables directory not found in {self.bin_dir}") return diff --git a/titles/mai2/schema/profile.py b/titles/mai2/schema/profile.py index 54bda21..916be20 100644 --- a/titles/mai2/schema/profile.py +++ b/titles/mai2/schema/profile.py @@ -461,6 +461,17 @@ recent_rating = Table( mysql_charset="utf8mb4", ) +consec_logins = Table( + "mai2_profile_consec_logins", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False), + Column("version", Integer, nullable=False), + Column("logins", Integer), + UniqueConstraint("user", "version", name="mai2_profile_consec_logins_uk"), + mysql_charset="utf8mb4", +) + class Mai2ProfileData(BaseData): def put_profile_detail( self, user_id: int, version: int, detail_data: Dict, is_dx: bool = True @@ -764,4 +775,43 @@ class Mai2ProfileData(BaseData): result = self.execute(sql) if result is None: return None - return result.fetchone() \ No newline at end of file + return result.fetchone() + + def add_consec_login(self, user_id: int, version: int) -> None: + sql = insert(consec_logins).values( + user=user_id, + version=version, + logins=1 + ) + + conflict = sql.on_duplicate_key_update( + logins=consec_logins.c.logins + 1 + ) + + result = self.execute(conflict) + if result is None: + self.logger.error(f"Failed to update consecutive login count for user {user_id} version {version}") + + def get_consec_login(self, user_id: int, version: int) -> Optional[Row]: + sql = select(consec_logins).where(and_( + consec_logins.c.user==user_id, + consec_logins.c.version==version, + )) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def reset_consec_login(self, user_id: int, version: int) -> Optional[Row]: + sql = consec_logins.update(and_( + consec_logins.c.user==user_id, + consec_logins.c.version==version, + )).values( + logins=1 + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() diff --git a/titles/mai2/schema/score.py b/titles/mai2/schema/score.py index 6b25d14..181a895 100644 --- a/titles/mai2/schema/score.py +++ b/titles/mai2/schema/score.py @@ -362,4 +362,4 @@ class Mai2ScoreData(BaseData): result = self.execute(sql) if result is None: return None - return result.fetchone() + return result.fetchall()