"""⑥ narration — 롱컷 나레이션 7문장. 축제 3문장이 VLM 생성인 것과 달리 여기는 meta에서 채우는 고정 슬롯이다. 캐스팅 스케줄 문장은 예매 전에 확인하는 정보라 빠지면 안 된다. """ from models.cast import CastExtraction from models.narration_slots import NARRATION_SLOTS, NarrationLine, SlotNarration from models.nol import NolMeta MAX_CAST_IN_LINE = 3 DEFAULT_GENRE = "공연" def period_text(meta: NolMeta) -> str: start, end = meta.play_start_date or "", meta.play_end_date or "" period = f"{start} ~ {end}".strip(" ~") if (start or end) else "" return period.replace("-", ".") def build_narration(meta: NolMeta, cast: CastExtraction | None = None) -> SlotNarration: title = meta.goods_name or "" names = "·".join((cast.names if cast else [])[:MAX_CAST_IN_LINE]) date_text = period_text(meta) place = meta.place_name or "" texts = [ f"{title}, 무대에서 만나세요.", "포스터가 움직이기 시작합니다.", f"{meta.genre_name or DEFAULT_GENRE}의 한 장면을 미리 봅니다.", f"{names} 출연." if names else "출연진을 상세페이지에서 확인하세요.", "캐스팅 스케줄은 상세페이지에서 확인하세요.", f"{date_text} {place}".strip() + ".", "지금 예매하세요.", ] return SlotNarration(lines=[NarrationLine(slot=slot, text=text) for slot, text in zip(NARRATION_SLOTS, texts, strict=True)])