Skip to content

Instantly share code, notes, and snippets.

@joshhunt
Created August 11, 2020 10:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshhunt/19a1dd58bfe15e7b8e9d605ab63e42cb to your computer and use it in GitHub Desktop.
Save joshhunt/19a1dd58bfe15e7b8e9d605ab63e42cb to your computer and use it in GitHub Desktop.
const round = (num) => Math.round((num + Number.EPSILON) * 100) / 100;
const DAYS_IN_A_YEAR = 365;
const VAT_MULTIPLIER = 1.05;
function priceCommand(plans, _annualUsage) {
const annualUsage = parseInt(_annualUsage);
const results = plans
.map((plan) => {
const standingCharge = plan.standing_charge || 0;
let cost = DAYS_IN_A_YEAR * standingCharge;
let remainingKwh = annualUsage;
for (const rate of plan.rates) {
if (!rate.threshold || rate.threshold > remainingKwh) {
cost += rate.price * remainingKwh;
break;
}
cost += rate.threshold * rate.price;
remainingKwh -= rate.threshold;
}
cost = cost * VAT_MULTIPLIER;
return { plan, cost };
})
.sort((a, b) => a.cost - b.cost)
.map((result) =>
[result.plan.supplier, result.plan.plan, round(result.cost / 100)].join(
","
)
);
return results;
}
function usageCommand(plans, supplier, planName, _cost) {
const cost = parseInt(_cost);
const plan = plans.find(
(v) => v.supplier === supplier && v.plan === planName
);
if (!plan) {
throw new Error("Could not find plan");
}
const annualSpend = (cost * 12 * 100) / VAT_MULTIPLIER; // in pence, remove VAT
const standingCharge = plan.standing_charge || 0;
const standingChargeSpend = standingCharge * DAYS_IN_A_YEAR;
const energyUsageSpend = annualSpend - standingChargeSpend;
let energyUsage = 0;
let remainingSpend = energyUsageSpend;
for (const rate of plan.rates) {
const energyConsumed = remainingSpend / rate.price;
if (rate.threshold && energyConsumed > rate.threshold) {
energyUsage += rate.threshold;
remainingSpend -= rate.price * rate.threshold;
} else {
energyUsage += energyConsumed;
break;
}
}
return [Math.round(energyUsage).toString()];
}
function exitCommand() {
process.exit(0);
}
function unknownCommand() {
return ["unknown command"];
}
module.exports = {
priceCommand,
usageCommand,
exitCommand,
unknownCommand,
};
const test = require("ava");
const { priceCommand, usageCommand } = require("./commands");
const plans = require("./plans.json");
test("price 1000", (t) => {
const result = priceCommand(plans, "1000");
t.deepEqual(result, [
"eon,variable,108.68",
"edf,fixed,111.25",
"ovo,standard,120.23",
"bg,standing-charge,121.33",
]);
});
test("price 2000", (t) => {
const result = priceCommand(plans, "2000");
t.deepEqual(result, [
"edf,fixed,205.75",
"eon,variable,213.68",
"bg,standing-charge,215.83",
"ovo,standard,235.73",
]);
});
test("usage edf fixed 350", (t) => {
const result = usageCommand(plans, "edf", "fixed", "350");
t.deepEqual(result, ["44267"]);
});
test("usage ovo standard 1000", (t) => {
const result = usageCommand(plans, "ovo", "standard", "1000");
t.deepEqual(result, ["103855"]);
});
test("usage bg standing-charge 120", (t) => {
const result = usageCommand(plans, "bg", "standing-charge", "120");
t.deepEqual(result, ["14954"]);
});
const readline = require("readline");
const path = require("path");
const {
priceCommand,
usageCommand,
exitCommand,
unknownCommand,
} = require("./commands");
const COMMANDS = {
price: priceCommand,
usage: usageCommand,
exit: exitCommand,
unknown: unknownCommand,
};
const plansPath = process.argv[2];
const plans = require(path.resolve(plansPath));
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false,
});
rl.on("line", function (line) {
const [command, ...args] = line.split(" ");
const commandFn = COMMANDS[command] || COMMANDS.unknown;
const results = commandFn(plans, ...args) || [];
results.forEach((line) => console.log(line));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment