60 lines
2.2 KiB
PHP
60 lines
2.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\Academy;
|
|
|
|
use App\Models\AcademyContentMetricDaily;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Collection;
|
|
|
|
final class AcademyPopularityService
|
|
{
|
|
/**
|
|
* @param array<string, int|float|null> $metrics
|
|
*/
|
|
public function calculatePopularityScore(array $metrics): float
|
|
{
|
|
return round(
|
|
((float) ($metrics['unique_visitors'] ?? 0) * 1)
|
|
+ ((float) ($metrics['engaged_views'] ?? 0) * 3)
|
|
+ ((float) ($metrics['likes'] ?? 0) * 5)
|
|
+ ((float) ($metrics['saves'] ?? 0) * 7)
|
|
+ ((float) ($metrics['prompt_copies'] ?? 0) * 8)
|
|
+ ((float) ($metrics['negative_prompt_copies'] ?? 0) * 4)
|
|
+ ((float) ($metrics['starts'] ?? 0) * 4)
|
|
+ ((float) ($metrics['completions'] ?? 0) * 10)
|
|
+ ((float) ($metrics['upgrade_clicks'] ?? 0) * 15)
|
|
+ ((float) ($metrics['premium_preview_views'] ?? 0) * 3)
|
|
- ((float) ($metrics['bounce_count'] ?? 0) * 2),
|
|
2,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, int|float|null> $metrics
|
|
*/
|
|
public function calculateConversionScore(array $metrics): float
|
|
{
|
|
$uniqueVisitors = max(1, (int) ($metrics['unique_visitors'] ?? 0));
|
|
|
|
return round((((float) ($metrics['upgrade_clicks'] ?? 0) * 100) / $uniqueVisitors), 2);
|
|
}
|
|
|
|
public function queryBetween(Carbon $from, Carbon $to): Builder
|
|
{
|
|
return AcademyContentMetricDaily::query()
|
|
->whereBetween('date', [$from->toDateString(), $to->toDateString()]);
|
|
}
|
|
|
|
public function topContent(Carbon $from, Carbon $to, int $limit = 10): Collection
|
|
{
|
|
return $this->queryBetween($from, $to)
|
|
->selectRaw('content_type, content_id, sum(views) as views, sum(unique_visitors) as unique_visitors, sum(engaged_views) as engaged_views, sum(likes) as likes, sum(saves) as saves, sum(prompt_copies) as prompt_copies, sum(completions) as completions, sum(upgrade_clicks) as upgrade_clicks, sum(popularity_score) as popularity_score')
|
|
->groupBy('content_type', 'content_id')
|
|
->orderByDesc('popularity_score')
|
|
->limit($limit)
|
|
->get();
|
|
}
|
|
} |