Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
Adds HUNT (Sniper/Trend/Forge), CFO dashboard (burn rate + kill list), and a plugin-based Analyze side panel with caching and SSRF hardening.
92 lines
2.3 KiB
Python
92 lines
2.3 KiB
Python
"""
|
||
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).",
|
||
)
|
||
|