ofcp_scoring 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.autotest +8 -0
  4. data/.gitignore +2 -0
  5. data/.rspec +2 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +27 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +59 -0
  11. data/Rakefile +1 -0
  12. data/lib/.DS_Store +0 -0
  13. data/lib/ofcp_scoring/chinese_poker_hand.rb +22 -0
  14. data/lib/ofcp_scoring/flush.rb +11 -0
  15. data/lib/ofcp_scoring/four_of_a_kind.rb +10 -0
  16. data/lib/ofcp_scoring/full_house.rb +4 -0
  17. data/lib/ofcp_scoring/hand_categorizer.rb +30 -0
  18. data/lib/ofcp_scoring/hand_evaluator.rb +50 -0
  19. data/lib/ofcp_scoring/hand_factory.rb +12 -0
  20. data/lib/ofcp_scoring/hand_organizer.rb +45 -0
  21. data/lib/ofcp_scoring/high_card.rb +6 -0
  22. data/lib/ofcp_scoring/organized_hand.rb +37 -0
  23. data/lib/ofcp_scoring/pair.rb +16 -0
  24. data/lib/ofcp_scoring/ranked_hand.rb +35 -0
  25. data/lib/ofcp_scoring/royal_flush.rb +3 -0
  26. data/lib/ofcp_scoring/royalties_calculator.rb +38 -0
  27. data/lib/ofcp_scoring/scoring_engine.rb +9 -0
  28. data/lib/ofcp_scoring/straight.rb +14 -0
  29. data/lib/ofcp_scoring/straight_flush.rb +2 -0
  30. data/lib/ofcp_scoring/three_of_a_kind.rb +10 -0
  31. data/lib/ofcp_scoring/two_pair.rb +22 -0
  32. data/lib/ofcp_scoring/version.rb +3 -0
  33. data/lib/ofcp_scoring.rb +9 -0
  34. data/ofcp_scoring-0.0.1.gem +0 -0
  35. data/ofcp_scoring.gemspec +24 -0
  36. data/spec/acceptance_spec.rb +32 -0
  37. data/spec/chinese_poker_hand_categorizer_spec.rb +117 -0
  38. data/spec/chinese_poker_hand_evaluator_spec.rb +69 -0
  39. data/spec/chinese_poker_hand_organizer_spec.rb +19 -0
  40. data/spec/chinese_poker_hand_spec.rb +23 -0
  41. data/spec/chinese_poker_scoring_engine_spec.rb +23 -0
  42. data/spec/hand_factory_spec.rb +22 -0
  43. data/spec/organized_hand_spec.rb +4 -0
  44. data/spec/ranked_hand_spec.rb +159 -0
  45. data/spec/royalties_calculator_spec.rb +103 -0
  46. data/spec/spec_helper.rb +28 -0
  47. metadata +143 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: 10da65d396f4b5efaf31275afdf8100f8f2b7a8c
