""" Radio Test analyzer (open-data, deterministic). No external API, no LLM. This is a heuristic that explains its decision. """ from __future__ import annotations import re from dataclasses import dataclass VOWELS = set("aeiou") def _count_syllables(word: str) -> int: """ Approximate syllable count for brandability heuristics. Uses vowel-group counting with a few basic adjustments. """ w = re.sub(r"[^a-z]", "", word.lower()) if not w: return 0 groups = 0 prev_vowel = False for i, ch in enumerate(w): is_vowel = ch in VOWELS or (ch == "y" and i > 0) if is_vowel and not prev_vowel: groups += 1 prev_vowel = is_vowel # common silent-e adjustment if w.endswith("e") and groups > 1: groups -= 1 return max(1, groups) @dataclass(frozen=True) class RadioTestResult: sld: str syllables: int length: int has_hyphen: bool has_digits: bool status: str # pass|warn|fail rationale: str def run_radio_test(domain: str) -> RadioTestResult: sld = (domain or "").split(".")[0].lower() length = len(sld) has_hyphen = "-" in sld has_digits = bool(re.search(r"\d", sld)) syllables = _count_syllables(sld) # Hard fails: ugly for radio + high typo risk if length >= 20 or has_hyphen or (has_digits and length > 4): return RadioTestResult( sld=sld, syllables=syllables, length=length, has_hyphen=has_hyphen, has_digits=has_digits, status="fail", rationale="Hard to say/spell on radio (length/hyphen/digits).", ) # Ideal: 2–3 syllables, 4–12 chars, no digits if 2 <= syllables <= 3 and 4 <= length <= 12 and not has_digits: return RadioTestResult( sld=sld, syllables=syllables, length=length, has_hyphen=has_hyphen, has_digits=has_digits, status="pass", rationale="Short, pronounceable, low spelling friction.", ) return RadioTestResult( sld=sld, syllables=syllables, length=length, has_hyphen=has_hyphen, has_digits=has_digits, status="warn", rationale="Usable, but not ideal (syllables/length/digits).", )