diff --git a/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java b/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java index cb1dec2057c..87372ba4ea8 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java @@ -61,6 +61,7 @@ import javafx.util.StringConverter; +import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.OffsetDateTime; @@ -77,8 +78,10 @@ import java.util.Map; import java.util.Set; import java.util.Spliterators.AbstractSpliterator; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -88,9 +91,6 @@ import static bisq.desktop.util.FormBuilder.addTitledGroupBg; import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField; - -import java.sql.Date; - @FxmlView public class SupplyView extends ActivatableView implements DaoStateListener { @@ -110,7 +110,7 @@ public class SupplyView extends ActivatableView implements DaoSt private XYChart.Series seriesBSQIssuedMonthly2; - private ListChangeListener changeListenerBSQBurntDaily; + private ListChangeListener> changeListenerBSQBurntDaily; private NumberAxis yAxisBSQBurntDaily; private ToggleButton zoomToInliersSlide; @@ -194,22 +194,19 @@ private void initializeSeries() { var burntLabel = Res.get("dao.factsAndFigures.supply.burnt"); seriesBSQIssuedMonthly = new XYChart.Series<>(); - var issuedMonthlyLabel = issuedLabel; - seriesBSQIssuedMonthly.setName(issuedMonthlyLabel); + seriesBSQIssuedMonthly.setName(issuedLabel); // Because Series cannot be reused in multiple charts, we create a // "second" Series and populate it at the same time as the original. // Some other solutions: https://stackoverflow.com/questions/49770442 seriesBSQIssuedMonthly2 = new XYChart.Series<>(); - seriesBSQIssuedMonthly2.setName(issuedMonthlyLabel); + seriesBSQIssuedMonthly2.setName(issuedLabel); seriesBSQBurntMonthly = new XYChart.Series<>(); - var burntMonthlyLabel = burntLabel; - seriesBSQBurntMonthly.setName(burntMonthlyLabel); + seriesBSQBurntMonthly.setName(burntLabel); seriesBSQBurntDaily = new XYChart.Series<>(); - var burntDailyLabel = burntLabel; - seriesBSQBurntDaily.setName(burntDailyLabel); + seriesBSQBurntDaily.setName(burntLabel); seriesBSQBurntDailyMA = new XYChart.Series<>(); var burntMALabel = Res.get("dao.factsAndFigures.supply.burntMovingAverage"); @@ -223,21 +220,20 @@ private void createSupplyIncreasedVsDecreasedInformation() { var chartPane = wrapInChartPane(chart); - addToTopMargin(chartPane, Layout.COMPACT_FIRST_ROW_DISTANCE); + addToTopMargin(chartPane); root.getChildren().add(chartPane); } - private void addToTopMargin(Node child, double amount) { + private void addToTopMargin(Node child) { var margin = GridPane.getMargin(child); - var new_insets = - new Insets( - margin.getTop() + amount, - margin.getRight(), - margin.getBottom(), - margin.getLeft() - ); + var new_insets = new Insets( + margin.getTop() + Layout.COMPACT_FIRST_ROW_DISTANCE, + margin.getRight(), + margin.getBottom(), + margin.getLeft() + ); GridPane.setMargin(child, new_insets); } @@ -318,7 +314,7 @@ private Node createBSQIssuedVsBurntChart( configureChart(chart); chart.setCreateSymbols(false); - chart.getData().addAll(seriesBSQIssuedMonthly, seriesBSQBurntMonthly); + chart.getData().addAll(List.of(seriesBSQIssuedMonthly, seriesBSQBurntMonthly)); chart.setLegendVisible(true); @@ -344,7 +340,6 @@ private Node createBSQIssuedChart(XYChart.Series series) { return chart; } - @SuppressWarnings("unchecked") private Node createBSQBurntChart( XYChart.Series seriesBSQBurntDaily, XYChart.Series seriesBSQBurntDailyMA @@ -371,7 +366,7 @@ private Node createBSQBurntChart( configureChart(chart); chart.setCreateSymbols(false); - chart.getData().addAll(seriesBSQBurntDaily, seriesBSQBurntDailyMA); + chart.getData().addAll(List.of(seriesBSQBurntDaily, seriesBSQBurntDailyMA)); chart.setLegendVisible(true); @@ -501,11 +496,9 @@ private List getSortedBurntTxs() { Set burntTxs = new HashSet<>(daoStateService.getBurntFeeTxs()); burntTxs.addAll(daoStateService.getInvalidTxs()); - List sortedBurntTxs = burntTxs.stream() + return burntTxs.stream() .sorted(Comparator.comparing(Tx::getTime)) .collect(Collectors.toList()); - - return sortedBurntTxs; } private List> updateBSQBurntDaily(List sortedBurntTxs) { @@ -515,18 +508,16 @@ private List> updateBSQBurntDaily(List sortedBu sortedBurntTxs .stream() .collect(Collectors.groupingBy( - tx -> - new Date(tx.getTime()) - .toLocalDate() - .with(ADJUSTERS.get(DAY)) + tx -> Instant.ofEpochMilli(tx.getTime()).atZone(ZoneId.systemDefault()) + .toLocalDate() + .with(ADJUSTERS.get(DAY)) )); List> updatedBurntBsqDaily = burntBsqByDay .keySet() .stream() - .map(date -> - { + .map(date -> { ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault()); return new XYChart.Data( zonedDateTime.toInstant().getEpochSecond(), @@ -550,18 +541,16 @@ private void updateBSQBurntMonthly(List sortedBurntTxs) { sortedBurntTxs .stream() .collect(Collectors.groupingBy( - tx -> - new Date(tx.getTime()) - .toLocalDate() - .with(ADJUSTERS.get(MONTH)) + tx -> Instant.ofEpochMilli(tx.getTime()).atZone(ZoneId.systemDefault()) + .toLocalDate() + .with(ADJUSTERS.get(MONTH)) )); List> updatedBurntBsqMonthly = burntBsqByMonth .keySet() .stream() - .map(date -> - { + .map(date -> { ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault()); return new XYChart.Data( zonedDateTime.toInstant().getEpochSecond(), @@ -603,7 +592,7 @@ private void updateBSQBurntDailyMA(List> updatedBur maPeriod); BiFunction> xyToXyData = - XYChart.Data::new; + XYChart.Data::new; List> burntBsqMA = zip(burntBsqXValues, burntBsqMAYValues, xyToXyData) @@ -614,6 +603,11 @@ private void updateBSQBurntDailyMA(List> updatedBur } private void updateBSQIssuedMonthly() { + Function blockTimeFn = memoize(height -> + Instant.ofEpochMilli(daoFacade.getBlockTime(height)).atZone(ZoneId.systemDefault()) + .toLocalDate() + .with(ADJUSTERS.get(MONTH))); + Stream bsqByCompensation = daoStateService.getIssuanceSet(IssuanceType.COMPENSATION).stream() .sorted(Comparator.comparing(Issuance::getChainHeight)); @@ -621,8 +615,7 @@ private void updateBSQIssuedMonthly() { .sorted(Comparator.comparing(Issuance::getChainHeight)); Map> bsqAddedByVote = Stream.concat(bsqByCompensation, bsqByReimbursement) - .collect(Collectors.groupingBy(item -> new Date(daoFacade.getBlockTime(item.getChainHeight())).toLocalDate() - .with(ADJUSTERS.get(MONTH)))); + .collect(Collectors.groupingBy(blockTimeFn.compose(Issuance::getChainHeight))); List> updatedAddedBSQ = bsqAddedByVote.keySet().stream() .map(date -> { @@ -686,7 +679,7 @@ private void triggerZoomToInliers() { // When Guava version is bumped to at least 21.0, // can be replaced with com.google.common.collect.Streams.zip - public static Stream zip( + private static Stream zip( Stream leftStream, Stream rightStream, BiFunction combiner @@ -712,4 +705,9 @@ public boolean tryAdvance(Consumer action) { }; return StreamSupport.stream(spliterator, false); } + + private static Function memoize(Function fn) { + Map map = new ConcurrentHashMap<>(); + return x -> map.computeIfAbsent(x, fn); + } }