warlocks_cauldron/providers/spec/
ru.rs

1use std::iter::zip;
2
3use crate::data::parsed::RU;
4
5use super::super::{Local, Datelike, dependencies::*};
6
7
8lazy_static! {
9    static ref TAX_CODES: Vec<&'static str> = vec![
10        "7700", "7800", "5000", "0100",
11        "0200", "0300", "0500", "0600",
12        "0700", "0800", "0900", "1000",
13        "1100", "1200", "1300", "1400",
14        "1500", "1600", "1700", "1800",
15        "1900", "2000", "2100", "2200",
16        "2300", "2400", "2500", "2600",
17        "2700", "2800", "2900", "3000",
18        "3100", "3200", "3300", "3400",
19        "3500", "3600", "3700", "3800",
20        "3900", "4000", "4100", "4900",
21        "5100", "5200", "5300", "5400",
22        "5500", "5600", "5700", "5800",
23        "5900", "6000", "6100", "6200",
24        "6300", "6400", "6500", "6600",
25        "6700", "6800", "6900", "7000",
26        "7100", "7200", "7300", "7400",
27        "7500", "7600", "7900", "8600",
28        "8700", "8900", "9100", "9200",
29        "9800", "9900", "9901", "9951",
30        "9952", "9953", "9954", "9955",
31        "9956", "9957", "9958", "9959",
32        "9961", "9962", "9965", "9966",
33        "9971", "9972", "9973", "9974",
34        "9975", "9976", "9977", "9979",
35        "9998",
36    ];
37}
38
39
40/// Methods collection provides special data for Russia (ru)
41pub struct RussiaSpecProvider;
42
43impl RussiaSpecProvider {
44    /// Generate sentence from the parts.
45    pub fn generate_sentence() -> String {
46        let sentence = RU.builtin.get("sentence").unwrap()
47            .as_object().unwrap();
48
49        vec!["head", "p1", "p2", "tail"].into_iter()
50            .map(|k| get_random_element(
51                sentence.get(k).unwrap().as_array().unwrap().into_iter()
52                    .map(|i| i.as_str().unwrap())))
53                        .join(" ")
54    }
55
56    /// Generate random patronymic name
57    pub fn patronymic(gender: Option<Gender>) -> String {
58        let patronymics = RU.builtin.get("patronymic").unwrap()
59            .as_object().unwrap();
60
61        let gender = validate_enum(gender, None);
62
63        get_random_element(patronymics.get(gender).expect("Cannot find a patronymic with the given gender!")
64            .as_array().unwrap().into_iter()
65                .map(|i| i.as_str())).unwrap()
66                    .to_string()
67    }
68
69    /// Generate random series of passport
70    pub fn passport_series(year: Option<i32>) -> String {
71        let year = year.unwrap_or_else(|| randint(10, Local::now().year().to_string()[2..].parse().unwrap()));
72        let region = randint(1, 99);
73        format!("{region:02} {year}")
74    }
75
76    /// Generate random passport number
77    pub fn passport_number() -> i32 {
78        randint(100000, 999999)
79    }
80
81    /// Generate a random passport number and series
82    pub fn series_and_number(year: Option<i32>) -> String {
83        format!("{} {}", Self::passport_series(year), Self::passport_number())
84    }
85
86    /// Generate snils with special algorithm
87    pub fn snils() -> String {
88        let number = randints(0, 9, 9);
89        let control_code = (9..0).map(|i| number.get(9 - i).unwrap() * i).sum();
90        let code = number.into_iter().join("");
91
92        format!("{code}{:02}", if [100, 101].contains(&control_code) {
93            0
94        } else if control_code < 100 {
95            control_code
96        } else { // > 101
97            match control_code % 101 { 
98                100 => 0,
99                other => other,
100            }
101        })
102    }
103
104    fn control_sum(nums: &Vec<i32>, t: &str) -> i32 {
105        let digits = match t {
106            "n2" => vec![7, 2, 4, 10, 3, 5, 9, 4, 6, 8],
107            "n1" => vec![3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8],
108            _ => panic!("Invalid t arg!"),
109        };
110
111        zip(digits, nums).map(|(d, n)| d * n).sum::<i32>() % 11 % 10
112    }
113
114    /// Generate random, but valid ``INN``
115    pub fn inn() -> String {
116        let mut numbers: Vec<i32> = randints(1, 9, 1).into_iter()
117            .chain(randints(0, 9, 9).into_iter())
118            .collect();
119        
120        numbers.push(Self::control_sum(&numbers, "n2"));
121        numbers.push(Self::control_sum(&numbers, "n2"));
122        numbers.into_iter().join("")
123    }
124
125    /// Generate random, but valid ``OGRN``
126    pub fn ogrn() -> String {
127        let numbers: Vec<i32> = randints(1, 9, 1).into_iter()
128            .chain(randints(0, 9, 11).into_iter())
129            .collect();
130        
131        let ogrn: u64 = numbers.into_iter().join("").parse().unwrap();
132        let checksum = ogrn % 11 % 10;
133
134        format!("{ogrn}{checksum}")
135    }
136
137    /// Generate random ``BIC`` (Bank ID Code)
138    pub fn bic() -> String {
139        let country_code = "04";
140        let code = randint(1, 10);
141        let bank_number = randint(0, 99);
142        let bank_office = randint(50, 999);
143
144        format!("{:02}{:02}{:02}{:03}", country_code, code, bank_number, bank_office)
145    }
146
147    /// Generate random ``KPP``
148    pub fn kpp() -> String {
149        let tax_code = get_random_element(TAX_CODES.iter());
150
151        let reg_code = randint(1, 99);
152        let reg_number = randint(1, 999);
153        format!("{tax_code:04}{reg_code:02}{reg_number:03}")
154    }
155}