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 001ff85..beeb79d 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
@@ -2,6 +2,8 @@
import edu.ntnu.idi.idatt2003.g40.mappe.engine.Exchange;
import edu.ntnu.idi.idatt2003.g40.mappe.model.*;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.PurchaseCalculator;
+import edu.ntnu.idi.idatt2003.g40.mappe.service.SaleCalculator;
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;
@@ -77,6 +79,106 @@ public DashBoardController(final DashBoardView viewElement,
private void handleStockSelection(final Stock stock, final float amountOwned) {
getViewElement().setCurrentStock(stock, amountOwned);
getViewElement().updateGraph(selectedTimeRange);
+ updatePreviews();
+ }
+
+ /**
+ * Recalculates both the cost preview (for buying) and the
+ * sale preview (for selling) based on the currently selected
+ * stock's price and the value of the share quantity input
+ * field, and pushes the results to the view.
+ *
+ *
Uses {@link PurchaseCalculator} for the cost preview so it
+ * reflects the same rates that are applied when an actual
+ * purchase is committed (0.5% commission, no tax).
+ *
+ * Uses {@link SaleCalculator} for the sale preview, built on
+ * a {@link Share} that reuses the player's existing position
+ * (purchase price and capped quantity), so the calculated tax
+ * and net amount reflect what the player would actually receive
+ * if they sold right now. If the player owns no shares of the
+ * currently selected stock, the sale preview shows zero.
+ * */
+ private void updatePreviews() {
+ Stock current = getViewElement().getCurrentStock();
+ if (current == null) {
+ getViewElement().updateCostPreview(0f, 0f);
+ getViewElement().updateSalePreview(0f, 0f);
+ return;
+ }
+ String text = getViewElement().getQuantityInputField().getText();
+ if (!Validator.NOT_EMPTY.isValid(text)) {
+ getViewElement().updateCostPreview(0f, 0f);
+ getViewElement().updateSalePreview(0f, 0f);
+ return;
+ }
+ try {
+ BigDecimal quantity = new BigDecimal(text);
+ if (quantity.compareTo(BigDecimal.ZERO) <= 0) {
+ getViewElement().updateCostPreview(0f, 0f);
+ getViewElement().updateSalePreview(0f, 0f);
+ return;
+ }
+ updateCostPreview(current, quantity);
+ updateSalePreview(current, quantity);
+ } catch (IllegalArgumentException e) {
+ getViewElement().updateCostPreview(0f, 0f);
+ getViewElement().updateSalePreview(0f, 0f);
+ }
+ }
+
+ /**
+ * Computes and pushes the cost preview (total cost +
+ * commission) for buying the given quantity of the given
+ * stock at the current price.
+ *
+ * @param stock the stock to compute the cost for.
+ * @param quantity the amount of shares to buy.
+ * */
+ private void updateCostPreview(final Stock stock,
+ final BigDecimal quantity) {
+ Share previewShare = new Share(stock, quantity, stock.getSalesPrice());
+ PurchaseCalculator calc = new PurchaseCalculator(previewShare);
+ getViewElement().updateCostPreview(
+ calc.calculateTotal().floatValue(),
+ calc.calculateCommission().floatValue()
+ );
+ }
+
+ /**
+ * Computes and pushes the sale preview (net amount received
+ * + tax) for selling the given quantity of the given stock
+ * at the current price.
+ *
+ * Caps the requested quantity at the amount the player
+ * actually owns (mirroring the behavior in
+ * {@link Exchange#sell}). If the player owns nothing of
+ * the stock, the preview is set to zero.
+ *
+ * @param stock the stock to compute the sale for.
+ * @param quantity the amount of shares the player wants to sell.
+ * */
+ private void updateSalePreview(final Stock stock,
+ final BigDecimal quantity) {
+ List owned = player.getPortfolio().getShares(stock.getSymbol());
+ if (owned.isEmpty()) {
+ getViewElement().updateSalePreview(0f, 0f);
+ return;
+ }
+ Share ownedPosition = owned.getFirst();
+ BigDecimal sellQuantity = quantity.min(ownedPosition.getQuantity());
+ if (sellQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+ getViewElement().updateSalePreview(0f, 0f);
+ return;
+ }
+ Share previewShare = new Share(
+ stock, sellQuantity, ownedPosition.getPurchasePrice()
+ );
+ SaleCalculator calc = new SaleCalculator(previewShare);
+ getViewElement().updateSalePreview(
+ calc.calculateTotal().floatValue(),
+ calc.calculateTax().floatValue()
+ );
}
/**
@@ -136,6 +238,7 @@ protected void initInteractions() {
populateStockList("");
getViewElement().setCurrentStock(stockList.getFirst(), 0);
getViewElement().updateGraph(selectedTimeRange);
+ updatePreviews();
getViewElement().setOnAction(DashBoardActions.BUY_SHARES, () -> {
if (Validator.NOT_EMPTY.isValid(getViewElement().getQuantityInputField().getText())
&& Float.parseFloat(getViewElement().getQuantityInputField().getText()) > 0) {
@@ -147,6 +250,7 @@ protected void initInteractions() {
);
if (purchase.isCommited()) {
getViewElement().addOwnedShares(purchase.getShare().getQuantity().floatValue());
+ updatePreviews();
}
}
});
@@ -161,6 +265,7 @@ protected void initInteractions() {
if(sale.isCommited()) {
getViewElement().addOwnedShares(-sale.getShare().getQuantity().floatValue());
+ updatePreviews();
}
}
});
@@ -194,6 +299,7 @@ protected void initInteractions() {
exchange.weekProperty().addListener((observable,o,n) -> {
getViewElement().updateGraph(selectedTimeRange);
populateStockList(selectedFilter);
+ updatePreviews();
});
getViewElement().getQuantityInputField().setTextFormatter(new TextFormatter<>(change -> {
@@ -203,6 +309,10 @@ protected void initInteractions() {
return null;
}));
+ getViewElement().getQuantityInputField().textProperty().addListener((observable, o, n) -> {
+ updatePreviews();
+ });
+
getViewElement().getQuantityInputField().focusedProperty().addListener((observable, wasFocused, isNowFocused) -> {
if (!isNowFocused && getViewElement().getQuantityInputField().getText().trim().isEmpty()) {
getViewElement().getQuantityInputField().setText("1.0");
@@ -241,6 +351,7 @@ public void handleStockPoolUpdate(final List updatedStocks) {
.getTotalShareQuantityBySymbol(firstStock.getSymbol());
handleStockSelection(firstStock, ownedAmount.floatValue());
+ updatePreviews();
}
/**
@@ -268,5 +379,6 @@ public void handleEvent(final EventData data) {
);
}
+ updatePreviews();
}
}
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 d7edb2a..5304015 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
@@ -208,6 +208,32 @@ public final class DashBoardView extends ViewElement {
* */
private Label highPriceLabel;
+ /**
+ * The label showing the estimated cost of buying/selling
+ * the chosen quantity of shares at the current price.
+ * */
+ private Label costPreviewLabel;
+
+ /**
+ * The label showing the estimated commission and tax
+ * for the chosen quantity of shares at the current price.
+ * */
+ private Label feesPreviewLabel;
+
+ /**
+ * The label showing the estimated total amount received
+ * when selling the chosen quantity of shares at the
+ * current price (gross minus commission and tax).
+ * */
+ private Label saleTotalPreviewLabel;
+
+ /**
+ * The label showing the estimated tax that will be paid
+ * when selling the chosen quantity of shares at the
+ * current price.
+ * */
+ private Label saleTaxPreviewLabel;
+
/**
* Constructor.
* */
@@ -300,6 +326,11 @@ protected void initLayout() {
buySharesBtn = new Button("buy");
sellSharesBtn = new Button("sell");
+ costPreviewLabel = new Label("Cost: 0 NOK");
+ feesPreviewLabel = new Label("Commission: 0 NOK Tax: 0 NOK");
+ saleTotalPreviewLabel = new Label("Sale total: 0 NOK");
+ saleTaxPreviewLabel = new Label("Tax: 0 NOK");
+
grid = new GridPane();
grid.setHgap(0);
grid.setVgap(0);
@@ -325,8 +356,16 @@ protected void initLayout() {
HBox.setHgrow(buySharesBtn, Priority.ALWAYS);
HBox.setHgrow(sellSharesBtn, Priority.ALWAYS);
- grid.add(qtySection, 0, 0, 6,1);
- grid.add(tradeBtns, 0, 1, 6, 1);
+ grid.add(costPreviewLabel, 0, 0, 6, 1);
+ grid.add(feesPreviewLabel, 0, 1, 6, 1);
+ grid.add(qtySection, 0, 2, 6, 1);
+ grid.add(saleTotalPreviewLabel, 0, 3, 6, 1);
+ grid.add(saleTaxPreviewLabel, 0, 4, 6, 1);
+ grid.add(tradeBtns, 0, 5, 6, 1);
+ GridPane.setHalignment(costPreviewLabel, HPos.CENTER);
+ GridPane.setHalignment(feesPreviewLabel, HPos.CENTER);
+ GridPane.setHalignment(saleTotalPreviewLabel, HPos.CENTER);
+ GridPane.setHalignment(saleTaxPreviewLabel, HPos.CENTER);
HBox.setHgrow(stockIdentity, Priority.ALWAYS);
HBox.setHgrow(priceStats, Priority.ALWAYS);
@@ -382,6 +421,10 @@ protected void initStyling() {
rightQty.getStyleClass().add("dashboard-rightQty");
qtySection.getStyleClass().add("dashboard-qtySection");
tradeBtns.getStyleClass().add("dashboard-tradeBtns");
+ costPreviewLabel.getStyleClass().add("dashboard-cost-preview");
+ feesPreviewLabel.getStyleClass().add("dashboard-fees-preview");
+ saleTotalPreviewLabel.getStyleClass().add("dashboard-sale-preview");
+ saleTaxPreviewLabel.getStyleClass().add("dashboard-tax-preview");
timeRangeSelector.getStyleClass().add("dashboard-combo-box");
}
@@ -516,6 +559,45 @@ private void setHighPriceLabel(final float value) {
highPriceLabel.setText("High: " + Math.round(value * 100f) / 100f + " NOK");
}
+ /**
+ * Updates the cost preview labels, showing how much it will
+ * cost to buy the chosen amount of shares at the current
+ * stock price (gross + commission), as well as the
+ * commission part of the cost on its own.
+ *
+ * @param cost the estimated total cost in NOK
+ * (gross + commission).
+ * @param commission the estimated commission in NOK.
+ * */
+ public void updateCostPreview(final float cost,
+ final float commission) {
+ costPreviewLabel.setText("Cost: " + Math.round(cost * 100f) / 100f + " NOK");
+ feesPreviewLabel.setText(
+ "Commission: " + Math.round(commission * 100f) / 100f + " NOK"
+ );
+ }
+
+ /**
+ * Updates the sale preview labels, showing how much the
+ * player would receive on their account if they sold the
+ * chosen amount of currently owned shares right now
+ * (gross minus commission and tax), as well as the tax
+ * part of that calculation on its own.
+ *
+ * @param saleNet the estimated net amount received from
+ * the sale in NOK (gross - commission - tax).
+ * @param tax the estimated tax in NOK.
+ * */
+ public void updateSalePreview(final float saleNet,
+ final float tax) {
+ saleTotalPreviewLabel.setText(
+ "Sale total: " + Math.round(saleNet * 100f) / 100f + " NOK"
+ );
+ saleTaxPreviewLabel.setText(
+ "Tax: " + Math.round(tax * 100f) / 100f + " NOK"
+ );
+ }
+
/**
* Getter method for the search text field in the sidebar.
*
diff --git a/src/main/resources/saves/Newbie.json b/src/main/resources/saves/Newbie.json
index 6163131..9ce1a99 100644
--- a/src/main/resources/saves/Newbie.json
+++ b/src/main/resources/saves/Newbie.json
@@ -1,11 +1,12 @@
{
"name": "Newbie",
- "balance": 388.6825,
+ "balance": 11.2045,
"startingCapital": 10000.0,
"stockDataPath": null,
"week": 5,
"ownedShares": [
- { "symbol": "NVDA", "quantity": 50.0, "purchasePrice": 191.27 }
+ { "symbol": "NVDA", "quantity": 50.0, "purchasePrice": 191.27 },
+ { "symbol": "CARR", "quantity": 5.0, "purchasePrice": 75.12 }
],
"transactions": [
{ "type": "PURCHASE", "symbol": "NVDA", "quantity": 5.0, "price": 191.27, "week": 1 },
@@ -17,164 +18,166 @@
{ "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": "PURCHASE", "symbol": "CARR", "quantity": 1.0, "price": 75.12, "week": 5 },
+ { "type": "PURCHASE", "symbol": "CARR", "quantity": 4.0, "price": 75.12, "week": 5 }
],
"stocks": [
- { "symbol": "CARR", "name": "Carrier Global", "price": 68.59 },
- { "symbol": "AAPL", "name": "Apple Inc.", "price": 240.45 },
- { "symbol": "SNDK", "name": "Sandisk Corporation", "price": 740.83 },
- { "symbol": "WYNN", "name": "Wynn Resorts", "price": 111.25 },
- { "symbol": "TSCO", "name": "Tractor Supply", "price": 52.80 },
- { "symbol": "AMGN", "name": "Amgen", "price": 358.00 },
- { "symbol": "TSLA", "name": "Tesla Inc.", "price": 366.59 },
- { "symbol": "GDDY", "name": "GoDaddy", "price": 83.65 },
- { "symbol": "SBUX", "name": "Starbucks", "price": 105.29 },
- { "symbol": "KVUE", "name": "Kenvue", "price": 15.87 },
- { "symbol": "META", "name": "Meta Platforms", "price": 720.15 },
- { "symbol": "DLTR", "name": "Dollar Tree", "price": 169.51 },
- { "symbol": "ABBV", "name": "AbbVie", "price": 275.17 },
- { "symbol": "HUBB", "name": "Hubbell Incorporated", "price": 512.46 },
- { "symbol": "JKHY", "name": "Jack Henry & Associates", "price": 180.79 },
- { "symbol": "FSLR", "name": "First Solar", "price": 235.26 },
- { "symbol": "FTNT", "name": "Fortinet", "price": 101.07 },
- { "symbol": "EPAM", "name": "EPAM Systems", "price": 180.79 },
- { "symbol": "POOL", "name": "Pool Corporation", "price": 315.77 },
- { "symbol": "MCHP", "name": "Microchip Technology", "price": 67.75 },
- { "symbol": "VRSK", "name": "Verisk Analytics", "price": 174.19 },
- { "symbol": "MRNA", "name": "Moderna", "price": 31.99 },
- { "symbol": "HOOD", "name": "Robinhood Markets Inc.", "price": 51.69 },
- { "symbol": "VRSN", "name": "Verisign", "price": 231.93 },
- { "symbol": "AMAT", "name": "Applied Materials", "price": 400.38 },
- { "symbol": "MDLZ", "name": "Mondelez International", "price": 66.40 },
- { "symbol": "PCAR", "name": "Paccar", "price": 121.81 },
- { "symbol": "NDAQ", "name": "Nasdaq Inc.", "price": 79.17 },
- { "symbol": "INTU", "name": "Intuit", "price": 422.34 },
- { "symbol": "HSIC", "name": "Henry Schein", "price": 85.34 },
- { "symbol": "FISV", "name": "Fiserv Inc.", "price": 65.42 },
- { "symbol": "CSGP", "name": "CoStar Group", "price": 42.14 },
- { "symbol": "DDOG", "name": "Datadog", "price": 140.83 },
- { "symbol": "BLDR", "name": "Builders FirstSource", "price": 131.69 },
- { "symbol": "AXON", "name": "Axon Enterprise", "price": 496.46 },
- { "symbol": "ALGN", "name": "Align Technology", "price": 185.84 },
- { "symbol": "FICO", "name": "Fair Isaac", "price": 1531.67 },
- { "symbol": "FITB", "name": "Fifth Third Bancorp", "price": 54.20 },
- { "symbol": "NTAP", "name": "NetApp", "price": 112.35 },
- { "symbol": "FOXA", "name": "Fox Corporation (Class A)", "price": 58.78 },
- { "symbol": "QCOM", "name": "Qualcomm", "price": 152.02 },
- { "symbol": "VTRS", "name": "Viatris", "price": 17.02 },
- { "symbol": "LRCX", "name": "Lam Research", "price": 258.37 },
- { "symbol": "PLTR", "name": "Palantir Technologies", "price": 124.17 },
- { "symbol": "PANW", "name": "Palo Alto Networks", "price": 176.63 },
- { "symbol": "NFLX", "name": "Netflix", "price": 66.23 },
- { "symbol": "KLAC", "name": "KLA Corporation", "price": 1490.09 },
- { "symbol": "NVDA", "name": "Nvidia", "price": 203.67 },
- { "symbol": "IBKR", "name": "Interactive Brokers Group", "price": 63.52 },
- { "symbol": "CRWD", "name": "CrowdStrike", "price": 418.49 },
- { "symbol": "ULTA", "name": "Ulta Beauty", "price": 580.07 },
- { "symbol": "JBHT", "name": "J.B. Hunt", "price": 240.95 },
- { "symbol": "SMCI", "name": "Supermicro", "price": 32.34 },
- { "symbol": "NXPI", "name": "NXP Semiconductors", "price": 232.52 },
- { "symbol": "VRTX", "name": "Vertex Pharmaceuticals", "price": 461.97 },
- { "symbol": "MTCH", "name": "Match Group", "price": 31.01 },
- { "symbol": "CBOE", "name": "Cboe Global Markets", "price": 249.25 },
- { "symbol": "CPRT", "name": "Copart", "price": 40.68 },
- { "symbol": "VICI", "name": "Vici Properties", "price": 30.56 },
- { "symbol": "CHRW", "name": "C.H. Robinson", "price": 177.08 },
- { "symbol": "INTC", "name": "Intel", "price": 39.96 },
- { "symbol": "ROST", "name": "Ross Stores", "price": 201.01 },
- { "symbol": "GEHC", "name": "GE HealthCare", "price": 92.85 },
- { "symbol": "SCHW", "name": "Charles Schwab Corporation", "price": 81.80 },
- { "symbol": "CVNA", "name": "Carvana Co.", "price": 375.66 },
- { "symbol": "IDXX", "name": "Idexx Laboratories", "price": 872.55 },
- { "symbol": "INCY", "name": "Incyte", "price": 113.76 },
- { "symbol": "GNRC", "name": "Generac", "price": 213.47 },
- { "symbol": "CPAY", "name": "Corpay", "price": 395.18 },
- { "symbol": "REGN", "name": "Regeneron Pharmaceuticals", "price": 683.79 },
- { "symbol": "CTAS", "name": "Cintas", "price": 231.48 },
- { "symbol": "FAST", "name": "Fastenal", "price": 38.50 },
- { "symbol": "AMZN", "name": "Amazon", "price": 199.96 },
- { "symbol": "ZBRA", "name": "Zebra Technologies", "price": 273.76 },
- { "symbol": "ODFL", "name": "Old Dominion", "price": 187.76 },
- { "symbol": "TTWO", "name": "Take-Two Interactive", "price": 171.95 },
- { "symbol": "CTRA", "name": "Coterra", "price": 29.69 },
- { "symbol": "LDOS", "name": "Leidos", "price": 169.83 },
- { "symbol": "ARES", "name": "Ares Management Corporation", "price": 129.38 },
- { "symbol": "CINF", "name": "Cincinnati Financial", "price": 166.18 },
- { "symbol": "ANET", "name": "Arista Networks", "price": 145.62 },
- { "symbol": "AMCR", "name": "Amcor", "price": 42.20 },
- { "symbol": "HBAN", "name": "Huntington Bancshares", "price": 22.01 },
- { "symbol": "EVRG", "name": "Evergy", "price": 89.25 },
- { "symbol": "ABNB", "name": "Airbnb", "price": 116.35 },
- { "symbol": "DASH", "name": "DoorDash", "price": 162.34 },
- { "symbol": "COIN", "name": "Coinbase Global", "price": 136.11 },
- { "symbol": "CIEN", "name": "Ciena Corporation", "price": 241.53 },
- { "symbol": "FANG", "name": "Diamondback Energy", "price": 159.90 },
- { "symbol": "PSKY", "name": "Paramount Skydance Corp", "price": 10.08 },
- { "symbol": "ORLY", "name": "O'Reilly Auto Parts", "price": 88.49 },
- { "symbol": "SBAC", "name": "SBA Communications", "price": 200.89 },
- { "symbol": "ACGL", "name": "Arch Capital Group", "price": 92.91 },
- { "symbol": "CTSH", "name": "Cognizant", "price": 65.25 },
- { "symbol": "VLTO", "name": "Veralto", "price": 101.60 },
- { "symbol": "MPWR", "name": "Monolithic Power Systems", "price": 1111.92 },
- { "symbol": "PODD", "name": "Insulet Corporation", "price": 277.32 },
- { "symbol": "MRSH", "name": "Marsh & McLennan Companies Inc.", "price": 170.53 },
- { "symbol": "PAYC", "name": "Paycom", "price": 121.42 },
- { "symbol": "NTRS", "name": "Northern Trust", "price": 141.13 },
- { "symbol": "ADSK", "name": "Autodesk", "price": 221.31 },
- { "symbol": "MSCI", "name": "MSCI", "price": 407.02 },
- { "symbol": "ORCL", "name": "Oracle Corporation", "price": 183.95 },
- { "symbol": "ERIE", "name": "Erie Indemnity", "price": 344.39 },
- { "symbol": "TECH", "name": "Bio-Techne", "price": 51.89 },
- { "symbol": "TRMB", "name": "Trimble Inc.", "price": 69.10 },
- { "symbol": "EBAY", "name": "eBay", "price": 72.07 },
- { "symbol": "INVH", "name": "Invitation Homes", "price": 25.89 },
- { "symbol": "NDSN", "name": "Nordson Corporation", "price": 307.32 },
- { "symbol": "DECK", "name": "Deckers Brands", "price": 104.47 },
- { "symbol": "ADBE", "name": "Adobe Inc.", "price": 303.30 },
- { "symbol": "SNPS", "name": "Synopsys", "price": 453.75 },
- { "symbol": "CHTR", "name": "Charter Communications", "price": 307.39 },
- { "symbol": "STLD", "name": "Steel Dynamics", "price": 181.89 },
- { "symbol": "BIIB", "name": "Biogen", "price": 211.35 },
- { "symbol": "TRGP", "name": "Targa Resources", "price": 232.83 },
- { "symbol": "SOLV", "name": "Solventum", "price": 63.49 },
- { "symbol": "TROW", "name": "T. Rowe Price", "price": 95.44 },
- { "symbol": "AVGO", "name": "Broadcom", "price": 380.85 },
- { "symbol": "CSCO", "name": "Cisco", "price": 74.31 },
- { "symbol": "CTVA", "name": "Corteva", "price": 68.47 },
- { "symbol": "EXPD", "name": "Expeditors International", "price": 163.00 },
- { "symbol": "EXPE", "name": "Expedia Group", "price": 325.05 },
- { "symbol": "AKAM", "name": "Akamai Technologies", "price": 95.17 },
- { "symbol": "CBRE", "name": "CBRE Group", "price": 119.50 },
- { "symbol": "FFIV", "name": "F5 Inc.", "price": 278.60 },
- { "symbol": "MSFT", "name": "Microsoft", "price": 415.20 },
- { "symbol": "COST", "name": "Costco", "price": 934.12 },
- { "symbol": "NCLH", "name": "Norwegian Cruise Line Holdings", "price": 23.39 },
- { "symbol": "KEYS", "name": "Keysight Technologies", "price": 206.83 },
- { "symbol": "SPGI", "name": "S&P Global", "price": 412.77 },
- { "symbol": "UBER", "name": "Uber", "price": 79.67 },
- { "symbol": "BKNG", "name": "Booking Holdings", "price": 4282.77 },
- { "symbol": "DELL", "name": "Dell Technologies", "price": 146.30 },
- { "symbol": "DXCM", "name": "Dexcom", "price": 58.22 },
- { "symbol": "PYPL", "name": "PayPal", "price": 33.15 },
- { "symbol": "GOOG", "name": "Alphabet Inc. (Class C)", "price": 247.06 },
- { "symbol": "BALL", "name": "Ball Corporation", "price": 76.36 },
- { "symbol": "WELL", "name": "Welltower", "price": 201.33 },
- { "symbol": "MNST", "name": "Monster Beverage", "price": 78.98 },
- { "symbol": "OTIS", "name": "Otis Worldwide", "price": 89.40 },
- { "symbol": "SWKS", "name": "Skyworks Solutions", "price": 63.24 },
- { "symbol": "GRMN", "name": "Garmin", "price": 216.38 },
- { "symbol": "WDAY", "name": "Workday Inc.", "price": 101.25 },
- { "symbol": "APTV", "name": "Aptiv", "price": 86.79 },
- { "symbol": "RVTY", "name": "Revvity", "price": 80.62 },
- { "symbol": "TMUS", "name": "T-Mobile US", "price": 190.57 },
- { "symbol": "LULU", "name": "Lululemon Athletica", "price": 153.22 },
- { "symbol": "HOLX", "name": "Hologic", "price": 66.06 },
- { "symbol": "NWSA", "name": "News Corp (Class A)", "price": 19.59 },
- { "symbol": "PAYX", "name": "Paychex", "price": 91.49 },
- { "symbol": "CDNS", "name": "Cadence Design Systems", "price": 261.07 },
- { "symbol": "ALLE", "name": "Allegion", "price": 180.46 },
- { "symbol": "GILD", "name": "Gilead Sciences", "price": 149.07 },
- { "symbol": "EQIX", "name": "Equinix", "price": 901.41 },
- { "symbol": "ISRG", "name": "Intuitive Surgical", "price": 580.56 }
+ { "symbol": "CARR", "name": "Carrier Global", "price": 75.12 },
+ { "symbol": "AAPL", "name": "Apple Inc.", "price": 232.42 },
+ { "symbol": "SNDK", "name": "Sandisk Corporation", "price": 861.26 },
+ { "symbol": "WYNN", "name": "Wynn Resorts", "price": 97.54 },
+ { "symbol": "TSCO", "name": "Tractor Supply", "price": 53.32 },
+ { "symbol": "AMGN", "name": "Amgen", "price": 404.61 },
+ { "symbol": "TSLA", "name": "Tesla Inc.", "price": 360.17 },
+ { "symbol": "GDDY", "name": "GoDaddy", "price": 85.21 },
+ { "symbol": "SBUX", "name": "Starbucks", "price": 110.59 },
+ { "symbol": "KVUE", "name": "Kenvue", "price": 15.57 },
+ { "symbol": "META", "name": "Meta Platforms", "price": 707.00 },
+ { "symbol": "DLTR", "name": "Dollar Tree", "price": 175.45 },
+ { "symbol": "ABBV", "name": "AbbVie", "price": 258.94 },
+ { "symbol": "HUBB", "name": "Hubbell Incorporated", "price": 495.97 },
+ { "symbol": "JKHY", "name": "Jack Henry & Associates", "price": 169.66 },
+ { "symbol": "FSLR", "name": "First Solar", "price": 229.93 },
+ { "symbol": "FTNT", "name": "Fortinet", "price": 95.95 },
+ { "symbol": "EPAM", "name": "EPAM Systems", "price": 178.35 },
+ { "symbol": "POOL", "name": "Pool Corporation", "price": 318.43 },
+ { "symbol": "MCHP", "name": "Microchip Technology", "price": 65.59 },
+ { "symbol": "VRSK", "name": "Verisk Analytics", "price": 178.39 },
+ { "symbol": "MRNA", "name": "Moderna", "price": 31.43 },
+ { "symbol": "HOOD", "name": "Robinhood Markets Inc.", "price": 54.38 },
+ { "symbol": "VRSN", "name": "Verisign", "price": 233.77 },
+ { "symbol": "AMAT", "name": "Applied Materials", "price": 377.25 },
+ { "symbol": "MDLZ", "name": "Mondelez International", "price": 65.31 },
+ { "symbol": "PCAR", "name": "Paccar", "price": 115.13 },
+ { "symbol": "NDAQ", "name": "Nasdaq Inc.", "price": 83.12 },
+ { "symbol": "INTU", "name": "Intuit", "price": 440.63 },
+ { "symbol": "HSIC", "name": "Henry Schein", "price": 91.95 },
+ { "symbol": "FISV", "name": "Fiserv Inc.", "price": 59.88 },
+ { "symbol": "CSGP", "name": "CoStar Group", "price": 42.70 },
+ { "symbol": "DDOG", "name": "Datadog", "price": 146.05 },
+ { "symbol": "BLDR", "name": "Builders FirstSource", "price": 128.46 },
+ { "symbol": "AXON", "name": "Axon Enterprise", "price": 504.02 },
+ { "symbol": "ALGN", "name": "Align Technology", "price": 183.45 },
+ { "symbol": "FICO", "name": "Fair Isaac", "price": 1520.04 },
+ { "symbol": "FITB", "name": "Fifth Third Bancorp", "price": 51.73 },
+ { "symbol": "NTAP", "name": "NetApp", "price": 120.48 },
+ { "symbol": "FOXA", "name": "Fox Corporation (Class A)", "price": 55.61 },
+ { "symbol": "QCOM", "name": "Qualcomm", "price": 141.80 },
+ { "symbol": "VTRS", "name": "Viatris", "price": 17.43 },
+ { "symbol": "LRCX", "name": "Lam Research", "price": 248.71 },
+ { "symbol": "PLTR", "name": "Palantir Technologies", "price": 131.78 },
+ { "symbol": "PANW", "name": "Palo Alto Networks", "price": 184.16 },
+ { "symbol": "NFLX", "name": "Netflix", "price": 65.49 },
+ { "symbol": "KLAC", "name": "KLA Corporation", "price": 1443.99 },
+ { "symbol": "NVDA", "name": "Nvidia", "price": 179.79 },
+ { "symbol": "IBKR", "name": "Interactive Brokers Group", "price": 71.52 },
+ { "symbol": "CRWD", "name": "CrowdStrike", "price": 411.42 },
+ { "symbol": "ULTA", "name": "Ulta Beauty", "price": 575.53 },
+ { "symbol": "JBHT", "name": "J.B. Hunt", "price": 232.28 },
+ { "symbol": "SMCI", "name": "Supermicro", "price": 33.83 },
+ { "symbol": "NXPI", "name": "NXP Semiconductors", "price": 219.91 },
+ { "symbol": "VRTX", "name": "Vertex Pharmaceuticals", "price": 528.78 },
+ { "symbol": "MTCH", "name": "Match Group", "price": 32.55 },
+ { "symbol": "CBOE", "name": "Cboe Global Markets", "price": 252.98 },
+ { "symbol": "CPRT", "name": "Copart", "price": 42.35 },
+ { "symbol": "VICI", "name": "Vici Properties", "price": 30.53 },
+ { "symbol": "CHRW", "name": "C.H. Robinson", "price": 194.63 },
+ { "symbol": "INTC", "name": "Intel", "price": 39.70 },
+ { "symbol": "ROST", "name": "Ross Stores", "price": 204.91 },
+ { "symbol": "GEHC", "name": "GE HealthCare", "price": 85.26 },
+ { "symbol": "SCHW", "name": "Charles Schwab Corporation", "price": 80.90 },
+ { "symbol": "CVNA", "name": "Carvana Co.", "price": 356.72 },
+ { "symbol": "IDXX", "name": "Idexx Laboratories", "price": 864.02 },
+ { "symbol": "INCY", "name": "Incyte", "price": 116.33 },
+ { "symbol": "GNRC", "name": "Generac", "price": 218.82 },
+ { "symbol": "CPAY", "name": "Corpay", "price": 416.82 },
+ { "symbol": "REGN", "name": "Regeneron Pharmaceuticals", "price": 628.99 },
+ { "symbol": "CTAS", "name": "Cintas", "price": 213.98 },
+ { "symbol": "FAST", "name": "Fastenal", "price": 39.25 },
+ { "symbol": "AMZN", "name": "Amazon", "price": 221.21 },
+ { "symbol": "ZBRA", "name": "Zebra Technologies", "price": 289.08 },
+ { "symbol": "ODFL", "name": "Old Dominion", "price": 180.38 },
+ { "symbol": "TTWO", "name": "Take-Two Interactive", "price": 158.67 },
+ { "symbol": "CTRA", "name": "Coterra", "price": 32.93 },
+ { "symbol": "LDOS", "name": "Leidos", "price": 166.54 },
+ { "symbol": "ARES", "name": "Ares Management Corporation", "price": 120.77 },
+ { "symbol": "CINF", "name": "Cincinnati Financial", "price": 154.99 },
+ { "symbol": "ANET", "name": "Arista Networks", "price": 139.90 },
+ { "symbol": "AMCR", "name": "Amcor", "price": 42.97 },
+ { "symbol": "HBAN", "name": "Huntington Bancshares", "price": 21.94 },
+ { "symbol": "EVRG", "name": "Evergy", "price": 85.83 },
+ { "symbol": "ABNB", "name": "Airbnb", "price": 109.68 },
+ { "symbol": "DASH", "name": "DoorDash", "price": 149.25 },
+ { "symbol": "COIN", "name": "Coinbase Global", "price": 145.35 },
+ { "symbol": "CIEN", "name": "Ciena Corporation", "price": 235.39 },
+ { "symbol": "FANG", "name": "Diamondback Energy", "price": 150.66 },
+ { "symbol": "PSKY", "name": "Paramount Skydance Corp", "price": 9.44 },
+ { "symbol": "ORLY", "name": "O'Reilly Auto Parts", "price": 92.14 },
+ { "symbol": "SBAC", "name": "SBA Communications", "price": 220.40 },
+ { "symbol": "ACGL", "name": "Arch Capital Group", "price": 87.91 },
+ { "symbol": "CTSH", "name": "Cognizant", "price": 60.15 },
+ { "symbol": "VLTO", "name": "Veralto", "price": 110.53 },
+ { "symbol": "MPWR", "name": "Monolithic Power Systems", "price": 1094.81 },
+ { "symbol": "PODD", "name": "Insulet Corporation", "price": 261.32 },
+ { "symbol": "MRSH", "name": "Marsh & McLennan Companies Inc.", "price": 156.59 },
+ { "symbol": "PAYC", "name": "Paycom", "price": 133.30 },
+ { "symbol": "NTRS", "name": "Northern Trust", "price": 140.60 },
+ { "symbol": "ADSK", "name": "Autodesk", "price": 229.35 },
+ { "symbol": "MSCI", "name": "MSCI", "price": 383.57 },
+ { "symbol": "ORCL", "name": "Oracle Corporation", "price": 175.34 },
+ { "symbol": "ERIE", "name": "Erie Indemnity", "price": 329.21 },
+ { "symbol": "TECH", "name": "Bio-Techne", "price": 51.66 },
+ { "symbol": "TRMB", "name": "Trimble Inc.", "price": 71.90 },
+ { "symbol": "EBAY", "name": "eBay", "price": 78.21 },
+ { "symbol": "INVH", "name": "Invitation Homes", "price": 25.62 },
+ { "symbol": "NDSN", "name": "Nordson Corporation", "price": 310.61 },
+ { "symbol": "DECK", "name": "Deckers Brands", "price": 108.29 },
+ { "symbol": "ADBE", "name": "Adobe Inc.", "price": 275.09 },
+ { "symbol": "SNPS", "name": "Synopsys", "price": 424.09 },
+ { "symbol": "CHTR", "name": "Charter Communications", "price": 311.42 },
+ { "symbol": "STLD", "name": "Steel Dynamics", "price": 180.50 },
+ { "symbol": "BIIB", "name": "Biogen", "price": 210.90 },
+ { "symbol": "TRGP", "name": "Targa Resources", "price": 243.04 },
+ { "symbol": "SOLV", "name": "Solventum", "price": 57.18 },
+ { "symbol": "TROW", "name": "T. Rowe Price", "price": 103.71 },
+ { "symbol": "AVGO", "name": "Broadcom", "price": 361.04 },
+ { "symbol": "CSCO", "name": "Cisco", "price": 78.72 },
+ { "symbol": "CTVA", "name": "Corteva", "price": 75.55 },
+ { "symbol": "EXPD", "name": "Expeditors International", "price": 164.36 },
+ { "symbol": "EXPE", "name": "Expedia Group", "price": 320.19 },
+ { "symbol": "AKAM", "name": "Akamai Technologies", "price": 98.72 },
+ { "symbol": "CBRE", "name": "CBRE Group", "price": 123.63 },
+ { "symbol": "FFIV", "name": "F5 Inc.", "price": 290.99 },
+ { "symbol": "MSFT", "name": "Microsoft", "price": 392.30 },
+ { "symbol": "COST", "name": "Costco", "price": 904.79 },
+ { "symbol": "NCLH", "name": "Norwegian Cruise Line Holdings", "price": 23.90 },
+ { "symbol": "KEYS", "name": "Keysight Technologies", "price": 195.34 },
+ { "symbol": "SPGI", "name": "S&P Global", "price": 467.26 },
+ { "symbol": "UBER", "name": "Uber", "price": 74.73 },
+ { "symbol": "BKNG", "name": "Booking Holdings", "price": 4604.23 },
+ { "symbol": "DELL", "name": "Dell Technologies", "price": 137.42 },
+ { "symbol": "DXCM", "name": "Dexcom", "price": 59.60 },
+ { "symbol": "PYPL", "name": "PayPal", "price": 29.98 },
+ { "symbol": "GOOG", "name": "Alphabet Inc. (Class C)", "price": 247.04 },
+ { "symbol": "BALL", "name": "Ball Corporation", "price": 79.65 },
+ { "symbol": "WELL", "name": "Welltower", "price": 205.91 },
+ { "symbol": "MNST", "name": "Monster Beverage", "price": 80.26 },
+ { "symbol": "OTIS", "name": "Otis Worldwide", "price": 84.99 },
+ { "symbol": "SWKS", "name": "Skyworks Solutions", "price": 65.09 },
+ { "symbol": "GRMN", "name": "Garmin", "price": 201.12 },
+ { "symbol": "WDAY", "name": "Workday Inc.", "price": 99.40 },
+ { "symbol": "APTV", "name": "Aptiv", "price": 79.90 },
+ { "symbol": "RVTY", "name": "Revvity", "price": 88.91 },
+ { "symbol": "TMUS", "name": "T-Mobile US", "price": 188.82 },
+ { "symbol": "LULU", "name": "Lululemon Athletica", "price": 150.36 },
+ { "symbol": "HOLX", "name": "Hologic", "price": 60.47 },
+ { "symbol": "NWSA", "name": "News Corp (Class A)", "price": 19.11 },
+ { "symbol": "PAYX", "name": "Paychex", "price": 88.93 },
+ { "symbol": "CDNS", "name": "Cadence Design Systems", "price": 269.75 },
+ { "symbol": "ALLE", "name": "Allegion", "price": 187.22 },
+ { "symbol": "GILD", "name": "Gilead Sciences", "price": 152.35 },
+ { "symbol": "EQIX", "name": "Equinix", "price": 898.66 },
+ { "symbol": "ISRG", "name": "Intuitive Surgical", "price": 563.46 }
]
}
diff --git a/src/main/resources/styles.css b/src/main/resources/styles.css
index b6b16ef..60c21b6 100644
--- a/src/main/resources/styles.css
+++ b/src/main/resources/styles.css
@@ -718,10 +718,6 @@
-fx-background-color: transparent;
}
-.dashboard-chart .axis-label {
- -fx-text-fill: #ffffff;
-}
-
/* JavaFX charts use these inner classes for the plot area and grid. */
.chart {
-fx-background-color: transparent;
@@ -785,6 +781,45 @@
-fx-alignment: CENTER;
}
+/* Cost preview label, shown above the quantity input. Displays
+ the estimated total NOK cost (gross + commission) of the trade
+ based on the current stock price and the entered quantity. */
+.dashboard-cost-preview {
+ -fx-text-fill: #cdd5ed;
+ -fx-font-size: 17px;
+ -fx-font-weight: bold;
+ -fx-padding: 4 0 2 0;
+}
+
+/* Fees preview label, shown right under the cost. Displays the
+ commission part of the total cost as a smaller breakdown. */
+.dashboard-fees-preview {
+ -fx-text-fill: #cdd5ed;
+ -fx-font-size: 13px;
+ -fx-padding: 0 0 4 0;
+}
+
+/* Sale preview label, shown below the quantity input. Displays
+ the estimated net NOK amount the player would receive on their
+ account if they sold the entered quantity of currently owned
+ shares right now (gross - commission - tax). Mirrors the
+ cost preview above. */
+.dashboard-sale-preview {
+ -fx-text-fill: #cdd5ed;
+ -fx-font-size: 17px;
+ -fx-font-weight: bold;
+ -fx-padding: 4 0 2 0;
+}
+
+/* Tax preview label, shown right under the sale preview. Displays
+ the estimated tax part of a potential sale as a smaller breakdown.
+ Mirrors the fees preview above. */
+.dashboard-tax-preview {
+ -fx-text-fill: #cdd5ed;
+ -fx-font-size: 13px;
+ -fx-padding: 0 0 4 0;
+}
+
/* ========================================================
IN-GAME : MARKET VIEW
======================================================== */
@@ -1881,6 +1916,22 @@
-fx-text-fill: #2a3654;
}
+.light-mode .dashboard-cost-preview {
+ -fx-text-fill: #2a3654;
+}
+
+.light-mode .dashboard-fees-preview {
+ -fx-text-fill: #2a3654;
+}
+
+.light-mode .dashboard-sale-preview {
+ -fx-text-fill: #2a3654;
+}
+
+.light-mode .dashboard-tax-preview {
+ -fx-text-fill: #2a3654;
+}
+
.light-mode .dashboard-stock-button {
-fx-background-color: #eef3fa;
-fx-border-color: rgba(10, 132, 217, 0.18);
@@ -1927,10 +1978,6 @@
-fx-border-color: #0a84d9;
}
-.light-mode .dashboard-chart .axis-label {
- -fx-text-fill: #0f1b34;
-}
-
.light-mode .dashboard-qtyTextField {
-fx-background-color: #eef3fa;
-fx-border-color: rgba(10, 132, 217, 0.35);