From 6e0fe0557627efa4928f1e028a7cf6956ead90ac Mon Sep 17 00:00:00 2001 From: iMoHax Date: Mon, 13 Jul 2015 15:19:00 +0300 Subject: [PATCH] implement compute min and max fuel for jump to distance --- core/src/main/java/ru/trader/core/Ship.java | 89 +++++++++++++++---- .../test/java/ru/trader/core/ShipTest.java | 77 ++++++++++++++++ 2 files changed, 150 insertions(+), 16 deletions(-) create mode 100644 core/src/test/java/ru/trader/core/ShipTest.java diff --git a/core/src/main/java/ru/trader/core/Ship.java b/core/src/main/java/ru/trader/core/Ship.java index 2c0eb3f..f8de840 100644 --- a/core/src/main/java/ru/trader/core/Ship.java +++ b/core/src/main/java/ru/trader/core/Ship.java @@ -31,6 +31,7 @@ public class Ship { public void setCargo(int cargo) { this.cargo = cargo; + fuelTable = null; } public Engine getEngine() { @@ -38,11 +39,12 @@ public class Ship { } public void setEngine(int clazz, char rating) { - this.engine = new Engine(clazz, rating); + setEngine(new Engine(clazz, rating)); } public void setEngine(Engine engine) { this.engine = engine; + fuelTable = null; } public double getTank() { @@ -59,6 +61,7 @@ public class Ship { public void setMass(double mass) { this.mass = mass; + fuelTable = null; } public double getLadenMass(){ @@ -69,41 +72,49 @@ public class Ship { return mass+fuel+cargo; } - //Laden fuel cost - public double getFuelCost(double distance){ - return engine.getFuelCost(distance, getLadenMass(getRoundMaxFuel(distance))); - } - public double getFuelCost(double fuel, double distance){ return engine.getFuelCost(distance, getLadenMass(fuel)); } + public double getMaxFuelCost(double distance){ + return engine.getMaxFuel(distance, getLadenMass(engine.getMaxFuel())); + } + public double getRoundMaxFuel(double distance){ return getRoundMaxFuel(distance, REFILL_FUEL_STEP); } + public double getRoundFuel(double fuel){ + return getRoundFuel(fuel, REFILL_FUEL_STEP); + } + + public double getRoundFuel(double fuel, int step){ + fuel = Math.floor(fuel*step/tank) * tank / step; + return fuel < 0 ? 0 : fuel; + + } + private double getRoundMaxFuel(double distance, int step){ double fuel = getMaxFuel(distance); if (fuel == 0 || fuel == tank) return fuel; - double minFuel = engine.getFuelCost(distance, getLadenMass(0)); + double minFuel = getMinFuel(distance); fuel = Math.floor(fuel*step/tank) * tank / step; return fuel < minFuel ? 0 : fuel; } - public double getMaxFuel(double distance){ - double fuel = engine.getMaxFuel(distance, getLadenMass(0)); - if (fuel >= tank) return tank; - return fuel; - - } - public double getMaxJumpRange(){ - return getJumpRange(Math.min(engine.getMaxFuel(), tank)); + if (Double.isNaN(maxJumpRange)){ + maxJumpRange = getJumpRange(Math.min(engine.getMaxFuel(), tank)); + } + return maxJumpRange; } //Jump range with full fuel tank public double getJumpRange(){ - return getJumpRange(tank); + if (Double.isNaN(ladenJumpRange)){ + ladenJumpRange = getJumpRange(tank); + } + return ladenJumpRange; } //Laden jump range @@ -208,6 +219,7 @@ public class Ship { return getMultiplier() * Math.pow(distance * (mass / getOptMass()), getPowMultiplier()); } + //return max fuel for jump to distance public double getMaxFuel(double distance, double emptyTankMass){ double f = Math.pow(getMaxFuel()/getMultiplier(), 1/getPowMultiplier())*getOptMass()/distance - emptyTankMass; return f < getMaxFuel() ? 0 : f; @@ -224,4 +236,49 @@ public class Ship { ", fuelPJ="+getMaxFuel()+"}"; } } + + private final static float FUEL_TABLE_STEP = 0.01f; + private FuelHelper[] fuelTable; + private double maxJumpRange = Double.NaN; + private double ladenJumpRange = Double.NaN; + private void fillFuelTable(){ + double fuel = getEngine().getMaxFuel(); + fuelTable = new FuelHelper[(int) (fuel/FUEL_TABLE_STEP)]; + maxJumpRange = Double.NaN; ladenJumpRange = Double.NaN; + for (int i = fuelTable.length - 1; i >= 0; i--) { + double distance = getJumpRange(fuel); + fuelTable[i] = new FuelHelper(distance, fuel); + fuel = fuel - FUEL_TABLE_STEP; + } + } + + public double getMaxFuel(double distance){ + if (distance > getMaxJumpRange()) return 0; + if (distance <= getJumpRange()) return tank; + return engine.getMaxFuel(distance, getLadenMass(0)); + } + + public double getMinFuel(double distance){ + if (fuelTable == null) fillFuelTable(); + if (distance > getMaxJumpRange()) return 0; + for (int i = 0; i < fuelTable.length; i++) { + FuelHelper h = fuelTable[i]; + if (distance <= h.distance) { + return i == 0 ? 0 : h.fuel <= tank ? h.fuel : 0; + } + } + return 0; + } + + private class FuelHelper { + private final double distance; + private final double fuel; + + private FuelHelper(double distance, double fuel) { + this.distance = distance; + this.fuel = fuel; + } + } + + } diff --git a/core/src/test/java/ru/trader/core/ShipTest.java b/core/src/test/java/ru/trader/core/ShipTest.java new file mode 100644 index 0000000..b59e61e --- /dev/null +++ b/core/src/test/java/ru/trader/core/ShipTest.java @@ -0,0 +1,77 @@ +package ru.trader.core; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ShipTest extends Assert { + private final static Logger LOG = LoggerFactory.getLogger(ShipTest.class); + + @Test + public void testShip() throws Exception { + Ship ship = new Ship(); + ship.setCargo(440); ship.setTank(15); + ship.setEngine(5, 'A'); ship.setMass(466); + + assertEquals(906, ship.getLadenMass(0), 0.0000001); + assertEquals(913, ship.getLadenMass(7), 0.0000001); + assertEquals(921, ship.getLadenMass(15), 0.0000001); + assertEquals(921, ship.getLadenMass(), 0.0000001); + + assertEquals(13.373, ship.getJumpRange(), 0.001); + assertEquals(13.373, ship.getJumpRange(15), 0.001); + assertEquals(13.446, ship.getJumpRange(10), 0.001); + assertEquals(13.519, ship.getJumpRange(5), 0.001); + assertEquals(9.332, ship.getJumpRange(2), 0.001); + assertEquals(0, ship.getJumpRange(0), 0.001); + assertEquals(13.519, ship.getMaxJumpRange(), 0.001); + assertEquals(40.339, ship.getFullTankJumpRange(), 0.001); + + assertEquals(0, ship.getMinFuel(0), 0.01); + assertEquals(0.44, ship.getMinFuel(5), 0.01); + assertEquals(2.38, ship.getMinFuel(10), 0.01); + assertEquals(4.54, ship.getMinFuel(13), 0.01); + assertEquals(4.94, ship.getMinFuel(13.45), 0.01); + assertEquals(5, ship.getMinFuel(13.519), 0.01); + assertEquals(0, ship.getMinFuel(14), 0.01); + assertEquals(0, ship.getMinFuel(20), 0.01); + + assertEquals(15, ship.getMaxFuel(0), 0.01); + assertEquals(15, ship.getMaxFuel(5), 0.01); + assertEquals(15, ship.getMaxFuel(10), 0.01); + assertEquals(15, ship.getMaxFuel(13), 0.01); + assertEquals(9.73, ship.getMaxFuel(13.45), 0.01); + assertEquals(5.05, ship.getMaxFuel(13.519), 0.01); + assertEquals(0, ship.getMaxFuel(14), 0.01); + assertEquals(0, ship.getMaxFuel(20), 0.01); + + assertEquals(15, ship.getRoundMaxFuel(0), 0.01); + assertEquals(15, ship.getRoundMaxFuel(5), 0.01); + assertEquals(15, ship.getRoundMaxFuel(10), 0.01); + assertEquals(15, ship.getRoundMaxFuel(13), 0.01); + assertEquals(9, ship.getRoundMaxFuel(13.45), 0.01); + assertEquals(0, ship.getRoundMaxFuel(13.519), 0.01); + assertEquals(0, ship.getRoundMaxFuel(14), 0.01); + assertEquals(0, ship.getRoundMaxFuel(20), 0.01); + + assertEquals(0, ship.getFuelCost(15, 0), 0.001); + assertEquals(0.448, ship.getFuelCost(15, 5), 0.001); + assertEquals(2.453, ship.getFuelCost(15, 10), 0.001); + assertEquals(4.665, ship.getFuelCost(15, 13), 0.001); + assertEquals(5.070, ship.getFuelCost(15, 13.45), 0.001); + assertEquals(5.134, ship.getFuelCost(15, 13.519), 0.001); + assertEquals(5.593, ship.getFuelCost(15, 14), 0.001); + assertEquals(13.403, ship.getFuelCost(15, 20), 0.001); + + assertEquals(0, ship.getFuelCost(5, 0), 0.001); + assertEquals(0.437, ship.getFuelCost(5, 5), 0.001); + assertEquals(2.388, ship.getFuelCost(5, 10), 0.001); + assertEquals(4.542, ship.getFuelCost(5, 13), 0.001); + assertEquals(4.936, ship.getFuelCost(5, 13.45), 0.001); + assertEquals(4.999, ship.getFuelCost(5, 13.519), 0.001); + assertEquals(5.446, ship.getFuelCost(5, 14), 0.001); + assertEquals(13.050, ship.getFuelCost(5, 20), 0.001); + + } +}