use crate::blob_store::types::{BlobId, BlobMeta};
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::fmt;
#[derive(Debug, Clone)]
pub struct SignalWeights {
pub semantic: f32,
pub temporal: f32,
pub causal: f32,
}
impl SignalWeights {
pub(crate) fn normalized_f64(&self) -> (f64, f64, f64) {
let sem = f64::from(self.semantic).max(0.0);
let tmp = f64::from(self.temporal).max(0.0);
let cau = f64::from(self.causal).max(0.0);
let total = sem + tmp + cau;
if total <= f64::from(f32::EPSILON) {
return (0.0, 0.0, 0.0);
}
(sem / total, tmp / total, cau / total)
}
pub(crate) fn any_active(&self) -> bool {
self.semantic > 0.0 || self.temporal > 0.0 || self.causal > 0.0
}
}
impl Default for SignalWeights {
fn default() -> Self {
Self {
semantic: 0.0,
temporal: 0.0,
causal: 0.0,
}
}
}
#[derive(Debug, Clone)]
pub struct SignalScores {
pub semantic: Option<f64>,
pub temporal: Option<f64>,
pub causal: Option<f64>,
}
#[derive(Debug, Clone)]
pub struct ScoredBlob {
pub blob_id: BlobId,
pub meta: BlobMeta,
pub score: f64,
pub signals: SignalScores,
}
impl fmt::Display for ScoredBlob {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ScoredBlob({:?}, score={:.4})", self.blob_id, self.score)
}
}
#[derive(Debug, Clone)]
pub(crate) struct CandidateEntry {
pub blob_id: BlobId,
pub meta: Option<BlobMeta>,
pub raw_distance: Option<f32>,
pub wall_clock_ns: Option<u64>,
pub causal_hops: Option<u32>,
}
pub(crate) struct HeapEntry {
pub score: f64,
pub blob_id: BlobId,
pub meta: BlobMeta,
pub signals: SignalScores,
}
impl PartialEq for HeapEntry {
fn eq(&self, other: &Self) -> bool {
self.score == other.score
}
}
impl Eq for HeapEntry {}
impl PartialOrd for HeapEntry {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for HeapEntry {
fn cmp(&self, other: &Self) -> Ordering {
other.score.total_cmp(&self.score)
}
}
impl HeapEntry {
pub fn into_scored_blob(self) -> ScoredBlob {
ScoredBlob {
blob_id: self.blob_id,
meta: self.meta,
score: self.score,
signals: self.signals,
}
}
}
pub(crate) fn heap_to_sorted(heap: alloc::collections::BinaryHeap<HeapEntry>) -> Vec<ScoredBlob> {
let mut results: Vec<ScoredBlob> = heap.into_iter().map(|e| e.into_scored_blob()).collect();
results.sort_by(|a, b| b.score.total_cmp(&a.score));
results
}