38 lines
1.5 KiB
JavaScript
38 lines
1.5 KiB
JavaScript
// Pure math helpers. No state, no DOM.
|
|
|
|
export function clamp(value, min, max) {
|
|
return Math.min(max, Math.max(min, value));
|
|
}
|
|
|
|
/** Price of the next item when `owned` items are already owned. */
|
|
export function unitCost(base, growth, owned) {
|
|
return base * growth ** owned;
|
|
}
|
|
|
|
/** Total price of buying `count` more items (geometric series, rounded up). */
|
|
export function bulkCost(base, growth, owned, count) {
|
|
if (count <= 0) return 0;
|
|
return Math.ceil((unitCost(base, growth, owned) * (growth ** count - 1)) / (growth - 1));
|
|
}
|
|
|
|
/** How many items `budget` can pay for, robust against float error. */
|
|
export function maxAffordable(base, growth, owned, budget) {
|
|
const first = unitCost(base, growth, owned);
|
|
if (Number.isNaN(budget) || budget < first) return 0;
|
|
let n = Math.floor(Math.log((budget * (growth - 1)) / first + 1) / Math.log(growth));
|
|
while (n > 0 && bulkCost(base, growth, owned, n) > budget) n--;
|
|
while (bulkCost(base, growth, owned, n + 1) <= budget) n++;
|
|
return Math.max(n, 0);
|
|
}
|
|
|
|
/**
|
|
* Units customers want to buy per second at `price`.
|
|
* Demand is maxed at or below the fair price and drops steeply above it, so
|
|
* extra production is only worth selling at a higher price while supply is
|
|
* short; to sell more at the fair price, the player needs more demand.
|
|
*/
|
|
export function demandPerSecond(market, price, multiplier) {
|
|
const overpriced = Math.max(1, price / market.fairPrice);
|
|
return (market.baseDemand * multiplier) / overpriced ** market.elasticity;
|
|
}
|