use crate::agent::swarm::knowledge::SharedKnowledge;
use crate::agent::swarm::knowledge::types::{BlackboardEntry, BlackboardKind, ConsensusResult};
impl SharedKnowledge {
pub async fn post_to_blackboard(
&self,
key: &str,
value: &str,
author: &str,
kind: BlackboardKind,
) {
let mut inner = self.inner.write().await;
inner.blackboard.insert(
key.to_string(),
BlackboardEntry {
key: key.to_string(),
value: value.to_string(),
author: author.to_string(),
kind,
votes_for: vec![author.to_string()], votes_against: Vec::new(),
timestamp: std::time::Instant::now(),
},
);
}
pub async fn read_blackboard(&self, key: &str) -> Option<BlackboardEntry> {
let inner = self.inner.read().await;
inner.blackboard.get(key).cloned()
}
#[allow(dead_code)]
pub async fn query_blackboard_prefix(&self, prefix: &str) -> Vec<BlackboardEntry> {
let inner = self.inner.read().await;
inner
.blackboard
.range(prefix.to_string()..)
.take_while(|(k, _)| k.starts_with(prefix))
.map(|(_, v)| v.clone())
.collect()
}
pub async fn blackboard_by_kind(&self, kind: BlackboardKind) -> Vec<BlackboardEntry> {
let inner = self.inner.read().await;
inner
.blackboard
.values()
.filter(|e| e.kind == kind)
.cloned()
.collect()
}
pub async fn vote_on_proposal(
&self,
key: &str,
voter_id: &str,
approve: bool,
) -> Option<ConsensusResult> {
let mut inner = self.inner.write().await;
let entry = inner.blackboard.get_mut(key)?;
if entry.kind != BlackboardKind::Proposal {
return None;
}
entry.votes_for.retain(|v| v != voter_id);
entry.votes_against.retain(|v| v != voter_id);
if approve {
entry.votes_for.push(voter_id.to_string());
} else {
entry.votes_against.push(voter_id.to_string());
}
Some(ConsensusResult {
key: key.to_string(),
approved: approve,
votes_for: entry.votes_for.len(),
votes_against: entry.votes_against.len(),
total_agents: 0, })
}
pub async fn check_consensus(&self, key: &str, total_agents: usize) -> Option<ConsensusResult> {
let inner = self.inner.read().await;
let entry = inner.blackboard.get(key)?;
let for_count = entry.votes_for.len();
let against_count = entry.votes_against.len();
let total_votes = for_count + against_count;
let majority = total_agents.div_ceil(2);
let approved = if for_count >= majority {
true
} else if against_count >= majority {
false
} else if total_votes >= total_agents {
for_count >= against_count
} else {
return None;
};
Some(ConsensusResult {
key: key.to_string(),
approved,
votes_for: for_count,
votes_against: against_count,
total_agents,
})
}
pub async fn finalize_proposal(&self, key: &str) -> bool {
let mut inner = self.inner.write().await;
if let Some(entry) = inner.blackboard.get_mut(key)
&& entry.kind == BlackboardKind::Proposal
{
entry.kind = BlackboardKind::Decision;
return true;
}
false
}
}