44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
from collections import Counter
|
|
|
|
from serato_doctor.matching import MatchingEngine
|
|
from serato_doctor.models.health import HealthReport
|
|
from serato_doctor.models.library import Library
|
|
|
|
|
|
def analyze_health(library: Library) -> HealthReport:
|
|
"""Calculate defensible health metrics without changing the library."""
|
|
|
|
results = library.reconcile_by_filename()
|
|
missing = [result for result in results if not result.exists_by_filename]
|
|
healthy_count = len(results) - len(missing)
|
|
score = (
|
|
round(healthy_count / len(results) * 100, 1) if results else None
|
|
)
|
|
|
|
disk_name_counts = Counter(track.filename for track in library.tracks)
|
|
duplicate_counts = [count for count in disk_name_counts.values() if count > 1]
|
|
referenced_names = {reference.filename for reference in library.references}
|
|
unused_count = sum(
|
|
1 for track in library.tracks if track.filename not in referenced_names
|
|
)
|
|
|
|
matcher = MatchingEngine(library.tracks)
|
|
suggested_count = sum(
|
|
bool(matcher.candidates_for(result.reference)) for result in missing
|
|
)
|
|
|
|
return HealthReport(
|
|
score=score,
|
|
total_references=len(results),
|
|
healthy_references=healthy_count,
|
|
missing_references=len(missing),
|
|
unique_missing_filenames=len(
|
|
{result.reference.filename for result in missing}
|
|
),
|
|
disk_tracks=len(library.tracks),
|
|
duplicate_filename_groups=len(duplicate_counts),
|
|
duplicate_files=sum(count - 1 for count in duplicate_counts),
|
|
unused_tracks=unused_count,
|
|
suggested_matches=suggested_count,
|
|
)
|