import re, string _POS = {"great", "awesome", "fantastic", "good", "excellent", "optimal", "stable", "secure"} _NEG = {"bad", "terrible", "awful", "hate", "horrible", "angry", "frustrated", "error", "fail"} _HIGH_AROUSAL = {"!", "!!", "!!!"} _LOW_AROUSAL = {"...", "…"} def _clean(text: str) -> str: return text.translate(str.maketrans("", "", string.punctuation)).lower() def extract_affect(text: str) -> tuple[float, float]: tokens = set(_clean(text).split()) pos = len(tokens & _POS) neg = len(tokens & _NEG) sentiment = 0.0 if pos == neg == 0 else (pos - neg) / max(pos + neg, 1) valence = (sentiment + 1) / 2 arousal = 0.5 if any(p in text for p in _HIGH_AROUSAL): arousal = 0.9 elif any(p in text for p in _LOW_AROUSAL): arousal = 0.2 return round(valence, 3), round(arousal, 3)