Describe the issue
Let's see a problem on an example: Slag to Sour Water contract.
Raw data exported from the game source:
Quantity to pay with: 540
Quantity to buy: 218
Pay state: Loose (180 per ship module)
Buy state: Liquid (220 per ship module)
The game trading page states for 8-module ship: 1068 to 432. Which actually remains room for more goods. Correct values should have been 1080 to 436.
Your code in GetTradeEstimateForShipSize is a mess. 2 nested loops of iteration for no reason I could understand.
Let's do the different approach. Inputs are raw data and amount of modules = 8.
- Calculate module fill ratios for both products. They are 540/180 and 218/220 respectively.
- Divide them one over each other in a way we get a >1 ratio. We get 330/109. We also know here that Slag fills faster (I don't mean physical filling rates , I mean virtual "filling rate" in terms of internal contract ratio of 540/218).
- Add 1 to that ratio. We get 439/109. Then divide amount of modules by that new number. We get 872/439.
- Here, because buying product is the slower one, we ceil that number. Rule is that it's either ceil or floor, whatever gives us the most product bought. We get 2. This is an optimal amount of slower filling modules (Sour Water in our case). 6 Modules are reserved for faster filling Slag.
- Calculate full fill of Slag modules. 180 * 6 = 1080. Then deduce Sour Water amount from that number, using original 540/218 ratio, round it down to the next integer. If for some reason it became higher than 2 * 220, floor it to that, and recalculate Slag amount rounding up to the next integer. This should be probably decided by the same IF case from step 4, which decides if we floor or ceil there.
Algo may not be perfect and requires some edge casing in some contracts, but at least this is much faster than yours and produces a fully filled ship.
Expected behavior
1080 to 436