All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.robozonky.notifications.samples.Util Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021 The RoboZonky Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.robozonky.notifications.samples;

import static com.github.robozonky.internal.util.BigDecimalCalculator.divide;
import static com.github.robozonky.internal.util.BigDecimalCalculator.plus;

import java.math.BigDecimal;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.github.robozonky.api.Money;
import com.github.robozonky.api.Ratio;
import com.github.robozonky.api.notifications.ExtendedPortfolioOverview;
import com.github.robozonky.api.remote.entities.Investment;
import com.github.robozonky.api.remote.entities.Loan;
import com.github.robozonky.api.remote.entities.Participation;
import com.github.robozonky.api.remote.enums.LoanHealth;
import com.github.robozonky.api.remote.enums.MainIncomeType;
import com.github.robozonky.api.remote.enums.Purpose;
import com.github.robozonky.api.remote.enums.Rating;
import com.github.robozonky.api.remote.enums.Region;
import com.github.robozonky.api.strategies.PortfolioOverview;
import com.github.robozonky.internal.ApiConstants;
import com.github.robozonky.internal.remote.entities.AmountsImpl;
import com.github.robozonky.internal.remote.entities.InvestmentImpl;
import com.github.robozonky.internal.remote.entities.InvestmentLoanDataImpl;
import com.github.robozonky.internal.remote.entities.LoanHealthStatsImpl;
import com.github.robozonky.internal.remote.entities.LoanImpl;
import com.github.robozonky.internal.remote.entities.ParticipationImpl;
import com.github.robozonky.internal.test.DateUtil;

final class Util {

    private static final Random RANDOM = new Random(0); // generate the same entities every time
    private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In consectetur "
            +
            "dolor lorem, eu finibus dolor aliquet eleifend. Etiam lectus massa, dapibus vitae dictum non, pretium sed "
            +
            "libero. Etiam eu risus porttitor, scelerisque risus dictum, posuere orci. Nulla mattis in mauris nec " +
            "consectetur. Donec sodales libero commodo lorem lacinia dignissim. Integer pharetra est sit amet tortor " +
            "gravida egestas. Phasellus quis pellentesque dui, eget pretium elit. Ut non lobortis metus. Maecenas " +
            "sodales sit amet dolor eu ornare. Proin ac malesuada ligula, a laoreet nibh. Aliquam arcu velit, " +
            "posuere in bibendum viverra, ornare vitae nisl. Morbi ut dolor vitae nibh faucibus volutpat id eu ipsum." +
            " Cras luctus dolor ac ullamcorper consequat. Vivamus eget erat convallis elit volutpat consectetur id ut" +
            " augue. Duis dapibus suscipit massa id iaculis. Fusce eget tortor est.";

    private Util() {
        // no external instances
    }

    private static  T randomize(final T[] values) {
        final Object[] withoutUnknown = Stream.of(values)
            .filter(v -> !Objects.equals(v.toString(), "UNKNOWN"))
            .toArray(Object[]::new);
        return (T) withoutUnknown[RANDOM.nextInt(withoutUnknown.length)];
    }

    private static String generateText(final int wordCount) {
        final String[] words = LOREM_IPSUM.split(" ");
        return Stream.of(words)
            .limit(wordCount)
            .collect(Collectors.joining(" "));
    }

    private static String generateShortText() {
        final int wordCount = 2 + RANDOM.nextInt(10);
        return generateText(wordCount);
    }

    public static Loan randomizeLoan() {
        final LoanImpl loan = new LoanImpl();
        loan.setId(100_000 + RANDOM.nextInt(900_000)); // six-digit number
        loan.setInterestRate(Rating.values()[RANDOM.nextInt(Rating.values().length)].getInterestRate());
        loan.setMainIncomeType(randomize(MainIncomeType.values()));
        loan.setPurpose(randomize(Purpose.values()));
        loan.setRegion(randomize(Region.values()));
        // set basic financial properties
        final int amount = (2 + RANDOM.nextInt(89)) * 10_000; // from 20K to 900K
        loan.setAmount(Money.from(amount));
        final int term = 6 + RANDOM.nextInt(115); // from 6 to 120
        loan.setTermInMonths(term);
        final BigDecimal annuity = divide(amount, term);
        loan.setAnnuity(Money.from(annuity));
        // set insurance properties
        final boolean isInsured = RANDOM.nextBoolean();
        if (isInsured) {
            loan.setInsuranceActive(true);
            loan.setAnnuityWithInsurance(Money.from(plus(annuity, 50)));
        } else {
            loan.setInsuranceActive(false);
            loan.setAnnuityWithInsurance(Money.from(annuity));
        }
        // set rating and infer other dependent properties
        Rating rating = randomize(Rating.values());
        loan.setInterestRate(rating.getInterestRate());
        loan.setRevenueRate(rating.getMaximalRevenueRate());
        // set various dates
        loan.setDatePublished(OffsetDateTime.now()
            .minusDays(3));
        // set textual properties
        loan.setUrl(ApiConstants.ZONKY_API_HOSTNAME + "/loan/" + loan.getId());
        loan.setStory(LOREM_IPSUM);
        loan.setName(generateShortText());
        return loan;
    }

