tournament 0.0.3 → 1.0.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/History.txt CHANGED
@@ -1,8 +1,20 @@
1
- == 0.0.1 / 2008-03-23
1
+ == 1.0.0 / 2008-03-26
2
2
 
3
- * Initial Release
3
+ * Change the pool command line script usage to make it simpler (I hope)
4
+ * Add a new report: final_four
5
+ * FIXME: Final four report assumes payouts go to 1st and 2nd and last places.
6
+ This should be configurable.
7
+
8
+ == 0.0.3 / 2008-03-23
9
+
10
+ * Bugfix the picker wrapper script. Getting used to bones/rubyforge.
4
11
 
5
12
  == 0.0.2 / 2008-03-23
6
13
 
7
14
  * Changed the picker wrapper script to ruby because it seems that
8
15
  that is what rubyforge tools expect.
16
+
17
+ == 0.0.1 / 2008-03-23
18
+
19
+ * Initial Release
20
+
data/README.txt CHANGED
@@ -19,66 +19,82 @@ basketball tournament pool.
19
19
 
20
20
  == SYNOPSIS:
21
21
 
22
- The tournament command line program is installed as 'tournament'. The library
22
+ The tournament command line program is installed as 'pool'. The library
23
23
  has the 2008 NCAA tournament pre-configured. If you were to use
24
24
  this library for the 2009 NCAA tournament, code changes would be
25
25
  necessary. FIXME (add ability to read teams from a simple configuration
26
- file).
26
+ file). For usage, just execute
27
+
28
+ pool --help
29
+
30
+ For command specific usage, execute
31
+
32
+ pool <command> --help
33
+
34
+ where <command> is one of the available commands described below. The
35
+ pool command saves state in a file called pool.yml by default. This
36
+ can be overridden in all cases by using the --save-file option.
27
37
 
28
38
  The pool manager would use this program as follows:
29
39
 
30
- 1. Choose a scoring strategy. There are various scoring strategies
31
- that could be used. The library comes pre-configured with
32
- two scoring strategies:
33
-
34
- 1. Basic scoring strategy: each correct pick is worth 2 X the round.
35
- 2. Upset favoring strategy: each correct pick is worth a
36
- base amount per round plus the seed number of the winner. As
37
- pre-configured, the base amounts per round are 3, 5, 11, 19, 30
38
- and 40 points.
40
+ 1. Choose a scoring strategy. There are various scoring strategies
41
+ that could be used. The library comes pre-configured with
42
+ two scoring strategies:
43
+ 1. Basic scoring strategy: each correct pick is worth 2 X the round.
44
+ 2. Upset favoring strategy: each correct pick is worth a
45
+ base amount per round plus the seed number of the winner. As
46
+ pre-configured, the base amounts per round are 3, 5, 11, 19, 30
47
+ and 40 points.
48
+ If your scoring strategy is not one of the above, you will have to
49
+ write a class in the Bracket class, in file lib/tournament/bracket.rb.
39
50
 
40
- If your scoring strategy is not one of the above, you will have to
41
- write a class in the Bracket class, in file lib/tournament/bracket.rb.
51
+ 2. Create a directory to hold the pool data and change to it
42
52
 
43
- 2. Initialize the pool
53
+ 3. Initialize the pool
44
54
 
45
- tournament setup pool.yml [--scoring=upset_scoring_strategy]
55
+ pool setup [--scoring=upset_scoring_strategy]
46
56
 
47
- Use the --scoring argument to change to the upset favoring
48
- strategy. If the basic strategy is ok, the --scoring argument is
49
- not required.
57
+ Use the --scoring argument to change to the upset favoring
58
+ strategy. If the basic strategy is ok, the --scoring argument is
59
+ not required.
50
60
 
51
- 3. Export a tournament entry YAML file
61
+ As mentioned above, unless overridden by using the --save-file
62
+ option, the pool will save itself to the file 'pool.yml'
52
63
 
53
- tournament bracket pool.yml tournament.yml
64
+ 3. Export a tournament entry YAML file
54
65
 
55
- 4. Create entries. You can use the included buggy GUI (see below),
56
- or edit YAML files by hand.
66
+ pool dump
57
67
 
58
- 5. Import the entry YAML files into the pool
68
+ This will save the tournament entry file as tournament.yml unless
69
+ the --entry option is used to override it.
59
70
 
60
- tournament update pool.yml --add-entry=path/to/entry.yml
71
+ 4. Create entries. You can use the included buggy GUI (see below),
72
+ or edit YAML files by hand.
61
73
 
62
- 6. As games progress, update the tournament.yml file, again using the GUI or
63
- editing the YAML file by hand. Then update the pool with the new
64
- tournament YAML file
74
+ 5. Import the entry YAML files into the pool
65
75
 
