232 lines
6.6 KiB
Python
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
|
|
}
|