Skip to content

Commit

Permalink
feat: Implement Finish barebone MVC to finish the game.
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelSapula committed May 24, 2026
1 parent b4a8c63 commit a4a82c9
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/main/java/edu/ntnu/idi/idatt/view/SceneFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import edu.ntnu.idi.idatt.model.market.Stock;
import edu.ntnu.idi.idatt.session.UserSession;
import edu.ntnu.idi.idatt.storage.SessionManager;
import edu.ntnu.idi.idatt.view.entry.StartController;
import edu.ntnu.idi.idatt.view.entry.StartModel;
import edu.ntnu.idi.idatt.view.entry.StartView;
Expand All @@ -14,6 +15,9 @@
import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeController;
import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeModel;
import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeView;
import edu.ntnu.idi.idatt.view.primary.finish.FinishController;
import edu.ntnu.idi.idatt.view.primary.finish.FinishModel;
import edu.ntnu.idi.idatt.view.primary.finish.FinishView;
import edu.ntnu.idi.idatt.view.primary.stock.StockController;
import edu.ntnu.idi.idatt.view.primary.stock.StockModel;
import edu.ntnu.idi.idatt.view.primary.stock.StockView;
Expand Down Expand Up @@ -148,4 +152,16 @@ public static Parent createNewspaperView(String symbol) {
return view.getInstance();
}

