#!/usr/bin/env python # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 # Copyright (c) 2007 Heikki Toivonen # # MultiListbox Copyright: # Brent Burley 2001 # Pedro Werneck 2003 # Heikki Toivonen 2007 # # CaltrainPy 0.1 # # Caltrain schedule for systems that have Python and Tkinter, for # example Windows Mobile. # # Tested on Cingular 8525 running Windows Mobile 5 and Python 2.5+Tkinter. # # My installation: # Download PythonCE 2.5 and Tkinter from: # http://pythonce.sourceforge.net/Wikka/HomePage # Installed Python 2.5 onto storage card without a problem. Then # downloaded Tkinter, unzipped on PC, and copied files as follows: # * DLLs from Windows directory to device's \Windows directory # * From tcl8.4.3 directory copied library and tk8.4 directories into # storage card's Program Files directory (siblings of Python25) # Made CaltrainPy directory, a sibling of Python25 and placed caltrain.py # there. Launched caltrain.py by clicking on it in Explorer. # # BUGS/TODO # * Weekend/Holiday, change From station to San Jose, click Northbound # => From-To reset # * Fullscreen # * Fit the screen ;) # * Respond to OK on Windows Mobile # * Legend # * am/pm indicators # * bullet & express indicators # * About # * Show only trains that stop at selected stations # * Map # ... import array import _tkinter # Seems to help some with DLL load problems from Tkinter import * # Constant strings weekday = "Mon-Fri" weekend = "Weekend/Holiday" northbound = "Northbound" southbound = "Southbound" trainNumber = "Train No." service = { weekday: {northbound:None, southbound:None}, weekend: {northbound:None, southbound:None}, } stations = { weekday: {northbound:None, southbound:None}, weekend: {northbound:None, southbound:None}, } # To get the service & stations: # 1. Open HTML in OpenOffice.org writer, copy a schedule table, and paste into # text program like Emacs. Save file. # 2. Ensure that train number ends on a singe line, same with scheduled times # 3. Run the following script, and copy the output here. """ stations = [] timetables = {} station = "" for line in open("timetable.txt"): line = line.strip() line = line.replace('-', '') line = line.replace('\xa0', ' ') if line and line[0].isalpha(): station = line if station != "Train No.": stations.append(station) continue if timetables.get(station, None) is None: timetables[station] = [] timetables[station].append(line) print timetables print stations """ service[weekday][northbound] = {'Santa Clara': ['4:35', '5:10', '', '6:02', '', '6:27', '', '', '7:02', '', '7:25', '', '', '8:02', '', '8:27', '8:45', '9:15', '9:45', '10:15', '10:45', '11:15', '11:45', '12:15', '12:45', '1:15', '1:45', '2:15', '2:45', '3:12', '3:49', '4:10', '', '4:44', '', '5:10', '', '', '5:44', '', '6:10', '', '', '', '6:55', '8:15', '9:15', '10:35'], 'Hayward Park': ['5:22', '5:57', '', '', '', '7:05', '', '', '', '', '8:05', '', '', '', '', '9:05', '', '10:02', '', '11:02', '', '12:02', '', '1:02', '', '2:02', '', '3:02', '', '3:59', '', '4:45', '', '', '', '5:45', '', '', '', '', '6:45', '', '', '', '7:42', '9:02', '10:02', '11:22'], 'San Francisco': ['6:01', '6:36', '6:42', '7:19', '7:02', '7:48', '7:42', '7:57', '8:19', '8:02', '8:48', '8:42', '8:57', '9:19', '9:02', '9:45', '10:02', '10:41', '11:02', '11:41', '12:02', '12:41', '1:02', '1:41', '2:02', '2:41', '3:02', '3:41', '4:02', '4:38', '5:03', '5:29', '5:24', '6:02', '5:44', '6:29', '6:24', '6:39', '7:02', '6:44', '7:29', '7:24', '7:39', '8:00', '8:21', '9:41', '10:41', '12:01'], 'San Martin': ['', '', '', '', '', '', '', '', '6:16', '', '6:39', '', '', '7:14', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 'San Mateo': ['5:25', '6:00', '', '', '6:39', '7:08', '', '7:32', '', '7:39', '8:08', '', '8:32', '', '8:39', '9:08', '9:33', '10:05', '10:33', '11:05', '11:33', '12:05', '12:33', '1:05', '1:33', '2:05', '2:33', '3:05', '3:33', '4:02', '4:36', '4:48', '', '5:36', '', '5:48', '', '6:12', '6:36', '', '6:48', '', '7:12', '7:32', '7:45', '9:05', '10:05', '11:25'], 'Blossom Hill': ['', '', '', '', '', '', '', '', '6:35', '', '6:58', '', '', '7:33', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 'College Park': ['', '', '', '', '', '', '', '', '', '', '', '', '', '7:58', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '3:08', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 'Lawrence': ['4:40', '5:15', '', '6:12', '', '', '', '', '7:12', '', '7:30', '', '', '8:12', '', '', '8:50', '9:20', '9:50', '10:20', '10:50', '11:20', '11:50', '12:20', '12:50', '1:20', '1:50', '2:20', '2:50', '3:17', '3:54', '', '', '4:52', '', '', '', '5:39', '5:52', '', '', '', '6:39', '6:53', '7:00', '8:20', '9:20', '10:40'], 'Burlingame': ['5:28', '6:03', '', '', '', '7:11', '', '7:35', '', '', '8:11', '', '8:35', '', '', '9:11', '9:36', '10:08', '10:36', '11:08', '11:36', '12:08', '12:36', '1:08', '1:36', '2:08', '2:36', '3:08', '3:36', '4:05', '', '4:51', '', '', '', '5:51', '', '6:15', '', '', '6:51', '', '7:15', '7:35', '7:48', '9:08', '10:08', '11:28'], 'Mountain View': ['4:49', '5:24', '5:57', '6:23', '', '6:37', '6:57', '7:05', '7:23', '', '7:37', '7:57', '8:05', '8:23', '', '8:37', '8:59', '9:29', '9:59', '10:29', '10:59', '11:29', '11:59', '12:29', '12:59', '1:29', '1:59', '2:29', '2:59', '3:26', '4:03', '', '4:37', '5:03', '4:58', '', '5:37', '5:46', '6:03', '5:58', '', '6:37', '6:46', '7:00', '7:09', '8:29', '9:29', '10:49'], '22nd Street': ['5:52', '6:27', '', '', '', '7:40*', '', '', '', '', '8:40*', '', '', '', '', '9:37', '', '10:32', '', '11:32', '', '12:32', '', '1:32', '', '2:32', '', '3:32', '', '4:29', '4:55', '5:21*', '5:17', '5:55', '5:37', '6:21*', '6:17', '', '6:55', '6:37', '7:21*', '7:17', '', '7:53', '8:12', '9:32', '10:32', '11:52'], 'Bayshore': ['5:47', '6:22', '', '', '', '7:33*', '', '', '', '', '8:33*', '', '', '', '', '9:31', '', '10:27', '', '11:27', '', '12:27', '', '1:27', '', '2:27', '', '3:27', '', '4:24', '', '5:13*', '', '', '', '6:13*', '', '', '', '', '7:13*', '', '', '', '8:07', '9:27', '10:27', '11:47'], 'San Antonio': ['4:53', '5:28', '', '6:27', '', '', '', '', '7:27', '', '', '', '', '8:27', '', '', '9:03', '9:33', '10:03', '10:33', '11:03', '11:33', '12:03', '12:33', '1:03', '1:33', '2:03', '2:33', '3:03', '3:30', '4:07', '', '', '5:07', '', '', '', '', '6:07', '', '', '', '', '', '7:13', '8:33', '9:33', '10:53'], 'Millbrae': ['5:33', '6:08', '6:24', '6:59', '6:45', '7:17', '7:24', '', '7:59', '7:45', '8:17', '8:24', '', '8:59', '8:45', '9:17', '9:41', '10:13', '10:41', '11:13', '11:41', '12:13', '12:41', '1:13', '1:41', '2:13', '2:41', '3:13', '3:41', '4:10', '4:43', '4:57', '5:05', '5:43', '5:25', '5:57', '6:05', '', '6:43', '6:25', '6:57', '7:05', '', '7:41', '7:53', '9:13', '10:13', '11:33'], 'San Carlos': ['5:13', '5:48', '', '', '', '6:55', '', '7:24', '', '', '7:55', '', '8:24', '', '', '8:55', '9:23', '9:53', '10:23', '10:53', '11:23', '11:53', '12:23', '12:53', '1:23', '1:53', '2:23', '2:53', '3:23', '3:50', '4:29', '4:35', '', '5:29', '', '5:35', '', '6:04', '6:29', '', '6:35', '', '7:04', '7:23', '7:33', '8:53', '9:53', '11:13'], 'Train No.': ['101', '103', '305', '207', '309', '211', '313', '215', '217', '319', '221', '323', '225', '227', '329', '231', '233', '135', '237', '139', '241', '143', '245', '147', '249', '151', '253', '155', '257', '159', '261', '263', '365', '267', '369', '271', '373', '275', '277', '379', '281', '383', '285', '287', '189', '191', '193', '195#'], 'Menlo Park': ['5:04', '5:39', '', '6:39', '', '6:45', '', '', '7:39', '', '7:45', '', '', '8:39', '', '8:45', '9:14', '9:44', '10:14', '10:44', '11:14', '11:44', '12:14', '12:44', '1:14', '1:44', '2:14', '2:44', '3:14', '3:41', '4:19', '', '4:46', '5:19', '', '', '5:46', '5:57', '6:19', '', '', '6:46', '6:57', '7:13', '7:24', '8:44', '9:44', '11:04'], 'San Jose': ['4:30', '5:05', '5:45', '5:57', '6:03', '6:22', '6:45', '6:50', '6:57', '7:03', '7:20', '7:45', '7:50', '7:55', '8:03', '8:22', '8:40', '9:10', '9:40', '10:10', '10:40', '11:10', '11:40', '12:10', '12:40', '1:10', '1:40', '2:10', '2:40', '3:05', '3:44', '4:05', '4:25', '4:39', '4:45', '5:05', '5:25', '5:31', '5:39', '5:45', '6:05', '6:25', '6:31', '6:45', '6:50', '8:10', '9:10', '10:30'], 'Hillsdale': ['5:19', '5:54', '6:16', '6:51', '', '7:02', '7:16', '7:28', '7:51', '', '8:02', '8:16', '8:28', '8:51', '', '9:02', '9:29', '9:59', '10:29', '10:59', '11:29', '11:59', '12:29', '12:59', '1:29', '1:59', '2:29', '2:59', '3:29', '3:56', '', '4:42', '', '', '5:17', '5:42', '', '6:08', '', '6:17', '6:42', '', '7:08', '7:28', '7:39', '8:59', '9:59', '11:19'], 'Sunnyvale': ['4:44', '5:19', '', '6:18', '6:13', '', '', '7:00', '7:18', '7:13', '', '', '8:00', '8:18', '8:13', '', '8:54', '9:24', '9:54', '10:24', '10:54', '11:24', '11:54', '12:24', '12:54', '1:24', '1:54', '2:24', '2:54', '3:21', '3:58', '', '', '4:58', '', '', '', '', '5:58', '', '', '', '', '', '7:04', '8:24', '9:24', '10:44'], 'Palo Alto': ['5:01', '5:36', '6:05', '6:36', '6:23', '', '7:05', '7:16', '7:36', '7:23', '', '8:05', '8:16', '8:36', '8:23', '', '9:11', '9:41', '10:11', '10:41', '11:11', '11:41', '12:11', '12:41', '1:11', '1:41', '2:11', '2:41', '3:11', '3:38', '4:16', '4:24', '', '5:16', '5:06', '5:24', '', '5:54', '6:16', '6:06', '6:24', '', '6:54', '7:10', '7:21', '8:41', '9:41', '11:01'], 'Redwood City': ['5:09', '5:44', '', '6:45@', '6:30', '6:51@', '', '', '7:45@', '7:30', '7:51@', '', '', '8:45@', '8:30', '8:51@', '9:19', '9:49', '10:19', '10:49', '11:19', '11:49', '12:19', '12:49', '1:19', '1:49', '2:19', '2:49', '3:19', '3:46', '4:25@', '4:31@', '4:52', '5:25@', '', '5:31@', '5:52', '', '6:25@', '', '6:31@', '6:52', '', '7:19', '7:29', '8:49', '9:49', '11:09'], 'San Bruno': ['5:37', '6:12', '', '', '', '7:21', '', '7:42', '', '', '8:21', '', '8:42', '', '', '9:21', '9:45', '10:17', '10:45', '11:17', '11:45', '12:17', '12:45', '1:17', '1:45', '2:17', '2:45', '3:17', '3:45', '4:14', '', '5:01', '', '', '', '6:01', '', '6:22', '', '', '7:01', '', '7:22', '', '7:57', '9:17', '10:17', '11:37'], 'So. San Francisco': ['5:41', '6:16', '', '7:05', '', '7:25', '', '', '8:05', '', '8:25', '', '', '9:05', '', '9:25', '', '10:21', '', '11:21', '', '12:21', '', '1:21', '', '2:21', '', '3:21', '', '4:18', '', '5:05', '', '', '', '6:05', '', '', '', '', '7:05', '', '', '', '8:01', '9:21', '10:21', '11:41'], 'Capitol': ['', '', '', '', '', '', '', '', '6:41', '', '7:04', '', '', '7:39', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 'Morgan Hill': ['', '', '', '', '', '', '', '', '6:22', '', '6:45', '', '', '7:20', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 'Belmont': ['5:16', '5:51', '', '', '', '6:58', '', '', '', '', '7:58', '', '', '', '', '8:58', '9:26', '9:56', '10:26', '10:56', '11:26', '11:56', '12:26', '12:56', '1:26', '1:56', '2:26', '2:56', '3:26', '3:53', '', '4:38', '', '', '', '5:38', '', '', '', '', '6:38', '', '', '', '7:36', '8:56', '9:56', '11:16'], 'Tamien': ['', '4:58', '', '5:50', '5:56', '', '', '', '6:49', '6:56', '7:12', '', '', '7:47', '7:56', '', '8:33', '', '9:33', '', '10:33', '', '11:33', '', '12:33', '', '1:33', '', '2:33', '', '3:37', '3:58', '', '4:32', '', '4:58', '', '', '5:32', '', '5:58', '', '6:24', '', '', '8:03', '9:03', ''], 'California Ave': ['4:57', '5:32', '', '6:31', '', '', '', '7:11', '7:31', '', '', '', '8:11', '8:31', '', '', '9:07', '9:37', '10:07', '10:37', '11:07', '11:37', '12:07', '12:37', '1:07', '1:37', '2:07', '2:37', '3:07', '3:34', '4:11', '', '', '5:11', '', '', '', '', '6:11', '', '', '', '', '7:06', '7:17', '8:37', '9:37', '10:57'], 'Gilroy': ['', '', '', '', '', '', '', '', '6:07', '', '6:30', '', '', '7:05', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']} stations[weekday][northbound] = ['Gilroy', 'San Martin', 'Morgan Hill', 'Blossom Hill', 'Capitol', 'Tamien', 'San Jose', 'College Park', 'Santa Clara', 'Lawrence', 'Sunnyvale', 'Mountain View', 'San Antonio', 'California Ave', 'Palo Alto', 'Menlo Park', 'Redwood City', 'San Carlos', 'Belmont', 'Hillsdale', 'Hayward Park', 'San Mateo', 'Burlingame', 'Millbrae', 'San Bruno', 'So. San Francisco', 'Bayshore', '22nd Street', 'San Francisco'] service[weekday][southbound] = {'Santa Clara': ['6:17', '6:47', '', '7:34', '7:56*', '', '', '', '8:34', '8:56*', '', '', '', '9:34', '9:56*', '', '10:29', '10:51', '11:29', '11:51', '12:29', '12:51', '13:29', '1:51', '2:29', '2:51', '3:29', '3:51', '4:29', '4:51', '', '', '5:47', '', '6:08*', '', '', '6:48', '', '7:08*', '', '7:47', '', '8:04', '8:42', '9:47', '11:22', '1:23'], 'Hayward Park': ['5:29', '5:59', '', '6:58', '', '', '', '', '7:58', '', '', '', '', '8:58', '', '', '9:41', '', '10:41', '', '11:41', '', '12:41', '', '1:41', '', '2:41', '', '3:41', '', '', '', '5:07', '', '', '', '', '6:07', '', '', '', '7:07', '', '', '7:54', '8:59', '10:34', '12:35'], 'San Martin': ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '5:17', '', '', '', '', '', '6:54', '', '', '7:34', '', '', '', '', '', '', '', '', '', ''], 'San Francisco': ['4:55', '5:25', '6:11', '6:24', '6:44', '6:59', '7:14', '7:19', '7:24', '7:44', '7:59', '8:14', '8:19', '8:24', '8:44', '8:59', '9:07', '9:37', '10:07', '10:37', '11:07', '11:37', '12:07', '12:37', '1:07', '1:37', '2:07', '2:37', '3:07', '3:37', '4:09', '4:19', '4:27', '4:33', '4:56', '5:14', '5:20', '5:27', '5:33', '5:56', '6:14', '6:27', '6:33', '6:56', '7:20', '8:25', '10:00', '12:01'], 'San Mateo': ['5:26', '5:56', '6:36', '6:55', '7:07', '', '', '7:42', '7:55', '8:07', '', '', '8:42', '8:55', '9:07', '', '9:38', '10:02', '10:38', '11:02', '11:38', '12:02', '12:38', '1:02', '1:38', '2:02', '2:38', '3:02', '3:38', '4:02', '', '4:42', '5:04', '4:57', '', '', '5:43', '6:04', '5:57', '', '', '7:04', '6:57', '', '7:51', '8:56', '10:31', '12:32'], 'San Carlos': ['5:38', '6:08', '6:44', '7:07', '7:13', '', '', '7:50', '8:07', '8:13', '', '', '8:50', '9:07', '9:13', '', '9:50', '10:12', '10:50', '11:12', '11:50', '12:12', '12:50', '1:12', '1:50', '2:12', '2:50', '3:12', '3:50', '4:12', '', '4:51', '5:18', '', '', '', '5:52', '6:18', '', '', '', '7:18', '', '', '8:03', '9:08', '10:43', '12:44'], 'College Park': ['', '', '', '', '7:59*', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '4:32', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''], 'Lawrence': ['6:12', '6:42', '7:12', '', '7:49*', '', '', '8:16', '', '8:49*', '', '', '9:16', '', '9:49*', '', '10:24', '10:46', '11:24', '11:46', '12:24', '12:46', '13:24', '1:46', '2:24', '2:46', '3:24', '3:46', '4:24', '4:46', '', '', '', '', '6:01*', '', '', '6:43', '', '7:01*', '', '', '', '7:59', '8:37', '9:42', '11:17', '1:18'], 'Burlingame': ['5:23', '5:53', '6:33', '6:52', '', '', '', '7:38', '7:52', '', '', '', '8:38', '8:52', '', '', '9:35', '9:59', '10:35', '10:59', '11:35', '11:59', '12:35', '12:59', '1:35', '1:59', '2:35', '2:59', '3:35', '3:59', '', '4:38', '5:00', '', '', '', '5:39', '6:00', '', '', '', '7:00', '', '', '7:48', '8:53', '10:28', '12:29'], 'Mountain View': ['6:03', '6:33', '7:07', '', '7:38', '7:44', '7:58', '8:09', '', '8:38', '8:44', '8:58', '9:09', '', '9:38', '9:44', '10:15', '10:37', '11:15', '11:37', '12:15', '12:37', '13:15', '1:37', '2:15', '2:37', '3:15', '3:37', '4:15', '4:37', '4:51', '5:11', '5:36', '', '5:50', '5:56', '6:12', '6:36', '', '6:50', '6:56', '7:36', '', '7:50', '8:28', '9:33', '11:08', '1:09'], '22nd Street': ['5:00', '5:30', '6:16', '6:29', '6:49', '7:04', '7:19', '', '7:29', '7:49', '8:04', '8:19', '', '8:29', '8:49', '9:04', '9:12', '', '10:12', '', '11:12', '', '12:12', '', '1:12', '', '2:12', '', '3:12', '', '', '', '4:32', '', '', '', '', '5:32', '', '', '', '6:32', '', '', '7:25', '8:30', '10:05', '12:06'], 'Bayshore': ['5:05', '5:35', '', '6:34', '', '', '', '', '7:34', '', '', '', '', '8:34', '', '', '9:17', '', '10:17', '', '11:17', '', '12:17', '', '1:17', '', '2:17', '', '3:17', '', '', '', '4:40', '', '', '', '', '5:40', '', '', '', '6:40', '', '', '7:30', '8:35', '10:10', '12:11'], 'San Antonio': ['5:59', '6:29', '', '', '7:34', '', '', '', '', '8:34', '', '', '', '', '9:34', '', '10:11', '10:33', '11:11', '11:33', '12:11', '12:33', '13:11', '1:33', '2:11', '2:33', '3:11', '3:33', '4:11', '4:33', '', '', '', '', '5:46', '', '', '', '', '6:46', '', '', '', '7:46', '8:24', '9:29', '11:04', '1:05'], 'Millbrae': ['5:19', '5:49', '6:29', '6:48', '7:01', '7:17', '7:32', '', '7:48', '8:01', '8:17', '8:32', '', '8:48', '9:01', '9:17', '9:31', '9:55', '10:31', '10:55', '11:31', '11:55', '12:31', '12:55', '1:31', '1:55', '2:31', '2:55', '3:31', '3:55', '4:25', '', '4:56', '4:49', '5:14', '5:30', '', '5:56', '5:49', '6:14', '6:30', '6:56', '6:49', '7:14', '7:44', '8:49', '10:24', '12:25'], 'Blossom Hill': ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '4:58', '', '', '', '', '', '6:35', '', '', '7:15', '', '', '', '', '', '', '', '', '', ''], 'Train No.': ['102', '104', '206', '208', '210', '312', '314', '216', '218', '220', '322', '324', '226', '228', '230', '332', '134', '236', '138', '240', '142', '244', '146', '248', '150', '252', '154', '256', '158', '260', '362', '264', '266', '368', '270', '372', '274', '276', '378', '280', '382', '284', '386', '288', '190', '192', '194', '196'], 'Menlo Park': ['5:48', '6:18', '6:54', '', '7:23', '7:35', '', '7:58', '', '8:23', '8:35', '', '8:58', '', '9:23', '9:35', '10:00', '10:22', '11:00', '11:22', '12:00', '12:22', '13:00', '1:22', '2:00', '2:22', '3:00', '3:22', '4:00', '4:22', '', '', '5:28', '', '5:34', '', '', '6:28', '', '6:34', '', '7:28', '', '7:34', '8:13', '9:18', '10:53', '12:54'], 'San Jose': ['6:26', '6:56', '7:24', '7:43', '8:06', '7:58', '8:13', '8:28', '8:43', '9:05', '8:58', '9:13', '9:28', '9:43', '10:05', '9:58', '10:38', '11:00', '11:38', '12:00', '12:38', '1:00', '1:38', '2:00', '2:38', '3:00', '3:38', '4:00', '4:39', '5:00', '5:06', '5:27', '5:55', '5:32', '6:16', '6:11', '6:28', '6:56', '6:32', '7:16', '7:11', '7:55', '7:32', '8:12', '8:51', '9:56', '11:31', '1:32'], 'Hillsdale': ['5:32', '6:02', '6:40', '7:01', '', '', '7:40', '7:46', '8:01', '', '', '8:40', '8:46', '9:01', '', '', '9:44', '10:06', '10:44', '11:06', '11:44', '12:06', '12:44', '1:06', '1:44', '2:06', '2:44', '3:06', '3:44', '4:06', '4:33', '4:47', '5:11', '', '5:22', '5:38', '5:48', '6:11', '', '6:22', '6:38', '7:11', '', '7:22', '7:57', '9:02', '10:37', '12:38'], 'Sunnyvale': ['6:08', '6:38', '', '', '7:43', '', '', '', '', '8:43', '', '', '', '', '9:43', '', '10:20', '10:42', '11:20', '11:42', '12:20', '12:42', '13:20', '1:42', '2:20', '2:42', '3:20', '3:42', '4:20', '4:42', '', '5:16', '', '5:21', '5:55', '', '6:17', '', '6:21', '6:55', '', '', '7:21', '7:55', '8:33', '9:38', '11:13', '1:14'], 'Palo Alto': ['5:51', '6:21', '6:57', '7:18', '7:26', '', '7:51', '8:01', '8:18', '8:26', '', '8:51', '9:01', '9:18', '9:26', '', '10:03', '10:25', '11:03', '11:25', '12:03', '12:25', '13:03', '1:25', '2:03', '2:25', '3:03', '3:25', '4:03', '4:25', '4:44', '5:01', '', '5:12', '5:38', '5:49', '6:02', '', '6:12', '6:38', '6:49', '', '7:12', '7:38', '8:16', '9:21', '10:56', '12:57'], 'Redwood City': ['5:43', '6:13', '6:49', '7:12@', '7:18@', '7:30', '', '', '8:12@', '8:18@', '8:30', '', '', '9:12@', '9:18@', '9:30', '9:55', '10:17', '10:55', '11:17', '11:55', '12:17', '12:55', '1:17', '1:55', '2:17', '2:55', '3:17', '3:55', '4:17', '', '', '5:22@', '5:06', '5:28@', '', '', '6:22@', '6:06', '6:28@', '', '7:22@', '7:06', '7:28@', '8:08', '9:13', '10:48', '12:49'], 'San Bruno': ['5:15', '5:45', '', '6:44', '', '', '', '7:33', '7:44', '', '', '', '8:33', '8:44', '', '', '9:27', '9:51', '10:27', '10:51', '11:27', '11:51', '12:27', '12:51', '1:27', '1:51', '2:27', '2:51', '3:27', '3:51', '', '4:33', '4:52', '', '', '', '5:34', '5:52', '', '', '', '6:52', '', '', '7:40', '8:45', '10:20', '12:21'], 'So. San Francisco': ['5:11', '5:41', '', '6:40', '', '', '', '', '7:40', '', '', '', '', '8:40', '', '', '9:23', '', '10:23', '', '11:23', '', '12:23', '', '1:23', '', '2:23', '', '3:23', '', '', '', '4:48', '', '5:08', '', '', '5:48', '', '6:08', '', '6:48', '', '7:08', '7:36', '8:41', '10:16', '12:17'], 'Capitol': ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '4:52', '', '', '', '', '', '6:29', '', '', '7:09', '', '', '', '', '', '', '', '', '', ''], 'Morgan Hill': ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '5:11', '', '', '', '', '', '6:48', '', '', '7:28', '', '', '', '', '', '', '', '', '', ''], 'Belmont': ['5:35', '6:05', '', '7:04', '', '', '', '', '8:04', '', '', '', '', '9:04', '', '', '9:47', '10:09', '10:47', '11:09', '11:47', '12:09', '12:47', '1:09', '1:47', '2:09', '2:47', '3:09', '3:47', '4:09', '', '', '5:14', '', '', '', '', '6:14', '', '', '', '7:14', '', '', '8:00', '9:05', '10:40', '12:41'], 'Tamien': ['', '7:03', '', '7:50', '8:13', '', '', '', '8:50', '9:12', '', '', '', '9:50', '10:12', '', '', '11:07', '', '12:07', '', '1:07', '', '2:07', '', '3:07', '', '4:07', '4:45', '5:07', '', '', '', '5:39', '6:22', '', '', '7:02', '6:39', '7:23', '', '', '7:39', '8:19', '', '10:03', '11:38', ''], 'California Ave': ['5:55', '6:25', '7:01', '', '7:30', '', '', '', '', '8:30', '', '', '', '', '9:30', '', '10:07', '10:29', '11:07', '11:29', '12:07', '12:29', '13:07', '1:29', '2:07', '2:29', '3:07', '3:29', '4:07', '4:29', '', '5:05', '', '', '5:42', '', '6:06', '', '', '6:42', '', '', '', '7:42', '8:20', '9:25', '11:00', '1:01'], 'Gilroy': ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '5:30', '', '', '', '', '', '7:07', '', '', '7:47', '', '', '', '', '', '', '', '', '', '']} stations[weekday][southbound] = ['San Francisco', '22nd Street', 'Bayshore', 'So. San Francisco', 'San Bruno', 'Millbrae', 'Burlingame', 'San Mateo', 'Hayward Park', 'Hillsdale', 'Belmont', 'San Carlos', 'Redwood City', 'Menlo Park', 'Palo Alto', 'California Ave', 'San Antonio', 'Mountain View', 'Sunnyvale', 'Lawrence', 'Santa Clara', 'College Park', 'San Jose', 'Tamien', 'Capitol', 'Blossom Hill', 'Morgan Hill', 'San Martin', 'Gilroy'] service[weekend][northbound] = {'Shuttle Bus arr. S.J.': [' ', '7:45', '8:45', '9:45', '10:45', '11:45', '12:45', '1:45', '2:45', '3:45', '4:45', '5:45', '6:45', '7:45', ' ', ' '], 'Santa Clara': ['7:05', '8:05', '9:05', '10:05', '11:05', '12:05', '1:05', '2:05', '3:05', '4:05', '5:05', '6:05', '7:05', '8:05', '9:05', '10:35'], 'Hayward Park': ['7:54', '8:54', '9:54', '10:54', '11:54', '12:54', '1:54', '2:54', '3:54', '4:54', '5:54', '6:54', '7:54', '8:54', '9:54', '11:24'], 'San Francisco': ['8:36', '9:36', '10:36', '11:36', '12:36', '1:36', '2:36', '3:36', '4:36', '5:36', '6:36', '7:36', '8:36', '9:36', '10:36', '12:06'], 'San Mateo': ['7:57', '8:57', '9:57', '10:57', '11:57', '12:57', '1:57', '2:57', '3:57', '4:57', '5:57', '6:57', '7:57', '8:57', '9:57', '11:27'], 'San Carlos': ['7:45', '8:45', '9:45', '10:45', '11:45', '12:45', '1:45', '2:45', '3:45', '4:45', '5:45', '6:45', '7:45', '8:45', '9:45', '11:15'], 'Atherton': ['7:37', '8:37', '9:37', '10:37', '11:37', '12:37', '1:37', '2:37', '3:37', '4:37', '5:37', '6:37', '7:37', '8:37', '9:37', '11:07'], 'Lawrence': ['7:10', '8:10', '9:10', '10:10', '11:10', '12:10', '1:10', '2:10', '3:10', '4:10', '5:10', '6:10', '7:10', '8:10', '9:10', '10:40'], 'Burlingame': ['8:00', '9:00', '10:00', '11:00', '12:00', '1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '10:00', '11:30'], 'Mountain View': ['7:19', '8:19', '9:19', '10:19', '11:19', '12:19', '1:19', '2:19', '3:19', '4:19', '5:19', '6:19', '7:19', '8:19', '9:19', '10:49'], 'Shuttle dep. Tamien': [' ', '7:31', '8:31', '9:31', '10:31', '11:31', '12:31', '1:31', '2:31', '3:31', '4:31', '5:31', '6:31', '7:31', ' ', ' '], 'San Antonio': ['7:23', '8:23', '9:23', '10:23', '11:23', '12:23', '1:23', '2:23', '3:23', '4:23', '5:23', '6:23', '7:23', '8:23', '9:23', '10:53'], 'Millbrae': ['8:08', '9:08', '10:08', '11:08', '12:08', '1:08', '2:08', '3:08', '4:08', '5:08', '6:08', '7:08', '8:08', '9:08', '10:08', '11:38'], 'Bayshore': ['8:23', '9:23', '10:23', '11:23', '12:23', '1:23', '2:23', '3:23', '4:23', '5:23', '6:23', '7:23', '8:23', '9:23', '10:23', '11:53', '22nd Street', '8:28', '9:28', '10:28', '11:28', '12:28', '1:28', '2:28', '3:28', '4:28', '5:28', '6:28', '7:28', '8:28', '9:28', '10:28', '11:58'], 'Train No.': ['421SAT.only', '423', '425', '427', '429', '431', '433', '435', '437', '439', '441', '443', '445', '447', '449', '451#SAT.only'], 'Menlo Park': ['7:34', '8:34', '9:34', '10:34', '11:34', '12:34', '1:34', '2:34', '3:34', '4:34', '5:34', '6:34', '7:34', '8:34', '9:34', '11:04'], 'San Jose': ['7:00', '8:00', '9:00', '10:00', '11:00', '12:00', '1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '10:30'], 'Hillsdale': ['7:51', '8:51', '9:51', '10:51', '11:51', '12:51', '1:51', '2:51', '3:51', '4:51', '5:51', '6:51', '7:51', '8:51', '9:51', '11:21'], 'Sunnyvale': ['7:14', '8:14', '9:14', '10:14', '11:14', '12:14', '1:14', '2:14', '3:14', '4:14', '5:14', '6:14', '7:14', '8:14', '9:14', '10:44'], 'Palo Alto': ['7:31', '8:31', '9:31', '10:31', '11:31', '12:31', '1:31', '2:31', '3:31', '4:31', '5:31', '6:31', '7:31', '8:31', '9:31', '11:01'], 'Redwood City': ['7:41', '8:41', '9:41', '10:41', '11:41', '12:41', '1:41', '2:41', '3:41', '4:41', '5:41', '6:41', '7:41', '8:41', '9:41', '11:11'], 'San Bruno': ['8:12', '9:12', '10:12', '11:12', '12:12', '1:12', '2:12', '3:12', '4:12', '5:12', '6:12', '7:12', '8:12', '9:12', '10:12', '11:42'], 'So. San Francisco': ['8:17', '9:17', '10:17', '11:17', '12:17', '1:17', '2:17', '3:17', '4:17', '5:17', '6:17', '7:17', '8:17', '9:17', '10:17', '11:47'], 'Belmont': ['7:48', '8:48', '9:48', '10:48', '11:48', '12:48', '1:48', '2:48', '3:48', '4:48', '5:48', '6:48', '7:48', '8:48', '9:48', '11:18'], 'Broadway': ['8:03', '9:03', '10:03', '11:03', '12:03', '1:03', '2:03', '3:03', '4:03', '5:03', '6:03', '7:03', '8:03', '9:03', '10:03', '11:33'], 'California Ave': ['7:27', '8:27', '9:27', '10:27', '11:27', '12:27', '1:27', '2:27', '3:27', '4:27', '5:27', '6:27', '7:27', '8:27', '9:27', '10:57']} stations[weekend][northbound] = ['Shuttle dep. Tamien', 'Shuttle Bus arr. S.J.', 'San Jose', 'Santa Clara', 'Lawrence', 'Sunnyvale', 'Mountain View', 'San Antonio', 'California Ave', 'Palo Alto', 'Menlo Park', 'Atherton', 'Redwood City', 'San Carlos', 'Belmont', 'Hillsdale', 'Hayward Park', 'San Mateo', 'Burlingame', 'Broadway', 'Millbrae', 'San Bruno', 'So. San Francisco', 'Bayshore', 'San Francisco'] service[weekend][southbound] = {'Santa Clara': ['9:28', '10:28', '11:28', '12:28', '1:28', '2:28', '3:28', '4:28', '5:28', '6:28', '7:28', '8:28', '9:28', '10:28', '11:28', '1:29'], 'Hayward Park': ['8:37', '9:37', '10:37', '11:37', '12:37', '1:37', '2:37', '3:37', '4:37', '5:37', '6:37', '7:37', '8:37', '9:37', '10:37', '12:38'], 'San Francisco': ['8:00', '9:00', '10:00', '11:00', '12:00', '1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '10:00', '12:01', '22nd Street', '8:05', '9:05', '10:05', '11:05', '12:05', '1:05', '2:05', '3:05', '4:05', '5:05', '6:05', '7:05', '8:05', '9:05', '10:05', '12:06'], 'San Mateo': ['8:34', '9:34', '10:34', '11:34', '12:34', '1:34', '2:34', '3:34', '4:34', '5:34', '6:34', '7:34', '8:34', '9:34', '10:34', '12:35'], 'San Carlos': ['8:46', '9:46', '10:46', '11:46', '12:46', '1:46', '2:46', '3:46', '4:46', '5:46', '6:46', '7:46', '8:46', '9:46', '10:46', '12:47'], 'Atherton': ['8:56', '9:56', '10:56', '11:56', '12:56', '1:56', '2:56', '3:56', '4:56', '5:56', '6:56', '7:56', '8:56', '9:56', '10:56', '12:57'], 'Lawrence': ['9:23', '10:23', '11:23', '12:23', '1:23', '2:23', '3:23', '4:23', '5:23', '6:23', '7:23', '8:23', '9:23', '10:23', '11:23', '1:24'], 'Burlingame': ['8:30', '9:30', '10:30', '11:30', '12:30', '1:30', '2:30', '3:30', '4:30', '5:30', '6:30', '7:30', '8:30', '9:30', '10:30', '12:31'], 'Mountain View': ['9:14', '10:14', '11:14', '12:14', '1:14', '2:14', '3:14', '4:14', '5:14', '6:14', '7:14', '8:14', '9:14', '10:14', '11:14', '1:15'], 'x8:10': ['9:10', '10:10', '11:10', '12:10', '1:10', '2:10', '3:10', '4:10', '5:10', '6:10', '7:10', '8:10', '9:10', '10:10', '12:11'], 'San Antonio': ['9:10', '10:10', '11:10', '12:10', '1:10', '2:10', '3:10', '4:10', '5:10', '6:10', '7:10', '8:10', '9:10', '10:10', '11:10', '1:11'], 'Millbrae': ['8:24', '9:24', '10:24', '11:24', '12:24', '1:24', '2:24', '3:24', '4:24', '5:24', '6:24', '7:24', '8:24', '9:24', '10:24', '12:25'], 'San Jose ': ['9:36', '10:36', '11:36', '12:36', '1:36', '2:36', '3:36', '4:36', '5:36', '6:36', '7:36', '8:36', '9:36', '10:36', '11:36', '1:37'], 'Train No.': ['422', '424', '426', '428', '430', '432', '434', '436', '438', '440', '442', '444', '446', '448', '450SAT.only', '454SAT.only'], 'Menlo Park': ['8:59', '9:59', '10:59', '11:59', '12:59', '1:59', '2:59', '3:59', '4:59', '5:59', '6:59', '7:59', '8:59', '9:59', '10:59', '1:00'], 'Hillsdale': ['8:40', '9:40', '10:40', '11:40', '12:40', '1:40', '2:40', '3:40', '4:40', '5:40', '6:40', '7:40', '8:40', '9:40', '10:40', '12:41'], 'Shuttle arr. Tamien': ['10:03', '11:03', '12:03', '1:03', '2:03', '3:03', '4:03', '5:03', '6:03', '7:03', '8:03', '9:03', '10:03', ' ', ' ', ' '], 'Sunnyvale': ['9:19', '10:19', '11:19', '12:19', '1:19', '2:19', '3:19', '4:19', '5:19', '6:19', '7:19', '8:19', '9:19', '10:19', '11:19', '1:20'], 'Palo Alto': ['9:02', '10:02', '11:02', '12:02', '1:02', '2:02', '3:02', '4:02', '5:02', '6:02', '7:02', '8:02', '9:02', '10:02', '11:02', '1:03'], 'Shuttle Bus dep. SJ': ['9:55', '10:55', '11:55', '12:55', '1:55', '2:55', '3:55', '4:55', '5:55', '6:55', '7:55', '8:55', '9:55', ' ', ' ', ' '], 'Redwood City': ['8:52', '9:52', '10:52', '11:52', '12:52', '1:52', '2:52', '3:52', '4:52', '5:52', '6:52', '7:52', '8:52', '9:52', '10:52', '12:53'], 'San Bruno': ['8:20', '9:20', '10:20', '11:20', '12:20', '1:20', '2:20', '3:20', '4:20', '5:20', '6:20', '7:20', '8:20', '9:20', '10:20', '12:21'], 'So. San Francisco': ['8:16', '9:16', '10:16', '11:16', '12:16', '1:16', '2:16', '3:16', '4:16', '5:16', '6:16', '7:16', '8:16', '9:16', '10:16', '12:17'], 'Belmont': ['8:43', '9:43', '10:43', '11:43', '12:43', '1:43', '2:43', '3:43', '4:43', '5:43', '6:43', '7:43', '8:43', '9:43', '10:43', '12:44'], 'Broadway': ['8:28', '9:28', '10:28', '11:28', '12:28', '1:28', '2:28', '3:28', '4:28', '5:28', '6:28', '7:28', '8:28', '9:28', '10:28', '12:29'], 'California Ave': ['9:06', '10:06', '11:06', '12:06', '1:06', '2:06', '3:06', '4:06', '5:06', '6:06', '7:06', '8:06', '9:06', '10:06', '11:06', '1:07']} stations[weekend][southbound] = ['San Francisco', 'Bayshore', 'x8:10', 'So. San Francisco', 'San Bruno', 'Millbrae', 'Broadway', 'Burlingame', 'San Mateo', 'Hayward Park', 'Hillsdale', 'Belmont', 'San Carlos', 'Redwood City', 'Atherton', 'Menlo Park', 'Palo Alto', 'California Ave', 'San Antonio', 'Mountain View', 'Sunnyvale', 'Lawrence', 'Santa Clara', 'San Jose ', 'Shuttle Bus dep. SJ', 'Shuttle arr. Tamien'] ### # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52266 class MultiListbox(Frame): def __init__(self, master, lists): Frame.__init__(self, master) self.lists = [] for l,w in lists: frame = Frame(self); frame.pack(side=LEFT, expand=YES, fill=BOTH) Label(frame, text=l, borderwidth=1, relief=RAISED).pack(fill=X) lb = Listbox(frame, width=w, borderwidth=0, selectborderwidth=0, relief=FLAT, exportselection=FALSE) lb.pack(expand=YES, fill=BOTH) self.lists.append(lb) lb.bind('', lambda e, s=self: s._select(e.y)) lb.bind('', lambda e, s=self: s._select(e.y)) lb.bind('', lambda e: 'break') lb.bind('', lambda e, s=self: s._b2motion(e.x, e.y)) lb.bind('', lambda e, s=self: s._button2(e.x, e.y)) lb.bind('',lambda e,s=self: s._scroll(SCROLL, -1, UNITS)) lb.bind('',lambda e,s=self: s._scroll(SCROLL, 1, UNITS)) lb.bind('',lambda e,s=self: s._scroll(SCROLL, -1, UNITS)) lb.bind('',lambda e,s=self: s._scroll(SCROLL, 1, UNITS)) frame = Frame(self); frame.pack(side=LEFT, fill=Y) Label(frame, borderwidth=1, relief=RAISED).pack(fill=X) sb = Scrollbar(frame, orient=VERTICAL, command=self._scroll) sb.pack(expand=YES, fill=Y) self.lists[0]['yscrollcommand']=sb.set def _select(self, y): row = self.lists[0].nearest(y) self.lists[0].focus_set() self.selection_clear(0, END) self.selection_set(row) return 'break' def _button2(self, x, y): for l in self.lists: l.scan_mark(x, y) return 'break' def _b2motion(self, x, y): for l in self.lists: l.scan_dragto(x, y) return 'break' def _scroll(self, *args): for l in self.lists: apply(l.yview, args) return 'break' def curselection(self): return self.lists[0].curselection() def delete(self, first, last=None): for l in self.lists: l.delete(first, last) def get(self, first, last=None): result = [] for l in self.lists: result.append(l.get(first,last)) if last: return apply(map, [None] + result) return result def index(self, index): self.lists[0].index(index) def insert(self, index, *elements): for e in elements: i = 0 for l in self.lists: l.insert(index, e[i]) i = i + 1 def size(self): return self.lists[0].size() def see(self, index): for l in self.lists: l.see(index) def selection_anchor(self, index): for l in self.lists: l.selection_anchor(index) def selection_clear(self, first, last=None): for l in self.lists: l.selection_clear(first, last) def selection_includes(self, index): return self.lists[0].selection_includes(index) def selection_set(self, first, last=None): for l in self.lists: l.selection_set(first, last) # ### class Caltrain(object): def __init__(self): self.root = Tk() self.root.title("CaltrainPy") # This makes it full screen, but for some reason controls don't fill # It also makes OptionMenus hard to use (seems like a bug) #w, h = self.root.winfo_screenwidth(), self.root.winfo_screenheight() #self.root.geometry("%dx%d+0+0" % (w, h)) self.init() def onDays(self): text = self.days['text'] if text == weekday: self.days['text'] = weekend else: self.days['text'] = weekday self.updateFromTo() def onDirection(self): if self.direction['text'] == northbound: self.direction['text'] = southbound else: self.direction['text'] = northbound fromStation = self.fromDefault.get() self.fromDefault.set(self.toDefault.get()) self.toDefault.set(fromStation) self.updateTable() def updateFromTo(self, _a=None, _b=None, _c=None): fromStation = self.fromDefault.get() toStation = self.toDefault.get() day = self.days['text'] direction = self.direction['text'] s = stations[day][direction] if fromStation not in s or toStation not in s: self.fromDefault.set(s[0]) self.toDefault.set(s[-1]) self.fromMenu.destroy() self.fromMenu = OptionMenu(self.root, self.fromDefault, *s) self.fromMenu.grid(row=1, column=1) self.toMenu.destroy() self.toMenu = OptionMenu(self.root, self.toDefault, *s) self.toMenu.grid(row=1, column=2, sticky=E) self.updateTable() def updateTable(self, _a=None): fromStation = self.fromDefault.get() toStation = self.toDefault.get() day = self.days['text'] direction = self.direction['text'] self.trains = MultiListbox(self.root, (("Train", 1), (fromStation,2), (toStation, 3))) for train, fromTime, toTime in zip(service[day][direction][trainNumber], service[day][direction][fromStation], service[day][direction][toStation]): self.trains.insert(END, (train, fromTime, toTime)) self.trains.grid(row=2, columnspan=3, sticky=W+E) def init(self): # top row buttons self.days = Button(self.root, text=weekday, command=self.onDays) self.direction = Button(self.root, text=northbound, command=self.onDirection) self.days.grid(row=0, columnspan=2, sticky=W) self.direction.grid(row=0, column=2, sticky=E) # Second row label and OptionsMenus Label(self.root, text="From-To").grid(row=1, sticky=W) self.fromDefault = StringVar(self.root) self.fromDefault.set(stations[weekday][northbound][0]) self.fromMenu = OptionMenu(self.root, self.fromDefault, *stations[weekday][northbound]) self.fromMenu.grid(row=1, column=1) self.fromDefault.trace_variable('w', self.updateFromTo) self.toDefault = StringVar(self.root) self.toDefault.set(stations[weekday][northbound][-1]) self.toMenu = OptionMenu(self.root, self.toDefault, *stations[weekday][northbound]) self.toMenu.grid(row=1, column=2, sticky=E) self.toDefault.trace_variable('w', self.updateFromTo) # Timetable self.updateTable() if __name__ == "__main__": caltrain = Caltrain() caltrain.root.mainloop()