Skip to content

Instantly share code, notes, and snippets.

@jalcine
Forked from parthibanloganathan/README.md
Created August 7, 2014 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jalcine/5ac5c8a4bd87e32e8c2e to your computer and use it in GitHub Desktop.
Save jalcine/5ac5c8a4bd87e32e8c2e to your computer and use it in GitHub Desktop.

Subway Info

##Preview

Screenshot 1: https://raw.github.com/parthibanloganathan/dashing_widgets/master/public/mta1.png Screenshot 2: https://raw.github.com/parthibanloganathan/dashing_widgets/master/public/mta2.png

Description

Subway Info is a Dashing widget which displays information on trains in New York City. Information includes train line, direction, station and arrival time. You can customize it to include any combination of lines and stations. This may also be used in other cities as well if you have the appropriate GTFS files.

##Dependencies

Add the following gem to the Gemfile:

gem 'gtfs'

and run bundle install.

##Usage

To use the widget, copy mta.rb to the /jobs folder. Create a folder called mta under /widgets. Copy mta.coffee, mta.html and mta.scss into /widgets/mta.

Add the following code snippet to your dashboard .erb file under /dashboards:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
   <div data-id="mta" data-view="Mta"></div>
</li>

##Settings

This widget allows you to specify the stops and lines of interest to you. Specify these as strings in the arrays target_stops and target_lines. Please limit the number of stops and lines. For example, this widget was tested with 2 stations with 2 lines each.

You can also specify the refresh time for the display, the interval between data updates and how far in the future to look for incoming trains.

Look at the comments at the beginning of the job mta.rb to learn more about customizing the widget.

Note: The widget may be used with other GTFS files too. This is not restricted to New York City. Keep in mind that this has only been tested with GTFS data from the MTA.

To use your own GTFS file, replace the URL to the zip file in the following line:

  $source = GTFS::Source.build('http://www.mta.info/developers/data/nyct/subway/google_transit.zip')

Add your desired URL instead.

####Note: If you would like to use the train line images instead of numbers, use the following mta.coffee and mta.html. Also download the images (1, 2, 3, 4, 5, 6, A, C, E, N, Q, R) from here into the folder /public.

##Warnings

This widget takes around one minute to load on startup. Be patient. Once it starts, the widget is quick and responsive. The job must download and parse a GTFS file from the MTA. The file can be found at the MTA Developer downloads page. To access, click New York City Transit Subway under static data feeds. The GTFS files are updated by the MTA every so often. This widget checks for an update every 24 hours or every time the dashboard's host server starts Dashing.

class Dashing.Mta extends Dashing.Widget
<p class="line" data-bind="line"></p>
<p class="name" data-bind="name"></p>
<p class="time" data-bind="time"></p>
<p class="direction" data-bind="direction"></p>
require 'gtfs'
require 'time'
# Add the stations and lines you want to get updates on
# Example:
# target_stops = ['116 St - Columbia University', '8 St - NYU']
# target_lines = ['1','2','N']
# This will give you info on the trains on the 1, 2 and N at 116th St - Columbia University and 8 St - NYU
# You can get these names by downloading http://www.mta.info/developers/data/nyct/subway/google_transit.zip and
# checking for valid stop names under the file called 'stops'
target_stops = [INSERT STOPS HERE]
target_lines = [INSERT LINES HERE]
# Change the refresh times if needed
# Updates list of trains arriving in the next 5 minutes (TIME) every 1 minute (UPDATE).
# Displays a particular train/stop combination data for 3 seconds (DISPLAY) before cycling to another
UPDATE = '1m'
TIME = 5 # Note that this is an integer, not a string (represents minutes)
DISPLAY = '3s'
request_flag = false
send_flag = false
source = nil
final_hash = Array.new
my_stop_ids = Array.new
stop_hash = Array.new
index = 0
stop_times = Array.new
# Retrieves GTFS data and builds primary data with lines of interest
SCHEDULER.every '24h', :first_in => 0 do |job|
# Defaults to strict checking of required columns
source = GTFS::Source.build('http://www.mta.info/developers/data/nyct/subway/google_transit.zip')
# Get stop_ids of our stops of interest (these are listed in the array target_stops)
source.stops.each do |stop|
if target_stops.include? stop.name
target_stop = Hash.new
target_stop['name'] = stop.name
target_stop['id'] = stop.id
stop_hash.push(target_stop)
my_stop_ids.push(stop.id)
end
end
# Get stop_times at stops with our stop_ids
stop_times = source.stop_times.select { |stop_time| my_stop_ids.include? stop_time.stop_id }
# Set request_flag to true so that we can start calculating schedules
request_flag = true
end
# Calculates trains leaving in the next few minutes which stop at the target_stations
SCHEDULER.every UPDATE, :first_in => '5s' do |job|
if request_flag == true
send_flag = false
final_hash = Array.new
# Get stop_times from our stops with trains departing in the next 10 minutes
stop_times.each do |stop_time|
split_dept_time = stop_time.departure_time.split(':')
dept_time = (3600*split_dept_time[0].to_i) + (60*split_dept_time[1].to_i) + (split_dept_time[2].to_i)
time = Time.now.to_a
now = 3600*time[2] + 60*time[1] + time[0]
# Time difference in seconds
diff = dept_time - now
# If train leaves in next 5 minutes
if 0 < diff && diff < TIME*60
# Get line and direction based on trip_id
# Then form objects containing final data to display
selected_trip = source.trips.select { |trip| trip.id == stop_time.trip_id }
# If line is one of our target lines, create data object
if target_lines.include? selected_trip[0].route_id
final_object = Hash.new
stop = stop_hash.select { |hashed_stop| hashed_stop['id'] == stop_time.stop_id }
final_object['name'] = stop[0]['name']
# There are numbers 1 and 0 before the time strings
# becausse we need to sort objects by time later.
# This is a hack, and needs to be refined.
mins = diff/60
if mins == 0
final_object['time'] = '0Leaving now'
elsif mins == 1
final_object['time'] = "1Arrives in #{mins} min"
else
final_object['time'] = "1Arrives in #{mins} mins"
end
final_object['line'] = selected_trip[0].route_id
final_object['direction'] = selected_trip[0].headsign
final_hash.push(final_object)
end
end
send_flag = true
final_hash.sort! { |obj1, obj2| obj1['time'] <=> obj2['time'] }
end
end
end
# Displays train/stop info, and cycles through the different data
SCHEDULER.every DISPLAY, :first_in => '5s' do |job|
line = ''
name = 'Loading'
direction = ''
time = ''
if send_flag == true
if index >= final_hash.size
index = 0
end
if final_hash.size > 0
line = final_hash[index]['line']
name = final_hash[index]['name']
direction = final_hash[index]['direction']
size = final_hash[index]['time'].size
time = final_hash[index]['time'][1..size]
end
index = index + 1
end
send_event('mta', {line: line, name: name, direction: direction, time: time})
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #FF9D00;
$text-color: #FFFDA3;
// ----------------------------------------------------------------------------
// Widget-text styles
// ----------------------------------------------------------------------------
.widget-mta {
background-color: $background-color;
.line {
font-size: 270%;
color: $text-color;
}
.name {
font-size: 140%;
color: $text-color;
}
.direction {
font-size: 100%;
color: $text-color;
}
.time {
font-size: 200%;
color: $text-color;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment