bridge 0.0.26 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/README.rdoc +10 -0
- data/bridge.gemspec +3 -3
- data/lib/bridge.rb +3 -52
- data/lib/bridge/constants.rb +109 -0
- data/lib/bridge/imp.rb +40 -0
- data/lib/bridge/score.rb +1 -4
- data/lib/bridge/version.rb +1 -1
- data/test/test_imp.rb +39 -0
- metadata +8 -7
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -35,6 +35,16 @@ You can use regexp to check if contract with result is valid:
|
|
35
35
|
will match i.e.
|
36
36
|
"1NT=", "2SX+1", "6NTXX-2"
|
37
37
|
|
38
|
+
== Imp
|
39
|
+
|
40
|
+
You can calculate how many IMP points you won by:
|
41
|
+
Bridge::Imp.new(:hcp => 25, :points => 420, :vulnerable => false).imps
|
42
|
+
|
43
|
+
Arguments:
|
44
|
+
* :hcp -- Integer (range between 20 and 40), which means how many honour card points has side
|
45
|
+
* :vulnerable -- Boolean, side with given hcp is vulnerable?
|
46
|
+
* :points -- Integer, the result at the end of board (can be calculated by Bridge::Score)
|
47
|
+
|
38
48
|
== Note on Patches/Pull Requests
|
39
49
|
|
40
50
|
* Fork the project.
|
data/bridge.gemspec
CHANGED
@@ -15,9 +15,9 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.required_rubygems_version = ">= 1.3.6"
|
16
16
|
s.rubyforge_project = "bridge"
|
17
17
|
|
18
|
-
s.add_development_dependency "bundler", ">= 1.0.0
|
18
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
19
19
|
|
20
20
|
s.files = `git ls-files`.split("\n")
|
21
|
-
s.executables = `git ls-files`.split("\n").
|
22
|
-
s.require_path =
|
21
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
22
|
+
s.require_path = 'lib'
|
23
23
|
end
|
data/lib/bridge.rb
CHANGED
@@ -1,68 +1,19 @@
|
|
1
1
|
require "bridge/bid"
|
2
2
|
require "bridge/card"
|
3
|
+
require "bridge/constants"
|
3
4
|
require "bridge/deal"
|
5
|
+
require "bridge/imp"
|
4
6
|
require "bridge/score"
|
5
7
|
require "bridge/trick"
|
6
8
|
require "bridge/version"
|
7
9
|
|
8
10
|
module Bridge
|
9
|
-
# Number of possible deals in bridge
|
10
|
-
DEALS = 53_644_737_765_488_792_839_237_440_000
|
11
|
-
|
12
|
-
# Card values - from A to 2
|
13
|
-
CARD_VALUES = %w(A K Q J T 9 8 7 6 5 4 3 2)
|
14
|
-
|
15
|
-
MAJORS = %w(S H)
|
16
|
-
|
17
|
-
MINORS = %w(D C)
|
18
|
-
|
19
|
-
# Trumps
|
20
|
-
TRUMPS = MAJORS + MINORS
|
21
|
-
|
22
|
-
# No trump string
|
23
|
-
NO_TRUMP = "NT"
|
24
|
-
|
25
|
-
# Array with card strings in the bridge deck (AKQJT98765432, four
|
26
|
-
# suits). Contains "SA", "HT", etc.
|
27
|
-
DECK = TRUMPS.inject([]) do |d, s|
|
28
|
-
d += CARD_VALUES.map { |c| s + c }
|
29
|
-
end
|
30
|
-
|
31
|
-
# Direction strings "N", "E", "S" and "W"
|
32
|
-
DIRECTIONS = %w(N E S W)
|
33
|
-
|
34
|
-
# Possible contracts in ascending order. Contains "1C", "6NT", etc.
|
35
|
-
CONTRACTS = %w(1 2 3 4 5 6 7).inject([]) do |b, l|
|
36
|
-
b += (TRUMPS.reverse + [NO_TRUMP]).map { |s| l + s }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Pass string
|
40
|
-
PASS = "PASS"
|
41
|
-
|
42
|
-
# Double string
|
43
|
-
DOUBLE = "X"
|
44
|
-
|
45
|
-
# Redouble string
|
46
|
-
REDOUBLE = "XX"
|
47
|
-
|
48
|
-
# Modifier bids (double and redouble)
|
49
|
-
MODIFIERS = [DOUBLE, REDOUBLE]
|
50
|
-
|
51
|
-
# All possible bids (including contracts, modifiers and pass)
|
52
|
-
BIDS = CONTRACTS + MODIFIERS + [PASS]
|
53
|
-
|
54
|
-
# 2 sides
|
55
|
-
SIDES = %w{NS EW}
|
56
|
-
|
57
|
-
# All possible vullnerabilites
|
58
|
-
VULNERABILITIES = ["NONE", SIDES, "BOTH"].flatten
|
59
|
-
|
60
11
|
def self.direction?(string)
|
61
12
|
DIRECTIONS.include?(string)
|
62
13
|
end
|
63
14
|
|
64
15
|
def self.deal_id?(integer)
|
65
|
-
(0
|
16
|
+
(0...DEALS).include?(integer)
|
66
17
|
end
|
67
18
|
|
68
19
|
def self.card?(string)
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Bridge
|
2
|
+
# Number of possible deals in bridge
|
3
|
+
DEALS = 53_644_737_765_488_792_839_237_440_000
|
4
|
+
|
5
|
+
# Card values - from A to 2
|
6
|
+
CARD_VALUES = %w(A K Q J T 9 8 7 6 5 4 3 2)
|
7
|
+
|
8
|
+
MAJORS = %w(S H)
|
9
|
+
|
10
|
+
MINORS = %w(D C)
|
11
|
+
|
12
|
+
# Trumps
|
13
|
+
TRUMPS = MAJORS + MINORS
|
14
|
+
|
15
|
+
# No trump string
|
16
|
+
NO_TRUMP = "NT"
|
17
|
+
|
18
|
+
# Array with card strings in the bridge deck (AKQJT98765432, four
|
19
|
+
# suits). Contains "SA", "HT", etc.
|
20
|
+
DECK = TRUMPS.map do |suit|
|
21
|
+
CARD_VALUES.map { |card| suit + card }
|
22
|
+
end.flatten
|
23
|
+
|
24
|
+
# Direction strings "N", "E", "S" and "W"
|
25
|
+
DIRECTIONS = %w(N E S W)
|
26
|
+
|
27
|
+
# Possible contracts in ascending order. Contains "1C", "6NT", etc.
|
28
|
+
CONTRACTS = %w(1 2 3 4 5 6 7).map do |level|
|
29
|
+
(TRUMPS.reverse + [NO_TRUMP]).map { |suit| level + suit }
|
30
|
+
end.flatten
|
31
|
+
|
32
|
+
# Pass string
|
33
|
+
PASS = "PASS"
|
34
|
+
|
35
|
+
# Double string
|
36
|
+
DOUBLE = "X"
|
37
|
+
|
38
|
+
# Redouble string
|
39
|
+
REDOUBLE = "XX"
|
40
|
+
|
41
|
+
# Modifier bids (double and redouble)
|
42
|
+
MODIFIERS = [DOUBLE, REDOUBLE]
|
43
|
+
|
44
|
+
# All possible bids (including contracts, modifiers and pass)
|
45
|
+
BIDS = CONTRACTS + MODIFIERS + [PASS]
|
46
|
+
|
47
|
+
# 2 sides
|
48
|
+
SIDES = %w{NS EW}
|
49
|
+
|
50
|
+
# All possible vullnerabilites
|
51
|
+
VULNERABILITIES = ["NONE", SIDES, "BOTH"].flatten
|
52
|
+
|
53
|
+
class Imp
|
54
|
+
# values in array: [not-vulnerable, vulnerable]
|
55
|
+
POINTS =
|
56
|
+
{
|
57
|
+
"20" => [0, 0],
|
58
|
+
"21" => [50, 50],
|
59
|
+
"22" => [70, 70],
|
60
|
+
"23" => [110, 110],
|
61
|
+
"24" => [200, 290],
|
62
|
+
"25" => [300, 440],
|
63
|
+
"26" => [350, 520],
|
64
|
+
"27" => [400, 600],
|
65
|
+
"28" => [430, 630],
|
66
|
+
"29" => [460, 660],
|
67
|
+
"30" => [490, 690],
|
68
|
+
"31" => [600, 900],
|
69
|
+
"32" => [700, 1050],
|
70
|
+
"33" => [900, 1350],
|
71
|
+
"34" => [1000, 1500],
|
72
|
+
"35" => [1100, 1650],
|
73
|
+
"36" => [1200, 1800],
|
74
|
+
"37" => [1300, 1950],
|
75
|
+
"38" => [1300, 1950],
|
76
|
+
"39" => [1300, 1950],
|
77
|
+
"40" => [1300, 1950]
|
78
|
+
}
|
79
|
+
|
80
|
+
IMPS =
|
81
|
+
{
|
82
|
+
"0...10" => 0,
|
83
|
+
"20...40" => 1,
|
84
|
+
"50...80" => 2,
|
85
|
+
"90...120" => 3,
|
86
|
+
"130...160" => 4,
|
87
|
+
"170...210" => 5,
|
88
|
+
"220...260" => 6,
|
89
|
+
"270...310" => 7,
|
90
|
+
"320...360" => 8,
|
91
|
+
"370...420" => 9,
|
92
|
+
"430...490" => 10,
|
93
|
+
"500...590" => 11,
|
94
|
+
"600...740" => 12,
|
95
|
+
"750...890" => 13,
|
96
|
+
"900...1090" => 14,
|
97
|
+
"1100...1290" => 15,
|
98
|
+
"1300...1490" => 16,
|
99
|
+
"1500...1740" => 17,
|
100
|
+
"1750...1990" => 18,
|
101
|
+
"2000...2240" => 19,
|
102
|
+
"2250...2490" => 20,
|
103
|
+
"2500...2990" => 21,
|
104
|
+
"3000...3490" => 22,
|
105
|
+
"3500...3990" => 23,
|
106
|
+
"4000...7600" => 24
|
107
|
+
}
|
108
|
+
end
|
109
|
+
end
|
data/lib/bridge/imp.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Bridge
|
2
|
+
class Imp
|
3
|
+
attr_reader :hcp, :points, :vulnerable
|
4
|
+
alias :vulnerable? :vulnerable
|
5
|
+
|
6
|
+
# Creates new Imp object
|
7
|
+
#
|
8
|
+
# ==== Example
|
9
|
+
# Bridge::Imp.new(:hcp => 25, :points => 420, :vulnerable => true)
|
10
|
+
def initialize(options = {})
|
11
|
+
@hcp = options[:hcp]
|
12
|
+
raise ArgumentError, "Invalid hcp: #{hcp} - value should be between 20 and 40" unless (20..40).include?(hcp)
|
13
|
+
@points = options[:points]
|
14
|
+
@vulnerable = options[:vulnerable] || false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns points that side should make with given hcp
|
18
|
+
def points_to_make
|
19
|
+
POINTS[hcp.to_s][vulnerable? ? 1 : 0]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns points score relative to hcp
|
23
|
+
def points_difference
|
24
|
+
points - points_to_make
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns imps (negative or positive) based on given points
|
28
|
+
def imps
|
29
|
+
IMPS.each do |range, imps|
|
30
|
+
return (imps * sign) if eval(range).include?(points_difference.abs)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def sign
|
37
|
+
points >= 0 ? 1 : -1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/bridge/score.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Bridge
|
2
2
|
class Score
|
3
3
|
attr_reader :tricks, :contract, :vulnerable
|
4
|
+
alias :vulnerable? :vulnerable
|
4
5
|
|
5
6
|
# Checks contract with result, i.e. "1NTX-1", "2S=", "6SXX+1"
|
6
7
|
# on Ruby >= 1.9 there are named groups :contract and :result
|
@@ -56,10 +57,6 @@ module Bridge
|
|
56
57
|
|
57
58
|
# private
|
58
59
|
|
59
|
-
def vulnerable?
|
60
|
-
@vulnerable == true
|
61
|
-
end
|
62
|
-
|
63
60
|
def tricks_to_make_contract
|
64
61
|
contract.level.to_i + 6
|
65
62
|
end
|
data/lib/bridge/version.rb
CHANGED
data/test/test_imp.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class TestImp < Test::Unit::TestCase
|
4
|
+
test "raises ArgumentError when invalid honour card points provided" do
|
5
|
+
assert_raises(ArgumentError) do
|
6
|
+
Bridge::Imp.new(:hcp => 15, :points => 100)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
test "set default vulnerable to false" do
|
11
|
+
imp = Bridge::Imp.new(:hcp => 40, :points => -100)
|
12
|
+
assert_false imp.vulnerable
|
13
|
+
end
|
14
|
+
|
15
|
+
test "return vulnerable boolean" do
|
16
|
+
imp = Bridge::Imp.new(:hcp => 20, :points => 100, :vulnerable => true)
|
17
|
+
assert imp.vulnerable?
|
18
|
+
end
|
19
|
+
|
20
|
+
test "return points to make when vulnerable" do
|
21
|
+
imp = Bridge::Imp.new(:hcp => 23, :points => 100, :vulnerable => true)
|
22
|
+
assert_equal 110, imp.points_to_make
|
23
|
+
end
|
24
|
+
|
25
|
+
test "return points to make when not vulnerable" do
|
26
|
+
imp = Bridge::Imp.new(:hcp => 23, :points => 100, :vulnerable => false)
|
27
|
+
assert_equal 110, imp.points_to_make
|
28
|
+
end
|
29
|
+
|
30
|
+
test "return positive imps" do
|
31
|
+
imp = Bridge::Imp.new(:hcp => 21, :points => 100)
|
32
|
+
assert_equal 2, imp.imps
|
33
|
+
end
|
34
|
+
|
35
|
+
test "return negative imps" do
|
36
|
+
imp = Bridge::Imp.new(:hcp => 21, :points => -100)
|
37
|
+
assert_equal -4, imp.imps
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.26
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Jakub Ku\xC5\xBAma"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-09-13 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -29,9 +29,7 @@ dependencies:
|
|
29
29
|
- 1
|
30
30
|
- 0
|
31
31
|
- 0
|
32
|
-
|
33
|
-
- 5
|
34
|
-
version: 1.0.0.rc.5
|
32
|
+
version: 1.0.0
|
35
33
|
type: :development
|
36
34
|
prerelease: false
|
37
35
|
version_requirements: *id001
|
@@ -54,7 +52,9 @@ files:
|
|
54
52
|
- lib/bridge.rb
|
55
53
|
- lib/bridge/bid.rb
|
56
54
|
- lib/bridge/card.rb
|
55
|
+
- lib/bridge/constants.rb
|
57
56
|
- lib/bridge/deal.rb
|
57
|
+
- lib/bridge/imp.rb
|
58
58
|
- lib/bridge/score.rb
|
59
59
|
- lib/bridge/trick.rb
|
60
60
|
- lib/bridge/version.rb
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- test/test_bridge.rb
|
64
64
|
- test/test_card.rb
|
65
65
|
- test/test_deal.rb
|
66
|
+
- test/test_imp.rb
|
66
67
|
- test/test_score.rb
|
67
68
|
- test/test_trick.rb
|
68
69
|
has_rdoc: true
|
@@ -79,7 +80,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
80
|
requirements:
|
80
81
|
- - ">="
|
81
82
|
- !ruby/object:Gem::Version
|
82
|
-
hash:
|
83
|
+
hash: 2761440476130499620
|
83
84
|
segments:
|
84
85
|
- 0
|
85
86
|
version: "0"
|