first commit

This commit is contained in:
Dwindi Ramadhana
2026-03-21 23:32:59 +07:00
commit cf193d7ea0
57 changed files with 17871 additions and 0 deletions

204
app/main.py Normal file
View File

@@ -0,0 +1,204 @@
"""
IRT Bank Soal - Adaptive Question Bank System
Main FastAPI application entry point.
Features:
- CTT (Classical Test Theory) scoring with exact Excel formulas
- IRT (Item Response Theory) support for adaptive testing
- Multi-website support for WordPress integration
- AI-powered question generation
"""
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.admin import admin as admin_app
from app.core.config import get_settings
from app.database import close_db, init_db
from app.routers import (
admin_router,
ai_router,
import_export_router,
reports_router,
sessions_router,
tryouts_router,
wordpress_router,
)
settings = get_settings()
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""
Application lifespan manager.
Handles startup and shutdown events.
"""
# Startup: Initialize database
await init_db()
yield
# Shutdown: Close database connections
await close_db()
# Initialize FastAPI application
app = FastAPI(
title="IRT Bank Soal",
description="""
## Adaptive Question Bank System with IRT/CTT Scoring
This API provides a comprehensive backend for adaptive assessment systems.
### Features
- **CTT Scoring**: Classical Test Theory with exact Excel formula compatibility
- **IRT Support**: Item Response Theory for adaptive testing (1PL Rasch model)
- **Multi-Site**: Single backend serving multiple WordPress sites
- **AI Generation**: Automatic question variant generation
### Scoring Formulas (PRD Section 13.1)
- **CTT p-value**: `p = Σ Benar / Total Peserta`
- **CTT Bobot**: `Bobot = 1 - p`
- **CTT NM**: `NM = (Total_Bobot_Siswa / Total_Bobot_Max) × 1000`
- **CTT NN**: `NN = 500 + 100 × ((NM - Rataan) / SB)`
### Authentication
Most endpoints require `X-Website-ID` header for multi-site isolation.
""",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
lifespan=lifespan,
)
# Configure CORS middleware
# Parse ALLOWED_ORIGINS from settings (comma-separated string)
allowed_origins = settings.ALLOWED_ORIGINS
if isinstance(allowed_origins, str):
allowed_origins = [origin.strip() for origin in allowed_origins.split(",") if origin.strip()]
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Health check endpoint
@app.get(
"/",
summary="Health check",
description="Returns API status and version information.",
tags=["health"],
)
async def root():
"""
Health check endpoint.
Returns basic API information for monitoring and load balancer checks.
"""
return {
"status": "healthy",
"service": "IRT Bank Soal",
"version": "1.0.0",
"docs": "/docs",
}
@app.get(
"/health",
summary="Detailed health check",
description="Returns detailed health status including database connectivity.",
tags=["health"],
)
async def health_check():
"""
Detailed health check endpoint.
Includes database connectivity verification.
"""
from app.database import engine
from sqlalchemy import text
db_status = "unknown"
try:
async with engine.connect() as conn:
await conn.execute(text("SELECT 1"))
db_status = "connected"
except Exception as e:
db_status = f"error: {str(e)}"
return {
"status": "healthy" if db_status == "connected" else "degraded",
"service": "IRT Bank Soal",
"version": "1.0.0",
"database": db_status,
"environment": settings.ENVIRONMENT,
}
# Include API routers with version prefix
app.include_router(
import_export_router,
)
app.include_router(
sessions_router,
prefix=f"{settings.API_V1_STR}",
)
app.include_router(
tryouts_router,
prefix=f"{settings.API_V1_STR}",
)
app.include_router(
wordpress_router,
prefix=f"{settings.API_V1_STR}",
)
app.include_router(
ai_router,
prefix=f"{settings.API_V1_STR}",
)
app.include_router(
reports_router,
prefix=f"{settings.API_V1_STR}",
)
# Mount FastAPI Admin panel
app.mount("/admin", admin_app)
# Include admin API router for custom actions
app.include_router(
admin_router,
prefix=f"{settings.API_V1_STR}",
)
# Placeholder routers for future implementation
# These will be implemented in subsequent phases
# app.include_router(
# items_router,
# prefix=f"{settings.API_V1_STR}",
# tags=["items"],
# )
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=8000,
reload=settings.ENVIRONMENT == "development",
)