1#![warn(missing_docs)]
7#![warn(rustdoc::missing_crate_level_docs)]
8#![forbid(unsafe_code)]
9
10use chrono::{DateTime, Utc};
11use serde::{Deserialize, Serialize};
12
13pub mod analysis;
14pub mod error;
15pub mod metrics;
16pub mod profiles;
17pub mod scoring;
18
19pub use profiles::ProfileWeights;
20
21pub type Result<T> = std::result::Result<T, error::CrabScoreError>;
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27
28 #[test]
29 fn test_industry_profile_weights() {
30 let profile = IndustryProfile::WebServices;
31 let weights = profile.weights();
32 assert!((weights.performance + weights.energy + weights.cost - 1.0).abs() < f64::EPSILON);
33 }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct CrabScore {
39 pub overall: f64,
41 pub performance: f64,
43 pub energy: f64,
45 pub cost: f64,
47 pub bonuses: f64,
49 pub certification: Certification,
51 pub timestamp: DateTime<Utc>,
53 pub metadata: ScoreMetadata,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct ScoreMetadata {
60 pub project_name: String,
62 pub version: String,
64 pub profile: IndustryProfile,
66 pub measurements: MeasurementSummary,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct MeasurementSummary {
73 pub duration: std::time::Duration,
75 pub iterations: u64,
77 pub environment: Environment,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct Environment {
84 pub os: String,
86 pub cpu: String,
88 pub memory_gb: f32,
90 pub rust_version: String,
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
96pub enum Certification {
97 None,
99 Verified,
101 Certified,
103 Elite,
105 Pioneer,
107 Sustainable,
109}
110
111#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
113pub enum IndustryProfile {
114 WebServices,
116 IotEmbedded,
118 Financial,
120 Gaming,
122 Enterprise,
124}
125
126impl Default for IndustryProfile {
128 fn default() -> Self {
129 Self::WebServices
130 }
131}
132
133impl IndustryProfile {
134 pub fn weights(&self) -> ProfileWeights {
136 match self {
137 Self::WebServices => ProfileWeights::new(0.4, 0.3, 0.3),
138 Self::IotEmbedded => ProfileWeights::new(0.2, 0.6, 0.2),
139 Self::Financial => ProfileWeights::new(0.5, 0.2, 0.3),
140 Self::Gaming => ProfileWeights::new(0.6, 0.2, 0.2),
141 Self::Enterprise => ProfileWeights::new(0.3, 0.3, 0.4),
142 }
143 }
144}