# -*- coding: utf-8 -*-
r"""브리프 07 — 1기 신도시가 30년을 넘었다 (2015~2025)

    py prep.py

★ 분모 이야기를 먼저 (이 브리프의 방법 전부가 여기 걸려 있다)

  쓰는 표 DT_1JU1521 은 건축 경과연수 축에 **「20년~30년 미만」과 「30년 이상」 두 칸뿐**이다.
  「계」가 없다. 그래서 **「전체 주택 중 노후 비율」을 이 표만으로는 못 낸다.**

  분모표 후보(DT_1JU1502 「주택_계」)를 찾긴 했다. 계산해 보면 안산 59.8% 처럼
  그럴듯한 값도 나온다. **그런데 쓰지 않았다** — 분모는 「미거주 주택(빈집) 제외」인데
  분자가 빈집을 포함하는지 **표 안에서 확인할 방법이 없다**(분자에 「계」가 없으므로).
  정의가 어긋난 채 비율을 내면 그럴듯하게 틀린 숫자가 나온다. 관문 C1 이 요구하는
  「원문에서 직접 확인」을 못 한 상태라 그 길을 접었다.

  → 대신 **같은 표 안의 두 칸으로만** 비율을 만든다:
       30년 이상 ÷ (20년~30년 미만 + 30년 이상)
    분자·분모가 같은 표·같은 정의라 어긋날 여지가 없다.
    ★ 다만 이 값은 「전체 주택 중 노후 비율」이 **아니다.**
      「20년 넘은 주택 중 30년을 넘긴 것의 비중」이다. 본문에서 그렇게만 말한다.
"""
import csv, sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
import kosis

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
# ⛔ 그림 저장은 정본(`chartkit.save`)을 지난다 〔2026-09-21〕 — 그래야
#   ⑴ 폰용 그림이 같이 나가고(`analysis/폰/`) ⑵ 「폰에서 읽히나」 관문이 돈다.
#   `plt.savefig` 를 직접 부르면 그 둘이 통째로 꺼진다.
import chartkit as ck

try:
    sys.stdout.reconfigure(encoding="utf-8")
except Exception:
    pass

plt.rcParams["font.family"] = ["Malgun Gothic", "sans-serif"]
plt.rcParams["axes.unicode_minus"] = False

ORG, TBL, ITM = "101", "DT_1JU1521", "T00"
Y0, Y1 = "2015", "2025"
B20, B30 = "20년~30년 미만", "30년 이상"
# 1기 신도시 (1991~1996 입주) 가 있는 시. 분당=성남 · 일산=고양 · 평촌=안양 · 중동=부천 · 산본=군포
신도시 = ["성남시", "고양시", "안양시", "부천시", "군포시"]
C_NEW, C_ETC, C_HL = "#c8482a", "#c9d1d9", "#2f6fb5"

m = kosis.meta(ORG, TBL)["SGG"]
시군 = [n for c, n in m.items()
       if c.startswith("31") and len(c) == 5 and (n.endswith("시") or n.endswith("군")) and n != "여주군"]
rec = kosis.fetch_rows(ORG, TBL, (Y0, Y1), sel={"SGG": 시군, "B": [B20, B30]},
                       prefix={"SGG": "31"}, itm=ITM)
d = {}
for r in rec:
    d.setdefault(r["연도"], {}).setdefault(r["SGG"], {})[r["B"]] = r["값"]
print(f"[대장] 원문위치(지역) → {kosis.cite(ORG, TBL, 'SGG', ['성남시'], '31')}")
print(f"[대장] 원문위치(연수) → {kosis.cite(ORG, TBL, 'B', [B20, B30], None)}")

def share(y, nm):
    a = d[y][nm]
    return 100 * a[B30] / (a[B20] + a[B30])

rows = []
for y in sorted(d):
    for nm in 시군:
        a = d[y][nm]
        rows.append({"연도": y, "시군": nm, "이십년대": a[B20], "삼십년이상": a[B30],
                     "삼십년비중": round(share(y, nm), 2),
                     "신도시": 1 if nm in 신도시 else 0})
with open("raw.csv", "w", encoding="utf-8-sig", newline="") as f:
    w = csv.DictWriter(f, fieldnames=["연도", "시군", "이십년대", "삼십년이상", "삼십년비중", "신도시"])
    w.writeheader(); w.writerows(rows)

order = sorted(시군, key=lambda n: share(Y1, n) - share(Y0, n))

