use crate::{
NodeCardExpectation, NodeCardStatus, TraceCondenseCandidate, TraceCondenseCandidates,
TraceProofResult,
};
use std::collections::{BTreeMap, BTreeSet};
pub const MIN_BODY_BYTES: u64 = 1_024;
pub const MAX_CANDIDATES: usize = 8;
pub fn recommend(
proof: &TraceProofResult,
memberships: &[BTreeSet<String>],
) -> TraceCondenseCandidates {
let mut sources = BTreeMap::<&str, BTreeSet<&str>>::new();
for support in &proof.supports {
sources
.entry(&support.target_node_id)
.or_default()
.insert(&support.source_node_id);
}
let mut sharing = BTreeMap::<&str, u32>::new();
for members in memberships {
let mut refs: BTreeSet<&str> = members.iter().map(String::as_str).collect();
for member in members {
if let Some(supports) = sources.get(member.as_str()) {
refs.extend(supports);
}
}
for reference in refs {
*sharing.entry(reference).or_default() += 1;
}
}
let mut result = TraceCondenseCandidates::default();
for object in &proof.objects {
let (Some(descriptor), Some(card)) = (&object.descriptor, &object.card) else {
continue;
};
let expect = match card.status {
NodeCardStatus::Valid => {
result.valid += 1;
continue;
}
NodeCardStatus::AfterCut => {
result.after_cut += 1;
continue;
}
NodeCardStatus::Absent => NodeCardExpectation::Absent,
NodeCardStatus::Stale => {
let Some(stored) = &card.stored else {
continue;
};
NodeCardExpectation::CardRevision(stored.card_revision)
}
};
if descriptor.body_bytes < MIN_BODY_BYTES {
result.below_floor += 1;
continue;
}
result.items.push(TraceCondenseCandidate {
descriptor: descriptor.clone(),
card_status: card.status,
shared_by: sharing
.get(descriptor.node_id.as_str())
.copied()
.unwrap_or(0),
expect,
});
}
result.items.sort_by(|left, right| {
right
.shared_by
.cmp(&left.shared_by)
.then_with(|| right.descriptor.body_bytes.cmp(&left.descriptor.body_bytes))
.then_with(|| left.descriptor.node_id.cmp(&right.descriptor.node_id))
});
result.omitted_count = result.items.len().saturating_sub(MAX_CANDIDATES) as u32;
result.items.truncate(MAX_CANDIDATES);
result
}
#[cfg(test)]
#[path = "trace_condense_policy_tests.rs"]
mod tests;