Gabungkan aplikasi RPS & Portofolio OBE (dashboard jadi bagian aplikasi)
Dashboard pemetaan statis kini dilayani aplikasi di /dashboard (app/static/dashboard.html). Fitur lengkap Tahap 1-4 + dasbor monitoring, menu global, filter semester, input nilai langsung, penggabungan nilai team teaching, tabel bisa urut. Dockerfile berubah dari nginx statis ke uvicorn/FastAPI: healthcheck, proxy-headers, volume /data (SQLite). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Ekstrak data kurikulum (CPL, CPMK, MK, Sub-CPMK, matriks) yang ter-embed di
|
||||
dashboard pemetaan, lalu simpan sebagai seed/kurikulum.json.
|
||||
|
||||
Jalankan ulang bila data dashboard diperbarui:
|
||||
python tools/extract_seed.py [path_index_html]
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
BASE = pathlib.Path(__file__).resolve().parent.parent
|
||||
DEFAULT_SRC = BASE.parent / "dashboard-deploy" / "index.html"
|
||||
OUT = BASE / "seed" / "kurikulum.json"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
src = pathlib.Path(sys.argv[1]) if len(sys.argv) > 1 else DEFAULT_SRC
|
||||
html = src.read_text(encoding="utf-8")
|
||||
i = html.find('{"cpl"')
|
||||
if i < 0:
|
||||
raise SystemExit(f"Blok JSON kurikulum tidak ditemukan di {src}")
|
||||
data, _ = json.JSONDecoder().raw_decode(html[i:])
|
||||
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT.write_text(json.dumps(data, ensure_ascii=False, indent=1), encoding="utf-8")
|
||||
|
||||
n_sub = sum(
|
||||
len(c["subs"]) for mk in data["sub"].values() for c in mk["cpmks"].values()
|
||||
)
|
||||
print(
|
||||
f"[OK] {OUT.name}: {len(data['cpl'])} CPL, {len(data['cpmk'])} CPMK, "
|
||||
f"{len(data['mk'])} MK, {n_sub} Sub-CPMK (sumber: {src})"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Ekstrak SKS + semester per MK dari sheet '14. Susunan MK' spreadsheet kurikulum
|
||||
→ seed/sks.json ({kode: {"sks": x, "semester": n}}).
|
||||
SKS dipakai untuk opsi roll-up tertimbang SKS; semester untuk prefill form RPS.
|
||||
|
||||
Jalankan: python tools/extract_sks.py [path_xlsx]
|
||||
"""
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
import openpyxl
|
||||
|
||||
BASE = pathlib.Path(__file__).resolve().parent.parent
|
||||
DEFAULT_SRC = BASE.parent / "Draft Kurikulum Terbaru 2025.xlsx"
|
||||
OUT = BASE / "seed" / "sks.json"
|
||||
SHEET = "14. Susunan MK"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
src = pathlib.Path(sys.argv[1]) if len(sys.argv) > 1 else DEFAULT_SRC
|
||||
kur = json.loads((BASE / "seed" / "kurikulum.json").read_text(encoding="utf-8"))
|
||||
kode_valid = set(kur["mk"].keys())
|
||||
|
||||
wb = openpyxl.load_workbook(src, read_only=True, data_only=True)
|
||||
ws = wb[SHEET]
|
||||
rows = [list(r) for r in ws.iter_rows(values_only=True)]
|
||||
|
||||
# baris header: memuat 'Kode MK' dan 'SKS'
|
||||
header_i = next(i for i, r in enumerate(rows)
|
||||
if any(str(v).strip() == "Kode MK" for v in r if v))
|
||||
header = [str(v).strip() if v is not None else "" for v in rows[header_i]]
|
||||
i_kode = header.index("Kode MK")
|
||||
i_sks = header.index("SKS")
|
||||
kolom_smt = {ci: int(h) for ci, h in enumerate(header) if h.isdigit()}
|
||||
|
||||
data = {}
|
||||
for r in rows[header_i + 1:]:
|
||||
if i_kode >= len(r) or not isinstance(r[i_kode], str):
|
||||
continue
|
||||
kode = r[i_kode].strip()
|
||||
if kode not in kode_valid:
|
||||
continue
|
||||
try:
|
||||
sks = float(r[i_sks])
|
||||
except (TypeError, ValueError, IndexError):
|
||||
continue
|
||||
semester = next((smt for ci, smt in kolom_smt.items()
|
||||
if ci < len(r) and r[ci] not in (None, "")), None)
|
||||
data[kode] = {"sks": sks, "semester": semester}
|
||||
|
||||
OUT.write_text(json.dumps(data, ensure_ascii=False, indent=1), encoding="utf-8")
|
||||
hilang = sorted(kode_valid - set(data))
|
||||
print(f"[OK] {OUT.name}: SKS untuk {len(data)}/{len(kode_valid)} MK "
|
||||
f"(total SKS: {sum(v['sks'] for v in data.values()):g})")
|
||||
if hilang:
|
||||
print(" tanpa SKS:", ", ".join(hilang))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user