tournament 0.0.1

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.
@@ -0,0 +1,341 @@
1
+ # Represents a NCAA tournament pool. Contains 4 regions
2
+ # of 16 teams each. Champions of Region 1 and Region 2
3
+ # and champions of Region 3 and Region 4 play each
4
+ # other in the final four.
5
+ class Tournament::Pool
6
+ attr_reader :regions # The regions in the pool
7
+ attr_reader :entries # Tournament::Entry objects for participants
8
+
9
+ # Create a new empty pool with no Regions or Entries
10
+ def initialize
11
+ @regions = Array.new(4)
12
+ @entries = []
13
+ end
14
+
15
+ # add regions to the pool. Champ of region with index = 0 plays
16
+ # region with index = 1 and index == 2 plays index == 3.
17
+ def add_region(name, teams, index)
18
+ @regions[index] = {
19
+ :name => name,
20
+ :teams => teams
21
+ }
22
+ end
23
+
24
+ # Add an Tournament::Entry object to the pool
25
+ def add_entry(entry)
26
+ @entries << entry
27
+ end
28
+
29
+ # Add an Tournament::Entry object to the pool after reading the Tournament::Entry
30
+ # from the provided YAML file.
31
+ def add_entry_yaml(yaml)
32
+ @entries << YAML::load_file(yaml)
33
+ end
34
+
35
+ # Creates a bracket for the pool by combining all the
36
+ # regions into one bracket of 64 teams. By default the
37
+ # bracket uses the basic scoring strategy.
38
+ def bracket
39
+ unless @bracket
40
+ if @regions.compact.size != 4
41
+ raise "Not all regions have been set."
42
+ end
43
+ all_teams = @regions.map do |region|
44
+ region[:teams]
45
+ end
46
+ all_teams = all_teams.flatten
47
+ @bracket = Tournament::Bracket.new(all_teams)
48
+ end
49
+ return @bracket
50
+ end
51
+
52
+ # Replaces the pool's bracket (as in after updating the bracket
53
+ # for game results)
54
+ def bracket=(new_bracket)
55
+ @bracket = new_bracket
56
+ end
57
+
58
+ # Creates a Pool object for the 2008 NCAA tournament
59
+ def self.ncaa_2008
60
+ pool = Tournament::Pool.new
61
+ pool.add_region("East",
62
+ [
63
+ Tournament::Team.new('North Carolina', 'UNC', 1),
64
+ Tournament::Team.new('Mt. St. Mary\'s', 'MSM', 16),
65
+ Tournament::Team.new('Indiana', 'Ind', 8),
66
+ Tournament::Team.new('Arkansas', 'Ark', 9),
67
+ Tournament::Team.new('Notre Dame', 'ND', 5),
68
+ Tournament::Team.new('George Mason', 'GM', 12),
69
+ Tournament::Team.new('Washington St.', 'WSt', 4),
70
+ Tournament::Team.new('Winthrop', 'Win', 13),
71
+ Tournament::Team.new('Oklahoma', 'Okl', 6),
72
+ Tournament::Team.new('St. Joseph\'s', 'StJ', 11),
73
+ Tournament::Team.new('Louisville', 'Lou', 3),
74
+ Tournament::Team.new('Boise St.', 'BSt', 14),
75
+ Tournament::Team.new('Butler', 'But', 7),
76
+ Tournament::Team.new('South Alabama', 'SAl', 10),
77
+ Tournament::Team.new('Tennessee', 'Ten', 2),
78
+ Tournament::Team.new('American', 'Am', 15)
79
+ ],
80
+ 0
81
+ )
82
+ pool.add_region("Midwest",
83
+ [
84
+ Tournament::Team.new('Kansas', 'Kan', 1),
85
+ Tournament::Team.new('Portland St.', 'PSt', 16),
86
+ Tournament::Team.new('UNLV', 'ULV', 8),
87
+ Tournament::Team.new('Kent St.', 'KSt', 9),
88
+ Tournament::Team.new('Clemson', 'Clm', 5),
89
+ Tournament::Team.new('Villanova', 'Vil', 12),
90
+ Tournament::Team.new('Vanderbilt', 'Van', 4),
91
+ Tournament::Team.new('Siena', 'Sie', 13),
92
+ Tournament::Team.new('USC', 'USC', 6),
93
+ Tournament::Team.new('Kansas St.', 'KSU', 11),
94
+ Tournament::Team.new('Wisconsin', 'Wis', 3),
95
+ Tournament::Team.new('CSU Fullerton', 'CSF', 14),
96
+ Tournament::Team.new('Gonzaga', 'Gon', 7),
97
+ Tournament::Team.new('Davidson', 'Dav', 10),
98
+ Tournament::Team.new('Georgetown', 'GT', 2),
99
+ Tournament::Team.new('UMBC', 'UBC', 15)
100
+ ],
101
+ 1
102
+ )
103
+ pool.add_region("South",
104
+ [
105
+ Tournament::Team.new('Memphis', 'Mem', 1),
106
+ Tournament::Team.new('TX Arlington', 'TxA', 16),
107
+ Tournament::Team.new('Mississippi St.', 'MiS', 8),
108
+ Tournament::Team.new('Oregon', 'Ore', 9),
109
+ Tournament::Team.new('Michigan St.', 'MSU', 5),
110
+ Tournament::Team.new('Temple', 'Tem', 12),
111
+ Tournament::Team.new('Pittsburgh', 'Pit', 4),
112
+ Tournament::Team.new('Oral Roberts', 'ORo', 13),
113
+ Tournament::Team.new('Marquette', 'Mar', 6),
114
+ Tournament::Team.new('Kentucky', 'Ken', 11),
115
+ Tournament::Team.new('Stanford', 'Sta', 3),
116
+ Tournament::Team.new('Cornell', 'Cor', 14),
117
+ Tournament::Team.new('Miami (FL)', 'Mia', 7),
118
+ Tournament::Team.new('St. Mary\'s', 'StM', 10),
119
+ Tournament::Team.new('Texas', 'Tex', 2),
120
+ Tournament::Team.new('Austin Peay', 'APe', 15)
121
+ ],
122
+ 2
123
+ )
124
+ pool.add_region("West",
125
+ [
126
+ Tournament::Team.new('UCLA', 'ULA', 1),
127
+ Tournament::Team.new('Mis. Valley St', 'MVS', 16),
128
+ Tournament::Team.new('BYU', 'BYU', 8),
129
+ Tournament::Team.new('Texas A&M', 'A&M', 9),
130
+ Tournament::Team.new('Drake', 'Dra', 5),
131
+ Tournament::Team.new('W. Kentucky', 'WKy', 12),
132
+ Tournament::Team.new('Connecticut', 'Con', 4),
133
+ Tournament::Team.new('San Diego', 'SD', 13),
134
+ Tournament::Team.new('Purdue', 'Pur', 6),
135
+ Tournament::Team.new('Baylor', 'Bay', 11),
136
+ Tournament::Team.new('Xavier', 'Xav', 3),
137
+ Tournament::Team.new('Georgia', 'UG', 14),
138
+ Tournament::Team.new('West Virginia', 'WVa', 7),
139
+ Tournament::Team.new('Arizona', 'UA', 10),
140
+ Tournament::Team.new('Duke', 'Duk', 2),
141
+ Tournament::Team.new('Belmont', 'Bel', 15)
142
+ ],
143
+ 3
144
+ )
145
+ return pool
146
+ end
147
+
148
+ def self.test(num_picks = 10)
149
+ pool = ncaa_2008
150
+ b = pool.bracket
151
+ b.scoring_strategy = Tournament::Bracket::UpsetScoringStrategy.new
152
+ picks = (1..num_picks).map {|n| Tournament::Bracket.random_bracket(b.teams)}
153
+ # Play out the bracket
154
+ 32.times { |n| b.set_winner(1,n+1, b.matchup(1, n+1)[rand(2)])}
155
+ 16.times { |n| b.set_winner(2,n+1, b.matchup(2, n+1)[rand(2)])}
156
+ 8.times { |n| b.set_winner(3,n+1, b.matchup(3, n+1)[rand(2)])}
157
+ 4.times { |n| b.set_winner(4,n+1, b.matchup(4, n+1)[rand(2)])}
158
+ 2.times { |n| b.set_winner(5,n+1, b.matchup(5, n+1)[rand(2)])}
159
+ 1.times { |n| b.set_winner(6,n+1, b.matchup(6, n+1)[rand(2)])}
160
+ picks.each_with_index {|p, idx| pool.add_entry Tournament::Entry.new("picker_#{idx}", p) }
161
+ picks.each_with_index do |p, idx|
162
+ puts "Score #{idx+1}: #{p.score_against(b)}"
163
+ end
164
+ #pool.possibility_report
165
+ pool.leader_report
166
+ pool.entry_report
167
+ end
168
+
169
+ def leader_report
170
+ puts "Total games played: #{@bracket.games_played}"
171
+ puts "Number of entries: #{@entries.size}"
172
+ if @entries.size > 0
173
+ puts " Curr| Max | |Champ| Round Scores"
174
+ puts "Score|Score| Name |Live?|" + (1..bracket.rounds).to_a.map{|r| "%3d" % r}.join(" ")
175
+ sep ="-----+-----+---------------+-----+" + ("-" * 4 * bracket.rounds)
176
+ puts sep
177
+ @entries.sort_by {|e| -e.picks.score_against(bracket)}.each do |entry|
178
+ total = entry.picks.score_against(bracket)
179
+ max = entry.picks.maximum_score(bracket)
180
+ champ = entry.picks.champion
181
+ round_scores = []
182
+ 1.upto(bracket.rounds) do |round|
183
+ scores = entry.picks.scores_for_round(round, bracket)
184
+ round_scores << scores.inject(0) {|sum, arr| sum += (arr[0] ? arr[0] : 0)}
185
+ end
186
+ puts "%5d|%5d|%15s|%3s %1s|%s" % [total, max, entry.name,
187
+ champ.short_name,(bracket.still_alive?(champ) ? 'Y' : 'N'), round_scores.map {|s| "%3d" % s}.join(" ")]
188
+ end
189
+ puts sep
190
+ end
191
+ end
192
+
193
+ def score_report
194
+ # Compute scores
195
+ puts "Total games played: #{@bracket.games_played}"
196
+ puts "Number of entries: #{@entries.size}"
197
+ sep = "-----+---------------+----------------------------------------------------------------------------------"
198
+ if @entries.size > 0
199
+ puts "Total| Name | Round Scores"
200
+ puts sep
201
+ fmt1 = "%5d|%15s|%d: %3d %s"
202
+ fmt2 = " | |%d: %3d %s"
203
+ fmt3 = " | | %s"
204
+ @entries.sort_by {|e| -e.picks.score_against(bracket)}.each do |entry|
205
+ total = entry.picks.score_against(bracket)
206
+ 1.upto(bracket.rounds) do |round|
207
+ scores = entry.picks.scores_for_round(round, bracket)
208
+ round_total = scores.inject(0) {|sum, arr| sum += (arr[0] ? arr[0] : 0)}
209
+ scores_str = scores.map{|arr| "#{arr[1].short_name}=#{arr[0] ? arr[0] : '?'}"}.join(" ")
210
+ if [1,2].include?(round)
211
+ scores_str_arr = Tournament::Pool.split_line(scores_str, 70)
212
+ if round == 1
213
+ puts fmt1 % [total, entry.name, round, round_total, scores_str_arr[0]]
214
+ else
215
+ puts fmt2 % [round, round_total, scores_str_arr[0]]
216
+ end
217
+ scores_str_arr[1..-1].each do |scores_str|
218
+ puts fmt3 % scores_str
219
+ end
220
+ else
221
+ puts fmt2 % [round, round_total, scores_str]
222
+ end
223
+ end
224
+ puts sep
225
+ end
226
+ end
227
+ end
228
+
229
+ def self.split_line(str, len)
230
+ new_str = []
231
+ beg_idx = 0
232
+ end_idx = len - 1
233
+ while end_idx < str.length
234
+ end_idx += 1 while end_idx < (str.length - 1) && str[end_idx].chr != ' '
235
+ new_str << str[beg_idx,(end_idx-beg_idx+1)].strip
236
+ beg_idx = end_idx + 1
237
+ end_idx += len
238
+ end
239
+ new_str << str[beg_idx,str.length-1]
240
+ return new_str.reject {|s| s.nil? || s.length == 0}
241
+ end
242
+
243
+ def entry_report
244
+ puts "There are #{@entries.size} entries."
245
+ if @entries.size > 0
246
+ puts "".center(15) + "|" + "First Round".center(128)
247
+ puts "Name".center(15) + "|" + "Sweet 16".center(64) + "|" + "Elite 8".center(32) +
248
+ "|" + "Final 4".center(16) + "|" + "Final 2".center(8) + "|" + "Champion".center(15) +
249
+ "|" + "Tie Break"
250
+ puts ("-" * 15) + "+" + ("-" * 64) + "+" + ("-" * 32) +
251
+ "+" + ("-" * 16) + "+" + ("-" * 8) + "+" + ("-" * 15) +
252
+ "+" + ("-" * 10)
253
+ output = Proc.new do |name, bracket, tie_breaker|
254
+ first_round = bracket.winners[1].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
255
+ sweet_16 = bracket.winners[2].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
256
+ elite_8 = bracket.winners[3].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
257
+ final_4 = bracket.winners[4].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
258
+ final_2 = bracket.winners[5].map {|t| "%s" % (t.short_name rescue 'Unk')}.join('-')
259
+ champ = bracket.champion.name rescue 'Unk'
260
+ puts " |%128s" % first_round
261
+ puts "%15s|%64s|%32s|%16s|%8s|%15s|%s" %
262
+ [name, sweet_16, elite_8, final_4, final_2, champ, tie_breaker.to_s]
263
+ puts ("-" * 15) + "+" + ("-" * 64) + "+" + ("-" * 32) +
264
+ "+" + ("-" * 16) + "+" + ("-" * 8) + "+" + ("-" * 15) +
265
+ "+" + ("-" * 10)
266
+ end
267
+
268
+ output.call('Tournament', bracket, '-')
269
+
270
+ @entries.sort_by{|e| e.name}.each do |entry|
271
+ output.call(entry.name, entry.picks, entry.tie_breaker)
272
+ end
273
+ end
274
+ end
275
+
276
+ def region_report
277
+ puts " Region | Seed | Team "
278
+ current_idx = -1
279
+ @regions.each_with_index do |region, idx|
280
+ region[:teams].each do |team|
281
+ region_name = ''
282
+ if idx != current_idx
283
+ region_name = region[:name]
284
+ current_idx = idx
285
+ puts "--------+------+-------------------------"
286
+ end
287
+ puts "%8s|%6d|%25s" % [region_name, team.seed, "#{team.name} (#{team.short_name})"]
288
+ end
289
+ end
290
+ end
291
+
292
+ def possibility_report
293
+ if @entries.size == 0
294
+ puts "There are no entries in the pool."
295
+ return
296
+ end
297
+ max_possible_score = @entries.map{|p| 0}
298
+ min_ranking = @entries.map{|p| @entries.size + 1}
299
+ times_winner = @entries.map{|p| 0 }
300
+ count = 0
301
+ start = Time.now.to_f
302
+ self.bracket.each_possible_bracket do |poss|
303
+ poss_scores = @entries.map{|p| p.picks.score_against(poss)}
304
+ sort_scores = poss_scores.sort.reverse
305
+ @entries.each_with_index do |entry, i|
306
+ score = poss_scores[i]
307
+ max_possible_score[i] = score if score > max_possible_score[i]
308
+ rank = sort_scores.index(score) + 1
309
+ min_ranking[i] = rank if rank < min_ranking[i]
310
+ times_winner[i] += 1 if rank == 1
311
+ end
312
+ 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
+
322
+ end
323
+ end
324
+ puts "\n"
325
+ #puts "\n Max Scores: #{max_possible_score.inspect}"
326
+ #puts "Highest Place: #{min_ranking.inspect}"
327
+ #puts " Times Winner: #{times_winner.inspect}"
328
+ sort_array = []
329
+ times_winner.each_with_index { |n, i| sort_array << [n, i, min_ranking[i], max_possible_score[i]] }
330
+ sort_array = sort_array.sort_by {|arr| arr[0] == 0 ? (arr[2] == 0 ? -arr[3] : arr[2]) : -arr[0]}
331
+ #puts "SORT: #{sort_array.inspect}"
332
+ puts " Entry | Win Chance | Highest Place | Max Score | Tie Break "
333
+ puts "--------------------+------------+---------------+-----------+------------"
334
+ sort_array.each do |arr|
335
+ chance = arr[0].to_f * 100.0 / self.bracket.number_of_outcomes
336
+ puts "%19s | %10.2f | %13d | %9d | %d" %
337
+ [@entries[arr[1]].name, chance, min_ranking[arr[1]], max_possible_score[arr[1]], @entries[arr[1]].tie_breaker]
338
+ end
339
+ end
340
+
341
+ end
@@ -0,0 +1,19 @@
1
+ # Represents a team in a tournament Bracket
2
+ class Tournament::Team
3
+ attr_reader :name, :short_name, :seed
4
+
5
+ def initialize(name, short_name, seed)
6
+ @name = name
7
+ @short_name = short_name
8
+ @seed = seed
9
+ end
10
+
11
+ def ==(other)
12
+ return false unless Tournament::Team === other
13
+ @name == other.name && @short_name == other.short_name && @seed == other.seed
14
+ end
15
+
16
+ def eql?(other)
17
+ @name.eql?(other)
18
+ end
19
+ end
data/lib/tournament.rb ADDED
@@ -0,0 +1,56 @@
1
+ # $Id$
2
+
3
+ # Equivalent to a header guard in C/C++
4
+ # Used to prevent the class/module from being loaded more than once
5
+ unless defined? Tournament
6
+
7
+ module Tournament
8
+
9
+ # :stopdoc:
10
+ VERSION = '1.0.0'
11
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
12
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
13
+ # :startdoc:
14
+
15
+ # Returns the version string for the library.
16
+ #
17
+ def self.version
18
+ VERSION
19
+ end
20
+
21
+ # Returns the library path for the module. If any arguments are given,
22
+ # they will be joined to the end of the libray path using
23
+ # <tt>File.join</tt>.
24
+ #
25
+ def self.libpath( *args )
26
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
27
+ end
28
+
29
+ # Returns the lpath for the module. If any arguments are given,
30
+ # they will be joined to the end of the path using
31
+ # <tt>File.join</tt>.
32
+ #
33
+ def self.path( *args )
34
+ args.empty? ? PATH : ::File.join(PATH, *args)
35
+ end
36
+
37
+ # Utility method used to rquire all files ending in .rb that lie in the
38
+ # directory below this file that has the same name as the filename passed
39
+ # in. Optionally, a specific _directory_ name can be passed in such that
40
+ # the _filename_ does not have to be equivalent to the directory.
41
+ #
42
+ def self.require_all_libs_relative_to( fname, dir = nil )
43
+ dir ||= ::File.basename(fname, '.*')
44
+ search_me = ::File.expand_path(
45
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
46
+
47
+ Dir.glob(search_me).sort.each {|rb| require rb}
48
+ end
49
+
50
+ end # module Tournament
51
+
52
+ Tournament.require_all_libs_relative_to __FILE__
53
+
54
+ end # unless defined?
55
+
56
+ # EOF
@@ -0,0 +1,17 @@
1
+ # $Id$
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib tournament]))
5
+
6
+ Spec::Runner.configure do |config|
7
+ # == Mock Framework
8
+ #
9
+ # RSpec uses it's own mocking framework by default. If you prefer to
10
+ # use mocha, flexmock or RR, uncomment the appropriate line:
11
+ #
12
+ # config.mock_with :mocha
13
+ # config.mock_with :flexmock
14
+ # config.mock_with :rr
15
+ end
16
+
17
+ # EOF
@@ -0,0 +1,8 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
4
+
5
+ describe Tournament do
6
+ end
7
+
8
+ # EOF
Binary file
data/tasks/ann.rake ADDED
@@ -0,0 +1,76 @@
1
+ # $Id$
2
+
3
+ begin
4
+ require 'bones/smtp_tls'
5
+ rescue LoadError
6
+ require 'net/smtp'
7
+ end
8
+ require 'time'
9
+
10
+ namespace :ann do
11
+
12
+ file PROJ.ann_file do
13
+ puts "Generating #{PROJ.ann_file}"
14
+ File.open(PROJ.ann_file,'w') do |fd|
15
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
16
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
17
+ fd.puts(" #{PROJ.url}") if PROJ.url
18
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
19
+ fd.puts
20
+ fd.puts("== DESCRIPTION")
21
+ fd.puts
22
+ fd.puts(PROJ.description)
23
+ fd.puts
24
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
25
+ fd.puts
26
+ PROJ.ann_paragraphs.each do |p|
27
+ fd.puts "== #{p.upcase}"
28
+ fd.puts
29
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
30
+ fd.puts
31
+ end
32
+ fd.puts PROJ.ann_text if PROJ.ann_text
33
+ end
34
+ end
35
+
36
+ desc "Create an announcement file"
37
+ task :announcement => PROJ.ann_file
38
+
39
+ desc "Send an email announcement"
40
+ task :email => PROJ.ann_file do
41
+ from = PROJ.ann_email[:from] || PROJ.email
42
+ to = Array(PROJ.ann_email[:to])
43
+
44
+ ### build a mail header for RFC 822
45
+ rfc822msg = "From: #{from}\n"
46
+ rfc822msg << "To: #{to.join(',')}\n"
47
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
48
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
49
+ rfc822msg << "\n"
50
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
51
+ rfc822msg << "Message-Id: "
52
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{PROJ.ann_email[:domain]}>\n\n"
53
+ rfc822msg << File.read(PROJ.ann_file)
54
+
55
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
56
+ PROJ.ann_email[key]
57
+ end
58
+
59
+ params[3] = PROJ.email if params[3].nil?
60
+
61
+ if params[4].nil?
62
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
63
+ params[4] = STDIN.gets.chomp
64
+ end
65
+
66
+ ### send email
67
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
68
+ end
69
+ end # namespace :ann
70
+
71
+ desc 'Alias to ann:announcement'
72
+ task :ann => 'ann:announcement'
73
+
74
+ CLOBBER << PROJ.ann_file
75
+
76
+ # EOF
@@ -0,0 +1,22 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ desc "Enumerate all annotations"
6
+ task :notes do
7
+ Bones::AnnotationExtractor.enumerate(
8
+ PROJ, PROJ.annotation_tags.join('|'), :tag => true)
9
+ end
10
+
11
+ namespace :notes do
12
+ PROJ.annotation_tags.each do |tag|
13
+ desc "Enumerate all #{tag} annotations"
14
+ task tag.downcase.to_sym do
15
+ Bones::AnnotationExtractor.enumerate(PROJ, tag)
16
+ end
17
+ end
18
+ end
19
+
20
+ end # if HAVE_BONES
21
+
22
+ # EOF
data/tasks/bones.rake ADDED
@@ -0,0 +1,40 @@
1
+ # $Id$
2
+
3
+ require 'pp'
4
+ require 'stringio'
5
+
6
+ namespace :bones do
7
+
8
+ desc 'Show the PROJ open struct'
9
+ task :debug do |t|
10
+ atr = if ARGV.length == 2
11
+ t.application.top_level_tasks.pop
12
+ end
13
+ sio = StringIO.new
14
+ sep = "\n" + ' '*27
15
+ fmt = "%23s => %s"
16
+
17
+ if atr
18
+ PP.pp(PROJ.send(atr.to_sym), sio, 49)
19
+ sio.seek 0
20
+ val = sio.read
21
+ val = val.split("\n").join(sep)
22
+
23
+ puts fmt % [atr, val]
24
+ else
25
+ h = PROJ.instance_variable_get(:@table)
26
+ h.keys.map {|k| k.to_s}.sort.each do |k|
27
+ sio.truncate 0
28
+ PP.pp(h[k.to_sym], sio, 49)
29
+ sio.seek 0
30
+ val = sio.read
31
+ val = val.split("\n").join(sep)
32
+
33
+ puts fmt % [k, val]
34
+ end
35
+ end
36
+ end
37
+
38
+ end # namespace :bones
39
+
40
+ # EOF
data/tasks/doc.rake ADDED
@@ -0,0 +1,48 @@
1
+ # $Id$
2
+
3
+ require 'rake/rdoctask'
4
+
5
+ namespace :doc do
6
+
7
+ desc 'Generate RDoc documentation'
8
+ Rake::RDocTask.new do |rd|
9
+ rd.main = PROJ.rdoc_main
10
+ rd.rdoc_dir = PROJ.rdoc_dir
11
+
12
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
13
+ excl = Regexp.new(PROJ.rdoc_exclude.join('|'))
14
+ files = PROJ.files.find_all do |fn|
15
+ case fn
16
+ when excl; false
17
+ when incl; true
18
+ else false end
19
+ end
20
+ rd.rdoc_files.push(*files)
21
+
22
+ title = "#{PROJ.name}-#{PROJ.version} Documentation"
23
+ title = "#{PROJ.rubyforge_name}'s " + title if PROJ.rubyforge_name != title
24
+
25
+ rd.options << "-t #{title}"
26
+ rd.options.concat(PROJ.rdoc_opts)
27
+ end
28
+
29
+ desc 'Generate ri locally for testing'
30
+ task :ri => :clobber_ri do
31
+ sh "#{RDOC} --ri -o ri ."
32
+ end
33
+
34
+ task :clobber_ri do
35
+ rm_r 'ri' rescue nil
36
+ end
37
+
38
+ end # namespace :doc
39
+
40
+ desc 'Alias to doc:rdoc'
41
+ task :doc => 'doc:rdoc'
42
+
43
+ desc 'Remove all build products'
44
+ task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
45
+
46
+ remove_desc_for_task %w(doc:clobber_rdoc)
47
+
48
+ # EOF