use crate::agent::AgentId;
use crate::error::Result;
use std::collections::HashMap;
use tokio::sync::RwLock;
pub type TrustScore = f64;
#[derive(Debug, Clone)]
pub struct ReputationMetrics {
pub trust_score: TrustScore,
pub successful_collaborations: u32,
pub failed_collaborations: u32,
pub avg_response_time: f64,
pub reliability: f64,
}
impl Default for ReputationMetrics {
fn default() -> Self {
Self {
trust_score: 0.5, successful_collaborations: 0,
failed_collaborations: 0,
avg_response_time: 0.0,
reliability: 0.5,
}
}
}
pub struct TrustManager {
reputation_data: RwLock<HashMap<AgentId, ReputationMetrics>>,
config: TrustConfig,
}
#[derive(Debug, Clone)]
pub struct TrustConfig {
pub success_weight: f64,
pub failure_weight: f64,
pub response_time_weight: f64,
pub decay_factor: f64,
pub min_trust_score: f64,
pub max_trust_score: f64,
}
impl Default for TrustConfig {
fn default() -> Self {
Self {
success_weight: 0.4,
failure_weight: 0.3,
response_time_weight: 0.3,
decay_factor: 0.95,
min_trust_score: 0.0,
max_trust_score: 1.0,
}
}
}
impl TrustManager {
pub fn new() -> Self {
Self::with_config(TrustConfig::default())
}
pub fn with_config(config: TrustConfig) -> Self {
Self {
reputation_data: RwLock::new(HashMap::new()),
config,
}
}
pub async fn get_trust_score(&self, agent_id: &AgentId) -> Result<TrustScore> {
let reputation_data = self.reputation_data.read().await;
if let Some(metrics) = reputation_data.get(agent_id) {
Ok(metrics.trust_score)
} else {
Ok(self.config.min_trust_score +
(self.config.max_trust_score - self.config.min_trust_score) / 2.0)
}
}
pub async fn get_reputation_metrics(&self, agent_id: &AgentId) -> Option<ReputationMetrics> {
let reputation_data = self.reputation_data.read().await;
reputation_data.get(agent_id).cloned()
}
pub async fn record_success(&self, agent_id: &AgentId, response_time: f64) -> Result<()> {
let mut reputation_data = self.reputation_data.write().await;
let metrics = reputation_data.entry(*agent_id).or_insert_with(ReputationMetrics::default);
metrics.successful_collaborations += 1;
self.update_response_time(metrics, response_time);
self.recalculate_trust_score(metrics);
Ok(())
}
pub async fn record_failure(&self, agent_id: &AgentId, response_time: f64) -> Result<()> {
let mut reputation_data = self.reputation_data.write().await;
let metrics = reputation_data.entry(*agent_id).or_insert_with(ReputationMetrics::default);
metrics.failed_collaborations += 1;
self.update_response_time(metrics, response_time);
self.recalculate_trust_score(metrics);
Ok(())
}
fn update_response_time(&self, metrics: &mut ReputationMetrics, new_response_time: f64) {
let total_collaborations = metrics.successful_collaborations + metrics.failed_collaborations;
if total_collaborations > 1 {
metrics.avg_response_time = (metrics.avg_response_time * (total_collaborations - 1) as f64
+ new_response_time) / total_collaborations as f64;
} else {
metrics.avg_response_time = new_response_time;
}
}
fn recalculate_trust_score(&self, metrics: &mut ReputationMetrics) {
let total_collaborations = metrics.successful_collaborations + metrics.failed_collaborations;
if total_collaborations == 0 {
return; }
let success_ratio = metrics.successful_collaborations as f64 / total_collaborations as f64;
let response_reliability = if metrics.avg_response_time > 0.0 {
(10.0 / (metrics.avg_response_time + 10.0)).min(1.0)
} else {
1.0
};
metrics.reliability = response_reliability;
let trust_score =
success_ratio * self.config.success_weight +
response_reliability * self.config.response_time_weight +
(1.0 - (metrics.failed_collaborations as f64 / (total_collaborations as f64 + 1.0))) * self.config.failure_weight;
metrics.trust_score = trust_score
.max(self.config.min_trust_score)
.min(self.config.max_trust_score);
}
pub async fn apply_decay(&self) -> Result<()> {
let mut reputation_data = self.reputation_data.write().await;
for metrics in reputation_data.values_mut() {
metrics.trust_score *= self.config.decay_factor;
metrics.trust_score = metrics.trust_score.max(self.config.min_trust_score);
}
Ok(())
}
pub async fn get_trust_rankings(&self) -> Vec<(AgentId, TrustScore)> {
let reputation_data = self.reputation_data.read().await;
let mut rankings: Vec<(AgentId, TrustScore)> = reputation_data
.iter()
.map(|(agent_id, metrics)| (*agent_id, metrics.trust_score))
.collect();
rankings.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
rankings
}
}
impl Default for TrustManager {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_trust_score_calculation() {
let trust_manager = TrustManager::new();
let agent_id = AgentId::new();
let initial_score = trust_manager.get_trust_score(&agent_id).await.unwrap();
assert!((initial_score - 0.5).abs() < 0.01);
trust_manager.record_success(&agent_id, 5.0).await.unwrap();
let updated_score = trust_manager.get_trust_score(&agent_id).await.unwrap();
assert!(updated_score > initial_score);
}
#[tokio::test]
async fn test_trust_rankings() {
let trust_manager = TrustManager::new();
let agent1 = AgentId::new();
let agent2 = AgentId::new();
trust_manager.record_success(&agent1, 5.0).await.unwrap();
trust_manager.record_success(&agent1, 6.0).await.unwrap();
trust_manager.record_success(&agent2, 8.0).await.unwrap();
let rankings = trust_manager.get_trust_rankings().await;
assert_eq!(rankings.len(), 2);
assert_eq!(rankings[0].0, agent1); }
}