1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::collections::HashMap;

use serde::Deserialize;

use crate::system::{System, SystemTweaks};

#[derive(PartialEq, Debug, Deserialize)]
pub struct TweakSettings {
    pub gamemode: Option<bool>,
    pub mangohud: Option<bool>,
}

#[derive(Debug, Deserialize)]
pub struct Issue {
    pub description: String,
    pub solution: String,
}

#[derive(Debug, Deserialize)]
pub struct Tweaks {
    pub tricks: Vec<String>,
    pub env: HashMap<String, String>,
    pub args: Vec<String>,
    pub settings: TweakSettings,
    pub system: System,
}

#[derive(Debug, Deserialize)]
pub struct App {
    pub id: String,
    pub name: String,
    pub tweaks: Tweaks,
    pub issues: Vec<Issue>,
}

impl Clone for TweakSettings {
    fn clone(&self) -> Self {
        Self {
            gamemode: self.gamemode.clone(),
            mangohud: self.mangohud.clone(),
        }
    }
}

impl App {
    /// Utilizes system info to flatten out the App into a collection of applicable tweaks
    pub async fn flatten(&self) -> SystemTweaks {
        let mut env = self.tweaks.env.clone();
        let mut tricks = self.tweaks.tricks.clone();
        let mut args = self.tweaks.args.clone();
        let mut settings = self.tweaks.settings.clone();

        if let Some(gpu_tweaks) = self.tweaks.system.gpu_driver.get_tweaks().await {
            // gpu-level settings overwrite global settings
            env.extend(gpu_tweaks.env.clone());
            tricks.extend(gpu_tweaks.tricks.clone());
            args.extend(gpu_tweaks.args.clone());

            if let Some(gamemode) = gpu_tweaks.settings.gamemode {
                settings.gamemode = Some(gamemode);
            }

            if let Some(mangohud) = gpu_tweaks.settings.mangohud {
                settings.mangohud = Some(mangohud);
            }
        }

        SystemTweaks {
            env,
            args,
            tricks,
            settings,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::Protontweaks;

    #[tokio::test]
    async fn flatten() {
        let api = Protontweaks::new();

        let app = api.app("644930").await;

        assert_eq!(app.tweaks.tricks.len(), app.flatten().await.tricks.len());
    }
}