notation_model 0.6.0

Fun notation - runtime models
Documentation
use std::fmt::Display;
use std::sync::Arc;

use notation_proto::prelude::{Chord, Position};

use crate::prelude::{ModelEntry, Tab};
use crate::tab_bar::TabBar;

#[derive(Clone, Debug)]
pub struct TabChord {
    pub chord: Chord,
    pub entries: Vec<Arc<ModelEntry>>,
    pub bars: Vec<Arc<TabBar>>,
}
impl Display for TabChord {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "<TabChord>({}, E:{}, B:{})",
            self.chord,
            self.entries.len(),
            self.bars.len(),
        )
    }
}

impl TabChord {
    pub fn tab(&self) -> Option<Arc<Tab>> {
        self.entries.first().and_then(|x| x.tab())
    }
    pub fn first_entry(&self) -> Option<Arc<ModelEntry>> {
        self.entries.first().map(|x| x.clone())
    }
    pub fn calc_bars(tab: Option<Arc<Tab>>, chord: Chord) -> Vec<Arc<TabBar>> {
        let mut bars = Vec::new();
        if tab.is_some() {
            for bar in tab.unwrap().bars.iter() {
                if bar.get_chords().contains(&chord) {
                    bars.push(bar.clone());
                }
            }
        }
        bars
    }
    pub fn search_in_bars(
        &self,
        begin_bar_ordinal: usize,
        end_bar_ordinal: usize,
    ) -> Option<Arc<TabBar>> {
        for bar_ordinal in begin_bar_ordinal..=end_bar_ordinal {
            for bar in self.bars.iter() {
                if bar.props.bar_ordinal == bar_ordinal {
                    return Some(bar.clone());
                }
            }
        }
        None
    }
    pub fn search_next(&self, pass_end: bool, position: Option<Position>) -> Option<Arc<TabBar>> {
        if let Some(tab) = self.tab() {
            let last_bar_ordinal = tab.bars.len() + 1;
            match position {
                Some(pos) => {
                    let bar_ordinal = pos.bar.bar_ordinal;
                    if let Some(entry) = self.search_in_bars(bar_ordinal + 1, last_bar_ordinal) {
                        return Some(entry);
                    } else if pass_end {
                        return self.search_in_bars(1, bar_ordinal);
                    }
                }
                None => {
                    return self.search_in_bars(1, last_bar_ordinal);
                }
            }
        }
        None
    }
}