Files
SkinbaseNova/config/ranking.php

64 lines
2.8 KiB
PHP

<?php
declare(strict_types=1);
/**
* Ranking system configuration — Skinbase Nova rank_v1
*
* All weights, half-lives, and thresholds are tunable here.
* Increment model_version when changing weights so caches expire gracefully.
*/
return [
// ── Model versioning ────────────────────────────────────────────────────
'model_version' => 'rank_v1',
// ── Engagement signal weights (log-scaled) ──────────────────────────────
'weights' => [
'views' => 1.0,
'favourites' => 3.0,
'downloads' => 2.5,
],
// ── Time-decay half-lives (hours) ───────────────────────────────────────
'half_life' => [
'trending' => 72, // Explore / global trending
'new_hot' => 36, // New & Hot novelty feed
'best' => 720, // Evergreen / Best-of (30 days)
'category' => 96, // Per-category trending
],
// ── Novelty boost (New & Hot only) ──────────────────────────────────────
'novelty_weight' => 0.35,
// ── Quality modifiers ───────────────────────────────────────────────────
'quality' => [
'has_tags' => 0.05,
'has_thumbnail' => 0.02,
'tag_count_max' => 10,
'tag_count_bonus' => 0.01, // per normalised tag fraction (max 0.01 total)
'penalty_hidden' => 0.50, // deducted if hidden/inactive
],
// ── Diversity constraints ────────────────────────────────────────────────
'diversity' => [
'max_per_author' => 3,
'list_size' => 50,
'candidate_pool' => 200, // top N candidates to run diversity filter on
],
// ── Anti-spam / burst-view damping ──────────────────────────────────────
'spam' => [
'views_24h_threshold' => 2000,
'fav_ratio_threshold' => 0.002,
'dl_ratio_threshold' => 0.001,
'trending_penalty_factor' => 0.5,
],
// ── Redis cache ─────────────────────────────────────────────────────────
'cache' => [
'ttl' => 900, // seconds (15 min) — lists are rebuilt hourly
'prefix' => 'rank',
],
];