diff --git a/src/bingpai.rs b/src/bingpai.rs index 65e6903..9a4e7c4 100644 --- a/src/bingpai.rs +++ b/src/bingpai.rs @@ -66,36 +66,43 @@ pub(crate) enum InvalidBingpaiError { InvalidTileFor3Player(usize), } -pub(crate) fn count_bingpai(bingpai: &Bingpai) -> Result { - let num_bingpai = bingpai.iter().try_fold(0, |acc, &num_tile| { - if num_tile > MAX_NUM_SAME_TILE { - return Err(InvalidBingpaiError::ExceedsMaxNumSameTile(num_tile)); +pub(crate) trait BingpaiExt { + fn count(&self) -> Result; + fn count_3_player(&self) -> Result; +} + +impl BingpaiExt for Bingpai { + fn count(&self) -> Result { + let num_bingpai = self.iter().try_fold(0, |acc, &num_tile| { + if num_tile > MAX_NUM_SAME_TILE { + return Err(InvalidBingpaiError::ExceedsMaxNumSameTile(num_tile)); + } + Ok(acc + num_tile) + })?; + + if num_bingpai > MAX_NUM_SHOUPAI { + return Err(InvalidBingpaiError::ExceedsMaxNumBingpai(num_bingpai)); + } + if num_bingpai == 0 { + return Err(InvalidBingpaiError::EmptyBingpai); + } + if num_bingpai % 3 == 0 { + return Err(InvalidBingpaiError::InvalidNumBingpai(num_bingpai)); } - Ok(acc + num_tile) - })?; - if num_bingpai > MAX_NUM_SHOUPAI { - return Err(InvalidBingpaiError::ExceedsMaxNumBingpai(num_bingpai)); - } - if num_bingpai == 0 { - return Err(InvalidBingpaiError::EmptyBingpai); - } - if num_bingpai % 3 == 0 { - return Err(InvalidBingpaiError::InvalidNumBingpai(num_bingpai)); + Ok(num_bingpai) } - Ok(num_bingpai) -} + fn count_3_player(&self) -> Result { + self[1..8].iter().enumerate().try_for_each(|(i, &t)| { + if t > 0 { + return Err(InvalidBingpaiError::InvalidTileFor3Player(i + 1)); + } + Ok(()) + })?; -pub(crate) fn count_bingpai_3_player(bingpai: &Bingpai) -> Result { - bingpai[1..8].iter().enumerate().try_for_each(|(i, &t)| { - if t > 0 { - return Err(InvalidBingpaiError::InvalidTileFor3Player(i + 1)); - } - Ok(()) - })?; - - count_bingpai(bingpai) + self.count() + } } #[cfg(test)] @@ -123,9 +130,9 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, // z ]; - let num_bingpai_1 = count_bingpai(&bingpai_1).unwrap(); - let num_bingpai_2 = count_bingpai(&bingpai_2).unwrap(); - let num_bingpai_3 = count_bingpai(&bingpai_3).unwrap(); + let num_bingpai_1 = bingpai_1.count().unwrap(); + let num_bingpai_2 = bingpai_2.count().unwrap(); + let num_bingpai_3 = bingpai_3.count().unwrap(); assert_eq!(num_bingpai_1, bingpai_1.iter().sum()); assert_eq!(num_bingpai_2, bingpai_2.iter().sum()); @@ -140,7 +147,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 0, 0, 0, // z ]; - let result = count_bingpai(&bingpai).unwrap_err(); + let result = bingpai.count().unwrap_err(); assert!(matches!(result, InvalidBingpaiError::EmptyBingpai)); } @@ -152,7 +159,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 1, 1, 1, 1, 1, 1, // z ]; - let result = count_bingpai(&bingpai).unwrap_err(); + let result = bingpai.count().unwrap_err(); assert!(matches!( result, InvalidBingpaiError::ExceedsMaxNumBingpai(15) @@ -167,7 +174,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 0, 0, 0, // z ]; - let result_1 = count_bingpai(&bingpai_1).unwrap_err(); + let result_1 = bingpai_1.count().unwrap_err(); assert!(matches!( result_1, InvalidBingpaiError::ExceedsMaxNumSameTile(5) @@ -179,7 +186,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 0, 0, 0, // z ]; - let result_2 = count_bingpai(&bingpai_2).unwrap_err(); + let result_2 = bingpai_2.count().unwrap_err(); assert!(matches!( result_2, InvalidBingpaiError::ExceedsMaxNumSameTile(5) @@ -194,7 +201,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 1, 1, 1, // z ]; - let result = count_bingpai(&bingpai).unwrap_err(); + let result = bingpai.count().unwrap_err(); assert!(matches!(result, InvalidBingpaiError::InvalidNumBingpai(12))); } @@ -219,9 +226,9 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, // z ]; - let num_bingpai_1 = count_bingpai_3_player(&bingpai_1).unwrap(); - let num_bingpai_2 = count_bingpai_3_player(&bingpai_2).unwrap(); - let num_bingpai_3 = count_bingpai_3_player(&bingpai_3).unwrap(); + let num_bingpai_1 = bingpai_1.count_3_player().unwrap(); + let num_bingpai_2 = bingpai_2.count_3_player().unwrap(); + let num_bingpai_3 = bingpai_3.count_3_player().unwrap(); assert_eq!(num_bingpai_1, bingpai_1.iter().sum()); assert_eq!(num_bingpai_2, bingpai_2.iter().sum()); @@ -236,7 +243,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 0, 0, 0, // z ]; - let result = count_bingpai_3_player(&bingpai).unwrap_err(); + let result = bingpai.count_3_player().unwrap_err(); assert!(matches!(result, InvalidBingpaiError::EmptyBingpai)); } @@ -248,7 +255,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 1, 1, 1, 1, 1, 1, // z ]; - let result = count_bingpai_3_player(&bingpai).unwrap_err(); + let result = bingpai.count_3_player().unwrap_err(); assert!(matches!( result, InvalidBingpaiError::ExceedsMaxNumBingpai(15) @@ -263,7 +270,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 0, 0, 0, // z ]; - let result_1 = count_bingpai_3_player(&bingpai_1).unwrap_err(); + let result_1 = bingpai_1.count_3_player().unwrap_err(); assert!(matches!( result_1, InvalidBingpaiError::ExceedsMaxNumSameTile(5) @@ -275,7 +282,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 0, 0, 0, // z ]; - let result_2 = count_bingpai_3_player(&bingpai_2).unwrap_err(); + let result_2 = bingpai_2.count_3_player().unwrap_err(); assert!(matches!( result_2, InvalidBingpaiError::ExceedsMaxNumSameTile(5) @@ -290,7 +297,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 0, // s 0, 0, 0, 0, 1, 1, 1, // z ]; - let result = count_bingpai_3_player(&bingpai).unwrap_err(); + let result = bingpai.count_3_player().unwrap_err(); assert!(matches!(result, InvalidBingpaiError::InvalidNumBingpai(12))); } @@ -309,8 +316,8 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, // z ]; - let result_2m = count_bingpai_3_player(&bingpai_2m).unwrap_err(); - let result_8m = count_bingpai_3_player(&bingpai_8m).unwrap_err(); + let result_2m = bingpai_2m.count_3_player().unwrap_err(); + let result_8m = bingpai_8m.count_3_player().unwrap_err(); assert!(matches!( result_2m, diff --git a/src/calculate.rs b/src/calculate.rs index 997aa27..3085ab3 100644 --- a/src/calculate.rs +++ b/src/calculate.rs @@ -5,7 +5,7 @@ use super::qiduizi; use super::shisanyao; use super::standard; -use crate::bingpai::{count_bingpai, count_bingpai_3_player, Bingpai}; +use crate::bingpai::{Bingpai, BingpaiExt}; use crate::shoupai::{ validate_shoupai, validate_shoupai_3_player, FuluMianziList, InvalidShoupaiError, }; @@ -84,7 +84,7 @@ pub fn calculate_replacement_number( bingpai: &Bingpai, fulu_mianzi_list: &Option, ) -> Result { - let num_bingpai = count_bingpai(bingpai)?; + let num_bingpai = bingpai.count()?; if let Some(f) = fulu_mianzi_list { validate_shoupai(bingpai, f)?; @@ -174,7 +174,7 @@ pub fn calculate_replacement_number_3_player( bingpai: &Bingpai, fulu_mianzi_list: &Option, ) -> Result { - let num_bingpai = count_bingpai_3_player(bingpai)?; + let num_bingpai = bingpai.count_3_player()?; if let Some(f) = fulu_mianzi_list { validate_shoupai_3_player(bingpai, f)?;