BigDecimal switch

This commit is contained in:
nora 2021-01-10 21:39:38 +01:00
parent 31a219b3e2
commit 94a169b421
6 changed files with 144 additions and 65 deletions

View file

@ -1,20 +1,22 @@
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
public class ClickerModel { public class ClickerModel {
private double nicolas; private BigDecimal nicolas;
private final ArrayList<UpgradePanel> upgradePanels; private final ArrayList<UpgradePanel> upgradePanels;
public ClickerModel() { public ClickerModel() {
upgradePanels = new ArrayList<>(); upgradePanels = new ArrayList<>();
nicolas = BigDecimal.ZERO;
} }
public double getNicolas() { public BigDecimal getNicolas() {
return nicolas; return nicolas;
} }
public void setNicolas(double nicolas) { public void setNicolas(BigDecimal nicolas) {
this.nicolas = nicolas; this.nicolas = nicolas;
} }
@ -26,11 +28,27 @@ public class ClickerModel {
upgradePanels.forEach(UpgradePanel::refresh); upgradePanels.forEach(UpgradePanel::refresh);
} }
public double getNPS() { public BigDecimal getNPS() {
double nps = 0; BigDecimal nps = BigDecimal.ZERO;
for(UpgradePanel p : upgradePanels){ for(UpgradePanel p : upgradePanels){
nps += p.getNPS(); nps = nps.add(p.getNPS());
} }
return nps; 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<UpgradePanel> getUpgradePanels() {
return upgradePanels;
}
} }

View file

@ -1,13 +1,16 @@
import javax.swing.*; import javax.swing.*;
import java.math.BigDecimal;
public class ClickerPresenter { public class ClickerPresenter {
public static final int TARGET_FPS = 30; public static final int TARGET_FPS = 30;
public static final int MAX_UPGRADE_FACTOR = 100000;
private final ClickerView clickerView; private final ClickerView clickerView;
private final ClickerModel clickerModel; private final ClickerModel clickerModel;
private double upgradeFactor = 1; private int upgradeFactor = 1;
LargeFormatter formatter = new LargeFormatter(); LargeFormatter formatter = new LargeFormatter();
@ -25,7 +28,7 @@ public class ClickerPresenter {
addPanel(new UpgradePanel("Debugger", 1, 1, 1000000000, this)); addPanel(new UpgradePanel("Debugger", 1, 1, 1000000000, this));
clickerModel.getUpgradePanels().forEach(UpgradePanel::recalculateUpgradeButtonText);
Timer loop = new Timer(1000 / TARGET_FPS, e -> refresh()); Timer loop = new Timer(1000 / TARGET_FPS, e -> refresh());
loop.start(); loop.start();
} }
@ -37,7 +40,7 @@ public class ClickerPresenter {
public void nicolasButtonClick() { public void nicolasButtonClick() {
clickerModel.setNicolas(clickerModel.getNicolas() + 1); clickerModel.addNicolas(1);
} }
private void refresh() { private void refresh() {
@ -46,27 +49,32 @@ public class ClickerPresenter {
clickerModel.refresh(); clickerModel.refresh();
} }
public void removeNicolas(double amount) { public void removeNicolas(BigDecimal amount) {
clickerModel.setNicolas(clickerModel.getNicolas() - amount); clickerModel.removeNicolas(amount);
} }
public double getNicolas() { public BigDecimal getNicolas() {
return clickerModel.getNicolas(); return clickerModel.getNicolas();
} }
public void addNicolas(double gain) { public void addNicolas(long value) {
clickerModel.setNicolas(clickerModel.getNicolas() + gain); addNicolas(BigDecimal.valueOf(value));
}
public void addNicolas(BigDecimal gain) {
clickerModel.addNicolas(gain);
} }
public String changeFactor() { public String changeFactor() {
upgradeFactor *= 10; upgradeFactor *= 10;
if (upgradeFactor > 1000) { if (upgradeFactor > MAX_UPGRADE_FACTOR) {
upgradeFactor = 1; 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; return upgradeFactor;
} }

View file

@ -1,16 +1,22 @@
import java.math.BigDecimal;
public class LargeFormatter { public class LargeFormatter {
private static final String[] suffixes = {"", "k", "M", "B", "T", "q", "Q", "s", "S", "O", "N"}; 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 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 //input: 10 230 000 -> 10.23M
public String formatBigNumber(double number) { public String formatDouble(double number) {
int suffixSize = 0; int suffixSize = 0;
boolean scientific = false; boolean scientific = false;
while (number > 999) { while (number > 999) {
if(suffixSize == suffixes.length - 1){ if (suffixSize == suffixes.length - 1) {
scientific = true; scientific = true;
break; break;
} }
@ -19,15 +25,50 @@ public class LargeFormatter {
number /= 1000; number /= 1000;
} }
if(scientific){ if (scientific) {
int exp = 3 * suffixSize; int exp = 3 * suffixSize;
while(number >= 10){ while (number >= 10) {
exp++; exp++;
number /= 10; number /= 10;
} }
return String.format("%.2fE%d", number, exp); return String.format("%.2fE%d", number, exp);
} else { } 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]); return String.format("%.0f%s", number, suffixes[suffixSize]);
} else { } else {
return String.format("%.2f%s", number, suffixes[suffixSize]); return String.format("%.2f%s", number, suffixes[suffixSize]);

View file

@ -1,4 +1,6 @@
import javax.swing.*; import javax.swing.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class UpgradePanel extends JPanel { public class UpgradePanel extends JPanel {
@ -11,11 +13,11 @@ public class UpgradePanel extends JPanel {
private String name; private String name;
private final double costMultiplier; private final BigDecimal costMultiplier;
private final double baseGain; private final double baseGain;
private double cost; private BigDecimal cost;
private double gain = 0; private BigDecimal gain = BigDecimal.ZERO;
private int level; private int level;
private long lastAddedTimeStamp = 0; private long lastAddedTimeStamp = 0;
@ -24,12 +26,14 @@ public class UpgradePanel extends JPanel {
private final ClickerPresenter presenter; private final ClickerPresenter presenter;
private final LargeFormatter lf = new LargeFormatter(); private final LargeFormatter lf = new LargeFormatter();
private String upgradeButtonText = "";
public UpgradePanel(String name, double baseCost, double costMultiplier, double baseGain, ClickerPresenter presenter) { public UpgradePanel(String name, double baseCost, double costMultiplier, double baseGain, ClickerPresenter presenter) {
add(mainPanel); add(mainPanel);
this.name = name; this.name = name;
this.cost = baseCost; this.cost = new BigDecimal(baseCost);
this.costMultiplier = costMultiplier; this.costMultiplier = BigDecimal.valueOf(costMultiplier);
this.baseGain = baseGain; this.baseGain = baseGain;
this.presenter = presenter; this.presenter = presenter;
@ -38,62 +42,70 @@ public class UpgradePanel extends JPanel {
upgradeButton.addActionListener(e -> upgrade(presenter.getUpgradeFactor())); upgradeButton.addActionListener(e -> upgrade(presenter.getUpgradeFactor()));
} }
public void upgrade(double amount) { public void upgrade(int amount) {
presenter.removeNicolas(calculateExp(cost, costMultiplier, amount)); presenter.removeNicolas(calculateExp(cost, costMultiplier, amount));
gain += baseGain * amount; gain = gain.add(new BigDecimal(baseGain * amount));
level += amount; level += amount;
cost *= Math.pow(costMultiplier, amount); cost = cost.multiply(costMultiplier.pow(amount));
recalculateUpgradeButtonText();
} }
public void refresh() { 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 currentTime = System.currentTimeMillis();
long lastAddDeltaTime = currentTime - lastAddedTimeStamp; if (gain.compareTo(BigDecimal.ZERO) > 0) {
double timePerNicolas = 1 / gain * 1000; //should nicolas be added?
double lastAddDeltaTime = currentTime - lastAddedTimeStamp;
double inverseLastAddDeltaTime = 1 / (lastAddDeltaTime / 1000);
if (timePerNicolas < lastAddDeltaTime) { //gain=2 tpn=0.5 ladt=1000 laps=1
//add nicolas if (gain.compareTo(BigDecimal.valueOf(inverseLastAddDeltaTime)) > 0) {
long frameDeltaTime = currentTime - lastFrameTimeStamp; double frameDeltaTime = currentTime - lastFrameTimeStamp;
BigDecimal inverseFrameDeltaTime = BigDecimal.valueOf(1 / (frameDeltaTime / 1000));
System.out.printf("tpn=%.2f ladt=%d Δt=%d", timePerNicolas, lastAddDeltaTime, frameDeltaTime);
lastAddedTimeStamp = currentTime; lastAddedTimeStamp = currentTime;
if (gain.compareTo(inverseFrameDeltaTime) > 0) {
if (timePerNicolas < frameDeltaTime) { //normal: dt/tpn inverse: gain/idt
double missedNicolas = frameDeltaTime / timePerNicolas; System.out.println(inverseFrameDeltaTime + " " + gain);
System.out.printf(" FN mn=%.2f gain=%.2f add=%.2f", missedNicolas, gain, missedNicolas); BigDecimal missedNicolas = gain.divide(inverseFrameDeltaTime, 0, RoundingMode.HALF_UP); /*frameDeltaTime / timePerNicolas*/
System.out.println(missedNicolas);
presenter.addNicolas(missedNicolas); presenter.addNicolas(missedNicolas);
} else { } else {
presenter.addNicolas(1); presenter.addNicolas(1);
} }
System.out.print("\n");
} }
}
lastFrameTimeStamp = currentTime; lastFrameTimeStamp = currentTime;
levelLabel.setText("Level: " + level); levelLabel.setText("Level: " + level);
gainLabel.setText(lf.formatBigNumber(gain) + " Nicolas"); gainLabel.setText(lf.formatBigNumber(gain) + " Nicolas");
upgradeButton.setText(String.format("%,.0fx Upgrade: %s Nicolas", upgradeButton.setText(upgradeButtonText);
presenter.getUpgradeFactor(), lf.formatBigNumber(calculateExp(cost, costMultiplier, presenter.getUpgradeFactor()))));
} }
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... = //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...) // c * (x^0 + x^1 + x^2 + x^3...)
//new cost = c * x^amount //new cost = c * x^amount
double result = 0; BigDecimal result = BigDecimal.ZERO;
for (int i = 0; i < amount; i++) { 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; return gain;
} }
public void recalculateUpgradeButtonText() {
upgradeButtonText = String.format("%,dx Upgrade: %s Nicolas",
presenter.getUpgradeFactor(), lf.formatBigNumber(calculateExp(cost, costMultiplier, presenter.getUpgradeFactor())));
}
} }

View file

@ -16,34 +16,34 @@ class LargeFormatterLargeTest {
void normal(){ void normal(){
double n = 100000; double n = 100000;
String s = "100k"; String s = "100k";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void smallestSci(){ void smallestSci(){
double n = 1000000; double n = 1000000;
String s = "1.00E6"; String s = "1.00E6";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void biggerSci(){ void biggerSci(){
double n = 10000000; double n = 10000000;
String s = "1.00E7"; String s = "1.00E7";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void decimalSci(){ void decimalSci(){
double n = 16900000; double n = 16900000;
String s = "1.69E7"; String s = "1.69E7";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void pointNine(){ void pointNine(){
double n = 9780000; double n = 9780000;
String s = "9.78E6"; String s = "9.78E6";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
} }

View file

@ -16,27 +16,27 @@ class LargeFormatterTest {
void tinyNumberTest(){ void tinyNumberTest(){
double n = 0.1; double n = 0.1;
String s = "0.10"; String s = "0.10";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void smallNumberTest(){ void smallNumberTest(){
double n = 10; double n = 10;
String s = "10"; String s = "10";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void kTest(){ void kTest(){
double n = 1000; double n = 1000;
String s = "1k"; String s = "1k";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
@Test @Test
void mTest(){ void mTest(){
double n = 10230000; double n = 10230000;
String s = "10.23M"; String s = "10.23M";
assertEquals(s, lf.formatBigNumber(n)); assertEquals(s, lf.formatDouble(n));
} }
} }