Skip to content

Commit

Permalink
Merge branch '129-final-refactor' into 135-save-states-with-stock-fil…
Browse files Browse the repository at this point in the history
…e-integration
  • Loading branch information
tommyah committed May 26, 2026
2 parents 78eeba5 + a6e8218 commit c5d5164
Show file tree
Hide file tree
Showing 17 changed files with 876 additions and 498 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,7 @@ failsafe-reports/
coverage/
jacoco.exec

# ====== Stock data files ======= #
.txt
# ====== Stock data files and save files ======= #
*.txt
*.json
*.csv
190 changes: 92 additions & 98 deletions src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
import edu.ntnu.idi.idatt2003.g40.mappe.service.SaveGameService;
import edu.ntnu.idi.idatt2003.g40.mappe.service.StockFileManager;
import edu.ntnu.idi.idatt2003.g40.mappe.service.StockFileParser;
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.EventSubscriber;
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventType;
import edu.ntnu.idi.idatt2003.g40.mappe.utils.ConfigValues;
import edu.ntnu.idi.idatt2003.g40.mappe.utils.ThemeManager;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewManager;
Expand All @@ -24,18 +27,17 @@
import edu.ntnu.idi.idatt2003.g40.mappe.view.playgame.PlayGameView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.settings.SettingsController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.settings.SettingsView;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.WidgetEnum;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.dashboard.DashBoardController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.dashboard.DashBoardView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.financialsummary.SummaryView;
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.minigames.*;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.GameEngineController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.GameEngineView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.MiniGamesController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.MiniGamesView;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.games.ClickerGame;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.games.FindStockGame;
import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.games.TimeInputsGame;
Expand All @@ -45,6 +47,9 @@
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 java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
Expand All @@ -54,23 +59,31 @@
/**
* Main class.
*
* <p>
* Extends {@link Application}
* </p>
* <p>Extends {@link Application}</p>
*
* <p>
* Initializes the application through the javafx framework.
* </p>
*/
* <p>Launches the javafx thread and starts the program.</p>
* */
public class Main extends Application {

static void main(String[] args) {
/**
* Active {@link Exchange} object.
* */
private Exchange exchange;

/**
* Active {@link Player} object.
* */
private Player player;

/**
* Main method, launches the start javafx method.
*
* @param args standard Java parameter.
* */
public static void main(final String[] args) {
launch(args);
}

/**
* {@inheritDoc}
*/
@Override
public void start(final Stage stage) throws Exception {
Scene scene = new Scene(new Pane());
Expand All @@ -81,175 +94,156 @@ public void start(final Stage stage) throws Exception {
stage.setWidth(ConfigValues.VIEWPORT_WIDTH.getValue());
stage.setHeight(ConfigValues.VIEWPORT_HEIGHT.getValue());

// Register the scene with the theme manager so it can toggle dark/light.
ThemeManager.getInstance().registerScene(scene);

EventManager eventManager = new EventManager();
ViewManager viewManager = new ViewManager(stage, eventManager);

List<Stock> stocksInFile;
// Loads a default file in case of misreading (fallback)
StockFileManager fileManager = new StockFileManager("src/main/resources/sp500.csv");

StockFileParser fileParser = new StockFileParser();
stocksInFile = fileParser.getStocksFromStrings(fileManager.readFile());
List<Stock> stocksInFile = fileParser.getStocksFromStrings(fileManager.readFile());

Exchange exchange = new Exchange("Exchange", stocksInFile);
Player player = new Player("Player 1", new BigDecimal("10000"));
exchange = new Exchange("Exchange", stocksInFile);
player = new Player("Player 1", new BigDecimal("10000"));

// Bridges the save list to the live player + exchange. Subscribes
// to LOAD_SAVE; mutates state; publishes STATE_RESET for widgets.
GameStateLoader gameStateLoader = new GameStateLoader(
player, exchange, stocksInFile, eventManager);

// Main menu
MainMenuView mainMenuView = new MainMenuView();
new MainMenuController(mainMenuView, eventManager);

// Play game (mellom hovedmeny og spillet)
PlayGameView playGameView = new PlayGameView();
SaveGameService saveGameService = new SaveGameService();
PlayGameController playGameController =
new PlayGameController(playGameView, eventManager, saveGameService);
playGameController.refresh();


// Create game (mellom play-game og selve spillet)
CreateGameView createGameView = new CreateGameView();
CreateGameController createGameController =
new CreateGameController(createGameView, eventManager, saveGameService);
// Refresh save-listen etter at en ny save er skrevet til disk.
createGameController.setOnSaveCreated(playGameController::refresh);

// Settings
SettingsView settingsView = new SettingsView();
new SettingsController(settingsView, eventManager);

// Summary section of the top bar
SummaryView summaryView = new SummaryView();
new SummaryController(summaryView, eventManager, exchange, player);
SummaryController summaryController =
new SummaryController(summaryView, eventManager, exchange, player);

// Top bar with summary section
TopBarView topBarView = new TopBarView(summaryView);
TopBarController topBarController = new TopBarController(topBarView, eventManager);

// Top bar without summary section
TopBarView topBarView2 = new TopBarView();
new TopBarController(topBarView2, eventManager);

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

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

// Market page (Market-knappen tar deg hit)
MarketView marketView = new MarketView();
new MarketController(marketView,
eventManager,
player,
exchange,
stocksInFile);

// In-game (Change "topBarView" to "topBarView2" if no summary section).
// Dashboard er default center-view.
MarketController marketController =
new MarketController(marketView, eventManager, player, exchange, stocksInFile);

InGameView inGameView = new InGameView(topBarView, dashBoardView.getRootPane());
InGameController inGameController = new InGameController(
inGameView,
eventManager
);
InGameController inGameController = new InGameController(inGameView, eventManager);

// Transaction history page
TransactionsView transactionsView = new TransactionsView();
TransactionsController transactionsController = new TransactionsController(
transactionsView,
eventManager,
player.getTransactionArchive());
transactionsView, eventManager, player.getTransactionArchive());

ClickerGame clickerGame = new ClickerGame();
FindStockGame findStockGame = new FindStockGame(
stocksInFile.stream()
.map(Stock::getSymbol)
.toList()
stocksInFile.stream().map(Stock::getSymbol).toList()
);
TimeInputsGame timeInputsGame = new TimeInputsGame();

GameEngineView gameEngineView = new GameEngineView();
GameEngineController gameEngineController = new GameEngineController(
gameEngineView,
eventManager,
stocksInFile.getFirst()
gameEngineView, eventManager, stocksInFile.getFirst()
);

MiniGamesView miniGamesView = new MiniGamesView();
new MiniGamesController(
miniGamesView,
eventManager,
stocksInFile.getFirst(),
gameEngineView,
gameEngineController,
clickerGame,
inGameView,
findStockGame,
timeInputsGame
MiniGamesController miniGamesController =
new MiniGamesController(
miniGamesView, eventManager, stocksInFile.getFirst(), gameEngineView,
gameEngineController, clickerGame, inGameView, findStockGame, timeInputsGame
);

// Wire top bar buttons til å bytte mellom dashboard / stats / market /
// transactions. Stats-knappen tar deg til stats-siden.
// Adds a generic event subscriber to the event manager
// that handles STATE_RESET events. These events are
// triggered when a new save file is loaded.
// We define this implementation here, because
// this class has the highest level overview of the application.
eventManager.addSubscriber(new EventSubscriber() {
@Override
public <T> void handleEvent(final EventData<T> eventData) {
if (eventData.data() instanceof SaveGame) {

if (createGameController.getExchange() != null && createGameController.getPlayer() != null) {
gameStateLoader.setExchange(createGameController.getExchange());

exchange = createGameController.getExchange();
player = createGameController.getPlayer();
} else {
exchange = gameStateLoader.getExchange();
player = gameStateLoader.getPlayer();
}

List<Stock> dynamicStocks = exchange.getStocks();

// Updates the various UI components that
// depend on an exchange, player, or list of stocks.
findStockGame.updateStockPool(dynamicStocks.stream().map(Stock::getSymbol).toList());
summaryController.handleContextUpdate(Main.this.exchange, Main.this.player);
dashBoardController.handleStockPoolUpdate(dynamicStocks);
statsController.handleContextUpdate(Main.this.exchange, Main.this.player);
marketController.handleStockPoolUpdate(Main.this.exchange, Main.this.player, dynamicStocks);

if (!dynamicStocks.isEmpty()) {
miniGamesController.setActiveStock(dynamicStocks.getFirst());
}
}
}
}, EventType.STATE_RESET);

topBarController.setMarketIntegration(
inGameView::changeCenterView,
dashBoardView.getRootPane(),
marketView.getRootPane(),
statsView.getRootPane(),
transactionsView.getRootPane(),
transactionsController::refresh,
inGameView::changeCenterView, dashBoardView.getRootPane(), marketView.getRootPane(),
statsView.getRootPane(), transactionsView.getRootPane(), transactionsController::refresh,
miniGamesView.getRootPane()
);

// In-game settings overlay (Dark / Light theme toggle).
InGameSettingsView inGameSettingsView = new InGameSettingsView();
InGameSettingsController inGameSettingsController =
new InGameSettingsController(inGameSettingsView, eventManager, inGameView);
topBarController.setSettingsAction(inGameSettingsController::show);

// Auto-save the currently active save when the player quits back
// to the main menu. Silent if no save is active (i.e. the user
// got into the in-game scene without going through the save list).
topBarController.setOnQuitToMainMenu(() -> {
System.out.println("[auto-save] Quit triggered, attempting snapshot...");
SaveGame snapshot = gameStateLoader.snapshotActiveSave();
if (snapshot == null) {
System.out.println("[auto-save] No active save - nothing to write.");
return;
}
System.out.println("[auto-save] Snapshot built for '" + snapshot.getName()
+ "', balance=" + snapshot.getBalance()
+ ", week=" + snapshot.getWeek()
+ ", shares=" + snapshot.getOwnedShares().size()
+ ", txns=" + snapshot.getTransactions().size());
try {
saveGameService.saveGame(snapshot);
System.out.println("[auto-save] Wrote save '" + snapshot.getName() + "' to disk.");
} catch (Exception e) {
System.err.println("[auto-save] Failed: " + e.getMessage());
e.printStackTrace();
}
});

// Register all views
viewManager.addView(mainMenuView);
viewManager.addView(playGameView);
viewManager.addView(createGameView);
viewManager.addView(settingsView);
viewManager.addView(inGameView);
viewManager.setScene(mainMenuView);

// Register all widgets
inGameController.addwidget(WidgetEnum.DASHBOARD, dashBoardView.getRootPane());
inGameController.addwidget(WidgetEnum.MARKET, marketView.getRootPane());
inGameController.addwidget(WidgetEnum.MINIGAMES_OVERVIEW, miniGamesView.getRootPane());
Expand All @@ -259,4 +253,4 @@ public void start(final Stage stage) throws Exception {

stage.show();
}
}
}
Loading

0 comments on commit c5d5164

Please sign in to comment.