Skip to content

stats side #109

Merged
merged 1 commit into from
May 19, 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
74 changes: 42 additions & 32 deletions src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.dashboard.DashBoardView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.market.MarketController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.market.MarketView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats.StatsController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats.StatsView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.topbar.TopBarView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.transactions.TransactionsController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.transactions.TransactionsView;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
Expand All @@ -38,10 +39,14 @@
/**
* Main class.
*
* <p>Extends {@link Application}</p>
* <p>
* Extends {@link Application}
* </p>
*
* <p>Initializes the application through the javafx framework.</p>
* */
* <p>
* Initializes the application through the javafx framework.
* </p>
*/
public class Main extends Application {

static void main(String[] args) {
Expand All @@ -50,12 +55,12 @@ static void main(String[] args) {

/**
* {@inheritDoc}
* */
*/
@Override
public void start(final Stage stage) throws Exception {
Scene scene = new Scene(new Pane());
scene.getStylesheets()
.add(Objects.requireNonNull(getClass().getResource("/styles.css")).toExternalForm());
.add(Objects.requireNonNull(getClass().getResource("/styles.css")).toExternalForm());
Font.loadFont(getClass().getResourceAsStream("/Fonts/Aptos.ttf"), 16);
stage.setScene(scene);
stage.setWidth(ConfigValues.VIEWPORT_WIDTH.getValue());
Expand Down Expand Up @@ -85,7 +90,6 @@ public void start(final Stage stage) throws Exception {
SaveGameService saveGameService = new SaveGameService();
playGameView.setSaves(saveGameService.loadSaves());


// Settings
SettingsView settingsView = new SettingsView();
new SettingsController(settingsView, eventManager);
Expand All @@ -102,40 +106,46 @@ public void start(final Stage stage) throws Exception {
TopBarView topBarView2 = new TopBarView();
new TopBarController(topBarView2, eventManager);

// Stats page (dashboard, default center-view in-game)
// Dashboard (default center-view in-game - første siden du ser)
DashBoardView dashBoardView = new DashBoardView();
new DashBoardController(dashBoardView,
eventManager,
player,
exchange,
stocksInFile);
eventManager,
player,
exchange,
stocksInFile);

// Stats page (Stats-knappen i topbaren tar deg hit)
StatsView statsView = new StatsView();
new StatsController(statsView, eventManager, player, exchange);

// Market page (vises i samme InGameView, byttes til via Market-knappen)
// Market page (Market-knappen tar deg hit)
MarketView marketView = new MarketView();
new MarketController(marketView,
eventManager,
player,
exchange,
stocksInFile);

TransactionsView transactionsView = new TransactionsView();
TransactionsController transactionsController = new TransactionsController(
transactionsView,
eventManager,
player.getTransactionArchive());
eventManager,
player,
exchange,
stocksInFile);

// In-game (Change "topBarView" to "topBarView2" if no summary section).
// Dashboard er default center-view.
InGameView inGameView = new InGameView(topBarView, dashBoardView.getRootPane());

// Wire top bar buttons til å bytte mellom dashboard og market.
// Transactions-widgeten finnes ikke enda - bruker dashboardet som
// placeholder slik at TRANSACTIONS-knappen ikke krasjer. Bytt ut når
// den faktiske transactions-widgeten er på plass.
Node transactionsCenter = dashBoardView.getRootPane();
Runnable onTransactionUpdate = () -> {
};

// Wire top bar buttons til å bytte mellom dashboard / stats / market /
// transactions. Stats-knappen tar deg til stats-siden.
topBarController.setMarketIntegration(
inGameView::changeCenterView,
dashBoardView.getRootPane(),
marketView.getRootPane(),
transactionsView.getRootPane(),
transactionsController::refresh
);
inGameView::changeCenterView,
dashBoardView.getRootPane(),
marketView.getRootPane(),
statsView.getRootPane(),
transactionsCenter,
onTransactionUpdate);

// Register all views
viewManager.addView(mainMenuView);
Expand All @@ -146,4 +156,4 @@ public void start(final Stage stage) throws Exception {

stage.show();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
* Immutable data carrier for a single holding shown in {@link StatsView}.
*
* <p>Each instance represents an aggregated position in a single stock:
* the total number of shares owned, the weighted average purchase price,
* and the current market price. Derived values (value, cost, P&L) are
* computed on demand.</p>
* */
public final class HoldingData {

/** The stock ticker symbol. */
private final String ticker;

/** Total number of shares owned of this ticker. */
private final BigDecimal shares;

/** Weighted average purchase price per share. */
private final BigDecimal avgPrice;

/** Current market price per share. */
private final BigDecimal currentPrice;

/**
* Creates a new holding data row.
*
* @param ticker the stock ticker symbol.
* @param shares total number of shares owned.
* @param avgPrice weighted average purchase price per share.
* @param currentPrice current market price per share.
*
* @throws IllegalArgumentException if any argument is null.
* */
public HoldingData(final String ticker,
final BigDecimal shares,
final BigDecimal avgPrice,
final BigDecimal currentPrice) throws IllegalArgumentException {
if (ticker == null || shares == null || avgPrice == null || currentPrice == null) {
throw new IllegalArgumentException("Invalid holding data!");
}
this.ticker = ticker;
this.shares = shares;
this.avgPrice = avgPrice;
this.currentPrice = currentPrice;
}

/** @return the ticker symbol. */
public String getTicker() {
return ticker;
}

/** @return total shares owned. */
public BigDecimal getShares() {
return shares;
}

/** @return weighted average purchase price. */
public BigDecimal getAvgPrice() {
return avgPrice;
}

/** @return current market price. */
public BigDecimal getCurrentPrice() {
return currentPrice;
}

/** @return current market value of this position (shares * currentPrice). */
public BigDecimal getValue() {
return shares.multiply(currentPrice);
}

/** @return total cost paid for this position (shares * avgPrice). */
public BigDecimal getCost() {
return shares.multiply(avgPrice);
}

/** @return absolute profit and loss (value - cost). */
public BigDecimal getPnl() {
return getValue().subtract(getCost());
}

/** @return profit and loss as a percentage of cost. */
public double getPnlPct() {
BigDecimal cost = getCost();
if (cost.signum() == 0) {
return 0.0;
}
return getPnl().divide(cost, 6, RoundingMode.HALF_UP).doubleValue() * 100.0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.stats;

/**
* Enum representing all interactable actions in {@link StatsView}.
*
* <p>The stats widget is mostly an informational dashboard, so it currently
* has no top-level buttons of its own. {@code SELECT_HOLDING} is reserved
* for future use when individual holdings rows become clickable.</p>
* */
public enum StatsActions {
/** Reserved for future holding-row click handling. */
SELECT_HOLDING;
}
Loading