From 411c0b36ec2ab7f9a447cede24d3236d2b7b5b1c Mon Sep 17 00:00:00 2001 From: EspenTinius Date: Wed, 27 May 2026 00:11:40 +0200 Subject: [PATCH 1/2] 10 desimaler --- .../edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java index bfeaad4..16da1ea 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java @@ -331,8 +331,11 @@ public void advance() { stock.setFortune(0); BigDecimal factor = BigDecimal.ONE.add(change); + // Keep full simulation precision at 10 decimals. The UI is free + // to round for display, but the underlying numbers stay accurate + // so the chart and net-worth do not drift over many weeks. BigDecimal newPrice = currentPrice.multiply(factor) - .setScale(2, java.math.RoundingMode.HALF_UP); + .setScale(10, java.math.RoundingMode.HALF_UP); stock.addNewSalesPrice(newPrice); } week.set(week.get() + 1); From a52a8519f51c506eb2635d3c988c8880b12d56c2 Mon Sep 17 00:00:00 2001 From: EspenTinius Date: Wed, 27 May 2026 00:16:56 +0200 Subject: [PATCH 2/2] s --- .../idatt2003/g40/mappe/engine/Exchange.java | 199 +++++++++--------- 1 file changed, 101 insertions(+), 98 deletions(-) diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java index 16da1ea..c4d5dcd 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/engine/Exchange.java @@ -19,51 +19,57 @@ /** * Represents a stock exchange where stocks can be traded. * - *

Holds a map of {@link Stock} objects where stock symbol is key and - * stock is value.

+ *

+ * Holds a map of {@link Stock} objects where stock symbol is key and + * stock is value. + *

* - *

Delegates buying and selling to player elements using calculators

+ *

+ * Delegates buying and selling to player elements using calculators + *

* - *

Additionally controls the time in weeks, and therefore has the main - * responsibility for advancing weeks.

+ *

+ * Additionally controls the time in weeks, and therefore has the main + * responsibility for advancing weeks. + *

* * @see Player * @see edu.ntnu.idi.idatt2003.g40.mappe.service.TransactionCalculator * * @version 1.1.0 - * */ + */ public final class Exchange { /** * Exchange name. - * */ + */ private final String name; /** * Current week (set to 1 in constructor). - * */ + */ private final ReadOnlyIntegerWrapper week = new ReadOnlyIntegerWrapper(1); /** * Map of {@link Stock} objects. Key is stock symbol. Value is stock. - * */ + */ private final Map stockMap; /** * Random value determining week changes. - * */ + */ private final Random random; /** * Constructor. * - * @param name name of exchange. - * @param stocks list of {@link Stock} objects. + * @param name name of exchange. + * @param stocks list of {@link Stock} objects. * * @throws IllegalArgumentException if name or stocks are empty/null. - * */ + */ public Exchange(final String name, final List stocks) - throws IllegalArgumentException { + throws IllegalArgumentException { if (!Validator.NOT_EMPTY.isValid(name) || stocks == null || stocks.isEmpty()) { @@ -81,7 +87,7 @@ public Exchange(final String name, final List stocks) * Getter method for name. * * @return name of exchange. - * */ + */ public String getName() { return name; } @@ -90,7 +96,7 @@ public String getName() { * Getter method for current week. * * @return week. - * */ + */ public int getWeek() { return week.get(); } @@ -99,7 +105,7 @@ public int getWeek() { * Getter method for the {@link ReadOnlyIntegerProperty} object of week. * * @return week. - * */ + */ public ReadOnlyIntegerProperty weekProperty() { return week.getReadOnlyProperty(); } @@ -117,7 +123,7 @@ public ReadOnlyIntegerProperty weekProperty() { * @param newWeek the value to set the week to. * * @throws IllegalArgumentException if newWeek is below 1. - * */ + */ public void setWeek(final int newWeek) throws IllegalArgumentException { if (newWeek < 1) { throw new IllegalArgumentException("Week must be at least 1!"); @@ -140,7 +146,7 @@ public void setWeek(final int newWeek) throws IllegalArgumentException { * @param baselinePrices map of symbol to the price to seed with. * Symbols that aren't on this exchange are * skipped. - * */ + */ public void resetStocksTo(final Map baselinePrices) { if (baselinePrices == null) { return; @@ -158,8 +164,8 @@ public void resetStocksTo(final Map baselinePrices) { * * @param symbol the stock symbol. * - * @return true or false. - * */ + * @return true or false. + */ public boolean hasStock(final String symbol) { return stockMap.containsKey(symbol); } @@ -168,7 +174,7 @@ public boolean hasStock(final String symbol) { * Getter method for all stocks in exchange. * * @return List of stocks. - * */ + */ public List getStocks() { return List.copyOf(this.stockMap.values()); } @@ -176,18 +182,18 @@ public List getStocks() { /** * Getter method for stock element. * - * @param symbol the symbol of the stock to get. + * @param symbol the symbol of the stock to get. * - * @return {@link Stock} element gotten. + * @return {@link Stock} element gotten. * * @throws IllegalArgumentException if symbol is invalid or not in exchange. - * */ + */ public Stock getStock(final String symbol) - throws IllegalArgumentException { + throws IllegalArgumentException { if (!Validator.VALID_STOCK_SYMBOL.isValid(symbol) || !stockMap.containsKey(symbol)) { throw new IllegalArgumentException( - Validator.VALID_STOCK_SYMBOL.getErrorMessage()); + Validator.VALID_STOCK_SYMBOL.getErrorMessage()); } return stockMap.get(symbol); } @@ -197,14 +203,14 @@ public Stock getStock(final String symbol) * * @param searchTerm the term to search for. * - * @return a list of {@link Stock} objects. - * */ + * @return a list of {@link Stock} objects. + */ public List findStocks(final String searchTerm) { List result = new ArrayList<>(); for (Stock stock : stockMap.values()) { if (stock.getSymbol().toLowerCase() - .contains(searchTerm.toLowerCase()) - || stock.getCompany().toLowerCase() + .contains(searchTerm.toLowerCase()) + || stock.getCompany().toLowerCase() .contains(searchTerm.toLowerCase())) { result.add(stock); } @@ -215,17 +221,17 @@ public List findStocks(final String searchTerm) { /** * Method called when a player buys a stock. * - * @param symbol the stock this player buys. - * @param quantity the amount of stock to buy. - * @param player the player buying stock. + * @param symbol the stock this player buys. + * @param quantity the amount of stock to buy. + * @param player the player buying stock. * - * @return Transaction representing the transaction. + * @return Transaction representing the transaction. * * @throws IllegalArgumentException if symbol or player is invalid. - * */ + */ public Transaction buy(final String symbol, - final BigDecimal quantity, - final Player player) throws IllegalArgumentException { + final BigDecimal quantity, + final Player player) throws IllegalArgumentException { if (!Validator.VALID_STOCK_SYMBOL.isValid(symbol) || quantity == null || player == null) { @@ -234,8 +240,7 @@ public Transaction buy(final String symbol, Stock stock = getStock(symbol); Share share = new Share(stock, quantity, stock.getSalesPrice()); Transaction purchase = TransactionFactory.createTransaction( - TransactionType.PURCHASE, share, getWeek() - ); + TransactionType.PURCHASE, share, getWeek()); player.handleTransaction(purchase); return purchase; } @@ -243,21 +248,20 @@ TransactionType.PURCHASE, share, getWeek() /** * Method called when a player sells share. * - * @param share the share to sell. - * @param player the player buying stock. + * @param share the share to sell. + * @param player the player buying stock. * - * @return Transaction representing the transaction. + * @return Transaction representing the transaction. * * @throws IllegalArgumentException if share or player is null. - * */ + */ public Transaction sell(final Share share, final Player player) - throws IllegalArgumentException { + throws IllegalArgumentException { if (share == null || player == null) { throw new IllegalArgumentException("Invalid sell!"); } Transaction sale = TransactionFactory.createTransaction( - TransactionType.SALE, share, getWeek() - ); + TransactionType.SALE, share, getWeek()); player.handleTransaction(sale); return sale; } @@ -266,26 +270,28 @@ TransactionType.SALE, share, getWeek() * Method called when a player sells share, * defined by an amount instead of specific {@link Share} object. * - *

{@link edu.ntnu.idi.idatt2003.g40.mappe.model.Portfolio}

+ *

+ * {@link edu.ntnu.idi.idatt2003.g40.mappe.model.Portfolio} + *

* * @param amount the amount of "shares" to sell. * @param stockSymbol the stock to sell shares in. * @param player the player buying stock. * - * @return List of transactions commited to sell the shares. + * @return List of transactions commited to sell the shares. * * @throws IllegalArgumentException if any parameter is null, * or if player does not have enough shares, * or if player does not own any shares * of the given stock. - * */ + */ public Transaction sell(BigDecimal amount, - final String stockSymbol, - final Player player) - throws IllegalArgumentException { + final String stockSymbol, + final Player player) + throws IllegalArgumentException { if (amount == null - || player == null - || !Validator.VALID_STOCK_SYMBOL.isValid(stockSymbol)) { + || player == null + || !Validator.VALID_STOCK_SYMBOL.isValid(stockSymbol)) { throw new IllegalArgumentException("Invalid sell parameters!"); } @@ -306,8 +312,7 @@ public Transaction sell(BigDecimal amount, Share shareToSell = new Share(stock, amount, stock.getSalesPrice()); Transaction sale = TransactionFactory.createTransaction( - TransactionType.SALE, shareToSell, getWeek() - ); + TransactionType.SALE, shareToSell, getWeek()); player.handleTransaction(sale); return sale; @@ -316,26 +321,26 @@ TransactionType.SALE, shareToSell, getWeek() /** * Method for advancing time, increasing the amount of weeks. * - *

Applies a random price change from -5% to 5% to every stock, + *

+ * Applies a random price change from -5% to 5% to every stock, * plus a flat percent determined by their fortune, that can range from - * -10% to +10%.

+ * -10% to +10%. + *

* * @see edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.GameEngineView - * */ + */ public void advance() { for (Stock stock : stockMap.values()) { BigDecimal currentPrice = stock.getSalesPrice(); BigDecimal change = BigDecimal.valueOf(random.nextDouble() * 0.10 - 0.05) - .add(BigDecimal.valueOf(stock.getFortune())); + .add(BigDecimal.valueOf(stock.getFortune())); stock.setFortune(0); BigDecimal factor = BigDecimal.ONE.add(change); - // Keep full simulation precision at 10 decimals. The UI is free - // to round for display, but the underlying numbers stay accurate - // so the chart and net-worth do not drift over many weeks. + // Keep full simulation precision at 10 decimals. BigDecimal newPrice = currentPrice.multiply(factor) - .setScale(10, java.math.RoundingMode.HALF_UP); + .setScale(10, java.math.RoundingMode.HALF_UP); stock.addNewSalesPrice(newPrice); } week.set(week.get() + 1); @@ -345,31 +350,29 @@ public void advance() { * Method for getting the stocks with the most * amount of increase since last week. * - * @param limit the maximum amount of stocks returned + * @param limit the maximum amount of stocks returned * * @return list of {@link Stock} objects. * * @throws IllegalArgumentException if limit is invalid (negative or zero). - * */ + */ public List getGainers(final int limit) - throws IllegalArgumentException { + throws IllegalArgumentException { if (limit < 1) { throw new IllegalArgumentException("Invalid limit for getting gainers!"); } return stockMap.entrySet().stream() - // We only want the stocks with a positive price change. - .filter(e -> - e.getValue().getLatestPriceChange() - .compareTo(BigDecimal.ZERO) > 0) - // We sort the stocks based on the price change. - .sorted((e1, e2) -> - e2.getValue().getLatestPriceChange() - .compareTo(e1.getValue().getLatestPriceChange())) - // Sets a limit to the stream. - .limit(limit) - .map(Map.Entry::getValue) - // Converts to a list - .toList(); + // We only want the stocks with a positive price change. + .filter(e -> e.getValue().getLatestPriceChange() + .compareTo(BigDecimal.ZERO) > 0) + // We sort the stocks based on the price change. + .sorted((e1, e2) -> e2.getValue().getLatestPriceChange() + .compareTo(e1.getValue().getLatestPriceChange())) + // Sets a limit to the stream. + .limit(limit) + .map(Map.Entry::getValue) + // Converts to a list + .toList(); } /** @@ -381,34 +384,34 @@ public List getGainers(final int limit) * @return list of {@link Stock} objects. * * @throws IllegalArgumentException if limit is invalid (negative or zero). - * */ + */ public List getLosers(final int limit) - throws IllegalArgumentException { + throws IllegalArgumentException { if (limit < 1) { throw new IllegalArgumentException("Invalid limit for getting losers!"); } return stockMap.entrySet().stream() - // Only get entries with negative price change. - .filter(e -> - e.getValue().getLatestPriceChange() - .compareTo(BigDecimal.ZERO) < 0) - // Sort (lowest first) - .sorted((e1, e2) -> - e1.getValue().getLatestPriceChange() - .compareTo(e2.getValue().getLatestPriceChange())) - .limit(limit) - .map(Map.Entry::getValue) - .toList(); + // Only get entries with negative price change. + .filter(e -> e.getValue().getLatestPriceChange() + .compareTo(BigDecimal.ZERO) < 0) + // Sort (lowest first) + .sorted((e1, e2) -> e1.getValue().getLatestPriceChange() + .compareTo(e2.getValue().getLatestPriceChange())) + .limit(limit) + .map(Map.Entry::getValue) + .toList(); } /** * Replaces list of stocks with a new list. * - *

Used when loading a save game that uses a completely different set of - * stocks than the currently active simulation context.

+ *

+ * Used when loading a save game that uses a completely different set of + * stocks than the currently active simulation context. + *

* - * @param newStocks the new list of {@link Stock} - * objects to list on the exchange. + * @param newStocks the new list of {@link Stock} + * objects to list on the exchange. * @throws IllegalArgumentException if the provided list is null or empty. */ public void updateStockPool(final List newStocks) throws IllegalArgumentException {