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);
        }
    }
    ?>