# coding: utf8
import time


class Funnel(object):

    def __init__(self, capacity, leaking_rate):
        self.capacity = capacity  # 漏斗容量
        self.leaking_rate = leaking_rate  # 漏嘴流水速率
        self.left_quota = capacity  # 漏斗剩余空间
        self.leaking_ts = time.time()  # 上一次漏水时间

    def make_space(self):
        now_ts = time.time()
        delta_ts = now_ts - self.leaking_ts  # 距离上一次漏水过去了多久
        delta_quota = delta_ts * self.leaking_rate  # 又可以腾出不少空间了
        if delta_quota < 1:  # 腾的空间太少，那就等下次吧
            return
        self.left_quota += delta_quota  # 增加剩余空间
        self.leaking_ts = now_ts  # 记录漏水时间
        if self.left_quota > self.capacity:  # 剩余空间不得高于容量
            self.left_quota = self.capacity

    def watering(self, quota):
        self.make_space()
        if self.left_quota >= quota:  # 判断剩余空间是否足够
            self.left_quota -= quota
            return True
        return False


funnels = {}  # 所有的漏斗


# capacity  漏斗容量
# leaking_rate 漏嘴流水速率 quota/s
def is_action_allowed(user_id, action_key, capacity, leaking_rate):
    key = '%s:%s' % (user_id, action_key)
    funnel = funnels.get(key)
    if not funnel:
        funnel = Funnel(capacity, leaking_rate)
        funnels[key] = funnel
    return funnel.watering(1)


for i in range(20):
    print(is_action_allowed('laoqian', 'reply', 3, 0.5))
    time.sleep(1)

# output    delta_ts    delta_quota    left_quota   delta_quota
# True       0              0               2           0
# True       1              0.5             1           0
# True       2              1               1           1
# True      1               0.5             0           0
# True      2               1               0           1
# False     1               0.5             0           0
# True
# False
# True
# False
# True
# False
# True
# False
# True
# False
# True
# False
# True
# False

# coding: utf8
import time


class Funnel(object):

    def __init__(self, capacity, leaking_rate):
        self.capacity = capacity  # 漏斗容量
        self.leaking_rate = leaking_rate  # 漏嘴流水速率
        self.left_quota = capacity  # 漏斗剩余空间
        self.leaking_ts = time.time()  # 上一次漏水时间

    def make_space(self):
        now_ts = time.time()
        delta_ts = now_ts - self.leaking_ts  # 距离上一次漏水过去了多久
        delta_quota = delta_ts * self.leaking_rate  # 又可以腾出不少空间了
        if delta_quota < 1:  # 腾的空间太少，那就等下次吧
            return
        self.left_quota += delta_quota  # 增加剩余空间
        self.leaking_ts = now_ts  # 记录漏水时间
        if self.left_quota > self.capacity:  # 剩余空间不得高于容量
            self.left_quota = self.capacity

    def watering(self, quota):
        self.make_space()
        if self.left_quota >= quota:  # 判断剩余空间是否足够
            self.left_quota -= quota
            return True
        return False


funnels = {}  # 所有的漏斗


# capacity  漏斗容量
# leaking_rate 漏嘴流水速率 quota/s
def is_action_allowed(user_id, action_key, capacity, leaking_rate):
    key = '%s:%s' % (user_id, action_key)
    funnel = funnels.get(key)
    if not funnel:
        funnel = Funnel(capacity, leaking_rate)
        funnels[key] = funnel
    return funnel.watering(1)


for i in range(20):
    print(is_action_allowed('laoqian', 'reply', 3, 0.5))
    time.sleep(1)

# output    delta_ts    delta_quota    left_quota   delta_quota
# True       0              0               2           0
# True       1              0.5             1           0
# True       2              1               1           1
# True      1               0.5             0           0
# True      2               1               0           1
# False     1               0.5             0           0
# True
# False
# True
# False
# True
# False
# True
# False
# True
# False
# True
# False
# True
# False

# coding: utf8 # 漏斗容量 # 漏嘴流水速率 # 漏斗剩余空间 # 上一次漏水时间 # 距离上一次漏水过去了多久 # 又可以腾出不少空间了 # 腾的空间太少，那就等下次吧 # 增加剩余空间 # 记录漏水时间 # 剩余空间不得高于容量 # 判断剩余空间是否足够 # 所有的漏斗 # capacity  漏斗容量 # leaking_rate 漏嘴流水速率 quota/s # output    delta_ts    delta_quota    left_quota   delta_quota # True       0              0               2           0 # True       1              0.5             1           0 # True       2              1               1           1 # True      1               0.5             0           0 # True      2               1               0           1 # False     1               0.5             0           0 # True # False # True # False # True # False # True # False # True # False # True # False # True # False