1
use std::{
2
    collections::{BTreeMap, HashSet},
3
    ops::RangeInclusive,
4
};
5

            
6
use fake::{
7
    faker::{
8
        address::raw::{
9
            BuildingNumber, CityName, CountryCode, PostCode, StateName, StreetName, StreetSuffix,
10
        },
11
        company::raw::{Bs, BsAdj},
12
        internet::raw::SafeEmail,
13
        lorem::raw::Paragraphs,
14
        name::raw::Name,
15
        phone_number::raw::PhoneNumber,
16
    },
17
    locales::EN,
18
    Dummy, Fake,
19
};
20
use rand::{seq::SliceRandom, Rng};
21
use serde::{Deserialize, Serialize};
22

            
23
use crate::utils::gen_range;
24

            
25
4
#[derive(Default, Clone, Debug)]
26
pub struct InitialDataSet {
27
    pub customers: BTreeMap<u32, Customer>,
28
    pub products: BTreeMap<u32, Product>,
29
    pub categories: BTreeMap<u32, Category>,
30
    pub orders: BTreeMap<u32, Order>,
31
    pub reviews: Vec<ProductReview>,
32
}
33

            
34
pub struct InitialDataSetConfig {
35
    pub number_of_customers: RangeInclusive<u32>,
36
    pub number_of_products: RangeInclusive<u32>,
37
    pub number_of_categories: RangeInclusive<u32>,
38
    pub number_of_orders: RangeInclusive<u32>,
39
    pub number_of_reviews: RangeInclusive<u32>,
40
}
41

            
42
impl InitialDataSetConfig {
43
4
    pub fn fake<R: Rng>(&self, rng: &mut R) -> InitialDataSet {
44
4
        let mut data = InitialDataSet::default();
45
4
        let mut customer_names = HashSet::new();
46
562
        for customer_id in 0..gen_range(rng, self.number_of_customers.clone()) {
47
562
            let customer = Customer::fake(rng, &customer_names);
48
562
            customer_names.insert(customer.name.clone());
49
562
            data.customers.insert(customer_id, customer);
50
562
        }
51
35
        for category_id in 0..gen_range(rng, self.number_of_categories.clone()) {
52
35
            data.categories.insert(category_id, Category::fake(rng));
53
35
        }
54
4
        let mut product_names = HashSet::new();
55
324
        for product_id in 0..gen_range(rng, self.number_of_products.clone()) {
56
324
            let product = Product::fake(rng, &data.categories, &product_names);
57
324
            product_names.insert(product.name.clone());
58
324
            data.products.insert(product_id, product);
59
324
        }
60
4
        let customer_ids = data.customers.keys().copied().collect::<Vec<_>>();
61
4
        let product_ids = data.products.keys().copied().collect::<Vec<_>>();
62
467
        for order_id in 0..gen_range(rng, self.number_of_orders.clone()) {
63
467
            data.orders
64
467
                .insert(order_id, Order::fake(rng, &customer_ids, &product_ids));
65
467
        }
66
4
        let products_available_to_rate = data
67
4
            .orders
68
4
            .values()
69
467
            .flat_map(|order| {
70
467
                order
71
467
                    .product_ids
72
467
                    .iter()
73
3642
                    .map(|&product_id| (order.customer_id, product_id))
74
467
            })
75
4
            .collect::<Vec<_>>();
76
4
        let mut rated_products = HashSet::new();
77
4
        if !products_available_to_rate.is_empty() {
78
4
            for _ in 0..gen_range(rng, self.number_of_reviews.clone()) {
79
439
                if let Some(review) =
80
439
                    ProductReview::fake(rng, &products_available_to_rate, &mut rated_products)
81
439
                {
82
439
                    data.reviews.push(review);
83
439
                }
84
            }
85
        }
86

            
87
4
        data
88
4
    }
89
}
90

            
91
#[derive(Serialize, Deserialize, Debug)]
92
struct BenchmarkReport {}
93

            
94
2248
#[derive(Clone, Debug, Serialize, Deserialize)]
95
pub struct Customer {
96
    pub name: String,
97
    pub email: String,
98
    pub address: String,
99
    pub city: String,
100
    pub region: String,
101
    pub country: String,
102
    pub postal_code: String,
103
    pub phone: String,
104
}
105

            
106
impl Customer {
107
562
    pub fn fake<R: Rng>(rng: &mut R, taken_names: &HashSet<String>) -> Self {
108
562
        let name = loop {
109
562
            let name = format!(
110
562
                "{} {}",
111
562
                Name(EN).fake_with_rng::<String, _>(rng),
112
562
                rng.gen::<u8>()
113
562
            );
114
562
            if !taken_names.contains(&name) {
115
562
                break name;
116
            }
117
        };
118
562
        Self {
119
562
            name,
120
562
            email: SafeEmail(EN).fake_with_rng(rng),
121
562
            address: format!(
122
562
                "{} {} {}",
123
562
                BuildingNumber(EN).fake_with_rng::<String, _>(rng),
124
562
                StreetName(EN).fake_with_rng::<String, _>(rng),
125
562
                StreetSuffix(EN).fake_with_rng::<String, _>(rng)
126
562
            ),
127
562
            city: CityName(EN).fake_with_rng(rng),
128
562
            region: StateName(EN).fake_with_rng(rng),
129
562
            country: CountryCode(EN).fake_with_rng(rng),
130
562
            postal_code: PostCode(EN).fake_with_rng(rng),
131
562
            phone: PhoneNumber(EN).fake_with_rng(rng),
132
562
        }
133
562
    }
134
}
135

            
136
98840
#[derive(Clone, Debug, Serialize, Deserialize)]
137
pub struct Product {
138
    pub name: String,
139
    pub category_ids: Vec<u32>,
140
}
141

            
142
impl Product {
143
324
    pub fn fake<R: Rng>(
144
324
        rng: &mut R,
145
324
        available_categories: &BTreeMap<u32, Category>,
146
324
        taken_names: &HashSet<String>,
147
324
    ) -> Self {
148
324
        let mut available_category_ids = available_categories.keys().copied().collect::<Vec<_>>();
149
324
        let number_of_categories = if available_category_ids.is_empty() {
150
            0
151
        } else {
152
324
            rng.gen_range(0..(available_category_ids.len() + 1) / 2)
153
        };
154
324
        let mut category_ids = Vec::with_capacity(number_of_categories);
155
617
        for _ in 0..number_of_categories {
156
617
            let category_index = rng.gen_range(0..available_category_ids.len());
157
617
            category_ids.push(available_category_ids.remove(category_index));
158
617
        }
159

            
160
324
        let name = loop {
161
324
            let name = format!(
162
324
                "{} {}",
163
324
                Bs(EN).fake_with_rng::<String, _>(rng),
164
324
                rng.gen::<u8>()
165
324
            );
166
324
            if !taken_names.contains(&name) {
167
324
                break name;
168
            }
169
        };
170

            
171
324
        Self { name, category_ids }
172
324
    }
173
}
174

            
175
140
#[derive(Clone, Debug, Serialize, Deserialize)]
176
pub struct Category {
177
    pub name: String,
178
}
179

            
180
impl Category {
181
35
    pub fn fake<R: Rng>(rng: &mut R) -> Self {
182
35
        Self {
183
35
            name: BsAdj(EN).fake_with_rng(rng),
184
35
        }
185
35
    }
186
}
187

            
188
2320
#[derive(Clone, Debug, Serialize, Deserialize)]
189
pub struct Order {
190
    pub customer_id: u32,
191
    pub product_ids: Vec<u32>,
192
}
193

            
194
impl Order {
195
467
    pub fn fake<R: Rng>(
196
467
        rng: &mut R,
197
467
        available_customers: &[u32],
198
467
        available_products: &[u32],
199
467
    ) -> Self {
200
467
        let mut available_product_ids = available_products.to_vec();
201
467
        let number_of_products = if available_product_ids.is_empty() {
202
            0
203
        } else {
204
467
            rng.gen_range(0..((available_product_ids.len() + 2) / 3).min(20))
205
        };
206
467
        let mut product_ids = Vec::with_capacity(number_of_products);
207
3642
        for _ in 0..number_of_products {
208
3642
            let product_index = rng.gen_range(0..available_product_ids.len());
209
3642
            product_ids.push(available_product_ids.remove(product_index));
210
3642
        }
211

            
212
467
        Self {
213
467
            customer_id: *available_customers.choose(rng).unwrap(),
214
467
            product_ids,
215
467
        }
216
467
    }
217
}
218

            
219
26137
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
220
pub struct Cart {
221
    pub customer_id: Option<u32>,
222
    pub product_ids: Vec<u32>,
223
}
224

            
225
18972
#[derive(Clone, Debug, Serialize, Deserialize)]
226
pub struct ProductReview {
227
    pub customer_id: u32,
228
    pub product_id: u32,
229
    pub rating: u8,
230
    pub review: Option<String>,
231
}
232

            
233
impl ProductReview {
234
439
    pub fn fake<R: Rng>(
235
439
        rng: &mut R,
236
439
        available_customer_products: &[(u32, u32)],
237
439
        already_rated: &mut HashSet<(u32, u32)>,
238
439
    ) -> Option<Self> {
239
899
        while available_customer_products.len() > already_rated.len() {
240
899
            let index = rng.gen_range(0..available_customer_products.len());
241
899
            let (customer_id, product_id) = available_customer_products[index];
242
899
            if already_rated.insert((customer_id, product_id)) {
243
                return Some(Self {
244
439
                    customer_id,
245
439
                    product_id,
246
439
                    rating: rng.gen_range(1..=5),
247
439
                    review: if rng.gen_bool(0.25) {
248
96
                        Some(Vec::<String>::dummy_with_rng(&Paragraphs(EN, 1..5), rng).join("\n\n"))
249
                    } else {
250
343
                        None
251
                    },
252
                });
253
460
            }
254
        }
255

            
256
        None
257
439
    }
258
}