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

            
87
4
        data
88
4
    }
89
}
90

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

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

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

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

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

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

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

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

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

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

            
256
        None
257
222
    }
258
}