crabscore_core/
scoring.rs1use crate::{
4 metrics::{CostMetrics, EnergyMetrics, PerformanceMetrics, SafetyMetrics},
5 CrabScore, IndustryProfile,
6};
7
8pub struct ScoringEngine {
10 profile: IndustryProfile,
11}
12
13impl ScoringEngine {
14 pub fn new(profile: IndustryProfile) -> Self {
16 Self { profile }
17 }
18
19 pub fn calculate_score(
21 &self,
22 performance: &PerformanceMetrics,
23 energy: &EnergyMetrics,
24 cost: &CostMetrics,
25 safety: &SafetyMetrics,
26 ) -> CrabScore {
27 let weights = self.profile.weights();
28
29 let perf_score = self.score_performance(performance);
30 let energy_score = self.score_energy(energy);
31 let cost_score = self.score_cost(cost);
32 let bonuses = self.score_safety(safety);
33
34 let overall = (perf_score * weights.performance)
35 + (energy_score * weights.energy)
36 + (cost_score * weights.cost)
37 + bonuses;
38
39 let certification = if overall >= 85.0 {
40 crate::Certification::Certified
41 } else if overall >= 70.0 {
42 crate::Certification::Verified
43 } else {
44 crate::Certification::None
45 };
46
47 let metadata = crate::ScoreMetadata {
48 project_name: String::new(),
49 version: String::new(),
50 profile: self.profile,
51 measurements: crate::MeasurementSummary {
52 duration: std::time::Duration::from_secs(0),
53 iterations: 0,
54 environment: crate::Environment {
55 os: String::new(),
56 cpu: String::new(),
57 memory_gb: 0.0,
58 rust_version: String::new(),
59 },
60 },
61 };
62
63 CrabScore {
64 overall,
65 performance: perf_score,
66 energy: energy_score,
67 cost: cost_score,
68 bonuses,
69 certification,
70 timestamp: chrono::Utc::now(),
71 metadata,
72 }
73 }
74
75 fn clamp(v: f64) -> f64 {
80 v.clamp(0.0, 100.0)
81 }
82
83 fn score_performance(&self, m: &PerformanceMetrics) -> f64 {
84 let latency_ms = m.latency.p95_ms.max(1.0); let latency_score = (1.0 / (1.0 + latency_ms / 100.0)) * 100.0;
87
88 let tps = m.throughput.requests_per_second;
89 let throughput_score = (tps / (tps + 1000.0)) * 100.0;
90
91 let resource_score = 100.0 * m.resource_usage.cpu_efficiency.min(1.0);
92
93 Self::clamp((latency_score + throughput_score + resource_score) / 3.0)
94 }
95
96 fn score_energy(&self, m: &EnergyMetrics) -> f64 {
97 let watts = m.direct_consumption.average_watts.max(1.0);
99 let power_score = (1.0 / (1.0 + watts / 100.0)) * 100.0;
100 let renewable_score = m.carbon_efficiency.renewable_percentage * 100.0;
101 Self::clamp((power_score + renewable_score) / 2.0)
102 }
103
104 fn score_cost(&self, m: &CostMetrics) -> f64 {
105 let infra = m.infrastructure.cloud_compute_usd;
106 let infra_score = (1.0 / (1.0 + infra / 1000.0)) * 100.0;
107 let ops_score = (1.0 / (1.0 + m.operations.overhead_percentage)) * 100.0;
108 Self::clamp((infra_score + ops_score) / 2.0)
109 }
110
111 fn score_safety(&self, s: &SafetyMetrics) -> f64 {
112 let mut bonus = 0.0;
113 if s.unsafe_blocks == 0 {
114 bonus += 4.0;
115 }
116 if s.clippy_warnings == 0 {
117 bonus += 3.0;
118 }
119 if s.avg_cyclomatic <= 10.0 {
120 bonus += 3.0;
121 }
122 bonus }
124}