suggest/
fakespot.rs
1pub struct FakespotScore {
11 keywords_score: f64,
13 product_type_score: f64,
15 fakespot_score: f64,
18}
19
20impl FakespotScore {
21 pub fn new(query: &str, keywords: String, product_type: String, fakespot_score: f64) -> Self {
22 let query = query.to_lowercase();
23 let query_terms = split_terms(&query);
24 Self {
25 keywords_score: calc_keywords_score(&query_terms, &keywords),
26 product_type_score: calc_product_type_score(&query_terms, &product_type),
27 fakespot_score,
28 }
29 }
30
31 pub fn as_suggest_score(&self) -> f64 {
40 0.30 + (0.01 * self.keywords_score)
41 + (0.001 * self.product_type_score)
42 + (0.0001 * self.fakespot_score)
43 }
44}
45
46fn split_terms(string: &str) -> Vec<&str> {
48 string.split_whitespace().collect()
49}
50
51fn calc_keywords_score(query_terms: &[&str], keywords: &str) -> f64 {
52 let keyword_terms = split_terms(keywords);
54 if keyword_terms.is_empty() {
55 return 0.0;
56 }
57
58 if query_terms == keyword_terms {
59 1.0
60 } else {
61 0.0
62 }
63}
64
65fn calc_product_type_score(query_terms: &[&str], product_type: &str) -> f64 {
66 let product_type_terms = split_terms(product_type);
68 if product_type_terms.is_empty() {
69 return 0.0;
70 }
71 let count = product_type_terms
72 .iter()
73 .filter(|t| query_terms.contains(t))
74 .count() as f64;
75 count / product_type_terms.len() as f64
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 struct KeywordsTestCase {
83 keywords: &'static str,
84 query: &'static str,
85 expected: f64,
86 }
87
88 impl KeywordsTestCase {
89 fn test(&self) {
90 let actual =
91 calc_keywords_score(&split_terms(&self.query.to_lowercase()), self.keywords);
92 assert_eq!(
93 actual, self.expected,
94 "keywords: {} query: {} expected: {} actual: {actual}",
95 self.keywords, self.query, self.expected,
96 );
97 }
98 }
99
100 #[test]
101 fn test_keywords_score() {
102 KeywordsTestCase {
104 keywords: "apple",
105 query: "apple",
106 expected: 1.0,
107 }
108 .test();
109 KeywordsTestCase {
110 keywords: "apple",
111 query: "android",
112 expected: 0.0,
113 }
114 .test();
115 KeywordsTestCase {
116 keywords: "apple",
117 query: "apple phone",
118 expected: 0.0,
119 }
120 .test();
121 KeywordsTestCase {
123 keywords: "",
124 query: "",
125 expected: 0.0,
126 }
127 .test();
128 KeywordsTestCase {
129 keywords: "",
130 query: "apple",
131 expected: 0.0,
132 }
133 .test();
134 KeywordsTestCase {
136 keywords: "apple",
137 query: "Apple",
138 expected: 1.0,
139 }
140 .test();
141 }
142
143 struct ProductTypeTestCase {
144 query: &'static str,
145 product_type: &'static str,
146 expected: f64,
147 }
148 impl ProductTypeTestCase {
149 fn test(&self) {
150 let actual = calc_product_type_score(
151 &split_terms(&self.query.to_lowercase()),
152 self.product_type,
153 );
154 assert_eq!(
155 actual, self.expected,
156 "product_type: {} query: {} expected: {} actual: {actual}",
157 self.product_type, self.query, self.expected,
158 );
159 }
160 }
161
162 #[test]
163 fn test_product_type_score() {
164 ProductTypeTestCase {
167 product_type: "standing desk",
168 query: "standing desk",
169 expected: 1.0,
170 }
171 .test();
172 ProductTypeTestCase {
173 product_type: "standing desk",
174 query: "desk",
175 expected: 0.5,
176 }
177 .test();
178 ProductTypeTestCase {
179 product_type: "standing desk",
180 query: "desk desk desk",
181 expected: 0.5,
182 }
183 .test();
184 ProductTypeTestCase {
185 product_type: "standing desk",
186 query: "standing",
187 expected: 0.5,
188 }
189 .test();
190 ProductTypeTestCase {
191 product_type: "standing desk",
192 query: "phone",
193 expected: 0.0,
194 }
195 .test();
196 ProductTypeTestCase {
198 product_type: "standing desk",
199 query: "standing desk for my office",
200 expected: 1.0,
201 }
202 .test();
203 ProductTypeTestCase {
205 product_type: "",
206 query: "",
207 expected: 0.0,
208 }
209 .test();
210 ProductTypeTestCase {
212 product_type: "desk",
213 query: "Desk",
214 expected: 1.0,
215 }
216 .test();
217 ProductTypeTestCase {
219 product_type: "desk",
220 query: " desk ",
221 expected: 1.0,
222 }
223 .test();
224 }
225}