Skip to content

nå funker det skikkelig :) #133

Closed
wants to merge 1 commit into from
Closed
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
58 changes: 46 additions & 12 deletions src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,28 +217,62 @@ public void start(final Stage stage) throws Exception {
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...");
// Auto-save the currently active save. Used by every trigger below
// (quit-button, window close, money change, week advance). Silent
// if no save is active (i.e. the user got into the in-game scene
// without going through the save list), or if a save-load is
// currently in progress (the money / week mutations inside
// applySave fire the same property listeners we hook up below, so
// without this guard we would write half-loaded state back to disk
// in the middle of a load).
Runnable autoSave = () -> {
if (gameStateLoader.isLoading()) {
return;
}
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.");
System.out.println("[auto-save] Wrote save '" + snapshot.getName()
+ "' (balance=" + snapshot.getBalance()
+ ", week=" + snapshot.getWeek()
+ ", shares=" + snapshot.getOwnedShares().size()
+ ", txns=" + snapshot.getTransactions().size() + ").");
} catch (Exception e) {
System.err.println("[auto-save] Failed: " + e.getMessage());
e.printStackTrace();
}
};

// Trigger 1: quit-button in the top bar (refreshes the play-game
// list too so the row balance reflects what we just wrote).
topBarController.setOnQuitToMainMenu(() -> {
System.out.println("[auto-save] Quit-button triggered.");
autoSave.run();
playGameController.refresh();
});

// Trigger 2: window close (X-button on the OS window). Catches the
// case where the user closes the app directly instead of going
// back to the menu.
stage.setOnCloseRequest(e -> {
System.out.println("[auto-save] Window close triggered.");
autoSave.run();
});

// Trigger 3: every time the player's money changes (buy / sell).
// This means progress is persisted immediately after each
// transaction, so a save is never more than one action stale.
player.getMoneyAsFloatProperty().addListener((obs, oldVal, newVal) -> {
autoSave.run();
});

// Trigger 4: every time the in-game week advances. Captures price
// history-related state (the saved week is part of the snapshot).
exchange.weekProperty().addListener((obs, oldVal, newVal) -> {
autoSave.run();
});

// Register all views
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ public final class GameStateLoader
* */
private SaveGame activeSave;

/**
* Flag set while {@link #applySave} is running.
*
* <p>
* The apply-save flow mutates player money and the exchange week,
* both of which fire JavaFX property change events. The auto-save
* listeners hooked up in {@code Main} react to those events, so
* without this flag they would write the half-loaded state back to
* disk in the middle of a load. Auto-save callers check this via
* {@link #isLoading()} and skip while it is {@code true}.
* </p>
* */
private boolean loading;

/**
* Constructor.
*
Expand Down Expand Up @@ -123,6 +137,21 @@ public SaveGame getActiveSave() {
return activeSave;
}

/**
* Returns whether a save-load is currently in progress.
*
* <p>
* Used by the auto-save flow to suppress writes during {@link #applySave},
* since money and week mutations there fire JavaFX property change
* events that auto-save listens to.
* </p>
*
* @return {@code true} while {@link #applySave} is running.
* */
public boolean isLoading() {
return loading;
}

