use crate::kd_tree::Key;
use ark_std::{collections::BTreeMap, fmt::Debug, vec::Vec};
pub enum TransactionRating {
Positive,
Negative,
}
#[derive(Clone, Debug)]
pub struct Peer {
index: Key,
transaction_scores: BTreeMap<Key, u32>,
transaction_scores_sum: u32,
pre_trust_scores: BTreeMap<Key, f64>,
managers: Vec<Key>,
}
impl Peer {
pub fn new(index: Key, pre_trust_scores: BTreeMap<Key, f64>) -> Self {
Self {
index,
transaction_scores: BTreeMap::new(),
transaction_scores_sum: 0,
pre_trust_scores,
managers: Vec::new(),
}
}
pub fn set_managers(&mut self, managers: Vec<Key>) {
self.managers = managers;
}
pub fn mock_rate_transaction(&mut self, i: &Key, rating: TransactionRating) {
if !self.transaction_scores.contains_key(i) {
self.transaction_scores.insert(*i, 0);
}
let score = self.transaction_scores[i];
let sum = self.transaction_scores_sum;
let (new_score, new_sum) = match rating {
TransactionRating::Positive => (score + 1, sum + 1),
TransactionRating::Negative if score > 0 => (score - 1, sum - 1),
_ => (score, sum),
};
self.transaction_scores.insert(*i, new_score);
self.transaction_scores_sum = new_sum;
}
#[cfg(test)]
pub fn get_transaction_scores(&self, index: &Key) -> u32 {
*self.transaction_scores.get(index).unwrap_or(&0)
}
pub fn get_pre_trust_score(&self) -> f64 {
*self.pre_trust_scores.get(&self.index).unwrap_or(&0.)
}
pub fn get_index(&self) -> Key {
self.index.clone()
}
pub fn get_local_trust_score(&self, i: &Key) -> f64 {
let score = self.transaction_scores.get(i).unwrap_or(&0);
let sum = self.transaction_scores_sum;
let mut normalized_score = f64::from(*score) / f64::from(sum);
if normalized_score.is_nan() {
normalized_score = *self.pre_trust_scores.get(i).unwrap_or(&0.);
}
normalized_score
}
pub fn get_managers(&self) -> &Vec<Key> {
&self.managers
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_new() {
let mut pre_trust_scores = BTreeMap::new();
pre_trust_scores.insert(Key::from(0), 0.4);
let peer = Peer::new(Key::from(0), pre_trust_scores);
let index = peer.get_index();
let pre_trust_score = peer.get_pre_trust_score();
assert_eq!(index, Key::from(0));
assert_eq!(pre_trust_score, 0.4);
}
#[test]
fn local_trust_score_when_sum_is_zero() {
let mut pre_trust_scores = BTreeMap::new();
pre_trust_scores.insert(Key::from(1), 0.4);
let peer = Peer::new(Key::from(0), pre_trust_scores);
assert_eq!(peer.get_local_trust_score(&Key::from(1)), 0.4);
}
#[test]
fn test_transactions() {
let mut pre_trust_scores = BTreeMap::new();
pre_trust_scores.insert(Key::from(0), 0.4);
let mut peer = Peer::new(Key::from(0), pre_trust_scores);
let one = Key::from(1);
let two = Key::from(2);
peer.mock_rate_transaction(&one, TransactionRating::Positive);
peer.mock_rate_transaction(&one, TransactionRating::Positive);
peer.mock_rate_transaction(&one, TransactionRating::Negative);
peer.mock_rate_transaction(&two, TransactionRating::Positive);
peer.mock_rate_transaction(&two, TransactionRating::Positive);
peer.mock_rate_transaction(&two, TransactionRating::Positive);
assert_eq!(peer.get_local_trust_score(&one), 0.25);
assert_eq!(peer.get_local_trust_score(&two), 0.75);
assert_eq!(peer.get_transaction_scores(&one), 1);
assert_eq!(peer.get_transaction_scores(&two), 3);
}
}