79 lines
2.6 KiB
PHP
79 lines
2.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\EarlyGrowth;
|
|
|
|
use App\Models\Artwork;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
/**
|
|
* AdaptiveTimeWindow
|
|
*
|
|
* Dynamically widens the look-back window used by trending / rising feeds
|
|
* when recent upload volume is below configured thresholds.
|
|
*
|
|
* This only affects RANKING QUERIES — it never modifies artwork timestamps,
|
|
* canonical URLs, or any stored data.
|
|
*
|
|
* Behaviour:
|
|
* uploads/day ≥ narrow_threshold → normal window (7 d)
|
|
* uploads/day ≥ wide_threshold → medium window (30 d)
|
|
* uploads/day < wide_threshold → wide window (90 d)
|
|
*
|
|
* All thresholds and window sizes are configurable in config/early_growth.php.
|
|
*/
|
|
final class AdaptiveTimeWindow
|
|
{
|
|
/**
|
|
* Return the number of look-back days to use for trending / rising queries.
|
|
*
|
|
* @param int $defaultDays Returned as-is when EGS is disabled.
|
|
*/
|
|
public function getTrendingWindowDays(int $defaultDays = 30): int
|
|
{
|
|
if (! EarlyGrowth::adaptiveWindowEnabled()) {
|
|
return $defaultDays;
|
|
}
|
|
|
|
$uploadsPerDay = $this->getUploadsPerDay();
|
|
$narrowThreshold = (int) config('early_growth.thresholds.uploads_per_day_narrow', 10);
|
|
$wideThreshold = (int) config('early_growth.thresholds.uploads_per_day_wide', 3);
|
|
|
|
$narrowDays = (int) config('early_growth.thresholds.window_narrow_days', 7);
|
|
$mediumDays = (int) config('early_growth.thresholds.window_medium_days', 30);
|
|
$wideDays = (int) config('early_growth.thresholds.window_wide_days', 90);
|
|
|
|
if ($uploadsPerDay >= $narrowThreshold) {
|
|
return $narrowDays; // Healthy activity → normal 7-day window
|
|
}
|
|
|
|
if ($uploadsPerDay >= $wideThreshold) {
|
|
return $mediumDays; // Moderate activity → expand to 30 days
|
|
}
|
|
|
|
return $wideDays; // Low activity → expand to 90 days
|
|
}
|
|
|
|
/**
|
|
* Rolling 7-day average of approved public uploads per day.
|
|
* Cached for `early_growth.cache_ttl.time_window` seconds.
|
|
*/
|
|
public function getUploadsPerDay(): float
|
|
{
|
|
$ttl = (int) config('early_growth.cache_ttl.time_window', 600);
|
|
|
|
return Cache::remember('egs.uploads_per_day', $ttl, function (): float {
|
|
$count = Artwork::query()
|
|
->where('is_public', true)
|
|
->where('is_approved', true)
|
|
->whereNull('deleted_at')
|
|
->whereNotNull('published_at')
|
|
->where('published_at', '>=', now()->subDays(7))
|
|
->count();
|
|
|
|
return round($count / 7, 2);
|
|
});
|
|
}
|
|
}
|