From fd78a3fea50374ec40dad2a58416e679de757d30 Mon Sep 17 00:00:00 2001
From: =
- * Holds the display name, current balance, starting capital,
+ * Holds the display name, current balance, starting capital,
* (optionally) the path to a custom stock data file, the in-game week,
* the list of owned shares, the list of committed transactions, and
- * the current state of the exchange stocks for a single saved game.
- *
Used by JSON parser to map array
+ * + * @param name the display name of the save. + * @param balance the current balance value. + * @param startingCapital the starting capital chosen on creation. + * @param stockDataPath absolute path to a custom stock data file, + * or {@code null} to use the default file. + * @param week the in-game week when the save was written. + * @param ownedShares the shares the player owned (may be null; treated as empty). + * @param transactions the committed transactions (may be null; treated as empty). + * @param exchangeStocks the current list of stocks from the exchange (may be null; treated as empty). + * @param dummyFlagForOverloading sample dummy flag used for overload. */ public SaveGame(final String name, final double balance, @@ -115,7 +125,17 @@ public SaveGame(final String name, } /** - * Legacy backward-compatible constructor matching your previous full configuration. + * Backwards-compatible overload used in a previous implementation. + * + * @param name the display name of the save. + * @param balance the current balance value. + * @param startingCapital the starting capital chosen on creation. + * @param stockDataPath absolute path to a custom stock data file, + * or {@code null} to use the default file. + * @param week the in-game week when the save was written. + * @param ownedShares the shares the player owned (may be null; treated as empty). + * @param transactions the committed transactions (may be null; treated as empty). + * @param exchangeStocks the current list of stocks from the exchange (may be null; treated as empty). */ public SaveGame(final String name, final double balance, @@ -129,7 +149,16 @@ public SaveGame(final String name, } /** - * Legacy backward-compatible constructor matching your previous configuration. + * Backwards-compatible overload used in a previous implementation. + * + * @param name the display name of the save. + * @param balance the current balance value. + * @param startingCapital the starting capital chosen on creation. + * @param stockDataPath absolute path to a custom stock data file, + * or {@code null} to use the default file. + * @param week the in-game week when the save was written. + * @param ownedShares the shares the player owned (may be null; treated as empty). + * @param transactions the committed transactions (may be null; treated as empty). */ public SaveGame(final String name, final double balance, @@ -143,6 +172,11 @@ public SaveGame(final String name, /** * Convenience constructor matching the original format used by the create-game flow. + * @param name the display name of the save. + * @param balance the current balance value. + * @param startingCapital the starting capital chosen on creation. + * @param stockDataPath absolute path to a custom stock data file, + * or {@code null} to use the default file. */ public SaveGame(final String name, final double balance, @@ -151,13 +185,6 @@ public SaveGame(final String name, this(name, balance, startingCapital, stockDataPath, 1, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); } - /** - * Convenience constructor matching the legacy "name + balance" format. - */ - public SaveGame(final String name, final double balance) { - this(name, balance, balance, null, 1, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); - } - /** * Getter method for the name. * @@ -239,4 +266,4 @@ public ListCalls events of type
*/ public final class GameStateLoader implements EventSubscriber, EventPublisher { + /** + * Local reference to player. + * */ private final Player player; - private Exchange exchange; // Non-final to allow runtime context swaps + + /** + * Local reference to exchange. + * */ + private Exchange exchange; + + /** + * Local reference to event manager. + * */ private final EventManager eventManager; + + /** + * Baseline prices of symbols. + * */ private final MapIf save includes valid stocks, uses them. If not, + * uses fallback stocks (default data).
+ * + *Clears and rebuilds exchange, player, transactions, + * portfolio and net-worth history of player.
+ * + * @param save save to apply. + * */ private void applySave(final SaveGame save) { - System.out.println("[loader] applySave: name=" + save.getName()); - - // 1. Determine baseline context: use the save file's embedded stocks if present, - // otherwise fall back to the system's current baseline configuration. Map- * Each save is stored as a separate JSON file in a single directory, - * which lets several saves co-exist independently. - *
+ *Each save is stored as a separate JSON file in a single directory, + * which lets several saves co-exist independently.
* *JSON file format:
* @@ -43,23 +40,26 @@ * { "type": "PURCHASE", "symbol": "AAPL", "quantity": 5, * "price": 150.00, "week": 1 } * ] + * "stocks": [ + * { "symbol": "AAPL", "companyName": "Apple Inc.", "salesPrice": 155.25 } + * ] + * "netWorthHistory": [ + * 10000.00, + * 10026.25 + * ] * } * * - *- * The {@code week}, {@code ownedShares} and {@code transactions} + *
The {@code week}, {@code ownedShares} and {@code transactions} * fields are optional - old saves without them load with sensible - * defaults (week 1, empty lists). - *
+ * defaults (week 1, empty lists). * - *- * The service exposes both a "load all saves" entry point (used by + *
The service exposes both a "load all saves" entry point (used by * {@link edu.ntnu.idi.idatt2003.g40.mappe.view.playgame.PlayGameView}) * and a "save one" entry point (used by the create-game flow and the * auto-save flow). The JSON parsing logic is intentionally minimal and * tailored to this format - invalid files are skipped rather than - * throwing. - *
+ * throwing. */ public class SaveGameService { @@ -91,16 +91,12 @@ public SaveGameService(final String directoryPath) { /** * Loads all save games from the directory. * - *- * Walks the saves directory, parses every file with a + *
Walks the saves directory, parses every file with a * {@code .json} extension and returns the resulting list. - * Files that fail to parse are silently skipped. - *
+ * Files that fail to parse are silently skipped. * - *- * Returns an empty list if the directory does not exist or cannot - * be read. - *
+ *Returns an empty list if the directory does not exist or cannot + * be read.
* * @return the loaded {@link SaveGame} entries. */ @@ -134,12 +130,10 @@ public List- * The file name is derived from {@link SaveGame#getName()} sanitised + *
The file name is derived from {@link SaveGame#getName()} sanitised * to filesystem-safe characters and given the {@code .json} * extension. The saves directory is created automatically if it - * doesn't exist. - *
+ * doesn't exist. * * @param save the {@link SaveGame} object to write. * @@ -185,11 +179,9 @@ public boolean saveExists(final String name) { /** * Loads a single save from an explicit file path. * - *- * Used by the upload flow on the play-game screen so a save file + *
Used by the upload flow on the play-game screen so a save file * located anywhere on disk can be added to the displayed list - * without having to live inside the saves directory. - *
+ * without having to live inside the saves directory. * * @param file the file to parse. * @return the parsed {@link SaveGame}, or {@code null} if the file @@ -205,12 +197,10 @@ public SaveGame loadSaveFromFile(final Path file) { /** * Parses a single JSON file into a {@link SaveGame}. * - *- * Returns {@code null} for files that don't contain a valid save + *
Returns {@code null} for files that don't contain a valid save * record (missing required fields or malformed JSON). Old saves * that don't have week / ownedShares / transactions still parse - * cleanly, with those fields defaulted (week 1, empty lists). - *
+ * cleanly, with those fields defaulted (week 1, empty lists). * * @param file path to the file to parse. * @return the parsed {@link SaveGame}, or {@code null}. @@ -234,13 +224,11 @@ private SaveGame parseFile(final Path file) { ? Double.parseDouble(fields.get("startingCapital")) : balance; - // stockDataPath may be absent or explicitly "null". String stockDataPath = fields.get("stockDataPath"); if (stockDataPath != null && stockDataPath.isEmpty()) { stockDataPath = null; } - // Week - defaults to 1 for older saves that didn't store it. int week = 1; if (fields.containsKey("week") && !fields.get("week").isEmpty()) { week = Integer.parseInt(fields.get("week")); @@ -249,15 +237,11 @@ private SaveGame parseFile(final Path file) { } } - // The flat parser can't represent arrays in the result map, so - // the array bodies are pulled straight out of the raw content - // with extractArrayBody and then parsed object-by-object. List- * Output is pretty-printed with two-space indentation and a trailing + *
Output is pretty-printed with two-space indentation and a trailing * newline so the files are human-readable. Numeric values are * written via {@link BigDecimal#toPlainString()} so they never * surface as scientific notation. Owned shares and transactions - * write as JSON arrays of small flat objects. - *
+ * write as JSON arrays of small flat objects. * * @param save the save to convert. * @return JSON object string. @@ -320,7 +301,6 @@ private String toJson(final SaveGame save) { sb.append(" \"ownedShares\": ").append(ownedSharesToJson(save.getOwnedShares())).append(",\n"); sb.append(" \"transactions\": ").append(transactionsToJson(save.getTransactions())).append(",\n"); - // Wire the live tracking stocks from your game state container layout here sb.append(" \"stocks\": ").append(stocksToJson(save.getExchangeStocks())).append("\n"); sb.append("}\n"); return sb.toString(); @@ -422,22 +402,16 @@ private String formatNumber(final double value) { * Extracts the body of a top-level JSON array field from a raw save * file's content. * - *- * Given the raw content {@code {"name": "x", "ownedShares": [ ... ]}} + *
Given the raw content {@code {"name": "x", "ownedShares": [ ... ]}} * and a field name {@code "ownedShares"}, returns the substring - * between the opening {@code [} and the matching closing {@code ]}. - *
+ * between the opening {@code [} and the matching closing {@code ]}. * - *- * Returns {@code null} if the field is not present, or if the array + *
Returns {@code null} if the field is not present, or if the array * is malformed (no closing bracket). Returns an empty string for an - * empty array. - *
+ * empty array. * - *- * Brackets inside quoted strings are ignored, so a string value like - * {@code "weird]name"} won't confuse the matcher. - *
+ *Brackets inside quoted strings are ignored, so a string value like + * {@code "weird]name"} won't confuse the matcher.
* * @param content the raw file content. * @param fieldName the JSON field name to look for. @@ -499,12 +473,10 @@ private String extractArrayBody(final String content, /** * Splits a JSON array body into the substrings of its inner objects. * - *- * Tracks bracket and quote nesting so that commas inside the inner + *
Tracks bracket and quote nesting so that commas inside the inner * objects (or inside quoted strings) don't split the body * incorrectly. Returns the substrings of each top-level - * {@code {...}} found. - *
+ * {@code {...}} found. * * @param body the substring between {@code [} and {@code ]}. * @return list of object substrings, or an empty list.