"""data.json から、同じ質問を何度も聞いたときの揺れを集計する。 python3 analyze.py"""
import collections
import itertools
import json
from math import comb
from pathlib import Path

data = json.loads((Path(__file__).parent / "data.json").read_text(encoding="utf-8"))


def central_range(p, n):
    """真の出現率が p のとき、n回聞いた観測割合の95%が収まる範囲（二項分布）。"""
    lo = hi = None
    cum = 0.0
    for k in range(n + 1):
        cum += comb(n, k) * p**k * (1 - p) ** (n - k)
        if lo is None and cum >= 0.025:
            lo = k / n
        if hi is None and cum >= 0.975:
            hi = k / n
    return lo, hi


if __name__ == "__main__":
    for name, cond in data["conditions"].items():
        all_lists = [r["canon"] for r in cond["runs"]]
        lists = [l for l in all_lists if l]  # 製品を挙げなかった回（断り）は集計から外す
        n = len(lists)
        pairs = list(itertools.combinations(range(n), 2))
        same_set = sum(set(lists[a]) == set(lists[b]) for a, b in pairs)
        same_order = sum(lists[a] == lists[b] for a, b in pairs)
        share = collections.Counter(x for l in lists for x in set(l))
        top1 = collections.Counter(l[0] for l in lists).most_common(1)[0]
        kinds = [len({l[i] for l in lists if len(l) > i}) for i in range(len(lists[0]))]
        print(f"== {name} ({cond['model']}, tools={cond['tools']}) n={n}（製品を挙げなかった回 {len(all_lists) - n}）")
        print(f"  並びの種類={len({tuple(l) for l in lists})} 顔ぶれの種類={len({frozenset(l) for l in lists})}")
        print(f"  2回を選んで 同じ顔ぶれ={same_set/len(pairs):.1%} 同じ順序={same_order/len(pairs):.1%}")
        print(f"  1位の最頻={top1[0]} {top1[1]}/{n} 各順位の製品の種類={kinds}")
        for k, v in share.most_common(10):
            print(f"    {v}/{n} {k}")
    # 何回聞けば安定するか（勤怠管理・Sonnet 5.5 の AKASHI）
    runs = data["conditions"]["s5_q4"]["runs"]
    p = sum("AKASHI" in r["canon"] for r in runs) / len(runs)
    print(f"\nAKASHI の出現率 {p:.1%}（{len(runs)}回）。真の率がこれと同じとして、n回聞いたときの95%範囲")
    for n in (1, 3, 5, 10, 20, 40, 100):
        lo, hi = central_range(p, n)
        print(f"  n={n}: {lo:.0%}〜{hi:.0%}")
