#[derive(Debug, Clone, PartialEq)]
pub struct TrustDecision {
task_willingness: f32,
support_willingness: f32,
disclosure_willingness: f32,
decision_certainty: f32,
trustee_confidence: f32,
}
impl TrustDecision {
#[must_use]
pub fn new(
task_willingness: f32,
support_willingness: f32,
disclosure_willingness: f32,
decision_certainty: f32,
trustee_confidence: f32,
) -> Self {
TrustDecision {
task_willingness: task_willingness.clamp(0.0, 1.0),
support_willingness: support_willingness.clamp(0.0, 1.0),
disclosure_willingness: disclosure_willingness.clamp(0.0, 1.0),
decision_certainty: decision_certainty.clamp(0.0, 1.0),
trustee_confidence: trustee_confidence.clamp(0.0, 1.0),
}
}
#[must_use]
pub fn no_trust() -> Self {
TrustDecision {
task_willingness: 0.0,
support_willingness: 0.0,
disclosure_willingness: 0.0,
decision_certainty: 0.0,
trustee_confidence: 0.0,
}
}
#[must_use]
pub fn full_trust() -> Self {
TrustDecision {
task_willingness: 1.0,
support_willingness: 1.0,
disclosure_willingness: 1.0,
decision_certainty: 1.0,
trustee_confidence: 1.0,
}
}
#[must_use]
pub fn task_willingness(&self) -> f32 {
self.task_willingness
}
#[must_use]
pub fn support_willingness(&self) -> f32 {
self.support_willingness
}
#[must_use]
pub fn disclosure_willingness(&self) -> f32 {
self.disclosure_willingness
}
#[must_use]
pub fn decision_certainty(&self) -> f32 {
self.decision_certainty
}
#[must_use]
pub fn trustee_confidence(&self) -> f32 {
self.trustee_confidence
}
#[must_use]
pub fn confidence(&self) -> f32 {
self.decision_certainty
}
#[must_use]
#[deprecated(
since = "0.2.0",
note = "Trust is domain-specific per Mayer's model. Use domain-specific methods instead."
)]
pub fn overall_willingness(&self) -> f32 {
(self.task_willingness + self.support_willingness + self.disclosure_willingness) / 3.0
}
#[must_use]
pub fn would_delegate_task(&self, threshold: f32) -> bool {
self.task_willingness > threshold
}
#[must_use]
pub fn would_seek_support(&self, threshold: f32) -> bool {
self.support_willingness > threshold
}
#[must_use]
pub fn would_disclose(&self, threshold: f32) -> bool {
self.disclosure_willingness > threshold
}
#[must_use]
pub fn fully_willing(&self, threshold: f32) -> bool {
self.task_willingness > threshold
&& self.support_willingness > threshold
&& self.disclosure_willingness > threshold
}
#[must_use]
pub fn any_willing(&self, threshold: f32) -> bool {
self.task_willingness > threshold
|| self.support_willingness > threshold
|| self.disclosure_willingness > threshold
}
}
impl Default for TrustDecision {
fn default() -> Self {
TrustDecision::new(0.3, 0.3, 0.2, 0.3, 0.3)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_creates_with_values() {
let decision = TrustDecision::new(0.6, 0.7, 0.5, 0.8, 0.7);
assert!((decision.task_willingness() - 0.6).abs() < f32::EPSILON);
assert!((decision.support_willingness() - 0.7).abs() < f32::EPSILON);
assert!((decision.disclosure_willingness() - 0.5).abs() < f32::EPSILON);
assert!((decision.decision_certainty() - 0.8).abs() < f32::EPSILON);
assert!((decision.trustee_confidence() - 0.7).abs() < f32::EPSILON);
}
#[test]
fn new_clamps_values() {
let decision = TrustDecision::new(1.5, -0.5, 2.0, -1.0, 2.0);
assert!((decision.task_willingness() - 1.0).abs() < f32::EPSILON);
assert!(decision.support_willingness().abs() < f32::EPSILON);
assert!((decision.disclosure_willingness() - 1.0).abs() < f32::EPSILON);
assert!(decision.decision_certainty().abs() < f32::EPSILON);
assert!((decision.trustee_confidence() - 1.0).abs() < f32::EPSILON);
}
#[test]
fn no_trust_is_zero() {
let decision = TrustDecision::no_trust();
assert!(decision.task_willingness().abs() < f32::EPSILON);
assert!(decision.support_willingness().abs() < f32::EPSILON);
assert!(decision.disclosure_willingness().abs() < f32::EPSILON);
assert!(decision.decision_certainty().abs() < f32::EPSILON);
assert!(decision.trustee_confidence().abs() < f32::EPSILON);
}
#[test]
fn full_trust_is_one() {
let decision = TrustDecision::full_trust();
assert!((decision.task_willingness() - 1.0).abs() < f32::EPSILON);
assert!((decision.support_willingness() - 1.0).abs() < f32::EPSILON);
assert!((decision.disclosure_willingness() - 1.0).abs() < f32::EPSILON);
assert!((decision.decision_certainty() - 1.0).abs() < f32::EPSILON);
assert!((decision.trustee_confidence() - 1.0).abs() < f32::EPSILON);
}
#[test]
#[allow(deprecated)]
fn overall_willingness_is_average() {
let decision = TrustDecision::new(0.3, 0.6, 0.9, 0.5, 0.5);
let expected = (0.3 + 0.6 + 0.9) / 3.0;
assert!((decision.overall_willingness() - expected).abs() < f32::EPSILON);
}
#[test]
fn would_delegate_task() {
let decision = TrustDecision::new(0.5, 0.3, 0.2, 0.5, 0.5);
assert!(decision.would_delegate_task(0.4));
assert!(!decision.would_delegate_task(0.6));
}
#[test]
fn would_seek_support() {
let decision = TrustDecision::new(0.3, 0.7, 0.2, 0.5, 0.5);
assert!(decision.would_seek_support(0.6));
assert!(!decision.would_seek_support(0.8));
}
#[test]
fn would_disclose() {
let decision = TrustDecision::new(0.3, 0.3, 0.8, 0.5, 0.5);
assert!(decision.would_disclose(0.7));
assert!(!decision.would_disclose(0.9));
}
#[test]
fn fully_willing() {
let high = TrustDecision::new(0.8, 0.8, 0.8, 0.9, 0.9);
let mixed = TrustDecision::new(0.8, 0.3, 0.8, 0.5, 0.5);
assert!(high.fully_willing(0.7));
assert!(!mixed.fully_willing(0.7));
}
#[test]
fn any_willing() {
let low = TrustDecision::new(0.2, 0.2, 0.2, 0.3, 0.3);
let one_high = TrustDecision::new(0.2, 0.9, 0.2, 0.5, 0.5);
assert!(!low.any_willing(0.5));
assert!(one_high.any_willing(0.5));
}
#[test]
fn default_is_moderate() {
let decision = TrustDecision::default();
assert!(decision.task_willingness() > 0.0);
assert!(decision.task_willingness() < 0.5);
}
#[test]
fn clone_and_equality() {
let d1 = TrustDecision::new(0.5, 0.6, 0.7, 0.8, 0.7);
let d2 = d1.clone();
assert_eq!(d1, d2);
}
#[test]
fn debug_format() {
let decision = TrustDecision::new(0.5, 0.6, 0.7, 0.8, 0.7);
let debug = format!("{:?}", decision);
assert!(debug.contains("TrustDecision"));
}
#[test]
fn confidence_backward_compat() {
let decision = TrustDecision::new(0.5, 0.6, 0.7, 0.8, 0.7);
assert!((decision.confidence() - decision.decision_certainty()).abs() < f32::EPSILON);
}
#[test]
fn trustee_confidence_distinct_from_decision_certainty() {
let decision = TrustDecision::new(0.5, 0.6, 0.7, 0.4, 0.9);
assert!((decision.trustee_confidence() - 0.9).abs() < f32::EPSILON);
assert!((decision.decision_certainty() - 0.4).abs() < f32::EPSILON);
}
}