diff --git a/src/main/java/edu/ntnu/idi/idatt/Launcher.java b/src/main/java/edu/ntnu/idi/idatt/Launcher.java index 18c49a6..568ea1b 100644 --- a/src/main/java/edu/ntnu/idi/idatt/Launcher.java +++ b/src/main/java/edu/ntnu/idi/idatt/Launcher.java @@ -11,16 +11,22 @@ public final class Launcher { * Entry point of application. */ static void main() { - Application.launch(StockGame.class); + Application.launch(Millions.class); } - public static final class StockGame extends Application { + /** + * Class for JavaFX startup. + */ + public static final class Millions extends Application { + /** + * JavaFX entry point. + */ @Override public void start(Stage stage) { - stage.setWidth(1200); - stage.setHeight(700); - stage.setTitle("Stock Game"); + stage.setWidth(1440); + stage.setHeight(820); + stage.setTitle("Millions"); SceneManager.init(stage, SceneFactory.createStartView()); stage.show(); 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 db005da..8ee1e18 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/Exchange.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/Exchange.java @@ -41,20 +41,28 @@ public Exchange(String name, List stocks) { } /** - * - * Getters - * - * @return - their corresponding variables. + * Getter for name. + * + * @return String; */ - public String getName() { return name; } + /** + * Getter for week. + * + * @return int; + */ public int getWeek() { return week; } + /** + * Getter for all stocks. + * + * @return List of Stocks. + */ public List getStocks() { return stockMap.values().stream().toList(); } @@ -106,7 +114,7 @@ public List findStocks(String searchTerm) { * *

* Returns the stocks that have done it the best - * in the latest week. + * (percent change) in the latest week. *

* * @param limit - Amount of stocks to be returned. @@ -114,8 +122,8 @@ public List findStocks(String searchTerm) { */ public List getGainers(int limit) { return stockMap.values().stream() - .filter(stock -> stock.getLatestPriceChange().compareTo(BigDecimal.ZERO) > 0) - .sorted(Comparator.comparing(Stock::getLatestPriceChange).reversed()) + .filter(stock -> stock.getLatestPriceChangePercent().compareTo(BigDecimal.ZERO) > 0) + .sorted(Comparator.comparing(Stock::getLatestPriceChangePercent).reversed()) .limit(limit) .toList(); } @@ -125,16 +133,16 @@ public List getGainers(int limit) { * *

* Returns the stocks that have done it the worst - * in value in the latest week. + * in percent change in the latest week. *

* * @param limit - Amount of stocks to be returned. - * @return A list of stocks sorted in inclining order. + * @return A list of stocks sorted in ascending order. */ public List getLosers(int limit) { return stockMap.values().stream() - .filter(stock -> stock.getLatestPriceChange().compareTo(BigDecimal.ZERO) < 0) - .sorted(Comparator.comparing(Stock::getLatestPriceChange)) + .filter(stock -> stock.getLatestPriceChangePercent().compareTo(BigDecimal.ZERO) < 0) + .sorted(Comparator.comparing(Stock::getLatestPriceChangePercent)) .limit(limit) .toList(); } @@ -189,6 +197,7 @@ public Transaction sell(Share share, Player player) { * *

* Adds a new price to each of the stock array. + * Progresses week counter. *

* * @see Stock diff --git a/src/main/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnum.java b/src/main/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnum.java index bc48f3e..11b8c22 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnum.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnum.java @@ -1,5 +1,14 @@ package edu.ntnu.idi.idatt.model.enums; +/** + * Newspaper enum. + * + *

+ * Creates static events that can occur within Newspaper. + *

+ * + * @see Newspaper + */ public enum NewspaperEnum { NEW_PRODUCT( "New product announced!", @@ -83,6 +92,9 @@ public enum NewspaperEnum { private final double trend; private final double volatility; // How violently the price moves factor + /** + * Constructor for NewspaperEnum + */ NewspaperEnum(String title, String description, double trend, double volatility) { this.title = title; this.description = description; @@ -90,18 +102,38 @@ public enum NewspaperEnum { this.volatility = volatility; } + /** + * Getter for title + * + * @return String; + */ public String getTitle() { return title; } + /** + * Getter for description + * + * @return String; + */ public String getDescription() { return description; } + /** + * Getter for trend + * + * @return double; + */ public double getTrend() { return trend; } + /** + * Getter for volatility + * + * @return double; + */ public double getVolatility() { return volatility; } diff --git a/src/main/java/edu/ntnu/idi/idatt/model/enums/PlayerStatusEnum.java b/src/main/java/edu/ntnu/idi/idatt/model/enums/PlayerStatusEnum.java new file mode 100644 index 0000000..6661da9 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/model/enums/PlayerStatusEnum.java @@ -0,0 +1,64 @@ +package edu.ntnu.idi.idatt.model.enums; + +import java.math.BigDecimal; + +import edu.ntnu.idi.idatt.model.player.Player; + +/** + * Enum class that holds the different player statuses. + * + * @see Player + */ +public enum PlayerStatusEnum { + ROARING_KITTY("Roaring Kitty", 50, new BigDecimal("8")), + PAPER_HANDS("Paper Hands", 100, new BigDecimal("2")), + SPECULATOR("Speculator", 20, new BigDecimal("2")), + DIAMOND_HANDS("Diamond Hands", 10, new BigDecimal("3")), + INVESTOR("Investor", 10, new BigDecimal("1.2")), + NOVICE("Novice", 0, BigDecimal.ZERO); + + private final String title; + private final int tradingWeeks; + private final BigDecimal ratio; + + /** + * Constructor for PlayerStatusEnum + * + * @param title - Status name + * @param tradingWeeks - How many weeks in trading to reach status. + * @param ratio - NetWorth/starting money + */ + PlayerStatusEnum(String title, int tradingWeeks, BigDecimal ratio) { + this.title = title; + this.tradingWeeks = tradingWeeks; + this.ratio = ratio; + } + + /** + * Getter for title. + * + * @return String; + */ + public String getTitle() { + return title; + } + + /** + * Getter for trading weeks. + * + * @return int; + */ + public int getTradingWeeks() { + return tradingWeeks; + } + + /** + * Getter for ratio. + * + * @return BigDecimal. + */ + public BigDecimal getRatio() { + return ratio; + } + +} diff --git a/src/main/java/edu/ntnu/idi/idatt/model/Newspaper.java b/src/main/java/edu/ntnu/idi/idatt/model/market/Newspaper.java similarity index 64% rename from src/main/java/edu/ntnu/idi/idatt/model/Newspaper.java rename to src/main/java/edu/ntnu/idi/idatt/model/market/Newspaper.java index 4651b30..a8ad9a7 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/Newspaper.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/market/Newspaper.java @@ -1,4 +1,4 @@ -package edu.ntnu.idi.idatt.model; +package edu.ntnu.idi.idatt.model.market; import java.util.ArrayList; import java.util.List; @@ -6,11 +6,32 @@ import edu.ntnu.idi.idatt.model.enums.NewspaperEnum; +/** + * Newspaper class + * + *

+ * This class is used together with Stock, + * to provide a event-based context for the + * prices. + *

+ * + * @see Stock + */ public class Newspaper { ArrayList news = new ArrayList<>(List.of(NewspaperEnum.NONE_EVENT)); private static double chance = 0.05; // In percent + /** + * Method for creating news. + * + *

+ * Creates news and adds them to the + * news ArrayList. + *

+ * + * @return NewspaperEnum of NONE or random event. + */ public NewspaperEnum makeNews() { Random r = new Random(); double roll = r.nextDouble(); @@ -27,14 +48,31 @@ public NewspaperEnum makeNews() { return event; } + /** + * Method for checking if Newspaper has new news. + * + * @return true/false depending if a real event exists. + */ public boolean hasNewNews() { return news.getLast().equals(NewspaperEnum.NONE_EVENT) ? false : true; } + /** + * Getter for news arraylist. + */ public ArrayList getNews() { return news; } + /** + * Method for converting the arraylist to formatted strings. + * + *

+ * Converts NewspaperEnum to fitting String format. + *

+ * + * @return List of strings. + */ public List getNewsStrings() { ArrayList strings = new ArrayList<>(); 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 fc64df5..077174c 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 @@ -7,7 +7,6 @@ import java.util.List; import java.util.Random; -import edu.ntnu.idi.idatt.model.Newspaper; import edu.ntnu.idi.idatt.model.enums.NewspaperEnum; /** @@ -51,15 +50,19 @@ public Stock(String symbol, String company, List prices) { } /** - * Getters - * - * @return - Their corresponding variables. + * Getter for symbol + * + * @return String; */ - public String getSymbol() { return symbol; } + /** + * Getter for company + * + * @return String; + */ public String getCompany() { return company; } @@ -106,14 +109,22 @@ public BigDecimal getLatestPriceChange() { return prices.get(size - 1).subtract(prices.get(size - 2)); } - // TODO: JAVADOCS, JUNIT + /** + * Method for calculating the latest price change in percent. + * + *

+ * CurrentPrice/PreviousPrice * 100 + *

+ * + * @return BigDecimal of the change. + */ public BigDecimal getLatestPriceChangePercent() { if (prices.isEmpty() || prices.size() == 1) { return BigDecimal.ZERO; } - return (getLatestPriceChange().divide(prices.get(prices.size() - 2), 2, RoundingMode.HALF_UP)) - .multiply(new BigDecimal("100")); + return (getLatestPriceChange().multiply(new BigDecimal("100")) + .divide(prices.get(prices.size() - 2), 2, RoundingMode.HALF_UP)); } /** @@ -134,17 +145,39 @@ public void addNewSalesPrice(BigDecimal price) { prices.add(price); } - // TODO: JavaDocs ETC + /** + * Getter for newspaper + * + * @return Newspaper; + */ public Newspaper getNewspaper() { return newspaper; } + /** + * Method for calculating the price factor. + * + *

+ * Calculates the factor which is multiplied + * with current price to calculate the next week's price. + *

+ * + * @return factor (double) + */ private double calculatePriceFactor() { double noice = (new Random().nextGaussian() + 0.2) * volatility; return 0.01 /* positive trend */ + trend + momentum + noice; } + /** + * Method for calibrating the next price factor components + * + *

+ * Balances and controlls how the components making + * up the price factor adjust with each week. + *

+ */ private void calibrateNextPriceFactor() { momentum = calculatePriceFactor() * 0.35; @@ -161,6 +194,15 @@ private void calibrateNextPriceFactor() { } + /** + * Method for advancing stock price. + * + *

+ * Calculates next stock price based on + * current week's price and the price factor. + * Calls calibration when finished. + *

+ */ public void advancePrice() { BigDecimal currentPrice = this.getSalesPrice(); BigDecimal priceFactor = currentPrice.multiply(BigDecimal.valueOf(this.calculatePriceFactor())); @@ -172,7 +214,16 @@ public void advancePrice() { this.calibrateNextPriceFactor(); } - // TODO: JavaDocs + /** + * toString method. + * + *

+ * Converts stock to a String form used + * in diverse GUI components. + *

+ * + * @return String; + */ @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 d0a21e2..33e1932 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 @@ -1,5 +1,6 @@ package edu.ntnu.idi.idatt.model.player; +import edu.ntnu.idi.idatt.model.enums.PlayerStatusEnum; import edu.ntnu.idi.idatt.model.portfolio.Portfolio; import edu.ntnu.idi.idatt.model.transaction.TransactionArchive; @@ -73,23 +74,21 @@ public BigDecimal getNetWorth() { * players trading career has been going. *

* - * @return String of corresponding title. TODO: Change to ENUM!!! + * @return String of corresponding title. */ public String getStatus() { int tradingWeeks = transactionArchive.countDistinctWeeks(); BigDecimal netWorth = this.getNetWorth().divide(this.startingMoney, 2, RoundingMode.HALF_UP); - if (tradingWeeks >= 20 && netWorth.compareTo(new BigDecimal("2")) >= 0) { - return "Speculator"; + for (PlayerStatusEnum status : PlayerStatusEnum.values()) { + if (tradingWeeks >= status.getTradingWeeks() && netWorth.compareTo(status.getRatio()) >= 0) { + return status.getTitle(); + } } - - if (tradingWeeks >= 10 && netWorth.compareTo(new BigDecimal("1.2")) >= 0) { - return "Investor"; - } - - return "Novice"; + return PlayerStatusEnum.NOVICE.getTitle(); } - public BigDecimal getStartingMoney(){ + + public BigDecimal getStartingMoney() { return startingMoney; } 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 c255340..77c738a 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,7 +43,15 @@ public boolean removeShare(Share share) { return shares.remove(share); } - // TODO: JavaDocs, Junit + /** + * Removes all shares. + * + *

+ * Used only for reseeding the shares to + * match the instances of Exchange after loading + * from JSON. + *

+ */ public void removeShares() { shares.clear(); } @@ -67,25 +75,52 @@ public List getShares(String symbol) { return shares.stream().filter(s -> s.getStock().getSymbol().equals(symbol)).toList(); } - // TODO: JAVADOCS, JUNIT + /** + * Method for obtaining total amount of owned stock. + * + * @param symbol - The stock symbol of the corresponding shares. + * @return BigDecimal of amount. + */ public BigDecimal getOwnedAmount(String symbol) { return getShares(symbol).stream().map(s -> s.getQuantity()) .reduce(BigDecimal.ZERO, BigDecimal::add); } + /** + * Getter for total amount of owned shares. + * + * @return BigDecimal total amount. + */ public BigDecimal getOwnedAmount() { return getShares().stream().map(s -> s.getQuantity()) .reduce(BigDecimal.ZERO, BigDecimal::add); } + /** + * Method for obtaining profit from specified shares. + * + * @param symbol - Symbol of the specified Stock. + * @return BigDecimal of total profit. + */ public BigDecimal getProfitFromStock(String symbol) { return getShares(symbol).stream().map(s -> s.getProfit()).reduce(BigDecimal.ZERO, BigDecimal::add); } + /** + * Method for obtaining profit from all shares. + * + * @return total portfolio profit. + */ public BigDecimal getProfitFromStock() { return getShares().stream().map(s -> s.getProfit()).reduce(BigDecimal.ZERO, BigDecimal::add); } + /** + * Method for obtaining the profit percent change from a specified share. + * + * @param symbol - The symbol of the specified Stock. + * @return BigDecimal of profit percent change. + */ public BigDecimal getChangeFromStock(String symbol) { BigDecimal profitTotal = getProfitFromStock(symbol); BigDecimal costTotal = getShares(symbol).stream().map(s -> s.getTotalPurchasePrice()) @@ -97,13 +132,19 @@ public BigDecimal getChangeFromStock(String symbol) { return profitTotal.divide(costTotal, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); } + /** + * Method for obtaining the profit percent change for all shares. + * + * @return BigDecimal of portfolio percent change. + */ public BigDecimal getChangeFromStock() { BigDecimal profitTotal = getProfitFromStock(); BigDecimal costTotal = getShares().stream().map(s -> s.getTotalPurchasePrice()) .reduce(BigDecimal.ZERO, BigDecimal::add); - if (costTotal.compareTo(BigDecimal.ZERO) <= 0) + if (costTotal.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO; + } return profitTotal.divide(costTotal, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); } diff --git a/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Share.java b/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Share.java index 186cb43..c828dd6 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Share.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/portfolio/Share.java @@ -35,32 +35,64 @@ public Share(Stock stock, BigDecimal quantity, BigDecimal purchasePrice) { } /** - * Getters - * - * @return - Their corresponding variables. + * Getter for stock. + * + * @return Stock; */ - public Stock getStock() { return stock; } + /** + * Getter for quantity. + * + * @return BigDecimal; + */ public BigDecimal getQuantity() { return quantity; } + /** + * Getter for purchasePrice. + * + * @return BigDecimal; + */ public BigDecimal getPurchasePrice() { return purchasePrice; } - // TODO: JAVADOCS, JUNIT + /** + * Method for obtaining the total purchase price. + * + * @return BigDecimal (purchasePrice * quantity) + */ public BigDecimal getTotalPurchasePrice() { return purchasePrice.multiply(quantity); } + /** + * Method for obtaining the share current profit. + * + *

+ * SaleCalculator.calculateGross() - getTotalPurchasePrice() + *

+ * + * @see Player (Net worth calculation) + * @return BigDecimal current profit. + */ public BigDecimal getProfit() { return new SaleCalculator(this).calculateGross().subtract(getTotalPurchasePrice()); } + /** + * Method for obtaining the share profit change percent. + * + *

+ * profit/getTotalPurchasePrice * 100 + *

+ * + * @return BigDecimal profit percent change + */ public BigDecimal getProfitPercent() { return getProfit().divide(getTotalPurchasePrice(), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)); } diff --git a/src/main/java/edu/ntnu/idi/idatt/model/transaction/Transaction.java b/src/main/java/edu/ntnu/idi/idatt/model/transaction/Transaction.java index e42a892..50a31cd 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/transaction/Transaction.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/transaction/Transaction.java @@ -37,25 +37,37 @@ public abstract class Transaction { } /** - * - * Getters + * Getter for share. * - * @return - their corresponding variable - * + * @return Share; */ - public Share getShare() { return share; } + /** + * Getter for week. + * + * @return int; + */ public int getWeek() { return week; } + /** + * Getter for calculator. + * + * @return TransactionCalculator; + */ public TransactionCalculator getCalculator() { return calculator; } + /** + * Getter for commited. + * + * @return boolean; + */ public boolean isCommited() { return commited; } diff --git a/src/main/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchive.java b/src/main/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchive.java index 6112c89..a861539 100644 --- a/src/main/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchive.java +++ b/src/main/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchive.java @@ -44,7 +44,11 @@ public List getTransactions(int week) { return transactions.stream().filter(transaction -> transaction.getWeek() == week).toList(); } - // TODO: java, junit + /** + * Getter for all transactions done. + * + * @return List of transactions. + */ public List getTransactions() { return transactions; } @@ -61,7 +65,11 @@ public List getPurchases(int week) { .toList(); } - // TODO: java, junit + /** + * Getter for all purchases. + * + * @return List of Purchase. + */ public List getPurchases() { return getTransactions().stream().filter(t -> t instanceof Purchase) .map(t -> (Purchase) t) @@ -80,7 +88,11 @@ public List getSales(int week) { .toList(); } - // TODO: java, junit + /** + * Getter for all sales. + * + * @return List of Sale. + */ public List getSales() { return getTransactions().stream().filter(t -> t instanceof Sale) .map(t -> (Sale) t) @@ -88,9 +100,14 @@ public List getSales() { } /** - * Part 2 - * - * @return + * Method for counting amount of distinct weeks. + *

+ * Calculates how many weeks atleast one Transaction has been done. + * Used to calculate player statuses. + *

+ * + * @see Player + * @return int amount of distinct weeks. */ public int countDistinctWeeks() { return (int) transactions.stream() diff --git a/src/main/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculator.java b/src/main/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculator.java index 47819d5..bcbc17d 100644 --- a/src/main/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculator.java +++ b/src/main/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculator.java @@ -3,7 +3,6 @@ import edu.ntnu.idi.idatt.model.portfolio.Share; import java.math.BigDecimal; -import java.math.RoundingMode; /** * SaleCalculator class @@ -63,12 +62,12 @@ public BigDecimal calculateTax() { BigDecimal profit = calculateGross().subtract(purchasePrice.multiply(quantity)) .subtract(calculateCommision()); // (gross - tax - buy costs) - return profit.multiply(taxPercentage); + return profit.max(BigDecimal.ZERO).multiply(taxPercentage); } /** - * Method that calculates the total profit of a sold share + * Method that calculates the total price of a sold share * * @return - BigDecimal of gross value - commision fee - tax */ @@ -77,7 +76,16 @@ public BigDecimal calculateTotal() { return calculateGross().subtract(calculateCommision()).subtract(calculateTax()); } - // TODO: Javadocs, junit + /** + * Method for calculating the total profit for a sold share. + * + *

+ * Calculates the gross - total purchase price in respect + * to the net worth calculation method. + *

+ * + * @see Player + */ public BigDecimal calculateProfit() { return calculateGross().subtract(purchasePrice.multiply(quantity)); } 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 8531f80..05bacf6 100644 --- a/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java +++ b/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java @@ -7,7 +7,18 @@ import edu.ntnu.idi.idatt.storage.SessionManager; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; - +import javafx.beans.property.SimpleStringProperty; + +/** + * Class for managing current session. + *

+ * This class is the connector between the game model + * and user interface. Contains hooks for obtaining real time + * game state values. + * + * This is a singleton class. + *

+ */ public class UserSession { // Singleton instance @@ -17,6 +28,11 @@ public class UserSession { private UserSession() { } + /** + * Static getter for instance. + * + * @return UserSession; + */ public static UserSession getInstance() { if (INSTANCE == null) { INSTANCE = new UserSession(); @@ -27,19 +43,39 @@ public static UserSession getInstance() { private Player player; private Exchange exchange; + /** + * Getter for player. + * + * @return Player; + */ public Player getPlayer() { return player; } + /** + * Setter for player. + * + * @param player - Session player. + */ public void setPlayer(Player player) { this.player = player; updateGameState(); // Startup hook } + /** + * Getter for exchange. + * + * @return Exchange; + */ public Exchange getExchange() { return exchange; } + /** + * Setter for exchange. + * + * @param exchange - Session exchange. + */ public void setExchange(Exchange exchange) { this.exchange = exchange; updateGameState(); // Startup hook @@ -48,19 +84,52 @@ public void setExchange(Exchange exchange) { private final SimpleObjectProperty moneyProperty = new SimpleObjectProperty<>(BigDecimal.ZERO); private final SimpleObjectProperty netWorthProperty = new SimpleObjectProperty<>(BigDecimal.ZERO); private final SimpleIntegerProperty weekProperty = new SimpleIntegerProperty(); + private final SimpleStringProperty statusProperty = new SimpleStringProperty(); + /** + * Getter for moneyProperty. + * + * @return SimpleObjectProperty; + */ public SimpleObjectProperty moneyProperty() { return moneyProperty; } + /** + * Getter for netWorthProperty. + * + * @return SimpleObjectProperty + */ public SimpleObjectProperty netWorthProperty() { return netWorthProperty; } + /** + * Getter for weekProperty. + * + * @return SimpleIntegerProperty + */ public SimpleIntegerProperty weekProperty() { return weekProperty; } + /** + * Getter for statusProperty. + * + * @return SimpleStringProperty; + */ + public SimpleStringProperty statusProperty() { + return statusProperty; + } + + /** + * Method used for updating the game state. + *

+ * Updates the user interface model from diverse + * places through the code to synchronize model <-> UI. + * Saves current session. + *

+ */ public void updateGameState() { if (player == null || exchange == null) { @@ -70,27 +139,57 @@ public void updateGameState() { moneyProperty.set(player.getMoney()); netWorthProperty.set(player.getNetWorth()); weekProperty.set(exchange.getWeek()); + statusProperty.set(player.getStatus()); SessionManager.saveSession(); } + /** + * Getter for current session bundle. + * + * @return SessionBubndle. + */ public SessionBundle getSession() { return new SessionBundle(player, exchange); } + /** + * SessionBundle class. + * + *

+ * Wrapper class for easier creating big JSON models + * in arrays to serialize and deserialize. + *

+ */ public class SessionBundle { private Player player; private Exchange exchange; + /** + * Constructor for SessionBundle. + * + * @param player - Player object. + * @param exchange - Exchange object. + */ public SessionBundle(Player player, Exchange exchange) { this.player = player; this.exchange = exchange; } + /** + * Getter for player. + * + * @return Player; + */ public Player getPlayer() { return player; } + /** + * Getter for exchange. + * + * @return Exchange; + */ public Exchange getExchange() { return 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 94626d1..ad6ed08 100644 --- a/src/main/java/edu/ntnu/idi/idatt/storage/SessionManager.java +++ b/src/main/java/edu/ntnu/idi/idatt/storage/SessionManager.java @@ -34,6 +34,7 @@ *

* Utilizes gson serialization and deserialization to manage * player and game state. + *

*/ public class SessionManager { @@ -64,6 +65,8 @@ public static void newSession(Player player, Exchange exchange) { /** * Method for saving current session. + * + * @throws RuntimeException on failed save. */ public static void saveSession() { // don't save if current session is null accidentally @@ -128,6 +131,38 @@ public static boolean loadSession(String playerName) { return false; } + /** + * Method to remove current session. + * + * @throws RuntimeException on failed removal. + */ + public static void removeSession() { + // don't save if current session is null accidentally + if (UserSession.getInstance().getPlayer() == null || UserSession.getInstance().getExchange() == null) { + return; + } + + // Load all sessions + List bundles = loadAllSessions(); + + try (Writer writer = new FileWriter(StorageFile.getStorageFile().toFile())) { + + // Append current session + SessionBundle existing = bundles.stream() + .filter(s -> s.getPlayer().getName().equals(UserSession.getInstance().getPlayer().getName())) + .findFirst().orElse(null); + + if (existing != null) { + bundles.remove(bundles.indexOf(existing)); + } + + gson.toJson(bundles, writer); + + } catch (IOException e) { + throw new RuntimeException("Failed to remove current session!", e); + } + } + /** * Method for serialization of all sessions. * diff --git a/src/main/java/edu/ntnu/idi/idatt/storage/StockParser.java b/src/main/java/edu/ntnu/idi/idatt/storage/StockParser.java index 74c2739..0e88de3 100644 --- a/src/main/java/edu/ntnu/idi/idatt/storage/StockParser.java +++ b/src/main/java/edu/ntnu/idi/idatt/storage/StockParser.java @@ -3,13 +3,10 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.math.BigDecimal; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionAdapter.java b/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionAdapter.java index acc53be..ebd0218 100644 --- a/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionAdapter.java +++ b/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionAdapter.java @@ -14,8 +14,21 @@ import edu.ntnu.idi.idatt.model.transaction.Sale; import edu.ntnu.idi.idatt.model.transaction.Transaction; +/** + * Transaction adapter class. + *

+ * Guides Gson serializer/deserializer how to handle abstract object types. + *

+ */ public class TransactionAdapter implements JsonSerializer, JsonDeserializer { + /** + * Method for serialization of Transactions. + * + * @param t - Current transaction. + * @param typeOfT - Type of transaction. + * @param context - Serialization information. + */ @Override public JsonElement serialize(Transaction t, Type typeOfT, JsonSerializationContext context) { @@ -30,6 +43,13 @@ public JsonElement serialize(Transaction t, Type typeOfT, JsonSerializationConte return obj; } + /** + * Method for deserialization of Transactions. + * + * @param json - Current transaction json text. + * @param typeOfT - type of transaction. + * @param context - Deserialization information. + */ @Override public Transaction deserialize(JsonElement json, Type typeOfT, diff --git a/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionCalculatorAdapter.java b/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionCalculatorAdapter.java index 89f3204..d44e23f 100644 --- a/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionCalculatorAdapter.java +++ b/src/main/java/edu/ntnu/idi/idatt/storage/util/TransactionCalculatorAdapter.java @@ -14,9 +14,22 @@ import edu.ntnu.idi.idatt.service.transaction.SaleCalculator; import edu.ntnu.idi.idatt.service.transaction.TransactionCalculator; +/** + * TransactionCalculator adapter class. + *

+ * Guides Gson serializer/deserializer how to handle abstract object types. + *

+ */ public class TransactionCalculatorAdapter implements JsonSerializer, JsonDeserializer { + /** + * Method for serialization of TransactionCalculators. + * + * @param calc - Current calculator. + * @param typeOfT - Type of calculator. + * @param context - Serialization information. + */ @Override public JsonElement serialize(TransactionCalculator calc, Type typeOfT, JsonSerializationContext context) { @@ -31,6 +44,13 @@ public JsonElement serialize(TransactionCalculator calc, Type typeOfT, JsonSeria return obj; } + /** + * Method for deserialization of TransactioNCalculators.. + * + * @param json - Current calculator json text. + * @param typeOfT - type of calculator. + * @param context - Deserialization information. + */ @Override public TransactionCalculator deserialize(JsonElement json, Type typeOfT, 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 5eb1390..154e11b 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java @@ -2,6 +2,7 @@ import edu.ntnu.idi.idatt.model.market.Stock; import edu.ntnu.idi.idatt.session.UserSession; +import edu.ntnu.idi.idatt.storage.SessionManager; import edu.ntnu.idi.idatt.view.entry.StartController; import edu.ntnu.idi.idatt.view.entry.StartModel; import edu.ntnu.idi.idatt.view.entry.StartView; @@ -14,6 +15,9 @@ import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeController; import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeModel; import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeView; +import edu.ntnu.idi.idatt.view.primary.finish.FinishController; +import edu.ntnu.idi.idatt.view.primary.finish.FinishModel; +import edu.ntnu.idi.idatt.view.primary.finish.FinishView; import edu.ntnu.idi.idatt.view.primary.stock.StockController; import edu.ntnu.idi.idatt.view.primary.stock.StockModel; import edu.ntnu.idi.idatt.view.primary.stock.StockView; @@ -21,12 +25,24 @@ import edu.ntnu.idi.idatt.view.primary.transactions.TransactionModel; import edu.ntnu.idi.idatt.view.primary.transactions.TransactionView; import javafx.scene.Parent; +import javafx.util.Pair; import java.util.ArrayDeque; import java.util.Deque; +/** + * Factory class for creating MVC scenes. + * + *

+ * Initializes MVC objects to bind together + * MVC models. + *

+ */ public class SceneFactory { + /** + * Functional interface for saving factory methods. + */ @FunctionalInterface public interface MVCInitInterface { Parent execute(); @@ -35,6 +51,9 @@ public interface MVCInitInterface { private static Deque navigation = new ArrayDeque<>(); private static boolean navigatingBack = false; + /** + * Method for going back to previous MVC instance. + */ public static void goBack() { if (navigation.size() > 1) { navigation.pop(); @@ -44,22 +63,42 @@ public static void goBack() { } } + /** + * Method for refreshing current MVC instance. + *

+ * Used for refreshing static components after + * updating game model. + *

+ */ public static void reloadCurrent() { navigatingBack = true; SceneManager.switchTo(navigation.peek().execute()); navigatingBack = false; } + /** + * Method to save current MVC instance + */ private static void mark(MVCInitInterface initializer) { if (!navigatingBack) { navigation.push(initializer); } } + /** + * Method for checking if current MVC instance is final. + * + * @return boolean; + */ public static boolean isFinal() { return navigation.size() == 1; } + /** + * Initialization method for Start View. + * + * @return View's root. + */ public static Parent createStartView() { navigation.clear(); @@ -75,9 +114,12 @@ public static Parent createStartView() { } - public static Parent createPortfolioView() { - - mark(() -> createPortfolioView()); + /** + * Initialization method for all Portfolio views. + * + * @return View's root and controller. + */ + private static Pair createDefaultPortfolioView() { PortfolioModel model = new PortfolioModel(); PortfolioView view = new PortfolioView(); @@ -86,12 +128,65 @@ public static Parent createPortfolioView() { view.setModel(model); view.setController(controller); - return view.getInstance(); + return new Pair(view.getInstance(), controller); } - public static Parent createExchangeView() { + /** + * Wrapper for Portfolio View initialization method. + * + *

+ * Initializes a default portfolio. + *

+ * + * @return View's root. + */ + public static Parent createPortfolioView() { + + mark(() -> createPortfolioView()); + + Pair vc = createDefaultPortfolioView(); + return vc.getKey(); // View + } + + /** + * Wrapper for Portfolio View initialization method. + * + *

+ * Initializes a portfolio with a search query. + *

+ * + * @param initialSearch - Initial search query + * @return View's root + */ + public static Parent createPortfolioView(String initialSearch) { + + mark(() -> createPortfolioView(initialSearch)); + + Pair vc = createDefaultPortfolioView(); + Parent view = vc.getKey(); + + if (initialSearch == null || initialSearch.isEmpty()) { + return view; + } + + PortfolioController controller = vc.getValue(); + controller.handleSearchQuery(initialSearch); + return view; + + } - mark(() -> createExchangeView()); + /** + * Initialization method for Exchange View. + * + * @return View's root. + */ + private static Parent createDefaultExchangeView(boolean clean) { + + if (clean) { + navigation.clear(); + } + + mark(() -> createDefaultExchangeView(false)); ExchangeModel model = new ExchangeModel(); ExchangeView view = new ExchangeView(); @@ -104,6 +199,39 @@ public static Parent createExchangeView() { } + /** + * Wrapper for Exchange View initialization method. + * + *

+ * Initializes a default exchange view. + *

+ * + * @return View's root + */ + public static Parent createExchangeView() { + return createDefaultExchangeView(false); + } + + /** + * Wrapper for Exchange View initialization method. + * + *

+ * Initializes a default exchange view with the clean parameter. + *

+ * + * @param clean - should it reset the page stack. + * @rteturn View's root + */ + public static Parent createExchangeView(boolean clean) { + return createDefaultExchangeView(clean); + } + + /** + * Initialization method for Stock View. + * + * @param symbol - Symbol of stock for the view. + * @return View's root. + */ public static Parent createStockView(String symbol) { mark(() -> createStockView(symbol)); @@ -119,6 +247,11 @@ public static Parent createStockView(String symbol) { return view.getInstance(); } + /** + * Initialization method for Transaction View. + * + * @return View's root. + */ public static Parent createTransactionView() { mark(() -> createTransactionView()); @@ -133,6 +266,12 @@ public static Parent createTransactionView() { return view.getInstance(); } + /** + * Initialization method for Newspaper View. + * + * @param symbol - Symbol of stock for view. + * @return View's root. + */ public static Parent createNewspaperView(String symbol) { mark(() -> createNewspaperView(symbol)); @@ -148,4 +287,26 @@ public static Parent createNewspaperView(String symbol) { return view.getInstance(); } + /** + * Initialization method for Finish View. + * + *

+ * Deletes current session on visit, + * working as a destructor from controller. + *

+ * + * @return View's root. + */ + public static Parent createFinishView() { + + FinishModel model = new FinishModel(); + FinishView view = new FinishView(); + FinishController controller = new FinishController(model); + + view.setController(controller); + + SessionManager.removeSession(); + return view.getInstance(); + } + } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java index a334769..de916a7 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractController.java @@ -1,9 +1,21 @@ package edu.ntnu.idi.idatt.view.components; +/** + * Abstract class for controller. + * + *

+ * Works as indicator to bind together with a proper model object. + *

+ * + * @see Model + */ public abstract class AbstractController { protected final M model; + /** + * Default AbstractController constructor. + */ public AbstractController(M model) { this.model = model; } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java index 8c1a119..93a9574 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java @@ -10,6 +10,13 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +/** + * Abstract View UI class. + * + *

+ * Creates a view layout to simplify further view creation for child classes. + *

+ */ public abstract class AbstractViewUI extends AbstractView { private VBox navigation; @@ -18,6 +25,15 @@ public abstract class AbstractViewUI extends AbstractView { private VBox menu; private SimpleBooleanProperty isMenuVisible = new SimpleBooleanProperty(false); + /** + * Constructor for AbstactViewUI. + * + *

+ * Binds the abstract classes into + * the root StackPane. + * Binds together smaller modules which are persistent across all views. + *

+ */ public AbstractViewUI() { HBox wrapper = new HBox(); BorderPane layout = new BorderPane(); @@ -55,13 +71,16 @@ public AbstractViewUI() { this.getInstance().getChildren().addAll(wrapper, disableMenu, menu); } + /** + * Method for creating initial view wrappers. + */ public void createUIComponents() { navigation = new VBox(); navigation.setMaxHeight(Double.MAX_VALUE); navigation.getStyleClass().add("dark"); - navigation.setPrefWidth(150); // ScrollPane's affect this massively - navigation.setMaxWidth(150); - navigation.setMinWidth(150); + navigation.setPrefWidth(300); // ScrollPane's affect this massively + navigation.setMaxWidth(300); + navigation.setMinWidth(300); header = new HBox(); header.getStyleClass().add("light"); @@ -77,28 +96,71 @@ public void createUIComponents() { menu.setMaxWidth(300); } + /** + * Abstract method for content creation. + * + * @return Root node of content. + */ public abstract Parent createContent(); + /** + * Abstract method for navigation creation. + * + * @return Root node of navigation. + */ public abstract Parent createNavigation(); + /** + * Abstract method for header creation. + * + * @return Root node of header. + */ public abstract Parent createHeader(); + /** + * Abstract method for toolbar creation. + * + * @return Root node of toolbar. + */ public abstract Parent createToolbar(); + /** + * Abstract method for menu creation. + * + * @return Root node of menu. + */ public abstract Parent createMenu(); + /** + * Getter for navigation. + * + * @return VBox; + */ public VBox getNavigation() { return navigation; } + /** + * Getter for header. + * + * @return HBox; + */ public HBox getHeader() { return header; } + /** + * Getter for toolbar. + * + * @return HBox; + */ public HBox getToolbar() { return toolbar; } + /** + * Method for toggling the visibility of the menu. + */ public void toggleMenu() { isMenuVisible.set(!isMenuVisible.get()); } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java b/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java index 2465fd7..0687baa 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/Model.java @@ -1,4 +1,12 @@ package edu.ntnu.idi.idatt.view.components; +/** + * Interface Model + * + *

+ * Used as an indicator to bind to controllers + * with the right model. + *

+ */ public interface Model { } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java index a3ef67a..3931106 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java @@ -6,15 +6,30 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.StackPane; +/** + * Icon Component class. + * + *

+ * JavaFX Component for handeling repetative tasks. + * Creates a clickable icon with optional description. + *

+ */ public class IconComponent extends StackPane { private Button icon; + /** + * Constructor for IconComponent + * + * @param image - Icon image + * @param description - String describing icon button. + * @param size - width and height of the icon image. + */ public IconComponent(Image image, String description, int size) { ImageView iv = new ImageView(); iv.setImage(image); - iv.setFitHeight(size); // TODO: Fix? + iv.setFitHeight(size); iv.setFitWidth(size); icon = new Button(description, iv); @@ -25,6 +40,11 @@ public IconComponent(Image image, String description, int size) { this.getChildren().add(icon); } + /** + * Method for handeling icon click. + * + * @param handler - Functional interface. + */ public void onIconClick(ActionEventHandler handler) { this.icon.setOnAction(e -> handler.handle()); } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/NewspaperComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/NewspaperComponent.java deleted file mode 100644 index 8661c9b..0000000 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/NewspaperComponent.java +++ /dev/null @@ -1,33 +0,0 @@ -package edu.ntnu.idi.idatt.view.components.elements; - -import edu.ntnu.idi.idatt.model.portfolio.Share; -import edu.ntnu.idi.idatt.view.components.ui.UICompositor; -import javafx.geometry.Insets; -import javafx.geometry.Pos; -import javafx.scene.control.Label; -import javafx.scene.layout.HBox; -import javafx.scene.layout.VBox; - -public class NewspaperComponent extends HBox { - private final Label newsTitle; - private final Label newsText; - - public NewspaperComponent(Share share) { - this.setPadding(new Insets(30)); - this.getStyleClass().add("newspaper-article"); - - newsTitle = new Label("Earthquake in Norway"); - newsText = new Label("Intel are crashing"); - newsTitle.getStyleClass().add("newspaper-title"); - newsText.getStyleClass().add("newspaper-med-text"); - - UICompositor shareComponent = new UICompositor.Builder() - .parent(new VBox()) - .growWithAlignment(Pos.TOP_CENTER) - .addAllContent(newsTitle, newsText) - .build(); - - this.getChildren().add(shareComponent.makeUI()); - } - -} diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/RecieptComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/RecieptComponent.java new file mode 100644 index 0000000..8ada10f --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/RecieptComponent.java @@ -0,0 +1,126 @@ +package edu.ntnu.idi.idatt.view.components.elements; + +import java.util.List; + +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.service.transaction.PurchaseCalculator; +import edu.ntnu.idi.idatt.service.transaction.SaleCalculator; +import edu.ntnu.idi.idatt.view.components.primitives.ActionEventHandler; +import edu.ntnu.idi.idatt.view.components.ui.UICompositor; +import edu.ntnu.idi.idatt.view.util.CssUtils; +import javafx.geometry.Pos; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; + +/** + * Reciept component class + * + *

+ * JavaFX Component for handeling repetative tasks. + * Creates a reciept based on a transaction. + *

+ * + * @see Transaction + */ +public class RecieptComponent extends VBox { + + private Button doneButton; + + /** + * Constructor for RecieptComponent + * + * @param transaction - transaction object to create a reciept for. + */ + public RecieptComponent(Transaction transaction) { + + Label title = new Label("Reciept"); + CssUtils.apply(title, CssUtils.BIG_TEXT_32); + + Label operation = new Label(); + String operationString = "Transaction type: %s"; + + Label week = new Label(String.format("Week: %s", transaction.getWeek())); + + Label shareName = new Label(String.format("Share: %s", transaction.getShare().getStock().toString())); + Label shareAmount = new Label(String.format("Amount: %.3f", transaction.getShare().getQuantity())); + + Label gross = new Label(); + String grossString = "Gross: %.2f $"; + + Label tax = new Label(); + String taxString = "Taxes: %.2f $"; + + Label comission = new Label(); + String comissionString = "Comission: %.2f $"; + + Label total = new Label(); + String totalString = "Total: %.2f $"; + + Label profits = new Label(); + + List