From: James Edward Gray II Date: 2004-08-27T05:37:17+09:00 Subject: Code Critique Request I've mentioned it before, but if you don't know Perl programmers maintain a "Quiz of the Week". If you want to know more, the page is here: http://perl.plover.com/qotw/ This week's Regular Quiz (there also an Expert Quiz) came out last night. The curious can read it here: http://article.gmane.org/gmane.comp.lang.perl.qotw.quiz-of-the-week/105 *** SPOILER WARNING *** Stop reading this message if you read the Quiz and would like to solve it yourself, without seeing a solution first. Okay, now to my point, finally... I've solved the Quiz in Ruby. If you've seen my earlier posts, you know I'm brand new to Ruby. I've spent the last week and a half learning it and this is really my first attempt to put it to use. If any of you can spare the time, I would appreciate an honest review of the code I generated. I'm interested in any opinions you might have about constructs, style, whatever. I'm especially looking for things I'm handling in a non-Ruby fashion. Break my bad habits before they take hold... Thanks in advance for sharing your time. Here's the code: #!/usr/bin/ruby -w require "getoptlong" class Event attr_reader :category, :day, :month, :year, :name def Event.parse( string, cat ) if string =~ /^\s*(?:(\d+)\/)?(\d+)(?:\/(\d+))?\s+(.+?)\s*$/ return Event.new( cat, $4, $2, $1, $3 ) else return end end def initialize( cat, event, dd, mm = nil, yyyy = nil ) @category = cat @name = event @day = dd.to_i @month = mm.to_i @year = yyyy.to_i end def <=>( other ) if not year.zero? and not other.year.zero? and year != other.year return year <=> other.year elsif not month.zero? and not other.month.zero? and month != other.month return month <=> other.month else return day <=> other.day end end def between?( min, max ) times = [ min ] until times[-1].year == max.year and times[-1].month == max.month and times[-1].day == max.day times << times[-1] + (60 * 60 * 24) end result = times.find do | time | (year == 0 or year == time.year) and (month == 0 or month == time.month) and day == time.day end if result times.index result else return end end def date date = day.to_s unless month.zero? date = month.to_s + "/" + date end unless year.zero? date += "/" + year.to_s end return date end end delta = 7 GetoptLong.new( [ "-n", GetoptLong::REQUIRED_ARGUMENT ] ).each do | opt, arg | delta = arg.to_i if opt == "-n" end NOW = Time.now LIMIT = NOW + (delta * 24 * 60 * 60) OFFSETS = [ " ===>", " -->", " -->", " -->", "-->", "->", ">", "" ] DIR = File.join ENV["HOME"], '.upcoming'; events = { } Dir.foreach DIR do | file_name | next if file_name =~ /^\./ File.open File.join( DIR, file_name ) do | file | while line = file.gets e = Event.parse line, file_name if e events[file_name] = [ ] unless events.key? file_name events[file_name] << e end end end end puts events.each do | key, value | next unless value.find { | e | e.between? NOW, LIMIT } puts key value.sort.each do | e | offset = e.between? NOW, LIMIT next unless offset case offset when 0..7 printf "%-7s ", OFFSETS[offset] else printf "%-7s ", "(" + offset.to_s + ")" end printf "%-10s %s\n", e.date, e.name end puts end __END__ James Edward Gray II