scores($collection->fresh()); $collection->forceFill($scores)->save(); return $collection->fresh(); } public function scores(Collection $collection): array { $quality = 0.0; $ranking = 0.0; $titleLength = mb_strlen(trim((string) $collection->title)); $descriptionLength = mb_strlen(trim((string) ($collection->description ?? ''))); $summaryLength = mb_strlen(trim((string) ($collection->summary ?? ''))); $artworksCount = (int) $collection->artworks_count; $engagement = ((int) $collection->likes_count * 1.6) + ((int) $collection->followers_count * 2.2) + ((int) $collection->saves_count * 2.4) + ((int) $collection->comments_count * 1.2) + ((int) $collection->shares_count * 1.8); $quality += $titleLength >= 12 ? 12 : ($titleLength >= 6 ? 6 : 0); $quality += $descriptionLength >= 120 ? 12 : ($descriptionLength >= 60 ? 6 : 0); $quality += $summaryLength >= 60 ? 8 : ($summaryLength >= 20 ? 4 : 0); $quality += $collection->resolvedCoverArtwork(false) ? 14 : 0; $quality += min(24, $artworksCount * 2); $quality += $collection->type === Collection::TYPE_EDITORIAL ? 6 : 0; $quality += $collection->type === Collection::TYPE_COMMUNITY ? 4 : 0; $quality += $collection->isCollaborative() ? min(6, (int) $collection->collaborators_count) : 0; $quality += filled($collection->event_key) || filled($collection->season_key) || filled($collection->campaign_key) ? 4 : 0; $quality += $collection->usesPremiumPresentation() ? 5 : 0; $quality += $collection->moderation_status === Collection::MODERATION_ACTIVE ? 5 : -8; $quality = max(0.0, min(100.0, $quality)); $recencyBoost = 0.0; if ($collection->last_activity_at) { $days = max(0, now()->diffInDays($collection->last_activity_at)); $recencyBoost = max(0.0, 12.0 - min(12.0, $days * 0.4)); } $ranking = min(150.0, $quality + $recencyBoost + min(38.0, $engagement / 25)); return [ 'quality_score' => round($quality, 2), 'ranking_score' => round($ranking, 2), ]; } }