# ── 차트(웹) ── 10년 사이 얼마나 움직였나. 화살표가 이야기다.
fig, ax = plt.subplots(figsize=(7.6, 9.2))
for i, nm in enumerate(order):
    a, b = share(Y0, nm), share(Y1, nm)
    c = C_NEW if nm in 신도시 else C_ETC
    ax.plot([a, b], [i, i], color=c, lw=3.2, solid_capstyle="round", zorder=2)
    ax.scatter([b], [i], s=46, color=c, zorder=3)
    ax.scatter([a], [i], s=22, color="#ffffff", edgecolor=c, lw=1.6, zorder=3)
ax.set_yticks(range(len(order)))
ax.set_yticklabels([f"{n}" for n in order], fontsize=10.5)
for i, nm in enumerate(order):
    if nm in 신도시:
        ax.get_yticklabels()[i].set_color(C_NEW)
        ax.get_yticklabels()[i].set_fontweight("bold")
ax.set_xlabel("20년 넘은 주택 중 30년을 넘긴 것의 비중 (%)", fontsize=10.5)
ax.set_title("10년 사이 어디가 가장 빨리 늙었나\n"
             f"빈 점 {Y0} → 채운 점 {Y1} · 붉은색이 1기 신도시가 있는 5개 시",
             fontsize=12.5, fontweight="bold", loc="left", pad=14)
ax.grid(axis="x", color="#eef0f4", lw=.8)
ax.set_axisbelow(True)
for s in ("top", "right", "left"):
    ax.spines[s].set_visible(False)
ax.spines["bottom"].set_color("#cfd4de")
fig.tight_layout()
ck.save(fig, "chart.png", dpi=130)
plt.close(fig)

# ── 카드 ── 폰. 상위 8곳만.
top = sorted(시군, key=lambda n: -(share(Y1, n) - share(Y0, n)))[:8][::-1]
fig, ax = plt.subplots(figsize=(8.4, 6.4))
ys = range(len(top))
ax.barh(list(ys), [share(Y1, n) - share(Y0, n) for n in top],
        color=[C_NEW if n in 신도시 else C_ETC for n in top], height=.66)
ax.set_yticks(list(ys)); ax.set_yticklabels(top, fontsize=13)
for i, n in enumerate(top):
    v = share(Y1, n) - share(Y0, n)
    ax.text(v + 1.2, i, f"+{v:.0f}p", va="center", fontsize=12.5, fontweight="bold",
            color=C_NEW if n in 신도시 else "#5a6672")
ax.set_title("10년 만에 늙은 도시 — 30년 넘은 주택 비중 변화", fontsize=16,
             fontweight="bold", loc="left", pad=12)
ax.set_xlim(0, max(share(Y1, n) - share(Y0, n) for n in top) * 1.18)
for s in ("top", "right", "left", "bottom"):
    ax.spines[s].set_visible(False)
ax.set_xticks([])
fig.tight_layout()
fig.savefig("chart_card.png", dpi=130)
plt.close(fig)

print(f"[저장] raw.csv {len(rows)}행 · chart.png · chart_card.png")

print("\n[대장] 수치대장.csv 에 옮길 값 ─────────────────")
print(f"  시군수                  {len(시군)}")
for nm in ["성남시", "군포시", "광명시", "안양시", "부천시", "고양시", "과천시", "안산시"]:
    # ★ raw.csv 에 저장하는 정밀도(소수 2자리)와 **똑같이** 찍는다.
    #   1자리로 찍으면 그걸 그대로 대장에 옮긴 사람이 C2 에서 걸린다 —
    #   군포 2015 는 3.35 인데 "3.3" 으로 옮겨져 재계산과 0.05 차이가 났다 (2026-08-06 실제).
    print(f"  삼십년비중_{nm:<6} {Y0} {share(Y0,nm):6.2f} % → {Y1} {share(Y1,nm):6.2f} %  (변화 {share(Y1,nm)-share(Y0,nm):+.2f}p)")
print(f"  삼십년이상호수_성남_{Y1}  {d[Y1]['성남시'][B30]:,}")
print(f"  이십년대호수_성남_{Y1}    {d[Y1]['성남시'][B20]:,}")
import statistics
print(f"  시군평균비중_{Y1}         {statistics.mean(share(Y1,n) for n in 시군):.1f} %")
print(f"  최고_{Y1}               {max(시군, key=lambda n: share(Y1,n))} {max(share(Y1,n) for n in 시군):.1f} %")
print(f"  최저_{Y1}               {min(시군, key=lambda n: share(Y1,n))} {min(share(Y1,n) for n in 시군):.1f} %")
print(f"  신도시5곳평균변화         {statistics.mean(share(Y1,n)-share(Y0,n) for n in 신도시):+.1f} p")
print(f"  나머지평균변화           {statistics.mean(share(Y1,n)-share(Y0,n) for n in 시군 if n not in 신도시):+.1f} p")
