liao_generator/generator/
factor.rs

1use rand::{seq::SliceRandom, thread_rng};
2
3use crate::rules::ff::new_ff_rule;
4use crate::rules::{bf::new_bf_rule, lf::new_lf_rule, nf::new_nf_rule, *};
5use crate::constants::{GenerateRules, GenerateFormula, FactorOptions, Operation};
6
7fn generate_with_rule(rules: GenerateRules, options: &FactorOptions) -> Option<u8> {
8    let mut rng = thread_rng();
9
10    let rule = match options.schema.operation {
11        Some(op) => match op {
12            Operation::Decrement => rules.decrement,
13            Operation::Increment => rules.increment,
14        },
15        None => panic!("Operation is not setted"),
16    };
17
18    if let Ok(numbers) = get_value_by_number(options.number, rule) {
19        let mut numbers = numbers.clone();
20
21        if let Some(forbidden_number) = options.forbidden_number {
22            numbers.retain(|&x| x != forbidden_number);
23        }
24
25        let force_formula = options.schema.force_formula;
26
27        if force_formula {
28            let force_numbers_stop = numbers.iter().position(|x| *x == 0);
29            let mut force_numbers: Vec<u8> = numbers
30                .clone()
31                .drain(0..force_numbers_stop.unwrap_or(0))
32                .collect();
33
34            force_numbers.retain(|x| *x != 0);
35
36            if force_numbers.len() > 0 {
37                let force_number = force_numbers.choose(&mut rng).unwrap();
38                return Some(*force_number);
39            }
40        }
41
42        let can_generate_zero = options.schema.can_generate_zero;
43
44        if !can_generate_zero {
45            numbers.retain(|&x| x != 0);
46        }
47
48        if numbers.is_empty() {
49            return None;
50        }
51
52        numbers.shuffle(&mut rng);
53
54        return Some(numbers[0]);
55    } else {
56        None
57    }
58}
59
60pub fn generate_factor(options: &FactorOptions) -> Option<u8> {
61    let rules: Option<GenerateRules> = match options.formula {
62        GenerateFormula::NF => Some(new_nf_rule()),
63        GenerateFormula::LF => Some(new_lf_rule()),
64        GenerateFormula::BF => Some(new_bf_rule()),
65        GenerateFormula::FF => Some(new_ff_rule()),
66    };
67
68    if let Some(rules) = rules {
69        return generate_with_rule(rules, &options);
70    }
71
72    None
73}