Merge branch 'feature/refactor-fill-currency-list-items' of https://github.com/tau3/exchange into tau3-feature/refactor-fill-currency-list-items

This commit is contained in:
Manfred Karrer 2018-02-01 13:50:05 -05:00
commit f49e0effb3
No known key found for this signature in database
GPG Key ID: 401250966A6B2C46
8 changed files with 250 additions and 80 deletions

View File

@ -34,6 +34,7 @@ import io.bisq.gui.main.offer.offerbook.OfferBook;
import io.bisq.gui.main.offer.offerbook.OfferBookListItem;
import io.bisq.gui.main.settings.SettingsView;
import io.bisq.gui.main.settings.preferences.PreferencesView;
import io.bisq.gui.util.CurrencyList;
import io.bisq.gui.util.CurrencyListItem;
import io.bisq.gui.util.GUIUtil;
import javafx.beans.property.ObjectProperty;
@ -53,8 +54,6 @@ import java.util.Optional;
import java.util.stream.Collectors;
class OfferBookChartViewModel extends ActivatableViewModel {
private static final Logger log = LoggerFactory.getLogger(OfferBookChartViewModel.class);
private static final int TAB_INDEX = 0;
private final OfferBook offerBook;
@ -67,7 +66,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
private final List<XYChart.Data> sellData = new ArrayList<>();
private final ObservableList<OfferBookListItem> offerBookListItems;
private final ListChangeListener<OfferBookListItem> offerBookListItemsListener;
final ObservableList<CurrencyListItem> currencyListItems = FXCollections.observableArrayList();
final CurrencyList currencyListItems;
private final ObservableList<OfferListItem> topBuyOfferList = FXCollections.observableArrayList();
private final ObservableList<OfferListItem> topSellOfferList = FXCollections.observableArrayList();
private final ChangeListener<Number> currenciesUpdatedListener;
@ -120,6 +119,8 @@ class OfferBookChartViewModel extends ActivatableViewModel {
}
}
};
this.currencyListItems = new CurrencyList(preferences);
}
private void fillTradeCurrencies() {
@ -137,7 +138,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
.filter(e -> e != null)
.collect(Collectors.toList());
GUIUtil.fillCurrencyListItems(tradeCurrencyList, currencyListItems, null, preferences);
currencyListItems.updateWithCurrencies(tradeCurrencyList, null);
}
@Override

View File

@ -36,6 +36,7 @@ import io.bisq.gui.main.market.trades.charts.CandleData;
import io.bisq.gui.main.settings.SettingsView;
import io.bisq.gui.main.settings.preferences.PreferencesView;
import io.bisq.gui.util.BSFormatter;
import io.bisq.gui.util.CurrencyList;
import io.bisq.gui.util.CurrencyListItem;
import io.bisq.gui.util.GUIUtil;
import javafx.beans.property.BooleanProperty;
@ -82,7 +83,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
private final SetChangeListener<TradeStatistics2> setChangeListener;
final ObjectProperty<TradeCurrency> selectedTradeCurrencyProperty = new SimpleObjectProperty<>();
final BooleanProperty showAllTradeCurrenciesProperty = new SimpleBooleanProperty(false);
private final ObservableList<CurrencyListItem> currencyListItems = FXCollections.observableArrayList();
private final CurrencyList currencyListItems;
private final CurrencyListItem showAllCurrencyListItem = new CurrencyListItem(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, GUIUtil.SHOW_ALL_FLAG), -1);
final ObservableList<TradeStatistics2> tradeStatisticsByCurrency = FXCollections.observableArrayList();
final ObservableList<XYChart.Data<Number, Number>> priceItems = FXCollections.observableArrayList();
@ -119,6 +120,8 @@ class TradesChartsViewModel extends ActivatableViewModel {
selectedTradeCurrencyProperty.set(GlobalSettings.getDefaultTradeCurrency());
tickUnit = TickUnit.values()[preferences.getTradeStatisticsTickUnitIndex()];
currencyListItems = new CurrencyList(this.preferences);
}
private void fillTradeCurrencies() {
@ -135,7 +138,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
.filter(e -> e != null)
.collect(Collectors.toList());
GUIUtil.fillCurrencyListItems(tradeCurrencyList, currencyListItems, showAllCurrencyListItem, preferences);
currencyListItems.updateWithCurrencies(tradeCurrencyList, showAllCurrencyListItem);
}
@Override

