From f92ca7acbf6998f8cd2cb6b7e1116fcbd29767e4 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Wed, 7 Sep 2022 21:03:07 -0400 Subject: Add game component integrated with bidding component --- webapp/src/components.rs | 2 ++ webapp/src/components/bidding.rs | 78 ++++++++++++++++++++++------------------ webapp/src/components/game.rs | 68 +++++++++++++++++++++++++++++++++++ webapp/src/main.rs | 43 ++-------------------- 4 files changed, 115 insertions(+), 76 deletions(-) create mode 100644 webapp/src/components/game.rs (limited to 'webapp/src') diff --git a/webapp/src/components.rs b/webapp/src/components.rs index e13d372..6d9a5ec 100644 --- a/webapp/src/components.rs +++ b/webapp/src/components.rs @@ -5,11 +5,13 @@ mod hand; mod bidding_table; mod bidding_box; mod bidding; +mod game; pub use self::card::*; pub use self::bidding_box::*; pub use self::bidding_table::*; pub use self::bidding::*; +pub use self::game::*; pub use self::hand::*; pub fn suit_css_class(suit: Suit) -> &'static str { diff --git a/webapp/src/components/bidding.rs b/webapp/src/components/bidding.rs index b8fd893..26a4426 100644 --- a/webapp/src/components/bidding.rs +++ b/webapp/src/components/bidding.rs @@ -1,50 +1,58 @@ -use crate::bridge_engine::{Bid, BiddingResult, Player}; +use crate::bridge_engine::{self, Bid, BiddingResult, Contract, Player}; use crate::components::{BiddingBox, BiddingTable}; +use log::{info, error}; use yew::prelude::*; -#[derive(Debug)] -pub enum Msg { - Bid(Bid), -} - -pub struct Bidding { - bidding: BiddingResult, -} -#[derive(PartialEq, Properties)] +#[derive(PartialEq, Properties, Clone)] pub struct BiddingProperties { pub dealer: Player, + pub on_contract: Callback<(Contract, bridge_engine::Bidding)>, } -impl Component for Bidding { - type Message = Msg; - type Properties = BiddingProperties; +#[function_component(Bidding)] +pub fn bidding(props: &BiddingProperties) -> Html { + let bidding = use_state(|| bridge_engine::Bidding::new(props.dealer)); - fn create(ctx: &Context) -> Self { - Self { - bidding: BiddingResult::new(ctx.props().dealer), - } + { + let bidding = bidding.clone(); + let dealer = props.dealer.clone(); + use_effect_with_deps( + move |_| { + bidding.set(bridge_engine::Bidding::new(dealer)); + || () + }, + dealer, + ); } - fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { - match msg { - Msg::Bid(bid) => { - self.bidding = self.bidding.bidding().clone().bid(bid).unwrap(); - true + let on_bid = { + let bidding = bidding.clone(); + let on_contract = props.on_contract.clone(); + Callback::from(move |bid| { + match (*bidding).clone().bid(bid) { + Ok(BiddingResult::Contract(contract, bidding)) => { + on_contract.emit((contract, bidding)); + }, + Ok(BiddingResult::InProgress(new_bidding)) => { + bidding.set(new_bidding); + } + Err(err) => { + error!("Failed to place bid: {:?}", err); + } } - } - } + }) + }; - fn view(&self, ctx: &Context) -> Html { - html! { - <> -

{ "Bidding table" }

- -

{ "Bidding box" }

