156 lines
4.4 KiB
Python
156 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Scans all JSON song files and reports track information.
|
|
Shows each track's note count to help with track selection.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Dict, List, Tuple
|
|
|
|
|
|
def scan_song_file(file_path: Path) -> Dict:
|
|
"""
|
|
Scan a single JSON song file and extract track information.
|
|
|
|
Returns:
|
|
Dict with 'name', 'artist', 'tracks' (list of note counts)
|
|
"""
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
|
|
song_name = data.get('header', {}).get('name', 'Unknown')
|
|
artist = data.get('header', {}).get('artist', 'Unknown')
|
|
tracks = data.get('tracks', [])
|
|
|
|
track_info = []
|
|
for i, track in enumerate(tracks):
|
|
notes = track.get('notes', [])
|
|
instrument = track.get('instrument', {})
|
|
instrument_name = instrument.get('name', 'Unknown')
|
|
note_count = len(notes)
|
|
|
|
# Only count notes in the playable MIDI range (48-83)
|
|
playable_notes = [n for n in notes if 48 <= n.get('midi', 0) <= 83]
|
|
playable_count = len(playable_notes)
|
|
|
|
track_info.append({
|
|
'index': i,
|
|
'instrument': instrument_name,
|
|
'total_notes': note_count,
|
|
'playable_notes': playable_count,
|
|
'channel': track.get('channel', 'N/A')
|
|
})
|
|
|
|
return {
|
|
'name': song_name,
|
|
'artist': artist,
|
|
'tracks': track_info,
|
|
'file': file_path.name
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'name': 'ERROR',
|
|
'artist': str(e),
|
|
'tracks': [],
|
|
'file': file_path.name
|
|
}
|
|
|
|
|
|
def find_best_track(tracks: List[Dict]) -> int:
|
|
"""Find the track with the most playable notes (mimics the game logic)."""
|
|
if not tracks:
|
|
return 0
|
|
|
|
best_idx = 0
|
|
best_count = 0
|
|
for i, track in enumerate(tracks):
|
|
if track['playable_notes'] > best_count:
|
|
best_count = track['playable_notes']
|
|
best_idx = i
|
|
|
|
return best_idx
|
|
|
|
|
|
def main():
|
|
# Find the assets/songs/json directory
|
|
script_dir = Path(__file__).parent
|
|
json_dir = script_dir / 'assets' / 'songs' / 'json'
|
|
|
|
if not json_dir.exists():
|
|
print(f"Error: Directory not found: {json_dir}")
|
|
return
|
|
|
|
# Find all JSON files
|
|
json_files = sorted(json_dir.glob('*.json'))
|
|
|
|
if not json_files:
|
|
print(f"No JSON files found in {json_dir}")
|
|
return
|
|
|
|
print("=" * 80)
|
|
print("SONG TRACK ANALYSIS")
|
|
print("=" * 80)
|
|
print()
|
|
|
|
# Scan each file
|
|
all_songs = []
|
|
for json_file in json_files:
|
|
song_info = scan_song_file(json_file)
|
|
all_songs.append(song_info)
|
|
|
|
# Print detailed report
|
|
for song in all_songs:
|
|
print(f"FILE: {song['file']}")
|
|
print(f" Song: {song['name']}")
|
|
print(f" Artist: {song['artist']}")
|
|
print(f" Tracks: {len(song['tracks'])}")
|
|
|
|
if song['tracks']:
|
|
best_idx = find_best_track(song['tracks'])
|
|
print()
|
|
for track in song['tracks']:
|
|
is_best = track['index'] == best_idx
|
|
marker = " [AUTO-SELECTED]" if is_best else ""
|
|
print(f" Track {track['index']}: "
|
|
f"{track['playable_notes']:4d} playable notes "
|
|
f"({track['total_notes']:4d} total) - "
|
|
f"{track['instrument']}{marker}")
|
|
else:
|
|
print(" No tracks found!")
|
|
|
|
print()
|
|
print("-" * 80)
|
|
print()
|
|
|
|
# Summary statistics
|
|
print("\n" + "=" * 80)
|
|
print("SUMMARY")
|
|
print("=" * 80)
|
|
|
|
total_songs = len(all_songs)
|
|
total_tracks = sum(len(s['tracks']) for s in all_songs)
|
|
avg_tracks = total_tracks / total_songs if total_songs > 0 else 0
|
|
|
|
print(f"Total songs: {total_songs}")
|
|
print(f"Total tracks: {total_tracks}")
|
|
print(f"Average tracks per song: {avg_tracks:.1f}")
|
|
print()
|
|
|
|
# Show which songs would auto-select which track
|
|
print("Auto-selection would choose:")
|
|
for song in all_songs:
|
|
if song['tracks']:
|
|
best_idx = find_best_track(song['tracks'])
|
|
best_track = song['tracks'][best_idx]
|
|
print(f" {song['name']:40s} -> Track {best_idx} "
|
|
f"({best_track['playable_notes']} notes, {best_track['instrument']})")
|
|
|
|
print()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|