start rewriting game component
This commit is contained in:
parent
f7ffb5bb20
commit
9f9ce406ea
8 changed files with 434 additions and 199 deletions
|
@ -2,11 +2,11 @@ use leptos::*;
|
||||||
use lib::WhiteCardMeta;
|
use lib::WhiteCardMeta;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn BlackCard(card_data: ReadSignal<(String, u8)>) -> impl IntoView {
|
pub fn BlackCard(card_data: (String, u8)) -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
<div class="relative m-2 w-40 h-60 text-white bg-black rounded-lg">
|
<div class="relative m-2 w-40 h-60 text-white bg-black rounded-lg">
|
||||||
<p class="p-4">{move || card_data().0}</p>
|
<p class="p-4">{card_data.0}</p>
|
||||||
<p class="absolute right-4 bottom-4">Pick: {move || card_data().1}</p>
|
<p class="absolute right-4 bottom-4">Pick: {card_data.1}</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,169 +1,105 @@
|
||||||
use crate::components::cards::*;
|
use crate::components::cards::*;
|
||||||
|
use crate::components::game::header::*;
|
||||||
use crate::components::websocket::WebSocketContext;
|
use crate::components::websocket::WebSocketContext;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::core::ConnectionReadyState;
|
use leptos_use::core::ConnectionReadyState;
|
||||||
use lib::*;
|
use lib::*;
|
||||||
use serde_json::to_string;
|
use serde_json::to_string;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
pub mod header;
|
||||||
|
pub mod meta;
|
||||||
|
pub mod scoreboard;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Game() -> impl IntoView {
|
pub fn Game() -> impl IntoView {
|
||||||
|
// Websocket stuff
|
||||||
let websocket = expect_context::<WebSocketContext>();
|
let websocket = expect_context::<WebSocketContext>();
|
||||||
let tx = websocket.clone();
|
let tx = websocket.clone();
|
||||||
let (websocket_send, set_websocket_send) = create_signal("".to_string());
|
let (websocket_send, set_websocket_send) = create_signal("".to_string());
|
||||||
create_effect(move |_| {
|
create_effect(move |_| {
|
||||||
tx.send(&websocket_send());
|
tx.send(&websocket_send());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Incoming
|
||||||
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
||||||
let game_meta = expect_context::<ReadSignal<Option<GameStateMeta>>>();
|
let game_meta = expect_context::<ReadSignal<Option<GameStateMeta>>>();
|
||||||
let judge_round = expect_context::<ReadSignal<Option<JudgeRound>>>();
|
let judge_round = expect_context::<ReadSignal<Option<JudgeRound>>>();
|
||||||
|
|
||||||
let (game_id, set_game_id) = create_signal("".to_string());
|
// Internal
|
||||||
let (game_name, set_game_name) = create_signal("".to_string());
|
let (selected_cards, set_selected_cards) = create_signal::<Vec<WhiteCardMeta>>(vec![]);
|
||||||
let (game_host, set_game_host) = create_signal("".to_string());
|
|
||||||
let (game_players, set_game_players) = create_signal(vec![]);
|
|
||||||
let (game_czar, set_game_czar) = create_signal("".to_string());
|
|
||||||
let (game_white_count, set_game_white_count) = create_signal(0usize);
|
|
||||||
let (game_black_count, set_game_black_count) = create_signal(0usize);
|
|
||||||
let (game_white_discard_count, set_game_white_discard_count) = create_signal(0usize);
|
|
||||||
let (game_black, set_game_black) = create_signal(("".to_string(), 0u8));
|
|
||||||
let (selected_cards_ordered, set_selected_cards_ordered) = create_signal::<Vec<String>>(vec![]);
|
|
||||||
let (player_hand, set_player_hand) = create_signal::<Vec<String>>(vec![]);
|
|
||||||
let (player_white, set_player_white) =
|
|
||||||
create_signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
|
|
||||||
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
|
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
|
||||||
|
let (white_map, set_white_map) =
|
||||||
|
create_signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
|
||||||
|
|
||||||
|
// For subcomponents
|
||||||
provide_context::<WriteSignal<String>>(set_card_clicked);
|
provide_context::<WriteSignal<String>>(set_card_clicked);
|
||||||
|
|
||||||
// Clear everything on disconnect
|
// Put cards in a map for easier lookup
|
||||||
|
// The server sends a vec to preserve ordering
|
||||||
create_effect(move |_| {
|
create_effect(move |_| {
|
||||||
if !connected() {
|
if game_meta().is_some() {
|
||||||
set_game_id("".to_string());
|
for card in game_meta().unwrap().white {
|
||||||
set_game_name("".to_string());
|
set_white_map.update(|map| {
|
||||||
set_game_host("".to_string());
|
map.insert(card.uuid.clone(), card.clone());
|
||||||
set_game_players(vec![]);
|
|
||||||
set_game_czar("".to_string());
|
|
||||||
set_game_black(("".to_string(), 0u8));
|
|
||||||
set_selected_cards_ordered(vec![]);
|
|
||||||
set_player_hand(vec![]);
|
|
||||||
set_player_white.update(|hand| {
|
|
||||||
hand.clear();
|
|
||||||
});
|
|
||||||
set_game_white_count(0usize);
|
|
||||||
set_game_black_count(0usize);
|
|
||||||
set_game_white_discard_count(0usize);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle incoming judge message
|
|
||||||
create_effect(move |_| {
|
|
||||||
judge_round.with(move |judge_round| {
|
|
||||||
set_player_hand.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
set_player_white.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
set_card_clicked.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load hand
|
|
||||||
if let Some(judge) = judge_round {
|
|
||||||
for cards in judge.cards_to_judge.clone() {
|
|
||||||
for card in cards {
|
|
||||||
set_player_white.update(|hand| {
|
|
||||||
hand.insert(card.uuid.clone(), card.clone());
|
|
||||||
});
|
|
||||||
set_player_hand.update(|hand| {
|
|
||||||
hand.push(card.uuid.clone());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle incoming state update
|
|
||||||
create_effect(move |_| {
|
|
||||||
if let Some(game) = game_meta() {
|
|
||||||
// Clear in case of (re-)joining game
|
|
||||||
set_card_clicked.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
set_selected_cards_ordered.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
set_player_hand.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
set_player_white.update(|list| {
|
|
||||||
list.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load meta
|
|
||||||
set_game_id(game.uuid.clone());
|
|
||||||
set_game_name(game.name.clone());
|
|
||||||
set_game_host(game.host.clone());
|
|
||||||
set_game_players(game.players.clone());
|
|
||||||
set_game_czar(game.czar.clone());
|
|
||||||
set_game_black(game.black.clone());
|
|
||||||
set_game_white_count(game.white_count.clone());
|
|
||||||
set_game_black_count(game.black_count.clone());
|
|
||||||
set_game_white_discard_count(game.white_discard_count.clone());
|
|
||||||
|
|
||||||
// Load hand
|
|
||||||
for card in game.white {
|
|
||||||
set_player_white.update(|hand| {
|
|
||||||
hand.insert(card.uuid.clone(), card.clone());
|
|
||||||
});
|
|
||||||
set_player_hand.update(|hand| {
|
|
||||||
hand.push(card.uuid.clone());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Move cards back and forth between hand and selected when clicked
|
// Toggle selected status of cards
|
||||||
create_effect(move |_| {
|
create_effect(move |_| {
|
||||||
if let Some(card_index) = player_hand()
|
if card_clicked() != "".to_string() {
|
||||||
.iter()
|
if !selected_cards().contains(white_map().get(&card_clicked()).unwrap()) {
|
||||||
.position(|card| *card == card_clicked())
|
set_selected_cards
|
||||||
{
|
.update(|cards| cards.push(white_map().get(&card_clicked()).unwrap().clone()))
|
||||||
set_player_hand.update(|list| {
|
} else if selected_cards().contains(white_map().get(&card_clicked()).unwrap()) {
|
||||||
list.remove(card_index);
|
set_selected_cards.update(|cards| {
|
||||||
});
|
cards.remove(
|
||||||
|
cards
|
||||||
|
.iter()
|
||||||
|
.position(|card| card == white_map().get(&card_clicked()).unwrap())
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
set_selected_cards_ordered.update(|list| {
|
// You can't clear selected_cards without this line so don't fuck with it
|
||||||
list.push(card_clicked());
|
set_card_clicked("".to_string());
|
||||||
})
|
|
||||||
} else if let Some(card_index) = selected_cards_ordered()
|
|
||||||
.iter()
|
|
||||||
.position(|card| *card == card_clicked())
|
|
||||||
{
|
|
||||||
set_selected_cards_ordered.update(|list| {
|
|
||||||
list.remove(card_index);
|
|
||||||
});
|
|
||||||
|
|
||||||
set_player_hand.update(|list| {
|
|
||||||
list.push(card_clicked());
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Runs when submit button is clicked
|
||||||
let submit_move = move |_| {
|
let submit_move = move |_| {
|
||||||
let msg = to_string(&PlayerMoveRequest {
|
let msg = to_string(&PlayerMoveRequest {
|
||||||
game_id: game_id(),
|
game_id: game_meta().unwrap().uuid.clone(),
|
||||||
card_ids: selected_cards_ordered(),
|
card_ids: selected_cards()
|
||||||
|
.iter()
|
||||||
|
.map(|card| card.uuid.clone())
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
set_websocket_send(msg);
|
set_websocket_send(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// On incoming judge
|
||||||
|
create_effect(move |_| {
|
||||||
|
// Clear selected cards
|
||||||
|
if judge_round().is_some() {
|
||||||
|
set_selected_cards.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Runs when judging submit button is clicked
|
||||||
let submit_judge = move |_| {
|
let submit_judge = move |_| {
|
||||||
let msg = to_string(&JudgeDecisionRequest {
|
let msg = to_string(&JudgeDecisionRequest {
|
||||||
game_id: game_id(),
|
game_id: game_meta().unwrap().uuid.clone(),
|
||||||
winning_cards: selected_cards_ordered(),
|
winning_cards: selected_cards()
|
||||||
|
.iter()
|
||||||
|
.map(|card| card.uuid.clone())
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -172,80 +108,106 @@ pub fn Game() -> impl IntoView {
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="p-1">
|
<div class="p-1">
|
||||||
<div class="relative">
|
<h2 class="text-2xl">Game</h2>
|
||||||
<h2 class="text-2xl">Game</h2>
|
<Show
|
||||||
<span>
|
when=move || game_meta.get().is_some() && connected()
|
||||||
<p>Name: {move || game_name()}</p>
|
fallback=|| view! { "You are not in a game" }
|
||||||
<p>Host: {move || game_host()}</p>
|
>
|
||||||
<p>Czar: {move || game_czar()}</p>
|
<Header game_meta=game_meta().unwrap() />
|
||||||
<p>White Deck: {move || game_white_count().to_string()}</p>
|
</Show>
|
||||||
<p>White Discard: {move || game_white_discard_count().to_string()}</p>
|
|
||||||
<p>Black Deck: {move || game_black_count().to_string()}</p>
|
// ////////////////////
|
||||||
</span>
|
// Player is judging //
|
||||||
<span class="absolute top-0 right-0">
|
// ////////////////////
|
||||||
<p>Players:</p>
|
|
||||||
<table class="min-w-full border border-collapse table-auto">
|
<Show when=move || { judge_round.get().is_some() && connected() }>
|
||||||
<thead>
|
<div class="w-full ms-16 inline-flex flex-wrap">
|
||||||
<tr>
|
<BlackCard card_data=game_meta().unwrap().black />
|
||||||
<th class="border-b">Name</th>
|
|
||||||
<th class="border-b">Score</th>
|
// Selected cards
|
||||||
</tr>
|
<For
|
||||||
</thead>
|
each=move || selected_cards()
|
||||||
{move || {
|
key=move |card| card.uuid.clone()
|
||||||
game_players()
|
children=move |card| {
|
||||||
.iter()
|
view! { <WhiteCard card_data=card.clone() /> }
|
||||||
.map(|player| {
|
}
|
||||||
view! {
|
/>
|
||||||
<tr>
|
</div>
|
||||||
<td class="text-center border-b">{&player.name}</td>
|
|
||||||
<td class="text-center border-b">
|
{judge_round()
|
||||||
{&player.score.to_string()}
|
.unwrap()
|
||||||
</td>
|
.cards_to_judge
|
||||||
</tr>
|
.iter()
|
||||||
|
.map(|group| view! { {format!("{:#?}", group)} })
|
||||||
|
.collect_view()}
|
||||||
|
|
||||||
|
<For
|
||||||
|
each=move || judge_round().unwrap().cards_to_judge
|
||||||
|
key=move |_| 69
|
||||||
|
children=move |group| { { format!("{:#?}", group) } }
|
||||||
|
/>
|
||||||
|
|
||||||
|
// Submit button
|
||||||
|
<div class="w-full inline-flex flex-wrap justify-center">
|
||||||
|
<button type="button" on:click=submit_judge>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
// ////////////////////
|
||||||
|
// Player is playing //
|
||||||
|
// ////////////////////
|
||||||
|
|
||||||
|
<Show when=move || game_meta.get().is_some() && connected() && !judge_round().is_some()>
|
||||||
|
|
||||||
|
// 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 || {
|
||||||
|
if let Some(card) = white_map().get(&id) {
|
||||||
|
!selected_cards().contains(card)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
}>
|
||||||
.collect_view()
|
<WhiteCard card_data=card.clone() />
|
||||||
}}
|
</Show>
|
||||||
</table>
|
}
|
||||||
</span>
|
}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
// Game cards
|
|
||||||
// TODO: offset this correctly
|
|
||||||
<div class="w-full ms-16 inline-flex flex-wrap">
|
|
||||||
<BlackCard card_data=game_black />
|
|
||||||
|
|
||||||
// Card selection
|
|
||||||
<For
|
|
||||||
each=move || selected_cards_ordered()
|
|
||||||
key=move |card| player_white().get(card).unwrap().uuid.clone()
|
|
||||||
children=move |card| {
|
|
||||||
view! { <WhiteCard card_data=player_white().get(&card).unwrap().clone() /> }
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="w-full inline-flex flex-wrap justify-center">
|
|
||||||
<button type="button" on:click=submit_move>
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="w-full inline-flex flex-wrap justify-center">
|
|
||||||
<button type="button" on:click=submit_judge>
|
|
||||||
Judge
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
// Player cards
|
|
||||||
<div class="inline-flex flex-wrap justify-center">
|
|
||||||
<For
|
|
||||||
each=move || player_hand()
|
|
||||||
key=move |card| player_white().get(card).unwrap().uuid.clone()
|
|
||||||
children=move |card| {
|
|
||||||
view! { <WhiteCard card_data=player_white().get(&card).unwrap().clone() /> }
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
client/src/components/game/header.rs
Normal file
14
client/src/components/game/header.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use crate::components::game::meta::*;
|
||||||
|
use crate::components::game::scoreboard::*;
|
||||||
|
use leptos::*;
|
||||||
|
use lib::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Header(game_meta: GameStateMeta) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<div class="relative">
|
||||||
|
<Meta game_meta=game_meta.clone() />
|
||||||
|
<Scoreboard game_meta=game_meta.clone() />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
17
client/src/components/game/meta.rs
Normal file
17
client/src/components/game/meta.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use leptos::*;
|
||||||
|
use lib::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Meta(game_meta: GameStateMeta) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<span>
|
||||||
|
<p>Name: {game_meta.name}</p>
|
||||||
|
<p>Host: {game_meta.host}</p>
|
||||||
|
<p>Czar: {game_meta.czar}</p>
|
||||||
|
<p>White Deck: {game_meta.white_count.to_string()}</p>
|
||||||
|
<p>White Discard: {move || game_meta.white_discard_count.to_string()}</p>
|
||||||
|
<p>Black Deck: {move || game_meta.black_count.to_string()}</p>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
31
client/src/components/game/scoreboard.rs
Normal file
31
client/src/components/game/scoreboard.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use leptos::*;
|
||||||
|
use lib::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Scoreboard(game_meta: GameStateMeta) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<span class="absolute top-0 right-0">
|
||||||
|
<p>Players:</p>
|
||||||
|
<table class="min-w-full border border-collapse table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="border-b">Name</th>
|
||||||
|
<th class="border-b">Score</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{game_meta
|
||||||
|
.players
|
||||||
|
.iter()
|
||||||
|
.map(|player| {
|
||||||
|
view! {
|
||||||
|
<tr>
|
||||||
|
<td class="text-center border-b">{&player.name}</td>
|
||||||
|
<td class="text-center border-b">{&player.score.to_string()}</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect_view()}
|
||||||
|
</table>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
211
client/src/components/game_old.rs
Normal file
211
client/src/components/game_old.rs
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
use crate::components::cards::*;
|
||||||
|
use crate::components::websocket::WebSocketContext;
|
||||||
|
use leptos::*;
|
||||||
|
use leptos_use::core::ConnectionReadyState;
|
||||||
|
use lib::*;
|
||||||
|
use serde_json::to_string;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Game() -> impl IntoView {
|
||||||
|
let websocket = expect_context::<WebSocketContext>();
|
||||||
|
let tx = websocket.clone();
|
||||||
|
let (websocket_send, set_websocket_send) = create_signal("".to_string());
|
||||||
|
create_effect(move |_| {
|
||||||
|
tx.send(&websocket_send());
|
||||||
|
});
|
||||||
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
||||||
|
let game_meta = expect_context::<ReadSignal<Option<GameStateMeta>>>();
|
||||||
|
let judge_round = expect_context::<ReadSignal<Option<JudgeRound>>>();
|
||||||
|
|
||||||
|
let (game_id, set_game_id) = create_signal("".to_string());
|
||||||
|
let (game_name, set_game_name) = create_signal("".to_string());
|
||||||
|
let (game_host, set_game_host) = create_signal("".to_string());
|
||||||
|
let (game_players, set_game_players) = create_signal(vec![]);
|
||||||
|
let (game_czar, set_game_czar) = create_signal("".to_string());
|
||||||
|
let (game_white_count, set_game_white_count) = create_signal(0usize);
|
||||||
|
let (game_black_count, set_game_black_count) = create_signal(0usize);
|
||||||
|
let (game_white_discard_count, set_game_white_discard_count) = create_signal(0usize);
|
||||||
|
let (game_black, set_game_black) = create_signal(("".to_string(), 0u8));
|
||||||
|
let (selected_cards_ordered, set_selected_cards_ordered) = create_signal::<Vec<String>>(vec![]);
|
||||||
|
let (player_hand, set_player_hand) = create_signal::<Vec<String>>(vec![]);
|
||||||
|
let (player_white, set_player_white) =
|
||||||
|
create_signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
|
||||||
|
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
|
||||||
|
provide_context::<WriteSignal<String>>(set_card_clicked);
|
||||||
|
|
||||||
|
// Clear everything on disconnect
|
||||||
|
create_effect(move |_| {
|
||||||
|
if !connected() {
|
||||||
|
set_game_id("".to_string());
|
||||||
|
set_game_name("".to_string());
|
||||||
|
set_game_host("".to_string());
|
||||||
|
set_game_players(vec![]);
|
||||||
|
set_game_czar("".to_string());
|
||||||
|
set_game_black(("".to_string(), 0u8));
|
||||||
|
set_selected_cards_ordered(vec![]);
|
||||||
|
set_player_hand(vec![]);
|
||||||
|
set_player_white.update(|hand| {
|
||||||
|
hand.clear();
|
||||||
|
});
|
||||||
|
set_game_white_count(0usize);
|
||||||
|
set_game_black_count(0usize);
|
||||||
|
set_game_white_discard_count(0usize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle incoming judge message
|
||||||
|
create_effect(move |_| {
|
||||||
|
judge_round.with(move |judge_round| {
|
||||||
|
set_player_hand.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
set_player_white.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
set_card_clicked.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load hand
|
||||||
|
if let Some(judge) = judge_round {
|
||||||
|
for cards in judge.cards_to_judge.clone() {
|
||||||
|
for card in cards {
|
||||||
|
set_player_white.update(|hand| {
|
||||||
|
hand.insert(card.uuid.clone(), card.clone());
|
||||||
|
});
|
||||||
|
set_player_hand.update(|hand| {
|
||||||
|
hand.push(card.uuid.clone());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle incoming state update
|
||||||
|
create_effect(move |_| {
|
||||||
|
if let Some(game) = game_meta() {
|
||||||
|
// Clear in case of (re-)joining game
|
||||||
|
set_card_clicked.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
set_selected_cards_ordered.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
set_player_hand.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
set_player_white.update(|list| {
|
||||||
|
list.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load meta
|
||||||
|
set_game_id(game.uuid.clone());
|
||||||
|
set_game_name(game.name.clone());
|
||||||
|
set_game_host(game.host.clone());
|
||||||
|
set_game_players(game.players.clone());
|
||||||
|
set_game_czar(game.czar.clone());
|
||||||
|
set_game_black(game.black.clone());
|
||||||
|
set_game_white_count(game.white_count.clone());
|
||||||
|
set_game_black_count(game.black_count.clone());
|
||||||
|
set_game_white_discard_count(game.white_discard_count.clone());
|
||||||
|
|
||||||
|
// Load hand
|
||||||
|
for card in game.white {
|
||||||
|
set_player_white.update(|hand| {
|
||||||
|
hand.insert(card.uuid.clone(), card.clone());
|
||||||
|
});
|
||||||
|
set_player_hand.update(|hand| {
|
||||||
|
hand.push(card.uuid.clone());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Move cards back and forth between hand and selected when clicked
|
||||||
|
create_effect(move |_| {
|
||||||
|
if let Some(card_index) = player_hand()
|
||||||
|
.iter()
|
||||||
|
.position(|card| *card == card_clicked())
|
||||||
|
{
|
||||||
|
set_player_hand.update(|list| {
|
||||||
|
list.remove(card_index);
|
||||||
|
});
|
||||||
|
|
||||||
|
set_selected_cards_ordered.update(|list| {
|
||||||
|
list.push(card_clicked());
|
||||||
|
})
|
||||||
|
} else if let Some(card_index) = selected_cards_ordered()
|
||||||
|
.iter()
|
||||||
|
.position(|card| *card == card_clicked())
|
||||||
|
{
|
||||||
|
set_selected_cards_ordered.update(|list| {
|
||||||
|
list.remove(card_index);
|
||||||
|
});
|
||||||
|
|
||||||
|
set_player_hand.update(|list| {
|
||||||
|
list.push(card_clicked());
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let submit_move = move |_| {
|
||||||
|
let msg = to_string(&PlayerMoveRequest {
|
||||||
|
game_id: game_id(),
|
||||||
|
card_ids: selected_cards_ordered(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
set_websocket_send(msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
let submit_judge = move |_| {
|
||||||
|
let msg = to_string(&JudgeDecisionRequest {
|
||||||
|
game_id: game_id(),
|
||||||
|
winning_cards: selected_cards_ordered(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
set_websocket_send(msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<div class="p-1">
|
||||||
|
// Game cards
|
||||||
|
// TODO: offset this correctly
|
||||||
|
<div class="w-full ms-16 inline-flex flex-wrap">
|
||||||
|
// Card selection
|
||||||
|
<For
|
||||||
|
each=move || selected_cards_ordered()
|
||||||
|
key=move |card| player_white().get(card).unwrap().uuid.clone()
|
||||||
|
children=move |card| {
|
||||||
|
view! { <WhiteCard card_data=player_white().get(&card).unwrap().clone() /> }
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="w-full inline-flex flex-wrap justify-center">
|
||||||
|
<button type="button" on:click=submit_move>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="w-full inline-flex flex-wrap justify-center">
|
||||||
|
<button type="button" on:click=submit_judge>
|
||||||
|
Judge
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// Player cards
|
||||||
|
<div class="inline-flex flex-wrap justify-center">
|
||||||
|
<For
|
||||||
|
each=move || player_hand()
|
||||||
|
key=move |card| player_white().get(card).unwrap().uuid.clone()
|
||||||
|
children=move |card| {
|
||||||
|
view! { <WhiteCard card_data=player_white().get(&card).unwrap().clone() /> }
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod cards;
|
|
||||||
pub mod browser;
|
pub mod browser;
|
||||||
|
pub mod cards;
|
||||||
pub mod chat;
|
pub mod chat;
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
pub mod game;
|
pub mod game;
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub struct PlayerMoveRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// White Card Meta
|
/// White Card Meta
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct WhiteCardMeta {
|
pub struct WhiteCardMeta {
|
||||||
pub uuid: String,
|
pub uuid: String,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
|
|
Loading…
Add table
Reference in a new issue