LearnMood/app/Services/FlaskModelService.php

152 lines
5.1 KiB
PHP

<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Models\ActivityLog;
use App\Models\Recommendation;
use Carbon\Carbon;
class FlaskModelService
{
protected $apiUrl;
public function __construct()
{
$this->apiUrl = env('FLASK_API_URL', 'http://127.0.0.1:5000');
Log::info('Flask API URL: ' . $this->apiUrl);
}
/**
* TEST KONEKSI KE FLASK API
*/
public function testConnection()
{
try {
$response = Http::timeout(5)->get($this->apiUrl . '/health');
return $response->successful();
} catch (\Exception $e) {
Log::error('Test connection failed: ' . $e->getMessage());
return false;
}
}
/**
* PREDIKSI HARIAN (HARI 1-7)
* Method ini dipanggil dari ActivityController
*/
public function predictDaily($mood, $durasiBelajar, $durasiTidur)
{
try {
Log::info('Mengirim request ke Flask API (predictDaily):', [
'mood' => $mood,
'durasi_belajar' => $durasiBelajar,
'durasi_tidur' => $durasiTidur
]);
$response = Http::timeout(10)->post($this->apiUrl . '/predict', [
'mood' => $mood,
'durasi_belajar' => (int)$durasiBelajar,
'durasi_tidur' => (float)$durasiTidur
]);
if ($response->successful()) {
$result = $response->json();
Log::info('Response dari Flask API (predictDaily):', $result);
return [
'success' => true,
'category' => $result['prediction'] ?? $result['category'] ?? 'Sedang',
'confidence' => $result['confidence'] ?? 0.85
];
}
Log::error('Flask API error (predictDaily): ' . $response->body());
return [
'success' => false,
'message' => 'Gagal memanggil model prediksi'
];
} catch (\Exception $e) {
Log::error('Exception saat panggil Flask API (predictDaily): ' . $e->getMessage());
return [
'success' => false,
'message' => 'Koneksi ke model server gagal: ' . $e->getMessage()
];
}
}
/**
* PREDIKSI BERDASARKAN POLA SISWA (HARI 8+)
*/
public function predictBasedOnPattern($userId)
{
try {
// Ambil data 7 hari terakhir
$activities = ActivityLog::where('user_id', $userId)
->orderBy('activity_date', 'desc')
->take(7)
->get();
if ($activities->count() < 5) {
return [
'success' => false,
'message' => 'Data belum cukup untuk analisis pola (minimal 5 hari)',
'use_daily' => true
];
}
// Hitung fitur agregat
$avgDuration = $activities->avg('duration_minutes');
$mostFrequentMood = $activities->groupBy('mood')
->map->count()
->sortDesc()
->keys()
->first();
$avgSleep = $activities->avg('sleep_hours');
Log::info('Mengirim request ke Flask API (predictBasedOnPattern):', [
'user_id' => $userId,
'avg_duration' => $avgDuration,
'most_frequent_mood' => $mostFrequentMood,
'avg_sleep' => $avgSleep,
'consistency' => $activities->count()
]);
// Kirim ke Flask API endpoint /predict/pattern
$response = Http::timeout(10)->post($this->apiUrl . '/predict/pattern', [
'avg_duration' => (float)$avgDuration,
'most_frequent_mood' => $mostFrequentMood,
'avg_sleep' => (float)$avgSleep,
'trend' => 'stabil',
'consistency' => $activities->count()
]);
if ($response->successful()) {
$result = $response->json();
Log::info('Response dari Flask API (predictBasedOnPattern):', $result);
return [
'success' => true,
'category' => $result['prediction'] ?? $result['category'] ?? 'Sedang',
'confidence' => $result['confidence'] ?? 0.85,
'pattern_analysis' => $result['pattern_analysis'] ?? null
];
}
Log::error('Flask API error (predictBasedOnPattern): ' . $response->body());
return [
'success' => false,
'message' => 'Gagal memanggil model prediksi pola'
];
} catch (\Exception $e) {
Log::error('Error dalam pattern analysis: ' . $e->getMessage());
return [
'success' => false,
'message' => $e->getMessage()
];
}
}
}