use crate::fuzzy::membership::piecewise::PiecewiseLinearFunction;
use crate::fuzzy::membership::Membership;
use std::fmt::{Debug, Display, Formatter};
pub trait LabelMembership = Membership + Display;
#[derive(Debug, PartialEq, Clone)]
pub struct Label<T: LabelMembership> {
name: String,
membership: T,
}
impl<T: LabelMembership + Display> Display for Label<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} => {}", self.name, self.membership)
}
}
#[derive(Debug, PartialEq)]
pub enum LabelError {
NonStandardizedName { name: String },
EmptyName,
}
impl Display for LabelError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
use LabelError::*;
match &self {
NonStandardizedName { name } => {
write!(f, "Name '{}' isn't standardized.", name)
}
EmptyName => {
write!(f, "Empty name provided.")
}
}
}
}
impl<T: LabelMembership> Label<T> {
pub fn new(name: String, membership: T) -> Result<Self, LabelError> {
use LabelError::*;
if !is_standardized(&name) {
Err(NonStandardizedName { name })
} else if name.is_empty() {
Err(EmptyName)
} else {
Ok(Self { name, membership })
}
}
pub fn name(&self) -> &String {
&self.name
}
pub fn membership(&self) -> &T {
&self.membership
}
}
pub fn standardize_name(name: &str) -> String {
name.trim().to_lowercase()
}
pub fn is_standardized(name: &str) -> bool {
*name == standardize_name(name)
}
pub fn get_labels_names<T: Display + LabelMembership>(labels: &[Label<T>]) -> Vec<&str> {
labels
.iter()
.map(|l| l.name().as_str())
.collect::<Vec<&str>>()
}
#[allow(unused_imports)]
use crate::fuzzy::membership::Trapezoidal;
#[macro_export]
macro_rules! trapezoidal_labels {
( $( $name:expr => $membership:expr ),* ) => {
{
let mut labels = Vec::<$crate::fuzzy::Label<$crate::fuzzy::membership::Trapezoidal>>::new();
let mut abort = false;
let mut error = String::new();
$(
match abort {
false => {
match $crate::fuzzy::membership::Trapezoidal::new($membership) {
Ok(t) => {
match $crate::fuzzy::Label::new($name.to_string(), t) {
Ok(l) => labels.push(l),
Err(e) => {
error = format!("{}", e);
abort = true;
}
}
},
Err(e) => {
error = format!("{}", e);
abort = true;
}
}
},
_ => (),
}
)*
if abort {
Err(error)
} else {
Ok(labels)
}
}
};
}
impl From<&Label<Trapezoidal>> for PiecewiseLinearFunction {
fn from(l: &Label<Trapezoidal>) -> Self {
PiecewiseLinearFunction::from(&l.membership)
}
}