cat-q 0.1.2

cat-q library for testing and scoring
Documentation
use std::collections::VecDeque;

pub trait Scoring {
    fn score(&self, normative: bool) -> u8;
}

pub enum Answer {
   NeitherAgreeNorDisagree,
   StronglyDisagree,
   SomeWhatDisagree,
   SomeWhatAgree,
   StronglyAgree,
   Disagree,
   Agree,
}

pub enum Subscale {
    Assimilation,
    Compensation,
    Masking,
}

impl Scoring for Answer {
    fn score(&self, normative: bool) -> u8 {
        if normative {
            match self {
                Self::NeitherAgreeNorDisagree => 4,
                Self::SomeWhatDisagree => 5,
                Self::StronglyDisagree => 7,
                Self::SomeWhatAgree => 3,
                Self::StronglyAgree => 1,
                Self::Disagree => 6,
                Self::Agree => 2,
            } 
        } else {
            match self {
                Self::NeitherAgreeNorDisagree => 4,
                Self::SomeWhatDisagree => 3,
                Self::StronglyDisagree => 1,
                Self::SomeWhatAgree => 5,
                Self::StronglyAgree => 7,
                Self::Disagree => 2,
                Self::Agree => 6,
            }
        }
    }
}

#[derive(Debug)]
pub struct FinalScore {
    pub compensation_subtotal: u8,
    pub assimilation_subtotal: u8,
    pub masking_subtotal: u8,
    pub total: u8,
}

pub struct Question {
    score: Option<Answer>,
    pub content: String,
    subscale: Subscale,
    normative: bool,
}

impl Question {
    fn new(content: impl Into<String>, normative: bool, subscale: Subscale) -> Self {
        Self {
            content: content.into(),
            score: None,
            normative,
            subscale,
        }
    }

    pub fn answer(&mut self, answer: Answer) {
        self.score = Some(answer)
    }
}

pub struct CatQ {
    questions: VecDeque<Question>,
}

impl CatQ {
    pub fn new() -> Self {
        let questions = vec![
            Question::new("I have spent time learning social skills from television shows and films, and try to use these in my interactions", false, Subscale::Compensation),
            Question::new("I learn how people use their bodies and faces to interact by watching television or fils, or by reading fiction", false, Subscale::Compensation),
            Question::new("I monitor my body language or facial expressions so that I appear interested by the person I am interacting with", false, Subscale::Masking),
            Question::new("I adjust my body language or facial expressions so that I appear interested by the person I am interacting with", false, Subscale::Masking),
            Question::new("In my own social interactions, I use behaviors that I have learned from watching other people interacting", false, Subscale::Compensation),
            Question::new("When I am interacting with someone, I deliberately copy their body language or facial expressions", false, Subscale::Compensation),
            Question::new("I will repeat phrases that I have heard others say in the exact same way that I first heard them", false, Subscale::Compensation),
            Question::new("I have researched the rules of social interactions to improve my own social skills", false, Subscale::Compensation),
            Question::new("I have tried to improve my understanding of social skills by watching other people", false, Subscale::Compensation),
            Question::new("I rarely feel the need to put on an act in order to get through a social situation", true, Subscale::Assimilation),
            Question::new("I practice my facial expressions and body language to make sure they look natural", false, Subscale::Compensation),
            Question::new("When in social situations, I try to find ways to avoid interacting with others", false, Subscale::Assimilation),
            Question::new("I have to force myself to interact with people when I am in social situations", false, Subscale::Assimilation),
            Question::new("In social situations, I feel like I'm 'performing' rather than being myself", false, Subscale::Assimilation),
            Question::new("In social interactions, I do not pay attention to what my face or body are doing", true, Subscale::Masking),
            Question::new("When talking to other people, I feel like the conversation flows naturally", true, Subscale::Assimilation),
            Question::new("I don't feel the need to make eye contact with other people if I don't want to", true, Subscale::Masking),
            Question::new("I monitor my body language or facial expressions so that I appear relaxed", false, Subscale::Masking),
            Question::new("I adjust my body language or facial expressions so that I appear relaxed", false, Subscale::Masking),
            Question::new("In social situations, I feel like I am pretending to be 'normal'", false, Subscale::Assimilation),
            Question::new("I need the support of other people in order to socialize", false, Subscale::Assimilation),
            Question::new("I have developed a script to follow in social situations", false, Subscale::Compensation),
            Question::new("I am always aware of the impression I make on other people", false, Subscale::Masking),
            Question::new("I always think about the impression I make on other people", false, Subscale::Masking),
            Question::new("I feel free to be myself when I am with other people", true, Subscale::Assimilation),
        ];

        assert_eq!(questions.len(), 25);

        let dec = VecDeque::from(questions);

        Self {
            questions: dec,
        }
    }

    pub fn score(questions: Vec<Question>) -> FinalScore {
        let mut final_score = FinalScore {
            assimilation_subtotal: 0,
            compensation_subtotal: 0,
            masking_subtotal: 0,
            total: 0,
        };

        final_score.total = questions.iter().fold(0 as u8, |attr, a| {
            attr + match &a.score {
                Some(x) => {
                    let score = x.score(a.normative);

                    match a.subscale {
                        Subscale::Compensation => final_score.compensation_subtotal += score,
                        Subscale::Assimilation => final_score.assimilation_subtotal += score,
                        Subscale::Masking => final_score.masking_subtotal += score,
                    }

                    score
                }
                None => 0,
            }
        });

        final_score
    }

    pub fn push_front(&mut self, question: Question) {
        self.questions.push_front(question)
    }

    pub fn push_back(&mut self, question: Question) {
        self.questions.push_back(question)
    }

    #[deprecated]
    // use 'CatQ::push_front' instead
    pub fn reádd_front(&mut self, question: Question) {
        self.questions.push_front(question)
    }

    #[deprecated]
    // use 'CatQ::push_back' instead
    pub fn reádd_back(&mut self, question: Question) {
        self.questions.push_back(question)
    }
}

impl Iterator for CatQ {
    type Item = Question;

    fn next(&mut self) -> Option<Self::Item> {
        self.questions.pop_front()
    }
}

#[cfg(test)]
mod tests {
    use crate::CatQ;

    #[test]
    fn cat_q_twenty_five() {
        CatQ::new();
    }
}