Ensure each playlist is unique by storing a record of previously used songs.

This commit is contained in:
Brian Lee 2024-09-17 07:11:43 -07:00
parent cb66d4dc2d
commit f69e67de6f
2 changed files with 49 additions and 64 deletions

4
.gitignore vendored
View File

@ -6,4 +6,6 @@ __pycache__/
dist/
*.json
archive/
*.bplist
*.bplist
covers/
comfyui-output/

View File

@ -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'])}")
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()