불면증 인지행동치료 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""불면증 인지행동치료 문서와 연습 문제의 수면 효율·수면제한 계산을 검증한다.

수면 효율(%) = 실제 수면 시간 / 침대에 누워 있는 시간 x 100
수면제한: 침대 시간을 평균 실제 수면 시간으로 줄이고(최소 300분),
기상 시각을 고정한 채 취침 시각을 뒤로 민다.
한 주 평균 효율이 85% 이상이면 침대 시간을 15분 늘린다.
"""


def efficiency(total_sleep_min: int, time_in_bed_min: int) -> float:
    return total_sleep_min / time_in_bed_min * 100


def restricted_window(avg_sleep_min: int, minimum: int = 300) -> int:
    return max(avg_sleep_min, minimum)


def next_window(window_min: int, eff: float) -> int:
    return window_min + 15 if eff >= 85 else window_min


def clock(minutes_after_midnight: int) -> str:
    m = minutes_after_midnight % (24 * 60)
    return f"{m // 60:02d}:{m % 60:02d}"


if __name__ == "__main__":
    # 100 예시(GW): 23:00~07:00 침대(480분), 잠들기까지 90분, 중간에 깬 시간 30분
    tib = 8 * 60
    tst = tib - 90 - 30
    e = efficiency(tst, tib)
    assert tst == 360 and round(e, 1) == 75.0, (tst, e)
    w = restricted_window(tst)
    wake = 7 * 60
    assert w == 360 and clock(wake - w) == "01:00"
    print(f"GW: 수면 {tst}분 / 침대 {tib}분 = {e:.1f}% -> 침대 {w}분, 취침 {clock(wake - w)}")

    # 한 주 뒤: 침대 360분 가운데 330분 잠 -> 91.7% -> 15분 늘려 00:45 취침
    e2 = efficiency(330, 360)
    w2 = next_window(360, e2)
    assert round(e2, 1) == 91.7 and w2 == 375 and clock(wake - w2) == "00:45"
    print(f"GW 1주 뒤: {e2:.1f}% -> 침대 {w2}분, 취침 {clock(wake - w2)}")

    # 연습 문제(GV): 22:30~07:00(510분), 잠들기까지 60분, 깬 시간 45분
    tib_v = 8 * 60 + 30
    tst_v = tib_v - 60 - 45
    e_v = efficiency(tst_v, tib_v)
    assert tst_v == 405 and round(e_v, 1) == 79.4, (tst_v, e_v)
    w_v = restricted_window(tst_v)
    assert w_v == 405 and clock(wake - w_v) == "00:15"
    print(f"GV: 수면 {tst_v}분 / 침대 {tib_v}분 = {e_v:.1f}% -> 침대 {w_v}분, 취침 {clock(wake - w_v)}")

    # 연습 문제 변형(GV 1주 뒤): 침대 405분 가운데 370분 잠 -> 91.4% -> 420분, 00:00 취침
    e_v2 = efficiency(370, 405)
    w_v2 = next_window(405, e_v2)
    assert round(e_v2, 1) == 91.4 and w_v2 == 420 and clock(wake - w_v2) == "00:00"
    print(f"GV 1주 뒤: {e_v2:.1f}% -> 침대 {w_v2}분, 취침 {clock(wake - w_v2)}")

    # 경계: 평균 수면이 4시간(240분)이어도 침대 시간은 최소 300분
    assert restricted_window(240) == 300
    # 경계: 효율이 정확히 85%면 늘리고, 84.9%면 유지
    assert next_window(360, 85.0) == 375 and next_window(360, 84.9) == 360
    print("경계 3개 통과")
    print("ALL CHECKS PASSED")