aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-09-16 17:33:38 -0700
committerFuwn <[email protected]>2025-09-16 17:33:38 -0700
commit6bdc79a7f62b195847a6950fbc8a6cb1be336faa (patch)
tree7acba3f9a0abb61cfbe5b2e9b88c26560255805e
parentfeat(roleplay_limiter): Add minimum post allowance (diff)
downloadumabot-6bdc79a7f62b195847a6950fbc8a6cb1be336faa.tar.xz
umabot-6bdc79a7f62b195847a6950fbc8a6cb1be336faa.zip
feat(roleplay_limiter): Add dynamic thresholds
-rw-r--r--src/umabot/config.py8
-rw-r--r--src/umabot/rules/roleplay_limiter.py58
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: