#!/usr/bin/env python3
"""Bab 04 — Vector Playground.

Script ini memakai Python standard library saja agar bisa dijalankan di local,
VS Code, Jupyter, Colab, atau Kaggle. Tujuannya membuat vektor terasa seperti
panah, profil, dan skor keputusan — bukan rumus abstrak.
"""
from __future__ import annotations

import math


def dot(a: list[float], b: list[float]) -> float:
    return sum(x * y for x, y in zip(a, b))


def length(v: list[float]) -> float:
    return math.sqrt(sum(x * x for x in v))


def distance(a: list[float], b: list[float]) -> float:
    return math.sqrt(sum((x - y) ** 2 for x, y in zip(a, b)))


def cosine(a: list[float], b: list[float]) -> float:
    return dot(a, b) / (length(a) * length(b))


def linear_score(x: list[float], w: list[float], bias: float) -> float:
    return dot(x, w) + bias


def predict_boundary(x1: float, x2: float) -> str:
    score = 1.2 * x1 + 0.8 * x2 - 1.0
    return "layak" if score >= 0 else "tidak layak"


def main() -> None:
    print("Bab 04 — Vector Playground")
    print("=" * 52)

    a = [3, 2]
    b = [1, 4]
    print("Vektor A:", a)
    print("Vektor B:", b)
    print("Panjang A:", round(length(a), 3))
    print("Panjang B:", round(length(b), 3))
    print("Jarak A-B:", round(distance(a, b), 3))
    print("Dot A·B:", dot(a, b))
    print("Cosine A,B:", round(cosine(a, b), 3))

    print("\nProfil pelanggan")
    print("-" * 52)
    pelanggan = {
        "A": [5, 2, 1],  # kopi, es_teh, roti
        "B": [1, 5, 2],
        "C": [10, 4, 2],
    }
    for nama, v in pelanggan.items():
        print(f"{nama}: {v}, panjang={length(v):.2f}")
    print("Cosine A-B:", round(cosine(pelanggan["A"], pelanggan["B"]), 3))
    print("Cosine A-C:", round(cosine(pelanggan["A"], pelanggan["C"]), 3))

    print("\nModel linear mini")
    print("-" * 52)
    fitur_produk = [0.2, 0.9, 0.7]  # murah, rating, terjual (sudah dinormalisasi)
    bobot = [-0.3, 0.8, 0.5]
    bias = 0.1
    skor = linear_score(fitur_produk, bobot, bias)
    print("fitur produk:", fitur_produk)
    print("bobot:", bobot)
    print("bias:", bias)
    print("skor rekomendasi:", round(skor, 3))

    print("\nDecision boundary mini")
    print("-" * 52)
    for point in [(0.9, 0.8), (0.2, 0.3), (0.6, 0.6)]:
        print(point, "->", predict_boundary(*point))

    print("\nChallenge: ubah vektor pelanggan dan bobot model, lalu jalankan ulang.")


if __name__ == "__main__":
    main()
