From dfd9405fe6a8761cb6f55d687d617db541259566 Mon Sep 17 00:00:00 2001 From: Janik Kleinhoff Date: Sun, 17 May 2015 22:15:39 +0000 Subject: [PATCH] !wait: use a token bucket This makes up for removing the wait effect of !ping. Default settings are one !wait every 240 seconds, initially two !wait tokens, maximum (burst) of three tokens. --- src/settings.py | 7 +++++-- src/wolfgame.py | 47 +++++++++++++++++++++++++++-------------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/settings.py b/src/settings.py index 5ac78f6..f5fcfa3 100644 --- a/src/settings.py +++ b/src/settings.py @@ -5,10 +5,13 @@ from src import events PING_WAIT = 300 # Seconds PING_MIN_WAIT = 30 # How long !start has to wait after a !ping MINIMUM_WAIT = 60 -EXTRA_WAIT = 20 +EXTRA_WAIT = 30 EXTRA_WAIT_JOIN = 0 # Add this many seconds to the waiting time for each !join WAIT_AFTER_JOIN = 25 # Wait at least this many seconds after the last join -MAXIMUM_WAITED = 3 # limit for amount of !wait's +# !wait uses a token bucket +WAIT_TB_INIT = 2 # initial number of tokens +WAIT_TB_DELAY = 240 # wait time between adding tokens +WAIT_TB_BURST = 3 # maximum number of tokens that can be accumulated STATS_RATE_LIMIT = 60 VOTES_RATE_LIMIT = 60 ADMINS_RATE_LIMIT = 300 diff --git a/src/wolfgame.py b/src/wolfgame.py index 79c08b2..1ae6ea4 100644 --- a/src/wolfgame.py +++ b/src/wolfgame.py @@ -92,6 +92,7 @@ var.GAME_START_TIME = datetime.now() # for idle checker only var.CAN_START_TIME = 0 var.GRAVEYARD_LOCK = threading.RLock() var.WARNING_LOCK = threading.RLock() +var.WAIT_TB_LOCK = threading.RLock() var.STARTED_DAY_PLAYERS = 0 var.DISCONNECTED = {} # players who got disconnected @@ -1277,7 +1278,9 @@ def join_player(cli, player, chan, who = None, forced = False): mass_mode(cli, cmodes, []) var.ROLES["person"].append(player) var.PHASE = "join" - var.WAITED = 0 + with var.WAIT_TB_LOCK: + var.WAIT_TB_TOKENS = var.WAIT_TB_INIT + var.WAIT_TB_LAST = time.time() var.GAME_ID = time.time() var.PINGED_ALREADY_ACCS = [] var.PINGED_ALREADY = [] @@ -6570,24 +6573,30 @@ def wait(cli, nick, chan, rest): if chan != botconfig.CHANNEL: return - if (var.LAST_WAIT and nick in var.LAST_WAIT and var.LAST_WAIT[nick] + - timedelta(seconds=var.WAIT_RATE_LIMIT) > datetime.now()): - cli.notice(nick, ("This command is rate-limited. Please wait a while " - "before using it again.")) - return - if var.WAITED >= var.MAXIMUM_WAITED: - cli.msg(chan, "Limit has already been reached for extending the wait time.") - return - now = datetime.now() - var.LAST_WAIT[nick] = now - if now > var.CAN_START_TIME: - var.CAN_START_TIME = now + timedelta(seconds=var.EXTRA_WAIT) - else: - var.CAN_START_TIME += timedelta(seconds=var.EXTRA_WAIT) - var.WAITED += 1 - cli.msg(chan, ("\u0002{0}\u0002 increased the wait time by "+ - "{1} seconds.").format(nick, var.EXTRA_WAIT)) + with var.WAIT_TB_LOCK: + wait_check_time = time.time() + var.WAIT_TB_TOKENS += (wait_check_time - var.WAIT_TB_LAST) / var.WAIT_TB_DELAY + var.WAIT_TB_LAST = wait_check_time + + var.WAIT_TB_TOKENS = min(var.WAIT_TB_TOKENS, var.WAIT_TB_BURST) + + now = datetime.now() + if ((var.LAST_WAIT and nick in var.LAST_WAIT and var.LAST_WAIT[nick] + + timedelta(seconds=var.WAIT_RATE_LIMIT) > now) + or var.WAIT_TB_TOKENS < 1): + cli.notice(nick, ("This command is rate-limited. Please wait a while " + "before using it again.")) + return + + var.LAST_WAIT[nick] = now + var.WAIT_TB_TOKENS -= 1 + if now > var.CAN_START_TIME: + var.CAN_START_TIME = now + timedelta(seconds=var.EXTRA_WAIT) + else: + var.CAN_START_TIME += timedelta(seconds=var.EXTRA_WAIT) + cli.msg(chan, ("\u0002{0}\u0002 increased the wait time by "+ + "{1} seconds.").format(nick, var.EXTRA_WAIT)) @cmd("fwait", admin_only=True, join=True) @@ -6610,8 +6619,6 @@ def fwait(cli, nick, chan, rest): else: var.CAN_START_TIME += timedelta(seconds=extra) - var.WAITED += 1 - cli.msg(chan, ("\u0002{0}\u0002 forcibly {2}creased the wait time by {1} " "second{3}.").format(nick, abs(extra),