48 lines
1.4 KiB
Python
48 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any
|
|
|
|
try:
|
|
from .krea_action_context import normalize_hardcore_detail_density
|
|
except ImportError: # Allows local smoke tests with `python -c`.
|
|
from krea_action_context import normalize_hardcore_detail_density
|
|
|
|
|
|
def _clean(value: Any) -> str:
|
|
text = "" if value is None else str(value)
|
|
text = text.replace("\n", " ")
|
|
text = re.sub(r"\s+", " ", text).strip()
|
|
text = re.sub(r"\s+([,.;:])", r"\1", text)
|
|
return text
|
|
|
|
|
|
def detail_clauses(detail: str) -> list[str]:
|
|
return [part.strip(" ,;") for part in re.split(r",\s*(?:and\s+)?", _clean(detail)) if part.strip(" ,;")]
|
|
|
|
|
|
def join_detail_clauses(clauses: list[str]) -> str:
|
|
cleaned: list[str] = []
|
|
seen: set[str] = set()
|
|
for clause in clauses:
|
|
clause = _clean(clause).strip(" ,;")
|
|
key = clause.lower()
|
|
if clause and key not in seen:
|
|
cleaned.append(clause)
|
|
seen.add(key)
|
|
return ", ".join(cleaned)
|
|
|
|
|
|
def limit_detail_for_density(detail: str, density: str, is_climax: bool) -> str:
|
|
density = normalize_hardcore_detail_density(density)
|
|
if density == "compact":
|
|
return ""
|
|
clauses = detail_clauses(detail)
|
|
if not clauses:
|
|
return ""
|
|
if density == "balanced":
|
|
limit = 1 if is_climax else 2
|
|
else:
|
|
limit = 3 if is_climax else 4
|
|
return join_detail_clauses(clauses[:limit])
|