public static Parent createFinishView() {

FinishModel model = new FinishModel();
FinishView view = new FinishView();
FinishController controller = new FinishController(model);

view.setController(controller);

SessionManager.removeSession();
return view.getInstance();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package edu.ntnu.idi.idatt.view.primary.finish;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;

import edu.ntnu.idi.idatt.model.portfolio.Share;
import edu.ntnu.idi.idatt.session.UserSession;
import edu.ntnu.idi.idatt.view.components.AbstractController;
import edu.ntnu.idi.idatt.view.util.CssUtils;
import javafx.scene.Parent;

public class FinishController extends AbstractController<FinishModel> {

private UserSession session = UserSession.getInstance();

public FinishController(FinishModel model) {
super(model);
makeFinishedGameState();
}

public void makeFinishedGameState() {
// Sell all shares

// Copy shares (Avoid ConcurrentModificationException)
ArrayList<Share> holdings = new ArrayList<>(session.getPlayer().getPortfolio().getShares());

// Sell
holdings.forEach(share -> session.getExchange().sell(share, session.getPlayer()));

// Update gamestate
session.updateGameState();

}

public String getWeek() {
return String.format("Week: %d", session.getExchange().getWeek());
}

public String getTransactionAmount() {
return String.format("Transactions made: %d",
session.getPlayer().getTransactionArchive().getTransactions().size());
}

public String getPlayerStatus() {
return String.format("Player status: %s",
session.getPlayer().getStatus());
}

public String getPlayerName() {
return String.format("Player name: %s", session.getPlayer().getName());
}

public String getTotalNetWorth() {
return String.format("Total net worth: %.2f $",
session.getPlayer().getMoney());
}

private BigDecimal calculateProfits() {
BigDecimal profit = session.getPlayer().getMoney().subtract(
session.getPlayer().getStartingMoney());
return profit;
}

private BigDecimal calculateROI() {
BigDecimal profit = session.getPlayer().getMoney().subtract(
session.getPlayer().getStartingMoney());
BigDecimal profitPercent = profit.divide(session.getPlayer().getStartingMoney()).setScale(2, RoundingMode.HALF_UP);

BigDecimal returnOfInvestement = profitPercent.multiply(new BigDecimal("100"));

return returnOfInvestement;
}

public String getProfits() {
return String.format("Total profits: %.2f $",
calculateProfits());
}

public String getROI() {
return String.format("Return of investement: %.2f %%", calculateROI());
}

public void setProfitsColor(Parent profitsLabel) {
CssUtils.apply(profitsLabel, CssUtils.generateValueColors(calculateProfits()));
}

public void setRoiColor(Parent roiLabel) {
CssUtils.apply(roiLabel, CssUtils.generateValueColors(calculateROI()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package edu.ntnu.idi.idatt.view.primary.finish;

import java.math.BigDecimal;

import edu.ntnu.idi.idatt.view.components.Model;
import javafx.beans.property.SimpleObjectProperty;

public class FinishModel implements Model {

private final SimpleObjectProperty<BigDecimal> profitProperty = new SimpleObjectProperty<>();
private final SimpleObjectProperty<BigDecimal> roiProperty = new SimpleObjectProperty<>();

public SimpleObjectProperty<BigDecimal> getProfitProperty() {
return profitProperty;
}

public SimpleObjectProperty<BigDecimal> getRoiProperty() {
return roiProperty;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package edu.ntnu.idi.idatt.view.primary.finish;

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

import edu.ntnu.idi.idatt.view.SceneFactory;
import edu.ntnu.idi.idatt.view.SceneManager;
import edu.ntnu.idi.idatt.view.components.AbstractView;
import edu.ntnu.idi.idatt.view.components.ui.UICompositor;
import edu.ntnu.idi.idatt.view.util.CssUtils;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

public class FinishView extends AbstractView<StackPane> {

public FinishView() {
StackPane root = new StackPane();
super(root);
root.getStyleClass().add("dark");
}

Label playerName;
Label playerStatus;
Label weeksPassed;
Label transactionsAmount;
Label totalNetWorth;
Label totalProfits;
Label returnOfInvestement;

Button newGame;
Button exit;

@Override
public Parent createContent() {

Label title = new Label("Finished game! - Summary");
CssUtils.apply(title, CssUtils.BIG_TEXT_32);

playerName = new Label();
playerStatus = new Label();
weeksPassed = new Label();
transactionsAmount = new Label();
totalNetWorth = new Label();
totalProfits = new Label();
returnOfInvestement = new Label();

List<Label> labels = List.of(playerName, playerStatus, new Label(" "), weeksPassed, transactionsAmount,
totalNetWorth, totalProfits,
returnOfInvestement);

labels.forEach(l -> CssUtils.apply(l, CssUtils.MED_TEXT_16));

newGame = new Button("New game..");
exit = new Button("Exit..");

newGame.getStyleClass().add("button");
exit.getStyleClass().add("button");

UICompositor.Builder finishUIBuilder = new UICompositor.Builder()
.parent(new VBox())
.growWithAlignment(Pos.CENTER)
.addContent(title);

labels.forEach(l -> finishUIBuilder.addContent(l));

finishUIBuilder
.wrap(new HBox(10))
.growWithAlignment(Pos.CENTER)
.addAllContent(newGame, exit)
.unwrap();

return finishUIBuilder.build().makeUI();

}

public void setController(FinishController controller) {
playerName.setText(controller.getPlayerName());
playerStatus.setText(controller.getPlayerStatus());
weeksPassed.setText(controller.getWeek());
transactionsAmount.setText(controller.getTransactionAmount());
totalNetWorth.setText(controller.getTotalNetWorth());
totalProfits.setText(controller.getProfits());
returnOfInvestement.setText(controller.getROI());

controller.setProfitsColor(totalProfits);
controller.setRoiColor(returnOfInvestement);

newGame.setOnAction((e) -> SceneManager.switchTo(SceneFactory.createStartView()));
exit.setOnAction((e) -> Platform.exit());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import edu.ntnu.idi.idatt.model.transaction.Sale;
import edu.ntnu.idi.idatt.service.transaction.SaleCalculator;
import edu.ntnu.idi.idatt.session.UserSession;
import edu.ntnu.idi.idatt.view.SceneFactory;
import edu.ntnu.idi.idatt.view.SceneManager;
import edu.ntnu.idi.idatt.view.components.AbstractController;
import edu.ntnu.idi.idatt.view.components.elements.RecieptComponent;
import edu.ntnu.idi.idatt.view.components.elements.ShareComponent;
import edu.ntnu.idi.idatt.view.components.ui.UIAlert;
import edu.ntnu.idi.idatt.view.primary.finish.FinishView;
import edu.ntnu.idi.idatt.view.util.CssUtils;
import javafx.scene.effect.GaussianBlur;

Expand Down Expand Up @@ -87,6 +90,24 @@ public void showReciept(Sale sale) {
model.instanceChildren().add(reciept);
}

public void eventFinishGame() {

UIAlert askFinish = new UIAlert(
"Confirmation required.",
"Do you wish to finish the game?",
"This action is not reversable. A player summary " +
"of the playthrough will be shown, followed with account deletion.");

boolean status = askFinish.displayAwaitResponse();

if (!status) {
return;
}

SceneManager.switchTo(SceneFactory.createFinishView());

}

public void setupPlayerInfo() {
Portfolio portfolio = session.getPlayer().getPortfolio();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public void setPlayerInfoSectionModel(PlayerInfoModel model) {
public void setController(PortfolioController controller) {
searchQueryHandler = (query) -> controller.handleSearchQuery(query);
sortHandle = (sortAction) -> controller.sortSharesBy(sortAction);
playerInfoSection.finishButtonClicked(() -> controller.eventFinishGame());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import java.util.List;

import edu.ntnu.idi.idatt.view.components.elements.TextValueComponent;
import edu.ntnu.idi.idatt.view.components.primitives.ActionEventHandler;
import edu.ntnu.idi.idatt.view.components.ui.UICompositor;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
Expand All @@ -18,6 +20,7 @@ public class PlayerInfoSection extends VBox {
TextValueComponent netWorthTotalChange = new TextValueComponent("Total portfolio net worth change: ");
Label playerStatus = new Label();
Label totalSharesOwned = new Label();
Button finishGameButton;

public PlayerInfoSection() {

Expand All @@ -26,6 +29,9 @@ public PlayerInfoSection() {
List<Label> labels = List.of(netWorth, playerStatus, totalSharesOwned);
labels.forEach(l -> l.getStyleClass().add("portfolio-box-text"));

finishGameButton = new Button("Finish game");
finishGameButton.getStyleClass().add("button");

new UICompositor.Builder()
.parent(this)
.properties((parent) -> {
Expand All @@ -45,7 +51,7 @@ public PlayerInfoSection() {
.filler()
.wrap(new VBox())
.growWithAlignment(Pos.BOTTOM_CENTER)
.addAllContent(playerStatus, totalSharesOwned)
.addAllContent(playerStatus, totalSharesOwned, finishGameButton)
.unwrap()
.unwrap()
.build();
Expand All @@ -72,4 +78,8 @@ public Label getTotalSharesOwned() {
return totalSharesOwned;
}

public void finishButtonClicked(ActionEventHandler handler) {
finishGameButton.setOnAction((e) -> handler.handle());
}

}

0 comments on commit a4a82c9

Please sign in to comment.