1use crate::constants::field::Field;
2use crate::constants::hand::{Mentsu, WinningHand};
3use crate::constants::status::Status;
4use crate::constants::tiles::Tile;
5use crate::parser::ValidationError::InvalidHand;
6
7mod field_input;
8mod pi_input;
9mod status_input;
10
11#[derive(Debug, PartialEq)]
12pub enum ValidationError {
13 InvalidHand(String),
14 InvalidTileNumber(String, u8),
15 InvalidWinCombination(String, String),
16 OutOfRange(String),
17}
18
19trait InputBase {
20 fn validate(&self) -> Result<(), ValidationError>;
21}
22
23#[derive(Debug)]
24pub struct ParsedHand {
25 pub field: Field,
26 pub winning_hand: WinningHand,
27 pub status: Status,
28}
29
30#[derive(Clone)]
38pub struct PiInput {
39 pub hand: Vec<Tile>,
40 pub naki: Vec<Mentsu>,
41 pub hora: Tile,
42}
43
44pub struct Input {
52 pub pi_input: PiInput,
53 pub field_input: Field,
54 pub status_input: Status,
55}
56
57impl Input {
58 pub fn new(pi_input: PiInput, field_input: Field, status_input: Status) -> Self {
59 Self {
60 pi_input,
61 field_input,
62 status_input,
63 }
64 }
65
66 pub fn parse_hand(self) -> Result<Vec<ParsedHand>, ValidationError> {
67 self.validate()?;
68
69 let hand_results = self.pi_input.to_mentsu();
70 if hand_results.is_none() {
71 return Err(InvalidHand("Not a valid winning hand".to_string()));
72 }
73 let (hands, red_tiles) = hand_results.unwrap();
74
75 let mut result = Vec::new();
76
77 for hand in hands {
78 result.push(ParsedHand {
79 field: self.field_input.clone(),
80 winning_hand: WinningHand {
81 hand,
82 winning_tile: self.pi_input.hora.clone(),
83 red_tile: red_tiles,
84 },
85 status: self.status_input.clone(),
86 })
87 }
88
89 Ok(result)
90 }
91}
92
93impl InputBase for Input {
94 fn validate(&self) -> Result<(), ValidationError> {
95 self.pi_input.validate()?;
96 self.field_input.validate()?;
97 self.status_input.validate()?;
98
99 Ok(())
100 }
101}