Skip to content

Commit

Permalink
Merge pull request #114 from einaskoi/per/bugs
Browse files Browse the repository at this point in the history
fix not insufficient warning popup, receipt not refreshing & font cli…
  • Loading branch information
einaskoi authored May 15, 2026
2 parents c8f6c1f + 20f398c commit 7e6e604
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public final class StockAppController implements AppController {
/** Called when the player clicks Trade during a weekend. */
private Runnable onMarketClosed;

private Runnable onInsufficientFunds;

/**
* Constructs a new StockAppController.
*
Expand Down Expand Up @@ -199,6 +201,15 @@ public void setOnMarketClosed(final Runnable callback) {
this.onMarketClosed = callback;
}

/**
* Registers the callback invoked when the player has insufficient funds.
*
* @param callback the action to run (typically shows an insufficient-funds warning)
*/
public void setOnInsufficientFunds(final Runnable callback) {
this.onInsufficientFunds = callback;
}

/**
* Handles the trade button action based on the spinner value.
*/
Expand All @@ -218,7 +229,11 @@ private void handleTransaction() {
}
BigDecimal quantity = new BigDecimal(Math.abs(value));
if (value > 0) {
handleBuy(currentStock, quantity);
try{
handleBuy(currentStock, quantity);
} catch (Exception e) {
onInsufficientFunds.run();
}
} else {
handleSell(currentStock, quantity);
}
Expand All @@ -230,16 +245,12 @@ private void handleTransaction() {
* @param stock the stock to buy
* @param quantity the quantity to buy
*/
private void handleBuy(final Stock stock, final BigDecimal quantity) {
try {
Transaction transaction = marketController.getExchange()
.buy(stock.getSymbol(), quantity, player);
if (transaction != null) {
transaction.commit(player);
player.getPortfolio().addShare(transaction.getShare());
}
} catch (Exception exception) {
exception.printStackTrace();
private void handleBuy(final Stock stock, final BigDecimal quantity) throws Exception {
Transaction transaction = marketController.getExchange()
.buy(stock.getSymbol(), quantity);
if (transaction != null) {
transaction.commit(player);
player.getPortfolio().addShare(transaction.getShare());
}
}

Expand All @@ -253,17 +264,22 @@ private void handleSell(final Stock stock, final BigDecimal quantity) {
player.getPortfolio().getShares().stream()
.filter(share -> share.getStock().getSymbol().equals(stock.getSymbol()))
.findFirst()
.ifPresent(existingShare -> {
if (existingShare.getQuantity().compareTo(quantity) < 0) {
return;
}
Transaction transaction = marketController.getExchange()
.sell(existingShare, quantity, player);
if (transaction != null) {
transaction.commit(player);
player.getPortfolio().removeShare(transaction.getShare());
}
});
.ifPresent(
existingShare -> {
if (existingShare.getQuantity().compareTo(quantity) < 0) {
return;
}
Transaction transaction =
marketController.getExchange().sell(existingShare, quantity, player);
if (transaction != null) {
try {
transaction.commit(player);
} catch (Exception e) {
System.out.println("Transaction failed");
}
player.getPortfolio().removeShare(transaction.getShare());
}
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void setGameState(GameState gameState) {
public void startGame() {
timer = new Timer(true);
final int delay = 0;
final int period = 10; //TODO: This has to be 1000 (1 second) on release
final int period = 1000; //TODO: This has to be 1000 (1 second) on release

timer.scheduleAtFixedRate(
new TimerTask() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public DesktopViewController(final Player player, final GameController gameContr
});

stockAppController.setOnMarketClosed(this::showMarketClosedWarning);
stockAppController.setOnInsufficientFunds(this::showInsufficientFundsWarning);

this.desktopView = new DesktopView(this);
BorderPane root = desktopView.getRoot();
Expand Down Expand Up @@ -208,6 +209,16 @@ private void showMarketClosedWarning() {
showWarning();
}

private void showInsufficientFundsWarning() {
warningApp.configure(
"\uD83E\uDD7A",
"Insufficient Funds",
"You don't have enough cash to complete this purchase.",
"I'll be back");
warningApp.getPrimaryButton().setOnAction(event -> dismissWarning());
showWarning();
}

private void showWarning() {
warningApp.show();
desktopView.enterLayer(ModalLayer.WARNING);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,11 @@ public List<Stock> getAllStocks() {
*
* @param symbol the symbol of the stock to buy
* @param quantity the amount of stock to buy
* @param player the player performing the purchase
* @return a {@code Purchase} transaction
*/
public Transaction buy(
final String symbol,
final BigDecimal quantity,
final Player player
final BigDecimal quantity
) {
Stock stock = getStock(symbol);
BigDecimal purchasePrice = stock.getSalesPrice();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public void addMoney(final BigDecimal amount) {
* @param amount the amount to withdraw
* @throws InsufficientFunds if the player does not have enough money
*/
public void withdrawMoney(final BigDecimal amount) {
public void withdrawMoney(final BigDecimal amount) throws InsufficientFunds {
if (money.compareTo(amount) < 0) {
throw new InsufficientFunds("Not enough money to withdraw " + amount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public Purchase(final Share share, final int week) {
}

@Override
public void commit(final Player player) {
public void commit(final Player player) throws Exception {
setCommitted(true);
player.withdrawMoney(getCalculator().calculateTotal());
player.getTransactionArchive().add(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public boolean isCommitted() {
*
* @param player the player performing the transaction
*/
public abstract void commit(Player player);
public abstract void commit(Player player) throws Exception;

/**
* Sets the committed status of the transaction.
Expand Down
101 changes: 82 additions & 19 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/View/Apps/BankApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;

Expand All @@ -34,6 +35,9 @@ public class BankApp extends Popup {

private Consumer<Share> onShareSelected;

/**
* Constructs the Bank app popup.
*/
public BankApp() {
super(500, 550, 220, 100, App.BANK);

Expand All @@ -55,18 +59,40 @@ private void buildLayout() {
private VBox buildSummaryCard() {
Label title = new Label("Total Balance");
title.getStyleClass().add("bank-summary-title");
title.setMinWidth(Region.USE_PREF_SIZE);

netWorthLabel.getStyleClass().add("bank-summary-label-bold");
netWorthLabel.setMinWidth(Region.USE_PREF_SIZE);

VBox balanceBox = new VBox(5, title, netWorthLabel);
balanceBox.setAlignment(Pos.CENTER_LEFT);

cashLabel.getStyleClass().add("bank-summary-label-normal");
cashLabel.setMinWidth(Region.USE_PREF_SIZE);

investedLabel.getStyleClass().add("bank-summary-label-normal");
investedLabel.setMinWidth(Region.USE_PREF_SIZE);

totalReturnLabel.getStyleClass().add("bank-summary-label-normal");
totalReturnLabel.setMinWidth(Region.USE_PREF_SIZE);

GridPane grid = new GridPane();
grid.setHgap(40);
grid.setVgap(15);

ColumnConstraints c0 = new ColumnConstraints();
c0.setMinWidth(Region.USE_PREF_SIZE);
c0.setHgrow(Priority.ALWAYS);

ColumnConstraints c1 = new ColumnConstraints();
c1.setMinWidth(Region.USE_PREF_SIZE);
c1.setHgrow(Priority.ALWAYS);

ColumnConstraints c2 = new ColumnConstraints();
c2.setMinWidth(Region.USE_PREF_SIZE);
c2.setHgrow(Priority.ALWAYS);

grid.getColumnConstraints().addAll(c0, c1, c2);
grid.add(summaryItem("Cash Available", cashLabel), 0, 0);
grid.add(summaryItem("Invested", investedLabel), 1, 0);
grid.add(summaryItem("Total Return", totalReturnLabel), 2, 0);
Expand All @@ -79,6 +105,7 @@ private VBox buildSummaryCard() {
private VBox buildPortfolioSection() {
Label title = new Label("Investment Portfolio");
title.getStyleClass().add("bank-portfolio-title");
title.setMinWidth(Region.USE_PREF_SIZE);

portfolioList.setPrefHeight(300);
portfolioList.setMinHeight(200);
Expand All @@ -93,6 +120,7 @@ private VBox buildPortfolioSection() {
private VBox summaryItem(String title, Label valueLabel) {
Label titleLabel = new Label(title);
titleLabel.getStyleClass().add("bank-summary-item-title");
titleLabel.setMinWidth(Region.USE_PREF_SIZE);

VBox box = new VBox(5, titleLabel, valueLabel);
box.setAlignment(Pos.CENTER_LEFT);
Expand All @@ -105,7 +133,7 @@ private VBox summaryItem(String title, Label valueLabel) {
* @param netWorth total net worth (cash + portfolio value)
* @param cash uninvested cash available
* @param invested current market value of shares held
* @param startingMoney initial balance used as the growth baseline
* @param startingMoney initial balance used as the growth baseline
*/
public void updateStatus(double netWorth, double cash, double invested, double startingMoney) {
Platform.runLater(() -> {
Expand All @@ -120,10 +148,20 @@ public void updateStatus(double netWorth, double cash, double invested, double s
});
}

/**
* Returns the portfolio list view.
*
* @return the portfolio list
*/
public ListView<Share> getPortfolioList() {
return portfolioList;
}

/**
* Sets the callback invoked when the user clicks a share row.
*
* @param onShareSelected the callback to invoke with the selected share
*/
public void setOnShareSelected(Consumer<Share> onShareSelected) {
this.onShareSelected = onShareSelected;
}
Expand All @@ -147,22 +185,19 @@ private static String formatUsd(double amount) {
*/
private class ShareCell extends ListCell<Share> {

private final GridPane grid = new GridPane();
private static final double COL_SYMBOL_MIN = 120;
private static final double COL_QUANTITY_MIN = 100;
private static final double COL_PRICE_MIN = 90;
private static final double COL_GAIN_MIN = 90;

// Column 0
private final Label symbolLabel = new Label();
private final GridPane grid = new GridPane();
private final Label symbolLabel = new Label();
private final Label companyLabel = new Label();

// Column 1
private final Label quantityLabel = new Label();
private final Label avgPriceLabel = new Label();

// Column 2
private final Label currentPriceLabel = new Label();
private final Label marketValueLabel = new Label();

// Column 3
private final Label gainLabel = new Label();
private final Label marketValueLabel = new Label();
private final Label gainLabel = new Label();
private final Label gainPctLabel = new Label();

ShareCell() {
Expand All @@ -180,30 +215,58 @@ private class ShareCell extends ListCell<Share> {
}

private void configureColumns() {
for (int pct : new int[]{30, 20, 25, 25}) {
ColumnConstraints col = new ColumnConstraints();
col.setPercentWidth(pct);
grid.getColumnConstraints().add(col);
}
ColumnConstraints colSymbol = new ColumnConstraints();
colSymbol.setMinWidth(COL_SYMBOL_MIN);
colSymbol.setHgrow(Priority.ALWAYS);

ColumnConstraints colQuantity = new ColumnConstraints();
colQuantity.setMinWidth(COL_QUANTITY_MIN);
colQuantity.setHgrow(Priority.ALWAYS);

ColumnConstraints colPrice = new ColumnConstraints();
colPrice.setMinWidth(COL_PRICE_MIN);
colPrice.setHgrow(Priority.NEVER);

ColumnConstraints colGain = new ColumnConstraints();
colGain.setMinWidth(COL_GAIN_MIN);
colGain.setHgrow(Priority.NEVER);

grid.getColumnConstraints().addAll(colSymbol, colQuantity, colPrice, colGain);
}

private void addCellContent() {
symbolLabel.getStyleClass().add("stock-symbol");
symbolLabel.setMinWidth(Region.USE_PREF_SIZE);

companyLabel.getStyleClass().add("stock-company");
companyLabel.setMinWidth(Region.USE_PREF_SIZE);

grid.add(new VBox(2, symbolLabel, companyLabel), 0, 0);

quantityLabel.getStyleClass().add("bank-share-quantity");
quantityLabel.setMinWidth(Region.USE_PREF_SIZE);

avgPriceLabel.getStyleClass().add("bank-share-avg-price");
avgPriceLabel.setMinWidth(Region.USE_PREF_SIZE);

grid.add(new VBox(2, quantityLabel, avgPriceLabel), 1, 0);

currentPriceLabel.getStyleClass().add("bank-share-current-price");
currentPriceLabel.setMinWidth(Region.USE_PREF_SIZE);

marketValueLabel.getStyleClass().add("bank-share-value");
marketValueLabel.setMinWidth(Region.USE_PREF_SIZE);

VBox valBox = new VBox(2, currentPriceLabel, marketValueLabel);
valBox.setAlignment(Pos.CENTER_RIGHT);
grid.add(valBox, 2, 0);

gainLabel.getStyleClass().add("bank-share-gain");
gainLabel.setMinWidth(Region.USE_PREF_SIZE);

gainPctLabel.getStyleClass().add("bank-share-gain");
gainPctLabel.setMinWidth(Region.USE_PREF_SIZE);

VBox gainBox = new VBox(2, gainLabel, gainPctLabel);
gainBox.setAlignment(Pos.CENTER_RIGHT);
grid.add(gainBox, 3, 0);
Expand Down Expand Up @@ -238,10 +301,10 @@ private void populateLabels(Share share) {
avgPriceLabel.setText("Avg: $" + String.format("%,.2f", purchasePrice));

currentPriceLabel.setText("$" + String.format("%,.2f", currentPrice));
marketValueLabel.setText("$" + String.format("%,.2f", marketValue));
marketValueLabel.setText("$" + String.format("%,.2f", marketValue));

String sign = gain.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "";
gainLabel.setText(sign + "$" + String.format("%,.2f", gain));
gainLabel.setText(sign + "$" + String.format("%,.2f", gain));
gainPctLabel.setText(sign + String.format("%.2f", gainPercent) + "%");

applyGainStyle(gain.compareTo(BigDecimal.ZERO) >= 0);
Expand Down
Loading

0 comments on commit 7e6e604

Please sign in to comment.