liao-generator 0.1.2

Liao Mental Generator in Rust!
Documentation
use rand::{seq::SliceRandom, thread_rng};

use crate::rules::ff::new_ff_rule;
use crate::rules::{bf::new_bf_rule, lf::new_lf_rule, nf::new_nf_rule, *};
use crate::constants::{GenerateRules, GenerateFormula, FactorOptions, Operation};

fn generate_with_rule(rules: GenerateRules, options: &FactorOptions) -> Option<u8> {
    let mut rng = thread_rng();

    let rule = match options.schema.operation {
        Some(op) => match op {
            Operation::Decrement => rules.decrement,
            Operation::Increment => rules.increment,
        },
        None => panic!("Operation is not setted"),
    };

    if let Ok(numbers) = get_value_by_number(options.number, rule) {
        let mut numbers = numbers.clone();

        if let Some(forbidden_number) = options.forbidden_number {
            numbers.retain(|&x| x != forbidden_number);
        }

        let force_formula = options.schema.force_formula;

        if force_formula {
            let force_numbers_stop = numbers.iter().position(|x| *x == 0);
            let mut force_numbers: Vec<u8> = numbers
                .clone()
                .drain(0..force_numbers_stop.unwrap_or(0))
                .collect();

            force_numbers.retain(|x| *x != 0);

            if force_numbers.len() > 0 {
                let force_number = force_numbers.choose(&mut rng).unwrap();
                return Some(*force_number);
            }
        }

        let can_generate_zero = options.schema.can_generate_zero;

        if !can_generate_zero {
            numbers.retain(|&x| x != 0);
        }

        if numbers.is_empty() {
            return None;
        }

        numbers.shuffle(&mut rng);

        return Some(numbers[0]);
    } else {
        None
    }
}

pub fn generate_factor(options: &FactorOptions) -> Option<u8> {
    let rules: Option<GenerateRules> = match options.formula {
        GenerateFormula::NF => Some(new_nf_rule()),
        GenerateFormula::LF => Some(new_lf_rule()),
        GenerateFormula::BF => Some(new_bf_rule()),
        GenerateFormula::FF => Some(new_ff_rule()),
    };

    if let Some(rules) = rules {
        return generate_with_rule(rules, &options);
    }

    None
}