Files
dl-organizer/src/vlm/duplicate_resolve.py
T

52 lines
1.9 KiB
Python
Raw Normal View History

"""Duplicate group resolution: choose which file to keep when consuming analysis."""
from pathlib import Path
from typing import Union
from vlm.models import MovieIdentity, SeriesIdentity
def choose_keep_index(
items: list[tuple[Path, Union[MovieIdentity, SeriesIdentity]]],
strategy: str,
) -> int | None:
"""Choose the index of the item to keep in a duplicate group.
Strategies:
- by_reputation: Prefer items with reputation_score; then sort by score desc,
then reputation_votes desc, then first_seen (input order). Keep index 0 after sort.
- first_seen: Keep the first item (index 0).
- manual: Return None; caller should not generate quarantine ops, only record in metadata.
Args:
items: List of (path, identity) for the duplicate group.
strategy: One of "by_reputation", "first_seen", "manual".
Returns:
Index in [0, len(items)) to keep, or None for manual.
"""
if strategy == "manual":
return None
if strategy == "first_seen":
return 0
if strategy == "by_reputation":
return _by_reputation_index(items)
return 0
def _by_reputation_index(
items: list[tuple[Path, Union[MovieIdentity, SeriesIdentity]]],
) -> int:
"""Sort by: has reputation > no reputation; then score desc; then votes desc; then order. Return 0."""
def key(idx_reason: tuple[int, tuple[Path, Union[MovieIdentity, SeriesIdentity]]]) -> tuple:
idx, (path, identity) = idx_reason
has_rep = identity.reputation_score is not None
score = identity.reputation_score if identity.reputation_score is not None else -1.0
votes = identity.reputation_votes if identity.reputation_votes is not None else -1
# Prefer has reputation (True > False), then higher score, then higher votes, then lower index
return (not has_rep, -score, -votes, idx)
indexed = list(enumerate(items))
indexed.sort(key=key)
return indexed[0][0]