4
+ data.tar.gz: 5ea2afe03038edb5e9b4cd8408d255659c5c1d93
5
+ !binary "U0hBNTEy":
6
+ metadata.gz: 9f1e47a0593cf4276ed52dd9f77e848f9f87f45607e3657c4cdcf7167b33673bdc72d7cfd2960b97c41b79ae1a4914b29fa0b56fe8b9e187c89c5721c6b4aab6
7
+ data.tar.gz: 5ba7cafebbc4e425ac7106b92410ef9d078a87d1be2e9c3f4deda9f1b36dc6efaf898f593aaf13c75951e4492ecae6c3e6b8d54e1fae963b8e3a266837528603
data/.DS_Store ADDED
Binary file
data/.autotest ADDED
@@ -0,0 +1,8 @@
1
+ require "autotest/bundler"
2
+ require "autotest/doom"
3
+
4
+ Autotest.add_hook(:initialize) do |at|
5
+ at.add_exception %r{^\.git} # ignore Version Control System
6
+ at.add_exception %r{^./tmp}
7
+ at.add_exception %r{^./coverage}
8
+ end
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ coverage/
2
+ ofcp.sublime-*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.0.0"
4
+ # uncomment this line if your project needs to run something other than `rake`:
5
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ofcp_scoring.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ofcp_scoring (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.4)
10
+ rake (10.1.0)
11
+ rspec (2.14.1)
12
+ rspec-core (~> 2.14.0)
13
+ rspec-expectations (~> 2.14.0)
14
+ rspec-mocks (~> 2.14.0)
15
+ rspec-core (2.14.5)
16
+ rspec-expectations (2.14.2)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.14.3)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.3)
25
+ ofcp_scoring!
26
+ rake
27
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Clayton Lengel-Zigich
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Open Face Chinese Poker Scoring
2
+
3
+ A library for evaluating two open face chinese poker hands.
4
+
5
+ ## Build Status
6
+ [![Build Status](https://travis-ci.org/clayton/ofcp_scoring.png)](https://travis-ci.org/clayton/ofcp_scoring)
7
+
8
+ ## Getting Started
9
+
10
+ Without Bundler:
11
+ `gem install ofcp_scoring`
12
+
13
+ With Bundler:
14
+ Add `gem 'ofcp_scoring'` to your Gemfile
15
+
16
+ ## Basic Usage
17
+
18
+ The basic scoring engine will evaluate two Chinese Poker hands calculating
19
+ royalties and scoop bonuses.
20
+
21
+ Example:
22
+
23
+ engine = OfcpScoring::ScoringEngine.new
24
+ engine.score(
25
+ %w(2h 3h 5h 10d 10h 4h 7c 8s Jd Js 6c 7d 9c),
26
+ %w(Ah 3h 5h 6d 6h 4h 7c 8s Qd Qs 6c 7d 9c)
27
+ )
28
+ #=> [1,2]
29
+
30
+ ## Royalty Calculation
31
+
32
+ With Royalties you receive the following points for Back hands:
33
+
34
+ * 20 for a Royal
35
+ * 10 for StraightFlush
36
+ * 8 for Quads
37
+ * 6 for a Full House
38
+ * 4 for a OfcpScoring::Flush
39
+ * 2 for a Straight
40
+
41
+ You receive the following points for Middle hands:
42
+
43
+ * 20 for StraightFlush
44
+ * 16 for Quads
45
+ * 2 for a Full House
46
+ * 8 for a OfcpScoring::Flush
47
+ * 4 for a Straight
48
+
49
+ You receive the following points for Front hands (the 3 card hand):
50
+
51
+ * Pair of Aces: 9 points
52
+ * Pair of Kings: 8 points
53
+ * Pair of Queens: 7 points
54
+ * Pair of Jacks: 6 points
55
+ * Pair of Tens: 5 points
56
+ * Pair of Nines: 4 points
57
+ * Pair of Eights: 3 points
58
+ * Pair of Sevens: 2 points
59
+ * Paid of Sixes: 1 point
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/.DS_Store ADDED
Binary file
@@ -0,0 +1,22 @@
1
+ class OfcpScoring::ChinesePokerHand
2
+ def initialize(hand)
3
+ @hand = hand
4
+ end
5
+
6
+ def front
7
+ @hand[:front]
8
+ end
9
+
10
+ def middle
11
+ @hand[:middle]
12
+ end
13
+
14
+ def back
15
+ @hand[:back]
16
+ end
17
+
18
+ def misset?
19
+ true if front > middle || middle > back || front > back
20
+ end
21
+
22
+ end
@@ -0,0 +1,11 @@
1
+ require_relative 'ranked_hand'
2
+ class OfcpScoring::Flush < OfcpScoring::RankedHand
3
+ def <=>(other)
4
+ return super if super
5
+ highest_flush_card <=> other.highest_flush_card
6
+ end
7
+
8
+ def highest_flush_card
9
+ ranks.max
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ class OfcpScoring::FourOfAKind < OfcpScoring::RankedHand
2
+ def <=>(other)
3
+ return super if super
4
+ highest_quad_card <=> other.highest_quad_card
5
+ end
6
+
7
+ def highest_quad_card
8
+ grouped_ranks.map{|card,matches| card if matches.size == 4}.compact.max
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'three_of_a_kind'
2
+ class OfcpScoring::FullHouse < OfcpScoring::ThreeOfAKind
3
+
4
+ end
@@ -0,0 +1,30 @@
1
+ class OfcpScoring::HandCategorizer
2
+
3
+ def initialize(organizer = OfcpScoring::HandOrganizer.new)
4
+ @organizer = organizer
5
+ end
6
+
7
+ def categorize(hand)
8
+ return "" if hand.nil?
9
+
10
+ organized_hand = @organizer.organize(hand)
11
+
12
+ categorization = OfcpScoring::HighCard
13
+ categorization = OfcpScoring::Pair if organized_hand.two_cards_match?
14
+ categorization = OfcpScoring::TwoPair if organized_hand.two_different_cards_match?
15
+ categorization = OfcpScoring::ThreeOfAKind if organized_hand.three_cards_match?
16
+
17
+ unless organized_hand.three_card_hand?
18
+ categorization = OfcpScoring::Straight if organized_hand.ranks_in_order?
19
+ categorization = OfcpScoring::Flush if organized_hand.all_suits_match?
20
+ categorization = OfcpScoring::FullHouse if organized_hand.three_cards_match? && organized_hand.two_cards_match?
21
+ categorization = OfcpScoring::FourOfAKind if organized_hand.four_cards_match?
22
+ categorization = OfcpScoring::StraightFlush if organized_hand.all_suits_match? && organized_hand.ranks_in_order?
23
+ categorization = OfcpScoring::RoyalFlush if organized_hand.all_suits_match? && organized_hand.ranks_in_order? && organized_hand.high_card_ace?
24
+ end
25
+
26
+ return categorization.new(organized_hand)
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,50 @@
1
+ class OfcpScoring::HandEvaluator
2
+ def initialize(hand_factory = OfcpScoring::HandFactory.new, royalties_calculator = OfcpScoring::RoyaltiesCalculator.new)
3
+ @hand_factory = hand_factory
4
+ @royalties_calculator = royalties_calculator
5
+ @hand_one_score = 0
6
+ @hand_two_score = 0
7
+ @hand_one_royalties = 0
8
+ @hand_two_royalties = 0
9
+
10
+ end
11
+ def evaluate(hand_one, hand_two)
12
+ organized_hand_one = @hand_factory.build(hand_one)
13
+ organized_hand_two = @hand_factory.build(hand_two)
14
+
15
+ score_hands(organized_hand_one, organized_hand_two)
16
+ end
17
+
18
+ private
19
+ def score_hands(organized_hand_one, organized_hand_two)
20
+ [:front, :middle, :back].each do |sub_hand|
21
+ if organized_hand_one.send(sub_hand) > organized_hand_two.send(sub_hand)
22
+ @hand_one_score += 1
23
+ @hand_one_royalties += @royalties_calculator.calculate_bonus(organized_hand_one.send(sub_hand), sub_hand)
24
+ end
25
+ if organized_hand_two.send(sub_hand) > organized_hand_one.send(sub_hand)
26
+ @hand_two_score += 1
27
+ @hand_two_royalties += @royalties_calculator.calculate_bonus(organized_hand_two.send(sub_hand), sub_hand)
28
+ end
29
+ end
30
+
31
+ adjust_for_missets(organized_hand_one, organized_hand_two)
32
+
33
+ [(@hand_one_score + @hand_one_royalties), (@hand_two_score + @hand_two_royalties)]
34
+ end
35
+
36
+ def adjust_for_missets(organized_hand_one, organized_hand_two)
37
+ if organized_hand_one.misset?
38
+ @hand_one_score = 0
39
+ @hand_two_score = 3
40
+ end
41
+
42
+ if organized_hand_two.misset?
43
+ @hand_one_score = 3
44
+ @hand_two_score = 0
45
+ end
46
+
47
+ @hand_one_score += 3 if @hand_two_score == 0
48
+ @hand_two_score += 3 if @hand_one_score == 0
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ class OfcpScoring::HandFactory
2
+ def initialize(categorizer = OfcpScoring::HandCategorizer.new)
3
+ @categorizer = categorizer
4
+ end
5
+ def build(hand)
6
+ OfcpScoring::ChinesePokerHand.new({
7
+ :front => @categorizer.categorize(hand[0..2]),
8
+ :middle => @categorizer.categorize(hand[3..7]),
9
+ :back => @categorizer.categorize(hand[8..12])
10
+ })
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ class OfcpScoring::HandOrganizer
2
+ def organize(hand)
3
+ return "" if hand.nil?
4
+ suits_only = Hash.new(0)
5
+ ranks_only = Hash.new(0)
6
+ sorted_ranks = []
7
+ hand.each do |card|
8
+ ranks_only[card[0..-2]] += 1
9
+ suits_only[card[1]] += 1
10
+ case card[0]
11
+ when "A"
12
+ sorted_ranks << 1
13
+ when "K"
14
+ sorted_ranks << 13
15
+ when "Q"
16
+ sorted_ranks << 12
17
+ when "J"
18
+ sorted_ranks << 11
19
+ else
20
+ sorted_ranks << card[0..-2].to_i
21
+ end
22
+ end
23
+
24
+ sorted_ranks.sort!
25
+
26
+ OfcpScoring::OrganizedHand.new(build_organized_hand(ranks_only, suits_only, sorted_ranks))
27
+ end
28
+
29
+ private
30
+ def build_organized_hand(ranks, suits, sorted)
31
+ params = {:ranks => sorted}
32
+
33
+ params.merge!({:two_cards_match => true}) if ranks.values.include?(2)
34
+ params.merge!({:two_different_cards_match => true}) if ranks.find_all{|k,v| v == 2}.size > 1
35
+ params.merge!({:three_cards_match => true}) if ranks.values.include?(3)
36
+ params.merge!({:four_cards_match => true}) if ranks.values.include?(4)
37
+ params.merge!({:all_suits_match => true}) if suits.values.include?(5)
38
+ params.merge!({:ranks_in_order => true}) if (sorted.first..sorted.last).to_a == sorted
39
+ params.merge!({:ranks_in_order => true}) if (sorted & [1,10,11,12,13]) == sorted
40
+ params.merge!({:high_card_ace => true}) if sorted.include?(1)
41
+ params.merge!({:three_card_hand => true}) if sorted.size == 3
42
+
43
+ params
44
+ end
45
+ end
@@ -0,0 +1,6 @@
1
+ class OfcpScoring::HighCard < OfcpScoring::RankedHand
2
+ def <=>(other)
3
+ return super if super
4
+ self.ranks.max <=> other.ranks.max
5
+ end
6
+ end
@@ -0,0 +1,37 @@
1
+ class OfcpScoring::OrganizedHand
2
+ def initialize(organized_hand)
3
+ @hand = organized_hand
4
+ end
5
+
6
+ def ranks
7
+ @hand[:ranks]
8
+ end
9
+
10
+ def two_cards_match?
11
+ @hand[:two_cards_match]
12
+ end
13
+
14
+ def two_different_cards_match?
15
+ @hand[:two_different_cards_match]
16
+ end
17
+
18
+ def three_cards_match?
19
+ @hand[:three_cards_match]
20
+ end
21
+
22
+ def four_cards_match?
23
+ @hand[:four_cards_match]
24
+ end
25
+
26
+ def all_suits_match?
27
+ @hand[:all_suits_match]
28
+ end
29
+
30
+ def ranks_in_order?
31
+ @hand[:ranks_in_order]
32
+ end
33
+
34
+ def three_card_hand?
35
+ @hand[:three_card_hand]
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ class OfcpScoring::Pair < OfcpScoring::RankedHand
2
+
3
+ def <=>(other)
4
+ return super if super
5
+ if highest_paired_card == other.highest_paired_card
6
+ compare_ranks(other)
7
+ else
8
+ highest_paired_card <=> other.highest_paired_card
9
+ end
10
+ end
11
+
12
+ def highest_paired_card
13
+ grouped_ranks.map{|card,matches| card if matches.size == 2}.compact.first
14
+ end
15
+
16
+ end
@@ -0,0 +1,35 @@
1
+ class OfcpScoring::RankedHand
2
+ include Comparable
3
+
4
+ RANKINGS = [
5
+ "HighCard", "Pair", "TwoPair", "ThreeOfAKind", "Straight", "Flush",
6
+ "FullHouse", "FourOfAKind", "StraightFlush", "RoyalFlush"
7
+ ]
8
+
9
+ def rank_name
10
+ self.class.to_s.split("::").last
11
+ end
12
+
13
+ def <=>(other_hand)
14
+ RANKINGS.index(rank_name) <=> RANKINGS.index(other_hand.rank_name) unless rank_name == other_hand.rank_name
15
+ end
16
+
17
+ def initialize(hand=nil)
18
+ @hand = hand
19
+ end
20
+
21
+ def ranks
22
+ ranks = @hand.ranks
23
+ ranks.map{|r| r == 1 ? 14 : r}.sort
24
+ end
25
+
26
+ def grouped_ranks
27
+ ranks.group_by{|card| card }
28
+ end
29
+
30
+ def compare_ranks(other)
31
+ (ranks - (ranks & other.ranks)).max <=> (other.ranks - (ranks & other.ranks)).max
32
+ end
33
+
34
+
35
+ end
@@ -0,0 +1,3 @@
1
+ require_relative 'flush'
2
+ class OfcpScoring::RoyalFlush < OfcpScoring::Flush
3
+ end
@@ -0,0 +1,38 @@
1
+ class OfcpScoring::RoyaltiesCalculator
2
+ MIDDLE = {
3
+ "StraightFlush" => 20, "FourOfAKind" => 16, "FullHouse" => 12,
4
+ "Flush" => 8, "Straight" => 4, "Pair" => 0, "HighCard" => 0
5
+ }
6
+
7
+ BACK = {
8
+ "RoyalFlush" => 20, "StraightFlush" => 10, "FourOfAKind" => 8,
9
+ "FullHouse" => 6, "Flush" => 4, "Straight" => 2, "Pair" => 0,
10
+ "HighCard" => 0
11
+ }
12
+
13
+ def calculate_bonus(hand, position)
14
+ return calculate_front(hand) if position == :front
15
+ return calculate_middle(hand) if position == :middle
16
+ return calculate_back(hand) if position == :back
17
+ end
18
+
19
+ private
20
+ def calculate_back(hand)
21
+ BACK[hand.rank_name]
22
+ end
23
+
24
+ def calculate_middle(hand)
25
+ MIDDLE[hand.rank_name]
26
+ end
27
+
28
+ def calculate_front(hand)
29
+ return 0 unless hand.rank_name == "Pair"
30
+ bonus_accumulator = 0
31
+ bonus_start = 5
32
+ while hand.ranks.max > bonus_start
33
+ bonus_accumulator += 1
34
+ bonus_start += 1
35
+ end
36
+ bonus_accumulator
37
+ end
38
+ end
@@ -0,0 +1,9 @@
1
+ class OfcpScoring::ScoringEngine
2
+ def initialize(evaluator = OfcpScoring::HandEvaluator.new)
3
+ @evaluator = evaluator
4
+ end
5
+ def score(hand_one, hand_two)
6
+ return [0,0] if hand_one.nil? || hand_two.nil?
7
+ @evaluator.evaluate(hand_one, hand_two)
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ class OfcpScoring::Straight < OfcpScoring::RankedHand
2
+
3
+ def <=>(other)
4
+ return super if super
5
+ highest_straight_card <=> other.highest_straight_card
6
+ end
7
+
8
+ def highest_straight_card
9
+ return ranks.max unless ranks.include?(14)
10
+ return 1 if ranks.include?(14) && ranks.include?(5)
11
+ return 14
12
+ end
13
+
14
+ end
@@ -0,0 +1,2 @@
1
+ class OfcpScoring::StraightFlush < OfcpScoring::Straight
2
+ end
@@ -0,0 +1,10 @@
1
+ class OfcpScoring::ThreeOfAKind < OfcpScoring::RankedHand
2
+ def <=>(other)
3
+ return super if super
4
+ highest_trip_card <=> other.highest_trip_card
5
+ end
6
+
7
+ def highest_trip_card
8
+ grouped_ranks.map{|card,matches| card if matches.size == 3}.compact.max
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ class OfcpScoring::TwoPair < OfcpScoring::RankedHand
2
+ def <=>(other)
3
+ return super if super
4
+ if higher_paired_card == other.higher_paired_card
5
+ if lower_paired_card == other.lower_paired_card
6
+ compare_ranks(other)
7
+ else
8
+ lower_paired_card <=> other.lower_paired_card
9
+ end
10
+ else
11
+ higher_paired_card <=> other.higher_paired_card
12
+ end
13
+ end
14
+
15
+ def higher_paired_card
16
+ grouped_ranks.map{|card,matches| card if matches.size == 2}.compact.max
17
+ end
18
+
19
+ def lower_paired_card
20
+ grouped_ranks.map{|card,matches| card if matches.size == 2}.compact.min
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module OfcpScoring
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "ofcp_scoring/version"
2
+ require_relative 'ofcp_scoring/ranked_hand'
3
+ Gem.find_files("ofcp_scoring/*.rb").each { |path| require path }
4
+
5
+
6
+
7
+ module OfcpScoring
8
+ # Your code goes here...
9
+ end
Binary file
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ofcp_scoring/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ofcp_scoring"
8
+ spec.version = OfcpScoring::VERSION
9
+ spec.authors = ["Clayton Lengel-Zigich"]
10
+ spec.email = ["clayton@claytonlz.com"]
11
+ spec.description = %q{Open Face Chinese Poker Scoring}
12
+ spec.summary = %q{A library to categorize, rank and score open face chinese poker hands with royalties.}
13
+ spec.homepage = "http://github.com/clayton/ofcp_scoring"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Open Face Chinese Poker" do
4
+ it "should determine how many points each poker hand owes the other" do
5
+ my_hand = %w(2h 3h 5h 10d 10h 4h 7c 8s Jd Js 6c 7d 9c)
6
+ their_hand = %w(Ah 3h 5h 6d 6h 4h 7c 8s Qd Qs 6c 7d 9c)
7
+ sut = OfcpScoring::ScoringEngine.new
8
+ expect(sut.score(my_hand, their_hand)).to eq([1, 2])
9
+ end
10
+
11
+ it "should give me a scoop bonus when I scoop the other player" do
12
+ my_hand = %w(Ah 4s Qs Js Jd 7d 6c 8h Kc Kd Ad 2c 4d)
13
+ their_hand = %w(9h 4c Qs 10s 10d 7d 6c 8h Qc Qd Ad 2c 4d)
14
+ sut = OfcpScoring::ScoringEngine.new
15
+ expect(sut.score(my_hand, their_hand)).to eq([6, 0])
16
+ end
17
+
18
+ it "should give the other player a scoop bonus when they scoop me" do
19
+ my_hand = %w(9h 4c Qs 10s 10d 7d 6c 8h Qc Qd Ad 2c 4d)
20
+ their_hand = %w(Ah 4s Qs Js Jd 7d 6c 8h Kc Kd Ad 2c 4d)
21
+ sut = OfcpScoring::ScoringEngine.new
22
+ expect(sut.score(my_hand, their_hand)).to eq([0, 6])
23
+ end
24
+
25
+
26
+ it "should give royalties for extra special hands" do
27
+ my_hand = %w(Ah 4s Qs 2h 3h 4h 5h 7h Kh Kd Ks 9c 9s)
28
+ their_hand = %w(9h 4c Qs 10s 10d 7d 6c 8h Qc Qd Ad 2c 4d)
29
+ sut = OfcpScoring::ScoringEngine.new
30
+ expect(sut.score(my_hand, their_hand)).to eq([20, 0])
31
+ end
32
+ end