Skip to main content

gobby_code/
savings.rs

1//! Daemon-based savings tracking for gcode.
2//!
3//! Reports token savings to the Gobby daemon via HTTP POST when gcode returns
4//! compact symbol/outline data instead of full file contents.
5
6/// Calculate savings percentage.
7pub fn savings_pct(original_chars: usize, actual_chars: usize) -> f64 {
8    if original_chars == 0 {
9        return 0.0;
10    }
11    (1.0 - actual_chars as f64 / original_chars as f64) * 100.0
12}
13
14/// Report a savings event to the Gobby daemon via HTTP POST.
15///
16/// Best-effort: all errors are silently ignored. The daemon being down
17/// should never break gcode functionality.
18pub fn report_savings(base_url: &str, original_chars: usize, actual_chars: usize) {
19    let url = format!("{}/api/admin/savings/record", base_url);
20    let payload = serde_json::json!({
21        "category": "code_index",
22        "original_chars": original_chars,
23        "actual_chars": actual_chars,
24        "metadata": { "strategy": "outline" }
25    });
26    let _ = ureq::post(&url)
27        .timeout(std::time::Duration::from_secs(1))
28        .send_json(payload);
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn test_savings_pct_basic() {
37        let pct = savings_pct(1000, 200);
38        assert!((pct - 80.0).abs() < 0.01);
39    }
40
41    #[test]
42    fn test_savings_pct_zero_original() {
43        assert_eq!(savings_pct(0, 0), 0.0);
44    }
45
46    #[test]
47    fn test_savings_pct_no_savings() {
48        assert!((savings_pct(100, 100)).abs() < 0.01);
49    }
50}