Skip to content

Instantly share code, notes, and snippets.

@joeytwiddle
Created April 30, 2019 04:40
Show Gist options
  • Save joeytwiddle/cb649dc34bc7a1bbddc6171cb29709cd to your computer and use it in GitHub Desktop.
Save joeytwiddle/cb649dc34bc7a1bbddc6171cb29709cd to your computer and use it in GitHub Desktop.
Cooldown Monitor
"use strict";
/*
Simulates an object which can heat up and overheat, but with a constant rate of cooling over time.
Useful for throttling when you want to provide an initial allowance.
For example, it could be used to manage the overheating of a weapon in a game, or to avoid errors from generating huge logfiles, but without throttling the first few errors.
*/
const defaultOptions = {
// Initial allowance before overheating occurs
maxTemp: 5,
// Optional cooling rate, provide just one (the defaults shown will cool by 1 temperature unit per second)
//cooldownPerSecond: 1/60,
//cooldownPerMinute: 1,
//cooldownPerHour: 60,
};
/*
Example usage:
// Allow 10 actions, but after that only allow 2 actions per minute
const cooldownMonitor = new CooldownMonitor({maxTemp: 10, cooldownPerMinute: 2});
// ...
if (cooldownMonitor.isOverheated()) {
// do nothing
} else {
cooldownMonitor.warm(1);
doSomeAction();
}
Notes:
With a cooldownPerMinute of 10, you may sometimes see more than 10 actions in one minute, due to the initial allowance (maxTemp).
*/
const CooldownMonitor = function (_opts) {
const opts = Object.assign({}, defaultOptions, _opts);
let lastCheckTime = Date.now();
let currentTemperature = 0;
//noinspection JSUnresolvedVariable
const coolingRatePerMs = opts.cooldownPerSecond ? opts.cooldownPerSecond / 1000
: opts.cooldownPerMinute ? opts.cooldownPerMinute / 60 / 1000
: opts.cooldownPerHour ? opts.cooldownPerHour / 60 / 60 / 1000
: 1000;
// Check for valid value (not NaN)
if (coolingRatePerMs >= 0) {
// ok
} else {
throw Error("Something is wrong with the cooldown rate: " + coolingRatePerMs);
}
function doUncountedCooling () {
const currentTime = Date.now();
const timeSinceLastCheck = currentTime - lastCheckTime;
const coolingAmount = coolingRatePerMs * timeSinceLastCheck;
currentTemperature -= coolingAmount;
if (currentTemperature < 0) {
currentTemperature = 0;
}
lastCheckTime = currentTime;
}
return {
/**
* @param [amount] - number of degrees to increase temperature by, defaults to 1
*/
warm: (amount) => {
if (amount == null) {
amount = 1;
}
doUncountedCooling();
currentTemperature += amount;
},
isOverheated: () => {
doUncountedCooling();
return currentTemperature > opts.maxTemp;
},
getTemperature: () => {
doUncountedCooling();
return currentTemperature;
},
};
};
module.exports = CooldownMonitor;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment