summaryrefslogtreecommitdiff
path: root/blatube.rb
diff options
context:
space:
mode:
Diffstat (limited to 'blatube.rb')
-rw-r--r--blatube.rb62
1 files changed, 39 insertions, 23 deletions
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