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

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

            
18
use crate::utils::gen_range;
19

            
20
4
#[derive(Default, Clone, Debug)]
21
pub struct InitialDataSet {
22
    pub customers: BTreeMap<u32, Customer>,
23
    pub products: BTreeMap<u32, Product>,
24
    pub categories: BTreeMap<u32, Category>,
25
    pub orders: BTreeMap<u32, Order>,
26
    pub reviews: Vec<ProductReview>,
27
}
28

            
29
#[derive(Debug)]
30
pub struct InitialDataSetConfig {
31
    pub number_of_customers: RangeInclusive<u32>,
32
    pub number_of_products: RangeInclusive<u32>,
33
    pub number_of_categories: RangeInclusive<u32>,
34
    pub number_of_orders: RangeInclusive<u32>,
35
    pub number_of_reviews: RangeInclusive<u32>,
36
}
37

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

            
83
4
        data
84
4
    }
85
}
86

            
87
#[derive(Serialize, Deserialize, Debug)]
88
struct BenchmarkReport {}
89

            
90
2228
#[derive(Clone, Debug, Serialize, Deserialize)]
91
pub struct Customer {
92
    pub name: String,
93
    pub email: String,
94
    pub address: String,
95
    pub city: String,
96
    pub region: String,
97
    pub country: String,
98
    pub postal_code: String,
99
    pub phone: String,
100
}
101

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

            
132
100660
#[derive(Clone, Debug, Serialize, Deserialize)]
133
pub struct Product {
134
    pub name: String,
135
    pub category_ids: Vec<u32>,
136
}
137

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

            
156
370
        let name = loop {
157
370
            let name = format!(
158
370
                "{} {}",
159
370
                Bs(EN).fake_with_rng::<String, _>(rng),
160
370
                rng.gen::<u8>()
161
370
            );
162
370
            if !taken_names.contains(&name) {
163
370
                break name;
164
            }
165
        };
166

            
167
370
        Self { name, category_ids }
168
370
    }
169
}
170

            
171
240
#[derive(Clone, Debug, Serialize, Deserialize)]
172
pub struct Category {
173
    pub name: String,
174
}
175

            
176
impl Category {
177
60
    pub fn fake<R: Rng>(rng: &mut R) -> Self {
178
60
        Self {
179
60
            name: BsAdj(EN).fake_with_rng(rng),
180
60
        }
181
60
    }
182
}
183

            
184
5536
#[derive(Clone, Debug, Serialize, Deserialize)]
185
pub struct Order {
186
    pub customer_id: u32,
187
    pub product_ids: Vec<u32>,
188
}
189

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

            
208
1263
        Self {
209
1263
            customer_id: *available_customers.choose(rng).unwrap(),
210
1263
            product_ids,
211
1263
        }
212
1263
    }
213
}
214

            
215
26180
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
216
pub struct Cart {
217
    pub customer_id: Option<u32>,
218
    pub product_ids: Vec<u32>,
219
}
220

            
221
19620
#[derive(Clone, Debug, Serialize, Deserialize)]
222
pub struct ProductReview {
223
    pub customer_id: u32,
224
    pub product_id: u32,
225
    pub rating: u8,
226
    pub review: Option<String>,
227
}
228

            
229
impl ProductReview {
230
446
    pub fn fake<R: Rng>(
231
446
        rng: &mut R,
232
446
        available_customer_products: &HashSet<(u32, u32)>,
233
446
        already_rated: &mut HashSet<(u32, u32)>,
234
446
    ) -> Option<Self> {
235
446
        if available_customer_products.len() > already_rated.len() {
236
456
            for (customer_id, product_id) in available_customer_products
237
446
                .iter()
238
446
                .chain(available_customer_products.iter())
239
446
                .skip(rng.gen_range(0..available_customer_products.len()))
240
446
                .take(available_customer_products.len())
241
446
                .copied()
242
            {
243
456
                if already_rated.insert((customer_id, product_id)) {
244
                    return Some(Self {
245
446
                        customer_id,
246
446
                        product_id,
247
446
                        rating: rng.gen_range(1..=5),
248
446
                        review: if rng.gen_bool(0.25) {
249
131
                            Some(
250
131
                                Vec::<String>::dummy_with_rng(&Paragraphs(EN, 1..5), rng)
251
131
                                    .join("\n\n"),
252
131
                            )
253
                        } else {
254
315
                            None
255
                        },
256
                    });
257
10
                }
258
            }
259
        }
260

            
261
        None
262
446
    }
263
}