/**
* Builds a fresh {@link SaveGame} snapshot of the current player
* and exchange state, using the active save's name and starting
Expand Down Expand Up @@ -212,79 +241,84 @@ private void applySave(final SaveGame save) {
+ ", shares=" + save.getOwnedShares().size()
+ ", txns=" + save.getTransactions().size());

// 1. Roll the exchange's prices back to the captured baseline and
// the exchange's week back to 1, so the simulation starts
// fresh.
exchange.resetStocksTo(baselinePrices);
exchange.setWeek(1);
loading = true;
try {
// 1. Roll the exchange's prices back to the captured baseline and
// the exchange's week back to 1, so the simulation starts
// fresh.
exchange.resetStocksTo(baselinePrices);
exchange.setWeek(1);

// 2. Reset the player to an empty state with the saved starting
// capital. We use starting capital here (rather than the
// final saved balance) so the per-week net-worth samples
// collected by widget listeners during the advances below
// have a meaningful baseline.
Portfolio portfolio = player.getPortfolio();
portfolio.clear();
TransactionArchive archive = player.getTransactionArchive();
archive.clear();
player.setMoney(BigDecimal.valueOf(save.getStartingCapital()));
player.refreshProperties();
// 2. Reset the player to an empty state with the saved starting
// capital. We use starting capital here (rather than the
// final saved balance) so the per-week net-worth samples
// collected by widget listeners during the advances below
// have a meaningful baseline.
Portfolio portfolio = player.getPortfolio();
portfolio.clear();
TransactionArchive archive = player.getTransactionArchive();
archive.clear();
player.setMoney(BigDecimal.valueOf(save.getStartingCapital()));
player.refreshProperties();

// 3. Advance the exchange (save.getWeek() - 1) times so the
// stock price graphs get a real history, and so widgets that
// track per-week net-worth (the financial summary and the
// stats screen) accumulate chart points via their existing
// weekProperty listeners.
int targetWeek = Math.max(1, save.getWeek());
while (exchange.getWeek() < targetWeek) {
exchange.advance();
}
// 3. Advance the exchange (save.getWeek() - 1) times so the
// stock price graphs get a real history, and so widgets that
// track per-week net-worth (the financial summary and the
// stats screen) accumulate chart points via their existing
// weekProperty listeners.
int targetWeek = Math.max(1, save.getWeek());
while (exchange.getWeek() < targetWeek) {
exchange.advance();
}

// 4. Re-apply the saved owned shares (skipping unknown symbols
// instead of throwing - keeps the load robust against stock
// files that have diverged from the save).
for (OwnedShareData od : save.getOwnedShares()) {
if (!exchange.hasStock(od.getSymbol())) {
System.err.println("Skipping unknown stock from save: "
+ od.getSymbol());
continue;
// 4. Re-apply the saved owned shares (skipping unknown symbols
// instead of throwing - keeps the load robust against stock
// files that have diverged from the save).
for (OwnedShareData od : save.getOwnedShares()) {
if (!exchange.hasStock(od.getSymbol())) {
System.err.println("Skipping unknown stock from save: "
+ od.getSymbol());
continue;
}
Stock stock = exchange.getStock(od.getSymbol());
portfolio.addShare(new Share(
stock, od.getQuantity(), od.getPurchasePrice()));
}
Stock stock = exchange.getStock(od.getSymbol());
portfolio.addShare(new Share(
stock, od.getQuantity(), od.getPurchasePrice()));
}

// 5. Re-apply the saved transactions. We rebuild the original
// Purchase / Sale objects (with their share + calculator)
// directly into the archive, rather than re-running them
// through the player's transaction handler, so the player's
// balance is not mutated again here.
for (TransactionData td : save.getTransactions()) {
if (!exchange.hasStock(td.getSymbol())) {
System.err.println("Skipping transaction with unknown stock: "
+ td.getSymbol());
continue;
// 5. Re-apply the saved transactions. We rebuild the original
// Purchase / Sale objects (with their share + calculator)
// directly into the archive, rather than re-running them
// through the player's transaction handler, so the player's
// balance is not mutated again here.
for (TransactionData td : save.getTransactions()) {
if (!exchange.hasStock(td.getSymbol())) {
System.err.println("Skipping transaction with unknown stock: "
+ td.getSymbol());
continue;
}
Stock stock = exchange.getStock(td.getSymbol());
Share share = new Share(stock, td.getQuantity(), td.getPrice());
TransactionCalculator calculator = (td.getType() == TransactionType.SALE)
? new SaleCalculator(share)
: new PurchaseCalculator(share);
Transaction transaction = (td.getType() == TransactionType.SALE)
? new Sale(share, td.getWeek(), calculator)
: new Purchase(share, td.getWeek(), calculator);
archive.add(transaction);
}
Stock stock = exchange.getStock(td.getSymbol());
Share share = new Share(stock, td.getQuantity(), td.getPrice());
TransactionCalculator calculator = (td.getType() == TransactionType.SALE)
? new SaleCalculator(share)
: new PurchaseCalculator(share);
Transaction transaction = (td.getType() == TransactionType.SALE)
? new Sale(share, td.getWeek(), calculator)
: new Purchase(share, td.getWeek(), calculator);
archive.add(transaction);
}

// 6. Overwrite the balance with the saved value now that the
// history has been built up.
player.setMoney(BigDecimal.valueOf(save.getBalance()));
// 6. Overwrite the balance with the saved value now that the
// history has been built up.
player.setMoney(BigDecimal.valueOf(save.getBalance()));

// 7. Re-publish the float properties so the final loaded
// balance is visible to all listeners.
player.refreshProperties();
// 7. Re-publish the float properties so the final loaded
// balance is visible to all listeners.
player.refreshProperties();

this.activeSave = save;
this.activeSave = save;
} finally {
loading = false;
}
}

/**
Expand Down
6 changes: 0 additions & 6 deletions src/main/resources/saves/Halleluja.json

This file was deleted.

24 changes: 11 additions & 13 deletions src/main/resources/saves/Newbie.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
{
"name": "Newbie",
"balance": 388.6825,
"balance": 134.5153,
"startingCapital": 10000.0,
"stockDataPath": null,
"week": 5,
"week": 27,
"ownedShares": [
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 },
{ "symbol": "NVDA", "quantity": 5.0, "purchasePrice": 191.27 }
{ "symbol": "NVDA", "quantity": 50.0, "purchasePrice": 191.27 }
],
"transactions": [
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
Expand All @@ -26,6 +17,13 @@
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 }
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
{ "type": "SALE", "symbol": "NVDA", "quantity": 14.0, "price": 174.30, "week": 18 },
{ "type": "SALE", "symbol": "NVDA", "quantity": 14.0, "price": 174.30, "week": 18 },
{ "type": "SALE", "symbol": "NVDA", "quantity": 14.0, "price": 174.30, "week": 18 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 17.0, "price": 177.72, "week": 18 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 17.0, "price": 177.72, "week": 18 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 7.0, "price": 177.72, "week": 18 },
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 1.0, "price": 177.72, "week": 18 }
]
}
43 changes: 0 additions & 43 deletions src/main/resources/saves/Tommy.json

This file was deleted.