Ensure each playlist is unique by storing a record of previously used songs.
This commit is contained in:
parent
cb66d4dc2d
commit
f69e67de6f
4
.gitignore
vendored
4
.gitignore
vendored
@ -6,4 +6,6 @@ __pycache__/
|
|||||||
dist/
|
dist/
|
||||||
*.json
|
*.json
|
||||||
archive/
|
archive/
|
||||||
*.bplist
|
*.bplist
|
||||||
|
covers/
|
||||||
|
comfyui-output/
|
@ -1,101 +1,84 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
from saberlist.beatleaderAPI import BeatLeaderAPI
|
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 collections import defaultdict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
def build_difficulty_based_playlist(api, player_id):
|
HISTORY_FILE = "playlist_history.json"
|
||||||
"""
|
|
||||||
Builds a custom difficulty-based playlist for a given player and saves it as a bplist file.
|
|
||||||
|
|
||||||
This function creates a playlist with the following structure:
|
def load_history():
|
||||||
- 5 songs with difficulty 0 to 3 stars (Easy to Normal)
|
if os.path.exists(HISTORY_FILE):
|
||||||
- 5 songs with difficulty 4 to <6 stars (Hard to Expert)
|
with open(HISTORY_FILE, 'r') as f:
|
||||||
- 5 songs with difficulty 6 to <7 stars (Expert+)
|
return json.load(f)
|
||||||
- 5 songs with difficulty 7+ stars (Expert++)
|
return {}
|
||||||
|
|
||||||
For each difficulty range, it selects the 5 songs that were played longest ago,
|
def save_history(history):
|
||||||
ensuring a mix of nostalgic tracks and skill-appropriate challenges.
|
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
|
def build_difficulty_based_playlist(api, player_id, history, playlist_name):
|
||||||
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
|
|
||||||
scores_data = api.get_player_scores(player_id, use_cache=True)
|
scores_data = api.get_player_scores(player_id, use_cache=True)
|
||||||
all_scores = scores_data['data']
|
all_scores = scores_data['data']
|
||||||
|
|
||||||
# Sort scores by play time (oldest first)
|
|
||||||
all_scores.sort(key=lambda x: x['timepost'])
|
all_scores.sort(key=lambda x: x['timepost'])
|
||||||
|
|
||||||
# Group scores by difficulty
|
|
||||||
difficulty_groups = defaultdict(list)
|
difficulty_groups = defaultdict(list)
|
||||||
for score in all_scores:
|
for score in all_scores:
|
||||||
stars = score['leaderboard']['difficulty']['stars']
|
stars = score['leaderboard']['difficulty']['stars']
|
||||||
|
song_id = score['leaderboard']['song']['id']
|
||||||
|
difficulty_name = score['leaderboard']['difficulty']['difficultyName']
|
||||||
|
|
||||||
if 0 <= stars <= 3:
|
# Check if this song:difficulty combination is in history
|
||||||
difficulty_groups[0].append(score)
|
if song_id not in history or difficulty_name not in history[song_id]:
|
||||||
elif 4 <= stars < 6:
|
if 0 <= stars <= 3:
|
||||||
difficulty_groups[1].append(score)
|
difficulty_groups[0].append(score)
|
||||||
elif 6 <= stars < 7:
|
elif 4 <= stars < 6:
|
||||||
difficulty_groups[2].append(score)
|
difficulty_groups[1].append(score)
|
||||||
elif stars >= 7:
|
elif 6 <= stars < 7:
|
||||||
difficulty_groups[3].append(score)
|
difficulty_groups[2].append(score)
|
||||||
|
elif stars >= 7:
|
||||||
|
difficulty_groups[3].append(score)
|
||||||
|
|
||||||
# Build the playlist
|
|
||||||
playlist_scores = []
|
playlist_scores = []
|
||||||
for difficulty, count in [(0, 5), (1, 5), (2, 5), (3, 5)]:
|
for difficulty, count in [(0, 5), (1, 5), (2, 5), (3, 5)]:
|
||||||
# Remove duplicates (keep the oldest play for each unique song)
|
|
||||||
unique_songs = {}
|
unique_songs = {}
|
||||||
for score in difficulty_groups[difficulty]:
|
for score in difficulty_groups[difficulty]:
|
||||||
song_id = score['leaderboard']['song']['id']
|
song_id = score['leaderboard']['song']['id']
|
||||||
if song_id not in unique_songs or score['timepost'] < unique_songs[song_id]['timepost']:
|
if song_id not in unique_songs or score['timepost'] < unique_songs[song_id]['timepost']:
|
||||||
unique_songs[song_id] = score
|
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])
|
playlist_scores.extend(sorted(unique_songs.values(), key=lambda x: x['timepost'])[:count])
|
||||||
|
|
||||||
# Create the bplist file
|
# Update history
|
||||||
playlist_title = f"Custom Playlist - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
for score in playlist_scores:
|
||||||
playlist_file = api.create_bplist(playlist_scores, playlist_title)
|
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
|
return playlist_file, playlist_scores
|
||||||
|
|
||||||
def star_ladder():
|
def star_ladder():
|
||||||
api = BeatLeaderAPI()
|
api = BeatLeaderAPI()
|
||||||
player_id = '76561199407393962'
|
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(f"Playlist created: {playlist_file}")
|
||||||
print("Playlist contents:")
|
print("Playlist contents:")
|
||||||
for i, score in enumerate(playlist_scores, 1):
|
for i, score in enumerate(playlist_scores, 1):
|
||||||
song = score['leaderboard']['song']
|
song = score['leaderboard']['song']
|
||||||
difficulty = score['leaderboard']['difficulty']
|
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()
|
Loading…
x
Reference in New Issue
Block a user