Skip to main content

netspeed_cli/
result_processor.rs

1//! Responsible for grading test results.
2use crate::{grades, profiles::UserProfile, types::TestResult};
3
4/// Trait so callers can plug‑in alternative rating engines.
5pub trait ResultProcessor {
6    fn process(&self, result: &mut TestResult, profile: UserProfile);
7}
8
9/// Default implementation matching the historic behaviour.
10pub struct DefaultResultProcessor;
11
12impl DefaultResultProcessor {
13    // Convenience wrapper for legacy tests
14    pub fn process(
15        &self,
16        result: &mut crate::types::TestResult,
17        profile: crate::profiles::UserProfile,
18    ) {
19        ResultProcessor::process(self, result, profile);
20    }
21}
22
23impl ResultProcessor for DefaultResultProcessor {
24    fn process(&self, result: &mut TestResult, profile: UserProfile) {
25        // Compute overall grade only when we have any measurement data.
26        if result.ping.is_some()
27            || result.jitter.is_some()
28            || result.download.is_some()
29            || result.upload.is_some()
30        {
31            let overall = grades::grade_overall(
32                result.ping,
33                result.jitter,
34                result.download,
35                result.upload,
36                profile,
37            );
38            result.overall_grade = Some(overall.as_str().to_string());
39        }
40        result.download_grade = result.download.map(|d| {
41            grades::grade_download(d / 1_000_000.0, profile)
42                .as_str()
43                .to_string()
44        });
45        result.upload_grade = result.upload.map(|u| {
46            grades::grade_upload(u / 1_000_000.0, profile)
47                .as_str()
48                .to_string()
49        });
50        result.connection_rating =
51            Some(crate::formatter::ratings::connection_rating(result).to_string());
52    }
53}