diff --git a/src/main/java/edu/ntnu/idi/idatt/model/Exchange.java b/src/main/java/edu/ntnu/idi/idatt/model/Exchange.java index 3b96c81..e41a2c0 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/Exchange.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/Exchange.java @@ -1,7 +1,6 @@ package edu.ntnu.idi.idatt.model; import java.math.BigDecimal; -import java.math.MathContext; import java.math.RoundingMode; import java.util.*; @@ -11,7 +10,6 @@ import edu.ntnu.idi.idatt.model.transaction.Purchase; import edu.ntnu.idi.idatt.model.transaction.Sale; import edu.ntnu.idi.idatt.model.transaction.Transaction; -import edu.ntnu.idi.idatt.session.UserSession; /** * Exchange class @@ -201,10 +199,7 @@ public void advance() { Random random = new Random(); stockMap.values() .forEach(s -> s.addNewSalesPrice(s.getSalesPrice() - .multiply(BigDecimal.valueOf(random.nextDouble(0.8, 1.4)).setScale(2, RoundingMode.HALF_UP)))); - UserSession.getInstance().netWorthProperty().set( - UserSession.getInstance().getPlayer().getNetWorth().doubleValue()); // TODO: Remove hook from here, just for - // testing + .multiply(BigDecimal.valueOf(random.nextDouble(0.8, 1.4))).setScale(2, RoundingMode.HALF_UP))); } } diff --git a/src/main/java/edu/ntnu/idi/idatt/model/market/Stock.java b/src/main/java/edu/ntnu/idi/idatt/model/market/Stock.java index c7c65c4..cff8ad3 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/market/Stock.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/market/Stock.java @@ -119,4 +119,10 @@ public void addNewSalesPrice(BigDecimal price) { prices.add(price); } + // TODO: JavaDocs + @Override + public String toString() { + return this.getCompany() + " (" + this.getSymbol() + ")"; + } + } diff --git a/src/main/java/edu/ntnu/idi/idatt/model/player/Player.java b/src/main/java/edu/ntnu/idi/idatt/model/player/Player.java index 7af1065..6f981a7 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/player/Player.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/player/Player.java @@ -2,9 +2,9 @@ import edu.ntnu.idi.idatt.model.portfolio.Portfolio; import edu.ntnu.idi.idatt.model.transaction.TransactionArchive; -import edu.ntnu.idi.idatt.session.UserSession; import java.math.BigDecimal; +import java.math.RoundingMode; public class Player { @@ -50,19 +50,10 @@ public TransactionArchive getTransactionArchive() { public void addMoney(BigDecimal amount) { this.money = this.money.add(amount); - UserSession.getInstance().moneyProperty().set(this.money.doubleValue()); // Workaround instead of PropertyChange due - // to JSON saving - UserSession.getInstance().netWorthProperty().set(this.getNetWorth().doubleValue()); // Portfolio doesnt change - // without monetary change - // (either buy or sale) so thats - // the decision to hook net - // worth here and under. } public void withdrawMoney(BigDecimal amount) { this.money = this.money.subtract(amount); - UserSession.getInstance().moneyProperty().set(this.money.doubleValue()); // Hooks - UserSession.getInstance().netWorthProperty().set(this.getNetWorth().doubleValue()); } /** @@ -86,7 +77,7 @@ public BigDecimal getNetWorth() { */ public String getStatus() { int tradingWeeks = transactionArchive.countDistinctWeeks(); - BigDecimal netWorth = this.getNetWorth().divide(this.startingMoney); + BigDecimal netWorth = this.getNetWorth().divide(this.startingMoney, 2, RoundingMode.HALF_UP); if (tradingWeeks >= 20 && netWorth.compareTo(new BigDecimal("2")) >= 0) { return "Speculator"; diff --git a/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Portfolio.java b/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Portfolio.java index 5bfba56..78a591b 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Portfolio.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Portfolio.java @@ -43,6 +43,11 @@ public boolean removeShare(Share share) { return shares.remove(share); } + // TODO: JavaDocs, Junit + public void removeShares() { + shares.clear(); + } + /** * Getter for ArrayList shares. * @@ -69,19 +74,23 @@ public BigDecimal getOwnedAmount(String symbol) { } public BigDecimal getProfitFromStock(String symbol) { - return getShares(symbol).stream().map(s -> s.getProfit()) - .reduce(BigDecimal.ZERO, BigDecimal::add); + return getShares(symbol).stream().map(s -> { + BigDecimal total = new SaleCalculator(s).calculateTotal(); + BigDecimal buyPrice = s.getQuantity().multiply(s.getPurchasePrice()); + + return total.subtract(buyPrice); + }).reduce(BigDecimal.ZERO, BigDecimal::add); } public BigDecimal getChangeFromStock(String symbol) { BigDecimal profitTotal = getProfitFromStock(symbol); - BigDecimal costTotal = getShares(symbol).stream().map(s -> s.getPurchasePrice()) + BigDecimal costTotal = getShares(symbol).stream().map(s -> s.getPurchasePrice().multiply(s.getQuantity())) .reduce(BigDecimal.ZERO, BigDecimal::add); if (costTotal.compareTo(BigDecimal.ZERO) <= 0) return BigDecimal.ZERO; - return profitTotal.divide(costTotal, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); + return profitTotal.divide(costTotal, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); } /** diff --git a/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java b/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java index 3dcf5ab..2fef3e5 100644 --- a/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java +++ b/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java @@ -1,8 +1,11 @@ package edu.ntnu.idi.idatt.session; +import java.math.BigDecimal; + import edu.ntnu.idi.idatt.model.Exchange; import edu.ntnu.idi.idatt.model.player.Player; -import javafx.beans.property.SimpleDoubleProperty; +import edu.ntnu.idi.idatt.storage.SessionManager; +import javafx.beans.property.SimpleObjectProperty; public class UserSession { @@ -29,7 +32,7 @@ public Player getPlayer() { public void setPlayer(Player player) { this.player = player; - moneyProperty.set(player.getMoney().doubleValue()); // Startup hook + updateGameState(); // Startup hook } public Exchange getExchange() { @@ -40,17 +43,23 @@ public void setExchange(Exchange exchange) { this.exchange = exchange; } - private final SimpleDoubleProperty moneyProperty = new SimpleDoubleProperty(); - private final SimpleDoubleProperty netWorthProperty = new SimpleDoubleProperty(); + private final SimpleObjectProperty moneyProperty = new SimpleObjectProperty<>(BigDecimal.ZERO); + private final SimpleObjectProperty netWorthProperty = new SimpleObjectProperty<>(BigDecimal.ZERO); - public SimpleDoubleProperty moneyProperty() { + public SimpleObjectProperty moneyProperty() { return moneyProperty; } - public SimpleDoubleProperty netWorthProperty() { + public SimpleObjectProperty netWorthProperty() { return netWorthProperty; } + public void updateGameState() { + moneyProperty.set(player.getMoney()); + netWorthProperty.set(player.getNetWorth()); + SessionManager.saveSession(); + } + public SessionBundle getSession() { return new SessionBundle(player, exchange); } diff --git a/src/main/java/edu/ntnu/idi/idatt/storage/SessionManager.java b/src/main/java/edu/ntnu/idi/idatt/storage/SessionManager.java index 8b40489..94626d1 100644 --- a/src/main/java/edu/ntnu/idi/idatt/storage/SessionManager.java +++ b/src/main/java/edu/ntnu/idi/idatt/storage/SessionManager.java @@ -17,7 +17,10 @@ import com.google.gson.reflect.TypeToken; import edu.ntnu.idi.idatt.model.Exchange; +import edu.ntnu.idi.idatt.model.market.Stock; import edu.ntnu.idi.idatt.model.player.Player; +import edu.ntnu.idi.idatt.model.portfolio.Portfolio; +import edu.ntnu.idi.idatt.model.portfolio.Share; import edu.ntnu.idi.idatt.model.transaction.Transaction; import edu.ntnu.idi.idatt.service.transaction.TransactionCalculator; import edu.ntnu.idi.idatt.session.UserSession; @@ -104,6 +107,21 @@ public static boolean loadSession(String playerName) { if (session.getPlayer().getName().equals(playerName)) { UserSession.getInstance().setPlayer(session.getPlayer()); UserSession.getInstance().setExchange(session.getExchange()); + + // Reseed portfolio based on exchange's stock instances. + // This has to be done due to Gson loading via reflection. + Portfolio portfolio = UserSession.getInstance().getPlayer().getPortfolio(); + ArrayList validatedShares = new ArrayList<>(); + + for (Share oldShare : portfolio.getShares()) { // Create new instances + Stock stock = UserSession.getInstance().getExchange().getStock(oldShare.getStock().getSymbol()); + Share newShare = new Share(stock, oldShare.getQuantity(), oldShare.getPurchasePrice()); + validatedShares.add(newShare); + } + + portfolio.removeShares(); // Remove all old + validatedShares.forEach(share -> portfolio.addShare(share)); // Add new + return true; } } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java b/src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java index cd14152..350fa89 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java @@ -20,19 +20,17 @@ import edu.ntnu.idi.idatt.view.primary.transactions.TransactionView; import javafx.scene.Parent; -import java.math.BigDecimal; import java.util.ArrayDeque; import java.util.Deque; -import java.util.List; public class SceneFactory { @FunctionalInterface - public interface MVCInitializer { + public interface MVCInitInterface { Parent execute(); } - private static Deque navigation = new ArrayDeque<>(); + private static Deque navigation = new ArrayDeque<>(); private static boolean navigatingBack = false; public static void goBack() { @@ -50,7 +48,7 @@ public static void reloadCurrent() { navigatingBack = false; } - private static void mark(MVCInitializer initializer) { + private static void mark(MVCInitInterface initializer) { if (!navigatingBack) { navigation.push(initializer); } @@ -62,6 +60,8 @@ public static boolean isFinal() { public static Parent createStartView() { + navigation.clear(); + StartModel model = new StartModel(); StartView view = new StartView(); StartController controller = new StartController(model); @@ -72,13 +72,14 @@ public static Parent createStartView() { return view.getInstance(); } - public static Parent createPortfolioView(){ + + public static Parent createPortfolioView() { mark(() -> createPortfolioView()); - + PortfolioModel model = new PortfolioModel(); PortfolioView view = new PortfolioView(); - PortfolioController controller = new PortfolioController(model); + PortfolioController controller = new PortfolioController(model); view.setModel(model); view.setController(controller); diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/PlayerPortfolioComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/PlayerPortfolioComponent.java index 7457d36..6744dd4 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/PlayerPortfolioComponent.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/PlayerPortfolioComponent.java @@ -8,42 +8,42 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.util.ArrayList; import java.util.Collections; public class PlayerPortfolioComponent extends HBox { - public PlayerPortfolioComponent(Portfolio portfolio){ - this.setMaxSize(Double.MAX_VALUE, 500); - this.getStyleClass().add("light"); + public PlayerPortfolioComponent(Portfolio portfolio) { + this.setMaxSize(Double.MAX_VALUE, 500); + this.getStyleClass().add("light"); - Label userTitle = new Label(String.format("%s's Portfolio", UserSession.getInstance().getPlayer().getName())); - Label netWorth = new Label(); - netWorth.textProperty().bind( - UserSession.getInstance().netWorthProperty().asString("Net Worth: %.2f $")); - Label percentageChange = new Label("Percentage change: "+ UserSession.getInstance().netWorthProperty().doubleValue()); - Label playerStatus = new Label("Player status: "+ UserSession.getInstance().getPlayer().getStatus()); - Label totalShares = new Label("Total shares owned: "+ UserSession.getInstance().getPlayer().getPortfolio().getShares().size()); - ArrayList