62 lines
2.4 KiB
PHP
62 lines
2.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Collection;
|
|
|
|
class CollectionQualityService
|
|
{
|
|
public function sync(Collection $collection): Collection
|
|
{
|
|
$scores = $this->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),
|
|
];
|
|
}
|
|
}
|