1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
use crate::card::{Rank, Suit};
#[allow(unused_imports)]
use log::{debug, error, info, warn};
use yew::prelude::*;
pub mod card;
fn main() {
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
wasm_logger::init(wasm_logger::Config::default());
yew::start_app::<App>();
}
#[function_component(App)]
pub fn app() -> Html {
let mut rng = rand::thread_rng();
let (n, w, s, e) = card::shuffle_deck(&mut rng);
let north = use_state(|| HandProps::from_iter(n.into_iter()));
let west = use_state(|| HandProps::from_iter(w.into_iter()));
let south = use_state(|| HandProps::from_iter(s.into_iter()));
let east = use_state(|| HandProps::from_iter(e.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 (n, w, s, e) = card::shuffle_deck(&mut rng);
north.set(n.into_iter().collect());
west.set(w.into_iter().collect());
south.set(s.into_iter().collect());
east.set(e.into_iter().collect());
})
};
html! {
<>
<p>{ "North" }</p>
<Hand ..(*north).clone() />
<p>{ "West" }</p>
<Hand ..(*west).clone() />
<p>{ "South" }</p>
<Hand ..(*south).clone() />
<p>{ "East" }</p>
<Hand ..(*east).clone() />
<button onclick={shuffle}>{ "Shuffle" }</button>
</>
}
}
#[function_component(Hand)]
pub fn hand(props: &HandProps) -> Html {
let cards: Html = props
.cards
.iter()
.map(|c| {
html! {
<Card ..c.clone() />
}
})
.collect();
html! {
<div class="hand">
{ cards }
</div>
}
}
pub fn suit_css_class(suit: Suit) -> &'static str {
match suit {
Suit::Club => "suit-club",
Suit::Diamond => "suit-diamond",
Suit::Heart => "suit-heart",
Suit::Spade => "suit-spade",
}
}
#[derive(Clone, Default, PartialEq, Properties)]
pub struct HandProps {
#[prop_or_default]
cards: Vec<CardProps>,
}
impl<C: Into<CardProps>> FromIterator<C> for HandProps {
fn from_iter<Cards>(cards: Cards) -> Self
where
Cards: std::iter::IntoIterator<Item = C>,
{
HandProps {
cards: cards.into_iter().map(Into::into).collect(),
}
}
}
#[function_component(Card)]
pub fn wcard(props: &CardProps) -> Html {
html! {
<div class="card">
<div class={ suit_css_class(props.suit) }>
{ props.rank }
</div>
</div>
}
}
#[derive(PartialEq, Properties, Clone)]
pub struct CardProps {
suit: Suit,
rank: Rank,
}
impl From<card::Card> for CardProps {
fn from(card::Card(suit, rank): card::Card) -> Self {
CardProps { suit, rank }
}
}
|