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

            
87
4
        data
88
4
    }
89
}
90

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

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

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

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

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

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

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

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

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

            
219
24200
#[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
21305
#[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
514
    pub fn fake<R: Rng>(
235
514
        rng: &mut R,
236
514
        available_customer_products: &[(u32, u32)],
237
514
        already_rated: &mut HashSet<(u32, u32)>,
238
514
    ) -> Option<Self> {
239
557
        while available_customer_products.len() > already_rated.len() {
240
557
            let index = rng.gen_range(0..available_customer_products.len());
241
557
            let (customer_id, product_id) = available_customer_products[index];
242
557
            if already_rated.insert((customer_id, product_id)) {
243
                return Some(Self {
244
514
                    customer_id,
245
514
                    product_id,
246
514
                    rating: rng.gen_range(1..=5),
247
514
                    review: if rng.gen_bool(0.25) {
248
123
                        Some(Vec::<String>::dummy_with_rng(&Paragraphs(EN, 1..5), rng).join("\n\n"))
249
                    } else {
250
391
                        None
251
                    },
252
                });
253
43
            }
254
        }
255

            
256
        None
257
514
    }
258
}