<commit_before>package com.valkryst.generator;

import com.valkryst.markov.MarkovChain;
import lombok.NonNull;

import java.util.List;
import java.util.Optional;

public final class MarkovGenerator extends NameGenerator {
    /** The chain to use when generating names. */
    private final MarkovChain markovChain = new MarkovChain();

    /**
     * Constructs a MarkovGenerator.
     *
     * @param trainingNames
     *         The names to train the Markov Chain with.
     *
     * @throws NullPointerException
     *         If the list of training names is null.
     *
     * @throws IllegalArgumentException
     *         If the list of training names is empty.
     */
    public MarkovGenerator(final @NonNull List<String> trainingNames) {
        if (trainingNames.size() == 0) {
            throw new IllegalArgumentException("The list of training names is empty.");
        }

        markovChain.train(trainingNames);
    }

    @Override
    public String generateName(int length) {
        if (length == 0) {
            length = 2;
        }

        final StringBuilder sb = new StringBuilder();
        sb.append(markovChain.chooseRandomString()); // Begin the name with a random pair of two characters.

        for (int i = 2; i < length; ++i) {
            final Optional<Character> next = markovChain.chooseRandomCharacter(sb.substring(i - 2, i));

            if (next.isPresent()) {
                sb.append(next.get());
            } else {
                if (sb.length() != length) {
                    return generateName(length);
                } else {
                    break;
                }
            }
        }

        return super.capitalizeFirstCharacter(sb.toString());
    }
}<commit_msg>Fixes issue where MarkovGenerator could produce names with a length less than 2. Adds check to ensure names generated by the MarkovGenerator are of the required length.<commit_after>package com.valkryst.generator;

import com.valkryst.markov.MarkovChain;
import lombok.NonNull;

import java.util.List;
import java.util.Optional;

public final class MarkovGenerator extends NameGenerator {
    /** The chain to use when generating names. */
    private final MarkovChain markovChain = new MarkovChain();

    /**
     * Constructs a MarkovGenerator.
     *
     * @param trainingNames
     *         The names to train the Markov Chain with.
     *
     * @throws NullPointerException
     *         If the list of training names is null.
     *
     * @throws IllegalArgumentException
     *         If the list of training names is empty.
     */
    public MarkovGenerator(final @NonNull List<String> trainingNames) {
        if (trainingNames.size() == 0) {
            throw new IllegalArgumentException("The list of training names is empty.");
        }

        markovChain.train(trainingNames);
    }

    @Override
    public String generateName(int length) {
        if (length < 2) {
            length = 2;
        }

        final StringBuilder sb = new StringBuilder();
        sb.append(markovChain.chooseRandomString()); // Begin the name with a random pair of two characters.

        for (int i = 2; i < length; ++i) {
            final Optional<Character> next = markovChain.chooseRandomCharacter(sb.substring(i - 2, i));

            if (next.isPresent()) {
                sb.append(next.get());
            } else {
                if (sb.length() != length) {
                    return generateName(length);
                } else {
                    break;
                }
            }
        }

        if (sb.length() > length) {
            System.out.println(sb.length() + " " + length + " " + sb.toString());
            sb.deleteCharAt(sb.length() - (sb.length() - length));
        }

        return super.capitalizeFirstCharacter(sb.toString());
    }
}
{'fraction_non_alphanumeric': 0.09707724425887265, 'fraction_numerical': 0.002870563674321503, 'mean_word_length': 1.99453125, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2487020', 'n_tokens_mistral': 1027, 'n_tokens_neox': 967, 'n_words': 299}