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

            
87
4
        data
88
4
    }
89
}
90

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

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

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

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

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

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

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

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

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

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

            
256
        None
257
203
    }
258
}