Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fce5ad64e5 |
+32
-7
@@ -269,21 +269,46 @@ def _combined_title_variants(name: str) -> list[str]:
|
||||
return variants
|
||||
|
||||
|
||||
def _combined_match_score(fnorm: str, combined_name: str) -> float:
|
||||
def _combined_match_score(fnorm: str, combined_name: str, file_title: str = "") -> float:
|
||||
variants = _combined_title_variants(combined_name)
|
||||
return max((_similarity(fnorm, v) for v in variants), default=0.0)
|
||||
best = max((_similarity(fnorm, v) for v in variants), default=0.0)
|
||||
if file_title and _dual_title_matches_combined(file_title, combined_name):
|
||||
best = max(best, 0.96)
|
||||
return best
|
||||
|
||||
|
||||
def _combined_allowed_for_file(parsed: dict, target: EpisodeTarget) -> bool:
|
||||
"""Only treat as multi-episode when the file's episode code fits the range start."""
|
||||
def _dual_title_matches_combined(file_title: str, combined_name: str) -> bool:
|
||||
"""True when the filename lists both stories in a combined-order pair."""
|
||||
file_parts = [p.strip() for p in re.split(r"\s+-\s+", file_title) if p.strip()]
|
||||
combined_parts = split_combined_title(combined_name)
|
||||
if len(file_parts) < 2 or len(combined_parts) < 2:
|
||||
return False
|
||||
matched = 0
|
||||
for fp in file_parts[: len(combined_parts)]:
|
||||
fn = normalize_title(fp)
|
||||
if max(_similarity(fn, normalize_title(cp)) for cp in combined_parts) >= 0.72:
|
||||
matched += 1
|
||||
return matched >= 2
|
||||
|
||||
|
||||
def _combined_allowed_for_file(
|
||||
parsed: dict,
|
||||
target: EpisodeTarget,
|
||||
combined_name: str = "",
|
||||
) -> bool:
|
||||
"""Treat as multi-episode when the episode tag or dual title fits the aired range."""
|
||||
if target.span <= 1:
|
||||
return True
|
||||
if parsed.get("span", 1) > 1:
|
||||
return True
|
||||
file_title = parsed.get("title") or ""
|
||||
if combined_name and _dual_title_matches_combined(file_title, combined_name):
|
||||
return True
|
||||
file_ep = parsed.get("old_first")
|
||||
if file_ep is None:
|
||||
return False
|
||||
return file_ep == target.episode
|
||||
end = target.episode_end if target.episode_end is not None else target.episode
|
||||
return file_ep == target.episode or file_ep == end
|
||||
|
||||
|
||||
def _range_overlaps(
|
||||
@@ -390,9 +415,9 @@ def match_filenames_to_episodes(
|
||||
for _cep, target, variants in combined_entries:
|
||||
if not fnorm:
|
||||
continue
|
||||
if not _combined_allowed_for_file(parsed, target):
|
||||
if not _combined_allowed_for_file(parsed, target, _cep.name):
|
||||
continue
|
||||
best = _combined_match_score(fnorm, _cep.name)
|
||||
best = _combined_match_score(fnorm, _cep.name, raw_title)
|
||||
best = _apply_season_hint(best, target, parsed)
|
||||
pairs.append((best, fname, target, raw_title, _cep.name))
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
HSRename 1.0.11
|
||||
- Fix multi-episode detection when filename uses end episode (S01E06 for E05-E06)
|
||||
- Detect dual titles separated by " - " (Otto 3000 - Night Prowler) as combined pairs
|
||||
Reference in New Issue
Block a user