Skip to content

26 sale page #35

Merged
merged 7 commits into from
May 11, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion millions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>25.0.2</version>
<version>25.0.3</version>
</dependency>
</dependencies>

Expand Down
3 changes: 3 additions & 0 deletions millions/src/main/java/no/ntnu/gruppe53/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ public void start(Stage stage) {
ViewController vm = new ViewController(stage);

StartView startView = new StartView(vm);

new StartViewController(startView, vm);


vm.addView("start", startView);

vm.switchView("start");

stage.setTitle("Millions - the Stock Game");
Expand Down
1 change: 1 addition & 0 deletions millions/src/main/java/no/ntnu/gruppe53/FileHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
public class FileHandler {


/**
* Writes a list of {@link Stock}s to a CSV file in UTF-8 encoding.
*
Expand Down
101 changes: 101 additions & 0 deletions millions/src/main/java/no/ntnu/gruppe53/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package no.ntnu.gruppe53.controller;

import java.math.BigDecimal;
import java.util.List;

import no.ntnu.gruppe53.Exchange;
import no.ntnu.gruppe53.FileHandler;
import no.ntnu.gruppe53.Player;
import no.ntnu.gruppe53.Share;
import no.ntnu.gruppe53.Stock;
import no.ntnu.gruppe53.views.PortfolioView;
import no.ntnu.gruppe53.views.PurchaseView;

public class GameController {
private final ViewController vm;
private final FileHandler fileHandler = new FileHandler();

private Player player;
private Exchange exchange;
private List<Stock> stocks;
private PurchaseView purchaseView;
private PortfolioView portfolioView;

public GameController(ViewController vm) {
this.vm = vm;
}

public void startNewGame() {
player = new Player("Player 1", new BigDecimal("100000"));
stocks = fileHandler.readStocksFromFile("src/main/resources", "sp500.csv");
exchange = new Exchange("Millions Exchange", stocks);

purchaseView = new PurchaseView();
purchaseView.setPlayer(player);
purchaseView.setExchange(exchange);
purchaseView.setPurchaseHandler(this::purchaseStock);

portfolioView = new PortfolioView();
portfolioView.setPlayer(player);

purchaseView.setShowPortfolioHandler(this::showPortfolio);
portfolioView.setShowMarketHandler(this::showPurchaseView);
portfolioView.setSellHandler(this::sellShare);

vm.addView("purchase", purchaseView);
vm.addView("portfolio", portfolioView);

vm.switchView("purchase");
}

private void purchaseStock(String symbol, int quantity) {
if (exchange == null || player == null || symbol == null || quantity <= 0) {
return;
}

try {
exchange.buy(symbol, BigDecimal.valueOf(quantity), player);
purchaseView.setPlayer(player);
purchaseView.refreshStocks();
portfolioView.setPlayer(player);
} catch (RuntimeException ex) {
System.out.println("Purchase failed: " + ex.getMessage());
}
}

private void sellShare(Share share, int quantity) {
if (exchange == null || player == null || share == null || quantity <= 0) {
return;
}

try {
Share shareToSell = new Share(
share.getStock(),
BigDecimal.valueOf(quantity),
share.getPurchasePrice()
);

exchange.sell(shareToSell, player);
purchaseView.setPlayer(player);
purchaseView.refreshStocks();
portfolioView.setPlayer(player);
} catch (RuntimeException ex) {
System.out.println("Sell failed: " + ex.getMessage());
}
}

public void showPortfolio() {
if (portfolioView != null) {
portfolioView.setPlayer(player);
vm.switchView("portfolio");
}
}

public void showPurchaseView() {
if (purchaseView != null) {
purchaseView.setPlayer(player);
purchaseView.refreshStocks();
vm.switchView("purchase");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public class StartViewController {
public StartViewController(StartView view, ViewController vm) {

view.setOnNewGame(() -> {
System.out.println("Start new game");
GameController gameController = new GameController(vm);
gameController.startNewGame();

});

view.setOnQuit(Platform::exit);
Expand Down
138 changes: 138 additions & 0 deletions millions/src/main/java/no/ntnu/gruppe53/views/PortfolioView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package no.ntnu.gruppe53.views;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import no.ntnu.gruppe53.Player;
import no.ntnu.gruppe53.Share;

public class PortfolioView extends VBox {
private final Label titleLabel;
private final Label playerNameLabel;
private final Label netWorthLabel;
private final ListView<Share> portfolioListView;
private final Button marketButton;
private final Button portfolioButton;
private final Spinner<Integer> quantitySpinner;
private final Button sellButton;

private Player player;
private BiConsumer<Share, Integer> sellHandler;
private Runnable showMarketHandler;

public PortfolioView() {
setSpacing(12);
setPadding(new Insets(16));

HBox navigationBar = new HBox(10);
marketButton = new Button("Market");
portfolioButton = new Button("Portfolio");
navigationBar.getChildren().addAll(marketButton, portfolioButton);

titleLabel = new Label("Portfolio");
titleLabel.setStyle("-fx-font-size: 20px; -fx-font-weight: bold;");

playerNameLabel = new Label("Player: -");
netWorthLabel = new Label("Net worth: $0.00");

portfolioListView = new ListView<>();
portfolioListView.setPrefHeight(300);
portfolioListView.setCellFactory(list -> new javafx.scene.control.ListCell<>() {
@Override
protected void updateItem(Share item, boolean empty) {
super.updateItem(item, empty);
setText(empty || item == null ? null : formatShare(item));
}
});

HBox sellBar = new HBox(10);
Label quantityLabel = new Label("Quantity:");
quantitySpinner = new Spinner<>();
quantitySpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 1_000_000, 1));
quantitySpinner.setEditable(true);

sellButton = new Button("Sell");
sellBar.getChildren().addAll(quantityLabel, quantitySpinner, sellButton);

marketButton.setOnAction(event -> {
if (showMarketHandler != null) {
showMarketHandler.run();
}
});



sellButton.setOnAction(event -> {
if (sellHandler == null) {
return;
}

Share selectedShare = portfolioListView.getSelectionModel().getSelectedItem();
if (selectedShare == null) {
return;
}

int quantity = quantitySpinner.getValue();
sellHandler.accept(selectedShare, quantity);
});

getChildren().addAll(
navigationBar,
titleLabel,
playerNameLabel,
netWorthLabel,
portfolioListView,
sellBar
);
}

public void setShowMarketHandler(Runnable showMarketHandler) {
this.showMarketHandler = showMarketHandler;
}

public void setSellHandler(BiConsumer<Share, Integer> sellHandler) {
this.sellHandler = sellHandler;
}

public void setPlayer(Player player) {
this.player = player;
refresh();
}

public void refresh() {
if (player == null) {
playerNameLabel.setText("Player: -");
netWorthLabel.setText("Net worth: $0.00");
portfolioListView.getItems().clear();
return;
}

playerNameLabel.setText("Player: " + player.getName());
netWorthLabel.setText("Net worth: $" + formatMoney(player.getNetWorth()));
portfolioListView.getItems().setAll(player.getPortfolio().getShares());
}

private String formatShare(Share share) {
return share.getStock().getSymbol()
+ " - "
+ share.getStock().getCompany()
+ " | Qty: "
+ share.getQuantity()
+ " | Buy price: $"
+ formatMoney(share.getPurchasePrice());
}

private String formatMoney(BigDecimal money) {
return money == null ? "0.00" : money.setScale(2, RoundingMode.HALF_UP).toPlainString();
}
}
Loading