TIF_E41253310/Backend/app/routers/clustering_results.py

232 lines
6.6 KiB
Python

"""
Router untuk CRUD Clustering Results
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
from app.config.database import get_db
from app.schemas.models import (
ClusteringResultCreate,
ClusteringResultResponse,
ModelEvaluationCreate,
ModelEvaluationResponse,
BulkClusteringResult
)
from app.models.models import ClusteringResult, ModelEvaluation
from app.models.alumni import Alumni
router = APIRouter(prefix="/clustering", tags=["Clustering Results"])
# ============== CLUSTERING RESULTS ==============
@router.get("/results", response_model=List[ClusteringResultResponse])
def get_all_results(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db)
):
"""Ambil semua hasil clustering"""
results = db.query(ClusteringResult).offset(skip).limit(limit).all()
return results
@router.get("/results/{alumni_id}", response_model=ClusteringResultResponse)
def get_result_by_alumni(
alumni_id: int,
db: Session = Depends(get_db)
):
"""Ambil hasil clustering berdasarkan alumni_id"""
result = db.query(ClusteringResult).filter(
ClusteringResult.alumni_id == alumni_id
).first()
if not result:
raise HTTPException(status_code=404, detail="Hasil clustering tidak ditemukan")
return result
@router.post("/results", response_model=ClusteringResultResponse)
def create_result(
result_in: ClusteringResultCreate,
db: Session = Depends(get_db)
):
"""Tambah hasil clustering"""
# Cek apakah alumni exists
alumni = db.query(Alumni).filter(Alumni.id == result_in.alumni_id).first()
if not alumni:
raise HTTPException(status_code=404, detail="Alumni tidak ditemukan")
# Cek apakah sudah ada hasil untuk alumni ini
existing = db.query(ClusteringResult).filter(
ClusteringResult.alumni_id == result_in.alumni_id
).first()
if existing:
raise HTTPException(status_code=400, detail="Hasil clustering sudah ada untuk alumni ini")
result = ClusteringResult(**result_in.model_dump())
db.add(result)
db.commit()
db.refresh(result)
return result
@router.post("/results/bulk")
def create_bulk_results(
bulk_data: BulkClusteringResult,
db: Session = Depends(get_db)
):
"""Simpan hasil clustering dan evaluasi model"""
try:
# 1. Simpan evaluasi model
eval_data = {
"model_version": bulk_data.model_version,
"k": bulk_data.k,
"inertia": bulk_data.inertia,
"silhouette_score": bulk_data.silhouette_score
}
evaluation = ModelEvaluation(**eval_data)
db.add(evaluation)
db.flush()
# 2. Simpan hasil clustering per alumni
results_saved = 0
for item in bulk_data.results:
# Cek apakah alumni exists
alumni = db.query(Alumni).filter(Alumni.id == item["alumni_id"]).first()
if not alumni:
continue
# Hapus hasil lama jika ada
old = db.query(ClusteringResult).filter(
ClusteringResult.alumni_id == item["alumni_id"]
).first()
if old:
db.delete(old)
# Simpan hasil baru
result_data = {
"alumni_id": item["alumni_id"],
"model_version": bulk_data.model_version,
"k": bulk_data.k,
"cluster": item["cluster"],
"kategori": item["kategori"],
"profile_match": item.get("profile_match", False),
"matched_keyword": item.get("matched_keyword", "")
}
result = ClusteringResult(**result_data)
db.add(result)
results_saved += 1
db.commit()
return {
"status": "success",
"model_evaluation_id": evaluation.id,
"results_saved": results_saved
}
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/results/{alumni_id}")
def delete_result(
alumni_id: int,
db: Session = Depends(get_db)
):
"""Hapus hasil clustering berdasarkan alumni_id"""
result = db.query(ClusteringResult).filter(
ClusteringResult.alumni_id == alumni_id
).first()
if not result:
raise HTTPException(status_code=404, detail="Hasil clustering tidak ditemukan")
db.delete(result)
db.commit()
return {"message": "Hasil clustering berhasil dihapus"}
# ============== MODEL EVALUATIONS ==============
@router.get("/evaluations", response_model=List[ModelEvaluationResponse])
def get_all_evaluations(
skip: int = 0,
limit: int = 10,
db: Session = Depends(get_db)
):
"""Ambil semua evaluasi model"""
evaluations = db.query(ModelEvaluation).order_by(
ModelEvaluation.created_at.desc()
).offset(skip).limit(limit).all()
return evaluations
@router.get("/evaluations/latest", response_model=ModelEvaluationResponse)
def get_latest_evaluation(db: Session = Depends(get_db)):
"""Ambil evaluasi model terbaru"""
evaluation = db.query(ModelEvaluation).order_by(
ModelEvaluation.created_at.desc()
).first()
if not evaluation:
raise HTTPException(status_code=404, detail="Tidak ada evaluasi model")
return evaluation
@router.post("/evaluations", response_model=ModelEvaluationResponse)
def create_evaluation(
eval_in: ModelEvaluationCreate,
db: Session = Depends(get_db)
):
"""Tambah evaluasi model baru"""
evaluation = ModelEvaluation(**eval_in.model_dump())
db.add(evaluation)
db.commit()
db.refresh(evaluation)
return evaluation
# ============== STATISTIK ==============
@router.get("/stats")
def get_clustering_stats(db: Session = Depends(get_db)):
"""Ambil statistik hasil clustering"""
results = db.query(ClusteringResult).all()
if not results:
return {
"total": 0,
"by_kategori": {},
"by_cluster": {}
}
# Count by kategori
kategori_count = {}
for r in results:
kategori_count[r.kategori] = kategori_count.get(r.kategori, 0) + 1
# Count by cluster
cluster_count = {}
for r in results:
cluster_count[f"Cluster_{r.cluster}"] = cluster_count.get(f"Cluster_{r.cluster}", 0) + 1
# Count by prodi
prodi_kategori = {}
alumni_with_results = db.query(Alumni).join(ClusteringResult).all()
return {
"total": len(results),
"by_kategori": kategori_count,
"by_cluster": cluster_count,
"model_version": results[0].model_version if results else None
}