use crate::*;
use mem6_common::*;
use serde_derive::{Serialize, Deserialize};
use unwrap::unwrap;
use rand::{rngs::SmallRng, seq::SliceRandom, SeedableRng, Rng};
use strum_macros::AsRefStr;
use web_sys::WebSocket;
#[derive(Serialize, Deserialize, Clone)]
pub struct Size2d {
pub hor: usize,
pub ver: usize,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct GameMetadata {
pub folder: String,
pub name: String,
pub description: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct GamesMetadata {
pub vec_game_metadata: Vec<GameMetadata>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct GameConfig {
pub card_moniker: Vec<String>,
pub img_filename: Vec<String>,
pub sound_filename: Vec<String>,
pub card_width: usize,
pub card_height: usize,
pub grid_items_hor: usize,
pub grid_items_ver: usize,
}
#[derive(Serialize, Deserialize, AsRefStr)]
pub enum CardStatusCardFace {
Down,
UpTemporary,
UpPermanently,
}
#[derive(Serialize, Deserialize)]
pub struct Card {
pub status: CardStatusCardFace,
pub card_number_and_img_src: usize,
pub card_index_and_id: usize,
}
#[derive(Serialize, Deserialize)]
pub struct MsgInQueue {
pub player_ws_uid: usize,
pub msg_id: usize,
pub msg: WsMessage,
}
pub struct GameData {
pub my_ws_uid: usize,
pub my_nickname: String,
pub my_player_number: usize,
pub ws: WebSocket,
pub players: Vec<Player>,
pub players_ws_uid: String,
pub game_status: GameStatus,
pub card_grid_data: Vec<Card>,
pub card_index_of_first_click: usize,
pub card_index_of_second_click: usize,
pub game_name: String,
pub player_turn: usize,
pub content_folders: Vec<String>,
pub games_metadata: Option<GamesMetadata>,
pub game_config: Option<GameConfig>,
pub error_text: String,
pub href: String,
pub href_hash: String,
pub is_reconnect: bool,
pub msgs_waiting_ack: Vec<MsgInQueue>,
pub show_debug_info: bool,
}
impl GameData {
pub fn prepare_random_data(&mut self) {
let item_count_minus_one = unwrap!(unwrap!(self.game_config.as_ref())
.card_moniker
.len()
.checked_sub(1));
let players_count = self.players.len();
let cards_count = unwrap!(players_count.checked_mul(unwrap!(unwrap!(self
.game_config
.as_ref())
.grid_items_hor
.checked_mul(unwrap!(self.game_config.as_ref()).grid_items_ver))));
let random_count = unwrap!(cards_count.checked_div(2));
let multiple: usize = unwrap!(random_count.checked_div(item_count_minus_one));
let rest =
unwrap!(random_count.checked_sub(unwrap!(item_count_minus_one.checked_mul(multiple))));
let mut vec_of_random_numbers = Vec::new();
let mut rng = SmallRng::from_entropy();
vec_of_random_numbers.clear();
for _i in 1..=rest {
let mut num: usize;
loop {
num = rng.gen_range(1, unwrap!(item_count_minus_one.checked_add(1)));
if !vec_of_random_numbers.contains(&num) {
break;
}
}
vec_of_random_numbers.push(num);
vec_of_random_numbers.push(num);
}
for _m in 1..=multiple {
for i in 1..=item_count_minus_one {
vec_of_random_numbers.push(i);
vec_of_random_numbers.push(i);
}
}
let rnd_slice = vec_of_random_numbers.as_mut_slice();
rnd_slice.shuffle(&mut rng);
let mut card_grid_data = Vec::new();
let new_card = Card {
status: CardStatusCardFace::Down,
card_number_and_img_src: 0,
card_index_and_id: 0,
};
card_grid_data.push(new_card);
for (index, random_number) in vec_of_random_numbers.iter().enumerate() {
let new_card = Card {
status: CardStatusCardFace::Down,
card_number_and_img_src: *random_number,
card_index_and_id: unwrap!(index.checked_add(1), "usize overflow"),
};
card_grid_data.push(new_card);
}
self.card_grid_data = card_grid_data;
}
pub fn prepare_for_empty() -> Vec<Card> {
let mut card_grid_data = Vec::new();
for i in 0..=32 {
let new_card = Card {
status: CardStatusCardFace::Down,
card_number_and_img_src: 1,
card_index_and_id: i,
};
card_grid_data.push(new_card);
}
card_grid_data
}
pub fn new(ws: WebSocket, my_ws_uid: usize) -> Self {
let my_nickname = divnicknamemod::load_nickname();
let mut players = Vec::new();
players.push(Player {
ws_uid: my_ws_uid,
nickname: my_nickname.to_string(),
points: 0,
});
let players_ws_uid = prepare_players_ws_uid(&players);
GameData {
card_grid_data: Self::prepare_for_empty(),
card_index_of_first_click: 0,
card_index_of_second_click: 0,
ws,
my_ws_uid,
my_nickname,
players,
players_ws_uid,
game_status: GameStatus::StatusStartPage,
game_name: "alphabet".to_string(),
my_player_number: 1,
player_turn: 0,
content_folders: vec![String::from("alphabet")],
game_config: None,
games_metadata: None,
error_text: "".to_string(),
href: "".to_string(),
href_hash: "".to_string(),
is_reconnect: false,
msgs_waiting_ack: vec![],
show_debug_info: false,
}
}
}
pub fn prepare_players_ws_uid(players: &[Player]) -> String {
let mut players_ws_uid = Vec::new();
for pl in players {
players_ws_uid.push(pl.ws_uid);
}
unwrap!(serde_json::to_string(&players_ws_uid))
}