Update app.py
Browse files
app.py
CHANGED
|
@@ -1560,76 +1560,87 @@ ATURAN:
|
|
| 1560 |
except Exception as e:
|
| 1561 |
return f"⚠️ Error saat memanggil LLM: {repr(e)}"
|
| 1562 |
|
| 1563 |
-
def generate_word_report(wilayah
|
| 1564 |
doc = Document()
|
| 1565 |
doc.add_heading(f"Laporan IPLM — {wilayah}", level=1)
|
| 1566 |
|
|
|
|
|
|
|
|
|
|
| 1567 |
doc.add_heading("Ringkasan Dashboard", level=2)
|
|
|
|
| 1568 |
k = compute_dashboard_kpis(summary_jenis)
|
| 1569 |
-
doc.add_paragraph(
|
| 1570 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1571 |
|
|
|
|
|
|
|
|
|
|
| 1572 |
doc.add_heading("Ringkasan (Jenis + Keseluruhan)", level=2)
|
| 1573 |
-
show = summary_jenis.copy()
|
| 1574 |
-
preferred = [
|
| 1575 |
-
"Jenis","Jumlah_Wilayah","Total_Perpus",
|
| 1576 |
-
"Pop_Total_Jenis","Target68_Total_Jenis","Terkumpul_Jenis","Coverage_Target68_Jenis_%",
|
| 1577 |
-
"Indeks_Dasar_0_100","Indeks_Final_Disesuaikan_0_100","Penyesuaian_Poin"
|
| 1578 |
-
]
|
| 1579 |
-
show = show[[c for c in preferred if c in show.columns]]
|
| 1580 |
|
| 1581 |
-
|
| 1582 |
-
|
| 1583 |
-
|
| 1584 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1585 |
|
| 1586 |
-
|
| 1587 |
-
|
| 1588 |
for i, c in enumerate(show.columns):
|
| 1589 |
-
|
| 1590 |
-
|
| 1591 |
-
|
| 1592 |
-
|
| 1593 |
-
|
| 1594 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1595 |
else:
|
| 1596 |
-
cells[i].text =
|
| 1597 |
-
elif isinstance(v, (int, np.integer)):
|
| 1598 |
-
cells[i].text = str(int(v))
|
| 1599 |
-
else:
|
| 1600 |
-
cells[i].text = str(v)
|
| 1601 |
|
| 1602 |
-
|
| 1603 |
-
|
| 1604 |
-
|
| 1605 |
-
|
| 1606 |
-
h2 = t2.rows[0].cells
|
| 1607 |
-
for i, c in enumerate(cols):
|
| 1608 |
-
h2[i].text = str(c)
|
| 1609 |
-
|
| 1610 |
-
for _, r in agg_total.head(50).iterrows():
|
| 1611 |
-
rr = t2.add_row().cells
|
| 1612 |
-
for i, c in enumerate(cols):
|
| 1613 |
-
vv = r[c]
|
| 1614 |
-
if pd.isna(vv):
|
| 1615 |
-
rr[i].text = ""
|
| 1616 |
-
elif isinstance(vv, (float, np.floating)):
|
| 1617 |
-
rr[i].text = f"{float(vv):.2f}"
|
| 1618 |
-
elif isinstance(vv, (int, np.integer)):
|
| 1619 |
-
rr[i].text = str(int(vv))
|
| 1620 |
-
else:
|
| 1621 |
-
rr[i].text = str(vv)
|
| 1622 |
|
| 1623 |
-
|
| 1624 |
-
|
| 1625 |
-
|
| 1626 |
-
|
|
|
|
|
|
|
| 1627 |
|
| 1628 |
outpath = tempfile.mktemp(suffix=".docx")
|
| 1629 |
doc.save(outpath)
|
| 1630 |
return outpath
|
| 1631 |
|
| 1632 |
-
|
| 1633 |
# ============================================================
|
| 1634 |
# 15) CORE RUN
|
| 1635 |
# ============================================================
|
|
|
|
| 1560 |
except Exception as e:
|
| 1561 |
return f"⚠️ Error saat memanggil LLM: {repr(e)}"
|
| 1562 |
|
| 1563 |
+
def generate_word_report(wilayah, summary_jenis, agg_total, agg_jenis, analysis_text):
|
| 1564 |
doc = Document()
|
| 1565 |
doc.add_heading(f"Laporan IPLM — {wilayah}", level=1)
|
| 1566 |
|
| 1567 |
+
# =========================
|
| 1568 |
+
# Ringkasan Dashboard (KPI utama)
|
| 1569 |
+
# =========================
|
| 1570 |
doc.add_heading("Ringkasan Dashboard", level=2)
|
| 1571 |
+
|
| 1572 |
k = compute_dashboard_kpis(summary_jenis)
|
| 1573 |
+
doc.add_paragraph(
|
| 1574 |
+
f"Indeks IPLM FINAL (Disesuaikan): {k['final_all']:.2f} "
|
| 1575 |
+
f"(rata-rata 3 jenis: sekolah, umum, khusus; tetap ÷3)"
|
| 1576 |
+
)
|
| 1577 |
+
doc.add_paragraph(
|
| 1578 |
+
f"Indeks Dasar (Tanpa Penyesuaian): {k['dasar_all']:.2f} "
|
| 1579 |
+
f"(rata-rata 3 jenis; tetap ÷3)"
|
| 1580 |
+
)
|
| 1581 |
|
| 1582 |
+
# =========================
|
| 1583 |
+
# Ringkasan (Jenis + Keseluruhan)
|
| 1584 |
+
# =========================
|
| 1585 |
doc.add_heading("Ringkasan (Jenis + Keseluruhan)", level=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1586 |
|
| 1587 |
+
if summary_jenis is not None and not summary_jenis.empty:
|
| 1588 |
+
show = summary_jenis.copy()
|
| 1589 |
+
|
| 1590 |
+
preferred = [
|
| 1591 |
+
"Jenis",
|
| 1592 |
+
"Jumlah_Wilayah",
|
| 1593 |
+
"Total_Perpus",
|
| 1594 |
+
"Pop_Total_Jenis",
|
| 1595 |
+
"Target68_Total_Jenis",
|
| 1596 |
+
"Terkumpul_Jenis",
|
| 1597 |
+
"Coverage_Target68_Jenis_%",
|
| 1598 |
+
"Indeks_Dasar_0_100",
|
| 1599 |
+
"Indeks_Final_Disesuaikan_0_100",
|
| 1600 |
+
"Penyesuaian_Poin",
|
| 1601 |
+
]
|
| 1602 |
+
cols = [c for c in preferred if c in show.columns]
|
| 1603 |
+
show = show[cols].copy()
|
| 1604 |
|
| 1605 |
+
table = doc.add_table(rows=1, cols=len(show.columns))
|
| 1606 |
+
hdr = table.rows[0].cells
|
| 1607 |
for i, c in enumerate(show.columns):
|
| 1608 |
+
hdr[i].text = str(c)
|
| 1609 |
+
|
| 1610 |
+
for _, row in show.iterrows():
|
| 1611 |
+
cells = table.add_row().cells
|
| 1612 |
+
for i, c in enumerate(show.columns):
|
| 1613 |
+
v = row[c]
|
| 1614 |
+
if pd.isna(v):
|
| 1615 |
+
cells[i].text = ""
|
| 1616 |
+
elif isinstance(v, (float, np.floating)):
|
| 1617 |
+
if "Coverage" in c:
|
| 1618 |
+
cells[i].text = f"{float(v):.2f}"
|
| 1619 |
+
elif "Indeks" in c or "Penyesuaian" in c:
|
| 1620 |
+
cells[i].text = f"{float(v):.2f}"
|
| 1621 |
+
else:
|
| 1622 |
+
cells[i].text = f"{float(v):.0f}"
|
| 1623 |
+
elif isinstance(v, (int, np.integer)):
|
| 1624 |
+
cells[i].text = str(int(v))
|
| 1625 |
else:
|
| 1626 |
+
cells[i].text = str(v)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1627 |
|
| 1628 |
+
# =========================
|
| 1629 |
+
# Analisis Naratif (LLM)
|
| 1630 |
+
# =========================
|
| 1631 |
+
doc.add_heading("Analisis Naratif", level=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1632 |
|
| 1633 |
+
if analysis_text:
|
| 1634 |
+
for p in str(analysis_text).split("\n"):
|
| 1635 |
+
if p.strip():
|
| 1636 |
+
doc.add_paragraph(p.strip())
|
| 1637 |
+
else:
|
| 1638 |
+
doc.add_paragraph("Analisis tidak tersedia.")
|
| 1639 |
|
| 1640 |
outpath = tempfile.mktemp(suffix=".docx")
|
| 1641 |
doc.save(outpath)
|
| 1642 |
return outpath
|
| 1643 |
|
|
|
|
| 1644 |
# ============================================================
|
| 1645 |
# 15) CORE RUN
|
| 1646 |
# ============================================================
|