!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.
This commit is contained in:
Janik Kleinhoff 2015-05-17 22:15:39 +00:00
parent f893d12cc6
commit dfd9405fe6
2 changed files with 32 additions and 22 deletions

View File

@ -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

View File

@ -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,22 +6573,28 @@ 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()):
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
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
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)
var.WAITED += 1
cli.msg(chan, ("\u0002{0}\u0002 increased the wait time by "+
"{1} seconds.").format(nick, var.EXTRA_WAIT))
@ -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),