diff options
| author | Fuwn <[email protected]> | 2025-09-16 17:33:38 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-09-16 17:33:38 -0700 |
| commit | 6bdc79a7f62b195847a6950fbc8a6cb1be336faa (patch) | |
| tree | 7acba3f9a0abb61cfbe5b2e9b88c26560255805e | |
| parent | feat(roleplay_limiter): Add minimum post allowance (diff) | |
| download | umabot-6bdc79a7f62b195847a6950fbc8a6cb1be336faa.tar.xz umabot-6bdc79a7f62b195847a6950fbc8a6cb1be336faa.zip | |
feat(roleplay_limiter): Add dynamic thresholds
| -rw-r--r-- | src/umabot/config.py | 8 | ||||
| -rw-r--r-- | src/umabot/rules/roleplay_limiter.py | 58 |
2 files changed, 39 insertions, 27 deletions
diff --git a/src/umabot/config.py b/src/umabot/config.py index 39c034c..f49f936 100644 --- a/src/umabot/config.py +++ b/src/umabot/config.py @@ -33,11 +33,6 @@ class Config: roleplay_limit_window_hours: int = 24 # hours dry_run: bool = False - # Surge-based roleplay limiting (data-driven thresholds) - roleplay_surge_threshold_1: int = 8 # First threshold: ~27% of daily posts - roleplay_surge_threshold_2: int = 12 # Second threshold: ~41% of daily posts - roleplay_surge_threshold_3: int = 16 # Third threshold: ~55% of daily posts - @classmethod def from_env(cls) -> "Config": """Create configuration from environment variables.""" @@ -58,9 +53,6 @@ class Config: post_limit_window_hours=int(os.getenv("POST_LIMIT_WINDOW_HOURS", "24")), roleplay_limit_window_hours=int(os.getenv("ROLEPLAY_LIMIT_WINDOW_HOURS", "24")), dry_run=os.getenv("DRY_RUN", "false").lower() == "true", - roleplay_surge_threshold_1=int(os.getenv("ROLEPLAY_SURGE_THRESHOLD_1", "8")), - roleplay_surge_threshold_2=int(os.getenv("ROLEPLAY_SURGE_THRESHOLD_2", "12")), - roleplay_surge_threshold_3=int(os.getenv("ROLEPLAY_SURGE_THRESHOLD_3", "16")), ) def validate(self) -> None: diff --git a/src/umabot/rules/roleplay_limiter.py b/src/umabot/rules/roleplay_limiter.py index c63b1f7..57ed3db 100644 --- a/src/umabot/rules/roleplay_limiter.py +++ b/src/umabot/rules/roleplay_limiter.py @@ -20,11 +20,7 @@ class RoleplayLimiter(Rule): # Surge-based limits configuration self.base_limit = 3 # Base limit when no surge (maximum posts per user) - self.surge_thresholds = [ - (config.roleplay_surge_threshold_1, 2), # First threshold = 2 posts per user - (config.roleplay_surge_threshold_2, 1), # Second threshold = 1 post per user - (config.roleplay_surge_threshold_3, 1), # Third threshold = 1 post per user (minimum guaranteed) - ] + # Thresholds are now calculated dynamically based on daily post distribution def should_remove(self, submission: praw.models.Submission) -> bool: """Check if a user has posted too many roleplay posts based on surge.""" @@ -97,32 +93,56 @@ class RoleplayLimiter(Rule): return base_message + main_message + notice def _get_surge_level_and_limit(self) -> tuple[int, int]: - """Get current surge level and corresponding user limit.""" + """Get current surge level and corresponding user limit based on dynamic thresholds.""" try: - # Get recent roleplay posts from subreddit + # Get recent posts from subreddit to calculate daily distribution current_time = time.time() cutoff_time = current_time - self.surge_window - # Count roleplay posts in the surge window - surge_count = 0 + # Count all posts and roleplay posts in the surge window + total_posts = 0 + roleplay_posts = 0 + for submission in self.subreddit.new(limit=100): if submission.created_utc < cutoff_time: break + total_posts += 1 if self._is_roleplay_post(submission): - surge_count += 1 + roleplay_posts += 1 - # Determine limit based on surge level - user_limit = self.base_limit - for threshold, limit in self.surge_thresholds: - if surge_count >= threshold: - user_limit = limit - else: - break + # Calculate dynamic thresholds based on total post volume + # Target: Keep roleplay at ~20% of total content (down from current 31.66%) + target_roleplay_percentage = 0.20 + + # Calculate thresholds as percentages of total posts + threshold_1_percentage = 0.25 # 25% of posts can be roleplay + threshold_2_percentage = 0.35 # 35% of posts can be roleplay + threshold_3_percentage = 0.50 # 50% of posts can be roleplay + + # Convert percentages to actual post counts + threshold_1 = max(1, int(total_posts * threshold_1_percentage)) + threshold_2 = max(1, int(total_posts * threshold_2_percentage)) + threshold_3 = max(1, int(total_posts * threshold_3_percentage)) + + # Determine limit based on current roleplay count + if roleplay_posts >= threshold_3: + user_limit = 1 # Minimum guaranteed + elif roleplay_posts >= threshold_2: + user_limit = 1 # High surge + elif roleplay_posts >= threshold_1: + user_limit = 2 # Moderate surge + else: + user_limit = 3 # Normal activity + + self.logger.debug( + f"Dynamic thresholds: Total={total_posts}, Roleplay={roleplay_posts}, " + f"Thresholds=[{threshold_1}, {threshold_2}, {threshold_3}], Limit={user_limit}" + ) - return surge_count, user_limit + return roleplay_posts, user_limit except Exception as e: - self.logger.error(f"Error calculating surge level: {e}") + self.logger.error(f"Error calculating dynamic surge level: {e}") return 0, self.base_limit def _clean_old_posts(self, username: str, current_time: float) -> None: |