game_manager_lib/services/recommendation/
profile.rs1use super::core::*;
7use crate::constants::{RECOMMENDATION_WEIGHT_GENRE, RECOMMENDATION_WEIGHT_SERIES};
8use crate::utils::tag_utils::{combined_multiplier, TagKey, TagRole};
9use std::collections::{HashMap, HashSet};
10
11pub fn calculate_user_profile(
13 games: &[GameWithDetails],
14 ignored_ids: &HashSet<String>,
15) -> UserPreferenceVector {
16 let mut genres: HashMap<String, f32> = HashMap::new();
17 let mut tags: HashMap<TagKey, f32> = HashMap::new();
18 let mut series: HashMap<String, f32> = HashMap::new();
19 let mut total_playtime = 0;
20 let total_games = games.len() as i32;
21
22 for game_data in games {
23 if ignored_ids.contains(&game_data.game.id) {
24 continue;
25 }
26
27 let game = &game_data.game;
28 let weight = calculate_game_weight(game);
29 total_playtime += game.playtime.unwrap_or(0);
30
31 accumulate_genres(&mut genres, &game_data.genres, weight);
33
34 accumulate_tags(&mut tags, &game_data.tags, weight);
36
37 accumulate_series(&mut series, &game_data.series, weight);
39 }
40
41 UserPreferenceVector {
42 genres,
43 tags,
44 series,
45 total_playtime,
46 total_games,
47 }
48}
49
50fn accumulate_genres(genres: &mut HashMap<String, f32>, game_genres: &[String], weight: f32) {
53 for genre in game_genres {
54 *genres.entry(genre.clone()).or_insert(0.0) += weight * RECOMMENDATION_WEIGHT_GENRE;
55 }
56}
57
58fn accumulate_tags(
59 tags: &mut HashMap<TagKey, f32>,
60 game_tags: &[crate::models::GameTag],
61 weight: f32,
62) {
63 for tag in game_tags {
64 let key = TagKey::new(tag.category.clone(), tag.slug.clone());
65
66 if tag.role == TagRole::Filter {
68 continue;
69 }
70
71 let tag_weight = weight * tag.relevance * combined_multiplier(&tag.category, &tag.role);
72
73 *tags.entry(key).or_insert(0.0) += tag_weight;
74 }
75}
76
77fn accumulate_series(series: &mut HashMap<String, f32>, game_series: &Option<String>, weight: f32) {
78 if let Some(series_name) = game_series {
79 *series.entry(series_name.clone()).or_insert(0.0) += weight * RECOMMENDATION_WEIGHT_SERIES;
80 }
81}