    public static Investment randomizeInvestment(final Loan loan) {
        InvestmentImpl investment = new InvestmentImpl(new InvestmentLoanDataImpl(loan,
                new LoanHealthStatsImpl(LoanHealth.UNKNOWN)),
                Money.from(200 + (RANDOM.nextInt(24) * 200L))); // From 200 to 5_000.
        Money interest = Money.from(RANDOM.nextDouble() * 10);
        Money unpaidInterest = interest.divideBy(2);
        investment.setInterest(new AmountsImpl(interest, unpaidInterest));
        return investment;
    }

    public static Participation randomizeParticipation(final Loan loan) {
        return new ParticipationImpl(loan, Money.from(200 + (RANDOM.nextInt(24) * 200L)),
                RANDOM.nextInt(loan.getTermInMonths()));
    }

    public static PortfolioOverview randomizePortfolioOverview() {
        final ZonedDateTime now = DateUtil.zonedNow();
        final Map invested = Stream.of(Rating.values())
            .map(Rating::getInterestRate)
            .collect(Collectors.toMap(r -> r, r -> RANDOM.nextInt(10_000_000)));
        return new PortfolioOverview() {
            @Override
            public Money getInvested() {
                return Money.from(invested.values()
                    .stream()
                    .reduce(0, Integer::sum));
            }

            @Override
            public Money getInvested(Ratio r) {
                return Money.from(invested.get(r));
            }

            @Override
            public Ratio getAnnualProfitability() {
                final BigDecimal min = getMinimalAnnualProfitability().bigDecimalValue();
                final BigDecimal max = getOptimalAnnualProfitability().bigDecimalValue();
                return Ratio.fromRaw(divide(plus(min, max), 2));
            }

            @Override
            public ZonedDateTime getTimestamp() {
                return now;
            }
        };
    }

    public static ExtendedPortfolioOverview randomizeExtendedPortfolioOverview() {
        final PortfolioOverview portfolioOverview = randomizePortfolioOverview();
        return new ExtendedPortfolioOverview() {
            @Override
            public Money getAtRisk() {
                return Stream.of(Rating.values())
                    .map(Rating::getInterestRate)
                    .map(this::getAtRisk)
                    .reduce(Money.ZERO, Money::add);
            }

            @Override
            public Money getAtRisk(Ratio r) {
                int nextRandom = RANDOM.nextInt(100);
                if (nextRandom == 0) {
                    return Money.ZERO;
                } else {
                    return getInvested(r).divideBy(nextRandom);
                }
            }

            @Override
            public Money getSellable() {
                return Stream.of(Rating.values())
                    .map(Rating::getInterestRate)
                    .map(this::getSellable)
                    .reduce(Money.ZERO, Money::add);
            }

            @Override
            public Money getSellable(Ratio r) {
                return getAtRisk(r);
            }

            @Override
            public Money getSellableFeeless() {
                return Stream.of(Rating.values())
                    .map(Rating::getInterestRate)
                    .map(this::getSellableFeeless)
                    .reduce(Money.ZERO, Money::add);
            }

            @Override
            public Money getSellableFeeless(Ratio r) {
                int nextRandom = RANDOM.nextInt(100);
                if (nextRandom == 0) {
                    return Money.ZERO;
                } else {
                    return getSellable(r).divideBy(nextRandom);
                }
            }

            @Override
            public Money getInvested() {
                return portfolioOverview.getInvested();
            }

            @Override
            public Money getInvested(Ratio r) {
                return portfolioOverview.getInvested(r);
            }

            @Override
            public Ratio getAnnualProfitability() {
                return portfolioOverview.getAnnualProfitability();
            }

            @Override
            public ZonedDateTime getTimestamp() {
                return portfolioOverview.getTimestamp();
            }
        };
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy