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

            
87
4
        data
88
4
    }
89
}
90

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

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

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

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

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

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

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

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

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

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

            
256
        None
257
273
    }
258
}