Implement LinePad for easy line selection
[pywienerlinien] / itip
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from gotovienna import argparse
5 from gotovienna.utils import *
6 from gotovienna.realtime import *
7 from datetime import time
8
9 parser = argparse.ArgumentParser(description='Get realtime public transport information for Vienna')
10 parser.add_argument('line', nargs='?', help='line name (e.g. 59A)')
11 parser.add_argument('station', nargs='?', help='station name (e.g. Karlsplatz)')
12
13 args = parser.parse_args()
14
15 itip = ITipParser()
16
17 if args.line:
18     # Convert line name to uppercase (e.g. 'u4' -> 'U4')
19     args.line = args.line.upper()
20
21 if args.station:
22     args.station = args.station.decode('utf-8')
23
24 if args.line in itip.lines:
25     ITEM_WIDTH = 33
26     ITEM_SPACING = 4
27
28     # FIXME: change get_stations() to return (headers, stations) directly
29     stations = sorted(itip.get_stations(args.line).items())
30     headers, stations = zip(*stations)
31
32     maxlength = max(len(stops) for stops in stations)
33     for stops in stations:
34         # Pad station list with empty items for printing, so that
35         # different-sized lists aren't truncated (with zip below)
36         stops.extend([('', '')] * (maxlength - len(stops)))
37
38     stations_table = zip(*stations)
39     fmt = '%%-%ds' % ITEM_WIDTH
40     spacer = ' ' * ITEM_SPACING
41
42     print
43     print spacer, spacer.join(inblue(fmt % ('Richtung %s' % name))
44             for name in headers)
45     print spacer, spacer.join('-' * ITEM_WIDTH for name in headers)
46
47     def match_station(query, station):
48         return query and station and (query.lower() in station.lower())
49
50     for row in stations_table:
51         print spacer, spacer.join(ingreen(fmt % name)
52                 if match_station(args.station, name)
53                 else fmt % name
54                 for name, url in row)
55     print
56
57     # Get matching stations
58     stations = zip(headers, stations)
59     details = [(direction, name, url) for direction, stops in stations
60             for name, url in stops if match_station(args.station, name)]
61
62     # User entered a station, but no matches were found
63     if args.station and not details:
64         print inred('No station matched your query.')
65         print
66
67     # Format a departure time (in minutes from now) for display
68     def format_departure(departure):
69         minutes = departure['time']
70         if type(minutes) == time:
71             return inblue(minutes.strftime('%H:%M'))
72         elif minutes == 0:
73             return inred('now')
74         elif minutes == 1:
75             return inblue('1') + ' min'
76         else:
77             return inblue('%d' % minutes) + ' mins'
78
79     # Print the departure times for all matched stations
80     for direction, name, url in details:
81         print ingreen(name), '->', inblue(direction)
82
83         departures = itip.get_departures(url)
84         if departures:
85             print '  Next departures:', ', '.join(format_departure(x)
86                     for x in departures)
87         else:
88             print '  No departure information.'
89         print
90 else:
91     ITEMS_PER_LINE = 12
92     ITEM_WIDTH = 5
93     LINE_WIDTH = (ITEMS_PER_LINE * ITEM_WIDTH + ITEMS_PER_LINE)
94
95     if args.line:
96         print
97         print inred('The given line was not found. Valid lines:')
98
99     print
100     for label, remaining in categorize_lines(itip.lines):
101         prefix, fill, postfix = '|== ', '=', '==- -'
102         before, after = prefix + label + ' ', postfix
103         padding = LINE_WIDTH - len(before + after)
104         before = before.replace(label, inblue(label))
105         print ''.join((before, fill * padding, after))
106
107         while remaining:
108             this_row = [remaining.pop(0) for _ in
109                     range(min(len(remaining), ITEMS_PER_LINE))]
110             print ' '.join(('%%%ds' % ITEM_WIDTH) % x for x in this_row)
111
112         print