"""Offline cache accounting calculator. USD; no dependencies or network calls.""" from dataclasses import dataclass from decimal import Decimal import unittest D = Decimal MILLION = D(1_000_000) @dataclass(frozen=True) class Rates: ordinary: Decimal write: Decimal read: Decimal output: Decimal def cost(ordinary, written, read, output, rates, storage_usd="0"): counts = (ordinary, written, read, output) if any(type(n) is not int or n < 0 for n in counts): raise ValueError("Counts must be nonnegative integers") if any(not p.is_finite() or p < 0 for p in (rates.ordinary, rates.write, rates.read, rates.output)): raise ValueError("Rates must be finite and nonnegative") storage = D(storage_usd) if not storage.is_finite() or storage < 0: raise ValueError("Storage must be finite and nonnegative") return sum((D(n) * p for n, p in zip(counts, (rates.ordinary, rates.write, rates.read, rates.output))), D(0)) / MILLION + storage def campaign(requests, prefix, suffix, output, writes, hits, rates): if any(type(n) is not int or n < 0 for n in (requests, prefix, suffix, output, writes, hits)): raise ValueError("Campaign counts must be nonnegative integers") if writes + hits > requests: raise ValueError("Writes and hits exceed requests") misses = requests - writes - hits return cost(requests * suffix + misses * prefix, writes * prefix, hits * prefix, requests * output, rates) SOL = Rates(D("2"), D("2.50"), D("0.10"), D("10")) class Tests(unittest.TestCase): def test_baseline(self): self.assertEqual(campaign(100, 20000, 2000, 1000, 0, 0, SOL), D("5.4")) def test_warm(self): self.assertEqual(campaign(100, 20000, 2000, 1000, 1, 99, SOL), D("1.648")) def test_five_epochs(self): self.assertEqual(campaign(100, 20000, 2000, 1000, 5, 95, SOL), D("1.84")) def test_every_request_writes(self): self.assertEqual(campaign(100, 20000, 2000, 1000, 100, 0, SOL), D("6.4")) def test_storage(self): self.assertEqual(cost(0, 0, 0, 0, SOL, "0.01"), D("0.01")) def test_invalid(self): for args in ((1, 1, 1, 1, 1, 1), (1, -1, 1, 1, 0, 0), (1.0, 1, 1, 1, 0, 0)): with self.assertRaises(ValueError): campaign(*args, SOL) with self.assertRaises(ValueError): cost(0, 0, 0, 0, SOL, "-1") def test_nonfinite_money(self): for invalid in ("NaN", "Infinity", "-Infinity"): with self.assertRaises(ValueError): cost(0, 0, 0, 0, SOL, invalid) with self.assertRaises(ValueError): cost(1, 0, 0, 0, Rates(D(invalid), SOL.write, SOL.read, SOL.output)) if __name__ == "__main__": result = unittest.main(exit=False) if not result.result.wasSuccessful(): raise SystemExit(1) for label, writes, hits in (("No cache", 0, 0), ("Warm", 1, 99), ("Five epochs", 5, 95), ("Write churn", 100, 0)): print(f"{label}: ${campaign(100, 20000, 2000, 1000, writes, hits, SOL):.3f}")