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
458
        for customer_id in 0..gen_range(rng, self.number_of_customers.clone()) {
47
458
            let customer = Customer::fake(rng, &customer_names);
48
458
            customer_names.insert(customer.name.clone());
49
458
            data.customers.insert(customer_id, customer);
50
458
        }
51
53
        for category_id in 0..gen_range(rng, self.number_of_categories.clone()) {
52
53
            data.categories.insert(category_id, Category::fake(rng));
53
53
        }
54
4
        let mut product_names = HashSet::new();
55
365
        for product_id in 0..gen_range(rng, self.number_of_products.clone()) {
56
365
            let product = Product::fake(rng, &data.categories, &product_names);
57
365
            product_names.insert(product.name.clone());
58
365
            data.products.insert(product_id, product);
59
365
        }
60
4
        let customer_ids = data.customers.keys().copied().collect::<Vec<_>>();
61
4
        let product_ids = data.products.keys().copied().collect::<Vec<_>>();
62
759
        for order_id in 0..gen_range(rng, self.number_of_orders.clone()) {
63
759
            data.orders
64
759
                .insert(order_id, Order::fake(rng, &customer_ids, &product_ids));
65
759
        }
66
4
        let products_available_to_rate = data
67
4
            .orders
68
4
            .values()
69
759
            .map(|order| {
70
759
                order
71
759
                    .product_ids
72
759
                    .iter()
73
7164
                    .map(|&product_id| (order.customer_id, product_id))
74
759
            })
75
4
            .flatten()
76
4
            .collect::<Vec<_>>();
77
4
        let mut rated_products = HashSet::new();
78
4
        if !products_available_to_rate.is_empty() {
79
4
            for _ in 0..gen_range(rng, self.number_of_reviews.clone()) {
80
309
                if let Some(review) =
81
309
                    ProductReview::fake(rng, &products_available_to_rate, &mut rated_products)
82
309
                {
83
309
                    data.reviews.push(review);
84
309
                }
85
            }
86
        }
87

            
88
4
        data
89
4
    }
90
}
91

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

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

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

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

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

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

            
172
365
        Self { name, category_ids }
173
365
    }
174
}
175

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

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

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

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

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

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

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

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

            
257
        None
258
309
    }
259
}