use crate::{
enums::{Armor, BulletType, Club, Position, School, Squad, TacticalRole, WeaponType},
types::{Age, Released, Student, ID},
};
pub trait StudentFilter {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student>;
}
impl StudentFilter for Age {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.age == self)
.collect()
}
}
impl StudentFilter for Released {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.released == self)
.collect()
}
}
impl StudentFilter for ID {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.id == self)
.collect()
}
}
impl StudentFilter for School {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.school() == self)
.collect()
}
}
impl StudentFilter for TacticalRole {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.tactical_role() == self)
.collect()
}
}
impl StudentFilter for Squad {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.squad() == self)
.collect()
}
}
impl StudentFilter for Armor {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.armor() == self)
.collect()
}
}
impl StudentFilter for Position {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.position() == self)
.collect()
}
}
impl StudentFilter for BulletType {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.bullet_type() == self)
.collect()
}
}
impl StudentFilter for Club {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.club() == self)
.collect()
}
}
impl StudentFilter for WeaponType {
fn filter<'a>(&self, students: &'a [Student]) -> Vec<&'a Student> {
students
.iter()
.filter(|student| &student.weapon_type() == self)
.collect()
}
}
#[derive(Debug)]
pub struct StudentFilterOptions<'s> {
pub filtered_students: Option<Vec<&'s Student>>,
slice: &'s [Student],
}
impl<'s> StudentFilterOptions<'s> {
pub fn new(students: &'s Vec<Student>) -> Self {
Self {
filtered_students: None,
slice: students,
}
}
fn apply_filter(&mut self, student_filter: impl StudentFilter) {
let mut applied_filter = student_filter.filter(self.slice);
match &self.filtered_students {
Some(filtered) => {
applied_filter.retain(|student| filtered.contains(student));
self.filtered_students = Some(applied_filter);
}
None => self.filtered_students = Some(applied_filter),
}
}
pub fn apply(mut self, student_filter: impl StudentFilter) -> Self {
self.apply_filter(student_filter);
self
}
pub fn finish(self) -> Vec<&'s Student> {
self.filtered_students
.unwrap_or_default()
.into_iter()
.collect()
}
}