""" core/health_detector.py Identifies inactive, legacy, zombie, and hyper-viral channels based on engagement-to-audience ratios and upload cadence. """ from typing import Dict, Any import numpy as np import pandas as pd class ChannelHealthDetector: """ Evaluates channel vitality by examining daily velocity against subscriber scale. """ def __init__(self, zombie_sub_threshold: int = 25000, zombie_velocity_cutoff: float = 100.0): self.zombie_sub_threshold = zombie_sub_threshold self.zombie_velocity_cutoff = zombie_velocity_cutoff def classify_channel(self, row: pd.Series) -> Dict[str, Any]: subs = row.get("subscriber_count") daily_vel = row.get("daily_view_velocity") status_flag = row.get("status_flag", "") # Handle unresolvable or missing data if pd.isna(subs) or status_flag == "FAILED_LOOKUP": return { "health_status": "UNRESOLVED", "is_zombie": False, "health_notes": "Channel could not be resolved via YouTube API." } subs = float(subs) daily_vel = float(daily_vel) if pd.notna(daily_vel) else 0.0 engagement_ratio = daily_vel / max(subs, 1000.0) # 1. Zombie Channel: Large subscriber base with dead viewership if subs >= self.zombie_sub_threshold and daily_vel < self.zombie_velocity_cutoff: return { "health_status": "ZOMBIE_CHANNEL", "is_zombie": True, "health_notes": f"High subscriber base ({int(subs):,}) with negligible viewership ({daily_vel:.1f} views/day)." } # 2. Dormant Catalog: No recent uploads and negligible velocity if status_flag == "INACTIVE_OR_DORMANT" or daily_vel == 0.0: return { "health_status": "DORMANT_CATALOG", "is_zombie": subs >= 10000, "health_notes": "Zero recent uploads and stalled catalog velocity." } # 3. Viral Surge: Recent views exceed subscriber base if engagement_ratio >= 1.0: return { "health_status": "VIRAL_SURGE", "is_zombie": False, "health_notes": "Audience reach is exploding beyond existing subscriber base." } # 4. Catalog Evergreen: Big catalog keeping views high despite no new release if status_flag == "CATALOG_ACTIVE_NO_RECENT_UPLOAD": return { "health_status": "CATALOG_EVERGREEN", "is_zombie": False, "health_notes": "Strong passive catalog views despite release pause." } # 5. Healthy Active Channel return { "health_status": "ACTIVE_HEALTHY", "is_zombie": False, "health_notes": "Consistent release schedule and steady audience engagement." } def evaluate_dataframe(self, df: pd.DataFrame) -> pd.DataFrame: """Applies health classification across all artist records.""" out = df.copy() health_results = out.apply(self.classify_channel, axis=1) out["health_status"] = [r["health_status"] for r in health_results] out["is_zombie"] = [r["is_zombie"] for r in health_results] out["health_notes"] = [r["health_notes"] for r in health_results] return out