diff --git a/README.md b/README.md index 2cc23a4..ad4d9e7 100644 --- a/README.md +++ b/README.md @@ -373,6 +373,13 @@ Ogame.Trader.parseRate('3:2:1', 'deut'); // → { rateMetal: 3, rateCrystal: 2, rateDeut: 1 } ``` +The reference term always comes back as `1`, so a rate and any multiple of it are the same rate, whichever resource you sell: + +```javascript +Ogame.Trader.parseRate('4:3:2', 'deut'); +// → { rateMetal: 2, rateCrystal: 1.5, rateDeut: 1 } — same as '2:1.5:1' +``` + ### `Ogame.i18n` Every model entry carries `names: { en, fr }`. diff --git a/src/trades/deut.test.js b/src/trades/deut.test.js index cc69d57..83cf40e 100644 --- a/src/trades/deut.test.js +++ b/src/trades/deut.test.js @@ -6,4 +6,11 @@ describe('A deut trade', () => { expect(metal).toBe(100000); expect(crystal).toBe(75000); }); + + // `4:3:2` is the same rate as `2:1.5:1`; it used to pay twice as much. + it('Sells the same deut for the same amount at an equivalent rate', () => { + const { metal, crystal } = sellDeut(100000, 50, 50, '4:3:2'); + expect(metal).toBe(100000); + expect(crystal).toBe(75000); + }); }); diff --git a/src/trades/parseRate.js b/src/trades/parseRate.js index eea1aae..df20ff8 100644 --- a/src/trades/parseRate.js +++ b/src/trades/parseRate.js @@ -20,9 +20,14 @@ function extract(rate, type) { rateDeut: deut / crystal, }; } else if (type === 'deut') { + // Like the two branches above: express the other terms in units of the one + // being sold, so its own term becomes 1. Reading `metal` and `crystal` raw + // here only happened to work because rates are usually written against 1 + // deuterium — `4:3:2` is the same rate as `2:1.5:1`, but used to pay twice + // as much for the very same deuterium. res = { - rateMetal: metal, - rateCrystal: crystal, + rateMetal: metal / deut, + rateCrystal: crystal / deut, rateDeut: 1, }; } else { diff --git a/src/trades/parseRate.test.js b/src/trades/parseRate.test.js index 0d46d74..6326752 100644 --- a/src/trades/parseRate.test.js +++ b/src/trades/parseRate.test.js @@ -27,6 +27,26 @@ describe('Parse rate given a resource and a rate', () => { }); }); + // Normalizing means expressing the other two terms in units of the reference + // resource, whichever one it is. The deut branch used to read the metal and + // crystal terms raw, so a rate written against anything but 1 deuterium came + // back scaled. + it('Parse rate by selling deut when the deut term is not 1', () => { + const res = parseRate('4:3:2', 'deut'); + expect(res).toEqual({ + rateMetal: 2, + rateCrystal: 1.5, + rateDeut: 1, + }); + }); + + it('Reads equivalent rates identically, whichever resource is sold', () => { + ['metal', 'crystal', 'deut'].forEach((type) => { + expect(parseRate('4:3:2', type)).toEqual(parseRate('2:1.5:1', type)); + expect(parseRate('10:7.5:5', type)).toEqual(parseRate('2:1.5:1', type)); + }); + }); + it('Should return an error if rate is not correctly specified', () => { try { const res = parseRate('3:toto:1');