diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java
index 2a3b8e0..cf86ca5 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/service/SaveGameService.java
@@ -610,21 +610,17 @@ private List parseTransactionsArray(final String body) {
/**
* Parses a flat (one level deep) JSON object into a map.
*
- *
- * Only supports string, number, boolean and null values for the
+ *
Only supports string, number, boolean and null values for the
* top-level entries (which is everything {@link SaveGame} and
* {@link OwnedShareData} / {@link TransactionData} need). Nested
* arrays and objects are skipped past with an empty-string value,
* since the array contents are read separately via
* {@link #extractArrayBody}. Returns {@code null} if the content
- * can't be parsed.
- *
+ * can't be parsed.
*
- *
- * Values are returned as strings; {@code null} values are stored as
+ *
Values are returned as strings; {@code null} values are stored as
* an empty string so callers can distinguish "absent" from "null"
- * using {@link Map#containsKey(Object)}.
- *
+ * using {@link Map#containsKey(Object)}.
*
* @param content the raw file content.
* @return a map of field name to raw value, or {@code null}.
@@ -750,11 +746,9 @@ private int findStringEnd(final String s, final int start) {
* opening bracket / brace at {@code start}, accounting for quoted
* strings and nested structures. Returns -1 if no match is found.
*
- *
- * Used by {@link #parseFlatJsonObject} to skip past nested arrays
+ *
Used by {@link #parseFlatJsonObject} to skip past nested arrays
* and objects whose content isn't needed at the top level (top-level
- * arrays are read separately by {@link #extractArrayBody}).
- *
+ * arrays are read separately by {@link #extractArrayBody}).
* */
private int findStructuredEnd(final String s, final int start) {
char open = s.charAt(start);
@@ -849,11 +843,9 @@ private String unquote(final String token) {
/**
* Sanitises a save name to a safe filesystem identifier.
*
- *
- * All characters outside {@code [A-Za-z0-9_-]} are replaced with
+ *
All characters outside {@code [A-Za-z0-9_-]} are replaced with
* underscores. This keeps the on-disk file name predictable while
- * preserving the original display name in the JSON content.
- *
+ * preserving the original display name in the JSON content.
*/
private String sanitiseFileName(final String name) {
String trimmed = name.trim();
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/creategame/CreateGameController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/creategame/CreateGameController.java
index d1bd01f..ccd0d25 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/creategame/CreateGameController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/creategame/CreateGameController.java
@@ -10,11 +10,9 @@
import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
-
import java.io.File;
import java.io.IOException;
import java.util.List;
-
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
@@ -26,16 +24,12 @@
*
* Extends {@link ViewController}.
*
- *
- * Handles the four interactions on the create-game screen: picking
+ *
Handles the four interactions on the create-game screen: picking
* the default stock data, choosing a custom stock data file, cancel
- * (back to the play-game screen), and finally creating the save.
- *
+ * (back to the play-game screen), and finally creating the save.
*
- *
- * When a save is successfully written to disk a callback can be
- * notified so the play-game view can refresh its save list.
- *
+ * When a save is successfully written to disk a callback can be
+ * notified so the play-game view can refresh its save list.
*/
public class CreateGameController extends ViewController {
@@ -114,7 +108,6 @@ public void setOnSaveCreated(final Runnable handler) {
protected void initInteractions() {
getViewElement().setOnAction(CreateGameActions.USE_DEFAULT_STOCKS, () -> {
try {
- // Read the default stock resource pool to populate the initial exchange baseline
StockFileManager stockFileManager = new StockFileManager("sp500.csv");
StockFileParser stockFileParser = new StockFileParser();
List defaultStocks = stockFileParser.getStocksFromStrings(stockFileManager.readFile());
@@ -206,10 +199,8 @@ private void handleCreateGame() {
}
}
- // Safety check: ensure exchange baseline was built during choice selection loops
List initialStocks = (this.exchange != null) ? this.exchange.getStocks() : List.of();
- // Reconstruct utilizing the full array snapshot layout tracking parameter
SaveGame newSave = new SaveGame(
name,
capital,
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardController.java
index a9ad60b..9a5cd9c 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardController.java
@@ -220,19 +220,21 @@ protected void initInteractions() {
});
}
+ /**
+ * Method for setting a new list of stocks for the view and controller.
+ *
+ * @param updatedStocks new list of stocks.
+ * */
public void handleStockPoolUpdate(final List updatedStocks) {
if (updatedStocks == null || updatedStocks.isEmpty()) {
return;
}
- // Synchronize our final referenced list tracking structure
this.stockList.clear();
this.stockList.addAll(updatedStocks);
- // Rebuild the sidebar UI item buttons with the new stock identifiers
populateStockList(this.selectedFilter);
- // Default active UI chart presentation view elements focus to the first stock
Stock firstStock = this.stockList.getFirst();
BigDecimal ownedAmount = this.player.getPortfolio()
.getTotalShareQuantityBySymbol(firstStock.getSymbol());
@@ -249,8 +251,6 @@ public void handleStockPoolUpdate(final List updatedStocks) {
* */
@Override
public void handleEvent(final EventData data) {
- System.out.println("[dashboard] STATE_RESET: shares in portfolio = "
- + player.getPortfolio().getShares().size());
populateStockList(selectedFilter);
if (!stockList.isEmpty()) {
Stock first = stockList.getFirst();
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardView.java
index 438be15..d7edb2a 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/dashboard/DashBoardView.java
@@ -577,29 +577,4 @@ private String formatShares(final float amount) {
String formatted = String.format(java.util.Locale.US, "%.3f", amount);
return formatted.replaceAll("0+$", "").replaceAll("\\.$", "");
}
-
- /**
- * Clears the sidebar and populates it with a new list of stock buttons,
- * executing the provided configuration logic on each button.
- *
- * @param newStocks the new collection of {@link Stock} objects to display.
- * @param clickLogic the controller logic to bind to each newly generated button.
- */
- public void updateStockPool(final List newStocks, final Consumer clickLogic) {
- if (newStocks == null || clickLogic == null) {
- return;
- }
-
- // Clear the sidebar layout elements container completely
- clearStockList();
-
- // Generate fresh buttons for every stock inside the new collection pool
- for (Stock stock : newStocks) {
- String buttonText = stock.getSymbol() + " - " + stock.getCompany();
- Button stockBtn = createStockButton(buttonText);
-
- // Wire the interaction mapping back to the controller logic
- setOnStockAction(stockBtn, stock, clickLogic);
- }
- }
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
index bf83ddc..28a6224 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/financialsummary/SummaryController.java
@@ -7,7 +7,6 @@
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.view.ViewController;
-
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@@ -33,7 +32,8 @@ public SummaryController(final SummaryView viewElement,
super(viewElement, eventManager);
eventManager.addSubscriber(this, EventType.STATE_RESET);
eventManager.addSubscriber(this, EventType.PRE_LOAD_SAVE);
- getViewElement().setBalance(player.getStartingMoney().floatValue(), player.getStartingMoney().floatValue());
+ getViewElement().setBalance(player.getStartingMoney().floatValue(),
+ player.getStartingMoney().floatValue());
}
@Override
@@ -113,13 +113,12 @@ public void handleEvent(final EventData data) {
return;
}
- // STATE_RESET block
if (playerNetWorthHistory == null) {
playerNetWorthHistory = new ArrayList<>();
}
playerNetWorthHistory.clear();
- if (player.getNetWorthHistory() != null && !player.getNetWorthHistory().isEmpty()) {
+ if (!player.getNetWorthHistory().isEmpty()) {
playerNetWorthHistory.addAll(player.getNetWorthHistory());
} else {
playerNetWorthHistory.add(player.getStartingMoney());
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketController.java
index 0ddbbe1..b8ab2dc 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketController.java
@@ -114,12 +114,11 @@ private int ownedQuantity(final String symbol) {
}
/**
- * Refreshes the underlying tracking context references and triggers a complete
- * rebuilding processing loop for the graphical marketplace card components.
+ * Refreshes the view element with updated context.
*
- * @param updatedExchange the current active exchange engine.
- * @param updatedPlayer the current active player profile context.
- * @param freshStocks the new active collection pool of stocks.
+ * @param updatedExchange the current active exchange.
+ * @param updatedPlayer the current active player.
+ * @param freshStocks the new active collection of stocks.
*/
public void handleStockPoolUpdate(final Exchange updatedExchange,
final Player updatedPlayer,
@@ -128,12 +127,10 @@ public void handleStockPoolUpdate(final Exchange updatedExchange,
return;
}
- // Synchronize engine references
this.exchange = updatedExchange;
this.player = updatedPlayer;
this.stockList = freshStocks;
- // Push the changes down to the presentation layer view layout grid
getViewElement().updateStockPool(freshStocks);
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketView.java
index 327c1b7..c6750d7 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketView.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/market/MarketView.java
@@ -378,8 +378,7 @@ private Polyline buildMiniChart(final Stock stock) {
}
/**
- * Replaces the entire underlying stock data collection pool and forces
- * a full graphical UI re-render layout processing update loop.
+ * Re-renders the ui with a list of updated stocks.
*
* @param updatedStocks the fresh list of stocks parsed from the save file.
*/
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/FindStockGame.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/FindStockGame.java
index c101d6e..5e4c4f3 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/FindStockGame.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/FindStockGame.java
@@ -137,7 +137,6 @@ public void updateStockPool(final List newSymbols) {
}
this.availableSymbols = List.copyOf(newSymbols);
- // Regenerate the current round so symbols from a previous save don't linger on screen
generateRound();
}
diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
index 8cf6188..ac4d39e 100644
--- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
+++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/stats/StatsController.java
@@ -204,8 +204,7 @@ private static final class Aggregate {
}
/**
- * Updates the underlying tracking engine references and fully
- * synchronizes the metric graphs to match the newly loaded save state.
+ * Updates the graphs and information of the page given a new exchange and player.
*
* @param updatedExchange the current active exchange engine.
* @param updatedPlayer the current active player context profile.
@@ -222,21 +221,14 @@ public void handleContextUpdate(final Exchange updatedExchange, final Player upd
this.balanceHistory = new ArrayList<>();
}
- // 1. Clear the stale session data entirely
this.balanceHistory.clear();
- // 2. Reconstruct the entire weekly history timeline directly from the
- // loaded player/stock data if available, or fetch it from the save.
- // If your Player model stores historical net worth, parse it here:
- if (this.player.getNetWorthHistory() != null && !this.player.getNetWorthHistory().isEmpty()) {
+ if (!this.player.getNetWorthHistory().isEmpty()) {
this.balanceHistory.addAll(this.player.getNetWorthHistory());
} else {
- // Fallback: If no history array exists, use the baseline points
this.balanceHistory.add(this.player.getStartingMoney());
this.balanceHistory.add(this.player.getNetWorth());
}
-
- // 3. Flush completely recalculated asset structures to the UI
pushSnapshot();
}
}
\ No newline at end of file
diff --git a/src/main/resources/saves/Halleluja.json b/src/main/resources/saves/Halleluja.json
index 6068147..7737bf7 100644
--- a/src/main/resources/saves/Halleluja.json
+++ b/src/main/resources/saves/Halleluja.json
@@ -2,5 +2,12 @@
"name": "Halleluja",
"balance": 1000650901.43,
"startingCapital": 10000.0,
- "stockDataPath": null
+ "stockDataPath": null,
+ "week": 1,
+ "ownedShares": [],
+ "transactions": [],
+ "stocks": [
+ { "symbol": "TOTA", "name": "Total badass1", "price": 136.80 },
+ { "symbol": "LIBR", "name": "Libra avenger of worlds", "price": 19134.23 }
+ ]
}
diff --git a/src/main/resources/saves/Newbie.json b/src/main/resources/saves/Newbie.json
index 823acaf..2ea4a42 100644
--- a/src/main/resources/saves/Newbie.json
+++ b/src/main/resources/saves/Newbie.json
@@ -5,16 +5,7 @@
"stockDataPath": null,
"week": 5,
"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 },
@@ -27,5 +18,163 @@
{ "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 }
+ ],
+ "stocks": [
+ { "symbol": "CARR", "name": "Carrier Global", "price": 67.95 },
+ { "symbol": "AAPL", "name": "Apple Inc.", "price": 258.10 },
+ { "symbol": "SNDK", "name": "Sandisk Corporation", "price": 634.05 },
+ { "symbol": "WYNN", "name": "Wynn Resorts", "price": 117.80 },
+ { "symbol": "TSCO", "name": "Tractor Supply", "price": 51.12 },
+ { "symbol": "AMGN", "name": "Amgen", "price": 329.74 },
+ { "symbol": "TSLA", "name": "Tesla Inc.", "price": 376.58 },
+ { "symbol": "GDDY", "name": "GoDaddy", "price": 92.35 },
+ { "symbol": "SBUX", "name": "Starbucks", "price": 99.41 },
+ { "symbol": "KVUE", "name": "Kenvue", "price": 17.97 },
+ { "symbol": "META", "name": "Meta Platforms", "price": 756.48 },
+ { "symbol": "DLTR", "name": "Dollar Tree", "price": 144.19 },
+ { "symbol": "ABBV", "name": "AbbVie", "price": 251.10 },
+ { "symbol": "HUBB", "name": "Hubbell Incorporated", "price": 548.39 },
+ { "symbol": "JKHY", "name": "Jack Henry & Associates", "price": 180.51 },
+ { "symbol": "FSLR", "name": "First Solar", "price": 206.22 },
+ { "symbol": "FTNT", "name": "Fortinet", "price": 92.09 },
+ { "symbol": "EPAM", "name": "EPAM Systems", "price": 199.46 },
+ { "symbol": "POOL", "name": "Pool Corporation", "price": 284.22 },
+ { "symbol": "MCHP", "name": "Microchip Technology", "price": 72.57 },
+ { "symbol": "VRSK", "name": "Verisk Analytics", "price": 169.99 },
+ { "symbol": "MRNA", "name": "Moderna", "price": 33.00 },
+ { "symbol": "HOOD", "name": "Robinhood Markets Inc.", "price": 64.62 },
+ { "symbol": "VRSN", "name": "Verisign", "price": 247.98 },
+ { "symbol": "AMAT", "name": "Applied Materials", "price": 379.06 },
+ { "symbol": "MDLZ", "name": "Mondelez International", "price": 66.56 },
+ { "symbol": "PCAR", "name": "Paccar", "price": 128.11 },
+ { "symbol": "NDAQ", "name": "Nasdaq Inc.", "price": 79.41 },
+ { "symbol": "INTU", "name": "Intuit", "price": 403.44 },
+ { "symbol": "HSIC", "name": "Henry Schein", "price": 83.94 },
+ { "symbol": "FISV", "name": "Fiserv Inc.", "price": 65.43 },
+ { "symbol": "CSGP", "name": "CoStar Group", "price": 48.87 },
+ { "symbol": "DDOG", "name": "Datadog", "price": 129.43 },
+ { "symbol": "BLDR", "name": "Builders FirstSource", "price": 118.27 },
+ { "symbol": "AXON", "name": "Axon Enterprise", "price": 473.33 },
+ { "symbol": "ALGN", "name": "Align Technology", "price": 187.51 },
+ { "symbol": "FICO", "name": "Fair Isaac", "price": 1242.10 },
+ { "symbol": "FITB", "name": "Fifth Third Bancorp", "price": 50.53 },
+ { "symbol": "NTAP", "name": "NetApp", "price": 105.53 },
+ { "symbol": "FOXA", "name": "Fox Corporation (Class A)", "price": 60.47 },
+ { "symbol": "QCOM", "name": "Qualcomm", "price": 152.25 },
+ { "symbol": "VTRS", "name": "Viatris", "price": 16.25 },
+ { "symbol": "LRCX", "name": "Lam Research", "price": 239.39 },
+ { "symbol": "PLTR", "name": "Palantir Technologies", "price": 132.98 },
+ { "symbol": "PANW", "name": "Palo Alto Networks", "price": 170.52 },
+ { "symbol": "NFLX", "name": "Netflix", "price": 75.58 },
+ { "symbol": "KLAC", "name": "KLA Corporation", "price": 1342.60 },
+ { "symbol": "NVDA", "name": "Nvidia", "price": 187.67 },
+ { "symbol": "IBKR", "name": "Interactive Brokers Group", "price": 74.25 },
+ { "symbol": "CRWD", "name": "CrowdStrike", "price": 448.16 },
+ { "symbol": "ULTA", "name": "Ulta Beauty", "price": 577.29 },
+ { "symbol": "JBHT", "name": "J.B. Hunt", "price": 225.21 },
+ { "symbol": "SMCI", "name": "Supermicro", "price": 31.69 },
+ { "symbol": "NXPI", "name": "NXP Semiconductors", "price": 258.77 },
+ { "symbol": "VRTX", "name": "Vertex Pharmaceuticals", "price": 456.77 },
+ { "symbol": "MTCH", "name": "Match Group", "price": 29.70 },
+ { "symbol": "CBOE", "name": "Cboe Global Markets", "price": 261.74 },
+ { "symbol": "CPRT", "name": "Copart", "price": 38.12 },
+ { "symbol": "VICI", "name": "Vici Properties", "price": 33.48 },
+ { "symbol": "CHRW", "name": "C.H. Robinson", "price": 182.86 },
+ { "symbol": "INTC", "name": "Intel", "price": 44.51 },
+ { "symbol": "ROST", "name": "Ross Stores", "price": 206.42 },
+ { "symbol": "GEHC", "name": "GE HealthCare", "price": 86.95 },
+ { "symbol": "SCHW", "name": "Charles Schwab Corporation", "price": 96.49 },
+ { "symbol": "CVNA", "name": "Carvana Co.", "price": 368.51 },
+ { "symbol": "IDXX", "name": "Idexx Laboratories", "price": 766.54 },
+ { "symbol": "INCY", "name": "Incyte", "price": 101.02 },
+ { "symbol": "GNRC", "name": "Generac", "price": 224.22 },
+ { "symbol": "CPAY", "name": "Corpay", "price": 366.15 },
+ { "symbol": "REGN", "name": "Regeneron Pharmaceuticals", "price": 833.09 },
+ { "symbol": "CTAS", "name": "Cintas", "price": 230.80 },
+ { "symbol": "FAST", "name": "Fastenal", "price": 42.07 },
+ { "symbol": "AMZN", "name": "Amazon", "price": 207.86 },
+ { "symbol": "ZBRA", "name": "Zebra Technologies", "price": 285.78 },
+ { "symbol": "ODFL", "name": "Old Dominion", "price": 208.16 },
+ { "symbol": "TTWO", "name": "Take-Two Interactive", "price": 176.58 },
+ { "symbol": "CTRA", "name": "Coterra", "price": 28.69 },
+ { "symbol": "LDOS", "name": "Leidos", "price": 172.90 },
+ { "symbol": "ARES", "name": "Ares Management Corporation", "price": 131.22 },
+ { "symbol": "CINF", "name": "Cincinnati Financial", "price": 172.93 },
+ { "symbol": "ANET", "name": "Arista Networks", "price": 142.22 },
+ { "symbol": "AMCR", "name": "Amcor", "price": 45.14 },
+ { "symbol": "HBAN", "name": "Huntington Bancshares", "price": 20.67 },
+ { "symbol": "EVRG", "name": "Evergy", "price": 75.68 },
+ { "symbol": "ABNB", "name": "Airbnb", "price": 125.39 },
+ { "symbol": "DASH", "name": "DoorDash", "price": 164.09 },
+ { "symbol": "COIN", "name": "Coinbase Global", "price": 146.37 },
+ { "symbol": "CIEN", "name": "Ciena Corporation", "price": 254.65 },
+ { "symbol": "FANG", "name": "Diamondback Energy", "price": 155.78 },
+ { "symbol": "PSKY", "name": "Paramount Skydance Corp", "price": 10.73 },
+ { "symbol": "ORLY", "name": "O'Reilly Auto Parts", "price": 96.40 },
+ { "symbol": "SBAC", "name": "SBA Communications", "price": 193.40 },
+ { "symbol": "ACGL", "name": "Arch Capital Group", "price": 103.61 },
+ { "symbol": "CTSH", "name": "Cognizant", "price": 60.84 },
+ { "symbol": "VLTO", "name": "Veralto", "price": 102.80 },
+ { "symbol": "MPWR", "name": "Monolithic Power Systems", "price": 1210.08 },
+ { "symbol": "PODD", "name": "Insulet Corporation", "price": 264.60 },
+ { "symbol": "MRSH", "name": "Marsh & McLennan Companies Inc.", "price": 159.69 },
+ { "symbol": "PAYC", "name": "Paycom", "price": 112.44 },
+ { "symbol": "NTRS", "name": "Northern Trust", "price": 138.26 },
+ { "symbol": "ADSK", "name": "Autodesk", "price": 232.08 },
+ { "symbol": "MSCI", "name": "MSCI", "price": 472.01 },
+ { "symbol": "ORCL", "name": "Oracle Corporation", "price": 168.14 },
+ { "symbol": "ERIE", "name": "Erie Indemnity", "price": 273.98 },
+ { "symbol": "TECH", "name": "Bio-Techne", "price": 59.22 },
+ { "symbol": "TRMB", "name": "Trimble Inc.", "price": 70.40 },
+ { "symbol": "EBAY", "name": "eBay", "price": 67.25 },
+ { "symbol": "INVH", "name": "Invitation Homes", "price": 26.09 },
+ { "symbol": "NDSN", "name": "Nordson Corporation", "price": 289.84 },
+ { "symbol": "DECK", "name": "Deckers Brands", "price": 114.76 },
+ { "symbol": "ADBE", "name": "Adobe Inc.", "price": 258.37 },
+ { "symbol": "SNPS", "name": "Synopsys", "price": 452.44 },
+ { "symbol": "CHTR", "name": "Charter Communications", "price": 270.87 },
+ { "symbol": "STLD", "name": "Steel Dynamics", "price": 193.65 },
+ { "symbol": "BIIB", "name": "Biogen", "price": 193.61 },
+ { "symbol": "TRGP", "name": "Targa Resources", "price": 242.36 },
+ { "symbol": "SOLV", "name": "Solventum", "price": 70.47 },
+ { "symbol": "TROW", "name": "T. Rowe Price", "price": 92.55 },
+ { "symbol": "AVGO", "name": "Broadcom", "price": 365.11 },
+ { "symbol": "CSCO", "name": "Cisco", "price": 75.74 },
+ { "symbol": "CTVA", "name": "Corteva", "price": 76.63 },
+ { "symbol": "EXPD", "name": "Expeditors International", "price": 169.73 },
+ { "symbol": "EXPE", "name": "Expedia Group", "price": 281.69 },
+ { "symbol": "AKAM", "name": "Akamai Technologies", "price": 85.09 },
+ { "symbol": "CBRE", "name": "CBRE Group", "price": 137.79 },
+ { "symbol": "FFIV", "name": "F5 Inc.", "price": 285.06 },
+ { "symbol": "MSFT", "name": "Microsoft", "price": 389.46 },
+ { "symbol": "COST", "name": "Costco", "price": 932.30 },
+ { "symbol": "NCLH", "name": "Norwegian Cruise Line Holdings", "price": 24.07 },
+ { "symbol": "KEYS", "name": "Keysight Technologies", "price": 207.44 },
+ { "symbol": "SPGI", "name": "S&P Global", "price": 426.67 },
+ { "symbol": "UBER", "name": "Uber", "price": 75.84 },
+ { "symbol": "BKNG", "name": "Booking Holdings", "price": 4386.71 },
+ { "symbol": "DELL", "name": "Dell Technologies", "price": 142.26 },
+ { "symbol": "DXCM", "name": "Dexcom", "price": 65.13 },
+ { "symbol": "PYPL", "name": "PayPal", "price": 32.31 },
+ { "symbol": "GOOG", "name": "Alphabet Inc. (Class C)", "price": 282.90 },
+ { "symbol": "BALL", "name": "Ball Corporation", "price": 60.67 },
+ { "symbol": "WELL", "name": "Welltower", "price": 194.82 },
+ { "symbol": "MNST", "name": "Monster Beverage", "price": 80.45 },
+ { "symbol": "OTIS", "name": "Otis Worldwide", "price": 84.53 },
+ { "symbol": "SWKS", "name": "Skyworks Solutions", "price": 63.13 },
+ { "symbol": "GRMN", "name": "Garmin", "price": 185.49 },
+ { "symbol": "WDAY", "name": "Workday Inc.", "price": 118.22 },
+ { "symbol": "APTV", "name": "Aptiv", "price": 83.68 },
+ { "symbol": "RVTY", "name": "Revvity", "price": 91.38 },
+ { "symbol": "TMUS", "name": "T-Mobile US", "price": 204.96 },
+ { "symbol": "LULU", "name": "Lululemon Athletica", "price": 167.54 },
+ { "symbol": "HOLX", "name": "Hologic", "price": 64.16 },
+ { "symbol": "NWSA", "name": "News Corp (Class A)", "price": 21.24 },
+ { "symbol": "PAYX", "name": "Paychex", "price": 89.52 },
+ { "symbol": "CDNS", "name": "Cadence Design Systems", "price": 295.12 },
+ { "symbol": "ALLE", "name": "Allegion", "price": 198.52 },
+ { "symbol": "GILD", "name": "Gilead Sciences", "price": 144.57 },
+ { "symbol": "EQIX", "name": "Equinix", "price": 932.33 },
+ { "symbol": "ISRG", "name": "Intuitive Surgical", "price": 590.38 }
]
}