fix(analytics): shrink video efficiency and gate noisy boards by views
This commit is contained in:
1 parent
e7034cfb84
commit
bc3bef0743
12 files changed
+125
-40
No files matched your search
@@ -699,6 +699,7 @@ class DashboardQueries:
|
||||
latest = self._latest_date(conn) or self._today()
|
||||
analytics = self.config_store.get().analytics
|
||||
duration_sorts = {"efficiency", "interaction_efficiency"}
|
||||
min_view_for_ranking = max(0, int(analytics.min_view_for_ranking))
|
||||
within_field = None
|
||||
if within_days is not None:
|
||||
if within_days < 1:
|
||||
@@ -716,7 +717,7 @@ class DashboardQueries:
|
||||
)
|
||||
aids = [int(video["aid"]) for video in videos]
|
||||
snapshots = self._snapshot_map(conn, aids)
|
||||
_, _, heat, percentiles = self._global_heat(conn)
|
||||
videos_all, snapshots_all, heat, percentiles = self._global_heat(conn)
|
||||
|
||||
previous: dict[int, dict[str, Any]] = {}
|
||||
if sort in {"growth", "growth_rate", "interaction"}:
|
||||
@@ -740,16 +741,60 @@ class DashboardQueries:
|
||||
if sort in duration_sorts:
|
||||
latest_start, _ = day_bounds(latest)
|
||||
minimum_seconds = max(0, int(analytics.min_duration_seconds))
|
||||
min_view = max(0, int(analytics.min_view_for_efficiency))
|
||||
items = [
|
||||
item for item in items
|
||||
if item["metrics"] is not None
|
||||
and int(item["duration"] or 0) >= minimum_seconds
|
||||
and int((item["metrics"] or {}).get("view", 0)) >= min_view
|
||||
and int((item["metrics"] or {}).get("view", 0)) >= min_view_for_ranking
|
||||
and is_mature(
|
||||
item["pubdate"], latest_start, analytics.maturity_days
|
||||
)
|
||||
]
|
||||
kappa_hours = max(0, int(analytics.video_shrink_minutes)) / 60.0
|
||||
total_hours = 0.0
|
||||
total_views = 0.0
|
||||
total_interactions = 0.0
|
||||
for video in videos_all:
|
||||
hours = content_hours(video.get("duration"))
|
||||
if hours is None:
|
||||
continue
|
||||
metrics = _metric_map(snapshots_all.get(int(video["aid"])))
|
||||
if metrics is None:
|
||||
continue
|
||||
total_hours += hours
|
||||
total_views += metrics["view"]
|
||||
total_interactions += (
|
||||
metrics["like"] + metrics["coin"] + metrics["favorite"]
|
||||
)
|
||||
prior_views = total_views / total_hours if total_hours > 0 else 0.0
|
||||
prior_interactions = (
|
||||
total_interactions / total_hours if total_hours > 0 else 0.0
|
||||
)
|
||||
for item in items:
|
||||
hours = content_hours(item.get("duration")) or 0.0
|
||||
metrics = item["metrics"] or {}
|
||||
denominator = hours + kappa_hours
|
||||
if hours <= 0 or denominator <= 0:
|
||||
item["efficiency_score"] = None
|
||||
item["interaction_efficiency_score"] = None
|
||||
continue
|
||||
view = int(metrics.get("view", 0))
|
||||
interactions = (
|
||||
int(metrics.get("like", 0))
|
||||
+ int(metrics.get("coin", 0))
|
||||
+ int(metrics.get("favorite", 0))
|
||||
)
|
||||
item["efficiency_score"] = (
|
||||
view + kappa_hours * prior_views
|
||||
) / denominator
|
||||
item["interaction_efficiency_score"] = (
|
||||
interactions + kappa_hours * prior_interactions
|
||||
) / denominator
|
||||
if sort == "heat":
|
||||
items = [
|
||||
item for item in items
|
||||
if int((item["metrics"] or {}).get("view", 0)) >= min_view_for_ranking
|
||||
]
|
||||
if sort == "interaction":
|
||||
items = [item for item in items if item["interaction_rate"] is not None]
|
||||
if sort in {"growth", "growth_rate"}:
|
||||
@@ -773,7 +818,11 @@ class DashboardQueries:
|
||||
if sort == "interaction":
|
||||
return item["interaction_rate"] if item["interaction_rate"] is not None else float("-inf")
|
||||
if sort in {"efficiency", "interaction_efficiency"}:
|
||||
value = item.get(sort)
|
||||
field = (
|
||||
"efficiency_score" if sort == "efficiency"
|
||||
else "interaction_efficiency_score"
|
||||
)
|
||||
value = item.get(field)
|
||||
return value if value is not None else float("-inf")
|
||||
if sort in {"growth", "growth_rate"}:
|
||||
field = "delta" if sort == "growth" else "rate"
|
||||
@@ -800,13 +849,15 @@ class DashboardQueries:
|
||||
duration_filter = {
|
||||
"min_duration_seconds": max(0, int(analytics.min_duration_seconds)),
|
||||
"maturity_days": max(0, int(analytics.maturity_days)),
|
||||
"min_view": max(0, int(analytics.min_view_for_efficiency)),
|
||||
"min_view": min_view_for_ranking,
|
||||
"shrink_minutes": max(0, int(analytics.video_shrink_minutes)),
|
||||
}
|
||||
if not items:
|
||||
available = False
|
||||
reason = (
|
||||
f"仅统计时长 ≥ {duration_filter['min_duration_seconds']} 秒、"
|
||||
f"发布满 {duration_filter['maturity_days']} 天的视频"
|
||||
f"发布满 {duration_filter['maturity_days']} 天、"
|
||||
f"播放 ≥ {duration_filter['min_view']} 的视频"
|
||||
)
|
||||
return {
|
||||
"sort": sort,
|
||||
@@ -1425,7 +1476,8 @@ class DashboardQueries:
|
||||
"analytics": {
|
||||
"min_duration_seconds": cfg.analytics.min_duration_seconds,
|
||||
"maturity_days": cfg.analytics.maturity_days,
|
||||
"min_view_for_efficiency": cfg.analytics.min_view_for_efficiency,
|
||||
"min_view_for_ranking": cfg.analytics.min_view_for_ranking,
|
||||
"video_shrink_minutes": cfg.analytics.video_shrink_minutes,
|
||||
"shrink_minutes": cfg.analytics.shrink_minutes,
|
||||
},
|
||||
"heat_weights": {
|
||||
|
||||
Reference in new issue
Block a user