diff --git a/lib/dojo/hand.ex b/lib/dojo/hand.ex index 58260f2..77bf2ef 100644 --- a/lib/dojo/hand.ex +++ b/lib/dojo/hand.ex @@ -2,7 +2,55 @@ defmodule Dojo.Hand do alias Dojo.Card def score(cards) do - evaluate(cards) + check_of_a_kind(cards) + end + + defp check_of_a_kind(cards) do + cards + |> Enum.uniq_by(&(&1.rank)) + |> Enum.count + |> case do + 3 -> :three_of_a_kind + 2 -> check_full_house(cards) + _ -> check_flush(cards) + end + end + + defp check_full_house(cards) do + :four_of_a_kind + end + + defp check_flush(cards) do + cards + |> Enum.uniq_by(&(&1.suit)) + |> Enum.count + |> case do + 1 -> get_flush_type(cards) + _ -> evaluate(cards) + end + end + + def get_flush_type(cards) do + sorted_cards = + cards + |> Enum.map(&(&1.rank)) + |> Enum.sort + + sorted_cards + |> is_straight_or_royal + |> case do + true -> + Enum.sum(sorted_cards) + |> case do + 60 -> :royal_flush + _ -> :straight_flush + end + false -> :flush + end + end + + def is_straight_or_royal(cards) do + cards == Enum.to_list(Enum.at(cards, 0)..Enum.at(cards, length(cards) - 1)) end defp evaluate(_), do: :high_card diff --git a/test/dojo/hand_test.exs b/test/dojo/hand_test.exs index 5188ab3..ce3a8aa 100644 --- a/test/dojo/hand_test.exs +++ b/test/dojo/hand_test.exs @@ -5,6 +5,18 @@ defmodule Dojo.HandTest do doctest Dojo.Hand test "evaluates a straight flush" do + cards = [ + %Card{rank: 4, suit: :hearts}, + %Card{rank: 5, suit: :hearts}, + %Card{rank: 6, suit: :hearts}, + %Card{rank: 7, suit: :hearts}, + %Card{rank: 8, suit: :hearts} + ] + + assert Hand.score(cards) == :straight_flush + end + + test "evaluates a royal flush" do cards = [ %Card{rank: 10, suit: :hearts}, %Card{rank: 11, suit: :hearts}, @@ -13,7 +25,7 @@ defmodule Dojo.HandTest do %Card{rank: 14, suit: :hearts} ] - assert Hand.score(cards) == :straight_flush + assert Hand.score(cards) == :royal_flush end test "evaluates flush of hearts" do @@ -63,4 +75,40 @@ defmodule Dojo.HandTest do assert Hand.score(cards) == :high_card end + + test "evaluates four of a kind" do + cards = [ + %Card{rank: 2, suit: :spades}, + %Card{rank: 2, suit: :hearts}, + %Card{rank: 2, suit: :diamonds}, + %Card{rank: 2, suit: :clubs}, + %Card{rank: 11, suit: :spades} + ] + + assert Hand.score(cards) == :four_of_a_kind + end + + test "evaluates three of a kind" do + cards = [ + %Card{rank: 2, suit: :spades}, + %Card{rank: 2, suit: :hearts}, + %Card{rank: 2, suit: :diamonds}, + %Card{rank: 6, suit: :clubs}, + %Card{rank: 11, suit: :spades} + ] + + assert Hand.score(cards) == :three_of_a_kind + end + + test "evaluates full house" do + cards = [ + %Card{rank: 2, suit: :spades}, + %Card{rank: 2, suit: :hearts}, + %Card{rank: 2, suit: :diamonds}, + %Card{rank: 6, suit: :clubs}, + %Card{rank: 6, suit: :spades} + ] + + assert Hand.score(cards) == :full_house + end end