rodders 0.2.0 → 0.3.0
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.
- data/VERSION +1 -1
- data/lib/FixedOdds.rb +38 -23
- data/rodders.gemspec +3 -4
- data/spec/FixedOdds_spec.rb +34 -30
- metadata +16 -17
- data/lib/Rational.rb +0 -9
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/FixedOdds.rb
CHANGED
@@ -11,14 +11,16 @@ class FixedOdds
|
|
11
11
|
|
12
12
|
# creates a new FixedOdds from a string which can be in fractional,
|
13
13
|
# moneyline or decimal format
|
14
|
+
# @note strings like '5' are parsed as decimal odds, not as being
|
15
|
+
# equivalent to '5/1'
|
14
16
|
# @param [String] odds the odds in fractional, moneyline or decimal form
|
15
17
|
# @return [FixedOdds]
|
16
18
|
def FixedOdds.from_s(odds)
|
17
19
|
case
|
18
|
-
when
|
19
|
-
when
|
20
|
-
when
|
21
|
-
else
|
20
|
+
when self.fractional_odds?(odds) then self.fractional_odds odds
|
21
|
+
when self.moneyline_odds?(odds) then self.moneyline_odds odds
|
22
|
+
when self.decimal_odds?(odds) then self.decimal_odds odds
|
23
|
+
else raise ArgumentError, %{could not parse "#{odds}"}
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
@@ -55,7 +57,7 @@ class FixedOdds
|
|
55
57
|
# @param [String] fractional odds in fractional form
|
56
58
|
# @return (see FixedOdds.from_s)
|
57
59
|
def FixedOdds.fractional_odds(fractional)
|
58
|
-
raise %{could not parse "#{fractional}" as fractional odds} unless
|
60
|
+
raise %{could not parse "#{fractional}" as fractional odds} unless self.fractional_odds?(fractional)
|
59
61
|
return new(Rational('1/1')) if fractional == 'evens' || fractional == 'even money'
|
60
62
|
if /(?<numerator>\d+)(\/|-to-)(?<denominator>\d+)/ =~ fractional then r = Rational("#{numerator}/#{denominator}") end
|
61
63
|
r = r.reciprocal if fractional.end_with? ' on'
|
@@ -71,10 +73,11 @@ class FixedOdds
|
|
71
73
|
# creates a new FixedOdds from moneyline form. Examples are
|
72
74
|
# * +400
|
73
75
|
# * -500
|
76
|
+
# @note (see #from_s)
|
74
77
|
# @param [String] moneyline odds in moneyline form
|
75
78
|
# @return (see FixedOdds.from_s)
|
76
79
|
def FixedOdds.moneyline_odds(moneyline)
|
77
|
-
raise %{could not parse "#{moneyline}" as moneyline odds} unless
|
80
|
+
raise %{could not parse "#{moneyline}" as moneyline odds} unless self.moneyline_odds?(moneyline)
|
78
81
|
sign = moneyline[0]
|
79
82
|
if sign == '+' then new(Rational("#{moneyline}/100"))
|
80
83
|
else new(Rational("100/#{moneyline.to_i.magnitude}"))
|
@@ -87,15 +90,15 @@ class FixedOdds
|
|
87
90
|
# @param [String] decimal odds in decimal form
|
88
91
|
# @return (see FixedOdds.from_s)
|
89
92
|
def FixedOdds.decimal_odds(decimal)
|
90
|
-
raise %{could not parse "#{decimal}" as decimal odds} unless
|
93
|
+
raise %{could not parse "#{decimal}" as decimal odds} unless self.decimal_odds?(decimal)
|
91
94
|
new(Rational(decimal.to_f - 1))
|
92
95
|
end
|
93
96
|
|
94
97
|
# calculates the profit won on a winning bet
|
95
|
-
# @param [
|
98
|
+
# @param [Money] stake the stake
|
96
99
|
# @return [Money] the profit
|
97
100
|
def profit_on_winning_stake(stake)
|
98
|
-
stake
|
101
|
+
stake * @fractional_odds
|
99
102
|
end
|
100
103
|
|
101
104
|
# calculates the total return on a winning bet
|
@@ -103,15 +106,15 @@ class FixedOdds
|
|
103
106
|
# @param (see #profit_on_winning_stake)
|
104
107
|
# @return [Money] the total winnings
|
105
108
|
def total_return_on_winning_stake(stake)
|
106
|
-
profit_on_winning_stake(stake) + stake
|
109
|
+
profit_on_winning_stake(stake) + stake
|
107
110
|
end
|
108
111
|
|
109
112
|
# calculates the magnitude of the stake needed to
|
110
113
|
# win the specified amount in profit
|
111
|
-
# @param [
|
114
|
+
# @param [Money] win the desired profit
|
112
115
|
# @return [Money] the stake required to realise that profit on a winning bet
|
113
116
|
def stake_needed_to_win win
|
114
|
-
win
|
117
|
+
win / @fractional_odds
|
115
118
|
end
|
116
119
|
|
117
120
|
# string representation in fractional form like '4/1'
|
@@ -129,7 +132,7 @@ class FixedOdds
|
|
129
132
|
# string representation in moneyline form
|
130
133
|
# @return [String] moneyline form representation
|
131
134
|
def to_s_moneyline
|
132
|
-
integral_number_with_sign_regex =
|
135
|
+
integral_number_with_sign_regex = '%+d'
|
133
136
|
|
134
137
|
if @fractional_odds > 1.0
|
135
138
|
integral_number_with_sign_regex % (fractional_odds * 100).to_i
|
@@ -141,17 +144,29 @@ class FixedOdds
|
|
141
144
|
# string representation in decimal form
|
142
145
|
# @return [String] decimal form representation
|
143
146
|
def to_s_decimal
|
144
|
-
|
147
|
+
'%g' % (fractional_odds + 1)
|
145
148
|
end
|
146
149
|
|
147
|
-
|
148
|
-
def ==(other)
|
149
|
-
other.fractional_odds == @fractional_odds
|
150
|
-
end
|
150
|
+
protected
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
152
|
+
# equality method
|
153
|
+
def ==(other)
|
154
|
+
other.fractional_odds == @fractional_odds
|
155
|
+
end
|
156
|
+
|
157
|
+
# low odds are those which pay out the most money
|
158
|
+
# on a winning bet and vice-versa
|
159
|
+
def <=>(other)
|
160
|
+
other.fractional_odds <=> @fractional_odds
|
161
|
+
end
|
157
162
|
end
|
163
|
+
|
164
|
+
class Rational
|
165
|
+
# calculates the reciprocal
|
166
|
+
# @example
|
167
|
+
# Rational(2/3).reciprocal #=> Rational(3/2)
|
168
|
+
# @return [Rational] the reciprocal
|
169
|
+
def reciprocal
|
170
|
+
1 / self
|
171
|
+
end
|
172
|
+
end
|
data/rodders.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "rodders"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nigel Lowry"]
|
12
|
-
s.date = "2011-11
|
12
|
+
s.date = "2011-12-11"
|
13
13
|
s.description = "Converts between fractional, decimal and moneyline odds for betting and gambling. Calculates how much can be won on a given stake."
|
14
14
|
s.email = "nigel-lowry@ultra.eclipse.co.uk"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,7 +27,6 @@ Gem::Specification.new do |s|
|
|
27
27
|
"VERSION",
|
28
28
|
"lib/FixedOdds.rb",
|
29
29
|
"lib/MutuallyExclusiveCollection.rb",
|
30
|
-
"lib/Rational.rb",
|
31
30
|
"rodders.gemspec",
|
32
31
|
"spec/FixedOdds_spec.rb",
|
33
32
|
"spec/MutuallyExclusiveCollection_spec.rb",
|
@@ -37,7 +36,7 @@ Gem::Specification.new do |s|
|
|
37
36
|
s.homepage = "http://github.com/nigel-lowry/rodders"
|
38
37
|
s.licenses = ["MIT"]
|
39
38
|
s.require_paths = ["lib"]
|
40
|
-
s.rubygems_version = "1.8.
|
39
|
+
s.rubygems_version = "1.8.12"
|
41
40
|
s.summary = "Fixed odds betting library"
|
42
41
|
|
43
42
|
if s.respond_to? :specification_version then
|
data/spec/FixedOdds_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
3
|
|
3
4
|
describe "FixedOdds" do
|
@@ -5,10 +6,10 @@ describe "FixedOdds" do
|
|
5
6
|
describe "fractional_odds factory" do
|
6
7
|
it "should raise error if not fractional odds" do
|
7
8
|
expect {
|
8
|
-
FixedOdds.fractional_odds '
|
9
|
+
FixedOdds.fractional_odds '5'
|
9
10
|
}.to raise_error(
|
10
11
|
RuntimeError,
|
11
|
-
/could not parse "
|
12
|
+
/could not parse "5" as fractional odds/
|
12
13
|
)
|
13
14
|
end
|
14
15
|
|
@@ -100,26 +101,26 @@ describe "FixedOdds" do
|
|
100
101
|
end
|
101
102
|
|
102
103
|
describe "positive figures" do
|
103
|
-
it "should treat '+400' as meaning winning
|
104
|
+
it "should treat '+400' as meaning winning £400 on a £100 bet" do
|
104
105
|
plus400 = FixedOdds.moneyline_odds('+400')
|
105
|
-
plus400.profit_on_winning_stake(
|
106
|
+
plus400.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(400, :GBP)
|
106
107
|
end
|
107
108
|
|
108
|
-
it "should treat +100 as meaning winning
|
109
|
+
it "should treat +100 as meaning winning £100 on a £100 bet" do
|
109
110
|
plus100 = FixedOdds.moneyline_odds('+100')
|
110
|
-
plus100.profit_on_winning_stake(
|
111
|
+
plus100.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(100, :GBP)
|
111
112
|
end
|
112
113
|
end
|
113
114
|
|
114
115
|
describe "negative figures" do
|
115
|
-
it "should treat '-400' as meaning you need to wager
|
116
|
+
it "should treat '-400' as meaning you need to wager £400 to win £100" do
|
116
117
|
minus400 = FixedOdds.moneyline_odds('-400')
|
117
|
-
minus400.profit_on_winning_stake(
|
118
|
+
minus400.profit_on_winning_stake(Money.from_fixnum(400, :GBP)).should == Money.from_fixnum(100, :GBP)
|
118
119
|
end
|
119
120
|
|
120
|
-
it "should treat '-100' as meaning you need to wager
|
121
|
+
it "should treat '-100' as meaning you need to wager £100 to win £100 (which is identical to '+100')" do
|
121
122
|
minus100 = FixedOdds.moneyline_odds('-100')
|
122
|
-
minus100.profit_on_winning_stake(
|
123
|
+
minus100.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(100, :GBP)
|
123
124
|
end
|
124
125
|
end
|
125
126
|
end
|
@@ -134,19 +135,19 @@ describe "FixedOdds" do
|
|
134
135
|
)
|
135
136
|
end
|
136
137
|
|
137
|
-
it "should treat '2' as meaning you have to wager
|
138
|
+
it "should treat '2' as meaning you have to wager £100 to win £100" do
|
138
139
|
d2 = FixedOdds.decimal_odds('2')
|
139
|
-
d2.profit_on_winning_stake(
|
140
|
+
d2.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(100, :GBP)
|
140
141
|
end
|
141
142
|
|
142
|
-
it "should treat '5' as meaning you have to wager
|
143
|
+
it "should treat '5' as meaning you have to wager £100 to win £400" do
|
143
144
|
d5 = FixedOdds.decimal_odds('5')
|
144
|
-
d5.profit_on_winning_stake(
|
145
|
+
d5.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(400, :GBP)
|
145
146
|
end
|
146
147
|
|
147
|
-
it "should treat '1.25' as meaning yo have to wager
|
148
|
+
it "should treat '1.25' as meaning yo have to wager £400 to win £100" do
|
148
149
|
d1_25 = FixedOdds.decimal_odds('1.25')
|
149
|
-
d1_25.profit_on_winning_stake(
|
150
|
+
d1_25.profit_on_winning_stake(Money.from_fixnum(400, :GBP)).should == Money.from_fixnum(100, :GBP)
|
150
151
|
end
|
151
152
|
end
|
152
153
|
|
@@ -224,8 +225,11 @@ describe "FixedOdds" do
|
|
224
225
|
end
|
225
226
|
|
226
227
|
describe "decimal odds" do
|
227
|
-
it "should parse integral odds" do
|
228
|
-
|
228
|
+
it "should parse integral odds of '2' as decimal odds, not as fractional odds of '2/1'" do
|
229
|
+
decimal_odds_2 = FixedOdds.from_s('2')
|
230
|
+
|
231
|
+
decimal_odds_2.should == FixedOdds.decimal_odds('2')
|
232
|
+
decimal_odds_2.should_not == FixedOdds.fractional_odds('2/1')
|
229
233
|
end
|
230
234
|
|
231
235
|
it "should parse floating-point odds" do
|
@@ -345,38 +349,38 @@ describe "FixedOdds" do
|
|
345
349
|
end
|
346
350
|
|
347
351
|
describe "#profit_on_winning_stake" do
|
348
|
-
it "should return a profit of
|
352
|
+
it "should return a profit of £400 on a £100 stake on a 4/1 bet" do
|
349
353
|
fourToOne = FixedOdds.fractional_odds '4/1'
|
350
|
-
fourToOne.profit_on_winning_stake(
|
354
|
+
fourToOne.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(400, :GBP)
|
351
355
|
end
|
352
356
|
|
353
|
-
it "should return a profit of
|
357
|
+
it "should return a profit of £25 on a £100 stake with a 1/4 bet" do
|
354
358
|
oneToFour = FixedOdds.fractional_odds '1/4'
|
355
|
-
oneToFour.profit_on_winning_stake(
|
359
|
+
oneToFour.profit_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(25, :GBP)
|
356
360
|
end
|
357
361
|
end
|
358
362
|
|
359
363
|
describe "#total_return_on_winning_stake" do
|
360
|
-
it "should show that the full amount back on a winning 4/1 bet with a
|
364
|
+
it "should show that the full amount back on a winning 4/1 bet with a £100 stake is £500" do
|
361
365
|
fourToOne = FixedOdds.fractional_odds '4/1'
|
362
|
-
fourToOne.total_return_on_winning_stake(
|
366
|
+
fourToOne.total_return_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(500, :GBP)
|
363
367
|
end
|
364
368
|
|
365
|
-
it "should show that the full amount back on a winning 1/4 bet with a
|
369
|
+
it "should show that the full amount back on a winning 1/4 bet with a £100 stake is £125" do
|
366
370
|
oneToFour = FixedOdds.fractional_odds '1/4'
|
367
|
-
oneToFour.total_return_on_winning_stake(
|
371
|
+
oneToFour.total_return_on_winning_stake(Money.from_fixnum(100, :GBP)).should == Money.from_fixnum(125, :GBP)
|
368
372
|
end
|
369
373
|
end
|
370
374
|
|
371
375
|
describe "#stake_needed_to_win" do
|
372
|
-
it "should be
|
376
|
+
it "should be £1 on a 1/1 to win £1" do
|
373
377
|
oneToOne = FixedOdds.fractional_odds '1/1'
|
374
|
-
oneToOne.stake_needed_to_win(
|
378
|
+
oneToOne.stake_needed_to_win(Money.from_fixnum(1, :GBP)).should == Money.from_fixnum(1, :GBP)
|
375
379
|
end
|
376
380
|
|
377
|
-
it "should be
|
381
|
+
it "should be £100 on 4/1 to win £400" do
|
378
382
|
fourToOne = FixedOdds.fractional_odds '4/1'
|
379
|
-
fourToOne.stake_needed_to_win(
|
383
|
+
fourToOne.stake_needed_to_win(Money.from_fixnum(400, :GBP)).should == Money.from_fixnum(100, :GBP)
|
380
384
|
end
|
381
385
|
end
|
382
386
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodders
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11
|
12
|
+
date: 2011-12-11 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: money
|
16
|
-
requirement: &
|
16
|
+
requirement: &70347044732340 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70347044732340
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70347044731860 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.3.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70347044731860
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: yard
|
38
|
-
requirement: &
|
38
|
+
requirement: &70347044731320 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.6.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70347044731320
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
|
-
requirement: &
|
49
|
+
requirement: &70347044730800 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.0.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70347044730800
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &70347044730320 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.6.4
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70347044730320
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &70347044729800 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70347044729800
|
80
80
|
description: Converts between fractional, decimal and moneyline odds for betting and
|
81
81
|
gambling. Calculates how much can be won on a given stake.
|
82
82
|
email: nigel-lowry@ultra.eclipse.co.uk
|
@@ -96,7 +96,6 @@ files:
|
|
96
96
|
- VERSION
|
97
97
|
- lib/FixedOdds.rb
|
98
98
|
- lib/MutuallyExclusiveCollection.rb
|
99
|
-
- lib/Rational.rb
|
100
99
|
- rodders.gemspec
|
101
100
|
- spec/FixedOdds_spec.rb
|
102
101
|
- spec/MutuallyExclusiveCollection_spec.rb
|
@@ -117,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
116
|
version: '0'
|
118
117
|
segments:
|
119
118
|
- 0
|
120
|
-
hash:
|
119
|
+
hash: 2781179272829975536
|
121
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
121
|
none: false
|
123
122
|
requirements:
|
@@ -126,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
125
|
version: '0'
|
127
126
|
requirements: []
|
128
127
|
rubyforge_project:
|
129
|
-
rubygems_version: 1.8.
|
128
|
+
rubygems_version: 1.8.12
|
130
129
|
signing_key:
|
131
130
|
specification_version: 3
|
132
131
|
summary: Fixed odds betting library
|