diff --git a/.gitignore b/.gitignore index e2dcccf..628ab46 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ __pycache__/ dist/ *.json archive/ -*.bplist \ No newline at end of file +*.bplist +covers/ +comfyui-output/ \ No newline at end of file diff --git a/src/saberlist/beatleader.py b/src/saberlist/beatleader.py index ff2ae49..d457ffe 100644 --- a/src/saberlist/beatleader.py +++ b/src/saberlist/beatleader.py @@ -1,101 +1,84 @@ +import json +import os from saberlist.beatleaderAPI import BeatLeaderAPI -from collections import defaultdict -from datetime import datetime, timedelta - -import logging -logging.basicConfig( - format='%(asctime)s %(levelname)s: %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - level=logging.DEBUG -) -logger = logging.getLogger(__name__) - from collections import defaultdict from datetime import datetime -def build_difficulty_based_playlist(api, player_id): - """ - Builds a custom difficulty-based playlist for a given player and saves it as a bplist file. +HISTORY_FILE = "playlist_history.json" - This function creates a playlist with the following structure: - - 5 songs with difficulty 0 to 3 stars (Easy to Normal) - - 5 songs with difficulty 4 to <6 stars (Hard to Expert) - - 5 songs with difficulty 6 to <7 stars (Expert+) - - 5 songs with difficulty 7+ stars (Expert++) +def load_history(): + if os.path.exists(HISTORY_FILE): + with open(HISTORY_FILE, 'r') as f: + return json.load(f) + return {} - For each difficulty range, it selects the 5 songs that were played longest ago, - ensuring a mix of nostalgic tracks and skill-appropriate challenges. +def save_history(history): + with open(HISTORY_FILE, 'w') as f: + json.dump(history, f, indent=2) - The function handles duplicate songs by keeping only the oldest play for each unique song - within each difficulty group. - - Parameters: - api (BeatLeaderAPI): An instance of the BeatLeaderAPI class to fetch player scores. - player_id (str): The unique identifier of the player. - - Returns: - tuple: A tuple containing two elements: - - str: The file path of the created bplist file. - - list: A list of score objects included in the playlist. - - The created bplist file is saved in the current directory with a name format: - "Custom Playlist - YYYY-MM-DD HH:MM:SS.bplist" - - Note: - - This function uses cached score data if available. To force a fresh API call, - you may need to clear the cache or modify the api.get_player_scores() call. - - The function assumes that the BeatLeaderAPI class has a create_bplist() method - to generate the bplist file. - """ - - # Get all scores for the player +def build_difficulty_based_playlist(api, player_id, history, playlist_name): scores_data = api.get_player_scores(player_id, use_cache=True) all_scores = scores_data['data'] - - # Sort scores by play time (oldest first) all_scores.sort(key=lambda x: x['timepost']) - # Group scores by difficulty difficulty_groups = defaultdict(list) for score in all_scores: stars = score['leaderboard']['difficulty']['stars'] + song_id = score['leaderboard']['song']['id'] + difficulty_name = score['leaderboard']['difficulty']['difficultyName'] - if 0 <= stars <= 3: - difficulty_groups[0].append(score) - elif 4 <= stars < 6: - difficulty_groups[1].append(score) - elif 6 <= stars < 7: - difficulty_groups[2].append(score) - elif stars >= 7: - difficulty_groups[3].append(score) + # Check if this song:difficulty combination is in history + if song_id not in history or difficulty_name not in history[song_id]: + if 0 <= stars <= 3: + difficulty_groups[0].append(score) + elif 4 <= stars < 6: + difficulty_groups[1].append(score) + elif 6 <= stars < 7: + difficulty_groups[2].append(score) + elif stars >= 7: + difficulty_groups[3].append(score) - # Build the playlist playlist_scores = [] for difficulty, count in [(0, 5), (1, 5), (2, 5), (3, 5)]: - # Remove duplicates (keep the oldest play for each unique song) unique_songs = {} for score in difficulty_groups[difficulty]: song_id = score['leaderboard']['song']['id'] if song_id not in unique_songs or score['timepost'] < unique_songs[song_id]['timepost']: unique_songs[song_id] = score - # Add the oldest unique songs to the playlist playlist_scores.extend(sorted(unique_songs.values(), key=lambda x: x['timepost'])[:count]) - # Create the bplist file - playlist_title = f"Custom Playlist - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" - playlist_file = api.create_bplist(playlist_scores, playlist_title) + # Update history + for score in playlist_scores: + song_id = score['leaderboard']['song']['id'] + difficulty_name = score['leaderboard']['difficulty']['difficultyName'] + if song_id not in history: + history[song_id] = [] + history[song_id].append(difficulty_name) + + playlist_file = api.create_bplist(playlist_scores, playlist_name) return playlist_file, playlist_scores def star_ladder(): api = BeatLeaderAPI() player_id = '76561199407393962' - playlist_file, playlist_scores = build_difficulty_based_playlist(api, player_id) + + history = load_history() + + # Generate a unique playlist name + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + playlist_name = f"star_ladder-{timestamp}" + + playlist_file, playlist_scores = build_difficulty_based_playlist(api, player_id, history, playlist_name) + save_history(history) print(f"Playlist created: {playlist_file}") print("Playlist contents:") for i, score in enumerate(playlist_scores, 1): song = score['leaderboard']['song'] difficulty = score['leaderboard']['difficulty'] - print(f"{i}. {song['name']} by {song['author']} (Mapper: {song['mapper']}) - {difficulty['stars']:.2f} stars - Last played: {datetime.fromtimestamp(score['timepost'])}") \ No newline at end of file + print(f"{i}. {song['name']} by {song['author']} (Mapper: {song['mapper']}) - {difficulty['stars']:.2f} stars - Last played: {datetime.fromtimestamp(score['timepost'])}") + +if __name__ == "__main__": + star_ladder() \ No newline at end of file