66
- tournament update pool.yml --bracket=tournament.yml
76
+ pool entry --add=path/to/entry.yml
67
77
 
68
- 7. Run reports
78
+ 6. As games progress, update the tournament.yml file, again using the GUI or
79
+ editing the YAML file by hand. Then update the pool with the new
80
+ pool YAML file
81
+
82
+ pool update
83
+
84
+ 7. Run reports
69
85
 
70
- tournament report pool.yml --type=[entry|region|leader|score]
86
+ pool report [final_four|entry|region|leader|score]
71
87
 
72
- 8. After about 22 teams are left, run a possibility report. This report will
73
- run through all the remaining ways the tournament can come out and
74
- calculate the chance to win for each player. The chance to win
75
- is defined as the percentage of possibilities that lead to that player
76
- coming out on top in the pool. With more than about 22 teams left
77
- (YMMV), this report could take months to run. FIXME (Investigate
78
- possibly using EC2 or something to spread the load around, or
79
- otherwise optimize the possibility checking algorithm)
88
+ 8. After about 22 teams are left, run a possibility report. This report will
89
+ run through all the remaining ways the tournament can come out and
90
+ calculate the chance to win for each player. The chance to win
91
+ is defined as the percentage of possibilities that lead to that player
92
+ coming out on top in the pool. With more than about 22 teams left
93
+ (YMMV), this report could take months to run. FIXME (Investigate
94
+ possibly using EC2 or something to spread the load around, or
95
+ otherwise optimize the possibility checking algorithm)
80
96
 
81
- tournament report pool.yml --type=possibility
97
+ pool report possibility
82
98
 
83
99
  == SHOES GUI:
84
100
 
@@ -90,8 +106,10 @@ Tournament::Entry object. The picker program optionally takes one
90
106
  argument, the path to a Tournament::Entry YAML file. It will open
91
107
  with the provided entry's picks pre filled in.
92
108
 
93
- The GUI may be used for keeping the NCAA tournament entry YAML file
94
- up to date.
109
+ The GUI also may be used for keeping the NCAA tournament entry YAML file
110
+ up to date:
111
+
112
+ picker tournament.yml
95
113
 
96
114
  == REQUIREMENTS:
97
115
 
data/Rakefile CHANGED
@@ -16,7 +16,7 @@ PROJ.authors = 'Douglas A. Seifert'
16
16
  PROJ.email = 'doug+rubyforge@dseifert.net'
17
17
  PROJ.url = 'http://www.dseifert.net/code/tournament'
18
18
  PROJ.rubyforge_name = 'tournament'
19
- PROJ.version = '0.0.3'
19
+ PROJ.version = '1.0.0'
20
20
  PROJ.group_id = 5863
21
21
 
22
22
  PROJ.spec_opts << '--color'
@@ -24,4 +24,7 @@ PROJ.spec_opts << '--color'
24
24
  PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.svn ^pkg ^doc bin/fake bin/gui_v2.rb)
25
25
  PROJ.exclude << '^tags$'
26
26
 
27
+ PROJ.rdoc_opts = ["--line-numbers", "--inline-source"]
28
+ PROJ.rdoc_template = "tasks/jamis.rb"
29
+
27
30
  # EOF
data/bin/pool CHANGED
@@ -31,16 +31,17 @@ Main do
31
31
  end
32
32
  end
33
33
 
34
- argument('save-file') do
35
- required
34
+ option('save-file', 's') do
35
+ optional
36
36
  argument :required
37
+ default 'pool.yml'
37
38
  arity 1
38
39
  description "Save file for the pool."
39
40
  end
40
41
 
41
42
  mode('setup') do
42
43
  description "Sets up the pool the first time"
43
- option('scoring', 's') do
44
+ option('scoring', 'S') do
44
45
  optional
45
46
  argument :required
46
47
  arity 1
@@ -58,56 +59,79 @@ Main do
58
59
  end
59
60
 
60
61
  mode('update') do
61
- option('bracket', 'b') do
62
+ option('entry', 'e') do
62
63
  optional
63
64
  argument :required
65
+ default 'tournament.yml'
64
66
  arity 1
65
- description "Update the tournament bracket using supplied yaml file"
67
+ description "Update the tournament entry using supplied yaml file"
66
68
  end
67
- option('add-entry', 'a') do
69
+ def run
70
+ load_pool
71
+ tournament = YAML::load_file(params['entry'].value)
72
+ @pool.bracket = tournament.picks
73
+ save_pool
74
+ end
75
+ end
76
+
77
+ mode('entry') do
78
+ option('add', 'a') do
68
79
  optional
69
80
  argument :required
70
81
  arity -1
71
82
  description "Add an entry yaml file to the pool"
72
83
  end
