summaryrefslogtreecommitdiff
path: root/webapp/src/bridge_engine.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-09-04 19:42:57 -0400
committerKjetil Orbekk <kj@orbekk.com>2022-09-04 19:44:53 -0400
commitab68d26c6b16f973642d378900f5e6ac2be221b7 (patch)
tree357206052643d3ee0b065fd4ee6cb8af928e11f9 /webapp/src/bridge_engine.rs
parentb7180143745c5ebe571936b0116cca403d082e8d (diff)
Add turn/trick representation
Includes convenience test and parsing utilities
Diffstat (limited to 'webapp/src/bridge_engine.rs')
-rw-r--r--webapp/src/bridge_engine.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/webapp/src/bridge_engine.rs b/webapp/src/bridge_engine.rs
new file mode 100644
index 0000000..48c0fd2
--- /dev/null
+++ b/webapp/src/bridge_engine.rs
@@ -0,0 +1,108 @@
+use crate::card;
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub enum Player {
+ North,
+ West,
+ South,
+ East,
+}
+
+impl Player {
+ pub fn next(&self) -> Self {
+ match self {
+ Self::North => Self::West,
+ Self::West => Self::South,
+ Self::South => Self::East,
+ Self::East => Self::North,
+ }
+ }
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub struct Trick {
+ pub leader: Player,
+ pub cards_played: Vec<card::Card>,
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub struct Turn {
+ in_progress: Trick,
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub enum PlayResult {
+ InProgress(Turn),
+ Trick(Trick),
+}
+
+impl Turn {
+ pub fn new(p: Player) -> Turn {
+ Turn {
+ in_progress: Trick {
+ leader: p,
+ cards_played: Vec::with_capacity(4),
+ },
+ }
+ }
+
+ pub fn play(mut self: Turn, card: card::Card) -> PlayResult {
+ self.in_progress.cards_played.push(card);
+ if self.in_progress.cards_played.len() >= 4 {
+ return PlayResult::Trick(self.in_progress);
+ }
+ PlayResult::InProgress(self)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn next_player() {
+ let next_players = vec![Player::North, Player::West, Player::South, Player::East]
+ .iter()
+ .map(Player::next)
+ .collect::<Vec<_>>();
+ assert_eq!(
+ next_players,
+ vec![Player::West, Player::South, Player::East, Player::North]
+ );
+ }
+
+ fn as_turn(p: PlayResult) -> Turn {
+ if let PlayResult::InProgress(t) = p {
+ t
+ } else {
+ panic!("expected PlayResult::InProgress(): {:?}", p);
+ }
+ }
+
+ fn as_trick(p: PlayResult) -> Trick {
+ if let PlayResult::Trick(t) = p {
+ t
+ } else {
+ panic!("expected PlayResult::Trick(): {:?}", p);
+ }
+ }
+
+ #[test]
+ fn play_turn() {
+ let turn = Turn::new(Player::South);
+ let turn = as_turn(turn.play("♣4".parse().unwrap()));
+ let turn = as_turn(turn.play("♥A".parse().unwrap()));
+ let turn = as_turn(turn.play("♣4".parse().unwrap()));
+ let trick = as_trick(turn.play("♣A".parse().unwrap()));
+ assert_eq!(
+ trick,
+ Trick {
+ leader: Player::South,
+ cards_played: ["♣4", "♥A", "♣4", "♣A"]
+ .into_iter()
+ .map(|c| c.parse().unwrap())
+ .collect()
+ }
+ );
+ }
+}