use super::types::*;
use std::collections::HashMap;
pub const VIBE_WEB_BENCHMARK: f64 = 0.915;
pub const VIBE_ANDROID_BENCHMARK: f64 = 0.897;
pub const VIBE_IOS_BENCHMARK: f64 = 0.880;
pub struct VibeBenchmarkEvaluator {
platform: Platform,
}
impl VibeBenchmarkEvaluator {
pub fn new(platform: Platform) -> Self {
Self { platform }
}
pub fn benchmark_target(&self) -> f64 {
match self.platform {
Platform::Web => VIBE_WEB_BENCHMARK,
Platform::Android => VIBE_ANDROID_BENCHMARK,
Platform::IOS => VIBE_IOS_BENCHMARK,
Platform::Desktop => (VIBE_WEB_BENCHMARK + VIBE_IOS_BENCHMARK) / 2.0,
}
}
pub fn evaluate(&self, input: &DesignInput) -> VibeComplianceResult {
let criteria_results = self.evaluate_all_criteria(input);
let total_weight: f64 = criteria_results.iter().map(|c| c.weight).sum();
let weighted_score: f64 = criteria_results
.iter()
.map(|c| c.score * c.weight)
.sum::<f64>()
/ total_weight;
let mut platform_scores = HashMap::new();
platform_scores.insert(self.platform, weighted_score);
let passes_threshold = weighted_score >= self.benchmark_target();
VibeComplianceResult {
platform_scores,
overall_score: weighted_score,
passes_threshold,
criteria_results,
}
}
fn evaluate_all_criteria(&self, input: &DesignInput) -> Vec<VibeCriterionResult> {
vec![
self.evaluate_visual_coherence(input),
self.evaluate_interaction_quality(input),
self.evaluate_brand_consistency(input),
self.evaluate_element_alignment(input),
self.evaluate_typography_excellence(input),
self.evaluate_color_harmony(input),
self.evaluate_spacing_system(input),
self.evaluate_responsive_design(input),
self.evaluate_accessibility_compliance(input),
self.evaluate_performance_impact(input),
]
}
fn evaluate_visual_coherence(&self, input: &DesignInput) -> VibeCriterionResult {
let score = if input.design_tokens.is_some() {
0.92
} else {
0.75
};
VibeCriterionResult {
criterion: "Visual Coherence".to_string(),
score,
weight: 1.5,
details: "Evaluates overall visual unity and design system adherence".to_string(),
}
}
fn evaluate_interaction_quality(&self, input: &DesignInput) -> VibeCriterionResult {
let score = match input.component_type {
ComponentType::Button => 0.95,
ComponentType::Form => 0.88,
ComponentType::Navigation => 0.90,
ComponentType::Modal => 0.85,
_ => 0.82,
};
VibeCriterionResult {
criterion: "Interaction Quality".to_string(),
score,
weight: 1.3,
details: "Measures clarity and intuitiveness of interactive elements".to_string(),
}
}
fn evaluate_brand_consistency(&self, input: &DesignInput) -> VibeCriterionResult {
let score = if let Some(tokens) = &input.design_tokens {
if tokens.colors.primary.is_some() && tokens.typography.font_family_primary.is_some() {
0.90
} else {
0.70
}
} else {
0.60
};
VibeCriterionResult {
criterion: "Brand Consistency".to_string(),
score,
weight: 1.2,
details: "Checks adherence to brand guidelines and design tokens".to_string(),
}
}
fn evaluate_element_alignment(&self, _input: &DesignInput) -> VibeCriterionResult {
VibeCriterionResult {
criterion: "Element Alignment".to_string(),
score: 0.88,
weight: 1.0,
details: "Measures grid adherence and element alignment precision".to_string(),
}
}
fn evaluate_typography_excellence(&self, input: &DesignInput) -> VibeCriterionResult {
let score = if let Some(tokens) = &input.design_tokens {
if !tokens.typography.font_sizes.is_empty()
&& !tokens.typography.line_heights.is_empty()
{
0.92
} else {
0.75
}
} else {
0.70
};
VibeCriterionResult {
criterion: "Typography Excellence".to_string(),
score,
weight: 1.2,
details: "Evaluates font choices, hierarchy, and readability".to_string(),
}
}
fn evaluate_color_harmony(&self, input: &DesignInput) -> VibeCriterionResult {
let score = if let Some(tokens) = &input.design_tokens {
let has_primary = tokens.colors.primary.is_some();
let has_secondary = tokens.colors.secondary.is_some();
let has_background = tokens.colors.background.is_some();
let has_text = tokens.colors.text_primary.is_some();
let completeness = [has_primary, has_secondary, has_background, has_text]
.iter()
.filter(|&&x| x)
.count() as f64
/ 4.0;
0.70 + (completeness * 0.25)
} else {
0.70
};
VibeCriterionResult {
criterion: "Color Harmony".to_string(),
score,
weight: 1.1,
details: "Checks color relationships and contrast compliance".to_string(),
}
}
fn evaluate_spacing_system(&self, input: &DesignInput) -> VibeCriterionResult {
let score = if let Some(tokens) = &input.design_tokens {
if tokens.spacing.base_unit.is_some() || !tokens.spacing.scale.is_empty() {
0.90
} else {
0.70
}
} else {
0.65
};
VibeCriterionResult {
criterion: "Spacing System".to_string(),
score,
weight: 1.0,
details: "Evaluates spacing consistency and rhythm".to_string(),
}
}
fn evaluate_responsive_design(&self, _input: &DesignInput) -> VibeCriterionResult {
let score = match self.platform {
Platform::Web => 0.88,
Platform::Android => 0.85, Platform::IOS => 0.82, Platform::Desktop => 0.90, };
VibeCriterionResult {
criterion: "Responsive Design".to_string(),
score,
weight: 1.0,
details: "Measures adaptation to different screen sizes".to_string(),
}
}
fn evaluate_accessibility_compliance(&self, input: &DesignInput) -> VibeCriterionResult {
let score = if input.design_tokens.is_some() {
0.85
} else {
0.70
};
VibeCriterionResult {
criterion: "Accessibility Compliance".to_string(),
score,
weight: 1.3,
details: "Checks WCAG compliance and inclusive design".to_string(),
}
}
fn evaluate_performance_impact(&self, input: &DesignInput) -> VibeCriterionResult {
let score = match input.component_type {
ComponentType::Hero => 0.80, ComponentType::Page => 0.82,
ComponentType::Card => 0.92,
ComponentType::Button => 0.95,
_ => 0.85,
};
VibeCriterionResult {
criterion: "Performance Impact".to_string(),
score,
weight: 1.1,
details: "Measures design efficiency and load impact".to_string(),
}
}
}
pub struct MultiPlatformVibeEvaluator;
impl MultiPlatformVibeEvaluator {
pub fn evaluate_all(input: &DesignInput) -> HashMap<Platform, VibeComplianceResult> {
let platforms = vec![
Platform::Web,
Platform::Android,
Platform::IOS,
Platform::Desktop,
];
platforms
.into_iter()
.map(|p| {
let evaluator = VibeBenchmarkEvaluator::new(p);
(p, evaluator.evaluate(input))
})
.collect()
}
pub fn combined_score(results: &HashMap<Platform, VibeComplianceResult>) -> f64 {
if results.is_empty() {
return 0.0;
}
let total: f64 = results.values().map(|r| r.overall_score).sum();
total / results.len() as f64
}
pub fn meets_all_benchmarks(results: &HashMap<Platform, VibeComplianceResult>) -> bool {
results.values().all(|r| r.passes_threshold)
}
}
pub struct VibeScoreInterpreter;
impl VibeScoreInterpreter {
pub fn interpret(score: f64) -> VibeInterpretation {
let rating = if score >= 0.95 {
VibeRating::Exceptional
} else if score >= 0.90 {
VibeRating::Excellent
} else if score >= 0.85 {
VibeRating::Good
} else if score >= 0.75 {
VibeRating::Fair
} else if score >= 0.60 {
VibeRating::NeedsWork
} else {
VibeRating::Poor
};
let description = match rating {
VibeRating::Exceptional => "Design exceeds industry standards".to_string(),
VibeRating::Excellent => "Design meets professional quality standards".to_string(),
VibeRating::Good => "Design is solid with minor improvements possible".to_string(),
VibeRating::Fair => "Design is functional but needs refinement".to_string(),
VibeRating::NeedsWork => "Design has significant areas for improvement".to_string(),
VibeRating::Poor => "Design requires substantial revision".to_string(),
};
let improvement_areas = Self::suggest_improvements(score);
VibeInterpretation {
score,
rating,
description,
improvement_areas,
}
}
fn suggest_improvements(score: f64) -> Vec<String> {
let mut suggestions = Vec::new();
if score < 0.95 {
suggestions.push("Review visual coherence across components".to_string());
}
if score < 0.90 {
suggestions.push("Strengthen typography hierarchy".to_string());
}
if score < 0.85 {
suggestions.push("Improve color harmony and contrast".to_string());
}
if score < 0.80 {
suggestions.push("Establish consistent spacing system".to_string());
}
if score < 0.75 {
suggestions.push("Address accessibility compliance".to_string());
}
suggestions
}
}
#[derive(Debug, Clone)]
pub struct VibeInterpretation {
pub score: f64,
pub rating: VibeRating,
pub description: String,
pub improvement_areas: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VibeRating {
Exceptional,
Excellent,
Good,
Fair,
NeedsWork,
Poor,
}
pub struct M2BenchmarkComparison;
impl M2BenchmarkComparison {
pub fn compare(score: f64, platform: Platform) -> M2ComparisonResult {
let benchmark = match platform {
Platform::Web => VIBE_WEB_BENCHMARK,
Platform::Android => VIBE_ANDROID_BENCHMARK,
Platform::IOS => VIBE_IOS_BENCHMARK,
Platform::Desktop => (VIBE_WEB_BENCHMARK + VIBE_IOS_BENCHMARK) / 2.0,
};
let difference = score - benchmark;
let percentage_of_benchmark = (score / benchmark) * 100.0;
let status = if score >= benchmark {
M2ComparisonStatus::Exceeds
} else if score >= benchmark * 0.95 {
M2ComparisonStatus::Meets
} else if score >= benchmark * 0.85 {
M2ComparisonStatus::Approaching
} else {
M2ComparisonStatus::BelowTarget
};
M2ComparisonResult {
your_score: score,
m2_benchmark: benchmark,
difference,
percentage_of_benchmark,
status,
}
}
}
#[derive(Debug, Clone)]
pub struct M2ComparisonResult {
pub your_score: f64,
pub m2_benchmark: f64,
pub difference: f64,
pub percentage_of_benchmark: f64,
pub status: M2ComparisonStatus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum M2ComparisonStatus {
Exceeds,
Meets,
Approaching,
BelowTarget,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vibe_benchmarks() {
assert!((VIBE_WEB_BENCHMARK - 0.915).abs() < 0.001);
assert!((VIBE_ANDROID_BENCHMARK - 0.897).abs() < 0.001);
assert!((VIBE_IOS_BENCHMARK - 0.880).abs() < 0.001);
}
#[test]
fn test_vibe_evaluation() {
let evaluator = VibeBenchmarkEvaluator::new(Platform::Web);
let input = DesignInput {
data: DesignData::Html("<button>Test</button>".to_string()),
platform: Platform::Web,
context: None,
component_type: ComponentType::Button,
design_tokens: Some(DesignTokens {
colors: ColorTokens::reasonkit_brand(),
typography: TypographyTokens::reasonkit_brand(),
..Default::default()
}),
};
let result = evaluator.evaluate(&input);
assert!(result.overall_score > 0.0);
}
#[test]
fn test_m2_comparison() {
let result = M2BenchmarkComparison::compare(0.90, Platform::Web);
assert!((result.m2_benchmark - 0.915).abs() < 0.001);
}
#[test]
fn test_score_interpretation() {
let interp = VibeScoreInterpreter::interpret(0.92);
assert_eq!(interp.rating, VibeRating::Excellent);
}
}