diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/controller/appcontrollers/StockAppController.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/controller/appcontrollers/StockAppController.java index 513a9ca..aafa39f 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/controller/appcontrollers/StockAppController.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/controller/appcontrollers/StockAppController.java @@ -139,7 +139,7 @@ private ListCell createStockCell() { row.setAlignment(Pos.CENTER_LEFT); row.getStyleClass().add("stock-list-item"); - VBox names = new VBox(2, symbolLabel, companyLabel); + final VBox names = new VBox(2, symbolLabel, companyLabel); symbolLabel.getStyleClass().add("stock-symbol"); companyLabel.getStyleClass().add("stock-company"); @@ -190,11 +190,11 @@ protected void updateItem(final Stock stock, final boolean empty) { /** Sets weekend status. */ public void setWeekend(final boolean weekend) { this.isWeekend = weekend; - Platform.runLater(this::updateTradeUI); + Platform.runLater(this::updateTradeUi); } /** Updates the Trade button and spinner state. */ - private void updateTradeUI() { + private void updateTradeUi() { Button tradeButton = stockApp.getConfirmButton(); var spinner = stockApp.getQuantitySpinner(); @@ -307,30 +307,23 @@ private void handleSell(final Stock stock, final BigDecimal quantity) { private void updateReceipt() { if (currentStock != null) { Platform.runLater(() -> { - stockApp.getReceipt().update( - currentStock, - new BigDecimal(stockApp.getQuantitySpinner().getValue()) - ); - updateTradeUI(); + stockApp.getReceipt().update( + currentStock, + new BigDecimal(stockApp.getQuantitySpinner().getValue())); + updateTradeUi(); }); } } /** Updates the stock list with current sort and filter. */ private void updateStockList() { - List stocks = new ArrayList<>(marketController.getMarket(stockApp.getSearchField().getText())); - Comparator comparator; - switch (currentSort) { - case GAINER: - comparator = Comparator.comparing(Stock::getLatestPriceChange); - break; - case PRICE: - comparator = Comparator.comparing(Stock::getSalesPrice); - break; - default: - comparator = Comparator.comparing(Stock::getSymbol); - break; - } + List stocks = new ArrayList<>( + marketController.getMarket(stockApp.getSearchField().getText())); + Comparator comparator = switch (currentSort) { + case GAINER -> Comparator.comparing(Stock::getLatestPriceChange); + case PRICE -> Comparator.comparing(Stock::getSalesPrice); + default -> Comparator.comparing(Stock::getSymbol); + }; if (isDescending) { comparator = comparator.reversed(); } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Player.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Player.java index d07f6ff..c2517fa 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Player.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Player.java @@ -3,10 +3,21 @@ import edu.ntnu.idi.idatt2003.gruppe42.model.exceptions.InsufficientFunds; import edu.ntnu.idi.idatt2003.gruppe42.model.transaction.TransactionArchive; import java.math.BigDecimal; - -import javafx.beans.property.*; - -/** Represents a player. */ +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +/** + * Represents a player in the game, holding their financial state, portfolio, + * transaction history, lives, and progression status. + * + *

A player starts with a fixed amount of money and progresses through + * {@link Status} levels ({@code NOVICE} → {@code INVESTOR} → {@code SPECULATOR}) + * based on net worth growth and weeks of trading activity. + */ public class Player { private static final int MAX_LIVES = 3; @@ -19,6 +30,15 @@ public class Player { private final IntegerProperty lives = new SimpleIntegerProperty(MAX_LIVES); private final ObjectProperty status = new SimpleObjectProperty<>(Status.NOVICE); + /** + * Constructs a new {@code Player} with the given name and starting balance. + * + *

The player begins with {@link #MAX_LIVES} lives, an empty portfolio, + * an empty transaction archive, and {@link Status#NOVICE} status. + * + * @param name the display name of the player; must not be {@code null} + * @param startingMoney the initial cash balance; must not be {@code null} or negative + */ public Player(final String name, final BigDecimal startingMoney) { this.name.set(name); this.startingMoney = startingMoney; @@ -27,27 +47,34 @@ public Player(final String name, final BigDecimal startingMoney) { this.transactionArchive = new TransactionArchive(); } - - /** @return name property. */ + /** + * Returns the observable {@link StringProperty} backing the player's name. + * + *

Useful for binding UI components directly to the player's name. + * + * @return the name property; never {@code null} + */ public StringProperty getNameProperty() { return name; } - /** @return player's name. */ + public String getName() { return name.get(); } - /** Sets player's name. */ + + /** + * Sets the player's display name. + * + * @param name the new name; must not be {@code null} + */ public void setName(final String name) { this.name.set(name); } - - /** @return starting money. */ public BigDecimal getStartingMoney() { return startingMoney; } - /** @return current money. */ public BigDecimal getMoney() { return money; } @@ -77,23 +104,18 @@ public void deductRent(final BigDecimal amount) { updateStatus(); } - /** @return true if in debt. */ public boolean isInDebt() { return money.compareTo(BigDecimal.ZERO) < 0; } - /** @return total net worth. */ public BigDecimal getNetWorth() { return money.add(portfolio.getNetWorth()); } - - /** @return lives property. */ public IntegerProperty getLivesProperty() { return lives; } - /** @return number of lives. */ public int getLives() { return lives.get(); } @@ -103,19 +125,31 @@ public void loseLife() { lives.set(Math.max(0, lives.get() - 1)); } - - /** @return player's portfolio. */ public Portfolio getPortfolio() { return portfolio; } - /** @return transaction archive. */ public TransactionArchive getTransactionArchive() { return transactionArchive; } - - /** Updates the player's status. */ + /** + * Re-evaluates and updates the player's {@link Status} based on their current + * net worth and number of distinct trading weeks recorded in the + * {@link TransactionArchive}. + * + *

Promotion criteria: + *

    + *
  • SPECULATOR: at least 20 distinct weeks active and + * net worth ≥ 5× starting money.
  • + *
  • INVESTOR: at least 10 distinct weeks active and + * net worth ≥ 1.2× starting money.
  • + *
  • NOVICE: all other cases.
  • + *
+ * + *

This method is called automatically by {@link #addMoney(BigDecimal)}, + * {@link #withdrawMoney(BigDecimal)}, and {@link #deductRent(BigDecimal)}. + */ public void updateStatus() { final int investorWeeks = 10; final int speculatorWeeks = 20; @@ -142,8 +176,6 @@ public void updateStatus() { } } - - /** @return player status property. */ public ObjectProperty getStatusProperty() { return status; } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Stock.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Stock.java index 9751c9a..430c5e1 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Stock.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/model/Stock.java @@ -6,13 +6,25 @@ import java.util.ArrayList; import java.util.List; -/** Represents a stock of a company. */ +/** + * Represents a publicly traded stock belonging to a company. + * + *

A stock maintains a full chronological price history, exposes summary + * statistics (highest, lowest, the latest change), and delegates price-update + * logic to a {@link StockController}. An optional {@link StockGraph} can be + * lazily attached for visual rendering. + * + *

Price history is append-only: new prices are recorded via + * {@link #addNewSalesPrice(BigDecimal)} or {@link #updatePrice()}, and the + * most recent entry is always considered the current market price. + */ public class Stock { private final String symbol; private final String company; private StockGraph stockGraph; - private List prices = new ArrayList<>(); - private StockController stockController; + private final List prices = new ArrayList<>(); + private final StockController stockController; + /** Constructs a new stock. */ public Stock( final String symbol, @@ -25,17 +37,14 @@ public Stock( stockController = new StockController(this); } - /** @return the symbol. */ public String getSymbol() { return symbol; } - /** @return the company. */ public String getCompany() { return company; } - /** @return current sales price. */ public BigDecimal getSalesPrice() { return prices.isEmpty() ? BigDecimal.ZERO : prices.get(prices.size() - 1); } @@ -45,22 +54,20 @@ public void addNewSalesPrice(final BigDecimal salesPrice) { prices.add(salesPrice); } - /** @return historical prices. */ public List getHistoricalPrices() { return List.copyOf(prices); } - /** @return highest price. */ - public BigDecimal getHighestPrice() { - return prices.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO); - } - - /** @return lowest price. */ - public BigDecimal getLowestPrice() { - return prices.stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO); - } - - /** @return price change. */ + /** + * Returns the price change between the current price and the price recorded + * 120 ticks ago (or the oldest available price if fewer than 121 entries exist). + * + *

A positive value indicates the stock has risen over that window; + * a negative value indicates it has fallen. + * + * @return the price delta over the last 120 ticks; never {@code null}; + * {@link BigDecimal#ZERO} if the price history is empty + */ public BigDecimal getLatestPriceChange() { if (prices.isEmpty()) { return BigDecimal.ZERO; @@ -75,7 +82,12 @@ public void updatePrice() { prices.add(newPrice); } - /** @return stock graph. */ + /** + * Returns the {@link StockGraph} component associated with this stock, + * creating it lazily on the first call. + * + * @return the stock graph; never {@code null} + */ public StockGraph getStockGraph() { if (stockGraph == null) { stockGraph = new StockGraph(); diff --git a/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/PurchaseCalculatorTest.java b/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/PurchaseCalculatorTest.java index e74eed3..4bc34f8 100644 --- a/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/PurchaseCalculatorTest.java +++ b/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/PurchaseCalculatorTest.java @@ -11,13 +11,11 @@ public class PurchaseCalculatorTest { private PurchaseCalculator calculator; - private BigDecimal purchasePrice; - private BigDecimal quantity; @BeforeEach void setUp() { - purchasePrice = new BigDecimal("100"); - quantity = new BigDecimal("10"); + BigDecimal purchasePrice = new BigDecimal("100"); + BigDecimal quantity = new BigDecimal("10"); Stock stock = new Stock("AAPL", "Apple Inc.", new BigDecimal("150")); Share share = new Share(stock, quantity, purchasePrice); diff --git a/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/SaleCalculatorTest.java b/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/SaleCalculatorTest.java index 90aad67..b8ef938 100644 --- a/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/SaleCalculatorTest.java +++ b/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/model/calculator/SaleCalculatorTest.java @@ -11,15 +11,12 @@ public class SaleCalculatorTest { private SaleCalculator calculator; - private BigDecimal purchasePrice; - private BigDecimal salesPrice; - private BigDecimal quantity; @BeforeEach void setUp() { - purchasePrice = new BigDecimal("100"); - salesPrice = new BigDecimal("150"); - quantity = new BigDecimal("10"); + BigDecimal purchasePrice = new BigDecimal("100"); + BigDecimal salesPrice = new BigDecimal("150"); + BigDecimal quantity = new BigDecimal("10"); Stock stock = new Stock("AAPL", "Apple Inc.", salesPrice); Share share = new Share(stock, quantity, purchasePrice);