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 101b38e..51008ec 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
@@ -1,31 +1,108 @@
package edu.ntnu.idi.idatt2003.gruppe42.Controller.AppControllers;
import edu.ntnu.idi.idatt2003.gruppe42.Controller.MarketController;
+import edu.ntnu.idi.idatt2003.gruppe42.Model.Player;
+import edu.ntnu.idi.idatt2003.gruppe42.Model.Share;
+import edu.ntnu.idi.idatt2003.gruppe42.Model.Stock;
+import edu.ntnu.idi.idatt2003.gruppe42.Model.Transaction.Transaction;
import edu.ntnu.idi.idatt2003.gruppe42.View.Apps.StockApp;
+import java.math.BigDecimal;
public class StockAppController implements AppController {
private MarketController marketController;
private StockApp stockPopup;
+ private Stock currentStock;
- public StockAppController(StockApp stockPopup, MarketController marketController) {
+ public StockAppController(StockApp stockPopup, MarketController marketController, Player player) {
this.stockPopup = stockPopup;
this.marketController = marketController;
- stockPopup.getStockList().getItems().addAll(marketController.getMarket());
- stockPopup.getSearchField().textProperty().addListener((obs, old, newValue) -> {
+ stockPopup.getStockList().getItems().addAll(marketController.getExchange().getAllStocks());
+
+ stockPopup.getSearchField().textProperty().addListener((
+ obs, old, newValue) -> {
+ if (stockPopup.getCurrentStock() != null) {
+ stockPopup.openSearchPage();
+ }
stockPopup.getStockList().getItems().setAll(marketController.getMarket(newValue));
});
+ stockPopup.getBuyButton().setOnMouseClicked(event -> {
+ currentStock = stockPopup.getCurrentStock();
+ if (currentStock == null) {
+ return;
+ }
+
+ String quantityText = stockPopup.getQuantityField().getText();
+ BigDecimal quantity;
+ try {
+ quantity = new BigDecimal(quantityText);
+ if (quantity.compareTo(BigDecimal.ZERO) <= 0) {
+ return;
+ }
+ } catch (NumberFormatException e) {
+ return;
+ }
+
+ Transaction transaction = marketController.getExchange().buy(
+ currentStock.getSymbol(), quantity, player
+ );
+
+ if (transaction == null) {
+ return;
+ }
+
+ player.getTransactionArchive().add(transaction);
+ player.getPortfolio().addShare(transaction.getShare());
+ });
+
+ stockPopup.getSellButton().setOnMouseClicked(event -> {
+ currentStock = stockPopup.getCurrentStock();
+ if (currentStock == null) {
+ return;
+ }
+
+ String quantityText = stockPopup.getQuantityField().getText();
+ BigDecimal quantityToSell;
+ try {
+ quantityToSell = new BigDecimal(quantityText);
+ if (quantityToSell.compareTo(BigDecimal.ZERO) <= 0) {
+ return;
+ }
+ } catch (NumberFormatException e) {
+ return;
+ }
+
+ player.getPortfolio().getShares().stream()
+ .filter(s -> s.getStock().getSymbol().equals(currentStock.getSymbol()))
+ .findFirst()
+ .ifPresent(existingShare -> {
+ if (existingShare.getQuantity().compareTo(quantityToSell) < 0) {
+ return;
+ }
+
+ Transaction transaction = marketController.getExchange().sell(existingShare, quantityToSell, player);
+ player.getTransactionArchive().add(transaction);
+ player.getPortfolio().removeShare(transaction.getShare());
+ });
+ });
+
}
+ /**
+ * Updates the app state on each simulation tick.
+ * Refreshes the market data and updates the price label for the currently viewed stock.
+ */
@Override
- public void nextTick(){
+ public void nextTick() {
System.out.println("[DEBUG] StockAppController.nextTick() - Updating Market");
marketController.updateMarket();
- if (stockPopup.getCurrentStock() != null) {
- System.out.println("[DEBUG] Updating Price Label for: " + stockPopup.getCurrentStock().getCompany());
- stockPopup.updatePriceLabel(stockPopup.getCurrentStock());
+ Stock currentStockInView = stockPopup.getCurrentStock();
+ if (currentStockInView != null) {
+ System.out.println("[DEBUG] Updating Price Label for: "
+ + currentStockInView.getCompany());
+ stockPopup.updatePriceLabel(currentStockInView);
}
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/GameController.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/GameController.java
index e8e5401..7a0614d 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/GameController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/GameController.java
@@ -3,7 +3,6 @@
import edu.ntnu.idi.idatt2003.gruppe42.Controller.AppControllers.AppController;
import edu.ntnu.idi.idatt2003.gruppe42.Model.Player;
-import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/MarketController.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/MarketController.java
index f7d0711..1fe12cf 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/MarketController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/MarketController.java
@@ -1,5 +1,6 @@
package edu.ntnu.idi.idatt2003.gruppe42.Controller;
+import edu.ntnu.idi.idatt2003.gruppe42.Model.Exchange;
import edu.ntnu.idi.idatt2003.gruppe42.Model.Stock;
import edu.ntnu.idi.idatt2003.gruppe42.Model.StockFileHandler;
import edu.ntnu.idi.idatt2003.gruppe42.View.Apps.StockApp;
@@ -12,7 +13,7 @@
public class MarketController {
- private List market;
+ private Exchange exchange;
private int stockResolution;
private StockApp stockApp;
@@ -21,7 +22,7 @@ public MarketController() {
try {
Path path = Path.of(getClass().getClassLoader().getResource("stocks.csv").toURI());
- market = StockFileHandler.readFromFile(path);
+ exchange = new Exchange(StockFileHandler.readFromFile(path));
startMarket();
System.out.println("Market loaded");
@@ -31,19 +32,18 @@ public MarketController() {
}
}
- public List getMarket() {
- return market;
+ public Exchange getExchange() {
+ return exchange;
}
public List getMarket(String searchTerm) {
- return market.stream()
- .filter(stock -> stock.getCompany().toLowerCase().contains(searchTerm.toLowerCase()))
- .toList();
+ return exchange.findStocks(searchTerm);
}
public void updateMarket() {
- System.out.println("[DEBUG] MarketController.updateMarket() - Updating prices for " + market.size() + " stocks");
- for (Stock stock : market) {
+ System.out.println("[DEBUG] MarketController.updateMarket() - Updating prices for "
+ + exchange.getAllStocks().size() + " stocks");
+ for (Stock stock : exchange.getAllStocks()) {
stock.updatePrice();
if (stock.getStockGraph().getVisibility()) {
stock.updateStockGraph();
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/ViewControllers/DesktopViewController.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/ViewControllers/DesktopViewController.java
index 6f64d63..20d2b06 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/ViewControllers/DesktopViewController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Controller/ViewControllers/DesktopViewController.java
@@ -51,7 +51,7 @@ public DesktopViewController(Player player, GameController gameController) {
StockApp stockApp = new StockApp(400, 300, 120, 120);
MarketController marketController = new MarketController();
- gameController.addAppController(new StockAppController(stockApp, marketController));
+ gameController.addAppController(new StockAppController(stockApp, marketController, player));
MailApp mailApp = new MailApp(400, 300, 160, 160);
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Calculator/SaleCalculator.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Calculator/SaleCalculator.java
index 478e87d..a334bac 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Calculator/SaleCalculator.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Calculator/SaleCalculator.java
@@ -14,25 +14,52 @@ public SaleCalculator(Share share) {
this.quantity = share.getQuantity();
}
+ /**
+ * Calculates the gross value of the sale (quantity * sales price).
+ *
+ * @return the gross sale value
+ */
@Override
public BigDecimal calculateGross() {
return salesPrice.multiply(quantity);
}
+ /**
+ * Calculates the commission for the sale (1% of gross).
+ *
+ * @return the commission amount
+ */
@Override
public BigDecimal calculateCommission() {
BigDecimal commissionRate = new BigDecimal("0.01");
return calculateGross().multiply(commissionRate);
}
+ /**
+ * Calculates the tax on the capital gain (22% of profit).
+ * Profit is defined as (sales price - purchase price) * quantity.
+ * If there is no profit, tax is zero (clamped by max(ZERO) in a robust implementation,
+ * but here we follow existing logic).
+ *
+ * @return the tax amount
+ */
@Override
public BigDecimal calculateTax() {
BigDecimal taxRate = new BigDecimal("0.22");
- BigDecimal differencePrice = salesPrice.subtract(purchasePrice);
- BigDecimal difference = differencePrice.multiply(quantity);
- return difference.multiply(taxRate);
+ BigDecimal priceDifference = salesPrice.subtract(purchasePrice);
+ BigDecimal totalProfit = priceDifference.multiply(quantity);
+ // Only tax if there is a profit
+ if (totalProfit.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+ return totalProfit.multiply(taxRate);
}
+ /**
+ * Calculates the net total received from the sale (gross - commission - tax).
+ *
+ * @return the net sale amount
+ */
@Override
public BigDecimal calculateTotal() {
return calculateGross().subtract(calculateCommission()).subtract(calculateTax());
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Exchange.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Exchange.java
index 0f9ba70..5be159e 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Exchange.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Exchange.java
@@ -19,7 +19,6 @@
*
*/
public class Exchange {
- private String name;
private int week;
private Map stockMap;
private Random random;
@@ -27,11 +26,9 @@ public class Exchange {
/**
* Constructs a new {@code Exchange} with a name and a list of stocks.
*
- * @param name the name of the exchange (e.g., "NYSE")
* @param stocks the initial list of available stocks on the exchange
*/
- public Exchange(String name, List stocks) {
- this.name = name;
+ public Exchange(List stocks) {
this.week = 0;
this.stockMap = new HashMap();
this.random = new Random();
@@ -40,10 +37,6 @@ public Exchange(String name, List stocks) {
}
}
- public String getName() {
- return name;
- }
-
public int getWeek() {
return week;
}
@@ -69,20 +62,33 @@ public Stock getStock(String symbol) {
}
/**
- * Finds stocks by company name.
+ * Finds stocks by company name or symbol.
*
- * @param searchTerm the company name to search for
- * @return a list of {@code Stock} objects whose company name matches the search term
+ * @param searchTerm the term to search for (case-insensitive)
+ * @return a list of {@code Stock} objects matching the search term, sorted alphabetically
*/
public List findStocks(String searchTerm) {
- List foundStocks = new ArrayList<>();
-
- for (Stock stock : stockMap.values()) {
- if (stock.getCompany().equals(searchTerm)) {
- foundStocks.add(stock);
- }
+ if (searchTerm == null || searchTerm.isBlank()) {
+ return getAllStocks();
}
- return foundStocks;
+
+ String lowerSearchTerm = searchTerm.toLowerCase();
+ return stockMap.values().stream()
+ .filter(stock -> stock.getCompany().toLowerCase().contains(lowerSearchTerm)
+ || stock.getSymbol().toLowerCase().contains(lowerSearchTerm))
+ .sorted((a, b) -> a.getCompany().compareToIgnoreCase(b.getCompany()))
+ .toList();
+ }
+
+ /**
+ * Returns all available stocks on the exchange, sorted alphabetically by company name.
+ *
+ * @return a sorted list of all {@code Stock} objects
+ */
+ public List getAllStocks() {
+ return stockMap.values().stream()
+ .sorted((a, b) -> a.getCompany().compareToIgnoreCase(b.getCompany()))
+ .toList();
}
/**
@@ -97,10 +103,10 @@ public List findStocks(String searchTerm) {
* @return a {@code Purchase} transaction representing the purchase
*/
public Transaction buy(String symbol, BigDecimal quantity, Player player) {
- System.out.println("[DEBUG] Exchange " + name + " - Buying " + quantity + " of " + symbol + " for player " + player.getName());
- player.withdrawMoney(quantity);
+ System.out.println("[DEBUG] Exchange" + " Buying " + quantity + " of " + symbol + " for player " + player.getName());
Stock stock = getStock(symbol);
BigDecimal purchasePrice = stock.getSalesPrice();
+ player.withdrawMoney(quantity.multiply(purchasePrice));
Share share = new Share(stock, quantity, purchasePrice);
System.out.println("[DEBUG] Purchase complete: " + quantity + " shares of " + symbol + " at " + purchasePrice);
@@ -108,22 +114,24 @@ public Transaction buy(String symbol, BigDecimal quantity, Player player) {
}
/**
- * Allows a player to sell a share on the exchange.
- *
- * The player receives money based on the sale calculation, and a {@code Sale} transaction is returned.
- *
+ * Allows a player to sell a portion of a share position on the exchange.
*
- * @param share the share to sell
+ * @param share the share position from which to sell
+ * @param quantity the amount of stock to sell
* @param player the player performing the sale
* @return a sale transaction representing the sale
*/
- public Transaction sell(Share share, Player player) {
- System.out.println("[DEBUG] Exchange " + name + " - Selling shares of " + share.getStock().getSymbol() + " for player " + player.getName());
- SaleCalculator saleCalculator = new SaleCalculator(share);
+ public Transaction sell(Share share, BigDecimal quantity, Player player) {
+ System.out.println("[DEBUG] Exchange - Selling " + quantity + " shares of "
+ + share.getStock().getSymbol() + " for player " + player.getName());
+
+ Share shareToSell = new Share(share.getStock(), quantity, share.getPurchasePrice());
+ SaleCalculator saleCalculator = new SaleCalculator(shareToSell);
BigDecimal totalValue = saleCalculator.calculateTotal();
player.addMoney(totalValue);
+
System.out.println("[DEBUG] Sale complete: Received " + totalValue);
- return new Sale(share, week);
+ return new Sale(shareToSell, week);
}
/**
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Portfolio.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Portfolio.java
index 1353056..95dd309 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Portfolio.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Portfolio.java
@@ -3,8 +3,10 @@
import edu.ntnu.idi.idatt2003.gruppe42.Model.Calculator.SaleCalculator;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Represents a collection of {@link Share} objects owned by a {@link Player}.
@@ -24,40 +26,92 @@ public Portfolio() {
}
/**
- * Adds a share to the portfolio.
+ * Adds a share position to the portfolio.
+ * If a position already exists for the stock, the new quantity is added,
+ * and the purchase price is recalculated as a weighted average.
*
- * @param share the {@code Share} to add
- * @return {@code true} if the share was successfully added, {@code false} if the share was {@code null}
+ * @param shareToAdd the {@code Share} position to add
+ * @return {@code true} if the share was successfully added or merged, {@code false} if it was {@code null}
*/
- public boolean addShare(Share share) {
- if (share == null) {
+ public boolean addShare(Share shareToAdd) {
+ if (shareToAdd == null) {
return false;
- } else {
- return shares.add(share);
}
+
+ // Check if we already own a share with the same stock symbol
+ for (Share existingShare : shares) {
+ if (existingShare.getStock().getSymbol().equals(shareToAdd.getStock().getSymbol())) {
+
+ // Weighted average purchase price: (q1*p1 + q2*p2) / (q1+q2)
+ BigDecimal totalQuantity = existingShare.getQuantity().add(shareToAdd.getQuantity());
+
+ BigDecimal weightedPrice = existingShare.getQuantity()
+ .multiply(existingShare.getPurchasePrice())
+ .add(shareToAdd.getQuantity().multiply(shareToAdd.getPurchasePrice()))
+ .divide(totalQuantity, 10, RoundingMode.HALF_UP);
+
+ // Replace the existing share with the merged one
+ shares.remove(existingShare);
+ return shares.add(new Share(existingShare.getStock(), totalQuantity, weightedPrice));
+ }
+ }
+
+ // No matching symbol found — add as new position
+ return shares.add(shareToAdd);
}
/**
- * Removes a share from the portfolio.
+ * Removes a portion of a share position from the portfolio.
*
- * @param share the {@code Share} to remove
- * @return {@code true} if the share was successfully removed,
- * {@code false} if the share was {@code null} or not present in the portfolio
+ * @param shareToRemove the {@code Share} object containing the stock and quantity to remove
+ * @return {@code true} if the share was successfully removed or updated,
+ * {@code false} if the input was {@code null} or the share was not found,
+ * or if the quantity to remove exceeds the owned quantity.
*/
- public boolean removeShare(Share share) {
- if (share == null || !shares.contains(share)) {
+ public boolean removeShare(Share shareToRemove) {
+ if (shareToRemove == null) {
return false;
+ }
+
+ Optional match = shares.stream()
+ .filter(s -> s.getStock().getSymbol().equals(shareToRemove.getStock().getSymbol()))
+ .findFirst();
+
+ if (match.isEmpty()) {
+ System.out.println("[DEBUG] Portfolio - Did not find share: " + shareToRemove.getStock().getSymbol());
+ return false;
+ }
+
+ Share existingShare = match.get();
+ BigDecimal remainingQuantity = existingShare.getQuantity().subtract(shareToRemove.getQuantity());
+ int comparisonResult = remainingQuantity.compareTo(BigDecimal.ZERO);
+
+ if (comparisonResult < 0) {
+ // Trying to sell more than owned
+ System.out.println("[DEBUG] Portfolio - Cannot sell " + shareToRemove.getQuantity()
+ + " of " + shareToRemove.getStock().getSymbol()
+ + ", only " + existingShare.getQuantity() + " owned");
+ return false;
+ } else if (comparisonResult == 0) {
+ // Selling entire position — remove from list
+ System.out.println("[DEBUG] Portfolio - Fully closed position: " + existingShare.getStock().getSymbol());
+ return shares.remove(existingShare);
} else {
- return shares.remove(share);
+ // Partial sale — update quantity in place
+ existingShare.setQuantity(remainingQuantity);
+ System.out.println("[DEBUG] Portfolio - Partial sale: " + shareToRemove.getQuantity()
+ + " sold, " + remainingQuantity + " remaining of " + existingShare.getStock().getSymbol());
+ return true;
}
}
public List getShares() {
- return this.shares;
+ return shares;
}
/**
* Checks whether the portfolio contains a given share.
+ *
* @param share the {@code Share} to check for
* @return {@code true} if the share exists in the portfolio, {@code false} if {@code null} or not found
*/
@@ -66,15 +120,15 @@ public boolean contains(Share share) {
}
/**
- * Iterates through a player's portfolio and calculates
- * the total networth of all shares if sold today.
- * @return the total sum of all shares
+ * Calculates the total net worth of all shares in the portfolio if sold at their current market price.
+ *
+ * @return the total value of all shares in the portfolio
*/
public BigDecimal getNetWorth() {
- BigDecimal totalSum = BigDecimal.ZERO;
+ BigDecimal totalValue = BigDecimal.ZERO;
for (Share share : shares) {
- totalSum = totalSum.add(new SaleCalculator(share).calculateTotal());
+ totalValue = totalValue.add(new SaleCalculator(share).calculateTotal());
}
- return totalSum;
+ return totalValue;
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Share.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Share.java
index 8f645dc..5d3281c 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Share.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Share.java
@@ -30,6 +30,10 @@ public Stock getStock() {
return stock;
}
+ public void setQuantity(BigDecimal quantity) {
+ this.quantity = quantity;
+ }
+
public BigDecimal getQuantity() {
return quantity;
}
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 a0b5abd..5b9980b 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
@@ -73,10 +73,9 @@ public BigDecimal getLatestPriceChange() {
public void updatePrice() {
BigDecimal oldPrice = getSalesPrice();
- BigDecimal newPrice = getSalesPrice().subtract(new BigDecimal("1"));
+ BigDecimal newPrice = oldPrice.subtract(new BigDecimal("0"));
newPrice = newPrice.max(BigDecimal.ZERO);
prices.add(newPrice);
- System.out.println("[DEBUG] Stock " + symbol + " updated: " + oldPrice + " -> " + newPrice);
}
public StockGraph getStockGraph() {
return stockGraph;
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Transaction/Sale.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Transaction/Sale.java
index 6367cf9..fcfe51b 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Transaction/Sale.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Transaction/Sale.java
@@ -13,7 +13,7 @@ public Sale(Share share, int week) {
@Override
public void commit(Player player) {
setCommitted(true);
- player.withdrawMoney(getCalculator().calculateTotal());
+ player.addMoney(getCalculator().calculateTotal());
player.getTransactionArchive().add(this);
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/View/Apps/StockApp.java b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/View/Apps/StockApp.java
index deb75fd..37aad5a 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/View/Apps/StockApp.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/gruppe42/View/Apps/StockApp.java
@@ -18,6 +18,9 @@ public class StockApp extends Popup {
private TextField searchField;
private Label priceLabel;
private Stock currentStock;
+ private Button buyButton;
+ private Button sellButton;
+ private TextField quantityField;
/**
* Constructs a new Stock popup.
@@ -31,6 +34,17 @@ public StockApp(int width, int height, int x, int y) {
super(width, height, x, y, App.STOCK);
searchField = new TextField();
stockList = new ListView<>();
+ buyButton = new Button("Buy");
+ sellButton = new Button("Sell");
+ quantityField = new TextField("1");
+ quantityField.setPromptText("Quantity");
+
+ // Only allow numeric input
+ quantityField.textProperty().addListener((observable, oldValue, newValue) -> {
+ if (!newValue.matches("\\d*")) {
+ quantityField.setText(newValue.replaceAll("[^\\d]", ""));
+ }
+ });
stockList.setCellFactory(
lv ->
@@ -55,18 +69,6 @@ protected void updateItem(Stock stock, boolean empty) {
content.getChildren().addAll(searchField, stockList);
}
- public Stock getCurrentStock() {
- return currentStock;
- }
-
- public TextField getSearchField() {
- return searchField;
- }
-
- public ListView getStockList() {
- return stockList;
- }
-
public void openStockPage(Stock stock) {
currentStock = stock;
content.setAlignment(Pos.TOP_LEFT);
@@ -78,9 +80,8 @@ public void openStockPage(Stock stock) {
Label companyLabel = new Label(stock.getCompany());
priceLabel = new Label(stock.getSalesPrice().toString());
- Button buyButton = new Button("Buy");
- Button sellButton = new Button("Sell");
- header.getChildren().addAll(companyLabel, priceLabel, buyButton, sellButton);
+
+ header.getChildren().addAll(companyLabel, priceLabel, quantityField, buyButton, sellButton);
stock.getStockGraph().setVisibility(true);
Platform.runLater(() -> stock.updateStockGraph());
@@ -104,4 +105,26 @@ public void openSearchPage() {
content.getChildren().setAll(searchField, stockList);
}
+ public Stock getCurrentStock() {
+ return currentStock;
+ }
+
+ public TextField getSearchField() {
+ return searchField;
+ }
+ public Button getBuyButton() {
+ return buyButton;
+ }
+ public Button getSellButton() {
+ return sellButton;
+ }
+
+ public TextField getQuantityField() {
+ return quantityField;
+ }
+
+ public ListView getStockList() {
+ return stockList;
+ }
+
}
\ No newline at end of file
diff --git a/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/Model/ExchangeTest.java b/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/Model/ExchangeTest.java
index eb6bf72..3c3099a 100644
--- a/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/Model/ExchangeTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt2003/gruppe42/Model/ExchangeTest.java
@@ -16,7 +16,7 @@ public class ExchangeTest {
@BeforeEach
void setUp() {
Stock stock = new Stock("AAPL", "Apple Inc.", new BigDecimal("100"));
- exchange = new Exchange("NYSE", List.of(stock));
+ exchange = new Exchange(List.of(stock));
}
@Test