From: Benjohn Barnes Date: 2006-06-13T15:25:48+09:00 Subject: [QUIZ part solution] Running Coach (#82) I thought that this problem was actually a lot more subtle than it seemed on the outside. Getting the coach to put together sensible and varied sentences seemed to be hard. I really wanted to find a much more elegant solution, perhaps some sort of template based approach; so far that has eluded me though. It seems to be something that doesn't easily factor down in to simple and clean functions. I had trouble, at least. Here's the chunk of code that I have - it's currently only for week 3! You could, of course, write a similar function for the other weeks, but there's _got_ to be a better way than that? def count_down(s, activity) # Encouragement for the last few seconds (which could get annoying on longer runs?). counts = { 10 => "10 more seconds.", 20 => "20 seconds to go.", 30 => "Half a minute to go.", 60 => "You have 1 more minute of #{activity} left.", 90 => "You have 1 and a half minutes of #{activity} to go."} # Add in encouragement / prompts for minutes. [2, 3, 4, 6, 8, 10, 12, 15, 20, 25, 30].each {|m| counts[m*60] = "You have #{m} minutes of #{activity} to go."} # Build an ordered array of the possible lengths of time, and find the index of this # activity's length. times = counts.keys.sort start_index = times.index(s); raise "#{s} is not a known time." unless start_index # Count down through the time prompts. I bet inject could do this too :) start_index.downto(0) do |i| this_time = times[i] next_time = i>0 ? times[i-1] : 0 delay_to_next = this_time - next_time message = counts[this_time] say message wait delay_to_next end end def say(to_say) system("say \"#{to_say}\"") end def wait(s) @wait_until ||= Time.now @wait_until += s while((w = @wait_until - Time.new) > 0) sleep w end end # For testing it's really helpful to redefine the above to... def say(m); puts m; end def wait(s); puts "Waiting for #{s} seconds."; end # Code to deal with just week 3! def week_3 wait(0) say "Start your first short run." count_down(90, 'running') say "Stop running now. You have 1 long run and two short ones left." count_down(90, 'walking') say "Start the first long run now." count_down(3*60, 'running') say "Stop running now. You have a short run and a long run left." count_down(3*60, 'walking') say "Start your second short run." count_down(90, 'running') say "Stop running. You have 1 more long run left." count_down(90, 'walking') say "Start your last run now." count_down(3*60, 'running') say "Stop running. After this walk, you will have finished." count_down(3*60, 'walking') say "Great! You've finished for today." end # Call week 3's code. week_3