From e12a7e69dce4081ac809fc11d83de5d7330269cf Mon Sep 17 00:00:00 2001 From: otherl Date: Sun, 29 Sep 2013 01:44:00 +0100 Subject: Fixed a bug that caused change times to not be used. Improved input parsing for line status. Refactored and improved parts of the code. --- blatube.rb | 62 +++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 23 deletions(-) (limited to 'blatube.rb') diff --git a/blatube.rb b/blatube.rb index 68806fd..f82869d 100644 --- a/blatube.rb +++ b/blatube.rb @@ -14,7 +14,7 @@ require 'json' debug = false help = false ops = nil -VERSION = 'v1.1.2' +VERSION = 'v1.2.0' INFINITY = 1 << 64 WEIGHTS = ['distance','peak_time','off_peak_time','unimpeded_time'] @@ -23,7 +23,7 @@ args = ARGV.dup options = OptionParser.new do |opts| opts.banner = "Usage: #{File.basename($0)} -h" - opts.on( '-s', '--status [LINE]', 'Get the current status of a tube line.' ) {|l| @line = l || 'summary' } + opts.on( '-s', '--status [LINE]', 'Get the current status of a tube line.' ) {|l| @line = l || 'SUMMARY' } opts.on( '-f', '--from-station STATION', 'Find route from this station.' ) {|f| @from_station = f } opts.on( '-t', '--to-station STATION', 'Find route to this station.' ) {|t| @to_station = t } opts.on( '-w', '--weight WEIGHT', 'Shortest route using either distance, peak_time, off_peak_time or unimpeded_time.' ) {|w| @weight = WEIGHTS.include?(w) ? w : 'peak_time' } @@ -56,6 +56,7 @@ end def calculate_shortest_route return unless interpret_user_input @shortest_route = [] + add_terminals calculate_routes traverse_route @to_station.upcase build_route_output @@ -68,28 +69,42 @@ def interpret_user_input return found_from_station && found_to_station end -def interpret stations, station +def interpret options, input found_station = false - if stations.include?(station.upcase) - found_station = true - elsif (most_likely = stations.map {|stat| stat.match("^#{station.upcase}.*") ? stat : nil}.compact) != [] + if options.include?(input.upcase) + found_input = true + elsif (most_likely = options.map {|option| option.match("^#{input.upcase}.*") ? option : nil}.compact) != [] if most_likely.size == 1 - station = most_likely.first - found_station = true + input = most_likely.first + found_input = true else - @output << "Did you mean: #{most_likely.map {|stat| stat.split(' ').map {|word| word.capitalize}.join(' ')}.join(', ')}?" + @output << "Did you mean: #{most_likely.map {|option| option.split(' ').map {|word| word.capitalize}.join(' ')}.join(', ')}?" end - elsif (less_likely = stations.map {|stat| stat.match(".*#{station.upcase}.*") ? stat : nil}.compact) != [] + elsif (less_likely = options.map {|option| option.match(".*#{input.upcase}.*") ? option : nil}.compact) != [] if less_likely.size == 1 - station = less_likely.first - found_station = true + input = less_likely.first + found_input = true else - @output << "Did you mean: #{less_likely.map {|stat| stat.split(' ').map {|word| word.capitalize}.join(' ')}.join(', ')}?" + @output << "Did you mean: #{less_likely.map {|option| option.split(' ').map {|word| word.capitalize}.join(' ')}.join(', ')}?" end else - @output << "Could not find a matching station for '#{station}'." + @output << "Could not find a match for '#{input}'." + end + return found_input, input +end + +def add_terminals + @graph.find_all {|station, data| station.match /^#{@to_station.upcase}_|^#{@from_station.upcase}_/}.each do |station, data| + if station.match @from_station.upcase + @graph[station][@from_station.upcase] = {'line' => station.split('_')[1], 'direction' => nil, 'distance' => 0, 'unimpeded_time' => 0, 'peak_time' => 0, 'off_peak_time' => 0} + @graph[@from_station.upcase] ||= {} + @graph[@from_station.upcase][station] = {'line' => station.split('_')[1], 'direction' => nil, 'distance' => 0, 'unimpeded_time' => 0, 'peak_time' => 0, 'off_peak_time' => 0} + elsif station.match @to_station.upcase + @graph[station][@to_station.upcase] = {'line' => station.split('_')[1], 'direction' => nil, 'distance' => 0, 'unimpeded_time' => 0, 'peak_time' => 0, 'off_peak_time' => 0} + @graph[@to_station.upcase] ||= {} + @graph[@to_station.upcase][station] = {'line' => station.split('_')[1], 'direction' => nil, 'distance' => 0, 'unimpeded_time' => 0, 'peak_time' => 0, 'off_peak_time' => 0} + end end - return found_station, station end def calculate_routes @@ -145,10 +160,10 @@ end def build_route_output line_colours = @colour ? YAML::load(File.open('line_colours.yaml')) : Hash.new('') verbose_route = '' - pairs = @shortest_route.pairs + pairs = @shortest_route[1..-2].pairs from,to = pairs.first current_line = @graph[from][to]['line'] - verbose_route << "#{line_colours[current_line]}#{from} - #{current_line} (#{@graph[from][to]['direction']})" + verbose_route << "#{line_colours[current_line]}#{from.split('_')[0]} - #{current_line} (#{@graph[from][to]['direction']})" pairs[1..-2].each do |from,to| next if (new_line = @graph[from][to]['line']) == current_line || @graph[from][to]['direction'] == nil current_line = new_line @@ -163,7 +178,7 @@ def build_route_output from_1 = from_s[0..(from_s.length/2.0 - 1)] from_2 = from_s[(from_s.length/2.0)..-1] verbose_route << " - #{from_1}#{line_colours['reset_colour']}#{line_colours[new_line]}#{from_2} - #{new_line} (#{@graph[from][to]['direction']})" unless new_line == current_line - verbose_route << " - #{to}#{line_colours['reset_colour']}" + verbose_route << " - #{to.split('_')[0]}#{line_colours['reset_colour']}" @output << verbose_route if @weight == 'distance' @output << "Distance: #{@distances[@to_station.upcase].round(2)} km" @@ -177,14 +192,15 @@ end def get_line_status xml = Nokogiri::HTML(open('http://cloud.tfl.gov.uk/TrackerNet/LineStatus')).remove_namespaces! sorted_lines = xml.xpath('//linestatus').sort_by {|xml| xml.xpath('.//line/@name').text} - if @line && @line != 'summary' - l_s_xml = nil - sorted_lines.each {|xml| l_s_xml = xml and break if xml.xpath('.//line/@name').text.upcase.match @line.upcase} - @output << ("#{l_s_xml.xpath('.//line/@name').text}: #{l_s_xml.xpath('.//status/@description').text}. #{l_s_xml.xpath('./@statusdetails').text}" rescue "Could not find a line matching '#{@line}'") - else + found_line, line = interpret sorted_lines.map{|xml| xml.xpath('.//line/@name').text.upcase} << 'SUMMARY', @line.upcase + return unless found_line + if @line == 'SUMMARY' line_summary = '' sorted_lines.each {|xml| line_summary << "#{xml.xpath('.//line/@name').text}: #{xml.xpath('./@statusdetails').text} " unless xml.xpath('./@statusdetails').text == ''} @output << (line_summary == '' ? 'Good Serice on all lines.' : "#{line_summary}Good Service on all other lines.") + else + l_s_xml = sorted_lines.find {|xml| xml.xpath('.//line/@name').text.upcase.match line} + @output << ("#{l_s_xml.xpath('.//line/@name').text}: #{l_s_xml.xpath('.//status/@description').text}. #{l_s_xml.xpath('./@statusdetails').text}") end end -- cgit v1.2.3