"""laporan_lengkap.py -- laporan statistik nilai ujian satu kelas.

Dataset: nilai ujian 30 siswa untuk tiga mata pelajaran.
Seluruh perhitungan memakai data yang melekat pada skrip ini,
sehingga laporan dapat direproduksi kapan saja tanpa berkas lain.
"""

import statistics

from scipy.stats import skew

DATA = [
    ("Adi", 70, 78, 88), ("Bunga", 88, 70, 60), ("Cakra", 76, 91, 93),
    ("Dewi", 80, 84, 73), ("Eka", 65, 67, 70), ("Fajar", 84, 82, 78),
    ("Gilang", 92, 74, 64), ("Hana", 68, 89, 90), ("Intan", 78, 76, 75),
    ("Joko", 86, 80, 83), ("Kirana", 73, 86, 58), ("Lukman", 62, 64, 71),
    ("Maya", 82, 93, 68), ("Nadia", 45, 72, 76), ("Okta", 90, 88, 92),
    ("Putri", 66, 75, 65), ("Qori", 77, 81, 74), ("Rafi", 81, 68, 79),
    ("Sari", 60, 95, 62), ("Tirta", 79, 77, 72), ("Utami", 74, 69, 85),
    ("Vina", 87, 85, 67), ("Wahyu", 67, 73, 77), ("Yuni", 76, 90, 70),
    ("Zaki", 83, 80, 81), ("Bagas", 69, 87, 59), ("Citra", 75, 71, 86),
    ("Danu", 64, 92, 74), ("Eni", 72, 83, 63), ("Filda", 85, 80, 82),
]
MAPEL = [("matematika", 1), ("bahasa", 2), ("sains", 3)]


def nilai_kolom(kolom):
    return [baris[kolom] for baris in DATA]


def deteksi_outlier(kolom):
    """Kembalikan daftar (nama, nilai, z) dengan |z| > 2 (std sampel)."""
    nilai = nilai_kolom(kolom)
    mean = statistics.mean(nilai)
    s = statistics.stdev(nilai)
    hasil = []
    for baris, x in zip(DATA, nilai):
        z = (x - mean) / s
        if abs(z) > 2:
            hasil.append((baris[0], x, z))
    return hasil


print("LAPORAN NILAI UJIAN - 30 SISWA, 3 MATA PELAJARAN")
print("=" * 48)
print(f"{'mapel':<11}{'mean':>7}{'median':>8}{'modus':>10}{'std':>7}{'min':>4}{'max':>4}{'skew':>7}")
for nama, kolom in MAPEL:
    nilai = nilai_kolom(kolom)
    print(f"{nama:<11}{statistics.mean(nilai):>7.2f}{statistics.median(nilai):>8.1f}"
          f"{str(statistics.multimode(nilai)):>10}{statistics.stdev(nilai):>7.2f}"
          f"{min(nilai):>4}{max(nilai):>4}{skew(nilai):>7.2f}")

print()
print("Deteksi outlier (|z| > 2, std sampel):")
for nama, kolom in MAPEL:
    out = deteksi_outlier(kolom)
    if out:
        for siswa, x, z in out:
            print(f"  {nama:<10s}: {siswa}, nilai {x}, z = {z:.2f}")
    else:
        print(f"  {nama:<10s}: tidak ada")

mat = nilai_kolom(1)
bah = nilai_kolom(2)
sai = nilai_kolom(3)
mean_penuh = statistics.mean(mat)
mean_tanpa = statistics.mean([x for x in mat if x != 45])
print()
print("Catatan mean vs median:")
print(f"  matematika: mean {mean_penuh:.2f}, median {statistics.median(mat):.1f};")
print(f"  tanpa nilai 45, mean naik ke {mean_tanpa:.2f}, "
      f"median tetap {statistics.median([x for x in mat if x != 45]):.1f}")

print()
print("Kesimpulan")
print(f"1. bahasa: capaian tertinggi dan sebaran paling rapat "
      f"(mean {statistics.mean(bah):.2f}, std {statistics.stdev(bah):.2f}).")
print(f"2. matematika: satu outlier rendah (nilai 45) menarik mean "
      f"dari {mean_tanpa:.2f} menjadi {mean_penuh:.2f}.")
print(f"3. sains: sedikit miring kanan (skew {skew(sai):.2f}); mean "
      f"{statistics.mean(sai):.2f} di atas median {statistics.median(sai):.1f}.")
print("4. seluruh angka di atas dihitung ulang dari data yang melekat pada skrip ini.")
