First one-shot pass

This commit is contained in:
2026-02-10 14:29:23 -05:00
parent 739d79d6a2
commit f65e3d8413
48 changed files with 5409 additions and 2 deletions

45
src/engine/scoring.rs Normal file
View File

@@ -0,0 +1,45 @@
use crate::session::result::LessonResult;
pub fn compute_score(result: &LessonResult, complexity: f64) -> f64 {
let speed = result.cpm;
let errors = result.incorrect as f64;
let length = result.total_chars as f64;
(speed * complexity) / (errors + 1.0) * (length / 50.0)
}
pub fn compute_complexity(unlocked_count: usize) -> f64 {
(unlocked_count as f64 / 26.0).max(0.1)
}
pub fn level_from_score(total_score: f64) -> u32 {
let level = (total_score / 100.0).sqrt() as u32;
level.max(1)
}
#[allow(dead_code)]
pub fn score_to_next_level(total_score: f64) -> f64 {
let current_level = level_from_score(total_score);
let next_level_score = ((current_level + 1) as f64).powi(2) * 100.0;
next_level_score - total_score
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_level_starts_at_one() {
assert_eq!(level_from_score(0.0), 1);
}
#[test]
fn test_level_increases_with_score() {
assert!(level_from_score(1000.0) > level_from_score(100.0));
}
#[test]
fn test_complexity_scales_with_letters() {
assert!(compute_complexity(26) > compute_complexity(6));
assert!((compute_complexity(26) - 1.0).abs() < 0.001);
}
}