cards/client/src/components/game.rs

279 lines
10 KiB
Rust
Raw Normal View History

2024-08-27 18:37:04 -04:00
use crate::components::game::cards::*;
2024-08-26 02:37:09 -04:00
use crate::components::game::header::*;
2024-08-17 21:55:15 -04:00
use crate::components::websocket::WebSocketContext;
2024-08-09 01:21:04 -04:00
use leptos::*;
2024-08-21 22:25:33 -04:00
use leptos_use::core::ConnectionReadyState;
2024-08-09 02:57:27 -04:00
use lib::*;
2024-08-17 21:55:15 -04:00
use serde_json::to_string;
2024-08-20 22:25:39 -04:00
use std::collections::HashMap;
2024-08-27 18:37:04 -04:00
pub mod cards;
2024-08-26 02:37:09 -04:00
pub mod header;
pub mod meta;
pub mod scoreboard;
2024-08-09 01:21:04 -04:00
#[component]
pub fn Game() -> impl IntoView {
2024-08-26 02:37:09 -04:00
// Websocket stuff
2024-08-17 21:55:15 -04:00
let websocket = expect_context::<WebSocketContext>();
2024-08-25 15:57:41 -04:00
let tx = websocket.clone();
let (websocket_send, set_websocket_send) = create_signal("".to_string());
create_effect(move |_| {
tx.send(&websocket_send());
});
2024-08-26 02:37:09 -04:00
// Incoming
2024-08-21 22:25:33 -04:00
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
2024-08-14 00:16:54 -04:00
let game_meta = expect_context::<ReadSignal<Option<GameStateMeta>>>();
2024-08-20 22:25:39 -04:00
let judge_round = expect_context::<ReadSignal<Option<JudgeRound>>>();
2024-08-09 02:57:27 -04:00
2024-08-26 20:25:46 -04:00
// Signals //
2024-08-26 02:37:09 -04:00
let (selected_cards, set_selected_cards) = create_signal::<Vec<WhiteCardMeta>>(vec![]);
2024-08-18 18:48:37 -04:00
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
2024-08-26 20:25:46 -04:00
let (player_hand, set_player_hand) =
2024-08-26 02:37:09 -04:00
create_signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
2024-08-26 20:25:46 -04:00
let (judging, set_judging) = create_signal(false);
2024-08-20 22:25:39 -04:00
2024-08-26 20:25:46 -04:00
// Outoging
2024-08-26 02:37:09 -04:00
provide_context::<WriteSignal<String>>(set_card_clicked);
2024-08-20 22:25:39 -04:00
2024-08-26 20:25:46 -04:00
// On Incoming Meta //
2024-08-26 02:37:09 -04:00
// Put cards in a map for easier lookup
// The server sends a vec to preserve ordering
2024-08-09 02:57:27 -04:00
create_effect(move |_| {
2024-08-26 02:37:09 -04:00
if game_meta().is_some() {
for card in game_meta().unwrap().white {
2024-08-26 20:25:46 -04:00
set_player_hand.update(|map| {
2024-08-26 02:37:09 -04:00
map.insert(card.uuid.clone(), card.clone());
2024-08-18 19:51:45 -04:00
});
2024-08-18 18:48:37 -04:00
}
2024-08-09 02:57:27 -04:00
}
2024-08-26 20:25:46 -04:00
set_selected_cards.update(|list| {
list.clear();
});
2024-08-09 02:57:27 -04:00
});
2024-08-26 20:25:46 -04:00
// On Incoming Judge //
2024-08-17 21:55:15 -04:00
create_effect(move |_| {
2024-08-26 20:25:46 -04:00
// Clear selected cards
if judge_round().is_some() {
set_selected_cards.update(|list| {
list.clear();
});
set_judging(true);
2024-08-18 18:48:37 -04:00
}
2024-08-17 21:55:15 -04:00
});
2024-08-26 20:25:46 -04:00
// Player Submit Handler //
2024-08-25 15:57:41 -04:00
let submit_move = move |_| {
let msg = to_string(&PlayerMoveRequest {
2024-08-26 02:37:09 -04:00
game_id: game_meta().unwrap().uuid.clone(),
card_ids: selected_cards()
.iter()
.map(|card| card.uuid.clone())
.collect(),
2024-08-25 15:57:41 -04:00
})
.unwrap();
2024-08-20 22:25:39 -04:00
2024-08-25 15:57:41 -04:00
set_websocket_send(msg);
2024-08-26 20:25:46 -04:00
set_selected_cards.update(|list| {
list.clear();
});
2024-08-25 15:57:41 -04:00
};
2024-08-26 20:25:46 -04:00
// Judging Submit Handler //
2024-08-25 15:57:41 -04:00
let submit_judge = move |_| {
let msg = to_string(&JudgeDecisionRequest {
2024-08-26 02:37:09 -04:00
game_id: game_meta().unwrap().uuid.clone(),
winning_cards: selected_cards()
.iter()
.map(|card| card.uuid.clone())
.collect(),
2024-08-20 22:25:39 -04:00
})
2024-08-25 15:57:41 -04:00
.unwrap();
set_websocket_send(msg);
2024-08-26 20:25:46 -04:00
set_judging(false);
set_selected_cards.update(|list| {
list.clear();
});
2024-08-20 22:25:39 -04:00
};
2024-08-18 18:48:37 -04:00
2024-08-26 20:25:46 -04:00
// Card selection //
// Toggle selected status of cards
create_effect(move |_| {
if card_clicked() != "".to_string() {
if judging.get_untracked() {
let identical_cards = selected_cards
.get_untracked()
.into_iter()
.filter(|card| card.uuid == card_clicked.get_untracked())
.collect::<Vec<WhiteCardMeta>>();
if identical_cards.len() > 0 {
set_selected_cards.update(|list| {
list.clear();
});
} else {
// Clear selected cards
set_selected_cards.update(|list| {
list.clear();
});
// Select card group
for group in judge_round.get_untracked().unwrap().cards_to_judge {
for card in &group {
if card.uuid == card_clicked() {
set_selected_cards.update(|cards| cards.extend(group));
break;
}
}
}
}
// Clear the signal otherwise it selects the last selected card again
set_card_clicked.update_untracked(|value| value.clear());
} else {
if !selected_cards.get_untracked().contains(
player_hand
.get_untracked()
.get(&card_clicked.get_untracked())
.unwrap(),
) {
set_selected_cards.update(|cards| {
cards.push(player_hand().get(&card_clicked()).unwrap().clone())
})
} else if selected_cards
.get_untracked()
.contains(player_hand.get_untracked().get(&card_clicked()).unwrap())
{
set_selected_cards.update(|cards| {
cards.remove(
cards
.iter()
.position(|card| {
card == player_hand().get(&card_clicked()).unwrap()
})
.unwrap(),
);
})
}
// Clear the signal otherwise it selects the last selected card again
set_card_clicked.update_untracked(|value| value.clear());
}
}
});
2024-08-09 01:21:04 -04:00
view! {
2024-08-27 01:21:30 -04:00
<div>
2024-08-26 02:37:09 -04:00
<h2 class="text-2xl">Game</h2>
<Show
when=move || game_meta.get().is_some() && connected()
fallback=|| view! { "You are not in a game" }
>
<Header game_meta=game_meta().unwrap() />
</Show>
2024-08-26 20:25:46 -04:00
// Judging view //
2024-08-26 02:37:09 -04:00
2024-08-26 20:25:46 -04:00
<Show when=move || { judging() && connected() }>
2024-08-26 02:37:09 -04:00
<div class="w-full ms-16 inline-flex flex-wrap">
<BlackCard card_data=game_meta().unwrap().black />
// Selected cards
<For
each=move || selected_cards()
key=move |card| card.uuid.clone()
children=move |card| {
view! { <WhiteCard card_data=card.clone() /> }
}
/>
</div>
// Submit button
<div class="w-full inline-flex flex-wrap justify-center">
<button type="button" on:click=submit_judge>
Submit
</button>
</div>
2024-08-26 20:25:46 -04:00
<For
each=move || judge_round().unwrap().cards_to_judge
key=move |_| 69
children=move |group| {
view! {
<div class="m-2 inline-flex flex-wrap justify-center">
<For
each=move || group.clone()
key=move |card| card.uuid.clone()
children=move |card| {
view! {
// Hide cards from hand view when they exist as selected
<Show when={
let waste_of_memory = card.clone();
move || { !selected_cards().contains(&waste_of_memory) }
}>
<WhiteCard card_data=card.clone() />
</Show>
}
}
/>
</div>
}
}
/>
2024-08-26 02:37:09 -04:00
</Show>
2024-08-26 20:25:46 -04:00
// Playing view //
2024-08-26 02:37:09 -04:00
2024-08-26 20:25:46 -04:00
<Show when=move || game_meta.get().is_some() && connected() && !judging()>
2024-08-26 02:37:09 -04:00
// Play cards
<div class="w-full ms-16 inline-flex flex-wrap">
<BlackCard card_data=game_meta().unwrap().black />
// Selected cards
<For
each=move || selected_cards()
key=move |card| card.uuid.clone()
children=move |card| {
view! { <WhiteCard card_data=card.clone() /> }
}
/>
</div>
// Submit button
<div class="w-full inline-flex flex-wrap justify-center">
<button type="button" on:click=submit_move>
Submit
</button>
</div>
// Player hand
<div class="inline-flex flex-wrap justify-center">
<For
each=move || game_meta().unwrap().white
key=move |card| card.uuid.clone()
children=move |card| {
view! {
// Hide cards from hand view when they exist as selected
<Show when={
let id = card.uuid.clone();
move || {
2024-08-26 20:25:46 -04:00
if let Some(card) = player_hand().get(&id) {
2024-08-26 02:37:09 -04:00
!selected_cards().contains(card)
} else {
true
}
}
}>
<WhiteCard card_data=card.clone() />
</Show>
}
}
/>
</div>
</Show>
2024-08-09 01:21:04 -04:00
</div>
}
}