84
+ option('remove', 'r') do
85
+ optional
86
+ argument :required
87
+ arity -1
88
+ description "Remove an entry by name"
89
+ end
73
90
  def run
74
91
  load_pool
75
- if params['bracket'].given?
76
- tournament = YAML::load_file(params['bracket'].value)
77
- @pool.bracket = tournament.picks
92
+ if params['add'].given?
93
+ @pool.add_entry_yaml(params['add'].value)
78
94
  save_pool
79
- elsif params['add-entry'].given?
80
- @pool.add_entry_yaml(params['add-entry'].value)
95
+ elsif params['remove'].given?
96
+ @pool.remove_by_name(params['remove'].value)
81
97
  save_pool
82
98
  else
83
- puts "Please specify bracket or add-entry"
99
+ puts "Please specify add or remove"
84
100
  print usage.to_s
85
101
  exit_warn!
86
102
  end
87
103
  end
88
104
  end
89
105
 
90
- mode('bracket') do
91
- argument('bracket-yaml') do
92
- required
93
- description "Dump the pool's bracket as an Tournament::Entry object to a yaml file."
106
+ mode('dump') do
107
+ option('entry', 'e') do
108
+ optional
109
+ argument :required
110
+ default 'tournament.yml'
111
+ description "Dump the pool entry object to a yaml file."
94
112
  end
95
113
  def run
96
114
  load_pool
97
115
  tournament = Tournament::Entry.new('Tournament', @pool.bracket, 0)
98
- File.open(params['bracket-yaml'].value, "w") do |f|
116
+ File.open(params['entry'].value, "w") do |f|
99
117
  YAML::dump(tournament, f)
100
118
  end
101
119
  end
102
120
  end
103
121
 
104
122
  mode('report') do
105
- option('type', 't') do
123
+ available_reports = Tournament::Pool.instance_methods(false).map do |name|
124
+ if idx = name.index("_report")
125
+ name[0,idx]
126
+ else
127
+ nil
128
+ end
129
+ end.compact
130
+ argument('type') do
106
131
  required
107
132
  arity 1
108
- argument :required
109
- validate {|rt| ['score', 'region', 'leader', 'possibility', 'entry'].include?(rt)}
110
- description "Which report to run, score, leader, region, possibility or entry"
133
+ validate {|rt| available_reports.include?(rt)}
134
+ description "Which report to run among #{available_reports.join(', ')}"
111
135
  end
112
136
  def run
113
137
  load_pool
@@ -115,4 +139,9 @@ Main do
115
139
  end
116
140
  end
117
141
 
142
+ def run
143
+ print usage.to_s
144
+ exit_warn!
145
+ end
146
+
118
147
  end
@@ -176,7 +176,7 @@ class Tournament::Bracket
176
176
  #num_possibilities = 0
177
177
  #shifts.size.times { |n| num_possibilities |= (1 << n) }
178
178
 
179
- puts "Checking #{num_possibilities} (#{number_of_outcomes}) possible outcomes."
179
+ #puts "Checking #{num_possibilities} (#{number_of_outcomes}) possible outcomes."
180
180
  possibility = num_possibilities - 1
181
181
  while possibility >= 0
182
182
  #puts " possibility: #{Tournament::Bracket.jbin(possibility, teams.size - 1)}"
@@ -185,9 +185,9 @@ class Tournament::Bracket
185
185
  real_poss |= (((possibility & (1 << i)) > 0 ? 1 : 0) << s)
186
186
  end
187
187
  #puts " real_poss: #{Tournament::Bracket.jbin(real_poss, teams.size - 1)}"
188
- real_possibility = winners | real_poss
189
- #puts " possibility: #{Tournament::Bracket.jbin(real_possibility, teams.size - 1)}"
190
- yield(real_possibility)
188
+ real_poss = winners | real_poss
189
+ #puts " real_poss: #{Tournament::Bracket.jbin(real_poss, teams.size - 1)}"
190
+ yield(real_poss)
191
191
  possibility -= 1
192
192
  end
193
193
  end
@@ -32,6 +32,14 @@ class Tournament::Pool
32
32
  @entries << YAML::load_file(yaml)
33
33
  end
34
34
 
35
+ # Remove an entry by name from the pool
36
+ def remove_by_name(name)
37
+ entry = @entries.find {|e| e.name == name}
38
+ if !entry.nil?
39
+ @entries.delete(entry)
40
+ end
41
+ end
42
+
35
43
  # Creates a bracket for the pool by combining all the
36
44
  # regions into one bracket of 64 teams. By default the
37
45
  # bracket uses the basic scoring strategy.
@@ -289,7 +297,38 @@ class Tournament::Pool
289
297
  end
290
298
  end
291
299
 
