Util { static Set<Rating> rankRatingsByDemand(final ParsedStrategy strategy, final PortfolioOverview portfolio) { final SortedMap<Ratio, SortedMap<Ratio, EnumSet<Rating>>> mostWantedRatings = new TreeMap<>(); for (Rating r : Rating.values()) { final Ratio permittedShare = strategy.getPermittedShare(r); if (permittedShare.compareTo(Ratio.ZERO) <= 0) { LOGGER.debug("Rating {} permitted share is {} %, skipping.", r, permittedShare.asPercentage()); continue; } final Ratio currentRatingShare = portfolio.getShareOnInvestment(r); final Ratio ratio = Ratio.fromRaw(divide(currentRatingShare.bigDecimalValue(), permittedShare.bigDecimalValue())); final boolean overinvested = ratio.compareTo(Ratio.ONE) >= 0; if (overinvested) { final BigDecimal percentOver = ratio.asPercentage() .subtract(HUNDRED); LOGGER.debug("Rating {} over-invested by {} %, skipping. (Expected {}, got {}.)", r, percentOver, permittedShare, currentRatingShare); continue; } LOGGER.debug("Rating {} under-invested by {} %. (Expected {}, got {}.)", r, HUNDRED.subtract(ratio.asPercentage()), permittedShare, currentRatingShare); mostWantedRatings.computeIfAbsent(ratio, k -> new TreeMap<>(Comparator.reverseOrder())); mostWantedRatings.get(ratio) .compute(permittedShare, (k, v) -> { if (v == null) { return EnumSet.of(r); } else { v.add(r); return v; } }); } return mostWantedRatings.values() .stream() .flatMap(s -> s.values() .stream()) .flatMap(Collection::stream) .collect(Collectors.toCollection(LinkedHashSet::new)); } private  Util();   }
@Test void properRankingOfRatings() { final int targetShareA = 1; final int targetShareB = targetShareA * 5; final int targetShareC = targetShareB * 5; final ParsedStrategy parsed = new ParsedStrategy(new DefaultValues(DefaultPortfolio.EMPTY), asList( new PortfolioShare(Rating.A, fromPercentage(targetShareA)), new PortfolioShare(Rating.B, fromPercentage(targetShareB)), new PortfolioShare(Rating.C, fromPercentage(targetShareC))), Collections.emptyMap(), Collections.emptyMap()); final Set<Rating> ratings = EnumSet.of(Rating.A, Rating.B, Rating.C); PortfolioOverview portfolio = preparePortfolio(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); assertOrder(Util.rankRatingsByDemand(parsed, portfolio), Rating.C, Rating.B, Rating.A); portfolio = preparePortfolio(BigDecimal.ZERO, BigDecimal.valueOf(10), BigDecimal.valueOf(30)); assertOrder(Util.rankRatingsByDemand(parsed, portfolio), Rating.A); portfolio = preparePortfolio(BigDecimal.valueOf(0.99), BigDecimal.ZERO, BigDecimal.valueOf(24.9)); assertOrder(Util.rankRatingsByDemand(parsed, portfolio), Rating.B, Rating.A, Rating.C); }