use std::fmt::Display;
use notation_core::prelude::EntryPassMode;
use serde::{Deserialize, Serialize};
use crate::prelude::Units;
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, Debug)]
pub struct TabPosition {
pub in_tab_pos: Units,
}
impl Display for TabPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "<TabPosition>({})", self.in_tab_pos.0)
}
}
impl TabPosition {
pub const ZERO: Self = Self {
in_tab_pos: Units(0.0),
};
pub fn new(in_tab_pos: Units) -> Self {
Self { in_tab_pos }
}
}
impl From<TabPosition> for Units {
fn from(v: TabPosition) -> Self {
v.in_tab_pos
}
}
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, Debug)]
pub struct BarPosition {
pub bar_units: Units,
pub bar_ordinal: usize,
pub in_bar_pos: Units,
}
impl Display for BarPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"<BarPosition>({}:{})",
self.bar_ordinal, self.in_bar_pos.0
)
}
}
impl From<BarPosition> for Units {
fn from(v: BarPosition) -> Self {
v.bar_pos() + v.in_bar_pos
}
}
impl BarPosition {
pub const ZERO: Self = Self {
bar_units: Units(0.0),
bar_ordinal: 0,
in_bar_pos: Units(0.0),
};
pub fn new(bar_units: Units, bar_ordinal: usize, in_bar_pos: Units) -> Self {
Self {
bar_units,
bar_ordinal,
in_bar_pos,
}
}
pub fn with_in_bar_pos(&self, in_bar_pos: Units) -> Self {
Self::new(self.bar_units, self.bar_ordinal, in_bar_pos)
}
pub fn with_delay(&self, delay: Units) -> Self {
Self::new(self.bar_units, self.bar_ordinal, self.in_bar_pos + delay)
}
pub fn bar_pos(&self) -> Units {
Units(self.bar_ordinal as f32 * self.bar_units.0)
}
}
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, Debug)]
pub struct Position {
pub tab: TabPosition,
pub bar: BarPosition,
}
impl Display for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"<Position>(tab:{}, bar:{}:{})",
self.tab.in_tab_pos.0, self.bar.bar_ordinal, self.bar.in_bar_pos.0
)
}
}
impl From<Position> for Units {
fn from(v: Position) -> Self {
v.tab.in_tab_pos
}
}
impl Position {
pub fn new(bar_units: Units) -> Self {
Self {
tab: TabPosition::new(Units(0.0)),
bar: BarPosition::new(bar_units, 0, Units(0.0)),
}
}
pub fn calc_bar_ordinal(&self, pos: Units) -> usize {
let bar = pos.0 / self.bar.bar_units.0;
bar.trunc() as usize
}
pub fn cal_bar_pos(&self, bar_ordinal: usize) -> Units {
Units(bar_ordinal as f32 * self.bar.bar_units.0)
}
pub fn set_in_tab(&mut self, pos: Units) {
self.tab = TabPosition::new(pos);
self.bar.bar_ordinal = self.calc_bar_ordinal(pos);
self.bar.in_bar_pos = self.tab.in_tab_pos - self.cal_bar_pos(self.bar.bar_ordinal);
}
pub fn set_in_bar(&mut self, bar_ordinal: usize, in_bar_pos: Units) {
self.tab = TabPosition::new(self.cal_bar_pos(bar_ordinal) + in_bar_pos);
self.bar.bar_ordinal = bar_ordinal;
self.bar.in_bar_pos = in_bar_pos;
}
pub fn _is_passed(&self, pass_mode: EntryPassMode, in_tab_pos: Units) -> bool {
match pass_mode {
EntryPassMode::Immediate => in_tab_pos.0 <= self.tab.in_tab_pos.0,
EntryPassMode::Delayed => in_tab_pos.0 < self.tab.in_tab_pos.0,
}
}
pub fn is_passed(&self, pass_mode: EntryPassMode, pos: &BarPosition) -> bool {
let in_tab_pos = self.cal_bar_pos(pos.bar_ordinal) + pos.in_bar_pos;
self._is_passed(pass_mode, in_tab_pos)
}
pub fn is_passed_with(
&self,
pass_mode: EntryPassMode,
pos: &BarPosition,
units: Units,
) -> bool {
let in_tab_pos = self.cal_bar_pos(pos.bar_ordinal) + pos.in_bar_pos + units;
self._is_passed(pass_mode, in_tab_pos)
}
}
impl From<BarPosition> for TabPosition {
fn from(v: BarPosition) -> Self {
TabPosition::new(Units::from(v))
}
}
impl From<BarPosition> for Position {
fn from(v: BarPosition) -> Self {
Position {
tab: TabPosition::from(v),
bar: v,
}
}
}