Untitled
unknown
plain_text
9 months ago
6.4 kB
12
Indexable
# Membuat infografis A3 (PNG) dan mindmap (PNG) berdasarkan kasus Champlain Towers South (Surfside, 2021).
# File akan disimpan di /mnt/data dan link akan diberikan setelah eksekusi.
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt
import textwrap
import os
# Siapkan folder output
out_dir = "/mnt/data"
os.makedirs(out_dir, exist_ok=True)
# Fungsi bantu untuk menulis teks dengan wrapping pada PIL ImageDraw
def draw_wrapped_text(draw, text, x, y, max_width, font, line_spacing=4):
lines = []
for paragraph in text.split("\n"):
wrapped = textwrap.wrap(paragraph, width= max_width)
if not wrapped:
lines.append("")
else:
lines.extend(wrapped)
for i, line in enumerate(lines):
draw.text((x, y + i*(font.getsize(line)[1]+line_spacing)), line, font=font, fill=(0,0,0))
return y + len(lines)*(font.getsize("Ay")[1]+line_spacing)
# Load default font (a fallback)
try:
font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 56)
font_h = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 36)
font_text = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 22)
font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 18)
except:
font_title = ImageFont.load_default()
font_h = ImageFont.load_default()
font_text = ImageFont.load_default()
font_small = ImageFont.load_default()
# 1) Infografis A3 (landscape) - ukuran A3 in inches 16.5 x 11.7. We'll use 300 DPI.
dpi = 300
width_in, height_in = 16.5, 11.7
W, H = int(width_in * dpi), int(height_in * dpi)
img = Image.new("RGB", (W, H), color=(255,255,255))
draw = ImageDraw.Draw(img)
# Judul
draw.text((80,40), "Infografis: Runtuhnya Champlain Towers South (Surfside, 2021)", font=font_title, fill=(0,0,0))
# Subtitle & fakta cepat
y = 140
draw.text((80,y), "Fakta Singkat", font=font_h, fill=(0,0,0))
y += 50
facts = [
"Tanggal: 24 Juni 2021",
"Lokasi: Surfside, Florida, AS",
"Korban: 98 orang tewas (parsial collapse)",
"Jenis bangunan: Kondominium 12 lantai (dibangun ~1980)",
]
for f in facts:
draw.text((100,y), "• " + f, font=font_text, fill=(0,0,0))
y += 34
# Penyebab utama (ringkasan)
y += 10
draw.text((80,y), "Temuan Teknis (ringkas)", font=font_h)
y += 48
cause_text = ("- Bukti korosi tulangan, pelapukan beton, dan overlapping/beban yang tidak sesuai pada kolom/plat.\n"
"- Area asal kegagalan kemungkinan: pool deck / slab-to-column connection yang lalu berkembang ke parkiran dan menimbulkan runtuhan progresif.\n"
"- Tanda-tanda distress terlihat minggu-minggu sebelum runtuh (kebocoran air, retak yang memburuk).\n"
"- Kombinasi kelemahan konstruksi, perawatan yang tidak memadai, dan kerusakan lingkungan (air laut).")
draw_wrapped_text(draw, cause_text, 100, y, max_width=110, font=font_text)
y += 220
# Timeline singkat (kanan)
tx = W//2 + 40
ty = 140
draw.text((tx,ty), "Timeline & Investigasi", font=font_h)
ty += 48
timeline = ("24 Jun 2021: Runtuh sebagian. \n"
"25 Jun 2021: NIST kirim tim investigasi NCST. \n"
"2022-2024: Laporan-laporan teknis, analisis forensik independen (WJE, dsb.). \n"
"2023: Update NIST — fokus pada pool deck dan slab-column connections. \n"
"2024-2025: Analisis lanjutan, simulasi progresif, rekomendasi kode dan inspeksi.")
draw_wrapped_text(draw, timeline, tx, ty, max_width=110, font=font_text)
ty += 190
# Rekomendasi praktis (kanan bawah)
draw.text((tx, ty), "Rekomendasi Teknik & Manajemen", font=font_h)
ty += 48
reco = ("1. Inspeksi milestone ketat (30-tahun + interval lanjutan).\n"
"2. Fokus pada area basah / pool & parkir: cek korosi, sambungan, pelapukan beton.\n"
"3. Perawatan keluaran air/drainase dan waterproofing.\n"
"4. Documentasi perbaikan struktural dan review engineering independen sebelum perbaikan besar.\n"
"5. Perbaikan kebijakan pemeriksaan dan pemantauan jangka panjang.")
draw_wrapped_text(draw, reco, tx, ty, max_width=110, font=font_text)
# Footer - sumber (ringkas)
footer_y = H - 200
draw.line([(60, footer_y-10), (W-60, footer_y-10)], fill=(0,0,0))
draw.text((80, footer_y), "Sumber (ringkas): NIST NCST updates (2023), WJE forensic analysis (2022-2025), ASCE reviews (2024), penelitian journal (2022).", font=font_small)
draw.text((80, footer_y+36), "Grafis dibuat oleh ChatGPT untuk keperluan edukasi. Untuk referensi lengkap, lihat daftar referensi yang disertakan.", font=font_small)
infografis_path = os.path.join(out_dir, "infografis_champlain_A3.png")
img.save(infografis_path, dpi=(dpi,dpi))
# 2) Mindmap - peran teknik sipil dari kasus tersebut
# Buat mindmap sederhana menggunakan matplotlib (nodes + lines)
import networkx as nx
G = nx.DiGraph()
root = "Kasus Champlain Towers South"
roles = [
("Insinyur Struktur", ["Analisis forensik", "Desain perbaikan", "Verifikasi kapasitas"]),
("Insinyur Geoteknik", ["Penyelidikan fondasi", "Subsidence / settlement analysis"]),
("Insinyur Material", ["Uji korosi tulangan", "Uji kekuatan beton", "Evaluasi degradasi"]),
("Insinyur Pemeliharaan", ["Jadwal inspeksi", "Perbaikan waterproofing", "Drainase"]),
("Pengawas Lapangan", ["Kontrol kualitas konstruksi", "Pengawasan perbaikan"]),
("Regulator / Pemeriksa", ["Sertifikasi inspeksi", "Perubahan kebijakan inspeksi"]),
("Konsultan Forensik", ["Rekonstruksi kejadian", "Laporan hukum dan asuransi"]),
]
G.add_node(root)
for role, tasks in roles:
G.add_node(role)
G.add_edge(root, role)
for t in tasks:
G.add_node(t)
G.add_edge(role, t)
plt.figure(figsize=(11,8))
pos = nx.spring_layout(G, seed=42, k=0.9)
nx.draw_networkx_nodes(G, pos, node_size=1200)
nx.draw_networkx_labels(G, pos, font_size=9)
nx.draw_networkx_edges(G, pos, arrows=True)
plt.axis('off')
mindmap_path = os.path.join(out_dir, "mindmap_peran_teknik_sipil.png")
plt.savefig(mindmap_path, dpi=200, bbox_inches='tight')
plt.close()
# Selesai, tampilkan paths sebagai output yang user bisa download
print(f"Infografis A3 disimpan: file://{infografis_path}")
print(f"Mindmap peran teknik sipil disimpan: file://{mindmap_path}")Editor is loading...
Leave a Comment