poker-ranking 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/card.rb ADDED
@@ -0,0 +1,40 @@
1
+
2
+ module PokerRanking
3
+ class PokerRanking::Card
4
+
5
+ RANKS = %w(2 3 4 5 6 7 8 9 10 Jack Queen King Ace)
6
+ SUITS = %w(Hearts Diamonds Spades Clubs)
7
+
8
+ def initialize(card_data)
9
+ @suit = card_data[:suit]
10
+ @rank = card_data[:rank].to_s
11
+ set_value_by_rank_name(@rank)
12
+ end
13
+
14
+ def set_value_by_rank_name(rank)
15
+ @value = RANKS.index(rank) + 2
16
+ end
17
+
18
+ def worth_less_than(other_hand)
19
+ @value < other_hand.value
20
+ end
21
+
22
+ def to_s
23
+ "#{@rank} of #{@suit}"
24
+ end
25
+
26
+ def ==(other_card)
27
+ @value == other_card.value && @rank == other_card.rank
28
+ end
29
+
30
+ attr_reader :value
31
+ attr_reader :rank
32
+ attr_reader :suit
33
+
34
+ def self.from_name(name)
35
+ rank, suit = name.split /\s+of\s+/
36
+ PokerRanking::Card.new({rank: rank, suit: suit})
37
+ end
38
+
39
+ end
40
+ end
data/lib/hand.rb ADDED
@@ -0,0 +1,84 @@
1
+ require 'card'
2
+
3
+ require_relative 'hand_type'
4
+
5
+ module PokerRanking
6
+
7
+
8
+ class Hand
9
+
10
+ HAND_TYPES = [HandType::StraightFlush, HandType::FourOfAKind, HandType::FullHouse, HandType::Flush, HandType::Straight, HandType::ThreeOfAKind, HandType::TwoPair, HandType::Pair, HandType::HighCard]
11
+
12
+ attr_reader :cards
13
+ attr_reader :rank
14
+ attr_reader :value
15
+ attr_reader :second_value
16
+ attr_reader :kickers
17
+
18
+ def initialize(cards)
19
+ @cards = []
20
+ cards.each do |card|
21
+ if card.is_a? PokerRanking::Card
22
+ @cards << card
23
+ elsif card.is_a? String
24
+ @cards << PokerRanking::Card::from_name(card)
25
+ else
26
+ @cards << PokerRanking::Card.new(card)
27
+ end
28
+ end
29
+
30
+ if @cards.length > 0
31
+ @cards.sort_by! { |card| card.value }
32
+
33
+ calculate_rank
34
+ end
35
+ end
36
+
37
+
38
+ def defeats?(other_hand)
39
+ if @cards.length == 0
40
+ return false
41
+ end
42
+
43
+ if other_hand.cards.length == 0
44
+ return true
45
+ end
46
+
47
+ return self.rank > other_hand.rank unless self.rank == other_hand.rank
48
+ return self.value > other_hand.value unless self.value == other_hand.value
49
+ return self.second_value > other_hand.second_value unless self.second_value == other_hand.second_value
50
+ self.kickers.each_with_index do |kicker,index|
51
+ return kicker > other_hand.kickers[index] unless kicker == other_hand.kickers[index]
52
+ end
53
+ return false
54
+ end
55
+
56
+ def name
57
+ hand_type.name
58
+ end
59
+
60
+ def ==(other)
61
+ cards == other.cards
62
+ end
63
+
64
+
65
+ private
66
+
67
+ def calculate_rank
68
+ @rank = hand_type.rank
69
+ @value = hand_type.value
70
+ @second_value = hand_type.second_value
71
+ @kickers = hand_type.kickers
72
+ end
73
+
74
+ def hand_type
75
+ HAND_TYPES.each do |hand_type_class|
76
+ hand_type = hand_type_class.new @cards
77
+ if hand_type.handles?
78
+ return hand_type
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ end
data/lib/hand_type.rb ADDED
@@ -0,0 +1,12 @@
1
+
2
+ require_relative 'hand_type/base'
3
+ require_relative 'hand_type/high_card'
4
+ require_relative 'hand_type/pair'
5
+ require_relative 'hand_type/two_pair'
6
+ require_relative 'hand_type/three_of_a_kind'
7
+ require_relative 'hand_type/straight'
8
+ require_relative 'hand_type/flush'
9
+ require_relative 'hand_type/full_house'
10
+ require_relative 'hand_type/four_of_a_kind'
11
+ require_relative 'hand_type/straight_flush'
12
+
@@ -0,0 +1,58 @@
1
+ module PokerRanking
2
+ module HandType
3
+ class Base
4
+ attr_reader :cards
5
+
6
+ def initialize(cards)
7
+ @cards = cards
8
+ end
9
+
10
+ def value
11
+ cards[-1].value
12
+ end
13
+
14
+ def n_of_a_kind?(n)
15
+ highest_same_value(n) > 0
16
+ end
17
+
18
+ def highest_same_value(n)
19
+ highest_same_value_except n, 0
20
+ end
21
+
22
+ def number_of_kickers
23
+ 5
24
+ end
25
+
26
+ def second_value
27
+ value
28
+ end
29
+
30
+ def highest_same_value_except(n, skipped_values)
31
+ skipped_values = [skipped_values] unless skipped_values.respond_to? :include?
32
+ value = 0
33
+ count = 1
34
+ last_value = 0
35
+ @cards.each do |card|
36
+ if card.value == last_value && !(skipped_values.include? card.value)
37
+ count += 1
38
+ value = last_value if count == n
39
+ else
40
+ count = 1
41
+ last_value = card.value
42
+ end
43
+ end
44
+ value
45
+ end
46
+
47
+ def kickers
48
+ kickers = []
49
+ @cards.map(&:value).reverse.each do |value|
50
+ kickers << value if @cards.map(&:value).count(value) == 1
51
+ end
52
+ kickers[0..number_of_kickers-1]
53
+ end
54
+
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,47 @@
1
+ module PokerRanking
2
+ module HandType
3
+ class Flush < Base
4
+
5
+ attr_reader :flush_suit
6
+
7
+ def handles?
8
+ count = { 'Hearts' => 0, 'Clubs' => 0, 'Diamonds' => 0, 'Spades' => 0 }
9
+ @cards.each do |card|
10
+ count[card.suit] += 1
11
+ end
12
+
13
+ count.each do |suit, suit_count|
14
+ if suit_count >= 5
15
+ @flush_suit = suit
16
+ return true
17
+ end
18
+ end
19
+
20
+ return false
21
+ end
22
+
23
+ def value
24
+ kickers.first
25
+ end
26
+
27
+ #only use kickers that are of the suit
28
+ def kickers
29
+ kick = []
30
+ @cards.reverse.each do |card|
31
+ if card.suit == @flush_suit
32
+ kick << card.value
33
+ end
34
+ end
35
+ kick[0..number_of_kickers-1]
36
+ end
37
+
38
+ def rank
39
+ 5
40
+ end
41
+
42
+ def name
43
+ 'flush'
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+
2
+ module PokerRanking
3
+ module HandType
4
+ class FourOfAKind < Base
5
+
6
+ def handles?
7
+ n_of_a_kind? 4
8
+ end
9
+
10
+ def number_of_kickers
11
+ 1
12
+ end
13
+
14
+ def rank
15
+ 7
16
+ end
17
+
18
+ def value
19
+ highest_same_value 4
20
+ end
21
+
22
+ #because the kicker could be part of a pair
23
+ def kickers
24
+ [[super,highest_same_value_except(2,value)].flatten.max]
25
+ end
26
+
27
+ def name
28
+ 'four of a kind'
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ module PokerRanking
2
+ module HandType
3
+ class FullHouse < Base
4
+
5
+ def handles?
6
+ return false unless n_of_a_kind? 3
7
+ second_value > 0
8
+ end
9
+
10
+ def rank
11
+ 6
12
+ end
13
+
14
+ def second_value
15
+ highest_same_value_except(2, value)
16
+ end
17
+
18
+ def value
19
+ highest_same_value 3
20
+ end
21
+
22
+ def name
23
+ 'full house'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ module PokerRanking
2
+ module HandType
3
+ class HighCard < Base
4
+
5
+ def handles?
6
+ true
7
+ end
8
+
9
+ def rank
10
+ 0
11
+ end
12
+
13
+ def name
14
+ 'high card'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+
2
+ module PokerRanking
3
+ module HandType
4
+ class Pair < Base
5
+
6
+ def handles?
7
+ n_of_a_kind? 2
8
+ end
9
+
10
+ def rank
11
+ 1
12
+ end
13
+
14
+ def value
15
+ highest_same_value 2
16
+ end
17
+
18
+ def number_of_kickers
19
+ 3
20
+ end
21
+
22
+ def name
23
+ 'pair'
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,55 @@
1
+ module PokerRanking
2
+ module HandType
3
+ class Straight < Base
4
+
5
+ def handles?
6
+ straight_value > 0
7
+ end
8
+
9
+ def rank
10
+ 4
11
+ end
12
+
13
+ def value
14
+ straight_value
15
+ end
16
+
17
+ def name
18
+ 'straight'
19
+ end
20
+
21
+ private
22
+
23
+ def straight_value
24
+ count = 1
25
+ last_value = 0
26
+ value = 0
27
+
28
+ if has_ace()
29
+ count += 1
30
+ last_value = 1
31
+ end
32
+
33
+ @cards.each do |card|
34
+ if card.value == last_value + 1
35
+ count += 1
36
+ else
37
+ count = 1
38
+ end
39
+ last_value = card.value
40
+
41
+ if count >= 5
42
+ value = card.value
43
+ end
44
+ end
45
+ value
46
+ end
47
+
48
+ def has_ace
49
+ @cards[-1].rank == 'Ace'
50
+ end
51
+
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,65 @@
1
+ module PokerRanking
2
+ module HandType
3
+ class StraightFlush < Base
4
+
5
+ SUITS = %w(Hearts Diamonds Spades Clubs)
6
+
7
+ def handles?
8
+ (value > 0)
9
+ end
10
+
11
+ def rank
12
+ 8
13
+ end
14
+
15
+ def value
16
+ SUITS.each do |suit|
17
+ value_for_suit = straight_value_for_suit(suit)
18
+ return value_for_suit if value_for_suit > 0
19
+ end
20
+ 0
21
+ end
22
+
23
+ def name
24
+ 'straight flush'
25
+ end
26
+
27
+ private
28
+
29
+ def straight_value_for_suit(suit)
30
+ count = 1
31
+ last_value = 0
32
+ value = 0
33
+
34
+ if has_ace_of_suit(suit)
35
+ count += 1
36
+ last_value = 1
37
+ end
38
+
39
+ cards.each do |card|
40
+ if card.suit == suit
41
+ if card.value == last_value + 1
42
+ count += 1
43
+ else
44
+ count = 1
45
+ end
46
+ last_value = card.value
47
+
48
+ if count >= 5
49
+ value = card.value
50
+ end
51
+ end
52
+ end
53
+ value
54
+ end
55
+
56
+ def has_ace_of_suit(suit)
57
+ cards.each do |card|
58
+ return true if card.value == 14 && card.suit == suit
59
+ end
60
+
61
+ false
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+
2
+ module PokerRanking
3
+ module HandType
4
+ class ThreeOfAKind < Base
5
+
6
+ def handles?
7
+ n_of_a_kind? 3
8
+ end
9
+
10
+ def number_of_kickers
11
+ 2
12
+ end
13
+
14
+ def rank
15
+ 3
16
+ end
17
+
18
+ def value
19
+ highest_same_value 3
20
+ end
21
+
22
+ def name
23
+ 'three of a kind'
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,50 @@
1
+ module PokerRanking
2
+
3
+ module HandType
4
+ class TwoPair < Base
5
+
6
+ def handles?
7
+ has_two_pair?
8
+ end
9
+
10
+ def rank
11
+ 2
12
+ end
13
+
14
+ def value
15
+ highest_same_value 2
16
+ end
17
+
18
+ def number_of_kickers
19
+ 1
20
+ end
21
+
22
+ def second_value
23
+ highest_same_value_except(2, value)
24
+ end
25
+
26
+ def kickers
27
+ [[super,highest_same_value_except(2,[value,second_value])].flatten.max]
28
+ end
29
+
30
+ def name
31
+ 'two pairs'
32
+ end
33
+
34
+ private
35
+
36
+ def has_two_pair?
37
+ pair_count = 0
38
+ last_value = 0
39
+ @cards.each do |card|
40
+ if card.value == last_value
41
+ pair_count += 1
42
+ end
43
+ last_value = card.value
44
+ end
45
+ return pair_count >= 2
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'hand'
2
+ require_relative 'card'
3
+
4
+ module PokerRanking
5
+ VERSION = '1.0.0'
6
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: poker-ranking
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rafael Ordog aka DeVill
9
+ - Paul Yule
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-01-31 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rake
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: Created for the lean poker project
48
+ email: rafael@ordog.tk
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/hand_type/high_card.rb
54
+ - lib/hand_type/straight.rb
55
+ - lib/hand_type/flush.rb
56
+ - lib/hand_type/full_house.rb
57
+ - lib/hand_type/straight_flush.rb
58
+ - lib/hand_type/base.rb
59
+ - lib/hand_type/pair.rb
60
+ - lib/hand_type/four_of_a_kind.rb
61
+ - lib/hand_type/two_pair.rb
62
+ - lib/hand_type/three_of_a_kind.rb
63
+ - lib/card.rb
64
+ - lib/hand_type.rb
65
+ - lib/poker_ranking.rb
66
+ - lib/hand.rb
67
+ homepage: http://leanpoker.org
68
+ licenses:
69
+ - MIT
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 1.8.23
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Poker cards, and ranking utilities for poker apps.
92
+ test_files: []