From f7ef95b90cc7776e63b9225e4f68851528674134 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 26 May 2026 23:23:51 +0200 Subject: [PATCH] Feat: Fix portfolio and summary controller Fixed portfolio (revert to arraylist of shares), and fixed visual bug in financial summary graph --- .../idatt2003/g40/mappe/engine/Exchange.java | 3 +- .../idatt2003/g40/mappe/model/Portfolio.java | 107 +++++++++--------- .../financialsummary/SummaryController.java | 1 - 3 files changed, 54 insertions(+), 57 deletions(-) diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java index bfeaad4..5e7bf07 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java @@ -297,13 +297,14 @@ public Transaction sell(BigDecimal amount, Share ownedPosition = matchingShares.getFirst(); BigDecimal totalOwned = ownedPosition.getQuantity(); + BigDecimal ownedPurchasePrice = ownedPosition.getPurchasePrice(); if (amount.compareTo(totalOwned) > 0) { amount = totalOwned; } Stock stock = ownedPosition.getStock(); - Share shareToSell = new Share(stock, amount, stock.getSalesPrice()); + Share shareToSell = new Share(stock, amount, ownedPurchasePrice); Transaction sale = TransactionFactory.createTransaction( TransactionType.SALE, shareToSell, getWeek() diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java index a2a73a3..3b08af9 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Portfolio.java @@ -2,6 +2,7 @@ import edu.ntnu.idi.idatt2003.g40.mappe.utils.Validator; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,9 +18,9 @@ public final class Portfolio { /** - * Map used to handle internal shares. + * List of shares in portfolio. * */ - private final Map shares = new HashMap<>(); + private final List shares = new ArrayList<>(); /** * Creates an empty portfolio. @@ -39,30 +40,13 @@ public void addShare(final Share share) throws IllegalArgumentException { if (share == null) { throw new IllegalArgumentException("Invalid share!"); } - String symbol = share.getStock().getSymbol().toUpperCase(); - - if (shares.containsKey(symbol)) { - Share existingShare = shares.get(symbol); - BigDecimal totalQuantity = - existingShare.getQuantity().add(share.getQuantity()); - - shares.put(symbol, - new Share( - share.getStock(), - totalQuantity, existingShare.getPurchasePrice() - ) - ); - } else { - shares.put(symbol, share); - } + shares.add(share); } /** * Removes a share from the portfolio. * - *

Uses the quantity value to deduct share amount from the map. - * If quantity to remove is equal to amount held, removes share entirely. - * If not, splits the share.

+ *

Removes based on FIFO (First In First Out)

* * @param share the share to remove * @@ -72,35 +56,42 @@ public void addShare(final Share share) throws IllegalArgumentException { * @throws IllegalArgumentException if share is null. * */ - public boolean removeShare(final Share share) - throws IllegalArgumentException { + public boolean removeShare(final Share share) throws IllegalArgumentException { if (share == null) { throw new IllegalArgumentException("Invalid share!"); } - String symbol = share.getStock().getSymbol().toUpperCase(); - if (!shares.containsKey(symbol)) { - return false; - } - Share ownedShare = shares.get(symbol); - int comparison = ownedShare.getQuantity().compareTo(share.getQuantity()); + String symbol = share.getStock().getSymbol(); - if (comparison < 0) { - throw new IllegalArgumentException( - "Cannot remove more shares than are currently owned!"); - } else if (comparison == 0) { - - shares.remove(symbol); - } else { - BigDecimal remainingQuantity = - ownedShare.getQuantity().subtract(share.getQuantity()); - shares.put(symbol, - new Share( - share.getStock(), - remainingQuantity, - ownedShare.getPurchasePrice() - ) - ); + List matchingShares = shares.stream() + .filter(s -> s.getStock().getSymbol().equalsIgnoreCase(symbol)) + .toList(); + + BigDecimal quantityToRemove = share.getQuantity(); + + BigDecimal totalOwned = matchingShares.stream() + .map(Share::getQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + if (quantityToRemove.compareTo(totalOwned) > 0) { + throw new IllegalArgumentException("Cannot remove more shares than are currently owned!"); + } + + for (Share s : matchingShares) { + if (quantityToRemove.signum() <= 0) { + break; + } + + int comparison = s.getQuantity().compareTo(quantityToRemove); + shares.remove(s); + + if (comparison > 0) { + BigDecimal remainingQuantity = s.getQuantity().subtract(quantityToRemove); + shares.add(new Share(s.getStock(), remainingQuantity, s.getPurchasePrice())); + quantityToRemove = BigDecimal.ZERO; + } else { + quantityToRemove = quantityToRemove.subtract(s.getQuantity()); + } } return true; } @@ -111,7 +102,7 @@ public boolean removeShare(final Share share) * @return a list of shares */ public List getShares() { - return List.copyOf(shares.values()); + return shares; } /** @@ -141,8 +132,9 @@ public List getShares(final String symbol) throw new IllegalArgumentException( Validator.VALID_STOCK_SYMBOL.getErrorMessage()); } - Share share = shares.get(symbol.toUpperCase()); - return share != null ? List.of(share) : List.of(); + return shares.stream() + .filter(s -> s.getStock().getSymbol().equalsIgnoreCase(symbol)) + .toList(); } /** @@ -160,10 +152,13 @@ public boolean contains(final Share share) if (share == null) { throw new IllegalArgumentException("Invalid share!"); } - String symbol = share.getStock().getSymbol().toUpperCase(); - Share owned = shares.get(symbol); - return owned != null - && owned.getQuantity().compareTo(share.getQuantity()) >= 0; + + BigDecimal totalOwned = shares.stream() + .filter(s -> s.getStock().getSymbol().equalsIgnoreCase(share.getStock().getSymbol())) + .map(Share::getQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + return totalOwned.compareTo(share.getQuantity()) >= 0; } /** @@ -174,7 +169,7 @@ public boolean contains(final Share share) * */ public BigDecimal getNetWorth() { BigDecimal netWorth = BigDecimal.ZERO; - for (Share s : shares.values()) { + for (Share s : shares) { netWorth = netWorth.add( s.getQuantity().multiply(s.getStock().getSalesPrice()) ); @@ -194,7 +189,9 @@ public BigDecimal getTotalShareQuantityBySymbol(final String symbol) { if (symbol == null) { return BigDecimal.ZERO; } - Share share = shares.get(symbol.toUpperCase()); - return share != null ? share.getQuantity() : BigDecimal.ZERO; + return shares.stream() + .filter(s -> s.getStock().getSymbol().equalsIgnoreCase(symbol)) + .map(Share::getQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); } } diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java index 9b5aa5c..4fd2020 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java @@ -102,7 +102,6 @@ public void handleContextUpdate(final Exchange criticalExchange, final Player ac this.playerNetWorthHistory.addAll(this.player.getNetWorthHistory()); } else { this.playerNetWorthHistory.add(this.player.getStartingMoney()); - this.playerNetWorthHistory.add(this.player.getNetWorth()); } getViewElement().setWeek(this.exchange.getWeek());