"""blinded paired pairwise 집계 수학. 실질 arm 관점: pair 의 첫 arm = "first", 둘째 = "second". forward orientation 은 X=첫 arm, reversed 는 X=둘째 arm(뒤집힘). 단순평균 금지 — 순위 기반.""" from collections import Counter def normalize(orientation, winner): """judge 의 X/Y 승자를 실질 arm 관점(first/second)으로 정규화. tie 는 그대로 tie.""" if winner == "tie": return "tie" if orientation == "forward": return "first" if winner == "X" else "second" return "second" if winner == "X" else "first" # reversed: X=둘째 arm def stable(fwd_real, rev_real): """두 orientation 이 같은 실질 승자를 판정하는가.""" return fwd_real == rev_real def preference_score(wins, ties, valid_stable): """(wins + 0.5*ties) / valid_stable. arm 의 우호도.""" if valid_stable <= 0: return 0.0 return (wins + 0.5 * ties) / valid_stable def panel_agreement(stable_verdicts): """최빈 판정이 차지하는 비중. 0.0 if empty.""" if not stable_verdicts: return 0.0 top = Counter(stable_verdicts).most_common(1)[0][1] return top / len(stable_verdicts) def flip_consistency(paired): """paired: [{fwd, rev}...] 각 실질 arm 관점. fwd==rev 면 flip 일관성 유지.""" if not paired: return 0.0 ok = sum(1 for p in paired if p["fwd"] == p["rev"]) return ok / len(paired) def panel_verdict(stable_verdicts): """panel 의 최종 판정. unstable = 투표 일관성 부족.""" if len(stable_verdicts) < 2: return "unstable" verdict, cnt = Counter(stable_verdicts).most_common(1)[0] return verdict if cnt >= 2 else "unstable"