View File

@ -0,0 +1,103 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.gui.util;
import com.google.common.collect.Lists;
import com.sun.javafx.collections.ObservableListWrapper;
import io.bisq.common.locale.TradeCurrency;
import io.bisq.core.user.Preferences;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.BiFunction;
public class CurrencyList extends ObservableListWrapper<CurrencyListItem> {
private final CurrencyPredicates predicates;
private final Preferences preferences;
public CurrencyList(Preferences preferences) {
this(new ArrayList<>(), preferences, new CurrencyPredicates());
}
CurrencyList(List<CurrencyListItem> delegate, Preferences preferences, CurrencyPredicates predicates) {
super(delegate);
this.predicates = predicates;
this.preferences = preferences;
}
public void updateWithCurrencies(List<TradeCurrency> currencies, @Nullable CurrencyListItem first) {
List<CurrencyListItem> result = Lists.newLinkedList();
Optional.ofNullable(first).ifPresent(result::add);
result.addAll(getPartitionedSortedItems(currencies));
setAll(result);
}
private List<CurrencyListItem> getPartitionedSortedItems(List<TradeCurrency> currencies) {
Map<TradeCurrency, Integer> tradesPerCurrency = countTrades(currencies);
Comparator<CurrencyListItem> comparator = getComparator();
Queue<CurrencyListItem> fiatCurrencies = new PriorityQueue<>(comparator);
Queue<CurrencyListItem> cryptoCurrencies = new PriorityQueue<>(comparator);
for (Map.Entry<TradeCurrency, Integer> entry : tradesPerCurrency.entrySet()) {
TradeCurrency currency = entry.getKey();
Integer count = entry.getValue();
CurrencyListItem item = new CurrencyListItem(currency, count);
if (predicates.isFiatCurrency(currency)) {
fiatCurrencies.add(item);
}
if (predicates.isCryptoCurrency(currency)) {
cryptoCurrencies.add(item);
}
}
List<CurrencyListItem> result = Lists.newLinkedList();
result.addAll(fiatCurrencies);
result.addAll(cryptoCurrencies);
return result;
}
private Comparator<CurrencyListItem> getComparator() {
Comparator<CurrencyListItem> result;
if (preferences.isSortMarketCurrenciesNumerically()) {
Comparator<CurrencyListItem> byCount = Comparator.comparingInt(left -> left.numTrades);
result = byCount.reversed();
} else {
result = Comparator.comparing(item -> item.tradeCurrency);
}
return result;
}
private Map<TradeCurrency, Integer> countTrades(List<TradeCurrency> currencies) {
Map<TradeCurrency, Integer> result = new HashMap<>();
BiFunction<TradeCurrency, Integer, Integer> incrementCurrentOrOne =
(key, value) -> value == null ? 1 : value + 1;
currencies.forEach(currency -> result.compute(currency, incrementCurrentOrOne));
Set<TradeCurrency> preferred = new HashSet<>();
preferred.addAll(preferences.getFiatCurrencies());
preferred.addAll(preferences.getCryptoCurrencies());
preferred.forEach(currency -> result.putIfAbsent(currency, 0));
return result;
}
}

View File

@ -0,0 +1,31 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bisq.gui.util;
import io.bisq.common.locale.CurrencyUtil;
import io.bisq.common.locale.TradeCurrency;
class CurrencyPredicates {
boolean isCryptoCurrency(TradeCurrency currency) {
return CurrencyUtil.isCryptoCurrency(currency.getCode());
}
boolean isFiatCurrency(TradeCurrency currency) {
return CurrencyUtil.isFiatCurrency(currency.getCode());
}
}

View File

