Skip to content

93 finish dashboard page #102

Merged
merged 13 commits into from
May 19, 2026
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
import edu.ntnu.idi.idatt2003.g40.mappe.model.Share;
import edu.ntnu.idi.idatt2003.g40.mappe.model.Stock;
import edu.ntnu.idi.idatt2003.g40.mappe.model.Transaction;
import edu.ntnu.idi.idatt2003.g40.mappe.service.PurchaseCalculator;
import edu.ntnu.idi.idatt2003.g40.mappe.service.SaleCalculator;
import edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionCalculator;
import edu.ntnu.idi.idatt2003.g40.mappe.service.*;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventData;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventPublisher;
Expand Down Expand Up @@ -199,11 +197,59 @@ public Transaction sell(final Share share, final Player player)
return sale;
}

/**
* Method called when a player sells share.
*
* @param amount the amount of "shares" to sell.
* @param stockSymbol the stock to sell shares in.
* @param player the player buying stock.
*
* @return Transaction representing the transaction.
*
* @throws IllegalArgumentException if any parameter is null, or if player does not have enough shares.
* */
public List<Transaction> sell(BigDecimal amount, final String stockSymbol, final Player player)
throws IllegalArgumentException {
if (amount == null || player == null || !Validator.NOT_EMPTY.isValid(stockSymbol)) {
throw new IllegalArgumentException("Invalid sell!");
} else {

List<Share> sharesOfStock = player.getPortfolio().getShares().stream()
.filter(s -> s.getStock().getSymbol().equals(stockSymbol))
.toList();

BigDecimal totalOwned = player.getPortfolio().getTotalSharesBySymbol(stockSymbol);

if (amount.compareTo(totalOwned) > 0) {
amount = totalOwned;
}
ArrayList<Transaction> transactions = new ArrayList<>();
BigDecimal remainingToSell = amount;

for (Share share : sharesOfStock) {
if (remainingToSell.compareTo(BigDecimal.ZERO) <= 0) {
break;
}

BigDecimal shareQty = share.getQuantity();

if (shareQty.compareTo(remainingToSell) <= 0) {
remainingToSell = remainingToSell.subtract(shareQty);
transactions.add(sell(share, player));
} else {
Share newShare = player.getPortfolio().splitShare(share, remainingToSell);
remainingToSell = BigDecimal.ZERO;
transactions.add(sell(newShare, player));
}
}
return transactions;
}
}

/**
* Method for advancing time, increasing the amount of weeks.
* */
public void advance() {
week.set(week.get() + 1);
for (Stock stock : stockMap.values()) {
BigDecimal currentPrice = stock.getSalesPrice();

Expand All @@ -213,6 +259,7 @@ public void advance() {
BigDecimal newPrice = currentPrice.multiply(factor);
stock.addNewSalesPrice(newPrice);
}
week.set(week.get() + 1);
}

/**
Expand Down
33 changes: 25 additions & 8 deletions src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/model/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public final class Player {
* */
private final FloatProperty networthAsFloatProp = new SimpleFloatProperty(0);

/**
* Current money of player as a listenable {@link FloatProperty} object.
* */
private final FloatProperty moneyAsFloatProp = new SimpleFloatProperty(0);

/**
* The players' portfolio, holding their shares.
* */
Expand Down Expand Up @@ -68,6 +73,7 @@ public Player(final String name, final BigDecimal startingMoney) throws IllegalA
this.startingMoney = startingMoney;
this.money = this.startingMoney;
this.networthAsFloatProp.setValue(this.startingMoney);
this.moneyAsFloatProp.setValue(this.startingMoney);
this.portfolio = new Portfolio();
this.transactionArchive = new TransactionArchive();
}
Expand Down Expand Up @@ -115,7 +121,6 @@ public void addMoney(final BigDecimal amount) {
*/
public void withdrawMoney(final BigDecimal amount) {
money = money.subtract(amount);

}

/**
Expand Down Expand Up @@ -155,6 +160,15 @@ public FloatProperty getNetWorthAsFloatProperty() {
return networthAsFloatProp;
}

/**
* Get money as a {@link FloatProperty} object, allowing listening for changes.
*
* @return FloatProperty.
* */
public FloatProperty getMoneyAsFloatProperty() {
return moneyAsFloatProp;
}

/**
* Getter method for players' current status.
*
Expand All @@ -172,17 +186,20 @@ public PlayerStatus getStatus() {
* @param transaction the transaction to handle.
* */
public void handleTransaction(final Transaction transaction) {
if (money.floatValue() > transaction.getCalculator().calculateTotal().floatValue()) {
transactionArchive.add(transaction);
if (transaction instanceof Purchase purchase) {
if (transaction instanceof Purchase purchase) {
if (money.floatValue() > transaction.getCalculator().calculateTotal().floatValue()) {
withdrawMoney(purchase.getCalculator().calculateTotal());
portfolio.addShare(purchase.getShare());
} else if (transaction instanceof Sale sale) {
addMoney(sale.getCalculator().calculateTotal());
portfolio.removeShare(sale.getShare());
transactionArchive.add(transaction);
transaction.commit(this);
}
networthAsFloatProp.setValue(getNetWorth().floatValue());
} else if (transaction instanceof Sale sale) {
addMoney(sale.getCalculator().calculateTotal());
portfolio.removeShare(sale.getShare());
transactionArchive.add(transaction);
transaction.commit(this);
}
networthAsFloatProp.setValue(getNetWorth().floatValue());
moneyAsFloatProp.setValue(money);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,41 @@ public BigDecimal getNetWorth() {
}
return netWorth;
}

/**
* Helper method to get total amount of shares owned in a specific stock.
*
* @param symbol the symbol of the stock to check for shares.
* */
public BigDecimal getTotalSharesBySymbol(final String symbol) {
return shares.stream()
.filter(s -> s.getStock().getSymbol().equals(symbol))
.map(Share::getQuantity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}

/**
* "Splits" a share in two pieces based on an amount.
*
* @param share the share to split.
* @param splitAmount the amount to split by.
*
* @return the split share from the original to the split amount.
*
* @throws IllegalArgumentException if share or split amount is invalid.
* */
public Share splitShare(final Share share, final BigDecimal splitAmount)
throws IllegalArgumentException {
if (!contains(share) || splitAmount.compareTo(share.getQuantity()) > 0) {
throw new IllegalArgumentException("Cannot split share!");
}
BigDecimal remainingAmount = share.getQuantity().subtract(splitAmount);

Share newShare1 = new Share(share.getStock(), splitAmount, share.getPurchasePrice());
Share newShare2 = new Share(share.getStock(), remainingAmount, share.getPurchasePrice());
removeShare(share);
addShare(newShare1);
addShare(newShare2);
return newShare1;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.dashboard;

/**
* Enum representing actions done in an instance of {@link DashBoardView}.
* */
public enum DashBoardActions {
/**
* Buying shares.
* */
BUY_SHARES,

/**
* Selling shares.
* */
SELL_SHARES,
SELECT_STOCK;

/**
* Decreasing quantity of shares to buy/sell by five.
* */
DECREASE_5,

/**
* Decreasing quantity of shares to buy/sell by one.
* */
DECREASE_1,

/**
* Increasing quantity of shares to buy/sell by one.
* */
INCREASE_1,

/**
* Increasing quantity of shares to buy/sell by five.
* */
INCREASE_5;
}
Loading