Skip to main content

game_manager_lib/
models.rs

1//! Modelos de dados do banco de dados.
2//!
3//! Define as structs que representam as tabelas do banco:
4//! - Game: tabela `games`
5//! - GameDetails: tabela `game_details`
6//! - WishlistGame: tabela `wishlist`
7//! - Subscriptions: tabela `subscriptions`
8//! - PcgwData: tabela `pcgw_data`
9
10// Reexportar GameTag do utils para consistência
11pub use crate::utils::tag_utils::GameTag;
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14use std::str::FromStr;
15
16// === ENUMS ===
17
18/// Nível de confiança da importação do jogo
19#[derive(Debug, Serialize, Deserialize, Clone)]
20pub enum ImportConfidence {
21    High,
22    Medium,
23    Low,
24}
25
26impl FromStr for ImportConfidence {
27    type Err = ();
28    fn from_str(s: &str) -> Result<Self, Self::Err> {
29        match s {
30            "High" => Ok(ImportConfidence::High),
31            "Medium" => Ok(ImportConfidence::Medium),
32            "Low" => Ok(ImportConfidence::Low),
33            _ => Err(()),
34        }
35    }
36}
37
38impl std::fmt::Display for ImportConfidence {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        let s = match self {
41            ImportConfidence::High => "High",
42            ImportConfidence::Medium => "Medium",
43            ImportConfidence::Low => "Low",
44        };
45        write!(f, "{}", s)
46    }
47}
48
49/// Plataformas suportadas
50#[derive(Debug, Serialize, Deserialize, Clone)]
51pub enum Platform {
52    Steam,
53    Epic,
54    GOG,
55    Amazon,
56    Ubisoft,
57    EA,
58    BattleNet,
59    Xbox,
60    Heroic,
61    LegacyGames,
62    Indiegala,
63    Itch,
64    Indie,
65    Outra,
66}
67
68impl FromStr for Platform {
69    type Err = ();
70    fn from_str(s: &str) -> Result<Self, Self::Err> {
71        match s {
72            "Steam" => Ok(Platform::Steam),
73            "Epic" => Ok(Platform::Epic),
74            "GOG" => Ok(Platform::GOG),
75            "Amazon" => Ok(Platform::Amazon),
76            "Ubisoft" => Ok(Platform::Ubisoft),
77            "EA" => Ok(Platform::EA),
78            "BattleNet" => Ok(Platform::BattleNet),
79            "Xbox" => Ok(Platform::Xbox),
80            "Heroic" => Ok(Platform::Heroic),
81            "LegacyGames" => Ok(Platform::LegacyGames),
82            "Indiegala" => Ok(Platform::Indiegala),
83            "Itch" => Ok(Platform::Itch),
84            "Indie" => Ok(Platform::Indie),
85            "Outra" => Ok(Platform::Outra),
86            _ => Err(()),
87        }
88    }
89}
90
91impl std::fmt::Display for Platform {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        let s = match self {
94            Platform::Steam => "Steam",
95            Platform::Epic => "Epic",
96            Platform::GOG => "GOG",
97            Platform::Amazon => "Amazon",
98            Platform::EA => "EA",
99            Platform::Ubisoft => "Ubisoft",
100            Platform::BattleNet => "BattleNet",
101            Platform::Xbox => "Xbox",
102            Platform::Heroic => "Heroic",
103            Platform::LegacyGames => "LegacyGames",
104            Platform::Indiegala => "Indiegala",
105            Platform::Itch => "Itch",
106            Platform::Indie => "Indie",
107            Platform::Outra => "Outra",
108        };
109        write!(f, "{}", s)
110    }
111}
112
113// === Modelos de Dados ===
114
115/// Jogo na biblioteca do usuário.
116///
117/// Representa um jogo adicionado à biblioteca pessoal, com metadados
118/// importados da plataforma e dados de progresso do usuário.
119#[derive(Debug, Serialize, Deserialize, Clone)]
120#[serde(rename_all = "camelCase")]
121pub struct Game {
122    pub id: String,
123    pub name: String,
124    pub cover_url: Option<String>,
125    pub genres: Option<String>,
126    pub developer: Option<String>,
127    pub platform: Platform,
128    pub platform_game_id: String,
129
130    // Execução
131    pub installed: bool,
132    pub install_path: Option<String>,
133    pub executable_path: Option<String>,
134    pub launch_args: Option<String>,
135    pub import_confidence: Option<ImportConfidence>,
136
137    // Dados do Usuário
138    pub user_rating: Option<i32>,
139    pub favorite: bool,
140    pub status: Option<String>,
141    pub playtime: Option<i32>,
142
143    // Metadados de Tempo
144    pub last_played: Option<String>,
145    pub added_at: String,
146
147    // Conteúdo Adulto
148    #[serde(default)]
149    pub is_adult: bool,
150}
151
152/// Detalhes adicionais do jogo (Schema v3).
153///
154/// Contém metadados enriquecidos obtidos de APIs externas como RAWG,
155/// substituindo e expandindo os dados anteriores.
156#[derive(Debug, Serialize, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct GameDetails {
159    pub game_id: String,
160    pub steam_app_id: Option<String>,
161
162    // Metadados Básicos
163    pub developer: Option<String>,
164    pub publisher: Option<String>,
165    pub release_date: Option<String>,
166
167    // Categorização
168    pub genres: Option<String>,
169    pub tags: Option<Vec<GameTag>>,
170    pub series: Option<String>,
171
172    // Descrição
173    pub description_raw: Option<String>,
174    pub description_ptbr: Option<String>,
175
176    // Mídia
177    pub background_image: Option<String>,
178
179    // Scores e Avaliações
180    pub critic_score: Option<i32>,
181
182    // Steam Reviews
183    pub steam_review_label: Option<String>,
184    pub steam_review_count: Option<i32>,
185    pub steam_review_score: Option<f32>,
186    pub steam_review_updated_at: Option<String>,
187
188    // Conteúdo Adulto
189    pub esrb_rating: Option<String>,
190    pub is_adult: bool,
191    pub adult_tags: Option<String>,
192
193    // Links Externos
194    pub external_links: Option<HashMap<String, String>>,
195
196    // Tempo de jogo
197    pub median_playtime: Option<i32>, // Alternativa para HLTB (média da Steam)
198    pub estimated_playtime: Option<f32>, // Estimativa de tempo de jogo
199}
200
201/// Jogo na lista de desejos (wishlist) com tracking de preços.
202///
203/// Representa um jogo adicionado à wishlist do usuário,
204/// incluindo informações de preço, disponibilidade e vouchers.
205#[derive(Debug, Serialize, Deserialize)]
206#[serde(rename_all = "camelCase")]
207pub struct WishlistGame {
208    pub id: String,
209    pub name: String,
210    pub cover_url: Option<String>,
211    pub store_url: Option<String>,
212    pub store_platform: Option<String>,
213    pub itad_id: Option<String>,
214    pub current_price: Option<f64>,
215    pub normal_price: Option<f64>,
216    pub lowest_price: Option<f64>,
217    pub currency: Option<String>,
218    pub on_sale: bool,
219    pub voucher: Option<String>,
220    pub added_at: Option<String>,
221}
222
223/// Assinatura de serviço de jogos rastreada pelo usuário.
224///
225/// Representa um serviço como Game Pass, Prime Gaming ou EA Play,
226/// com controle de ativação e timestamp da última sincronização.
227#[derive(Debug, Serialize, Deserialize, Clone)]
228pub struct Subscription {
229    pub service: String, // EX: "game_pass", "prime_gaming", "ea_play", etc.
230    pub enabled: bool,
231    // Timestamp ISO 8601 da última sincronização com a API do serviço. `None` se nunca foi sincronizado.
232    #[serde(rename = "lastSynced")]
233    pub last_synced: Option<String>,
234}
235
236/// Dados técnicos do jogo obtidos do PCGamingWiki.
237///
238/// Tratados como dados estáticos do jogo — não expiram automaticamente.
239/// Atualizados apenas por invalidação explícita.
240///
241/// Tabelas Cargo consultadas: Infobox_game, API, Video, Input, Audio, L10n, Tags.
242#[derive(Debug, Serialize, Deserialize, Default)]
243#[serde(rename_all = "camelCase")]
244pub struct GameExtras {
245    pub steam_app_id: String,
246    pub pcgw_page_id: Option<String>,
247    pub pcgw_page_name: Option<String>,
248    pub engine: Option<String>,
249
250    // Plataformas suportadas — string separada por vírgula, ex: "Windows,Linux"
251    pub available_on: Option<String>,
252
253    // Graphics APIs (tabela API)
254    pub dx_versions: Option<String>, // ex: "11, 12"
255    pub vulkan_versions: Option<String>,
256    pub opengl_versions: Option<String>,
257
258    // Executáveis por OS — confirma suporte real (tabela API)
259    pub win64: Option<String>,
260    pub linux64: Option<String>,
261    #[serde(rename = "macOsArm")]
262    pub macos_arm: Option<String>,
263    #[serde(rename = "macOsIntel64")]
264    pub macos_intel64: Option<String>,
265
266    // Tecnologias gráficas (tabela Video)
267    pub ray_tracing: Option<String>,
268    pub upscaling: Option<String>, // ex: "DLSS 3,FSR 3,XeSS"
269    pub frame_gen: Option<String>, // ex: "DLSS Frame Generation"
270
271    // Display (tabela Video)
272    pub ultrawidescreen: Option<String>,
273    pub four_k_support: Option<String>,
274    pub hdr: Option<String>,
275    pub high_fps: Option<String>, // 120fps+
276    pub fov: Option<String>,      // FOV ajustável
277    pub borderless_windowed: Option<String>,
278    pub color_blind: Option<String>,
279
280    // Controle (tabela Input)
281    pub controller_support: Option<String>,
282    pub full_controller: Option<String>,
283    pub playstation_controllers: Option<String>,
284    pub xinput_controllers: Option<String>,
285
286    // Áudio (tabela Audio)
287    pub surround_sound: Option<String>,
288    pub subtitles: Option<String>,
289    pub closed_captions: Option<String>,
290
291    // Presença de dados (tabela Tags)
292    pub has_save_data: Option<String>,
293    pub has_config_data: Option<String>,
294
295    // Idiomas (tabela L10n) — JSON arrays
296    pub languages_interface: Option<Vec<String>>,
297    pub languages_audio: Option<Vec<String>>,
298    pub languages_subtitles: Option<Vec<String>>,
299
300    pub fetched_at: Option<String>,
301}
302
303/// Requisitos de sistema para um único OS/tier.
304///
305/// Campos `cpu2` e `gpu2` capturam alternativas AMD/Intel quando presentes.
306#[derive(Debug, Clone, Serialize, Deserialize, Default)]
307#[serde(rename_all = "camelCase")]
308pub struct SystemRequirements {
309    pub steam_app_id: String,
310    pub os_family: String, // OS alvo: "Windows", "Linux", "Mac OS", "DOS", etc.
311    pub tier_title: Option<String>, // Rótulo do tier — `None` para padrão (min/rec). Ex: `Some("High")`, `Some("Ultra (1440p)")`.
312    pub target: Option<String>,     // Ex: "1080p, DX11".
313
314    // Mínimo
315    pub min_os: Option<String>,
316    pub min_cpu: Option<String>,
317    pub min_cpu2: Option<String>,
318    pub min_ram: Option<String>,
319    pub min_gpu: Option<String>,
320    pub min_gpu2: Option<String>,
321    pub min_vram: Option<String>,
322    pub min_dx: Option<String>,
323    pub min_storage: Option<String>,
324
325    // Recomendado
326    pub rec_os: Option<String>,
327    pub rec_cpu: Option<String>,
328    pub rec_cpu2: Option<String>,
329    pub rec_ram: Option<String>,
330    pub rec_gpu: Option<String>,
331    pub rec_gpu2: Option<String>,
332    pub rec_vram: Option<String>,
333    pub rec_dx: Option<String>,
334    pub rec_storage: Option<String>,
335}
336
337/// Caminho de dado do jogo (save ou config) para um OS específico.
338#[derive(Debug, Clone, Serialize, Deserialize)]
339#[serde(rename_all = "camelCase")]
340pub struct GameDataPath {
341    pub steam_app_id: String,
342    pub kind: String,                  // Tipo do dado: `"config"` ou `"saves"`.
343    pub os: String,                    // OS alvo: `"Windows"`, `"Linux"`, `"OS X"`, etc.
344    pub raw_path: String, // Caminho bruto preservando `{{p|variavel}}`. Ex: `"{{p|userprofile\\Documents}}\\Reus\\"`.
345    pub expanded_path: Option<String>, // Caminho com variáveis expandidas. `None` até que o frontend expanda `{{p|...}}`.
346}
347
348/// Resultado completo do scraping de uma página do PCGamingWiki.
349#[derive(Debug, Default, Serialize, Deserialize)]
350#[serde(rename_all = "camelCase")]
351pub struct PcgwScrapedData {
352    pub system_requirements: Vec<SystemRequirements>,
353    pub game_data_paths: Vec<GameDataPath>,
354}