Write a RateLimiter(max_calls, window) class with one method, allow(now).
allow returns True when the caller is within its budget and records the call; it returns False and records nothing when the budget is spent.
The budget is max_calls within any window seconds, measured backwards from now. Calls older than the window no longer count.
Time is passed in rather than read from the clock, so the behaviour is testable. That is worth doing in real code too.