Add a help message and set up attributes for choosing a playlist strategy.
This commit is contained in:
parent
2d87cdd59e
commit
106c97ae41
@ -1,5 +1,7 @@
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timedelta, timezone
|
||||
@ -94,9 +96,105 @@ def normalize_difficulty_name(difficulty_name):
|
||||
# Return the mapped value or the original name if there is no mapping
|
||||
return difficulty_names.get(difficulty_name, difficulty_name)
|
||||
|
||||
def playlist_strategy_scoresaber_oldscores(
|
||||
api: ScoreSaberAPI,
|
||||
song_count: int = 20 # Total number of songs to select
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Build and format a list of songs based on old scores from ScoreSaber, avoiding reusing the same song+difficulty."""
|
||||
|
||||
player_id = prompt_for_player_id()
|
||||
history = load_history()
|
||||
history.setdefault('scoresaber_oldscores', {})
|
||||
|
||||
scores_data = api.get_player_scores(player_id, use_cache=True)
|
||||
all_scores = scores_data.get('playerScores', [])
|
||||
if not all_scores:
|
||||
logging.warning(f"No scores found for player ID {player_id}.")
|
||||
return []
|
||||
logging.debug(f"Found {len(all_scores)} scores for player ID {player_id}.")
|
||||
|
||||
# Sort scores by timeSet in ascending order (oldest first)
|
||||
all_scores.sort(key=lambda x: x['score'].get('timeSet', ''))
|
||||
|
||||
playlist_data = []
|
||||
current_time = datetime.now(timezone.utc)
|
||||
|
||||
for score in all_scores:
|
||||
leaderboard = score.get('leaderboard', {})
|
||||
song_id = leaderboard.get('songHash')
|
||||
difficulty_raw = leaderboard.get('difficulty', {}).get('difficultyRaw', '')
|
||||
|
||||
if not song_id or not difficulty_raw:
|
||||
logging.debug(f"Skipping score due to missing song_id or difficulty_raw: {score}")
|
||||
continue # Skip if essential data is missing
|
||||
|
||||
# Calculate time ago
|
||||
time_set_str = score['score'].get('timeSet')
|
||||
if not time_set_str:
|
||||
logging.debug(f"Skipping score due to missing timeSet: {score}")
|
||||
continue # Skip if time_set is missing
|
||||
try:
|
||||
time_set = datetime.fromisoformat(time_set_str.replace('Z', '+00:00'))
|
||||
except ValueError as e:
|
||||
logging.error(f"Invalid time format for score ID {score['score'].get('id')}: {e}")
|
||||
continue
|
||||
time_difference = current_time - time_set
|
||||
time_ago = format_time_ago(time_difference)
|
||||
|
||||
# Normalize the difficulty name
|
||||
difficulty = normalize_difficulty_name(difficulty_raw)
|
||||
game_mode = leaderboard.get('difficulty', {}).get('gameMode', 'Standard')
|
||||
if 'Standard' in game_mode:
|
||||
game_mode = 'Standard'
|
||||
|
||||
# Check history to avoid reusing song+difficulty
|
||||
if song_id in history['scoresaber_oldscores'] and difficulty in history['scoresaber_oldscores'][song_id]:
|
||||
logging.debug(f"Skipping song {song_id} with difficulty {difficulty} as it's in history.")
|
||||
continue # Skip if already used
|
||||
|
||||
# Format the song data as expected by PlaylistBuilder
|
||||
song_dict = {
|
||||
'hash': song_id,
|
||||
'songName': leaderboard.get('songName', 'Unknown'),
|
||||
'difficulties': [
|
||||
{
|
||||
'name': difficulty,
|
||||
'characteristic': game_mode
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Add the song to the playlist
|
||||
playlist_data.append(song_dict)
|
||||
logging.debug(f"Selected song for playlist: {song_dict['songName']} ({difficulty})")
|
||||
|
||||
# Log the song addition
|
||||
mapper = "Unknown" # Mapper information can be added if available
|
||||
logging.info(f"Song added: {song_dict['songName']} ({difficulty}), mapped by {mapper}. Last played {time_ago} ago.")
|
||||
|
||||
# Check if the desired number of songs has been reached
|
||||
if len(playlist_data) >= song_count:
|
||||
logging.debug(f"Reached the desired song count: {song_count}.")
|
||||
break
|
||||
|
||||
# Log if no songs were added
|
||||
if not playlist_data:
|
||||
logging.info("No new songs found to add to the playlist based on history.")
|
||||
else:
|
||||
logging.info(f"Total songs added to playlist: {len(playlist_data)}")
|
||||
|
||||
# Update history to avoid reusing the same song+difficulty
|
||||
for song in playlist_data:
|
||||
song_id = song['hash']
|
||||
difficulty_name = song['difficulties'][0]['name']
|
||||
history['scoresaber_oldscores'].setdefault(song_id, []).append(difficulty_name)
|
||||
save_history(history)
|
||||
|
||||
return playlist_data
|
||||
|
||||
def playlist_strategy_beatleader_oldscores(
|
||||
api: BeatLeaderAPI,
|
||||
song_count: int = 40
|
||||
song_count: int = 20
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Build and format a list of songs based on old scores from BeatLeader,
|
||||
@ -186,12 +284,13 @@ def playlist_strategy_beatleader_oldscores(
|
||||
|
||||
return playlist_data
|
||||
|
||||
def saberlist(strategy='beatleader_oldscores') -> None:
|
||||
def saberlist() -> None:
|
||||
"""
|
||||
Generate a playlist of songs from a range of difficulties, all with scores previously set a long time ago.
|
||||
The range of difficulties ensures that the first few songs are good for warming up.
|
||||
Avoids reusing the same song+difficulty in a playlist based on history.
|
||||
"""
|
||||
strategy = get_strategy()
|
||||
if strategy == 'scoresaber_oldscores':
|
||||
api = ScoreSaberAPI(cache_expiry_days=CACHE_EXPIRY_DAYS)
|
||||
elif strategy == 'beatleader_oldscores':
|
||||
@ -206,7 +305,7 @@ def saberlist(strategy='beatleader_oldscores') -> None:
|
||||
if strategy == 'scoresaber_oldscores':
|
||||
playlist_data = playlist_strategy_scoresaber_oldscores(api)
|
||||
elif strategy == 'beatleader_oldscores':
|
||||
playlist_data = playlist_strategy_beatleader_oldscores(api, song_count=40)
|
||||
playlist_data = playlist_strategy_beatleader_oldscores(api)
|
||||
|
||||
if not playlist_data:
|
||||
logging.info("No new scores found to add to the playlist.")
|
||||
@ -218,19 +317,16 @@ def saberlist(strategy='beatleader_oldscores') -> None:
|
||||
playlist_author="SaberList Tool"
|
||||
)
|
||||
|
||||
"""
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
def get_strategy():
|
||||
parser = argparse.ArgumentParser(description="Generate Beat Saber playlists")
|
||||
parser.add_argument("-s", "--strategy",
|
||||
choices=["scoresaber_oldscores", "beatleader_oldscores"],
|
||||
help="Specify the playlist generation strategy",
|
||||
required=True)
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
parser = argparse.ArgumentParser(description="Generate a playlist based on player scores.")
|
||||
parser.add_argument(
|
||||
'--strategy',
|
||||
type=str,
|
||||
default='beatleader_oldscores',
|
||||
choices=['scoresaber_oldscores', 'beatleader_oldscores'],
|
||||
help='Strategy to use for building the playlist.'
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
saberlist(strategy=args.strategy)
|
||||
"""
|
||||
return args.strategy
|
Loading…
Reference in New Issue
Block a user