186 lines
6.7 KiB
Python
186 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test script to verify episode matching logic with mock data.
|
|
"""
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# Add src to path
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
|
|
|
from Matcher.episode_renamer import EpisodeRenamer
|
|
|
|
def create_mock_episodes():
|
|
"""Create mock episode data to test the matching logic."""
|
|
return [
|
|
{
|
|
'path': Path('Disc 1_t01.mkv'),
|
|
'name': 'Disc 1_t01.mkv',
|
|
'size_bytes': 2 * 1024**3, # 2GB
|
|
'size_gb': 2.0,
|
|
'duration_minutes': 61.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 1_t02.mkv'),
|
|
'name': 'Disc 1_t02.mkv',
|
|
'size_bytes': 2.1 * 1024**3, # 2.1GB
|
|
'size_gb': 2.1,
|
|
'duration_minutes': 55.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 1_t03.mkv'),
|
|
'name': 'Disc 1_t03.mkv',
|
|
'size_bytes': 2.2 * 1024**3, # 2.2GB
|
|
'size_gb': 2.2,
|
|
'duration_minutes': 57.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 2_t01.mkv'),
|
|
'name': 'Disc 2_t01.mkv',
|
|
'size_bytes': 2.0 * 1024**3, # 2GB
|
|
'size_gb': 2.0,
|
|
'duration_minutes': 55.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 2_t02.mkv'),
|
|
'name': 'Disc 2_t02.mkv',
|
|
'size_bytes': 2.1 * 1024**3, # 2.1GB
|
|
'size_gb': 2.1,
|
|
'duration_minutes': 54.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 2_t03.mkv'),
|
|
'name': 'Disc 2_t03.mkv',
|
|
'size_bytes': 1.9 * 1024**3, # 1.9GB
|
|
'size_gb': 1.9,
|
|
'duration_minutes': 52.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 3_t01.mkv'),
|
|
'name': 'Disc 3_t01.mkv',
|
|
'size_bytes': 2.2 * 1024**3, # 2.2GB
|
|
'size_gb': 2.2,
|
|
'duration_minutes': 57.0,
|
|
},
|
|
{
|
|
'path': Path('Disc 3_t02.mkv'),
|
|
'name': 'Disc 3_t02.mkv',
|
|
'size_bytes': 2.1 * 1024**3, # 2.1GB
|
|
'size_gb': 2.1,
|
|
'duration_minutes': 58.0,
|
|
}
|
|
]
|
|
|
|
def create_mock_tvdb_episodes():
|
|
"""Create mock TVDB episode data."""
|
|
return [
|
|
{'episode_number': 1, 'name': 'Winter Is Coming', 'runtime': 61},
|
|
{'episode_number': 2, 'name': 'The Kingsroad', 'runtime': 55},
|
|
{'episode_number': 3, 'name': 'Lord Snow', 'runtime': 57},
|
|
{'episode_number': 4, 'name': 'Cripples, Bastards, and Broken Things', 'runtime': 55},
|
|
{'episode_number': 5, 'name': 'The Wolf and the Lion', 'runtime': 54},
|
|
{'episode_number': 6, 'name': 'A Golden Crown', 'runtime': 52},
|
|
{'episode_number': 7, 'name': 'You Win or You Die', 'runtime': 57},
|
|
{'episode_number': 8, 'name': 'The Pointy End', 'runtime': 58},
|
|
{'episode_number': 9, 'name': 'Baelor', 'runtime': 56},
|
|
{'episode_number': 10, 'name': 'Fire and Blood', 'runtime': 52},
|
|
]
|
|
|
|
def test_episode_matching():
|
|
"""Test the episode matching logic."""
|
|
print("=== Testing Episode Matching Logic ===\n")
|
|
|
|
# Create mock data
|
|
episodes = create_mock_episodes()
|
|
tvdb_episodes = create_mock_tvdb_episodes()
|
|
|
|
print(f"Mock episode files ({len(episodes)}):")
|
|
for ep in episodes:
|
|
print(f" - {ep['name']} ({ep['duration_minutes']} min)")
|
|
|
|
print(f"\nTVDB episodes ({len(tvdb_episodes)}):")
|
|
for ep in tvdb_episodes:
|
|
print(f" - Episode {ep['episode_number']}: {ep['name']} ({ep['runtime']} min)")
|
|
|
|
# Initialize renamer
|
|
renamer = EpisodeRenamer("/tmp/test", "Game of Thrones", 1)
|
|
|
|
# Test the matching logic
|
|
print("\n" + "="*80)
|
|
print("TESTING EPISODE MATCHING")
|
|
print("="*80)
|
|
|
|
try:
|
|
matched_episodes = renamer._match_episodes_by_duration(episodes, tvdb_episodes)
|
|
|
|
print(f"\n=== MATCHING RESULTS ===")
|
|
print(f"Successfully matched {len(matched_episodes)} episodes:")
|
|
|
|
for match in matched_episodes:
|
|
file_name = match['file_info']['path'].name
|
|
episode_num = match['episode_number']
|
|
tvdb_name = match['tvdb_info']['name'] if match['tvdb_info'] else 'Unknown'
|
|
duration_diff = match.get('duration_diff', 'N/A')
|
|
|
|
print(f" {file_name} → Episode {episode_num}: {tvdb_name}")
|
|
if duration_diff != 'N/A' and duration_diff is not None:
|
|
print(f" Duration difference: {duration_diff:.1f} minutes")
|
|
|
|
# Test validity of assignments
|
|
print(f"\n=== ASSIGNMENT VALIDATION ===")
|
|
episode_numbers = [m['episode_number'] for m in matched_episodes]
|
|
if len(set(episode_numbers)) == len(episode_numbers):
|
|
print("✓ All episodes assigned unique episode numbers")
|
|
else:
|
|
print("✗ Duplicate episode number assignments detected!")
|
|
duplicates = [x for x in episode_numbers if episode_numbers.count(x) > 1]
|
|
print(f" Duplicates: {set(duplicates)}")
|
|
|
|
# Check disc order constraint
|
|
disc_assignments = {}
|
|
for match in matched_episodes:
|
|
file_name = match['file_info']['path'].name
|
|
episode_num = match['episode_number']
|
|
|
|
# Extract disc number
|
|
if 'Disc 1' in file_name:
|
|
disc = 1
|
|
elif 'Disc 2' in file_name:
|
|
disc = 2
|
|
elif 'Disc 3' in file_name:
|
|
disc = 3
|
|
else:
|
|
disc = None
|
|
|
|
if disc:
|
|
if disc not in disc_assignments:
|
|
disc_assignments[disc] = []
|
|
disc_assignments[disc].append(episode_num)
|
|
|
|
print(f"\nDisc assignment validation:")
|
|
for disc in sorted(disc_assignments.keys()):
|
|
episodes = sorted(disc_assignments[disc])
|
|
print(f" Disc {disc}: Episodes {episodes}")
|
|
|
|
# Check if episodes are in reasonable order (earlier discs should have earlier episodes)
|
|
if disc == 1:
|
|
expected_range = list(range(1, 4)) # Episodes 1-3
|
|
elif disc == 2:
|
|
expected_range = list(range(4, 7)) # Episodes 4-6
|
|
elif disc == 3:
|
|
expected_range = list(range(7, 9)) # Episodes 7-8
|
|
|
|
if set(episodes).issubset(set(expected_range)):
|
|
print(f" ✓ Episodes {episodes} are within expected range {expected_range}")
|
|
else:
|
|
print(f" ⚠ Episodes {episodes} outside expected range {expected_range}")
|
|
|
|
except Exception as e:
|
|
print(f"Error during matching: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
if __name__ == "__main__":
|
|
test_episode_matching()
|