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);