@ -255,60 +255,6 @@ public class GUIUtil {
};
}
// TODO could be done more elegantly...
public static void fillCurrencyListItems(List<TradeCurrency> tradeCurrencyList,
ObservableList<CurrencyListItem> currencyListItems,
@Nullable CurrencyListItem showAllCurrencyListItem,
Preferences preferences) {
Map<String, Integer> tradesPerCurrencyMap = new HashMap<>();
Set<TradeCurrency> tradeCurrencySet = new HashSet<>();
// We get the list of all offers or trades. We want to find out how many items at each currency we have.
tradeCurrencyList.stream().forEach(tradeCurrency -> {
tradeCurrencySet.add(tradeCurrency);
String code = tradeCurrency.getCode();
if (tradesPerCurrencyMap.containsKey(code))
tradesPerCurrencyMap.put(code, tradesPerCurrencyMap.get(code) + 1);
else
tradesPerCurrencyMap.put(code, 1);
});
Set<TradeCurrency> userSet = new HashSet<>(preferences.getFiatCurrencies());
userSet.addAll(preferences.getCryptoCurrencies());
// Now all those items which are not in the offers or trades list but comes from the user preferred currency list
// will get set to 0
userSet.stream().forEach(tradeCurrency -> {
tradeCurrencySet.add(tradeCurrency);
String code = tradeCurrency.getCode();
if (!tradesPerCurrencyMap.containsKey(code))
tradesPerCurrencyMap.put(code, 0);
});
List<CurrencyListItem> list = tradeCurrencySet.stream()
.filter(e -> CurrencyUtil.isFiatCurrency(e.getCode()))
.map(e -> new CurrencyListItem(e, tradesPerCurrencyMap.get(e.getCode())))
.collect(Collectors.toList());
List<CurrencyListItem> cryptoList = tradeCurrencySet.stream()
.filter(e -> CurrencyUtil.isCryptoCurrency(e.getCode()))
.map(e -> new CurrencyListItem(e, tradesPerCurrencyMap.get(e.getCode())))
.collect(Collectors.toList());
if (preferences.isSortMarketCurrenciesNumerically()) {
list.sort((o1, o2) -> new Integer(o2.numTrades).compareTo(o1.numTrades));
cryptoList.sort((o1, o2) -> new Integer(o2.numTrades).compareTo(o1.numTrades));
} else {
list.sort((o1, o2) -> o1.tradeCurrency.compareTo(o2.tradeCurrency));
cryptoList.sort((o1, o2) -> o1.tradeCurrency.compareTo(o2.tradeCurrency));
}
list.addAll(cryptoList);
if (showAllCurrencyListItem != null)
list.add(0, showAllCurrencyListItem);
currencyListItems.setAll(list);
}
public static void updateConfidence(TransactionConfidence confidence, Tooltip tooltip, TxConfidenceIndicator txConfidenceIndicator) {
if (confidence != null) {
switch (confidence.getConfidenceType()) {

View File

@ -1,7 +1,6 @@
package io.bisq.common.locale;
import com.natpryce.makeiteasy.Instantiator;
import com.natpryce.makeiteasy.Maker;
import com.natpryce.makeiteasy.Property;
import static com.natpryce.makeiteasy.MakeItEasy.a;

View File

@ -0,0 +1,104 @@
package io.bisq.gui.util;
import com.google.common.collect.Lists;
import io.bisq.common.locale.CryptoCurrency;
import io.bisq.common.locale.FiatCurrency;
import io.bisq.common.locale.TradeCurrency;
import io.bisq.core.user.Preferences;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Preferences.class)
public class CurrencyListTest {
private static final TradeCurrency USD = new FiatCurrency("USD");
private static final TradeCurrency RUR = new FiatCurrency("RUR");
private static final TradeCurrency BTC = new CryptoCurrency("BTC", "Bitcoin");
private static final TradeCurrency ETH = new CryptoCurrency("ETH", "Ether");
private static final TradeCurrency BSQ = new CryptoCurrency("BSQ", "Bisq Token");
private Preferences preferences;
private List<CurrencyListItem> delegate;
private CurrencyList testedEntity;
@Before
public void setUp() {
Locale.setDefault(new Locale("en", "US"));
CurrencyPredicates predicates = mock(CurrencyPredicates.class);
when(predicates.isCryptoCurrency(USD)).thenReturn(false);
when(predicates.isCryptoCurrency(RUR)).thenReturn(false);
when(predicates.isCryptoCurrency(BTC)).thenReturn(true);
when(predicates.isCryptoCurrency(ETH)).thenReturn(true);
when(predicates.isFiatCurrency(USD)).thenReturn(true);
when(predicates.isFiatCurrency(RUR)).thenReturn(true);
when(predicates.isFiatCurrency(BTC)).thenReturn(false);
when(predicates.isFiatCurrency(ETH)).thenReturn(false);
this.preferences = mock(Preferences.class);
this.delegate = new ArrayList<>();
this.testedEntity = new CurrencyList(delegate, preferences, predicates);
}
@Test
public void testUpdateWhenSortNumerically() {
when(preferences.isSortMarketCurrenciesNumerically()).thenReturn(true);
List<TradeCurrency> currencies = Lists.newArrayList(USD, RUR, USD, ETH, ETH, BTC);
testedEntity.updateWithCurrencies(currencies, null);
List<CurrencyListItem> expected = Lists.newArrayList(
new CurrencyListItem(USD, 2),
new CurrencyListItem(RUR, 1),
new CurrencyListItem(ETH, 2),
new CurrencyListItem(BTC, 1));
assertEquals(expected, delegate);
}
@Test
public void testUpdateWhenNotSortNumerically() {
when(preferences.isSortMarketCurrenciesNumerically()).thenReturn(false);
List<TradeCurrency> currencies = Lists.newArrayList(USD, RUR, USD, ETH, ETH, BTC);
testedEntity.updateWithCurrencies(currencies, null);
List<CurrencyListItem> expected = Lists.newArrayList(
new CurrencyListItem(RUR, 1),
new CurrencyListItem(USD, 2),
new CurrencyListItem(BTC, 1),
new CurrencyListItem(ETH, 2));
assertEquals(expected, delegate);
}
@Test
public void testUpdateWhenSortNumericallyAndFirstSpecified() {
when(preferences.isSortMarketCurrenciesNumerically()).thenReturn(true);
List<TradeCurrency> currencies = Lists.newArrayList(USD, RUR, USD, ETH, ETH, BTC);
CurrencyListItem first = new CurrencyListItem(BSQ, 5);
testedEntity.updateWithCurrencies(currencies, first);
List<CurrencyListItem> expected = Lists.newArrayList(
first,
new CurrencyListItem(USD, 2),
new CurrencyListItem(RUR, 1),
new CurrencyListItem(ETH, 2),
new CurrencyListItem(BTC, 1));
assertEquals(expected, delegate);
}
}

View File

@ -2,14 +2,10 @@ package io.bisq.gui.util;
import io.bisq.common.locale.Res;
import io.bisq.common.locale.TradeCurrency;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.util.StringConverter;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import static com.natpryce.makeiteasy.MakeItEasy.make;
@ -17,10 +13,8 @@ import static com.natpryce.makeiteasy.MakeItEasy.with;
import static io.bisq.common.locale.TradeCurrencyMakers.bitcoin;
import static io.bisq.common.locale.TradeCurrencyMakers.euro;
import static io.bisq.core.user.PreferenceMakers.empty;
import static io.bisq.gui.util.CurrencyListItemMakers.bitcoinItem;
import static io.bisq.gui.util.CurrencyListItemMakers.euroItem;
import static io.bisq.gui.util.CurrencyListItemMakers.numberOfTrades;
import static org.junit.Assert.*;
import static io.bisq.gui.util.CurrencyListItemMakers.*;
import static org.junit.Assert.assertEquals;
public class GUIUtilTest {
@ -50,15 +44,4 @@ public class GUIUtilTest {
assertEquals("★ Euro (EUR) - 1 offer", currencyListItemConverter.toString(make(euroItem.but(with(numberOfTrades, 1)))));
}
@Test
public void testFillCurrencyListItems() {
ObservableList<CurrencyListItem> currencyListItems = FXCollections.observableArrayList();
List<TradeCurrency> tradeCurrencyList = new ArrayList<>();
tradeCurrencyList.add(euro);
CurrencyListItem euroListItem = make(euroItem.but(with(numberOfTrades,1)));
GUIUtil.fillCurrencyListItems(tradeCurrencyList, currencyListItems, null, empty );
assertTrue(euroListItem.equals(currencyListItems.get(0)));
}
}