CHUNITHM - dev branch GetRivalMusicApi is broken #57

Closed
opened 2023-10-27 01:39:58 +00:00 by DSRLIN · 2 comments
Contributor

Currently the api is using all playlogs to build user's rival music.
The function self.data.score.get_rival_music(rival_id) requires rival_id, index, count which are 3 params, but only 1 passed here.
But fixing this won't work either.


According to the code, len(all_entries) will always <= max_count because all_entries = get_rival_music(...), which uses the max count as a limit param.
And after compressing all musics in all_entries into a list that based on music_id, the result will always <= max_count because there must be some duplicated music_ids with different levels. So after packing them into another list, The list size can only shrink or remain the same.
So the "nextIndex": str(next_index + len(all_entries) if len(all_entries) <= len(user_rival_music_list) else -1) in result dict will almost always -1.


There are 2 places need to patch.
The first one is to replace the table in function "get_rival_music" from playlog to best_score. The things that currently in the code do is to build a best score list from playlogs. And the parameter index and count are useless too.

    def get_rival_music(self, rival_id: int) -> Optional[List[Dict]]:
        sql = select(best_score).where(best_score.c.user == rival_id)
        result = self.execute(sql)
        if result is None:
            return None
        return result.fetchall()

The second one is to modify the function "handle_get_user_rival_music_api_request".

    def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict:
        rival_id = data["rivalId"]
        next_index = int(data["nextIndex"])
        max_count = int(data["maxCount"])
        user_rival_music_list = []

        # Fetch all the rival music entries for the user
        all_entries = self.data.score.get_rival_music(rival_id)

        # Process the entries based on max_count and nextIndex
        for music in all_entries:
            music_id = music["musicId"]
            level = music["level"]
            score = music["scoreMax"]
            rank = music["scoreRank"]

            # Create a music entry for the current music_id if it's unique
            music_entry = next((entry for entry in user_rival_music_list if entry["musicId"] == music_id), None)
            if music_entry is None:
                music_entry = {
                    "musicId": music_id,
                    "length": 0,
                    "userRivalMusicDetailList": []
                }
                user_rival_music_list.append(music_entry)

            # Create a level entry for the current level if it's unique or has a higher score
            level_entry = next((entry for entry in music_entry["userRivalMusicDetailList"] if entry["level"] == level), None)
            if level_entry is None:
                level_entry = {
                    "level": level,
                    "scoreMax": score,
                    "scoreRank": rank
                }
                music_entry["userRivalMusicDetailList"].append(level_entry)
            elif score > level_entry["scoreMax"]:
                level_entry["scoreMax"] = score
                level_entry["scoreRank"] = rank

        # Calculate the length for each "musicId" by counting the unique levels
        for music_entry in user_rival_music_list:
            music_entry["length"] = len(music_entry["userRivalMusicDetailList"])

        # Prepare the result dictionary with user rival music data
        result = {
            "userId": data["userId"],
            "rivalId": data["rivalId"],
            "nextIndex": str(next_index + len(user_rival_music_list[next_index: next_index + max_count]) if max_count <= len(user_rival_music_list[next_index: next_index + max_count]) else -1),
            "userRivalMusicList": user_rival_music_list[next_index: next_index + max_count]
        }
        return result

I'm currently using these codes as a fix to this problem and is now testing with multiple accounts, each with 1000+ best scores. I'll update this issue once the test got a result.

Currently the api is using all playlogs to build user's rival music. The function self.data.score.get_rival_music(rival_id) requires rival_id, index, count which are 3 params, but only 1 passed here. But fixing this won't work either. <br> According to the code, len(all_entries) will always <= max_count because all_entries = get_rival_music(...), which uses the max count as a limit param. And after compressing all musics in all_entries into a list that based on music_id, the result will always <= max_count because there must be some duplicated music_ids with different levels. So after packing them into another list, The list size can only shrink or remain the same. So the "nextIndex": str(next_index + len(all_entries) if len(all_entries) <= len(user_rival_music_list) else -1) in result dict will almost always -1. <br> There are 2 places need to patch. The first one is to replace the table in function "get_rival_music" from playlog to best_score. The things that currently in the code do is to build a best score list from playlogs. And the parameter index and count are useless too. ```python def get_rival_music(self, rival_id: int) -> Optional[List[Dict]]: sql = select(best_score).where(best_score.c.user == rival_id) result = self.execute(sql) if result is None: return None return result.fetchall() ``` The second one is to modify the function "handle_get_user_rival_music_api_request". ```python def handle_get_user_rival_music_api_request(self, data: Dict) -> Dict: rival_id = data["rivalId"] next_index = int(data["nextIndex"]) max_count = int(data["maxCount"]) user_rival_music_list = [] # Fetch all the rival music entries for the user all_entries = self.data.score.get_rival_music(rival_id) # Process the entries based on max_count and nextIndex for music in all_entries: music_id = music["musicId"] level = music["level"] score = music["scoreMax"] rank = music["scoreRank"] # Create a music entry for the current music_id if it's unique music_entry = next((entry for entry in user_rival_music_list if entry["musicId"] == music_id), None) if music_entry is None: music_entry = { "musicId": music_id, "length": 0, "userRivalMusicDetailList": [] } user_rival_music_list.append(music_entry) # Create a level entry for the current level if it's unique or has a higher score level_entry = next((entry for entry in music_entry["userRivalMusicDetailList"] if entry["level"] == level), None) if level_entry is None: level_entry = { "level": level, "scoreMax": score, "scoreRank": rank } music_entry["userRivalMusicDetailList"].append(level_entry) elif score > level_entry["scoreMax"]: level_entry["scoreMax"] = score level_entry["scoreRank"] = rank # Calculate the length for each "musicId" by counting the unique levels for music_entry in user_rival_music_list: music_entry["length"] = len(music_entry["userRivalMusicDetailList"]) # Prepare the result dictionary with user rival music data result = { "userId": data["userId"], "rivalId": data["rivalId"], "nextIndex": str(next_index + len(user_rival_music_list[next_index: next_index + max_count]) if max_count <= len(user_rival_music_list[next_index: next_index + max_count]) else -1), "userRivalMusicList": user_rival_music_list[next_index: next_index + max_count] } return result ``` I'm currently using these codes as a fix to this problem and is now testing with multiple accounts, each with 1000+ best scores. I'll update this issue once the test got a result.
DSRLIN changed title from Chunithm - dev branch GetRivalMusicApi is broken to CHUNITHM - dev branch GetRivalMusicApi is broken 2023-10-27 01:41:05 +00:00
Contributor

See if my recent commits help this issue; I encountered this as well earlier, and I thought I fixed it with one of them. If not, we can merge your changes as well!

See if my recent commits help this issue; I encountered this as well earlier, and I thought I fixed it with one of them. If not, we can merge your changes as well!
Hay1tsme added the
bug
chuni
wip
labels 2023-12-13 02:16:25 +00:00
Contributor

Thank you for the fix! I've tested and confirmed this is working, so I added it to my current PR.

Thank you for the fix! I've tested and confirmed this is working, so I added it to my current PR.
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Hay1tsme/artemis#57
No description provided.