use super::FrameNumber;
use crate::roll::Roll;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FrameKind {
Strike,
Spare,
AllDown,
Open,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FramePosition {
Regular,
Final,
}
impl FramePosition {
#[inline]
pub const fn is_final(self) -> bool {
matches!(self, Self::Final)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScoredFrame {
number: FrameNumber,
position: FramePosition,
kind: FrameKind,
rolls: Vec<Roll>,
base_score: u16,
}
impl ScoredFrame {
pub(crate) fn new(
number: FrameNumber,
position: FramePosition,
kind: FrameKind,
rolls: Vec<Roll>,
base_score: u16,
) -> Self {
Self {
number,
position,
kind,
rolls,
base_score,
}
}
pub fn number(&self) -> FrameNumber {
self.number
}
pub fn position(&self) -> FramePosition {
self.position
}
pub fn is_final(&self) -> bool {
self.position.is_final()
}
pub fn kind(&self) -> FrameKind {
self.kind
}
pub fn rolls(&self) -> &[Roll] {
&self.rolls
}
pub fn base_score(&self) -> u16 {
self.base_score
}
pub fn bonus_balls(&self, strike_bonus: u8, spare_bonus: u8) -> u8 {
match self.kind {
FrameKind::Strike => {
if self.position.is_final() {
0
} else {
strike_bonus
}
}
FrameKind::Spare => {
if self.position.is_final() {
0
} else {
spare_bonus
}
}
FrameKind::AllDown | FrameKind::Open => 0,
}
}
}