diff --git a/fastapi/app/main.py b/fastapi/app/main.py index 207fc81..ea60ffe 100644 --- a/fastapi/app/main.py +++ b/fastapi/app/main.py @@ -23,9 +23,13 @@ from filelock import FileLock, Timeout # ────────────────────────────────────────────────────────────── BASE_DIR = Path(__file__).parent.parent ML_DIR = BASE_DIR / "ml_assets" +DATA_DIR = BASE_DIR.parent / "data" +KETERANGAN_PATH = DATA_DIR / "keterangan_ts_kemendiktisaintek.csv" +COORDS_PATH = DATA_DIR / "kabupaten_coords.json" PIPELINE_PATH = ML_DIR / "ml_pipeline_internal.pkl" STATUS_PATH = ML_DIR / "retrain_status.json" LOCK_PATH = ML_DIR / "retrain_status.lock" +METRICS_PATH = ML_DIR / "metrics_internal_only.json" RETRAIN_WORKER = Path(__file__).parent / "retrain_worker.py" TEMP_DIR = ML_DIR / "tmp" TEMP_DIR.mkdir(parents=True, exist_ok=True) @@ -237,6 +241,40 @@ def retrain_status(): except Exception: return JSONResponse(content={"stage": "unknown", "message": "Status tidak terbaca."}) +@app.get("/api/v1/metrics/internal", dependencies=[Depends(verify_token)]) +def get_internal_metrics(): + if not METRICS_PATH.exists(): + return JSONResponse(status_code=404, content={"status": "error", "message": "Metrics file not found"}) + try: + data = json.loads(METRICS_PATH.read_text(encoding="utf-8")) + return JSONResponse(content=data) + except Exception as e: + logger.error(f"Failed to read metrics: {e}") + return JSONResponse(status_code=500, content={"status": "error", "message": "Failed to read metrics"}) + +from fastapi.responses import Response + +@app.get("/api/v1/data/keterangan", dependencies=[Depends(verify_token)]) +def get_keterangan_csv(): + if not KETERANGAN_PATH.exists(): + return JSONResponse(status_code=404, content={"status": "error", "message": "CSV file not found"}) + try: + return Response(content=KETERANGAN_PATH.read_bytes(), media_type="text/csv") + except Exception as e: + logger.error(f"Failed to read CSV: {e}") + return JSONResponse(status_code=500, content={"status": "error", "message": "Failed to read CSV"}) + +@app.get("/api/v1/data/kabupaten_coords", dependencies=[Depends(verify_token)]) +def get_coords_json(): + if not COORDS_PATH.exists(): + return JSONResponse(status_code=404, content={"status": "error", "message": "Coords file not found"}) + try: + data = json.loads(COORDS_PATH.read_text(encoding="utf-8")) + return JSONResponse(content=data) + except Exception as e: + logger.error(f"Failed to read coords: {e}") + return JSONResponse(status_code=500, content={"status": "error", "message": "Failed to read coords"}) + @app.post("/api/v1/retrain/reload", dependencies=[Depends(verify_token)]) def reload_model(): diff --git a/sista_mif/app/Http/Controllers/InternalDataController.php b/sista_mif/app/Http/Controllers/InternalDataController.php index 93e4a9d..4c35e58 100644 --- a/sista_mif/app/Http/Controllers/InternalDataController.php +++ b/sista_mif/app/Http/Controllers/InternalDataController.php @@ -101,11 +101,7 @@ public function index(Request $request) 'map_lokasi' => $chartLokasi, ]; - $metricsPath = base_path('../fastapi/ml_assets/metrics_internal_only.json'); - $mlMetrics = null; - if (file_exists($metricsPath)) { - $mlMetrics = json_decode(file_get_contents($metricsPath), true); - } + $mlMetrics = app(\App\Services\FastApiWorkerService::class)->getInternalMetrics(); $manualOverrideCount = ClassificationResult::where('source_type', 'internal_mif') ->where('status', 'manual_override') diff --git a/sista_mif/app/Http/Controllers/KemendikDataController.php b/sista_mif/app/Http/Controllers/KemendikDataController.php index 1f78c8d..e02c13f 100644 --- a/sista_mif/app/Http/Controllers/KemendikDataController.php +++ b/sista_mif/app/Http/Controllers/KemendikDataController.php @@ -14,16 +14,20 @@ public function index() 'total_kemendik' => KemendikRawData::count(), ]; - $keteranganPath = base_path('../data/keterangan_ts_kemendiktisaintek.csv'); $keterangan = []; - if (file_exists($keteranganPath)) { - $lines = file($keteranganPath); + $csvText = app(\App\Services\FastApiWorkerService::class)->getKemendikKeteranganCsv(); + + if ($csvText) { + $lines = explode("\n", trim($csvText)); if (count($lines) > 0) { $rawHeaders = str_getcsv(trim($lines[0]), ';'); $headers = array_map('trim', $rawHeaders); for ($i = 1; $i < count($lines); $i++) { - $row = str_getcsv(trim($lines[$i]), ';'); + $rowStr = trim($lines[$i]); + if ($rowStr === '') continue; + + $row = str_getcsv($rowStr, ';'); foreach ($headers as $index => $header) { $val = trim($row[$index] ?? ''); if ($val !== '') { @@ -75,8 +79,7 @@ public function index() }, ['< 2 Juta' => 0, '2 - 4 Juta' => 0, '4 - 6 Juta' => 0, '> 6 Juta' => 0]); $chartPendapatan = array_filter($chartPendapatan); - $coordsPath = base_path('../data/kabupaten_coords.json'); - $kabupatenCoords = file_exists($coordsPath) ? json_decode(file_get_contents($coordsPath), true) : []; + $kabupatenCoords = app(\App\Services\FastApiWorkerService::class)->getKabupatenCoords() ?? []; $charts = [ 'status' => collect($statusCounts), diff --git a/sista_mif/app/Services/FastApiWorkerService.php b/sista_mif/app/Services/FastApiWorkerService.php index d937b98..2642bf3 100644 --- a/sista_mif/app/Services/FastApiWorkerService.php +++ b/sista_mif/app/Services/FastApiWorkerService.php @@ -172,4 +172,61 @@ public function reloadModel(): array return ['error' => "Kesalahan sistem internal: {$e->getMessage()}"]; } } + + /** + * Ambil data metrics internal ML dari FastAPI + */ + public function getInternalMetrics(): ?array + { + try { + $response = $this->getClient(5)->get($this->baseUrl . '/api/v1/metrics/internal'); + + if ($response->successful()) { + return $response->json(); + } + + if ($response->status() !== 404) { + Log::warning("FastAPI Metrics Error: HTTP {$response->status()} | {$response->body()}"); + } + return null; + } catch (ConnectionException $e) { + Log::warning("FastAPI Metrics Connection Error: {$e->getMessage()}"); + return null; + } catch (\Exception $e) { + Log::error("FastAPI Metrics System Error: {$e->getMessage()}"); + return null; + } + } + + /** + * Ambil data CSV keterangan Kemendikbud dari FastAPI + */ + public function getKemendikKeteranganCsv(): ?string + { + try { + $response = $this->getClient(5)->get($this->baseUrl . '/api/v1/data/keterangan'); + if ($response->successful()) { + return $response->body(); + } + return null; + } catch (\Exception $e) { + return null; + } + } + + /** + * Ambil data JSON koordinat kabupaten dari FastAPI + */ + public function getKabupatenCoords(): ?array + { + try { + $response = $this->getClient(5)->get($this->baseUrl . '/api/v1/data/kabupaten_coords'); + if ($response->successful()) { + return $response->json(); + } + return null; + } catch (\Exception $e) { + return null; + } + } } \ No newline at end of file