mirror of
https://github.com/Noratrieb/ClickerGameSwing.git
synced 2026-01-14 15:45:04 +01:00
BigDecimal switch
This commit is contained in:
parent
31a219b3e2
commit
94a169b421
6 changed files with 144 additions and 65 deletions
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
|
|
|
||||||
|
|
@ -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())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue