diff --git a/src/main/java/ClickerModel.java b/src/main/java/ClickerModel.java index 185b2a0..3a961ab 100644 --- a/src/main/java/ClickerModel.java +++ b/src/main/java/ClickerModel.java @@ -1,20 +1,22 @@ +import java.math.BigDecimal; import java.util.ArrayList; public class ClickerModel { - private double nicolas; + private BigDecimal nicolas; private final ArrayList upgradePanels; public ClickerModel() { upgradePanels = new ArrayList<>(); + nicolas = BigDecimal.ZERO; } - public double getNicolas() { + public BigDecimal getNicolas() { return nicolas; } - public void setNicolas(double nicolas) { + public void setNicolas(BigDecimal nicolas) { this.nicolas = nicolas; } @@ -26,11 +28,27 @@ public class ClickerModel { upgradePanels.forEach(UpgradePanel::refresh); } - public double getNPS() { - double nps = 0; + public BigDecimal getNPS() { + BigDecimal nps = BigDecimal.ZERO; for(UpgradePanel p : upgradePanels){ - nps += p.getNPS(); + nps = nps.add(p.getNPS()); } return nps; } + + public void addNicolas(long value) { + addNicolas(BigDecimal.valueOf(value)); + } + + public void addNicolas(BigDecimal value){ + nicolas = nicolas.add(value); + } + + public void removeNicolas(BigDecimal amount) { + nicolas = nicolas.subtract(amount); + } + + public ArrayList getUpgradePanels() { + return upgradePanels; + } } diff --git a/src/main/java/ClickerPresenter.java b/src/main/java/ClickerPresenter.java index 7f4c46e..d407f53 100644 --- a/src/main/java/ClickerPresenter.java +++ b/src/main/java/ClickerPresenter.java @@ -1,13 +1,16 @@ import javax.swing.*; +import java.math.BigDecimal; public class ClickerPresenter { public static final int TARGET_FPS = 30; + public static final int MAX_UPGRADE_FACTOR = 100000; + private final ClickerView clickerView; private final ClickerModel clickerModel; - private double upgradeFactor = 1; + private int upgradeFactor = 1; LargeFormatter formatter = new LargeFormatter(); @@ -25,7 +28,7 @@ public class ClickerPresenter { addPanel(new UpgradePanel("Debugger", 1, 1, 1000000000, this)); - + clickerModel.getUpgradePanels().forEach(UpgradePanel::recalculateUpgradeButtonText); Timer loop = new Timer(1000 / TARGET_FPS, e -> refresh()); loop.start(); } @@ -37,7 +40,7 @@ public class ClickerPresenter { public void nicolasButtonClick() { - clickerModel.setNicolas(clickerModel.getNicolas() + 1); + clickerModel.addNicolas(1); } private void refresh() { @@ -46,27 +49,32 @@ public class ClickerPresenter { clickerModel.refresh(); } - public void removeNicolas(double amount) { - clickerModel.setNicolas(clickerModel.getNicolas() - amount); + public void removeNicolas(BigDecimal amount) { + clickerModel.removeNicolas(amount); } - public double getNicolas() { + public BigDecimal getNicolas() { return clickerModel.getNicolas(); } - public void addNicolas(double gain) { - clickerModel.setNicolas(clickerModel.getNicolas() + gain); + public void addNicolas(long value) { + addNicolas(BigDecimal.valueOf(value)); + } + + public void addNicolas(BigDecimal gain) { + clickerModel.addNicolas(gain); } public String changeFactor() { upgradeFactor *= 10; - if (upgradeFactor > 1000) { + if (upgradeFactor > MAX_UPGRADE_FACTOR) { upgradeFactor = 1; } - return String.format("%,.0fx", upgradeFactor); + clickerModel.getUpgradePanels().forEach(UpgradePanel::recalculateUpgradeButtonText); + return String.format("%,dx", upgradeFactor); } - public double getUpgradeFactor() { + public int getUpgradeFactor() { return upgradeFactor; } diff --git a/src/main/java/LargeFormatter.java b/src/main/java/LargeFormatter.java index aa20de0..51b90f7 100644 --- a/src/main/java/LargeFormatter.java +++ b/src/main/java/LargeFormatter.java @@ -1,16 +1,22 @@ +import java.math.BigDecimal; + public class LargeFormatter { private static final String[] suffixes = {"", "k", "M", "B", "T", "q", "Q", "s", "S", "O", "N"}; //private static final String[] suffixes = {"", "k"}; //for large number testing + private static final BigDecimal _999 = BigDecimal.valueOf(999); + private static final BigDecimal THOUSAND = BigDecimal.valueOf(100); + private static final BigDecimal TEN = BigDecimal.TEN; + //input: 10 230 000 -> 10.23M - public String formatBigNumber(double number) { + public String formatDouble(double number) { int suffixSize = 0; boolean scientific = false; while (number > 999) { - if(suffixSize == suffixes.length - 1){ + if (suffixSize == suffixes.length - 1) { scientific = true; break; } @@ -19,15 +25,50 @@ public class LargeFormatter { number /= 1000; } - if(scientific){ + if (scientific) { int exp = 3 * suffixSize; - while(number >= 10){ + while (number >= 10) { exp++; number /= 10; } return String.format("%.2fE%d", number, exp); } else { - if(Math.floor(number) == number){ + if (Math.floor(number) == number) { + return String.format("%.0f%s", number, suffixes[suffixSize]); + } else { + return String.format("%.2f%s", number, suffixes[suffixSize]); + } + } + } + + public String formatBigNumber(BigDecimal number) { + if(number == null){ + System.err.println("NUMBER IS NULL "); + return ""; + } + int suffixSize = 0; + boolean scientific = false; + + while (number.compareTo(_999) > 0) { + + if (suffixSize == suffixes.length - 1) { + scientific = true; + break; + } + + suffixSize++; + number = number.divide(THOUSAND); + } + + if (scientific) { + int exp = 3 * suffixSize; + while (number.compareTo(TEN) >= 0) { + exp++; + number = number.divide(TEN); + } + return String.format("%.2fE%d", number, exp); + } else { + if (false) { //TODO implement better solution return String.format("%.0f%s", number, suffixes[suffixSize]); } else { return String.format("%.2f%s", number, suffixes[suffixSize]); diff --git a/src/main/java/UpgradePanel.java b/src/main/java/UpgradePanel.java index b8d7468..c3388bd 100644 --- a/src/main/java/UpgradePanel.java +++ b/src/main/java/UpgradePanel.java @@ -1,4 +1,6 @@ import javax.swing.*; +import java.math.BigDecimal; +import java.math.RoundingMode; public class UpgradePanel extends JPanel { @@ -11,11 +13,11 @@ public class UpgradePanel extends JPanel { private String name; - private final double costMultiplier; + private final BigDecimal costMultiplier; private final double baseGain; - private double cost; - private double gain = 0; + private BigDecimal cost; + private BigDecimal gain = BigDecimal.ZERO; private int level; private long lastAddedTimeStamp = 0; @@ -24,12 +26,14 @@ public class UpgradePanel extends JPanel { private final ClickerPresenter presenter; private final LargeFormatter lf = new LargeFormatter(); + private String upgradeButtonText = ""; + public UpgradePanel(String name, double baseCost, double costMultiplier, double baseGain, ClickerPresenter presenter) { add(mainPanel); this.name = name; - this.cost = baseCost; - this.costMultiplier = costMultiplier; + this.cost = new BigDecimal(baseCost); + this.costMultiplier = BigDecimal.valueOf(costMultiplier); this.baseGain = baseGain; this.presenter = presenter; @@ -38,62 +42,70 @@ public class UpgradePanel extends JPanel { upgradeButton.addActionListener(e -> upgrade(presenter.getUpgradeFactor())); } - public void upgrade(double amount) { + public void upgrade(int amount) { presenter.removeNicolas(calculateExp(cost, costMultiplier, amount)); - gain += baseGain * amount; + gain = gain.add(new BigDecimal(baseGain * amount)); level += amount; - cost *= Math.pow(costMultiplier, amount); + cost = cost.multiply(costMultiplier.pow(amount)); + + recalculateUpgradeButtonText(); } public void refresh() { - upgradeButton.setEnabled(presenter.getNicolas() >= calculateExp(cost, costMultiplier, presenter.getUpgradeFactor())); + upgradeButton.setEnabled(presenter.getNicolas().compareTo(calculateExp(cost, costMultiplier, presenter.getUpgradeFactor())) >= 0); - //should nicolas be added? long currentTime = System.currentTimeMillis(); - long lastAddDeltaTime = currentTime - lastAddedTimeStamp; - double timePerNicolas = 1 / gain * 1000; + if (gain.compareTo(BigDecimal.ZERO) > 0) { + //should nicolas be added? + double lastAddDeltaTime = currentTime - lastAddedTimeStamp; + double inverseLastAddDeltaTime = 1 / (lastAddDeltaTime / 1000); - if (timePerNicolas < lastAddDeltaTime) { - //add nicolas - long frameDeltaTime = currentTime - lastFrameTimeStamp; + //gain=2 tpn=0.5 ladt=1000 laps=1 + if (gain.compareTo(BigDecimal.valueOf(inverseLastAddDeltaTime)) > 0) { + double frameDeltaTime = currentTime - lastFrameTimeStamp; + BigDecimal inverseFrameDeltaTime = BigDecimal.valueOf(1 / (frameDeltaTime / 1000)); + lastAddedTimeStamp = currentTime; - System.out.printf("tpn=%.2f ladt=%d Δt=%d", timePerNicolas, lastAddDeltaTime, frameDeltaTime); - lastAddedTimeStamp = currentTime; - - - if (timePerNicolas < frameDeltaTime) { - double missedNicolas = frameDeltaTime / timePerNicolas; - System.out.printf(" FN mn=%.2f gain=%.2f add=%.2f", missedNicolas, gain, missedNicolas); - presenter.addNicolas(missedNicolas); - } else { - presenter.addNicolas(1); + if (gain.compareTo(inverseFrameDeltaTime) > 0) { + //normal: dt/tpn inverse: gain/idt + System.out.println(inverseFrameDeltaTime + " " + gain); + BigDecimal missedNicolas = gain.divide(inverseFrameDeltaTime, 0, RoundingMode.HALF_UP); /*frameDeltaTime / timePerNicolas*/ + System.out.println(missedNicolas); + presenter.addNicolas(missedNicolas); + } else { + presenter.addNicolas(1); + } } - - System.out.print("\n"); } + lastFrameTimeStamp = currentTime; levelLabel.setText("Level: " + level); gainLabel.setText(lf.formatBigNumber(gain) + " Nicolas"); - upgradeButton.setText(String.format("%,.0fx Upgrade: %s Nicolas", - presenter.getUpgradeFactor(), lf.formatBigNumber(calculateExp(cost, costMultiplier, presenter.getUpgradeFactor())))); + upgradeButton.setText(upgradeButtonText); } - private double calculateExp(double c, double fac, double amount) { + private BigDecimal calculateExp(BigDecimal c, BigDecimal fac, long amount) { //x10 cost = c + c*x + c*x*x + c*x*x*x... = c * x^1 + c*x^2 + c*x^3 + c*x^4 + c*x^5... = // c * (x^0 + x^1 + x^2 + x^3...) //new cost = c * x^amount - double result = 0; + BigDecimal result = BigDecimal.ZERO; for (int i = 0; i < amount; i++) { - result += Math.pow(fac, i); + result = result.add(fac.pow(i)); + } - return result * c; + return result.multiply(c); } - public double getNPS() { + public BigDecimal getNPS() { return gain; } + + public void recalculateUpgradeButtonText() { + upgradeButtonText = String.format("%,dx Upgrade: %s Nicolas", + presenter.getUpgradeFactor(), lf.formatBigNumber(calculateExp(cost, costMultiplier, presenter.getUpgradeFactor()))); + } } diff --git a/src/test/java/LargeFormatterLargeTest.java b/src/test/java/LargeFormatterLargeTest.java index b640f74..bcd6069 100644 --- a/src/test/java/LargeFormatterLargeTest.java +++ b/src/test/java/LargeFormatterLargeTest.java @@ -16,34 +16,34 @@ class LargeFormatterLargeTest { void normal(){ double n = 100000; String s = "100k"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void smallestSci(){ double n = 1000000; String s = "1.00E6"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void biggerSci(){ double n = 10000000; String s = "1.00E7"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void decimalSci(){ double n = 16900000; String s = "1.69E7"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void pointNine(){ double n = 9780000; String s = "9.78E6"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } } \ No newline at end of file diff --git a/src/test/java/LargeFormatterTest.java b/src/test/java/LargeFormatterTest.java index 9b1929e..de1594c 100644 --- a/src/test/java/LargeFormatterTest.java +++ b/src/test/java/LargeFormatterTest.java @@ -16,27 +16,27 @@ class LargeFormatterTest { void tinyNumberTest(){ double n = 0.1; String s = "0.10"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void smallNumberTest(){ double n = 10; String s = "10"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void kTest(){ double n = 1000; String s = "1k"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } @Test void mTest(){ double n = 10230000; String s = "10.23M"; - assertEquals(s, lf.formatBigNumber(n)); + assertEquals(s, lf.formatDouble(n)); } } \ No newline at end of file