- - - } + html! { + <> +

{ "Bidding table" }

+ +

{ "Bidding box" }

+ + } } diff --git a/webapp/src/components/game.rs b/webapp/src/components/game.rs new file mode 100644 index 0000000..d31433d --- /dev/null +++ b/webapp/src/components/game.rs @@ -0,0 +1,68 @@ +use crate::bridge_engine::{self, Contract, Player}; +use crate::card; +use crate::card::Suit; +use crate::components::{Bidding, Hand, HandProps}; +use yew::prelude::*; + +pub const SUIT_DISPLAY_ORDER: [Suit; 4] = [Suit::Diamond, Suit::Club, Suit::Heart, Suit::Spade]; + +#[function_component(Game)] +pub fn game() -> Html { + let mut rng = rand::thread_rng(); + let mut deal = card::deal(&mut rng); + deal.sort(&SUIT_DISPLAY_ORDER, card::RankOrder::Descending); + + let north = use_state(|| HandProps::from_iter(deal.north.into_iter())); + let west = use_state(|| HandProps::from_iter(deal.west.into_iter())); + let south = use_state(|| HandProps::from_iter(deal.south.into_iter())); + let east = use_state(|| HandProps::from_iter(deal.east.into_iter())); + + let dealer = use_state(|| Player::East); + + let contract: UseStateHandle> = use_state(|| None); + let on_contract = { + let contract = contract.clone(); + Callback::from(move |c| contract.set(Some(c))) + }; + + let shuffle = { + let north = north.clone(); + let west = west.clone(); + let south = south.clone(); + let east = east.clone(); + let dealer = dealer.clone(); + + Callback::from(move |_| { + let mut rng = rand::thread_rng(); + let mut deal = card::deal(&mut rng); + deal.sort(&SUIT_DISPLAY_ORDER, card::RankOrder::Descending); + north.set(deal.north.into_iter().collect()); + west.set(deal.west.into_iter().collect()); + south.set(deal.south.into_iter().collect()); + east.set(deal.east.into_iter().collect()); + + dealer.set(dealer.next()); + }) + }; + + html! { + <> +

{ format!("Dealer: {:?}", *dealer) }

+ if let Some((contract, bidding)) = &*contract { + { format!("Got contract {:?}. Bidding was {:?}", contract, bidding) } + } else { + + } +

{ "North" }

+ +

{ "West" }

+ +

{ "South" }

+ +

{ "East" }

+ +

{ "Controls" }

+ + + } +} diff --git a/webapp/src/main.rs b/webapp/src/main.rs index 3e77598..b6d75ee 100644 --- a/webapp/src/main.rs +++ b/webapp/src/main.rs @@ -5,16 +5,13 @@ use yew::prelude::*; pub mod bridge_engine; pub mod card; pub mod components; -use bridge_engine::Player; -use components::{Bidding, Hand, HandProps}; +use components::Game; extern crate wee_alloc; // Use `wee_alloc` as the global allocator. #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; -pub const SUIT_DISPLAY_ORDER: [Suit; 4] = [Suit::Diamond, Suit::Club, Suit::Heart, Suit::Spade]; - fn main() { std::panic::set_hook(Box::new(console_error_panic_hook::hook)); wasm_logger::init(wasm_logger::Config::default()); @@ -23,45 +20,9 @@ fn main() { #[function_component(App)] pub fn app() -> Html { - let mut rng = rand::thread_rng(); - let mut deal = card::deal(&mut rng); - deal.sort(&SUIT_DISPLAY_ORDER, card::RankOrder::Descending); - - let north = use_state(|| HandProps::from_iter(deal.north.into_iter())); - let west = use_state(|| HandProps::from_iter(deal.west.into_iter())); - let south = use_state(|| HandProps::from_iter(deal.south.into_iter())); - let east = use_state(|| HandProps::from_iter(deal.east.into_iter())); - - let shuffle = { - let north = north.clone(); - let west = west.clone(); - let south = south.clone(); - let east = east.clone(); - - Callback::from(move |_| { - let mut rng = rand::thread_rng(); - let mut deal = card::deal(&mut rng); - deal.sort(&SUIT_DISPLAY_ORDER, card::RankOrder::Descending); - north.set(deal.north.into_iter().collect()); - west.set(deal.west.into_iter().collect()); - south.set(deal.south.into_iter().collect()); - east.set(deal.east.into_iter().collect()); - }) - }; - html! { <> - -

{ "North" }

- -

{ "West" }

- -

{ "South" }

- -

{ "East" }

- -

{ "Controls" }

- + } } -- cgit v1.2.3