diff --git a/client/src/components/auth.rs b/client/src/components/auth.rs index 5efcba3..1c3cdde 100644 --- a/client/src/components/auth.rs +++ b/client/src/components/auth.rs @@ -41,6 +41,7 @@ pub fn Auth() -> impl IntoView { placeholder=move || username.get() node_ref=username_input_ref /> + handle empty
impl IntoView { let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open; let game_update_context = expect_context::>>(); + let card_packs = expect_context::>(); let (active_games, set_active_games) = create_signal::>(vec![]); - let new_game_input_ref = create_node_ref::(); + let new_game_name_ref = create_node_ref::(); + let (selected_packs, set_selected_packs) = create_signal::>(BTreeSet::new()); + // create_effect(move |_| { + // logging::log!("{:#?}", selected_packs().iter().collect::>()); + // }); // Game stuff let new_game = move |_| { (websocket.send)( &to_string(&NewGameRequest { - name: new_game_input_ref.get().unwrap().value(), + name: new_game_name_ref.get().unwrap().value(), + packs: selected_packs() + .into_iter() + .map(|n| n.clone()) // hax + .collect::>(), }) .unwrap(), ); - new_game_input_ref.get().unwrap().set_value(""); + new_game_name_ref.get().unwrap().set_value(""); }; create_effect(move |_| { @@ -40,20 +52,128 @@ pub fn Browser() -> impl IntoView { set_active_games(vec![]); } }); + let (show_packs, set_show_packs) = create_signal(false); + + let show_packs_button = move |_| set_show_packs(!show_packs()); view! {
+

Game Browser

    -

    Game Browser

    {move || active_games().into_iter().map(|n| view! {
  • {n}
  • }).collect_view()}
+ +
+
+
+

Create Game

+ handle empty +

Packs

+
+ + + + finish this +
+ + +
+

Official

+ {move || { + card_packs() + .official_meta + .into_iter() + .map(|n| { + view! { + + + +
+ {set_selected_packs + .update(|packs| { + packs.insert(n.pack); + })} + } + }) + .collect_view() + }} + +
+
+

Unofficial

+ {move || { + card_packs() + .unofficial_meta + .into_iter() + .map(|n| { + view! { + + + +
+ } + }) + .collect_view() + }} + +
+
+
+ impl IntoView { type="submit" value="Send" /> + handle empty

diff --git a/client/src/components/websocket.rs b/client/src/components/websocket.rs index 0dfb9d1..244fdd9 100644 --- a/client/src/components/websocket.rs +++ b/client/src/components/websocket.rs @@ -1,9 +1,8 @@ -use std::rc::Rc; - use leptos::*; use leptos_use::{core::ConnectionReadyState, use_websocket, UseWebsocketReturn}; use lib::models::*; use serde_json::from_str; +use std::rc::Rc; #[derive(Clone)] pub struct WebSocketContext { @@ -74,12 +73,17 @@ pub fn Websocket() -> impl IntoView { let (chat_update, set_chat_update) = create_signal::>(Option::None); let (chat_message, set_chat_message) = create_signal::>(Option::None); let (active_games, set_active_games) = create_signal::>(Option::None); + let (card_packs_meta, set_card_packs_meta) = create_signal::(CardPacksMeta { + official_meta: vec![], + unofficial_meta: vec![], + }); // provide_context::>>(game_object); provide_context::>>(user_update); provide_context::>>(chat_update); provide_context::>>(chat_message); provide_context::>>(active_games); + provide_context::>(card_packs_meta); provide_context::>>(state_summary); // Message handler @@ -101,6 +105,8 @@ pub fn Websocket() -> impl IntoView { set_chat_update(Some(chat_update)); } else if let Ok(games_update) = from_str::(message) { set_active_games(Some(games_update)); + } else if let Ok(packs_meta_update) = from_str::(message) { + set_card_packs_meta(packs_meta_update); } else { logging::log!("Unhandled message: {}", message); } diff --git a/lib/src/game_master.rs b/lib/src/game_master.rs index bd14a44..c03a785 100644 --- a/lib/src/game_master.rs +++ b/lib/src/game_master.rs @@ -8,7 +8,7 @@ use crate::models::*; impl Game { /// Build game decks from input data for game start. /// This should only run once and at startup. - fn _build_decks(&mut self, cards_json: Vec) -> Result<()> { + fn _build_decks(&mut self, cards_json: Vec) -> Result<()> { for pack in cards_json { if let Some(white) = pack.white { self.white.extend(white) diff --git a/lib/src/models.rs b/lib/src/models.rs index df31f00..74796f0 100644 --- a/lib/src/models.rs +++ b/lib/src/models.rs @@ -1,6 +1,27 @@ use serde::{Deserialize, Serialize}; use std::sync::{Arc, RwLock}; +/// Card Pack Meta +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CardPackMeta { + pub name: String, + pub pack: u8, + pub num_white: usize, + pub num_black: usize, +} +/// Card Packs Meta +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct CardPacksMeta { + pub official_meta: Vec, + pub unofficial_meta: Vec, +} +/// Card Packs Meta +#[derive(Debug, Serialize, Deserialize)] +pub struct CardPacks { + pub official: Vec, + pub unofficial: Vec, +} + /// Games update #[derive(Serialize, Deserialize, Debug)] pub struct GamesUpdate { @@ -56,6 +77,7 @@ impl User { pub struct NewGameRequest { /// Game name pub name: String, + pub packs: Vec, } /// New game request structure @@ -97,13 +119,11 @@ pub struct CardBlack { pub pack: u8, } -/// A card set +/// A card pack #[derive(Debug, Serialize, Deserialize)] -pub struct CardSet { +pub struct CardPack { /// Name of the pack pub name: String, - /// Pack Description - pub description: Option, /// Whether or not this is an official card pack pub official: bool, /// White card data diff --git a/server/src/api.rs b/server/src/api.rs index b994ced..aa16920 100644 --- a/server/src/api.rs +++ b/server/src/api.rs @@ -93,6 +93,7 @@ async fn handle_new_user( .send(Message::Text(server_summary_update(state))) .await?; sender.send(Message::Text(games_update(state))).await?; + sender.send(Message::Text(cards_meta_update(state))).await?; // Broadcast new user's existence // this should probably be combined and sent as one @@ -138,6 +139,12 @@ fn chat_meta_update(state: &Arc) -> String { .unwrap() } +/// Generage cards meta message +fn cards_meta_update(state: &Arc) -> String { + tracing::debug!("sending cards meta"); + to_string::(&state.packs_meta).unwrap() +} + /// Generate message-of-the-day server greeting fn motd() -> String { to_string::(&ChatMessage { diff --git a/server/src/api/message_handler.rs b/server/src/api/message_handler.rs index c05aa2d..edc23af 100644 --- a/server/src/api/message_handler.rs +++ b/server/src/api/message_handler.rs @@ -64,6 +64,7 @@ fn handle_new_game( .unwrap() .clone(), }; + tracing::debug!("Game Packs {:?}", new_game.packs); // create game if let Ok(new_game_object) = Game::new(manifest) { diff --git a/server/src/main.rs b/server/src/main.rs index 6fb8b70..64af62c 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -16,27 +16,17 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; pub mod api; use crate::api::*; -/// Card Pack Meta -#[derive(Debug)] -pub struct CardPackMeta { - name: String, - description: Option, - pack: u8, - num_white: usize, - num_black: usize, -} - /// Parse json for card data -fn load_cards_from_json(path: &str) -> Result> { +fn load_cards_from_json(path: &str) -> Result<(CardPacks, CardPacksMeta)> { let data: String = read_to_string(path).with_context(|| format!("Invalid JSON path: \"{}\"", path))?; - let jayson: Vec = - serde_json::from_str(&data).with_context(|| format!("\"{path}\" is invalid json"))?; + let jayson: Vec = serde_json::from_str(&data) + .with_context(|| format!("The contents of \"{path}\" is not valid JSON."))?; + + let mut official: Vec = vec![]; + let mut unofficial: Vec = vec![]; - let mut official: Vec = vec![]; let mut official_meta: Vec = vec![]; - - let mut unofficial: Vec = vec![]; let mut unofficial_meta: Vec = vec![]; for set in jayson { @@ -59,7 +49,6 @@ fn load_cards_from_json(path: &str) -> Result> { let meta = CardPackMeta { name: set.name, - description: set.description, pack: pack.expect("No card pack number!"), num_white, num_black, @@ -80,11 +69,22 @@ fn load_cards_from_json(path: &str) -> Result> { tracing::debug!("{:#?}", unofficial_meta[0]); official.shrink_to_fit(); - official_meta.shrink_to_fit(); unofficial.shrink_to_fit(); + + let packs = CardPacks { + official, + unofficial, + }; + + official_meta.shrink_to_fit(); unofficial_meta.shrink_to_fit(); - Ok(official) + let packs_meta = CardPacksMeta { + official_meta, + unofficial_meta, + }; + + Ok((packs, packs_meta)) } /// Parse name list @@ -109,7 +109,8 @@ pub struct AppState { // Channel used to send messages to all connected clients. tx: broadcast::Sender, // Master card decks - all_cards: Vec, + packs: CardPacks, + packs_meta: CardPacksMeta, // Games list games: RwLock>, // chatrooms: Mutex>>, @@ -133,7 +134,7 @@ async fn main() -> Result<()> { let (tx, _rx) = broadcast::channel(100); let online_users = RwLock::new(HashMap::>>::new()); let offline_users = RwLock::new(HashMap::>>::new()); - let all_cards = load_cards_from_json("data/cah-cards-full.json")?; + let (packs, packs_meta) = load_cards_from_json("data/cah-cards-full.json")?; let games = RwLock::new(vec![]); let first_names = load_names("data/first.txt")?; let last_names = load_names("data/last.txt")?; @@ -142,7 +143,8 @@ async fn main() -> Result<()> { online_users, offline_users, tx, - all_cards, + packs, + packs_meta, games, first_names, last_names,