Skip to content

fix(trades): reject rate terms that cannot describe a trade - #40

Merged
rolljee merged 1 commit into
masterfrom
fix/parse-rate-rejects-unusable-terms
Aug 15, 2026
Merged

fix(trades): reject rate terms that cannot describe a trade#40
rolljee merged 1 commit into
masterfrom
fix/parse-rate-rejects-unusable-terms

Conversation

@rolljee

@rolljee rolljee commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Follow-up to #39, which noted this in passing.

The bug

parseRate screened its result with hasNaN, which only catches NaN. Three other kinds of nonsense came back as numbers and travelled on into sellMetal / sellCrystal / sellDeut as if they were answers:

rate before why
'0:1.5:1' { deut: Infinity, crystal: Infinity } another term divided by zero
'2::1' { deut: 25, crystal: 0 } an empty term parses to 0, silently
'-2:1.5:1' { metal: -100, crystal: 75 } negative resources

None of the three describes a trade. Infinity and 0 are the bad ones: they reach a UI and get rendered.

The fix

The check now demands a real, strictly positive number for every normalized term — the only shape a worth can take. src/trades/utils.js goes from hasNaN to isUsableRate, its only caller being this one.

It stays on the result rather than the raw input for two reasons: every one of those cases surfaces there (as a NaN, an Infinity, a 0 or a negative ratio), and the unknown-reference-resource error must keep firing first — parseRate('0:0:0', 'gold') still says gold is not part of the game, which a test now pins.

Compatibility

No change for any usable rate. What changes is that three inputs which used to return a number now throw, which is what the README already promised ("Throws if the rate is malformed") and what the only shipped consumer already assumed:

  • ogame-ui screens its custom-rate form before calling, precisely because the library would not — so it never reaches this path.
  • og-bot-discord wraps every command in a try/catch, so a malformed rate falls back to the help message instead of printing Infinity. It is being bumped to v4 separately and gets its own message for this.

An all-negative rate like '-2:-1.5:-1' still passes, because it normalizes to exactly the same ratios as '2:1.5:1' — it is the same rate, written oddly.

Tests

0, empty and negative terms rejected across the three reference resources, the unknown-resource error still named, plus isUsableRate covered directly. Lint, types and 325 tests pass locally.

🤖 Generated with Claude Code

`parseRate` only screened its result for `NaN`, so three kinds of
nonsense came back as numbers and travelled on into `sellMetal` and
friends as if they were answers:

  '0:1.5:1'  -> another term divided by zero, so Infinity resources
  '2::1'     -> an empty term parses to 0, so 0 of that resource, silently
  '-2:1.5:1' -> negative resources

The check now runs on the normalized terms and demands a real, strictly
positive number, which is the only shape a worth can take. It stays on
the result rather than the raw input because every one of those cases
surfaces there as a NaN, an Infinity, a 0 or a negative ratio — and
because the unknown-reference-resource error must still come first.

Callers that passed a usable rate see no change. `ogame-ui` already
screened its custom-rate form for exactly these three, since the library
would not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rolljee
rolljee merged commit 173042c into master Aug 15, 2026
3 checks passed
@rolljee
rolljee deleted the fix/parse-rate-rejects-unusable-terms branch August 15, 2026 06:46
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 4.0.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant