cfg = $carouselConfig; $this->profileCityId = $profileCityId; $this->profileDivisionId = $profileDivisionId; $this->profileCountryId = $profileCountryId; } public function score(Call $call): float { $score = 1.0; $loc = $call->location; // --- Location specificity (only best-matching tier applied) --- if ($loc) { if ($loc->country_id === self::UNKNOWN_COUNTRY_ID) { $score *= (float) ($this->cfg['boost_location_unknown'] ?? 0.8); } elseif ($loc->city_id) { $score *= (float) ($this->cfg['boost_location_city'] ?? 2.0); } elseif ($loc->division_id) { $score *= (float) ($this->cfg['boost_location_division'] ?? 1.5); } elseif ($loc->country_id) { $score *= (float) ($this->cfg['boost_location_country'] ?? 1.1); } // Same-city (district) proximity bonus if ($this->profileCityId && $loc->city_id === $this->profileCityId) { $score *= (float) ($this->cfg['boost_same_district'] ?? 3.0); } } // --- Engagement: likes on the call --- $likeCount = $call->loveReactant?->reactionCounters ->firstWhere('reaction_type_id', self::REACTION_TYPE_LIKE)?->count ?? 0; $score *= (1.0 + $likeCount * (float) ($this->cfg['boost_like_count'] ?? 0.05)); // --- Engagement: stars on the callable --- $starCount = $call->callable?->loveReactant?->reactionCounters ->firstWhere('reaction_type_id', self::REACTION_TYPE_STAR)?->count ?? 0; $score *= (1.0 + $starCount * (float) ($this->cfg['boost_star_count'] ?? 0.10)); // --- Recency (created_at) --- $recentDays = (int) ($this->cfg['recent_days'] ?? 14); if ($call->created_at && $call->created_at->gte(now()->subDays($recentDays))) { $score *= (float) ($this->cfg['boost_recent_from'] ?? 1.3); } // --- Urgency (till expiry) --- $soonDays = (int) ($this->cfg['soon_days'] ?? 7); if ($call->till && $call->till->lte(now()->addDays($soonDays))) { $score *= (float) ($this->cfg['boost_soon_till'] ?? 1.2); } // --- Callable type --- $callableType = $call->callable_type ?? ''; if (str_ends_with($callableType, 'User')) { $score *= (float) ($this->cfg['boost_callable_user'] ?? 1.0); } elseif (str_ends_with($callableType, 'Organization')) { $score *= (float) ($this->cfg['boost_callable_organization'] ?? 1.2); } elseif (str_ends_with($callableType, 'Bank')) { $score *= (float) ($this->cfg['boost_callable_bank'] ?? 1.0); } return $score; } }