use rusqlite::Connection;
const CHARS_PER_TOKEN: f64 = 3.7;
pub fn savings_pct(original_chars: usize, actual_chars: usize) -> f64 {
if original_chars == 0 {
return 0.0;
}
(1.0 - actual_chars as f64 / original_chars as f64) * 100.0
}
pub fn record_savings(
conn: &Connection,
category: &str,
original_chars: usize,
actual_chars: usize,
project_id: Option<&str>,
metadata: Option<&str>,
) -> anyhow::Result<()> {
let original_tokens = (original_chars as f64 / CHARS_PER_TOKEN) as i64;
let actual_tokens = (actual_chars as f64 / CHARS_PER_TOKEN) as i64;
let tokens_saved = (original_tokens - actual_tokens).max(0);
let result = conn.execute(
"INSERT INTO savings_ledger \
(session_id, project_id, category, original_tokens, actual_tokens, \
tokens_saved, cost_saved_usd, model, metadata) \
VALUES (NULL, ?1, ?2, ?3, ?4, ?5, 0.0, NULL, ?6)",
rusqlite::params![
project_id,
category,
original_tokens,
actual_tokens,
tokens_saved,
metadata,
],
);
if let Err(e) = result {
eprintln!("Warning: failed to record savings: {e}");
}
Ok(())
}
pub fn print_savings(label: &str, original_chars: usize, actual_chars: usize) {
if original_chars <= actual_chars || original_chars == 0 {
return;
}
let pct = savings_pct(original_chars, actual_chars);
eprintln!("[gcode \u{2014} {label}, saved {pct:.0}% ({actual_chars}B vs {original_chars}B)]");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_chars_to_tokens() {
let tokens = (3700.0 / CHARS_PER_TOKEN) as i64;
assert_eq!(tokens, 1000);
}
#[test]
fn test_savings_pct_basic() {
let pct = savings_pct(1000, 200);
assert!((pct - 80.0).abs() < 0.01);
}
#[test]
fn test_savings_pct_zero_original() {
assert_eq!(savings_pct(0, 0), 0.0);
}
#[test]
fn test_savings_pct_no_savings() {
assert!((savings_pct(100, 100)).abs() < 0.01);
}
#[test]
fn test_record_savings_insert() {
let conn = Connection::open_in_memory().unwrap();
conn.execute_batch(
"CREATE TABLE savings_ledger (
session_id TEXT,
project_id TEXT,
category TEXT NOT NULL,
original_tokens INTEGER NOT NULL,
actual_tokens INTEGER NOT NULL,
tokens_saved INTEGER NOT NULL,
cost_saved_usd REAL NOT NULL,
model TEXT,
metadata TEXT
)",
)
.unwrap();
record_savings(
&conn,
"code_index",
3700,
370,
Some("test-project"),
Some(r#"{"symbol":"foo"}"#),
)
.unwrap();
let count: i64 = conn
.query_row("SELECT COUNT(*) FROM savings_ledger", [], |row| row.get(0))
.unwrap();
assert_eq!(count, 1);
let (original, actual, saved): (i64, i64, i64) = conn
.query_row(
"SELECT original_tokens, actual_tokens, tokens_saved FROM savings_ledger",
[],
|row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)),
)
.unwrap();
assert_eq!(original, 1000);
assert_eq!(actual, 100);
assert_eq!(saved, 900);
}
}