300
+ def final_four_report
301
+ if @entries.size == 0
302
+ puts "There are no entries in the pool."
303
+ return
304
+ end
305
+ if self.bracket.teams_left != 4
306
+ puts "The final four report should only be run when there"
307
+ puts "are exactly four teams left in the tournament."
308
+ return
309
+ end
310
+ print "Final Four: #{self.bracket.winners[4][0,2].map{|t| "(#{t.seed}) #{t.name}"}.join(" vs. ")}"
311
+ puts " #{self.bracket.winners[4][2,2].map{|t| "(#{t.seed}) #{t.name}"}.join(" vs. ")}"
312
+ sep= "--------------+----------------+----------------------------"
313
+ puts " Championship | Champion | Winners"
314
+ puts sep
315
+ self.bracket.each_possible_bracket do |poss|
316
+ rankings = @entries.map{|p| [p, p.picks.score_against(poss)] }.sort_by {|arr| -arr[1] }
317
+ first = rankings[0][0]
318
+ second = rankings[1][0]
319
+ last = rankings[-1][0]
320
+ puts "%14s|%16s|%s" % [poss.winners[5].map{|t| t.short_name}.join("-"),
321
+ poss.champion.name, " 1: #{first.name} (#{rankings[0][1]})"]
322
+ puts "%14s|%16s|%s" % ['', '',
323
+ " 2: #{second.name} (#{rankings[1][1]})"]
324
+ puts "%14s|%16s|%s" % ['', '',
325
+ "LAST: #{last.name} (#{rankings[-1][1]})"]
326
+ puts sep
327
+ end
328
+ end
329
+
292
330
  def possibility_report
331
+ $stdout.sync = true
293
332
  if @entries.size == 0
294
333
  puts "There are no entries in the pool."
295
334
  return
@@ -298,6 +337,9 @@ class Tournament::Pool
298
337
  min_ranking = @entries.map{|p| @entries.size + 1}
299
338
  times_winner = @entries.map{|p| 0 }
300
339
  count = 0
340
+ old_percentage = -1
341
+ old_remaining = 1_000_000_000_000
342
+ puts "Checking #{self.bracket.number_of_outcomes} possible outcomes"
301
343
  start = Time.now.to_f
302
344
  self.bracket.each_possible_bracket do |poss|
303
345
  poss_scores = @entries.map{|p| p.picks.score_against(poss)}
@@ -310,15 +352,15 @@ class Tournament::Pool
310
352
  times_winner[i] += 1 if rank == 1
311
353
  end
312
354
  count += 1
313
- percentage = (count * 100 / self.bracket.number_of_outcomes) * 1000
314
- if (percentage % 1000) == 0
315
- percentage /= 1000
316
- hashes = '#' * percentage + '>'
317
- elapsed = Time.now.to_f - start
318
- spp = elapsed / count
319
- remaining = ((self.bracket.number_of_outcomes - count) * spp).to_i
320
- print "\rCalculating: %3d%% +#{hashes.ljust(100, '-')}+ %5d seconds remaining" % [percentage, remaining]
321
-
355
+ percentage = (count * 100.0 / self.bracket.number_of_outcomes)
356
+ elapsed = Time.now.to_f - start
357
+ spp = elapsed / count
358
+ remaining = ((self.bracket.number_of_outcomes - count) * spp).to_i
359
+ if (percentage.to_i != old_percentage) || (remaining < old_remaining)
360
+ old_remaining = remaining
361
+ old_percentage = percentage.to_i
362
+ hashes = '#' * (percentage.to_i/5) + '>'
363
+ print "\rCalculating: %3d%% +#{hashes.ljust(20, '-')}+ %5d seconds remaining" % [percentage.to_i, remaining]
322
364
  end
323
365
  end
324
366
  puts "\n"
data/tasks/doc.rake CHANGED
@@ -8,6 +8,7 @@ namespace :doc do
8
8
  Rake::RDocTask.new do |rd|
9
9
  rd.main = PROJ.rdoc_main
10
10
  rd.rdoc_dir = PROJ.rdoc_dir
11
+ rd.template = PROJ.rdoc_template if PROJ.rdoc_template
11
12
 
12
13
  incl = Regexp.new(PROJ.rdoc_include.join('|'))
13
14
  excl = Regexp.new(PROJ.rdoc_exclude.join('|'))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tournament
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Douglas A. Seifert
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-03-23 00:00:00 -07:00
12
+ date: 2008-03-26 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -70,6 +70,8 @@ has_rdoc: true
70
70
  homepage: http://www.dseifert.net/code/tournament
71
71
  post_install_message:
72
72
  rdoc_options:
73
+ - --line-numbers
74
+ - --inline-source
73
75
  - --main
74
76
  - README.txt
75
77
  require_paths: