1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use serde::{Deserialize, Serialize};
use std::{
    collections::{HashMap, HashSet},
    sync::{Arc, RwLock},
};
#[derive(Deserialize, Serialize, Clone, Debug)]
pub enum Winning {
    C1(Vec<u32>),
    C2(Vec<u32>),
    T(Vec<u32>),
    TULUM(Vec<u32>),
}
#[derive(Default, Debug, Clone)]
pub struct Game {
    pub id: u64,
    pub c1: Vec<u32>,
    pub c2: Vec<u32>,
    pub t: Vec<u32>,
    pub balls: Vec<u8>,
    pub card_state: HashMap<u32, CardState>,
    pub card_index_by_number: CardIndex,
}
impl Game {
    pub fn new(game_id: u64, index: CardIndex) -> Arc<RwLock<Game>> {
        Arc::new(RwLock::new(Game {
            id: game_id,
            card_index_by_number: index,
            ..Default::default()
        }))
    }

    pub fn is_tulum(&self) -> bool {
        let (c1, c2, c3) = (&self.c1, &self.c2, &self.t);
        c1.len() == 1 && c2.len() == 1 && c3.len() == 1 && c1[0] == c2[0] && c2[0] == c3[0]
    }

    pub fn new_game(&mut self) -> u64 {
        self.id += 1;
        self.balls = Vec::new();
        self.c1 = Vec::new();
        self.c2 = Vec::new();
        self.t = Vec::new();
        self.card_state = HashMap::new();
        self.id
    }

    pub fn add_ball(&mut self, num: u8) -> Result<Option<Winning>, String> {
        if self.t.len() > 0 {
            return Err("game finished".to_string());
        } else if self.balls.contains(&num) {
            return Err("ball exists".to_string());
        }
        self.balls.push(num);
        let val = match self.card_index_by_number.get(&num) {
            Some(val) => val,
            None => return Ok(None),
        };
        let mut winner_cards: HashSet<u32> = HashSet::new();
        let num_row_required_to_win = if self.c1.len() == 0 {
            0
        } else if self.c2.len() == 0 {
            1
        } else if self.t.len() == 0 {
            2
        } else {
            return Ok(Some(Winning::T(self.t.clone())));
        };
        for card_info in val.iter() {
            let card_state = self.card_state.entry(card_info.card_id).or_default();
            let mut num_rows_completed = 0;
            match card_info.row {
                Row::R1 => card_state.r1 += 1,
                Row::R2 => card_state.r2 += 1,
                Row::R3 => card_state.r3 += 1,
            };
            if card_state.r1 > 4 {
                num_rows_completed += 1;
            }
            if card_state.r2 > 4 {
                num_rows_completed += 1;
            }
            if card_state.r3 > 4 {
                num_rows_completed += 1;
            }
            if num_rows_completed > num_row_required_to_win {
                winner_cards.insert(card_info.card_id);
            }
        }
        if !winner_cards.is_empty() {
            Ok(Some(match num_row_required_to_win {
                0 => {
                    self.c1 = winner_cards.into_iter().collect();
                    Winning::C1(self.c1.clone())
                }
                1 => {
                    self.c2 = winner_cards.into_iter().collect();
                    Winning::C2(self.c2.clone())
                }
                _ => {
                    self.t = winner_cards.into_iter().collect();
                    Winning::T(self.t.clone())
                }
            }))
        } else {
            Ok(None)
        }
    }
}
pub type CardIndex = HashMap<u8, Vec<Cardinfo>>; //number to card info
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum Row {
    R1,
    R2,
    R3,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Cardinfo {
    pub card_id: u32,
    pub row: Row,
}
#[derive(Default, Debug, Serialize, Deserialize, Clone)]
pub struct CardState {
    pub r1: u8,
    pub r2: u8,
    pub r3: u8,
}
pub type Card = (u32, [u8; 9], [u8; 9], [u8; 9]); //(id,row1,row2,row3)