rush_sync_server/commands/performance/
manager.rs

1// =====================================================
2// FILE: src/commands/performance/manager.rs - BUSINESS LOGIC
3// =====================================================
4
5use crate::core::prelude::*;
6
7/// Zentrale Verwaltung aller Performance-Operationen
8pub struct PerformanceManager;
9
10impl PerformanceManager {
11    /// Zeigt vollständigen Performance-Status
12    pub fn get_status() -> Result<String> {
13        let config_data = Self::load_config_values()?;
14        let performance_analysis = Self::analyze_performance(&config_data);
15
16        // ✅ TEST 1: Einfache Version OHNE i18n
17        let simple_report = format!(
18            "SIMPLE PERFORMANCE:\nPoll: {}ms\nTypewriter: {}ms\nMessages: {}\nHistory: {}",
19            config_data.poll_rate,
20            config_data.typewriter_delay,
21            config_data.max_messages,
22            config_data.max_history
23        );
24
25        // ✅ TEST 2: Deutsche i18n Version (problematisch?)
26        let i18n_report = Self::format_status_report(&config_data, &performance_analysis);
27
28        // ✅ DEBUG: Zähle Zeilen in beiden Versionen
29        let simple_lines = simple_report.lines().count();
30        let i18n_lines = i18n_report.lines().count();
31
32        log::info!("📊 PERFORMANCE DEBUG:");
33        log::info!("   Simple version: {} lines", simple_lines);
34        log::info!("   i18n version: {} lines", i18n_lines);
35        log::info!(
36            "   First 100 chars of i18n: {}",
37            &i18n_report.chars().take(100).collect::<String>()
38        );
39
40        // ✅ TEST: Verwende einfache Version zum Testen
41        if simple_lines <= 6 {
42            Ok(simple_report)
43        } else {
44            // Falls das auch Probleme macht, ultraminimal:
45            Ok(format!(
46                "Performance: {}ms poll, {}ms typewriter",
47                config_data.poll_rate, config_data.typewriter_delay
48            ))
49        }
50    }
51    /// Lädt Config-Werte direkt aus Datei (robust & schnell)
52    fn load_config_values() -> Result<ConfigData> {
53        let paths = crate::setup::setup_toml::get_config_paths();
54
55        for path in paths {
56            if path.exists() {
57                if let Ok(content) = std::fs::read_to_string(&path) {
58                    // ✅ CLIPPY FIX: Initialisierung mit struct literal statt Default + assignment
59                    let mut config_data = ConfigData {
60                        config_path: path.display().to_string(),
61                        config_name: path
62                            .file_name()
63                            .unwrap_or_default()
64                            .to_string_lossy()
65                            .to_string(),
66                        ..Default::default() // ✅ Rest mit Default füllen
67                    };
68
69                    // ✅ ROBUSTES PARSING (Line-by-Line) bleibt gleich
70                    for line in content.lines() {
71                        let line = line.trim();
72                        if line.starts_with("poll_rate") && line.contains('=') {
73                            if let Some(value_str) = line.split('=').nth(1) {
74                                if let Ok(value) = value_str.trim().parse::<u64>() {
75                                    config_data.poll_rate = value;
76                                }
77                            }
78                        } else if line.starts_with("typewriter_delay") && line.contains('=') {
79                            if let Some(value_str) = line.split('=').nth(1) {
80                                if let Ok(value) = value_str.trim().parse::<u64>() {
81                                    config_data.typewriter_delay = value;
82                                }
83                            }
84                        } else if line.starts_with("max_messages") && line.contains('=') {
85                            if let Some(value_str) = line.split('=').nth(1) {
86                                if let Ok(value) = value_str.trim().parse::<u64>() {
87                                    config_data.max_messages = value;
88                                }
89                            }
90                        } else if line.starts_with("max_history") && line.contains('=') {
91                            if let Some(value_str) = line.split('=').nth(1) {
92                                if let Ok(value) = value_str.trim().parse::<u64>() {
93                                    config_data.max_history = value;
94                                }
95                            }
96                        } else if line.starts_with("log_level") && line.contains('=') {
97                            if let Some(value_str) = line.split('=').nth(1) {
98                                config_data.log_level =
99                                    value_str.trim().trim_matches('"').trim().to_string();
100                            }
101                        }
102                    }
103
104                    return Ok(config_data);
105                }
106            }
107        }
108
109        Err(AppError::Validation(
110            "Keine Config-Datei gefunden".to_string(),
111        ))
112    }
113
114    /// Analysiert Performance-Werte und gibt Bewertung zurück
115    fn analyze_performance(config: &ConfigData) -> PerformanceAnalysis {
116        let fps = 1000.0 / config.poll_rate as f64;
117
118        let poll_status = match config.poll_rate {
119            0 => PerformanceStatus::Critical,
120            1..=15 => PerformanceStatus::Critical,
121            16..=33 => PerformanceStatus::Optimal,
122            34..=50 => PerformanceStatus::Good,
123            51..=100 => PerformanceStatus::Slow,
124            _ => PerformanceStatus::VerySlow,
125        };
126
127        let typewriter_info = if config.typewriter_delay == 0 {
128            TypewriterInfo {
129                chars_per_sec: None,
130                is_active: false,
131            }
132        } else {
133            let chars_per_sec = 1000.0 / config.typewriter_delay as f64;
134            TypewriterInfo {
135                chars_per_sec: Some(chars_per_sec),
136                is_active: true,
137            }
138        };
139
140        PerformanceAnalysis {
141            fps,
142            poll_status,
143            typewriter_info,
144        }
145    }
146
147    /// Formatiert den vollständigen Status-Report (i18n-fähig)
148    fn format_status_report(config: &ConfigData, analysis: &PerformanceAnalysis) -> String {
149        let status_icon = match analysis.poll_status {
150            PerformanceStatus::Critical => "🔥",
151            PerformanceStatus::Optimal => "✅",
152            PerformanceStatus::Good => "✅",
153            PerformanceStatus::Slow => "⚠️",
154            PerformanceStatus::VerySlow => "❌",
155        };
156
157        let typewriter_icon = if analysis.typewriter_info.is_active {
158            "⌨️"
159        } else {
160            "🚫"
161        };
162
163        // ✅ i18n STRINGS verwenden statt hardcoded
164        let header = crate::i18n::get_translation("system.commands.performance.header", &[]);
165        let poll_label = crate::i18n::get_translation("system.commands.performance.poll_rate", &[]);
166        let typewriter_label =
167            crate::i18n::get_translation("system.commands.performance.typewriter", &[]);
168        let messages_label =
169            crate::i18n::get_translation("system.commands.performance.max_messages", &[]);
170        let history_label =
171            crate::i18n::get_translation("system.commands.performance.max_history", &[]);
172        let log_label = crate::i18n::get_translation("system.commands.performance.log_level", &[]);
173        let config_label = crate::i18n::get_translation("system.commands.performance.config", &[]);
174        let recommendations =
175            crate::i18n::get_translation("system.commands.performance.recommendations", &[]);
176        let commands_label =
177            crate::i18n::get_translation("system.commands.performance.related_commands", &[]);
178        let config_edit =
179            crate::i18n::get_translation("system.commands.performance.config_edit", &[]);
180        let log_change =
181            crate::i18n::get_translation("system.commands.performance.log_change", &[]);
182        let version_cmd =
183            crate::i18n::get_translation("system.commands.performance.version_cmd", &[]);
184        let restart_cmd =
185            crate::i18n::get_translation("system.commands.performance.restart_cmd", &[]);
186
187        // ✅ STATUS MESSAGE übersetzt
188        let status_message = match analysis.poll_status {
189            PerformanceStatus::Critical => {
190                crate::i18n::get_translation("system.commands.performance.status.critical", &[])
191            }
192            PerformanceStatus::Optimal => {
193                crate::i18n::get_translation("system.commands.performance.status.optimal", &[])
194            }
195            PerformanceStatus::Good => {
196                crate::i18n::get_translation("system.commands.performance.status.good", &[])
197            }
198            PerformanceStatus::Slow => {
199                crate::i18n::get_translation("system.commands.performance.status.slow", &[])
200            }
201            PerformanceStatus::VerySlow => {
202                crate::i18n::get_translation("system.commands.performance.status.very_slow", &[])
203            }
204        };
205
206        // ✅ TYPEWRITER STATUS übersetzt
207        let typewriter_status = if analysis.typewriter_info.is_active {
208            crate::i18n::get_translation(
209                "system.commands.performance.typewriter.active",
210                &[&format!(
211                    "{:.1}",
212                    analysis.typewriter_info.chars_per_sec.unwrap_or(0.0)
213                )],
214            )
215        } else {
216            crate::i18n::get_translation("system.commands.performance.typewriter.disabled", &[])
217        };
218
219        format!(
220            "{}\n\n\
221            🎯 {}: {}ms ({:.1} FPS) {} {}\n\
222            {} {}: {}ms ({})\n\
223            📈 {}: {}\n\
224            📜 {}: {}\n\
225            🎨 {}: {}\n\
226            📍 {}: {}\n\n\
227            💡 {}:\n\
228            {}\n\n\
229            🔧 {}:\n\
230            • {}: {}\n\
231            • {}\n\
232            • {}: 'version'\n\
233            • {}: 'restart'",
234            header,
235            poll_label,
236            config.poll_rate,
237            analysis.fps,
238            status_icon,
239            status_message,
240            typewriter_icon,
241            typewriter_label,
242            config.typewriter_delay,
243            typewriter_status,
244            messages_label,
245            config.max_messages,
246            history_label,
247            config.max_history,
248            log_label,
249            config.log_level.to_uppercase(),
250            config_label,
251            config.config_name,
252            recommendations,
253            crate::i18n::get_translation(
254                "system.commands.performance.recommendations.content",
255                &[]
256            ),
257            commands_label,
258            config_edit,
259            config.config_path,
260            log_change,
261            version_cmd,
262            restart_cmd
263        )
264    }
265}
266
267// =====================================================
268// DATENSTRUKTUREN
269// =====================================================
270
271#[derive(Debug, Default)]
272struct ConfigData {
273    poll_rate: u64,
274    typewriter_delay: u64,
275    max_messages: u64,
276    max_history: u64,
277    log_level: String,
278    config_path: String,
279    config_name: String,
280}
281
282#[derive(Debug)]
283struct PerformanceAnalysis {
284    fps: f64,
285    poll_status: PerformanceStatus,
286    typewriter_info: TypewriterInfo,
287}
288
289#[derive(Debug)]
290enum PerformanceStatus {
291    Critical,
292    Optimal,
293    Good,
294    Slow,
295    VerySlow,
296}
297
298#[derive(Debug)]
299struct TypewriterInfo {
300    chars_per_sec: Option<f64>,
301    is_active: bool,
302}