use serde::{Deserialize, Serialize};
use crate::error::{BhavaError, Result};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TraitValue {
pub trait_name: TraitKind,
pub level: TraitLevel,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum TraitKind {
Formality,
Humor,
Verbosity,
Directness,
Warmth,
Empathy,
Patience,
Confidence,
Creativity,
RiskTolerance,
Curiosity,
Skepticism,
Autonomy,
Pedagogy,
Precision,
}
impl TraitKind {
pub const ALL: &'static [TraitKind] = &[
Self::Formality,
Self::Humor,
Self::Verbosity,
Self::Directness,
Self::Warmth,
Self::Empathy,
Self::Patience,
Self::Confidence,
Self::Creativity,
Self::RiskTolerance,
Self::Curiosity,
Self::Skepticism,
Self::Autonomy,
Self::Pedagogy,
Self::Precision,
];
pub const COUNT: usize = 15;
#[inline]
pub fn index(self) -> usize {
match self {
Self::Formality => 0,
Self::Humor => 1,
Self::Verbosity => 2,
Self::Directness => 3,
Self::Warmth => 4,
Self::Empathy => 5,
Self::Patience => 6,
Self::Confidence => 7,
Self::Creativity => 8,
Self::RiskTolerance => 9,
Self::Curiosity => 10,
Self::Skepticism => 11,
Self::Autonomy => 12,
Self::Pedagogy => 13,
Self::Precision => 14,
}
}
pub fn default_level(self) -> TraitLevel {
TraitLevel::Balanced
}
pub fn levels(self) -> &'static [TraitLevel] {
&[
TraitLevel::Lowest,
TraitLevel::Low,
TraitLevel::Balanced,
TraitLevel::High,
TraitLevel::Highest,
]
}
pub fn group(self) -> TraitGroup {
match self {
Self::Warmth | Self::Empathy | Self::Humor | Self::Patience => TraitGroup::Social,
Self::Curiosity | Self::Creativity | Self::Confidence | Self::Skepticism => {
TraitGroup::Cognitive
}
Self::Formality | Self::Verbosity | Self::Directness | Self::RiskTolerance => {
TraitGroup::Behavioral
}
Self::Autonomy | Self::Pedagogy | Self::Precision => TraitGroup::Professional,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum TraitGroup {
Social,
Cognitive,
Behavioral,
Professional,
}
impl TraitGroup {
pub const ALL: &'static [TraitGroup] = &[
Self::Social,
Self::Cognitive,
Self::Behavioral,
Self::Professional,
];
pub fn traits(self) -> &'static [TraitKind] {
match self {
Self::Social => &[
TraitKind::Warmth,
TraitKind::Empathy,
TraitKind::Humor,
TraitKind::Patience,
],
Self::Cognitive => &[
TraitKind::Curiosity,
TraitKind::Creativity,
TraitKind::Confidence,
TraitKind::Skepticism,
],
Self::Behavioral => &[
TraitKind::Formality,
TraitKind::Verbosity,
TraitKind::Directness,
TraitKind::RiskTolerance,
],
Self::Professional => &[
TraitKind::Autonomy,
TraitKind::Pedagogy,
TraitKind::Precision,
],
}
}
}
impl_display!(TraitGroup {
Social => "social",
Cognitive => "cognitive",
Behavioral => "behavioral",
Professional => "professional",
});
impl_display!(TraitKind {
Formality => "formality",
Humor => "humor",
Verbosity => "verbosity",
Directness => "directness",
Warmth => "warmth",
Empathy => "empathy",
Patience => "patience",
Confidence => "confidence",
Creativity => "creativity",
RiskTolerance => "risk_tolerance",
Skepticism => "skepticism",
Autonomy => "autonomy",
Pedagogy => "pedagogy",
Precision => "precision",
Curiosity => "curiosity",
});
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub enum TraitLevel {
Lowest,
Low,
Balanced,
High,
Highest,
}
impl TraitLevel {
#[inline]
#[must_use]
pub fn numeric(self) -> i8 {
match self {
Self::Lowest => -2,
Self::Low => -1,
Self::Balanced => 0,
Self::High => 1,
Self::Highest => 2,
}
}
#[inline]
#[must_use]
pub fn normalized(self) -> f32 {
self.numeric() as f32 / 2.0
}
#[must_use]
pub fn from_normalized(v: f32) -> Self {
let n = (v * 2.0).round() as i8;
match n.clamp(-2, 2) {
-2 => Self::Lowest,
-1 => Self::Low,
0 => Self::Balanced,
1 => Self::High,
_ => Self::Highest,
}
}
pub fn from_numeric(n: i8) -> Result<Self> {
match n {
-2 => Ok(Self::Lowest),
-1 => Ok(Self::Low),
0 => Ok(Self::Balanced),
1 => Ok(Self::High),
2 => Ok(Self::Highest),
_ => Err(BhavaError::InvalidConfig {
reason: format!("trait level must be -2..=2, got {n}"),
}),
}
}
}
impl_display!(TraitLevel {
Lowest => "lowest",
Low => "low",
Balanced => "balanced",
High => "high",
Highest => "highest",
});