app/Services/RecommendationService.php
Produk -> Rating
// Rating 1-5 berdasarkan histori transaksi
$matrix[$order->user_id][$order->product_name]
= (float) $order->rating;
}
// 2. Jika user baru (Cold Start), kembalikan produk populer
if (!isset($matrix[$userId])) {
return $this->getPopularProducts($limit);
}
// 3. Hitung Cosine Similarity dengan user lain
$userRatings = $matrix[$userId];
$similarities = [];
foreach ($matrix as $otherId => $otherRatings) {
if ($otherId == $userId) continue;
// Core Algorithm: Cosine Similarity
$similarities[$otherId] =
$this->calculateCosineSimilarity($userRatings, $otherRatings);
}
// 4. Urutkan user yang paling mirip (Nearest Neighbors)
arsort($similarities);
$neighbors = array_slice($similarities, 0, 10, true);
// 5. Prediksi skor untuk produk yang belum dibeli
$predictions = [];
$allProducts = $this->getAllUniqueProducts($orders);
foreach ($allProducts as $productName) {
// Skip produk yang sudah dibeli user target
if (isset($userRatings[$productName])) continue;
$scoreSum = 0;
$simSum = 0;
foreach ($neighbors as $neighborId => $sim) {
// Hanya hitung jika neighbor pernah membeli produk ini
if (isset($matrix[$neighborId][$productName])) {
// Rumus Weighted Sum
$scoreSum += $sim * $matrix[$neighborId][$productName];
$simSum += abs($sim);
}
}
if ($simSum > 0) {
$predictions[$productName] = $scoreSum / $simSum;
}
}
// Urutkan prediksi dari skor tertinggi
arsort($predictions);
return array_slice($predictions, 0, $limit, true);
}
}
?>