1pub fn savings_pct(original_chars: usize, actual_chars: usize) -> f64 {
10 if original_chars == 0 {
11 return 0.0;
12 }
13 (1.0 - actual_chars as f64 / original_chars as f64) * 100.0
14}
15
16pub fn report_savings(base_url: &str, original_chars: usize, actual_chars: usize) {
21 let url = format!("{}/api/admin/savings/record", base_url);
22 let payload = serde_json::json!({
23 "category": "code_index",
24 "original_chars": original_chars,
25 "actual_chars": actual_chars,
26 "metadata": { "strategy": "outline" }
27 });
28 let _ = ureq::post(&url)
29 .timeout(std::time::Duration::from_secs(1))
30 .send_json(payload);
31}
32
33pub fn resolve_daemon_url(config_url: Option<&str>) -> Option<String> {
37 if let Some(url) = config_url {
38 if url.contains("${GOBBY_PORT}") {
40 if let Ok(port) = std::env::var("GOBBY_PORT") {
41 return Some(url.replace("${GOBBY_PORT}", &port));
42 }
43 } else {
45 return Some(url.to_string());
46 }
47 }
48
49 if let Ok(port) = std::env::var("GOBBY_PORT") {
51 return Some(format!("http://localhost:{}", port));
52 }
53
54 Some("http://localhost:60887".to_string())
56}
57
58pub fn print_savings(label: &str, original_chars: usize, actual_chars: usize) {
60 if actual_chars == 0 || original_chars <= actual_chars {
61 return;
62 }
63 let pct = savings_pct(original_chars, actual_chars);
64 eprintln!("[gcode \u{2014} {label}, saved {pct:.0}% ({actual_chars}B vs {original_chars}B)]");
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_savings_pct_basic() {
73 let pct = savings_pct(1000, 200);
74 assert!((pct - 80.0).abs() < 0.01);
75 }
76
77 #[test]
78 fn test_savings_pct_zero_original() {
79 assert_eq!(savings_pct(0, 0), 0.0);
80 }
81
82 #[test]
83 fn test_savings_pct_no_savings() {
84 assert!((savings_pct(100, 100)).abs() < 0.01);
85 }
86
87 #[test]
88 fn test_resolve_daemon_url_config_value() {
89 let url = resolve_daemon_url(Some("http://custom:9999"));
90 assert_eq!(url, Some("http://custom:9999".to_string()));
91 }
92
93 #[test]
94 #[serial_test::serial]
95 fn test_resolve_daemon_url_env_var() {
96 unsafe { std::env::set_var("GOBBY_PORT", "12345") };
97 let url = resolve_daemon_url(None);
98 assert_eq!(url, Some("http://localhost:12345".to_string()));
99 unsafe { std::env::remove_var("GOBBY_PORT") };
100 }
101
102 #[test]
103 #[serial_test::serial]
104 fn test_resolve_daemon_url_default() {
105 unsafe { std::env::remove_var("GOBBY_PORT") };
106 let url = resolve_daemon_url(None);
107 assert_eq!(url, Some("http://localhost:60887".to_string()));
108 }
109
110 #[test]
111 #[serial_test::serial]
112 fn test_resolve_daemon_url_expand_port() {
113 unsafe { std::env::set_var("GOBBY_PORT", "54321") };
114 let url = resolve_daemon_url(Some("http://myhost:${GOBBY_PORT}"));
115 assert_eq!(url, Some("http://myhost:54321".to_string()));
116 unsafe { std::env::remove_var("GOBBY_PORT") };
117 }
118}