Merge branch 'master' of ssh://apples.lambdacomplex.org/git/bus
Merge branch 'master' of ssh://apples.lambdacomplex.org/git/bus

<html>  
<head>  
<link rel="stylesheet" href="main.css" type="text/css">  
<title>Graphserver - The Open-Source Multi-Modal Trip Planner</title>  
</head>  
 
<body>  
<div id='container'>  
<a href="gallery.html"><img src="img/graphbanner.png"></a>  
<h1>Graphserver</h1>  
The open-source multi-modal trip planner.  
 
<h2>Code Repository</h2>  
<a href="http://github.com/bmander/graphserver/tree/master">http://github.com/bmander/graphserver/tree/master</a>  
 
<h2>Mailing List</h2>  
 
Direct questions and comments to the <a href="http://groups.google.com/group/graphserver">Graphserver Google Group</a>.  
 
<h2>Download</h2>  
 
<pre style="background-color:#F5F5F5"> $ wget http://github.com/bmander/graphserver/zipball/08132009</pre>  
 
Or, for the stout of heart, get a copy of the current working branch  
 
<pre style="background-color:#F5F5F5"> $ git clone git://github.com/bmander/graphserver.git </pre>  
 
<h2>Install</h2>  
 
<h3>Cold Start</h3>  
<p>You'll need a computer running linux. The following setup was tested and checked on <a href="http://aws.amazon.com/console/">Amazon EC2</a> small instance running Fedora, built from an image with id "ami-48aa4921", at a cost of $0.20/hour.<p>  
<p>You'll need to get git:</p>  
<p>On Ubuntu:</p>  
<pre style="background-color:#F5F5F5"> $ sudo apt-get install git-core </pre>  
<p>On Fedora:</p>  
<pre style="background-color:#F5F5F5"> $ yum install git-core</pre>  
 
<h3>Get The Prerequisites</h3>  
 
<p>You're about to compile C code against python development libraries. You need to prepare for that.</p>  
 
On Ubuntu:  
<pre style="background-color:#F5F5F5">$ sudo apt-get install python-setuptools  
$ sudo apt-get install build-essential  
$ sudo apt-get install python-dev  
</pre>  
 
On Fedora:  
<pre style="background-color:#F5F5F5">  
$ yum install python-setuptools-devel  
$ yum install gcc  
$ yum install gcc-c++  
$ yum install python-devel  
$ easy_install simplejson  
</pre>  
 
<h3>One-step Install</h3>  
<p>Get a copy of Graphserver</p>  
<pre style="background-color:#F5F5F5">$ git clone git://github.com/bmander/graphserver.git</pre>  
 
This will download and compile the core, download and install package dependencies, and install the python wrappers in one go.  
 
<pre style="background-color:#F5F5F5">$ cd graphserver/pygs  
$ sudo python setup.py install  
</pre>  
 
<h3>Install RTree</h3>  
<p>If you want to load OSM Data (and you probably do), you have to laboriously install RTree</p>  
<pre style="background-color:#F5F5F5"> $ wget http://download.osgeo.org/libspatialindex/spatialindex-1.4.0.tar.gz  
$ gunzip spatialindex-1.4.0.tar.gz  
$ tar -xvf spatialindex-1.4.0.tar  
$ cd spatialindex-1.4.0  
$ ./configure --prefix=/usr  
$ make  
$ make install  
$ easy_install RTree  
$ cp /usr/lib/python2.5/site-packages/Rtree-0.5.0-py2.5-linux-i686.egg/libsidx.so /usr/lib  
</pre>  
 
<h2>A Quick Tour of the Basics</h2>  
 
<pre style="background-color:#F5F5F5">  
$ python  
&gt;&gt;&gt; from graphserver.core import Graph, Street, State  
&gt;&gt;&gt; gg = Graph()  
&gt;&gt;&gt; gg.add_vertex("A")  
<span class="computeroutput">&lt;graphserver.core.Vertex object at 0xb7d9608c&gt;</span>  
&gt;&gt;&gt; gg.add_vertex("B")  
<span class="computeroutput">&lt;graphserver.core.Vertex object at 0xb7c397cc&gt;</span>  
&gt;&gt;&gt; gg.add_edge( "A", "B", Street("1", 100) )  
<span class="computeroutput">&lt;graphserver.core.Edge object at 0xb7c4a92c&gt;</span>  
&gt;&gt;&gt; gg.add_edge( "A", "B", Street("2", 50 ) )  
<span class="computeroutput">&lt;graphserver.core.Edge object at 0xb7da708c&gt;</span>  
&gt;&gt;&gt; gg.size #the graph is quite small  
<span class="computeroutput">2</span>  
&gt;&gt;&gt; gg.get_vertex("A").outgoing <span class="pycomment"># the graph is directional</span>  
<span class="computeroutput">[&lt;graphserver.core.Edge object at 0xb7b9accc&gt;, &lt;graphserver.core.Edge object at 0xb7b9acac&gt;]</span>  
&gt;&gt;&gt; gg.get_vertex("A").incoming  
<span class="computeroutput">[]</span>  
&gt;&gt;&gt; spt = gg.shortest_path_tree( "A", "B", State(1,0) )  
&gt;&gt;&gt; spt  
<span class="computeroutput">&lt;graphserver.core.ShortestPathTree object at 0xb7c45b8c&gt;</span>  
&gt;&gt;&gt; spt.get_vertex("A") <span class="pycomment"># the shortest path tree is a partial copy of the graph</span>  
<span class="computeroutput">&lt;graphserver.core.Vertex object at 0xb7c4a92c&gt;</span>  
&gt;&gt;&gt; spt.get_vertex("A").outgoing <span class="pycomment"># which only contains the shortest paths to all points closer than 'B' </span>  
<span class="computeroutput">[&lt;graphserver.core.Edge object at 0xb7b9adec&gt;]</span>  
&gt;&gt;&gt; vertices, edges = spt.path("B") <span class="pycomment"># you can get the path 'A' to 'B' from the shortest path tree</span>  
&gt;&gt;&gt; vertices <span class="pycomment"># a list of references to the SPT vertices along the shortest path</span>  
<span class="computeroutput">[&lt;graphserver.core.Vertex object at 0xb7b9ae4c&gt;, &lt;graphserver.core.Vertex object at 0xb7b9adec&gt;]</span>  
&gt;&gt;&gt; edges <span class="pycomment"># a list of references to the SPT edges along the shortest path</span>  
<span class="computeroutput">[&lt;graphserver.core.Edge object at 0xb7b9accc&gt;]</span>  
&gt;&gt;&gt; edges[0].payload <span class="pycomment"># the edge payload contains information about the edge</span>  
<span class="computeroutput">&lt;Street name='2' length=50.000000 rise=0.000000 fall=0.000000 way=0&gt;</span>  
&gt;&gt;&gt; vertices[-1].payload <span class="pycomment"># the payload of the final vertex has useful information</span>  
<span class="computeroutput">&lt;graphserver.core.State object at 0xb7c4a92c&gt;</span>  
&gt;&gt;&gt; vertices[-1].payload.time <span class="pycomment"># it takes 58 seconds to get from "A" to "B"</span>  
<span class="computeroutput">58</span>  
&gt;&gt;&gt; spt.destroy() <span class="pycomment"># these functions are thin wrappers around C functions</span>  
&gt;&gt;&gt; gg.destroy() <span class="pycomment"># so we have to perform garbage collection explicitly</span>  
&gt;&gt;&gt; exit()  
</pre>  
<h2>Compiling Graphs</h2>  
<h3>Loading OpenStreetMap Data</h3>  
 
Grab some OSM data. Here, we download an area around of Redding, CA, US from the OpenStreetMap HTTP API.  
<pre style="background-color:#F5F5F5"> $ wget http://api.openstreetmap.org/api/0.6/map?bbox=-122.4624,40.5505,-122.2876,40.6334 -O map.osm  
</pre>  
<p>Compile the OSM file into an OSMDB file, and then load that OSMDB file into a graph.</p>  
<pre style="background-color:#F5F5F5"> $ gs_osmdb_compile map.osm map.osmdb  
$ gs_import_osm map.gdb map.osmdb  
</pre>  
<p>Take a look at your new graph. This prints every vertex label in the graph:</p>  
<pre style="background-color:#F5F5F5"> $ gs_gdb_inspect map.gdb</pre>  
<p>Pick one and see all edges outgoing from that vertex:</p>  
<pre style="background-color:#F5F5F5"> $ gs_gdb_inspect map.gdb osm-92080455</pre>  
Prints:  
<pre style="background-color:#F5F5F5">osm-92080455 -> osm-91938757  
&lt;Street name='10585937-1' length=136.119463 rise=0.000000 fall=0.000000 way=849&gt;  
osm-92080455 -> osm-92080457  
&lt;Street name='10585937-2' length=139.452776 rise=0.000000 fall=0.000000 way=849&gt;  
osm-92080455 -> osm-92601143  
&lt;Street name='10596654-0' length=126.551782 rise=0.000000 fall=0.000000 way=1809&gt;  
osm-92080455 -> osm-92080381  
&lt;Street name='10596654-1' length=6.382770 rise=0.000000 fall=0.000000 way=1809&gt;</pre>  
 
<h3>Loading Public Transit Data</h3>  
 
Grab the GTFS file for your favorite transit agency. Here, we grab the GTFS for the transit system in Redding, CA:  
<pre style="background-color:#F5F5F5"> $ wget http://trilliumtransit.com/transit_feeds/redding/google_transit.zip -O redding_gtfs.zip</pre>  
<p>Compile the GTFS into a GTFSDB, and then compile that GTFSDB into a graph<p>  
<pre style="background-color:#F5F5F5"> $ gs_gtfsdb_build redding_gtfs.zip redding.gtfsdb  
$ gs_import_gtfs redding.gdb redding.gtfsdb</pre>  
<p>Use gs_gdb_inspect to check that your new transit graph is in good shape</p>  
<pre style="background-color:#F5F5F5"> $ gs_gdb_inspect redding.gdb sta-3622</pre>  
should print  
<pre style="background-color:#F5F5F5">sta-3622 -> psv-0-000-004  
&lt;TripBoard int_sid=0 sid=105A166 agency=0 calendar=165157760 timezone=164034504 boardings=[('1572A105B166', 23964), ('1598A105B166', 27564), ('1602A105B166', 31164), ('1607A105B166', 34764), ('1600A105B166', 38364), ('1605A105B166', 41964), ('1603A105B166', 45564), ('1608A105B166', 49164), ('1601A105B166', 52764), ('1606A105B166', 56364), ('1599A105B166', 59964), ('1604A105B166', 63564), ('1609A105B166', 67164)]&gt;  
sta-3622 -> psv-0-000-004  
&lt;TripBoard int_sid=1 sid=106A166 agency=0 calendar=165157760 timezone=164034504 boardings=[('2459A106B166', 34764), ('1635A106B166', 38364), ('1640A106B166', 41964), ('1638A106B166', 45564), ('1643A106B166', 49164), ('1636A106B166', 52764), ('1641A106B166', 56364), ('1634A106B166', 59964), ('1639A106B166', 63564), ('1637A106B166', 67164)]&gt;  
</pre>  
 
<h3>Intermingling Public Transit and Street Data</h3>  
<p>You can load both OSM and GTFS data into the same graph, then run a command to link them.</p>  
<pre style="background-color:#F5F5F5"> $ gs_import_gtfs redding_all.gdb redding.gtfsdb  
$ gs_import_osm redding_all.gdb map.osmdb  
$ gs_link_osm_gtfs redding_all.gdb map.osmdb redding.gtfsdb</pre>  
<p>Inspect:</p>  
<pre style="background-color:#F5F5F5"> $ gs_gdb_inspect redding.gdb sta-3622</pre>  
<p>prints:</p>  
<pre style="background-color:#F5F5F5">sta-3622 -> osm-92366549  
&lt;graphserver.core.Link object at 0x9a0b20c&gt;  
sta-3622 -> psv-0-000-004  
&lt;TripBoard int_sid=0 sid=105A166 agency=0 calendar=163855912 timezone=161122808 boardings=[('1572A105B166', 23964), ('1598A105B166', 27564), ('1602A105B166', 31164), ('1607A105B166', 34764), ('1600A105B166', 38364), ('1605A105B166', 41964), ('1603A105B166', 45564), ('1608A105B166', 49164), ('1601A105B166', 52764), ('1606A105B166', 56364), ('1599A105B166', 59964), ('1604A105B166', 63564), ('1609A105B166', 67164)]&gt;  
sta-3622 -> psv-0-000-004  
&lt;TripBoard int_sid=1 sid=106A166 agency=0 calendar=163855912 timezone=161122808 boardings=[('2459A106B166', 34764), ('1635A106B166', 38364), ('1640A106B166', 41964), ('1638A106B166', 45564), ('1643A106B166', 49164), ('1636A106B166', 52764), ('1641A106B166', 56364), ('1634A106B166', 59964), ('1639A106B166', 63564), ('1637A106B166', 67164)]&gt;</pre>  
 
<h3>Inspecting the graph with gs_crawl</h3>  
<p>Start gs_crawl, a little graph inspection web service</p>  
<pre style="background-color:#F5F5F5"> $ gs_crawl redding.gdb 80</pre>  
<p>Then steer your web browser to the appropriate location.<p>  
<p>If you're using Amazon EC2, using your own public DNS:</p>  
<pre style="background-color:#F5F5F5">http://YOUR-EC2-ADDRESS.compute-1.amazonaws.com/</pre>  
<p>Or if you're simply running on your local machine:</p>  
<pre style="background-color:#F5F5F5">http://localhost:80/</pre>  
 
<h3 id="routeserver">Getting routes with gs_routeserver</h3>  
<p>First, you'll need PyYAML</p>  
<pre style="background-color:#F5F5F5"> $ sudo easy_install pyyaml</pre>  
<p>The routeserver finds a path, and then uses a series of "handlers" to convert that path into a human-readable format. Those handlers are enumearted and set up by a configuration file called handlers.yaml. Graphserver comes with an example handlers.yaml which you can use to get started</p>  
<pre style="background-color:#F5F5F5"> $ cp /path/to/graphserver/pygs/graphserver/ext/routeserver/handlers.yaml .</pre>  
<p>This handlers.yaml file is filled with "CHANGEME" stubs. Replace every "CHANGEME.gtfsdb" with "redding.gtfsdb" and every "CHANGEME.osmdb" with "redding.osmdb"</p>  
<p>Fire up a routeserver on the compiled graph</p>  
<pre style="background-color:#F5F5F5"> $ gs_routeserver redding.gdb handlers.yaml -p 80</pre>  
<p>Get a list of all vertices in the system</p>  
<pre style="background-color:#F5F5F5">http://YOUR_DOMAIN_NAME/vertices</pre>  
<p>Get a route narrative</p>  
<pre style="background-color:#F5F5F5">http://YOUR_DOMAIN_NAME/path?origin="osm-92011649"&amp;dest="sta-3803"&amp;currtime=1260839444</pre>  
<p>or</p>  
<pre style="background-color:#F5F5F5">http://YOUR_DOMAIN_NAME/path_raw?origin="osm-92011649"&amp;dest="sta-3803"&amp;currtime=1260839444</pre>  
 
<h3>What about a really big city?</h3>  
<p>First, get Java 1.6. Or Java6. I think they're the same thing. Get the JDK, but not the JVM, the JRE, SDK, SDN, or the JCE. Note Java SE comes with Jave EE, which is apparently at version 5, and may or may not have anything to do with J2EE. I don't know what those have to do with anything. Google it or something. I don't know. They don't make it particularly easy for you. It's like, they've got more money than god and nothing pleases them better than pouring all that expertise into baffling the hell out of you. Honestly, I can't stand Java, but you need it to run Osmosis.</p>  
<p>Then, get Osmosis</p>  
<pre style="background-color:#F5F5F5"> $ wget http://gweb.bretth.com/osmosis-latest.zip  
$ unzip osmosis-latest.zip  
$ chmod a+x ./osmosis-0.30/bin/osmosis</pre>  
<p>Download a biggie GTFS file. Here's the one for the Seattle area:</p>  
<pre style="background-color:#F5F5F5"> $ wget http://www.gtfs-data-exchange.com/gtfs/badhill_20091208_1910.zip</pre>  
<p>Compile it into a GTFSDB. This will take a few minutes</p>  
<pre style="background-color:#F5F5F5"> $ gs_gtfsdb_build badhill_20091208_1910.zip kingco.gtfsdb</pre>  
<p>Check the bounds of the GTFSDB</p>  
<pre style="background-color:#F5F5F5"> $ sqlite3 kingco.gtfsdb "select min(stop_lon),min(stop_lat),max(stop_lon),max(stop_lat) from stops"</pre>  
returns:  
<pre style="background-color:#F5F5F5">-122.506729|47.1553345|-121.78244|47.9323654</pre>  
This will come in handy soon.  
<p>Get a huge chunk of OSM data from the CloudMade state files. Here's Washington State:</p>  
<pre style="background-color:#F5F5F5"> $ wget http://downloads.cloudmade.com/north_america/united_states/washington/washington.osm.highway.bz2  
$ bunzip2 washington.osm.highway.bz2</pre>  
<p>Then, use the bounding box coordinates we just got to cut down the OSM file to the area surrounding the agency. Check it:<p>  
<pre style="background-color:#F5F5F5"> $ /path/to/osmosis-0.30/bin/osmosis --read-xml washington.osm.highway --bounding-box left=-122.506729 bottom=47.1553345 right=-121.78244 top=47.9323654 --write-xml kingco.osm</pre>  
<p>Then, compile and set it up like normal. It's a trip-planning bonanza.</p>  
 
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">  
</script>  
<script type="text/javascript">  
_uacct = "UA-1815162-1";  
urchinTracker();  
</script>  
</body>  
 
 
</html>  
 
file:a/origin-src/hbus.ca.html (deleted)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">  
 
<head profile="http://gmpg.org/xfn/11">  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
 
<title> hbus.ca: Blog</title>  
 
<link rel="icon" type="image/png" href="http://hbus.ca/site_media/images/favico_bus.png"/>.  
<link href="http://hbus.ca/site_media/stylesheets/scaffold.css" rel="stylesheet" type="text/css" />  
<link href="http://hbus.ca/site_media/stylesheets/style.css" rel="stylesheet" type="text/css" />  
<link rel="stylesheet" href="http://hbus.ca/blog/wp-content/themes/hbus/style.css" type="text/css" media="screen" />  
 
<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yahoo/yahoo-min.js"></script>  
<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>  
<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/element/element-beta-min.js"></script>  
<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/layout/layout-min.js"></script>  
 
<script type="text/javascript" src="http://yui.yahooapis.com/2.6.0/build/event/event-min.js"></script>  
 
 
<link rel="alternate" type="application/rss+xml" title="hbus.ca: Blog RSS Feed" href="http://hbus.ca/blog/?feed=rss2" />  
<link rel="alternate" type="application/atom+xml" title="hbus.ca: Blog Atom Feed" href="http://hbus.ca/blog/?feed=atom" />  
<link rel="pingback" href="http://hbus.ca/blog/xmlrpc.php" />  
 
 
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://hbus.ca/blog/xmlrpc.php?rsd" />  
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://hbus.ca/blog/wp-includes/wlwmanifest.xml" />  
<meta name="generator" content="WordPress 2.7.1" />  
 
</head>  
<body id="nav_blog">  
<div id="header">  
<h1><a href="/">hbus<span>.ca</span></a>&nbsp;<span class="beta">beta</span></h1>  
 
<p>Plan trips on Halifax Metro Transit</p>  
<ul class="nav">  
<li class="nav_home"><a href="http://hbus.ca/">Home</a></li>  
<li class="nav_about"><a href="http://hbus.ca/about">About</a></li>  
<li class="nav_help"><a href="http://hbus.ca/help">Help</a></li>  
<li class="nav_blog"><a href="http://hbus.ca/blog">Blog</a></li>  
<li class="nav_privacy"><a href="http://hbus.ca/privacy">Privacy</a></li>  
<ul>  
</div>  
 
<div class="container" id="content">  
 
<div class="container">  
<div id="sidebar">  
<ul>  
 
<!-- Author information is disabled per default. Uncomment and fill in your details if you want to use it.  
<li><h2>Author</h2>  
<p>A little something about you, the author. Nothing lengthy, just an overview.</p>  
</li>  
-->  
 
 
<li><h2>Archives</h2>  
<ul>  
<li><a href='http://hbus.ca/blog/?m=200904' title='April 2009'>April 2009</a></li>  
</ul>  
</li>  
<!--  
<li class="categories"><h2>Categories</h2><ul> <li class="cat-item cat-item-1"><a href="http://hbus.ca/blog/?cat=1" title="View all posts filed under Uncategorized">Uncategorized</a> (1)  
</li>  
</ul></li>-->  
<li id="linkcat-3" class="linkcat"><h2>Contributors</h2>  
<ul class='xoxo blogroll'>  
<li><a href="http://masalalabs.ca">Ginger Tea and Channa Masala » hbus</a></li>  
 
</ul>  
</li>  
<li id="linkcat-5" class="linkcat"><h2>Friends</h2>  
<ul class='xoxo blogroll'>  
<li><a href="http://carsharehfx.ca" title="Car sharing for Halifax">Car Share Halifax</a></li>  
<li><a href="http://thehubhalifax.ca" title="Coworking space in Halifax">The Hub Halifax</a></li>  
 
</ul>  
</li>  
<li id="linkcat-4" class="linkcat"><h2>Sponsors</h2>  
<ul class='xoxo blogroll'>  
<li><a href="http://navarra.ca" title="The Navarra Group">The Navarra Group</a></li>  
 
</ul>  
</li>  
 
<li><h2>Meta</h2>  
<ul>  
<li><a href="http://hbus.ca/blog/wp-login.php">Log in</a></li>  
<li><a href="http://validator.w3.org/check/referer" title="This page validates as XHTML 1.0 Transitional">Valid <abbr title="eXtensible HyperText Markup Language">XHTML</abbr></a></li>  
<li><a href="http://gmpg.org/xfn/"><abbr title="XHTML Friends Network">XFN</abbr></a></li>  
<li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform.">WordPress</a></li>  
</ul>  
</li>  
 
</ul>  
</div>  
 
 
<div id="posts">  
 
 
<div class="post hentry category-uncategorized" id="post-9">  
<h2><a href="http://hbus.ca/blog/?p=9" rel="bookmark" title="Permanent Link to Creating a google transit feed for fun and profit">Creating a google transit feed for fun and profit</a></h2>  
<small>April 23rd, 2009 <!-- by admin --></small>  
 
<div class="entry">  
<p>People frequently ask me how I manage to collect and input the data that is used by hbus.ca, given Metro Transit&#8217;s intransigence. The &#8220;bike and GPS&#8221; angle is well known <a href="http://www.thecoast.ca/halifax/beta-the-public-transit-day-tripper/Content?oid=1098826">by now</a>, but what about the rest of the process? How do I get the data into a format that hbus.ca can consume?</p>  
<p>The defacto standard for the interchange of transit information is <a href="http://code.google.com/p/googletransitdatafeed">Google Transit Feed</a> (GTFS). This exceedingly simple comma seperated value format is now supported by a plethora of software, including <a href="http://google.com/transit">Google Transit</a>, <a href="http://github.com/bmander/graphserver">graphserver</a>, as well as my very own <a href="http://github.com/wlach/libroutez">libroutez</a> (used by hbus.ca). It was obvious to me right from the beginning that the first step to building hbus.ca would be to create one of these feeds. </p>  
<p>Manipulating a GTFS by hand is probably not a great idea. It&#8217;s basically a dump of a relational database, and is pretty inscrutable from the point of view of a human being. What I really want to be able to do is be able<br />  
to manipulate things on the level of stops, service periods, and routes&#8211; and let some kind of abstraction layer take care of the low-level details. Fortunately, the awesome engineers at google created a python library called <a href="http://code.google.com/p/googletransitdatafeed">Google Transit Data Feed</a>, which can help with creating one of these things by providing abstractions of the key elements of a google transit feed (stops, service periods, etc.). You can then write a program which uses these abstractions to create and save a GTFS.</p>  
<p>Of course, providing the library appropriate information is easier said than done. Metro Transit&#8217;s PDF schedules are not readily computer parsable (being designed to be printed out, after all). I needed some kind of semi-automated way of converting a Metro Transit schedule into GTFS, or this whole project was<br />  
going nowhere fast. </p>  
<p>As an initial step, it turns out that it&#8217;s quite possible to extract textual information from a PDF using the open source <a href="http://poppler.freedesktop.org/">popplar</a> library. From there, it&#8217;s possible to extract the stopping times for an individual bus route. Let&#8217;s give an example. For example, let&#8217;s take the case of adding the 60 (Portland Hill&#8217;s route), something I&#8217;m currently working on. All I had to do was download the PDF file from Metro Transit&#8217;s site and then run the following on the command line:<br />  
<code><br />  
pdftotext -raw route60.pdf<br />  
</code><br />  
The raw option basically makes sure the raw strings are dumped to disk, and that no attempt is made to preserve formatting. The result is a text file with content like this in it:<br />  
<code><br />  
842a 847a 855a 858a 903a 906a 912a -<br />  
857a 902a 910a 913a 918a 921a - 925a<br />  
910a 915a 923a 926a 931a 934a 940a -<br />  
940a 945a 953a - 1000a 1003a 1009a -<br />  
...and every 30 minutes until<br />  
210p 215p 223p - 230p 233p 239p -<br />  
</code><br />  
This type of format can be parsed easily enough. To create a proper transit feed though, schedule information isn&#8217;t enough: you also need to know the locations of the stops, names of routes, etc. After some deliberation, I came to the determination that I needed some kind of intermediate format to store the above schedule information and this additional information. It would be readable both by humans (to ease its creation) and machines.</p>  
<p>The obvious markup for something like this is <a href="http://yaml.org">YAML</a> (if you&#8217;re still using XML to store structured information, run, don&#8217;t walk, and look at YAML: you can thank me later). Simple, clean, effective. GTFS is still the better choice for using the information in another application as its representation is much more amenable to being stored in a graph. Here&#8217;s a few examples of my YAML format in action:</p>  
<p><a href="http://github.com/wlach/halifax-transit-feed/blob/fef68c18928272670b3c57ae5530260deed85883/7-robie-to-gottingen.yml">7 (Robie to Gottingen)</a><br />  
<a href="http://github.com/wlach/halifax-transit-feed/blob/fef68c18928272670b3c57ae5530260deed85883/10-to-westphal.yml">10 (Westphal)</a></p>  
<p>Besides the scheduling information, the other main interesting component of a GTFS is the location of the stops. As anyone who&#8217;s used a Metro Transit schedule has noticed, only major timepoints are covered in the PDF schedules. What of all the stops in between? This is where the bike and GPS come in.</p>  
<p>What I did was take a standard GPS from Mountain Equipment Co-op (The Garmin GPSMap 60x), get on my bike, take the readings of individual gotime numbers and positioning information, of the individual stops between the major timepoints. I then took this device back to my computer and, using a utility called <a href="http://gpsbabel.org">GPSBabel</a>, dumped out the stop information in a format called &#8220;comma seperated value&#8221;. It looks like this:<br />  
<code><br />  
44.65825, -63.59252, 6785-21-31-33-34-35-3-7<br />  
44.65982, -63.59452, 6768-21-31-33-35-86-3-7<br />  
44.66113, -63.59659, 6782-21-31-33-34-35-3-7<br />  
</code><br />  
The first two items are latitude and longitude, providing the positioning of the stop. The last item is a gotime number, followed by the set of buses which pass by the stop. Turning this into YAML is a matter of applying<br />  
the following regular expression to the input:<br />  
<code><br />  
\([0-9]+.[0-9]+\), \(-63.[0-9]+\), \([0-9]+\)- -> - { name: xxx, stop_code: \3, lat: \1, lng: \2 }<br />  
</code><br />  
To get an actual name for the stop (i.e.: &#8220;Gottingen and Young&#8221;), I wrote a simple script which finds the nearest intersection close to the stop in the <a href="http://geobase.ca">GeoBase</a> dataset. I then (at my discretion) corrected it based on my on-the-street knowledge of the layout of Halifax as well as adding certain details to help the user (e.g. bus stops on the way to the south end of Halifax are marked &#8220;south bound&#8221;).</p>  
<p>With these two elements in place (a format for creating human-readable transit information and a library for creating GTFS), the only thing left to do is create a program which bridges the gap. Behold, the magic of<br />  
<a href="http://github.com/wlach/halifax-transit-feed/blob/fef68c18928272670b3c57ae5530260deed85883/createfeed.py">createfeed.py</a>. With all of this in place, creating a google transit feed for Halifax is a simple matter of typing &#8220;make&#8221;.</p>  
<p>Is this a ridiculous amount of work? I wouldn&#8217;t say so. The vast, vast majority of my work on hbus.ca has been in creating the pathfinding code and geocoding functionality. This is work that can be translated to many different municipalities, and can easily be extended and made more useful in a myriad of ways.</p>  
<p>What does seem a little intimidating to me is completing what I started. Capturing bus stop information for the Halifax peninsula is one thing, but covering the outlying areas (Bayer&#8217;s Lake, Sackville, etc.) is quite<br />  
another. There&#8217;s a lot of biking involved there, more perhaps than what one person can reasonably be expected to do. It was my hope that the initial release of hbus would validate the model of community-developed transit software to Metro Transit and they would see the benefit of releasing their internal copy of this data to the public, but unfortunately that doesn&#8217;t seem to have happened. </p>  
<p>Getting that problem solved seems to be more a political problem than a technical one, and it&#8217;s not my specialty. It really does make me wonder if I shouldn&#8217;t reconsider the option of crowd sourcing, which I had<br />  
<a href="http://masalalabs.ca/2009/03/hbusca-and-thoughts-about-crowdsourcing/">rejected</a> earlier.</p>  
</div>  
 
<p class="postmetadata"> Posted in <a href="http://hbus.ca/blog/?cat=1" title="View all posts in Uncategorized" rel="category">Uncategorized</a> | <a href="http://hbus.ca/blog/?p=9#respond" title="Comment on Creating a google transit feed for fun and profit">No Comments &#187;</a></p>  
</div>  
 
 
<div class="navigation">  
<div class="alignleft"></div>  
<div class="alignright"></div>  
</div>  
 
 
</div>  
</div>  
 
<div id="footer">  
<!-- If you'd like to support WordPress, having the "powered by" link somewhere on your blog is the best way; it's our only promotion or advertising. -->  
<p>  
hbus.ca: Blog is proudly powered by  
<a href="http://wordpress.org/">WordPress</a>  
<br /><a href="http://hbus.ca/blog/?feed=rss2">Entries (RSS)</a>  
and <a href="http://hbus.ca/blog/?feed=comments-rss2">Comments (RSS)</a>.  
<!-- 22 queries. 0.225 seconds. -->  
</p>  
</div>  
</div>  
 
<script>  
(function() {  
var Dom = YAHOO.util.Dom,  
Event = YAHOO.util.Event;  
 
Event.onDOMReady(function() {  
var layout = new YAHOO.widget.Layout({  
units: [  
{ position: 'top', body: 'header', gutter: '0', height: 60 },  
{ position: 'center', body: 'content', gutter: '0' },  
]  
});  
layout.render();  
});  
})();  
</script>  
</body>  
</html>  
</div>  
 
 
 Binary files a/origin-src/wlach-halifax-transit-feed-fef68c1.tar.gz and /dev/null differ
hfxfeed.zip  
hfxtable.yml  
*~  
short_name: 1  
long_name: To Dartmouth  
time_points: [ 7284, 7412, 6087, 7351, 7151 ]  
between_stops:  
7284-7412: [ 6203, 7423 ]  
7412-6087: [ 7419, 7409, 7402, 6453, 6447, 6449, 6454, 6452, 8328, 8337, 8333, 8336, 8327, 8338, 6121, 6106 ]  
6087-7351: [ 6455, 6773, 6778, 6779, 6775, 6787 ]  
stop_times: [  
[ -, -, -, 604a, 607a],  
[ 600a, 611a, 625a, 633a, 637a],  
[ 610a, 621a, 635a, 643a, 647a],  
[ 620a, 631a, 645a, 653a, 657a],  
[ 630a, 641a, 655a, 703a, 707a],  
[ 640a, 651a, 705a, 713a, 717a],  
[ 650a, 701a, 716a, 724a, 728a],  
[ 700a, 713a, 728a, 736a, 740a],  
[ 710a, 723a, 738a, 746a, 750a],  
[ 720a, 733a, 748a, 756a, 800a],  
[ 730a, 743a, 758a, 806a, 810a],  
[ 740a, 753a, 808a, 816a, 820a],  
[ 750a, 803a, 818a, 826a, 830a],  
[ 800a, 813a, 828a, 836a, 840a],  
[ 810a, 823a, 838a, 846a, 850a],  
[ 820a, 833a, 848a, 856a, 900a],  
[ 830a, 843a, 858a, 906a, 910a],  
[ 840a, 853a, 908a, 916a, 920a],  
[ 855a, 908a, 923a, 931a, 935a],  
[ 910a, 923a, 938a, 946a, 950a],  
[ 925a, 938a, 953a, 1001a, 1005a],  
[ 940a, 953a, 1008a, 1016a, 1020a],  
[ 955a, 1008a, 1023a, 1031a, 1035a],  
[ 1010a, 1023a, 1038a, 1046a, 1050a],  
[ 1025a, 1038a, 1053a, 1101a, 1105a],  
[ 1040a, 1053a, 1108a, 1116a, 1120a],  
[ 1055a, 1108a, 1123a, 1131a, 1135a],  
[ 1110a, 1123a, 1138a, 1146a, 1150a],  
[ 1125a, 1138a, 1153a, 1201p, 1205p],  
[ 1140a, 1153a, 1208p, 1216p, 1220p],  
[ 1155a, 1208p, 1223p, 1231p, 1235p],  
[ 1210p, 1223p, 1238p, 1246p, 1250p],  
[ 1225p, 1238p, 1253p, 101p, 105p],  
[ 1240p, 1253p, 108p, 116p, 120p],  
[ 1255p, 108p, 123p, 131p, 135p],  
[ 110p, 123p, 138p, 146p, 150p],  
[ 125p, 138p, 153p, 201p, 205p],  
[ 140p, 153p, 208p, 216p, 220p],  
[ 155p, 208p, 223p, 231p, 235p],  
[ 210p, 223p, 238p, 246p, 250p],  
[ 225p, 238p, 253p, 301p, 305p],  
[ 240p, 253p, 308p, 316p, 320p],  
[ 255p, 308p, 323p, 331p, 335p],  
[ 320p, 333p, 348p, 356p, 400p],  
[ 340p, 353p, 408p, 416p, 420p],  
[ 400p, 413p, 428p, 436p, 440p],  
[ 420p, 433p, 448p, 456p, 500p],  
[ 430p, 443p, 458p, 506p, 510p],  
[ 450p, 503p, 518p, 526p, 530p],  
[ 500p, 513p, 528p, 536p, 540p],  
[ 510p, 523p, 538p, 546p, 550p],  
[ 520p, 533p, 548p, 556p, 600p],  
[ 530p, 543p, 558p, 606p, 610p],  
[ 540p, 553p, 608p, 616p, 620p],  
[ 550p, 603p, 618p, 626p, 630p],  
[ 600p, 613p, 627p, 635p, 639p],  
[ 615p, 626p, 640p, 648p, 652p],  
[ 630p, 641p, 655p, 703p, 707p],  
[ 645p, 656p, 710p, 718p, 722p],  
[ 700p, 711p, 725p, 733p, 737p],  
[ 715p, 726p, 740p, 748p, 752p],  
[ 730p, 741p, 755p, 803p, 807p],  
[ 745p, 756p, 810p, 818p, 822p],  
[ 800p, 811p, 825p, 833p, 837p],  
[ 815p, 826p, 840p, 848p, 852p],  
[ 830p, 841p, 855p, 903p, 907p],  
[ 845p, 856p, 910p, 918p, 922p],  
[ 900p, 911p, 925p, 933p, 937p],  
[ 915p, 926p, 940p, 948p, 952p],  
[ 930p, 941p, 955p, 1003p, 1007p],  
[ 945p, 956p, 1010p, 1018p, 1022p],  
[ 1000p, 1011p, 1025p, 1033p, 1037p],  
[ 1015p, 1026p, 1040p, 1048p, 1052p],  
[ 1030p, 1041p, 1055p, 1103p, 1107p],  
[ 1045p, 1056p, 1110p, 1118p, 1122p],  
[ 1115p, 1126p, 1140p, 1148p, 1152p],  
[ 1150p, 1201x, 1215x, 1221x, 1225x],  
[ 1215x, 1226x, 1240x, 1248x, 1252x]  
]  
stop_times_saturday: [  
[ -, -, -, 602a, 605a],  
[ -, -, -, -, -],  
[ 605a, 616a, 628a, 634a, 637a],  
[ 620a, 631a, 643a, 649a, 652a],  
[ 635a, 646a, 658a, 704a, 707a],  
[ 650a, 701a, 713a, 719a, 722a],  
[ 705a, 716a, 728a, 734a, 737a],  
[ 720a, 731a, 743a, 749a, 752a],  
[ 735a, 746a, 758a, 804a, 807a],  
[ 750a, 801a, 813a, 819a, 822a],  
[ 805a, 816a, 828a, 834a, 837a],  
[ 820a, 831a, 843a, 849a, 852a],  
[ 835a, 846a, 858a, 904a, 907a],  
[ 850a, 901a, 913a, 919a, 922a],  
[ 905a, 916a, 928a, 934a, 937a],  
[ 920a, 931a, 943a, 949a, 952a],  
[ 935a, 946a, 958a, 1004a, 1007a],  
[ 950a, 1001a, 1013a, 1019a, 1022a],  
[ 1005a, 1016a, 1028a, 1034a, 1037a],  
[ 1020a, 1031a, 1043a, 1049a, 1052a],  
[ 1035a, 1046a, 1058a, 1104a, 1107a],  
[ 1050a, 1101a, 1113a, 1119a, 1122a],  
[ 1105a, 1116a, 1128a, 1134a, 1137a],  
[ 1120a, 1131a, 1143a, 1149a, 1152a],  
[ 1135a, 1146a, 1158a, 1204p, 1207p],  
[ 1150a, 1201p, 1213p, 1219p, 1222p],  
[ 1205p, 1216p, 1228p, 1234p, 1237p],  
[ 1220p, 1231p, 1243p, 1249p, 1253p],  
[ 1233p, 1244p, 1258p, 105p, 109p],  
[ 1245p, 1257p, 113p, 120p, 124p],  
[ 100p, 112p, 128p, 135p, 139p],  
[ 115p, 127p, 143p, 150p, 154p],  
[ 130p, 142p, 158p, 205p, 209p],  
[ 145p, 157p, 213p, 220p, 224p],  
[ 200p, 212p, 228p, 235p, 239p],  
[ 215p, 227p, 243p, 250p, 254p],  
[ 230p, 242p, 258p, 305p, 309p],  
[ 245p, 257p, 313p, 320p, 324p],  
[ 300p, 312p, 328p, 335p, 339p],  
[ 315p, 327p, 343p, 350p, 354p],  
[ 330p, 342p, 359p, 405p, 409p],  
[ 345p, 357p, 413p, 420p, 424p],  
[ 400p, 412p, 428p, 435p, 439p],  
[ 415p, 427p, 443p, 450p, 454p],  
[ 430p, 442p, 458p, 505p, 509p],  
[ 445p, 457p, 513p, 520p, 524p],  
[ 500p, 511p, 528p, 535p, 539p],  
[ 515p, 527p, 543p, 550p, 554p],  
[ 530p, 542p, 559p, 604p, 607p],  
[ 545p, 556p, 610p, 614p, 618p],  
[ 600p, 611p, 623p, 629p, 632p],  
[ 615p, 626p, 638p, 644p, 647p],  
[ 635p, 646p, 658p, 704p, 707p],  
[ 650p, 701p, 713p, 719p, 722p],  
[ 705p, 716p, 728p, 734p, 737p],  
[ 720p, 731p, 743p, 749p, 752p],  
[ 735p, 746p, 758p, 804p, 807p],  
[ 750p, 801p, 813p, 819p, 822p],  
[ 805p, 816p, 828p, 834p, 837p],  
[ 820p, 831p, 843p, 849p, 852p],  
[ 835p, 846p, 858p, 904p, 907p],  
[ 850p, 901p, 913p, 919p, 922p],  
[ 905p, 916p, 928p, 934p, 937p],  
[ 920p, 931p, 943p, 949p, 952p],  
[ 935p, 946p, 958p, 1004p, 1007p],  
[ 950p, 1001p, 1013p, 1019p, 1022p],  
[ 1005p, 1016p, 1028p, 1034p, 1037p],  
[ 1020p, 1031p, 1043p, 1049p, 1052p],  
[ 1035p, 1046p, 1058p, 1104p, 1107p],  
[ 1050p, 1101p, 1113p, 1119p, 1122p],  
[ 1105p, 1116p, 1128p, 1134p, 1137p],  
[ 1135p, 1146p, 1158p, 1204x, 1207x],  
[ 1205x, 1216x, 1228x, 1234x, 1237x]]  
stop_times_sunday: [  
[ 640a, 649a, 700a, 705a, 709a],  
[ 710a, 719a, 730a, 735a, 739a],  
[ 740a, 749a, 800a, 805a, 809a],  
[ 810a, 819a, 830a, 835a, 839a],  
[ 840a, 849a, 900a, 905a, 909a],  
[ 910a, 919a, 930a, 935a, 939a],  
[ 940a, 949a, 1000a, 1005a, 1009a],  
[ 1010a, 1019a, 1030a, 1035a, 1039a],  
[ 1040a, 1049a, 1100a, 1105a, 1109a],  
[ 1055a, 1104a, 1115a, 1120a, 1124a],  
[ 1110a, 1119a, 1130a, 1135a, 1139a],  
[ 1125a, 1134a, 1145a, 1150a, 1154a],  
[ 1140a, 1149a, 1200p, 1205p, 1209p],  
[ 1155a, 1204p, 1215p, 1220p, 1224p],  
[ 1210p, 1219p, 1230p, 1235p, 1239p],  
[ 1225p, 1234p, 1245p, 1250p, 1254p],  
[ 1240p, 1249p, 100p, 105p, 109p],  
[ 1255p, 104p, 115p, 120p, 124p],  
[ 110p, 119p, 130p, 135p, 139p],  
[ 125p, 134p, 145p, 150p, 154p],  
[ 140p, 149p, 200p, 205p, 209p],  
[ 155p, 204p, 215p, 220p, 224p],  
[ 210p, 219p, 230p, 235p, 239p],  
[ 225p, 234p, 245p, 250p, 254p],  
[ 240p, 249p, 300p, 305p, 309p],  
[ 255p, 304p, 315p, 320p, 324p],  
[ 310p, 319p, 330p, 335p, 339p],  
[ 325p, 334p, 345p, 350p, 354p],  
[ 340p, 349p, 400p, 405p, 409p],  
[ 355p, 404p, 415p, 420p, 424p],  
[ 410p, 419p, 430p, 435p, 439p],  
[ 425p, 434p, 445p, 450p, 454p],  
[ 440p, 449p, 500p, 505p, 509p],  
[ 455p, 504p, 515p, 520p, 524p],  
[ 510p, 519p, 530p, 535p, 539p],  
[ 525p, 534p, 545p, 550p, 554p],  
[ 540p, 549p, 600p, 605p, 609p],  
[ 555p, 604p, 615p, 620p, 624p],  
[ 610p, 619p, 630p, 635p, 639p],  
[ 640p, 649p, 700p, 705p, 709p],  
[ 710p, 719p, 730p, 735p, 739p],  
[ 740p, 749p, 800p, 805p, 809p],  
[ 810p, 819p, 830p, 835p, 839p],  
[ 840p, 849p, 900p, 905p, 909p],  
[ 910p, 919p, 930p, 935p, 939p],  
[ 940p, 949p, 1000p, 1005p, 1009p],  
[ 1010p, 1019p, 1030p, 1035p, 1039p],  
[ 1040p, 1049p, 1100p, 1105p, 1109p],  
[ 1110p, 1119p, 1130p, 1135p, 1139p],  
[ 1140p, 1149p, 1200x, 1205x, 1209x]  
]  
 
short_name: 1  
long_name: To Mumford  
time_points: [ 7151, 6105, 7421, 7284 ]  
between_stops:  
7151-6105: [ 8638, 6088, 6104, 6125 ]  
6105-7421: [ 6108, 6103, 6102, 6122, 8331, 8330, 8334, 8335, 8329, 8332, 6448, 6450, 6451, 7401, 7403, 7410, 7406 ]  
7421-7284: [ 7404, 6201, 6200 ]  
stop_times: [  
[ 610a, 620a, 633a, 644a],  
[ 640a, 650a, 703a, 714a],  
[ 705a, 715a, 728a, 742a],  
[ 715a, 725a, 738a, 752a],  
[ 735a, 745a, 758a, 812a],  
[ 755a, 805a, 818a, 832a],  
[ 815a, 825a, 838a, 852a],  
[ 836a, 846a, 859a, 913a],  
[ 845a, 855a, 908a, 922a],  
[ 855a, 905a, 918a, 932a],  
[ 905a, 915a, 928a, 942a],  
[ 915a, 925a, 938a, 952a],  
[ 925a, 935a, 948a, 1002a],  
[ 940a, 950a, 1003a, 1017a],  
[ 955a, 1005a, 1018a, 1032a],  
[ 1010a, 1020a, 1033a, 1047a],  
[ 1025a, 1035a, 1048a, 1102a],  
[ 1040a, 1050a, 1103a, 1117a],  
[ 1055a, 1105a, 1118a, 1132a],  
[ 1110a, 1120a, 1133a, 1147a],  
[ 1125a, 1135a, 1148a, 1202p],  
[ 1140a, 1150a, 1203p, 1217p],  
[ 1155a, 1205p, 1218p, 1232p],  
[ 1210p, 1220p, 1233p, 1247p],  
[ 1225p, 1235p, 1248p, 102p],  
[ 1240p, 1250p, 103p, 117p],  
[ 1255p, 105p, 118p, 132p],  
[ 110p, 120p, 133p, 147p],  
[ 125p, 135p, 148p, 202p],  
[ 140p, 150p, 203p, 217p],  
[ 155p, 205p, 218p, 232p],  
[ 210p, 220p, 233p, 247p],  
[ 225p, 235p, 248p, 302p],  
[ 240p, 250p, 303p, 317p],  
[ 255p, 305p, 318p, 332p],  
[ 310p, 320p, 333p, 347p],  
[ 325p, 335p, 351p, 405p],  
[ 335p, 345p, 401p, 415p],  
[ 345p, 355p, 411p, 425p],  
[ 355p, 405p, 421p, 435p],  
[ 405p, 415p, 431p, 445p],  
[ 415p, 425p, 441p, 455p],  
[ 425p, 435p, 451p, 505p],  
[ 435p, 445p, 501p, 515p],  
[ 445p, 455p, 511p, 525p],  
[ 455p, 505p, 521p, 535p],  
[ 505p, 515p, 531p, 545p],  
[ 515p, 525p, 541p, 555p],  
[ 525p, 535p, 551p, 605p],  
[ 540p, 550p, 606p, 620p],  
[ 555p, 605p, 621p, 635p],  
[ 610p, 620p, 636p, 650p],  
[ 625p, 635p, 651p, 705p],  
[ 640p, 650p, 706p, 720p],  
[ 655p, 705p, 721p, 735p],  
[ 710p, 720p, 736p, 750p],  
[ 725p, 735p, 751p, 805p],  
[ 740p, 750p, 804p, 818p],  
[ 755p, 805p, 818p, 832p],  
[ 810p, 820p, 833p, 847p],  
[ 825p, 835p, 848p, 902p],  
[ 840p, 850p, 903p, 917p],  
[ 855p, 905p, 918p, 932p],  
[ 910p, 920p, 933p, 947p],  
[ 925p, 935p, 948p, 1002p],  
[ 940p, 950p, 1003p, 1017p],  
[ 955p, 1005p, 1018p, 1032p],  
[ 1010p, 1020p, 1033p, 1047p],  
[ 1025p, 1035p, 1048p, 1102p],  
[ 1040p, 1050p, 1103p, 1114p],  
[ 1055p, 1105p, 1116p, 1127p],  
[ 1125p, 1135p, 1146p, 1157p],  
[ 1155p, 1205x, 1216x, 1227x],  
[ 1226x, 1236x, 1247x, 1258x]  
]  
stop_times_saturday: [  
[ 600a, 608a, 621a, 632a],  
[ 620a, 628a, 641a, 652a],  
[ 640a, 648a, 701a, 712a],  
[ 655a, 703a, 716a, 727a],  
[ 710a, 718a, 731a, 742a],  
[ 725a, 733a, 746a, 757a],  
[ 740a, 748a, 801a, 812a],  
[ 755a, 803a, 816a, 827a],  
[ 810a, 818a, 831a, 842a],  
[ 825a, 833a, 846a, 857a],  
[ 840a, 848a, 901a, 912a],  
[ 855a, 903a, 916a, 927a],  
[ 910a, 918a, 931a, 942a],  
[ 925a, 933a, 946a, 957a],  
[ 940a, 948a, 1001a, 1012a],  
[ 955a, 1003a, 1016a, 1027a],  
[ 1010a, 1018a, 1031a, 1042a],  
[ 1025a, 1033a, 1046a, 1057a],  
[ 1040a, 1049a, 1102a, 1113a],  
[ 1055a, 1104a, 1117a, 1128a],  
[ 1110a, 1119a, 1132a, 1143a],  
[ 1125a, 1134a, 1147a, 1158a],  
[ 1140a, 1149a, 1202p, 1215p],  
[ 1155a, 1204p, 1219p, 1232p],  
[ 1210p, 1220p, 1235p, 1248p],  
[ 1225p, 1235p, 1250p, 103p],  
[ 1240p, 1250p, 105p, 118p],  
[ 1255p, 105p, 120p, 133p],  
[ 110p, 120p, 135p, 148p],  
[ 125p, 135p, 150p, 203p],  
[ 140p, 150p, 205p, 218p],  
[ 155p, 205p, 220p, 233p],  
[ 210p, 220p, 235p, 248p],  
[ 225p, 235p, 250p, 303p],  
[ 240p, 250p, 305p, 318p],  
[ 255p, 305p, 320p, 333p],  
[ 310p, 320p, 335p, 348p],  
[ 325p, 335p, 350p, 403p],  
[ 340p, 350p, 405p, 418p],  
[ 355p, 405p, 420p, 433p],  
[ 410p, 420p, 435p, 448p],  
[ 425p, 435p, 450p, 459p],  
[ 440p, 450p, 504p, 514p],  
[ 455p, 505p, 518p, 529p],  
[ 510p, 520p, 532p, 543p],  
[ 525p, 535p, 547p, 558p],  
[ 540p, 550p, 602p, 613p],  
[ 555p, 605p, 617p, 628p],  
[ 610p, 620p, 632p, 643p],  
[ 625p, 635p, 647p, 658p],  
[ 640p, 650p, 702p, 713p],  
[ 710p, 720p, 732p, 743p],  
[ 725p, 735p, 747p, 758p],  
[ 740p, 750p, 802p, 813p],  
[ 755p, 805p, 817p, 828p],  
[ 810p, 820p, 832p, 843p],  
[ 825p, 835p, 847p, 858p],  
[ 840p, 850p, 902p, 913p],  
[ 855p, 905p, 917p, 928p],  
[ 910p, 920p, 932p, 943p],  
[ 925p, 935p, 947p, 958p],  
[ 940p, 950p, 1002p, 1013p],  
[ 955p, 1005p, 1017p, 1028p],  
[ 1010p, 1020p, 1032p, 1043p],  
[ 1025p, 1035p, 1047p, 1058p],  
[ 1040p, 1050p, 1102p, 1113p],  
[ 1055p, 1105p, 1117p, 1128p],  
[ 1125p, 1135p, 1147p, 1158p],  
[ 1155p, 1205x, 1217x, 1228x],  
[ 1225x, 1235x, 1247x, 1258x]  
]  
stop_times_sunday: [  
[ 655a, 709a, 720a, 729a],  
[ 716a, 730a, 741a, 750a],  
[ 746a, 800a, 811a, 820a],  
[ 816a, 830a, 841a, 850a],  
[ 846a, 900a, 911a, 920a],  
[ 916a, 930a, 941a, 950a],  
[ 946a, 1000a, 1011a, 1020a],  
[ 1016a, 1030a, 1041a, 1050a],  
[ 1031a, 1045a, 1056a, 1105a],  
[ 1046a, 1100a, 1111a, 1120a],  
[ 1101a, 1115a, 1126a, 1135a],  
[ 1116a, 1130a, 1141a, 1150a],  
[ 1131a, 1145a, 1156a, 1205p],  
[ 1146a, 1200p, 1211p, 1220p],  
[ 1201p, 1215p, 1226p, 1235p],  
[ 1216p, 1230p, 1241p, 1250p],  
[ 1231p, 1245p, 1256p, 105p],  
[ 1246p, 100p, 111p, 120p],  
[ 101p, 115p, 126p, 135p],  
[ 116p, 130p, 141p, 150p],  
[ 131p, 145p, 156p, 205p],  
[ 146p, 200p, 211p, 220p],  
[ 201p, 215p, 226p, 235p],  
[ 216p, 230p, 241p, 250p],  
[ 231p, 245p, 256p, 305p],  
[ 246p, 300p, 311p, 320p],  
[ 301p, 315p, 326p, 335p],  
[ 316p, 330p, 341p, 350p],  
[ 331p, 345p, 356p, 405p],  
[ 346p, 400p, 411p, 420p],  
[ 401p, 415p, 426p, 435p],  
[ 416p, 430p, 441p, 450p],  
[ 431p, 445p, 456p, 505p],  
[ 446p, 500p, 511p, 520p],  
[ 501p, 515p, 526p, 535p],  
[ 516p, 530p, 541p, 550p],  
[ 531p, 545p, 556p, 605p],  
[ 546p, 600p, 611p, 620p],  
[ 616p, 630p, 641p, 650p],  
[ 646p, 700p, 711p, 720p],  
[ 716p, 730p, 741p, 750p],  
[ 746p, 800p, 811p, 820p],  
[ 816p, 830p, 841p, 850p],  
[ 846p, 900p, 911p, 920p],  
[ 916p, 930p, 941p, 950p],  
[ 946p, 1000p, 1011p, 1020p],  
[ 1016p, 1030p, 1041p, 1050p],  
[ 1046p, 1100p, 1111p, 1120p],  
[ 1116p, 1130p, 1141p, 1150p],  
[ 1146p, 1200x, 1211x, 1220x]  
]  
 
short_name: 10  
long_name: To Dalhousie  
time_points: [ 6974, 8368, 7218, 6842, 6105, 6966, 7144 ]  
between_stops:  
6974-8368: [ 8160, 8161, 8162, 8483, 8484, 8482, 8319 ]  
8368-7218: [ 6835, 7175, 7209 ]  
7218-6842: [ 7211, 7215, 8581, 8583, 8584, 8585, 8424, 8419, 8429, 8427, 8389, 8392, 8614 ]  
6842-6105: [ 7351, 6088, 6104, 6125 ]  
6105-6966: [ 6108, 6103, 6102, 6122, 8331, 8330, 8334, 8313, 8311, 8315, 6960 ]  
stop_times: [  
[ 544a, 553a, 558a, 608a, 618a, 626a, 638a],  
[ 613a, 622a, 628a, 638a, 648a, 656a, 708a],  
[ 638a, 647a, 654a, 705a, 715a, 723a, 735a],  
[ 653a, 702a, 709a, 720a, 730a, 738a, 750a],  
[ -, 715a, 722a, 733a, 743a, 751a, 803a],  
[ 708a, 717a, 724a, 735a, 745a, 753a, 805a],  
[ 723a, 732a, 739a, 750a, 800a, 808a, 820a],  
[ -, -, 749a, 800a, 810a, 818a, 830a],  
[ 738a, 747a, 754a, 805a, 815a, 823a, 835a],  
[ -, -, 801a, 812a, 822a, 830a, 842a],  
[ 753a, 802a, 809a, 820a, 830a, 838a, 850a],  
[ -, -, 816a, 827a, 837a, 845a, 857a],  
[ 808a, 817a, 824a, 835a, 845a, 853a, 905a],  
[ 823a, 832a, 839a, 850a, 900a, 908a, 920a],  
[ 838a, 847a, 854a, 905a, 915a, 923a, 935a],  
[ 908a, 917a, 924a, 935a, 945a, 953a, 1005a],  
[ 938a, 947a, 954a, 1005a, 1015a, 1023a, 1035a],  
[ 1008a, 1017a, 1024a, 1035a, 1045a, 1053a, 1105a],  
[ 1038a, 1047a, 1054a, 1105a, 1115a, 1123a, 1135a],  
[ 1108a, 1117a, 1124a, 1135a, 1145a, 1153a, 1205p],  
[ 1138a, 1147a, 1154a, 1205p, 1215p, 1223p, 1235p],  
[ 1208p, 1217p, 1224p, 1235p, 1245p, 1253p, 105p],  
[ 1238p, 1247p, 1254p, 105p, 115p, 123p, 135p],  
[ 108p, 117p, 124p, 135p, 145p, 153p, 205p],  
[ 138p, 147p, 154p, 205p, 215p, 223p, 235p],  
[ 208p, 217p, 224p, 235p, 245p, 253p, 305p],  
[ 238p, 247p, 254p, 305p, 315p, 323p, 335p],  
[ 308p, 317p, 324p, 335p, 345p, 353p, 405p],  
[ 338p, 347p, 354p, 405p, 415p, 423p, 435p],  
[ 408p, 417p, 424p, 435p, 445p, 453p, 505p],  
[ 423p, 432p, 439p, 450p, 500p, 508p, 520p],  
[ 438p, 447p, 454p, 505p, 515p, 523p, 535p],  
[ 449p, 458p, 505p, 516p, -, -, -],  
[ 453p, 502p, 509p, 520p, 530p, 538p, 550p],  
[ 508p, 517p, 524p, 535p, 545p, 553p, 605p],  
[ 523p, 532p, 539p, 550p, -, -, -],  
[ 538p, 547p, 554p, 605p, 615p, 623p, 635p],  
[ 547p, 556p, 602p, 613p, -, -, -],  
[ 553p, 602p, 607p, 618p, -, -, -],  
[ 605p, 614p, 619p, 630p, 640p, 648p, 700p],  
[ 622p, 631p, 636p, 647p, -, -, -],  
[ 640p, 649p, 654p, 705p, 715p, 723p, 735p],  
[ 700p, 709p, 714p, 725p, 735p, 743p, 755p],  
[ 730p, 739p, 744p, 755p, 805p, 813p, 825p],  
[ 800p, 809p, 814p, 825p, 835p, 843p, 855p],  
[ 830p, 839p, 844p, 855p, 905p, 913p, 925p],  
[ 900p, 909p, 914p, 925p, 935p, 943p, 955p],  
[ 930p, 939p, 944p, 955p, 1005p, 1013p, 1025p],  
[ 1000p, 1009p, 1014p, 1025p, 1035p, 1043p, 1055p],  
[ 1030p, 1039p, 1044p, 1055p, 1105p, 1113p, 1125p],  
[ 1100p, 1109p, 1114p, 1125p, 1135p, 1143p, 1155p],  
[ 1130p, 1139p, 1144p, 1155p, -, -, -],  
[ 1200x, 1209x, 1214x, 1225x, -, -, -]  
]  
stop_times_saturday: [  
[ 603a, 612a, 620a, 630a, 640a, 648a, 700a],  
[ 633a, 642a, 650a, 700a, 710a, 718a, 730a],  
[ 703a, 712a, 720a, 730a, 740a, 748a, 800a],  
[ 733a, 742a, 750a, 800a, 810a, 818a, 830a],  
[ 803a, 812a, 820a, 830a, 840a, 848a, 900a],  
[ 833a, 842a, 850a, 900a, 910a, 918a, 930a],  
[ 903a, 912a, 920a, 930a, 940a, 948a, 1000a],  
[ 933a, 942a, 950a, 1000a, 1010a, 1018a, 1030a],  
[ 1003a, 1012a, 1020a, 1030a, 1040a, 1048a, 1100a],  
[ 1033a, 1042a, 1050a, 1100a, 1110a, 1118a, 1130a],  
[ 1103a, 1112a, 1120a, 1130a, 1140a, 1148a, 1200p],  
[ 1133a, 1142a, 1150a, 1200p, 1210p, 1218p, 1230p],  
[ 1203p, 1212p, 1220p, 1230p, 1240p, 1248p, 100p],  
[ 1233p, 1242p, 1250p, 100p, 110p, 118p, 130p],  
[ 103p, 112p, 120p, 130p, 140p, 148p, 200p],  
[ 133p, 142p, 150p, 200p, 210p, 218p, 230p],  
[ 203p, 212p, 220p, 230p, 240p, 248p, 300p],  
[ 233p, 242p, 250p, 300p, 310p, 318p, 330p],  
[ 303p, 312p, 320p, 330p, 340p, 348p, 400p],  
[ 333p, 342p, 350p, 400p, 410p, 418p, 430p],  
[ 403p, 412p, 420p, 430p, 440p, 448p, 500p],  
[ 433p, 442p, 450p, 500p, 510p, 518p, 530p],  
[ 503p, 512p, 520p, 530p, 540p, 548p, 600p],  
[ 533p, 542p, 550p, 600p, 610p, 618p, 630p],  
[ 603p, 612p, 620p, 630p, 640p, 648p, 700p],  
[ 633p, 642p, 650p, 700p, 710p, 718p, 730p],  
[ 703p, 712p, 720p, 730p, 740p, 748p, 800p],  
[ 733p, 742p, 750p, 800p, 810p, 818p, 830p],  
[ 803p, 812p, 820p, 830p, 840p, 848p, 900p],  
[ 833p, 842p, 850p, 900p, 910p, 918p, 930p],  
[ 903p, 912p, 920p, 930p, 940p, 948p, 1000p],  
[ 933p, 942p, 950p, 1000p, 1010p, 1018p, 1030p],  
[ 1003p, 1012p, 1020p, 1030p, 1040p, 1048p, 1100p],  
[ 1033p, 1042p, 1050p, 1100p, 1110p, 1118p, 1130p],  
[ 1103p, 1112p, 1120p, 1130p, 1140p, 1148p, 1200x],  
[ 1133p, 1142p, 1150p, 1200x, 1210x, 1218x, 1230x],  
[ 1200x, 1207x, 1215x, 1225x, -, -, -]  
]  
stop_times_sunday: [  
[ 712a, 721a, 729a, 740a, 750a, 759a, 809a],  
[ 812a, 821a, 829a, 840a, 850a, 859a, 909a],  
[ 912a, 921a, 929a, 940a, 950a, 959a, 1009a],  
[ 1012a, 1021a, 1029a, 1040a, 1050a, 1059a, 1109a],  
[ 1112a, 1121a, 1129a, 1140a, 1150a, 1159a, 1209p],  
[ 1212p, 1221p, 1229p, 1240p, 1250p, 1259p, 109p],  
[ 112p, 121p, 129p, 140p, 150p, 159p, 209p],  
[ 212p, 221p, 229p, 240p, 250p, 259p, 309p],  
[ 312p, 321p, 329p, 340p, 350p, 359p, 409p],  
[ 412p, 421p, 429p, 440p, 450p, 459p, 509p],  
[ 512p, 521p, 529p, 540p, 550p, 559p, 609p],  
[ 612p, 621p, 629p, 640p, 650p, 659p, 709p],  
[ 712p, 721p, 729p, 740p, 750p, 759p, 809p],  
[ 812p, 821p, 829p, 840p, 850p, 859p, 909p],  
[ 912p, 921p, 929p, 940p, 950p, 959p, 1009p],  
[ 1012p, 1021p, 1029p, 1040p, 1050p, 1059p, 1109p],  
[ 1112p, 1121p, 1129p, 1140p, -, -, -],  
[ 1212x, 1221x, -, -, -, -, -]  
]  
 
short_name: 10  
long_name: To Westphal  
time_points: [ 7144, 6965, 8312, 6087, 8640, 7219, 8369, 8598, 6974 ]  
between_stops:  
7144-6965: [ 8304, 6206, 6209, 6208, 6961, 6962, 6965 ]  
6965-8312: [ 6969, 8314, 8306, 8307, 8309, 8312 ]  
8312-6087: [ 8336, 8327, 8338, 6121, 6106 ]  
6087-8640: [ 6455, 6773, 6778, 6779, 6775, 6787, 7351 ]  
8640-7219: [ 8616, 6304, 6303, 8428, 8587, 8580, 8586, 8582, 7214, 7213 ]  
7219-8369: [ 7210, 7173, 6834, 8369 ]  
8369-8598: [ 8416, 8323, 8320, 8603 ]  
8598-6974: [ 6306, 6305, 7053, 7052, 7051, 6369, 6591, 6592, 7057 ]  
stop_times: [  
[ -, -, -, -, -, -, 535a, 539a, 543a],  
[ -, -, -, -, 553a, 559a, 604a, 608a, 612a],  
[ -, -, -, -, -, -, 629a, 633a, 637a],  
[ -, -, -, -, -, -, 644a, 648a, 652a],  
[ -, -, -, -, 643a, 650a, 657a, 701a, 707a],  
[ -, -, -, -, 656a, 704a, 711a, 715a, 721a],  
[ 641a, 646a, 651a, 658a, 709a, 719a, 726a, 730a, 736a],  
[ -, -, -, -, 725a, 735a, 742a, 746a, 752a],  
[ 710a, 715a, 721a, 728a, 740a, 750a, 757a, 801a, 807a],  
[ 725a, 730a, 736a, 743a, 755a, 805a, 812a, 816a, 822a],  
[ 740a, 745a, 751a, 758a, 810a, 820a, 827a, 831a, 837a],  
[ 810a, 815a, 821a, 828a, 840a, 850a, 857a, 901a, 907a],  
[ 825a, 830a, 836a, 843a, 855a, -, -, -, -],  
[ 840a, 845a, 851a, 858a, 910a, 920a, 927a, 931a, 937a],  
[ 910a, 915a, 921a, 928a, 940a, 950a, 957a, 1001a, 1007a],  
[ 940a, 945a, 951a, 958a, 1010a, 1020a, 1027a, 1031a, 1037a],  
[ 1010a, 1015a, 1021a, 1028a, 1040a, 1050a, 1057a, 1101a, 1107a],  
[ 1040a, 1045a, 1051a, 1058a, 1110a, 1120a, 1127a, 1131a, 1137a],  
[ 1110a, 1115a, 1121a, 1128a, 1140a, 1150a, 1157a, 1201p, 1207p],  
[ 1140a, 1145a, 1151a, 1158a, 1210p, 1220p, 1227p, 1231p, 1237p],  
[ 1210p, 1215p, 1221p, 1228p, 1240p, 1250p, 1257p, 101p, 107p],  
[ 1240p, 1245p, 1251p, 1258p, 110p, 120p, 127p, 131p, 137p],  
[ 110p, 115p, 121p, 128p, 140p, 150p, 157p, 201p, 207p],  
[ 140p, 145p, 151p, 158p, 210p, 220p, 227p, 231p, 237p],  
[ 210p, 215p, 221p, 228p, 240p, 250p, 257p, 301p, 307p],  
[ 240p, 245p, 251p, 258p, 310p, 320p, 327p, 331p, 337p],  
[ 310p, 315p, 321p, 328p, 340p, 350p, 357p, 401p, 407p],  
[ -, 325p, 331p, 338p, 350p, 400p, 407p, 411p, 417p],  
[ 325p, 330p, 336p, 343p, 355p, 405p, 412p, 416p, 422p],  
[ 340p, 345p, 351p, 358p, 410p, 420p, 427p, 431p, 437p],  
[ 350p, 355p, 401p, 408p, 420p, 430p, 437p, 441p, 447p],  
[ 355p, 400p, 406p, 413p, 425p, 435p, 442p, 446p, 452p],  
[ 403p, 408p, 414p, 421p, 433p, 443p, 450p, 454p, 500p],  
[ 410p, 415p, 421p, 428p, 440p, 450p, 457p, 501p, 507p],  
[ 417p, 422p, 428p, 435p, 447p, 457p, 504p, 508p, 514p],  
[ 425p, 430p, 436p, 443p, 455p, 505p, 512p, 516p, 522p],  
[ 440p, 445p, 451p, 458p, 510p, 520p, 527p, 531p, 537p],  
[ -, -, 500p, 507p, 519p, 529p, 536p, 540p, 547p],  
[ 455p, 500p, 506p, 513p, 525p, 535p, 542p, 546p, 552p],  
[ 510p, 515p, 521p, 528p, 540p, 550p, 556p, 600p, 605p],  
[ 530p, 535p, 541p, 548p, 600p, 607p, 613p, 617p, 621p],  
[ 550p, 555p, 601p, 608p, 618p, 625p, 631p, 635p, 639p],  
[ 610p, 615p, 621p, 628p, 638p, 645p, 651p, 655p, 659p],  
[ 640p, 645p, 651p, 658p, 708p, 715p, 721p, 725p, 729p],  
[ 710p, 715p, 721p, 728p, 738p, 745p, 751p, 755p, 759p],  
[ 740p, 745p, 751p, 758p, 808p, 815p, 821p, 825p, 829p],  
[ 810p, 815p, 821p, 828p, 838p, 845p, 851p, 855p, 859p],  
[ 840p, 845p, 851p, 858p, 908p, 915p, 921p, 925p, 929p],  
[ 910p, 915p, 921p, 928p, 938p, 945p, 951p, 955p, 959p],  
[ 940p, 945p, 951p, 958p, 1008p, 1015p, 1021p, 1025p, 1029p],  
[ 1010p, 1015p, 1021p, 1028p, 1038p, 1045p, 1051p, 1055p, 1059p],  
[ 1040p, 1045p, 1051p, 1058p, 1108p, 1115p, 1121p, 1125p, 1129p],  
[ 1110p, 1115p, 1121p, 1128p, 1138p, 1145p, 1151p, 1155p, 1159p]  
]  
stop_times_saturday: [  
[ 603a, 612a, 620a, 630a, 640a, 648a, 700a],  
[ 633a, 642a, 650a, 700a, 710a, 718a, 730a],  
[ 703a, 712a, 720a, 730a, 740a, 748a, 800a],  
[ 733a, 742a, 750a, 800a, 810a, 818a, 830a],  
[ 803a, 812a, 820a, 830a, 840a, 848a, 900a],  
[ 833a, 842a, 850a, 900a, 910a, 918a, 930a],  
[ 903a, 912a, 920a, 930a, 940a, 948a, 1000a],  
[ 933a, 942a, 950a, 1000a, 1010a, 1018a, 1030a],  
[ 1003a, 1012a, 1020a, 1030a, 1040a, 1048a, 1100a],  
[ 1033a, 1042a, 1050a, 1100a, 1110a, 1118a, 1130a],  
[ 1103a, 1112a, 1120a, 1130a, 1140a, 1148a, 1200p],  
[ 1133a, 1142a, 1150a, 1200p, 1210p, 1218p, 1230p],  
[ 1203p, 1212p, 1220p, 1230p, 1240p, 1248p, 100p],  
[ 1233p, 1242p, 1250p, 100p, 110p, 118p, 130p],  
[ 103p, 112p, 120p, 130p, 140p, 148p, 200p],  
[ 133p, 142p, 150p, 200p, 210p, 218p, 230p],  
[ 203p, 212p, 220p, 230p, 240p, 248p, 300p],  
[ 233p, 242p, 250p, 300p, 310p, 318p, 330p],  
[ 303p, 312p, 320p, 330p, 340p, 348p, 400p],  
[ 333p, 342p, 350p, 400p, 410p, 418p, 430p],  
[ 403p, 412p, 420p, 430p, 440p, 448p, 500p],  
[ 433p, 442p, 450p, 500p, 510p, 518p, 530p],  
[ 503p, 512p, 520p, 530p, 540p, 548p, 600p],  
[ 533p, 542p, 550p, 600p, 610p, 618p, 630p],  
[ 603p, 612p, 620p, 630p, 640p, 648p, 700p],  
[ 633p, 642p, 650p, 700p, 710p, 718p, 730p],  
[ 703p, 712p, 720p, 730p, 740p, 748p, 800p],  
[ 733p, 742p, 750p, 800p, 810p, 818p, 830p],  
[ 803p, 812p, 820p, 830p, 840p, 848p, 900p],  
[ 833p, 842p, 850p, 900p, 910p, 918p, 930p],  
[ 903p, 912p, 920p, 930p, 940p, 948p, 1000p],  
[ 933p, 942p, 950p, 1000p, 1010p, 1018p, 1030p],  
[ 1003p, 1012p, 1020p, 1030p, 1040p, 1048p, 1100p],  
[ 1033p, 1042p, 1050p, 1100p, 1110p, 1118p, 1130p],  
[ 1103p, 1112p, 1120p, 1130p, 1140p, 1148p, 1200x],  
[ 1133p, 1142p, 1150p, 1200x, 1210x, 1218x, 1230x],  
[ 1200x, 1207x, 1215x, 1225x, -, -, -]  
]  
stop_times_sunday: [  
[ 712a, 721a, 729a, 740a, 750a, 759a, 809a],  
[ 812a, 821a, 829a, 840a, 850a, 859a, 909a],  
[ 912a, 921a, 929a, 940a, 950a, 959a, 1009a],  
[ 1012a, 1021a, 1029a, 1040a, 1050a, 1059a, 1109a],  
[ 1112a, 1121a, 1129a, 1140a, 1150a, 1159a, 1209p],  
[ 1212p, 1221p, 1229p, 1240p, 1250p, 1259p, 109p],  
[ 112p, 121p, 129p, 140p, 150p, 159p, 209p],  
[ 212p, 221p, 229p, 240p, 250p, 259p, 309p],  
[ 312p, 321p, 329p, 340p, 350p, 359p, 409p],  
[ 412p, 421p, 429p, 440p, 450p, 459p, 509p],  
[ 512p, 521p, 529p, 540p, 550p, 559p, 609p],  
[ 612p, 621p, 629p, 640p, 650p, 659p, 709p],  
[ 712p, 721p, 729p, 740p, 750p, 759p, 809p],  
[ 812p, 821p, 829p, 840p, 850p, 859p, 909p],  
[ 912p, 921p, 929p, 940p, 950p, 959p, 1009p],  
[ 1012p, 1021p, 1029p, 1040p, 1050p, 1059p, 1109p],  
[ 1112p, 1121p, 1129p, 1140p, -, -, -],  
[ 1212x, 1221x, -, -, -, -, -]  
]  
 
short_name: 14  
long_name: To Leiblin Park  
time_points: [ 6105, 6966, 7421, 8643, 8168, 7143 ]  
between_stops:  
6105-6966: [ 6108, 6103, 6102, 6122, 8331, 8330, 8334, 8313, 8311, 8315, 6960 ]  
6966-7421: [ 8317, 7401, 7403, 7410, 7406 ]  
7421-8643: [ 7404, 6405, 6404, 6413, 6414, 7275 ]  
stop_times: [  
[ -, -, -, 637a, 649a, 701a],  
[ 618a, 630a, 637a, 648a, 700a, 712a],  
[ 655a, 707a, 714a, 725a, 737a, 749a],  
[ 713a, 725a, 732a, 743a, -, -],  
[ 715a, 727a, 734a, 745a, -, -],  
[ 735a, 747a, 754a, 805a, 817a, 829a],  
[ 755a, 807a, 814a, 825a, 837a, 849a],  
[ 816a, 828a, 835a, 846a, -, -],  
[ 835a, 847a, 854a, 905a, 917a, 929a],  
[ 902a, 914a, 921a, 932a, 944a, 956a],  
[ 912a, 924a, 931a, 942a, -, -],  
[ 930a, 942a, 949a, 1000a, -, -],  
[ 932a, 944a, 951a, 1002a, 1014a, 1026a],  
[ 1002a, 1014a, 1021a, 1032a, 1044a, 1056a],  
[ 1032a, 1044a, 1051a, 1102a, 1114a, 1126a],  
[ 1102a, 1114a, 1121a, 1132a, 1144a, 1156a],  
[ 1132a, 1144a, 1151a, 1202p, 1214p, 1226p],  
[ 1202p, 1214p, 1221p, 1232p, 1244p, 1256p],  
[ 1232p, 1244p, 1251p, 102p, 114p, 126p],  
[ 102p, 114p, 121p, 132p, 144p, 156p],  
[ 132p, 144p, 151p, 202p, 214p, 226p],  
[ 202p, 214p, 221p, 232p, 244p, 256p],  
[ 232p, 244p, 251p, 302p, 314p, 326p],  
[ 302p, 314p, 321p, 332p, 344p, 356p],  
[ 332p, 344p, 351p, 402p, 414p, 426p],  
[ 402p, 414p, 421p, 432p, 444p, 456p],  
[ 432p, 444p, 451p, 502p, 514p, 526p],  
[ 458p, 510p, 517p, 528p, -, -],  
[ 502p, 514p, 521p, 532p, 544p, 556p],  
[ 532p, 544p, 551p, 602p, 614p, 626p],  
[ 602p, 614p, 621p, 632p, 644p, 656p],  
[ 632p, 644p, 651p, 702p, 714p, 726p],  
[ 732p, 744p, 751p, 802p, 814p, 826p],  
[ 832p, 844p, 851p, 902p, 914p, 926p],  
[ 932p, 944p, 951p, 1002p, 1014p, 1026p],  
[ 1032p, 1044p, 1051p, 1102p, 1114p, 1126p],  
[ -, -, -, 1210x, 1222x, 1234x]  
]  
stop_times_saturday: [  
[ -, -, -, 618a, 627a, 640a],  
[ -, -, -, 718a, 727a, 740a],  
[ 748a, 800a, 807a, 818a, 827a, 840a],  
[ 848a, 900a, 907a, 918a, 927a, 940a],  
[ 948a, 1000a, 1007a, 1018a, 1027a, 1040a],  
[ 1048a, 1100a, 1107a, 1118a, 1127a, 1140a],  
[ 1148a, 1200p, 1207p, 1218p, 1227p, 1240p],  
[ 1248p, 100p, 107p, 118p, 127p, 140p],  
[ 148p, 200p, 207p, 218p, 227p, 240p],  
[ 248p, 300p, 307p, 318p, 327p, 340p],  
[ 348p, 400p, 407p, 418p, 427p, 440p],  
[ 448p, 500p, 507p, 518p, 527p, 540p],  
[ 548p, 600p, 607p, 618p, 627p, 640p],  
[ 648p, 700p, 707p, 718p, 727p, 740p],  
[ 748p, 800p, 807p, 818p, 827p, 840p],  
[ 848p, 900p, 907p, 918p, 927p, 940p],  
[ 948p, 1000p, 1007p, 1018p, 1027p, 1040p]  
]  
stop_times_sunday: [  
[ 636a, 645a, 652a, 705a, 712a, 722a],  
[ 736a, 745a, 752a, 805a, 812a, 822a],  
[ 836a, 845a, 852a, 905a, 912a, 922a],  
[ 936a, 945a, 952a, 1005a, 1012a, 1022a],  
[ 1036a, 1045a, 1052a, 1105a, 1112a, 1122a],  
[ 1136a, 1145a, 1152a, 1205p, 1212p, 1222p],  
[ 1236p, 1245p, 1252p, 105p, 112p, 122p],  
[ 136p, 145p, 152p, 205p, 212p, 222p],  
[ 236p, 245p, 252p, 305p, 312p, 322p],  
[ 336p, 345p, 352p, 405p, 412p, 422p],  
[ 436p, 445p, 452p, 505p, 512p, 522p],  
[ 536p, 545p, 552p, 605p, 612p, 622p],  
[ 636p, 645p, 652p, 705p, 712p, 722p],  
[ 736p, 745p, 752p, 805p, 812p, 822p],  
[ 836p, 845p, 852p, 905p, 912p, 922p],  
[ 936p, 945p, 952p, 1005p, 1012p, 1022p]  
]  
 
short_name: 14  
long_name: To Universities / Downtown  
time_points: [ 7143, 8167, 7285, 7412, 6965, 6087 ]  
between_stops:  
7285-7412: [ 7274, 6409, 6403, 6407, 6406, 7355 ]  
7412-6965: [ 7419, 7409, 7402, 8304, 6962 ]  
6965-6087: [ 6969, 8314, 8306, 8307, 8309, 8312, 8336, 8327, 8338, 6121, 6106 ]  
stop_times: [  
[ 632a, 642a, 657a, 708a, 715a, 727a],  
[ 702a, 712a, 727a, 738a, 745a, 757a],  
[ -, -, 755a, 806a, 813a, 825a],  
[ 732a, 742a, 757a, 808a, 815a, 827a],  
[ 802a, 812a, 827a, 838a, 845a, 857a],  
[ 832a, 842a, 857a, 908a, 915a, 927a],  
[ 902a, 912a, 927a, 938a, 945a, 957a],  
[ 932a, 942a, 957a, 1008a, 1015a, 1027a],  
[ 1002a, 1012a, 1027a, 1038a, 1045a, 1057a],  
[ 1032a, 1042a, 1057a, 1108a, 1115a, 1127a],  
[ 1102a, 1112a, 1127a, 1138a, 1145a, 1157a],  
[ 1132a, 1142a, 1157a, 1208p, 1215p, 1227p],  
[ 1202p, 1212p, 1227p, 1238p, 1245p, 1257p],  
[ 1232p, 1242p, 1257p, 108p, 115p, 127p],  
[ 102p, 112p, 127p, 138p, 145p, 157p],  
[ 132p, 142p, 157p, 208p, 215p, 227p],  
[ 202p, 212p, 227p, 238p, 245p, 257p],  
[ 232p, 242p, 257p, 308p, 315p, 327p],  
[ 302p, 312p, 327p, 338p, 345p, 357p],  
[ -, -, 340p, 351p, 358p, 410p],  
[ -, -, -, -, 407p, 419p],  
[ 332p, 342p, 357p, 408p, 415p, 427p],  
[ -, -, -, -, 428p, 440p],  
[ 359p, 409p, 424p, 435p, 442p, 454p],  
[ 432p, 442p, 457p, 508p, 515p, 527p],  
[ 502p, 512p, 527p, 538p, 545p, 557p],  
[ 532p, 542p, 557p, 608p, 615p, 627p],  
[ 602p, 612p, 627p, 638p, 645p, 657p],  
[ 632p, 642p, 657p, 708p, 715p, 727p],  
[ 702p, 712p, 727p, 738p, 745p, 757p],  
[ 732p, 742p, 757p, 808p, 815p, 827p],  
[ 832p, 842p, 857p, 908p, 915p, 927p],  
[ 932p, 942p, 957p, 1008p, 1015p, 1027p],  
[ 1032p, 1042p, 1057p, -, -, -],  
[ 1132p, 1142p, 1157p, -, -, -],  
[ 1235x, 1245x, 100x, -, -, -]  
]  
stop_times_saturday: [  
[ 646a, 655a, 710a, 721a, 728a, 740a],  
[ 746a, 755a, 810a, 821a, 828a, 840a],  
[ 846a, 855a, 910a, 921a, 928a, 940a],  
[ 946a, 955a, 1010a, 1021a, 1028a, 1040a],  
[ 1046a, 1055a, 1110a, 1121a, 1128a, 1140a],  
[ 1146a, 1155a, 1210p, 1221p, 1228p, 1240p],  
[ 1246p, 1255p, 110p, 121p, 128p, 140p],  
[ 146p, 155p, 210p, 221p, 228p, 240p],  
[ 246p, 255p, 310p, 321p, 328p, 340p],  
[ 346p, 355p, 410p, 421p, 428p, 440p],  
[ 446p, 455p, 510p, 521p, 528p, 540p],  
[ 546p, 555p, 610p, 621p, 628p, 640p],  
[ 646p, 655p, 710p, 721p, 728p, 740p],  
[ 746p, 755p, 810p, 821p, 828p, 840p],  
[ 846p, 855p, 910p, 921p, 928p, 940p],  
[ 946p, 955p, 1010p, 1021p, 1028p, 1040p],  
[ 1046p, 1055p, 1107p, -, -, -]  
]  
stop_times_sunday: [  
[ 728a, 736a, 750a, 801a, 808a, 817a],  
[ 828a, 836a, 850a, 901a, 908a, 917a],  
[ 928a, 936a, 950a, 1001a, 1008a, 1017a],  
[ 1028a, 1036a, 1050a, 1101a, 1108a, 1117a],  
[ 1128a, 1136a, 1150a, 1201p, 1208p, 1217p],  
[ 1228p, 1236p, 1250p, 101p, 108p, 117p],  
[ 128p, 136p, 150p, 201p, 208p, 217p],  
[ 228p, 236p, 250p, 301p, 308p, 317p],  
[ 328p, 336p, 350p, 401p, 408p, 417p],  
[ 428p, 436p, 450p, 501p, 508p, 517p],  
[ 528p, 536p, 550p, 601p, 608p, 617p],  
[ 628p, 636p, 650p, 701p, 708p, 717p],  
[ 728p, 736p, 750p, 801p, 808p, 817p],  
[ 828p, 836p, 850p, 901p, 908p, 917p],  
[ 928p, 936p, 950p, 1001p, 1008p, 1017p],  
[ 1028p, 1036p, 1050p, 1101p, 1108p, 1117p]  
]  
 
short_name: 17  
long_name: "To Hospitals / Universities"  
time_points: [ 7087, 7166, 6564, 8561, 8214, 8308, 6966 ]  
between_stops:  
6564-8561: [ 6197, 6193, 6203 ]  
8561-8214: [ 8564, 8557, 8566, 8559, 6545, 8205, 8190 ]  
8214-8308: [ 8183, 8196, 8195, 8194, 8328, 8337, 8333 ]  
8308-6966: [ 8313, 8311, 8315, 6960 ]  
stop_times: [  
[ 625a, 634a, 638a, 645a, 652a, 658a, 702a],  
[ 655a, 704a, 708a, 715a, 722a, 728a, 732a],  
[ 725a, 734a, 738a, 745a, 752a, 758a, 802a],  
[ 755a, 804a, 808a, 815a, 822a, 828a, 832a],  
[ -, -, 825a, 832a, 839a, 845a, 849a],  
[ 825a, 834a, 838a, 845a, 852a, 858a, 902a],  
[ 838a, 847a, 851a, 858a, 905a, 911a, 915a],  
[ 855a, 904a, 908a, 915a, 922a, 928a, 932a],  
[ -, -, 910a, 917a, 924a, 930a, 934a],  
[ 925a, 934a, 938a, 945a, 952a, 958a, 1002a],  
[ 955a, 1004a, 1008a, 1015a, 1022a, 1028a, 1032a],  
[ 1025a, 1034a, 1038a, 1045a, 1052a, 1058a, 1102a],  
[ 1055a, 1104a, 1108a, 1115a, 1122a, 1128a, 1132a],  
[ 1125a, 1134a, 1138a, 1145a, 1152a, 1158a, 1202p],  
[ 1155a, 1204p, 1208p, 1215p, 1222p, 1228p, 1232p],  
[ 1225p, 1234p, 1238p, 1245p, 1252p, 1258p, 102p],  
[ 1255p, 104p, 108p, 115p, 122p, 128p, 132p],  
[ 125p, 134p, 138p, 145p, 152p, 158p, 202p],  
[ 155p, 204p, 208p, 215p, 222p, 228p, 232p],  
[ 225p, 234p, 238p, 245p, 252p, 258p, 302p],  
[ 255p, 304p, 308p, 315p, 322p, 328p, 332p],  
[ 325p, 334p, 338p, 345p, 352p, 358p, 402p],  
[ 355p, 404p, 408p, 415p, 422p, 428p, 432p],  
[ 425p, 434p, 438p, 445p, 452p, 458p, 502p],  
[ 455p, 504p, 508p, 515p, 522p, 528p, 532p],  
[ 525p, 534p, 538p, 545p, 552p, 558p, 602p],  
[ 555p, 604p, 608p, 615p, 622p, 628p, 632p]  
]  
 
short_name: 17  
long_name: To Lacewood  
time_points: [ 6966, 8185, 8184, 8571, 6563, 6032, 7087 ]  
between_stops:  
6966-8185: [ 8220, 8187 ]  
8185-8184: [ 8219, 8179 ]  
8184-8571: [ 8206, 6544, 8558, 8554, 8568, 8556, 8572 ]  
8571-6563: [ 6192, 6196, 6201, 6200, 6199, 6198 ]  
6563-6032: [ 6565, 6984 ]  
stop_times: [  
[ 705a, 709a, 711a, 718a, 726a, 731a, 738a],  
[ 735a, 739a, 741a, 748a, 756a, 801a, 808a],  
[ 805a, 809a, 811a, 818a, 826a, 831a, 838a],  
[ 835a, 839a, 841a, 848a, 856a, 901a, 908a],  
[ 905a, 909a, 911a, 918a, 926a, 931a, 938a],  
[ 935a, 939a, 941a, 948a, 956a, 1001a, 1008a],  
[ 1005a, 1009a, 1011a, 1018a, 1026a, 1031a, 1038a],  
[ 1035a, 1039a, 1041a, 1048a, 1056a, 1101a, 1108a],  
[ 1105a, 1109a, 1111a, 1118a, 1126a, 1131a, 1138a],  
[ 1135a, 1139a, 1141a, 1148a, 1156a, 1201p, 1208p],  
[ 1205p, 1209p, 1211p, 1218p, 1226p, 1231p, 1238p],  
[ 1235p, 1239p, 1241p, 1248p, 1256p, 101p, 108p],  
[ 105p, 109p, 111p, 118p, 126p, 131p, 138p],  
[ 135p, 139p, 141p, 148p, 156p, 201p, 208p],  
[ 205p, 209p, 211p, 218p, 226p, 231p, 238p],  
[ 235p, 239p, 241p, 248p, 256p, 301p, 308p],  
[ 305p, 309p, 311p, 318p, 326p, 331p, 338p],  
[ 335p, 339p, 341p, 348p, 356p, 401p, 408p],  
[ 405p, 409p, 411p, 418p, 426p, 431p, 438p],  
[ 435p, 439p, 441p, 448p, 456p, 501p, 508p],  
[ 505p, 509p, 511p, 518p, 526p, 531p, 538p],  
[ 535p, 539p, 541p, 548p, 556p, 601p, 608p],  
[ 605p, 609p, 611p, 618p, 626p, 631p, 638p],  
[ 635p, 639p, 641p, 648p, 656p, 701p, 708p]  
 
]  
 
short_name: 18  
long_name: To Lacewood  
time_points: [ 6966, 8184, 6219, 7086 ]  
between_stops:  
6966-8184: [ 8220, 8187, 8185, 8219, 8179 ]  
8184-6219: [ 8206, 6544, 8558, 8554, 8568, 8556, 8572, 8571, 8574, 8550, 8549, 8567, 8570, 8552 ]  
stop_times: [  
[ -, -, 612a, 625a],  
[ -, -, 642a, 655a],  
[ 650a, 658a, 715a, 728a],  
[ 720a, 728a, 745a, 758a],  
[ 750a, 758a, 815a, 828a],  
[ 820a, 828a, 845a, 858a],  
[ 850a, 858a, 914a, 926a],  
[ 921a, 927a, 944a, 956a],  
[ 950a, 956a, 1013a, 1025a],  
[ 1020a, 1026a, 1043a, 1055a],  
[ 1050a, 1056a, 1113a, 1125a],  
[ 1120a, 1126a, 1143a, 1155a],  
[ 1150a, 1156a, 1213p, 1225p],  
[ 1220p, 1226p, 1243p, 1255p],  
[ 1250p, 1256p, 113p, 125p],  
[ 120p, 126p, 143p, 155p],  
[ 150p, 156p, 213p, 225p],  
[ 220p, 226p, 248p, 301p],  
[ 227p, 234p, 256p, 309p],  
[ 247p, 255p, 317p, 330p],  
[ 257p, 305p, 327p, 340p],  
[ 320p, 328p, 350p, 403p],  
[ 340p, 348p, 410p, 423p],  
[ 350p, 358p, 420p, 433p],  
[ 419p, 427p, 449p, 502p],  
[ 450p, 458p, 520p, 533p],  
[ 520p, 528p, 550p, 603p],  
[ 550p, 558p, 615p, 627p],  
[ 621p, 627p, 644p, 656p],  
[ 650p, 656p, 713p, 725p],  
[ 720p, 726p, 743p, 755p],  
[ 750p, 756p, 813p, 825p],  
[ 820p, 826p, 843p, 855p],  
[ 850p, 856p, 913p, 925p],  
[ 920p, 926p, 943p, 955p],  
[ 950p, 956p, 1013p, 1025p],  
[ 1020p, 1026p, 1043p, 1055p],  
[ 1050p, 1056p, 1113p, 1125p],  
[ 1120p, 1126p, 1143p, 1155p],  
[ 1150p, 1156p, 1213x, 1225x]  
]  
stop_times_saturday: [  
[ 702a, 713a, 730a, 740a],  
[ 802a, 813a, 830a, 840a],  
[ 832a, 843a, 900a, 910a],  
[ 902a, 913a, 930a, 940a],  
[ 932a, 943a, 1000a, 1010a],  
[ 1002a, 1013a, 1030a, 1040a],  
[ 1032a, 1043a, 1100a, 1110a],  
[ 1102a, 1113a, 1130a, 1140a],  
[ 1132a, 1143a, 1200p, 1210p],  
[ 1202p, 1213p, 1230p, 1240p],  
[ 1232p, 1243p, 100p, 110p],  
[ 102p, 113p, 130p, 140p],  
[ 132p, 143p, 200p, 210p],  
[ 202p, 213p, 230p, 240p],  
[ 232p, 243p, 300p, 310p],  
[ 302p, 313p, 330p, 340p],  
[ 332p, 343p, 400p, 410p],  
[ 402p, 413p, 430p, 440p],  
[ 432p, 443p, 500p, 510p],  
[ 502p, 513p, 530p, 540p],  
[ 532p, 543p, 600p, 610p],  
[ 602p, 613p, 630p, 640p],  
[ 632p, 643p, 700p, 710p],  
[ 702p, 713p, 730p, 740p],  
[ 732p, 743p, 800p, 810p],  
[ 802p, 813p, 830p, 840p],  
[ 832p, 843p, 900p, 910p],  
[ 902p, 913p, 930p, 940p],  
[ 932p, 943p, 1000p, 1010p],  
[ 1002p, 1013p, 1030p, 1040p],  
[ 1102p, 1113p, 1130p, 1140p],  
[ 1202x, 1213x, 1230x, 1240x]  
]  
stop_times_sunday: [  
[ -, -, 655a, 705a],  
[ 738a, 742a, 755a, 805a],  
[ 838a, 842a, 855a, 905a],  
[ 938a, 942a, 955a, 1005a],  
[ 1038a, 1042a, 1055a, 1105a],  
[ 1138a, 1142a, 1155a, 1205p],  
[ 1238p, 1242p, 1255p, 105p],  
[ 138p, 142p, 155p, 205p],  
[ 238p, 242p, 255p, 305p],  
[ 338p, 342p, 355p, 405p],  
[ 438p, 442p, 455p, 505p],  
[ 538p, 542p, 555p, 605p],  
[ 638p, 642p, 655p, 705p],  
[ 738p, 742p, 755p, 805p],  
[ 838p, 842p, 855p, 905p],  
[ 938p, 942p, 955p, 1005p],  
[ 1038p, 1042p, 1055p, 1105p],  
[ 1138p, 1142p, 1155p, 1205x]  
]  
 
short_name: 18  
long_name: To SMU  
time_points: [ 7087, 6216, 8214, 6966 ]  
between_stops:  
6216-8214: [ 8551, 8562, 8565, 8573, 8555, 8561, 8564, 8557, 8566, 8559, 6545, 8205, 8190 ]  
8214-6966: [ 8183, 8196, 8195, 8194, 8328, 8337, 8333, 8308, 8313, 8311, 8315, 6960 ]  
stop_times: [  
[ 610a, 622a, 641a, 649a],  
[ 640a, 652a, 711a, 719a],  
[ 710a, 722a, 741a, 749a],  
[ 740a, 752a, 811a, 819a],  
[ 810a, 822a, 841a, 849a],  
[ 840a, 852a, 911a, 921a],  
[ 910a, 922a, 939a, 949a],  
[ 940a, 952a, 1009a, 1019a],  
[ 1010a, 1022a, 1039a, 1049a],  
[ 1040a, 1052a, 1109a, 1119a],  
[ 1110a, 1122a, 1139a, 1149a],  
[ 1140a, 1152a, 1209p, 1219p],  
[ 1210p, 1222p, 1239p, 1249p],  
[ 1240p, 1252p, 109p, 119p],  
[ 110p, 122p, 139p, 149p],  
[ 140p, 152p, 209p, 219p],  
[ -, -, 214p, 224p],  
[ 210p, 222p, 237p, 244p],  
[ -, -, 240p, 247p],  
[ 240p, 253p, 310p, 317p],  
[ -, -, 330p, 337p],  
[ 310p, 323p, 340p, 347p],  
[ 340p, 353p, 410p, 417p],  
[ 410p, 423p, 440p, 447p],  
[ 440p, 453p, 510p, 517p],  
[ 510p, 523p, 540p, 547p],  
[ 540p, 553p, 611p, 621p],  
[ 610p, 622p, 639p, 649p],  
[ 640p, 652p, 709p, 719p],  
[ 710p, 722p, 739p, 749p],  
[ 740p, 752p, 809p, 819p],  
[ 810p, 822p, 839p, 849p],  
[ 840p, 852p, 909p, 919p],  
[ 910p, 922p, 939p, 949p],  
[ 940p, 952p, 1009p, 1019p],  
[ 1010p, 1022p, 1039p, 1049p],  
[ 1040p, 1052p, 1109p, 1119p],  
[ 1110p, 1122p, 1139p, 1149p],  
[ 1140p, 1152p, 1209x, 1219x],  
[ 1210x, 1222x, -, -],  
[ 1225x, 1237x, -, -]  
]  
stop_times_saturday: [  
[ 620a, 630a, 649a, 702a],  
[ 720a, 730a, 749a, 802a],  
[ 750a, 800a, 819a, 832a],  
[ 820a, 830a, 849a, 902a],  
[ 850a, 900a, 919a, 932a],  
[ 920a, 930a, 949a, 1002a],  
[ 950a, 1000a, 1019a, 1032a],  
[ 1020a, 1030a, 1049a, 1102a],  
[ 1050a, 1100a, 1119a, 1132a],  
[ 1120a, 1130a, 1149a, 1202p],  
[ 1150a, 1200p, 1219p, 1232p],  
[ 1220p, 1230p, 1249p, 102p],  
[ 1250p, 100p, 119p, 132p],  
[ 120p, 130p, 149p, 202p],  
[ 150p, 200p, 219p, 232p],  
[ 220p, 230p, 249p, 302p],  
[ 250p, 300p, 319p, 332p],  
[ 320p, 330p, 349p, 402p],  
[ 350p, 400p, 419p, 432p],  
[ 420p, 430p, 449p, 502p],  
[ 450p, 500p, 519p, 532p],  
[ 520p, 530p, 549p, 602p],  
[ 550p, 600p, 619p, 632p],  
[ 620p, 630p, 649p, 702p],  
[ 650p, 700p, 719p, 732p],  
[ 720p, 730p, 749p, 802p],  
[ 750p, 800p, 819p, 832p],  
[ 820p, 830p, 849p, 902p],  
[ 850p, 900p, 919p, 932p],  
[ 920p, 930p, 949p, 1002p],  
[ 1020p, 1030p, 1049p, 1102p],  
[ 1120p, 1130p, 1149p, 1202x],  
[ 1220x, 1230x, -, -]  
]  
stop_times_sunday: [  
[ 705a, 715a, 731a, 738a],  
[ 805a, 815a, 831a, 838a],  
[ 905a, 915a, 931a, 938a],  
[ 1005a, 1015a, 1031a, 1038a],  
[ 1105a, 1115a, 1131a, 1138a],  
[ 1205p, 1215p, 1231p, 1238p],  
[ 105p, 115p, 131p, 138p],  
[ 205p, 215p, 231p, 238p],  
[ 305p, 315p, 331p, 338p],  
[ 405p, 415p, 431p, 438p],  
[ 505p, 515p, 531p, 538p],  
[ 605p, 615p, 631p, 638p],  
[ 705p, 715p, 731p, 738p],  
[ 805p, 815p, 831p, 838p],  
[ 905p, 915p, 931p, 938p],  
[ 1005p, 1015p, 1031p, 1038p],  
[ 1105p, 1115p, 1131p, 1138p],  
[ 1205x, 1215x, -, -]  
]  
 
short_name: 2  
long_name: To Downtown via North Street  
time_points: [ 7019, 7023, 7087, 6564, 6612, 7284, 7351, 6105, 8435 ]  
between_stops:  
6564-7284: [ 6197, 6193 ]  
7284-7351: [ 7274, 6409, 6403, 6407, 6406, 7355, 7345, 7357, 7352, 7342, 7354, 7347 ]  
7351-6105: [ 7343, 6088, 6104, 6125 ]  
6105-8435: [ 6108, 6733 ]  
stop_times: [  
[ 557a, 601a, 610a, 624a, -, 632a, 642a, 646a, 649a],  
[ 637a, 641a, 650a, 704a, -, 712a, 722a, 727a, 730a],  
[ 707a, 711a, 720a, 734a, -, 742a, 752a, 757a, 800a],  
[ 737a, 741a, 750a, 804a, -, 812a, 822a, 827a, 830a],  
[ 807a, 811a, 820a, 834a, -, 842a, 852a, 857a, 900a],  
[ 837a, 841a, 850a, 904a, -, 912a, 922a, 928a, 931a],  
[ 907a, 911a, 920a, 935a, -, 943a, 953a, 959a, 1002a],  
[ 937a, 941a, 950a, 1005a, -, 1013a, 1023a, 1029a, 1032a],  
[ 1007a, 1011a, 1020a, 1035a, -, 1043a, 1053a, 1059a, 1102a],  
[ 1037a, 1041a, 1050a, 1105a, -, 1113a, 1123a, 1129a, 1132a],  
[ 1107a, 1111a, 1120a, 1135a, -, 1143a, 1153a, 1159a, 1202p],  
[ 1137a, 1141a, 1150a, 1205p, -, 1213p, 1223p, 1229p, 1232p],  
[ 1207p, 1211p, 1220p, 1235p, -, 1243p, 1253p, 1259p, 102p],  
[ 1237p, 1241p, 1250p, 105p, -, 113p, 123p, 129p, 132p],  
[ 107p, 111p, 120p, 135p, -, 143p, 153p, 159p, 202p],  
[ 137p, 141p, 150p, 205p, -, 213p, 223p, 229p, 232p],  
[ 207p, 211p, 220p, 235p, -, 243p, 253p, 259p, 302p],  
[ 237p, 241p, 250p, 305p, -, 313p, 323p, 329p, 332p],  
[ 307p, 311p, 320p, 335p, -, 343p, 353p, 359p, 402p],  
[ 337p, 341p, 350p, 405p, -, 413p, 423p, 429p, 432p],  
[ 407p, 411p, 420p, 435p, -, 443p, 453p, 459p, 502p],  
[ 437p, 441p, 450p, 505p, -, 513p, 523p, 529p, 532p],  
[ 507p, 511p, 520p, 535p, -, 543p, 553p, 559p, 602p],  
[ 537p, 541p, 550p, 604p, -, 610p, 618p, 622p, 625p],  
[ 607p, 611p, 620p, 633p, -, 639p, 647p, 651p, 654p],  
[ 637p, 641p, 650p, 703p, -, 709p, 717p, 721p, 724p],  
[ 737p, 741p, 750p, 803p, -, 809p, 817p, 821p, 824p],  
[ 837p, 841p, 850p, 903p, -, 909p, 917p, 921p, 924p],  
[ 937p, 941p, 950p, 1003p, 1005p, 1009p, 1017p, 1021p, 1024p],  
[ 1037p, 1041p, 1050p, 1103p, 1105p, 1109p, 1117p, 1121p, 1124p],  
[ 1137p, 1141p, 1150p, 1203x, 1205x, 1209x, 1217x, 1221x, 1224x],  
[ 1237x, 1241x, 1250x, -, -, -, -, -, -]  
]  
stop_times_saturday: [  
[ 632a, 637a, 645a, 659a, -, 705a, 713a, 716a, 718a],  
[ 732a, 737a, 745a, 759a, -, 805a, 813a, 816a, 818a],  
[ 832a, 837a, 845a, 859a, -, 905a, 915a, 917a, 920a],  
[ 932a, 937a, 945a, 1000a, -, 1006a, 1015a, 1018a, 1021a],  
[ 1032a, 1037a, 1045a, 1100a, -, 1106a, 1115a, 1118a, 1121a],  
[ 1102a, 1107a, 1115a, 1130a, -, 1136a, 1145a, 1148a, 1151a],  
[ 1132a, 1137a, 1145a, 1200a, -, 1206p, 1215p, 1218p, 1221p],  
[ 1202p, 1207p, 1215p, 1230p, -, 1236p, 1245p, 1248p, 1251p],  
[ 1232p, 1237p, 1245p, 100p, -, 106p, 115p, 118p, 121p],  
[ 102p, 107p, 115p, 130p, -, 136p, 145p, 148p, 151p],  
[ 132p, 137p, 145p, 200p, -, 206p, 215p, 218p, 221p],  
[ 202p, 207p, 215p, 230p, -, 236p, 245p, 248p, 251p],  
[ 232p, 237p, 245p, 300p, -, 306p, 315p, 318p, 321p],  
[ 302p, 307p, 315p, 330p, -, 336p, 345p, 348p, 351p],  
[ 332p, 337p, 345p, 400p, -, 406p, 415p, 418p, 421p],  
[ 402p, 407p, 415p, 430p, -, 436p, 445p, 448p, 451p],  
[ 432p, 437p, 445p, 500p, -, 506p, 515p, 518p, 521p],  
[ 502p, 507p, 515p, 530p, -, 536p, 545p, 548p, 551p],  
[ 532p, 537p, 545p, 600p, -, 606p, 615p, 618p, 619p],  
[ 602p, 607p, 615p, 628p, -, 634p, 642p, 645p, 647p],  
[ 632p, 637p, 645p, 658p, -, 704p, 712p, 715p, 717p],  
[ 737p, 742p, 750p, 803p, -, 809p, 817p, 820p, 822p],  
[ 837p, 842p, 850p, 903p, -, 909p, 917p, 920p, 922p],  
[ 937p, 942p, 950p, 1003p, 1005p, 1009p, 1017p, 1020p, 1022p],  
[ 1037p, 1042p, 1050p, 1103p, 1105p, 1109p, 1117p, 1120p, 1122p],  
[ 1137p, 1142p, 1150p, 1203x, 1205x, 1209x, 1217x, 1220x, 1222x],  
[ 1237x, 1242x, 1250x, -, -, -, -, -]  
]  
stop_times_sunday: [  
[ 740a, 743a, 750a, 800a, -, 808a, 818a, 821a, 823a],  
[ 840a, 843a, 850a, 900a, -, 908a, 918a, 921a, 923a],  
[ 940a, 943a, 950a, 1000a, -, 1008a, 1018a, 1021a, 1023a],  
[ 1040a, 1043a, 1050a, 1100a, -, 1108a, 1118a, 1121a, 1123a],  
[ 1140a, 1143a, 1150a, 1200p, -, 1208p, 1218p, 1221p, 1223p],  
[ 1240p, 1243p, 1250p, 100p, -, 108p, 118p, 121p, 123p],  
[ 140p, 143p, 150p, 200p, -, 208p, 218p, 221p, 223p],  
[ 240p, 243p, 250p, 300p, -, 308p, 318p, 318p, 323p],  
[ 340p, 343p, 350p, 400p, -, 408p, 418p, 421p, 423p],  
[ 440p, 443p, 450p, 500p, -, 508p, 518p, 521p, 523p],  
[ 540p, 543p, 550p, 600p, -, 606p, 616p, 619p, 621p],  
[ 640p, 643p, 650p, 700p, -, 706p, 716p, 719p, 721p],  
[ 740p, 743p, 750p, 800p, -, 806p, 816p, 819p, 821p],  
[ 840p, 843p, 850p, 900p, -, 906p, 916p, 919p, 921p],  
[ 940p, 943p, 950p, 1000p, 1002p, 1005p, 1015p, 1018p, 1020p],  
[ 1040p, 1043p, 1050p, 1100p, 1102p, 1105p, 1115p, 1118p, 1120p],  
[ 1140p, 1143p, 1150p, -, -, -, -, -, -]  
]  
 
short_name: 2  
long_name: To Wedgewood via Main  
time_points: [ 8435, 7348, 8643, 6612, 6563, 6032, 6597, 7087, 7019 ]  
between_stops:  
8435-7348: [ 6089, 6116 ]  
7348-8643: [ 7346, 7341, 7353, 7358, 7344, 7356, 6405, 6404, 6413, 6414, 7275 ]  
8643-6563: [ 6199, 6198 ]  
6563-6032: [ 6563, 6565, 6984 ]  
stop_times: [  
[ -, -, -, -, -, 540a, 545a, 550a, 556a],  
[ -, -, 610a, -, 616a, 620a, 625a, 630a, 636a],  
[ 625a, 631a, 640a, -, 646a, 650a, 655a, 700a, 706a],  
[ 655a, 701a, 710a, -, 716a, 720a, 725a, 730a, 736a],  
[ 725a, 731a, 740a, -, 746a, 750a, 755a, 800a, 806a],  
[ 755a, 801a, 810a, -, 816a, 820a, 825a, 830a, 836a],  
[ 818a, 824a, 837a, -, 844a, 849a, 856a, 857a, 906a],  
[ 847a, 854a, 907a, -, 914a, 919a, 926a, 930a, 936a],  
[ 917a, 924a, 937a, -, 944a, 949a, 956a, 1000a, 1006a],  
[ 947a, 954a, 1007a, -, 1014a, 1019a, 1026a, 1030a, 1036a],  
[ 1017a, 1024a, 1037a, -, 1044a, 1049a, 1056a, 1100a, 1106a],  
[ 1047a, 1054a, 1107a, -, 1114a, 1119a, 1126a, 1130a, 1136a],  
[ 1117a, 1124a, 1137a, -, 1144a, 1149a, 1156a, 1200p, 1206p],  
[ 1147a, 1154a, 1207p, -, 1214p, 1219p, 1226p, 1230p, 1236p],  
[ 1217p, 1224p, 1237p, -, 1244p, 1249p, 1256p, 100p, 106p],  
[ 1247p, 1254p, 107p, -, 114p, 119p, 126p, 130p, 136p],  
[ 117p, 124p, 137p, -, 144p, 149p, 156p, 200p, 206p],  
[ 146p, 153p, 206p, -, 213p, 218p, 225p, 229p, 236p],  
[ 216p, 223p, 237p, -, 244p, 249p, 256p, 300p, 306p],  
[ 246p, 253p, 307p, -, 314p, 319p, 326p, 330p, 336p],  
[ 314p, 322p, 337p, -, 344p, 349p, 356p, 400p, 406p],  
[ 344p, 352p, 407p, -, 414p, 419p, 426p, 430p, 436p],  
[ 414p, 422p, 437p, -, 444p, 449p, 456p, 500p, 506p],  
[ 444p, 452p, 507p, -, 514p, 519p, 526p, 530p, 536p],  
[ 514p, 522p, 537p, -, 544p, 549p, 556p, 600p, 606p],  
[ 553p, 601p, 610p, -, 616p, 620p, 625p, 630p, 636p],  
[ 653p, 700p, 710p, -, 716p, 720p, 725p, 729p, 736p],  
[ 753p, 800p, 810p, -, 816p, 820p, 825p, 829p, 836p],  
[ 854p, 901p, 910p, -, 916p, 920p, 925p, 930p, 936p],  
[ 954p, 1001p, 1010p, 1011p, 1016p, 1020p, 1025p, 1030p, 1036p],  
[ 1054p, 1101p, 1110p, 1111p, 1116p, 1120p, 1125p, 1130p, 1136p],  
[ 1154p, 1201x, 1210x, 1211x, 1216x, 1220x, 1225x, 1230x, 1236x]  
]  
stop_times_saturday: [  
[ -, -, 607a, -, 613a, 617a, 622a, 625a, 631a],  
[ 652a, 658a, 707a, -, 713a, 717a, 722a, 725a, 731a],  
[ 752a, 758a, 807a, -, 813a, 817a, 822a, 825a, 831a],  
[ 852a, 858a, 907a, -, 914a, 918a, 923a, 926a, 932a],  
[ 944a, 950a, 1004a, -, 1010a, 1015a, 1021a, 1024a, 1030a],  
[ 1014a, 1020a, 1034a, -, 1040a, 1045a, 1051a, 1054a, 1100a],  
[ 1044a, 1050a, 1104a, -, 1110a, 1115a, 1121a, 1124a, 1130a],  
[ 1114a, 1120a, 1134a, -, 1140a, 1145a, 1151a, 1154a, 1200p],  
[ 1144a, 1150a, 1204p, -, 1210p, 1215p, 1221p, 1224p, 1230p],  
[ 1214p, 1220p, 1234p, -, 1240p, 1245p, 1251p, 1254p, 100p],  
[ 1244p, 1250p, 104p, -, 110p, 115p, 121p, 124p, 130p],  
[ 114p, 120p, 134p, -, 140p, 145p, 151p, 154p, 200p],  
[ 144p, 150p, 204p, -, 210p, 215p, 221p, 224p, 230p],  
[ 214p, 220p, 234p, -, 240p, 245p, 251p, 254p, 300p],  
[ 244p, 250p, 304p, -, 310p, 315p, 321p, 324p, 330p],  
[ 314p, 320p, 334p, -, 340p, 345p, 351p, 354p, 400p],  
[ 344p, 350p, 404p, -, 410p, 415p, 421p, 424p, 430p],  
[ 414p, 420p, 434p, -, 440p, 445p, 451p, 454p, 500p],  
[ 444p, 450p, 504p, -, 510p, 515p, 521p, 524p, 530p],  
[ 514p, 520p, 534p, -, 540p, 545p, 551p, 554p, 600p],  
[ 553p, 559p, 608p, -, 614p, 617p, 622p, 625p, 631p],  
[ 658p, 704p, 713p, -, 719p, 722p, 727p, 730p, 736p],  
[ 758p, 804p, 813p, -, 819p, 822p, 827p, 830p, 836p],  
[ 858p, 904p, 913p, -, 919p, 921p, 927p, 930p, 936p],  
[ 958p, 1004p, 1013p, 1014p, 1018p, 1021p, 1026p, 1029p, 1035p],  
[ 1058p, 1104p, 1113p, 1114p, 1118p, 1121p, 1126p, 1129p, 1135p],  
[ 1158p, 1204x, 1213x, 1214x, 1218x, 1221x, 1226x, 1229x, 1235x]  
]  
stop_times_sunday: [  
[ 700a, 705a, 715a, -, 722a, 725a, 730a, 733a, 740a],  
[ 800a, 805a, 815a, -, 822a, 825a, 830a, 833a, 840a],  
[ 900a, 905a, 915a, -, 922a, 925a, 930a, 933a, 940a],  
[ 1000a, 1005a, 1015a, -, 1022a, 1025a, 1030a, 1033a, 1040a],  
[ 1100a, 1105a, 1115a, -, 1122a, 1125a, 1130a, 1133a, 1140a],  
[ 1200p, 1205p, 1215p, -, 1222p, 1225p, 1230p, 1233p, 1240p],  
[ 100p, 105p, 115p, -, 122p, 125p, 130p, 133p, 140p],  
[ 200p, 205p, 215p, -, 222p, 225p, 230p, 233p, 240p],  
[ 300p, 305p, 315p, -, 322p, 325p, 330p, 333p, 340p],  
[ 400p, 405p, 415p, -, 422p, 425p, 430p, 433p, 440p],  
[ 500p, 505p, 515p, -, 522p, 525p, 530p, 533p, 540p],  
[ 600p, 605p, 615p, -, 622p, 625p, 630p, 633p, 640p],  
[ 700p, 705p, 715p, -, 722p, 725p, 730p, 733p, 740p],  
[ 800p, 805p, 815p, -, 822p, 825p, 830p, 833p, 840p],  
[ 900p, 905p, 915p, -, 922p, 925p, 930p, 933p, 940p],  
[ 1000p, 1005p, 1015p, 1016p, 1022p, 1025p, 1030p, 1033p, 1040p],  
[ 1100p, 1105p, 1115p, 1116p, 1122p, 1125p, 1130p, 1133p, 1140p]  
]  
 
short_name: 20  
long_name: To Herring Cove  
time_points: [ 8414, 6568, 6105, 8151, 8643, 6797, 6851, 7121 ]  
between_stops:  
8151-8643: [ 8138, 8148, 8137, 8134, 8146, 6413, 6414, 7275 ]  
stop_times: [  
[ -, -, -, -, 510a, 527a, 532a, 539a],  
[ -, -, -, -, 530a, 547a, 552a, 559a],  
[ -, -, -, -, 600a, 617a, 622a, 629a],  
[ 607a, -, 610a, 619a, 635a, 652a, 657a, 704a],  
[ 637a, -, 640a, 649a, 705a, 722a, 727a, 734a],  
[ 707a, -, 710a, 719a, 735a, 752a, 757a, 804a],  
[ 737a, -, 740a, 749a, 805a, 822a, 827a, 834a],  
[ 805a, -, 808a, 817a, 833a, 850a, 855a, 902a],  
[ 837a, -, 840a, 849a, 905a, 922a, 927a, 934a],  
[ 907a, -, 910a, 919a, 935a, 952a, 957a, 1004a],  
[ 937a, -, 940a, 949a, 1005a, 1022a, 1027a, 1034a],  
[ 1007a, -, 1010a, 1019a, 1035a, 1052a, 1057a, 1104a],  
[ 1037a, -, 1040a, 1049a, 1105a, 1122a, 1127a, 1134a],  
[ 1107a, -, 1110a, 1119a, 1135a, 1152a, 1157a, 1204p],  
[ 1137a, -, 1140a, 1149a, 1205p, 1222p, 1227p, 1234p],  
[ 1205p, -, 1208p, 1217p, 1233p, 1250p, 1255p, 102p],  
[ 1237p, -, 1240p, 1249p, 105p, 122p, 127p, 134p],  
[ 107p, -, 110p, 119p, 135p, 152p, 157p, 204p],  
[ 137p, -, 140p, 149p, 205p, 222p, 227p, 234p],  
[ 207p, -, 210p, 219p, 235p, 252p, 257p, 304p],  
[ 237p, -, 240p, 249p, 305p, 322p, 327p, 334p],  
[ 257p, -, 300p, 309p, 325p, 342p, 347p, 354p],  
[ 317p, -, 320p, 329p, 345p, 402p, 407p, 414p],  
[ 332p, 336p, 341p, 350p, 406p, 423p, 428p, 435p],  
[ 357p, -, 400p, 409p, 425p, 442p, 447p, 454p],  
[ 412p, 416p, 421p, 430p, 446p, 503p, 508p, 515p],  
[ 437p, -, 440p, 449p, 505p, 522p, 527p, 534p],  
[ 507p, -, 510p, 519p, 535p, 552p, 557p, 604p],  
[ 537p, -, 540p, 549p, 605p, 622p, 627p, 634p],  
[ 607p, -, 610p, 619p, 635p, 652p, 657p, 704p],  
[ 642p, -, 645p, 654p, 710p, 727p, 732p, 739p],  
[ 712p, -, 715p, 724p, 740p, 756p, 801p, 808p],  
[ 742p, -, 745p, 754p, 810p, 826p, 831p, 838p],  
[ 812p, -, 815p, 824p, 840p, 856p, 901p, 908p],  
[ 842p, -, 845p, 854p, 910p, 926p, 931p, 938p],  
[ 912p, -, 915p, 924p, 940p, 956p, 1001p, 1008p],  
[ 942p, -, 945p, 954p, 1010p, 1026p, 1031p, 1038p],  
[ 1012p, -, 1015p, 1024p, 1040p, 1056p, 1101p, 1108p],  
[ 1042p, -, 1045p, 1054p, 1110p, 1126p, 1131p, 1138p],  
[ 1112p, -, 1115p, 1124p, 1140p, 1156p, 1201x, 1208x]]  
stop_times_saturday: [  
[ -, -, -, -, 530a, 545a, 550a, 600a],  
[ -, -, -, -, 635a, 650a, 655a, 705a],  
[ -, -, -, -, 705a, 720a, 725a, 735a],  
[ -, -, -, -, 735a, 750a, 755a, 805a],  
[ -, -, -, -, 805a, 820a, 825a, 835a],  
[ -, -, -, -, 835a, 850a, 855a, 905a],  
[ -, -, -, -, 905a, 920a, 925a, 935a],  
[ -, -, -, -, 935a, 950a, 955a, 1005a],  
[ -, -, -, -, 1005a, 1020a, 1025a, 1035a],  
[ -, -, -, -, 1035a, 1050a, 1055a, 1105a],  
[ -, -, -, -, 1105a, 1120a, 1125a, 1135a],  
[ -, -, -, -, 1135a, 1150a, 1155a, 1205p],  
[ -, -, -, -, 1205p, 1220p, 1225p, 1235p],  
[ -, -, -, -, 1235p, 1250p, 1255p, 105p],  
[ -, -, -, -, 105p, 120p, 125p, 135p],  
[ -, -, -, -, 135p, 150p, 155p, 205p],  
[ -, -, -, -, 205p, 220p, 225p, 235p],  
[ -, -, -, -, 235p, 250p, 255p, 305p],  
[ -, -, -, -, 305p, 320p, 325p, 335p],  
[ -, -, -, -, 335p, 350p, 355p, 405p],  
[ -, -, -, -, 405p, 420p, 425p, 435p],  
[ -, -, -, -, 435p, 450p, 455p, 505p],  
[ -, -, -, -, 505p, 520p, 525p, 535p],  
[ -, -, -, -, 535p, 550p, 555p, 605p],  
[ -, -, -, -, 605p, 620p, 625p, 635p],  
[ -, -, -, -, 635p, 650p, 655p, 705p],  
[ -, -, -, -, 710p, 725p, 730p, 740p],  
[ -, -, -, -, 740p, 755p, 800p, 810p],  
[ -, -, -, -, 810p, 825p, 830p, 840p],  
[ -, -, -, -, 840p, 855p, 900p, 910p],  
[ -, -, -, -, 910p, 925p, 930p, 940p],  
[ -, -, -, -, 940p, 955p, 1000p, 1010p],  
[ -, -, -, -, 1040p, 1055p, 1100p, 1110p],  
[ -, -, -, -, 1140p, 1155p, 1200x, 1210x]  
]  
stop_times_sunday: [  
[ -, -, -, -, 635a, 652a, 657a, 705a],  
[ -, -, -, -, 735a, 752a, 757a, 805a],  
[ -, -, -, -, 835a, 852a, 857a, 905a],  
[ -, -, -, -, 905a, 922a, 927a, 935a],  
[ -, -, -, -, 935a, 952a, 957a, 1005a],  
[ -, -, -, -, 1005a, 1022a, 1027a, 1035a],  
[ -, -, -, -, 1035a, 1052a, 1057a, 1105a],  
[ -, -, -, -, 1105a, 1122a, 1127a, 1135a],  
[ -, -, -, -, 1135a, 1152a, 1157a, 1205p],  
[ -, -, -, -, 1205p, 1222p, 1227p, 1235p],  
[ -, -, -, -, 1235p, 1252p, 1257p, 105p],  
[ -, -, -, -, 105p, 122p, 127p, 135p],  
[ -, -, -, -, 135p, 152p, 157p, 205p],  
[ -, -, -, -, 205p, 222p, 227p, 235p],  
[ -, -, -, -, 235p, 252p, 257p, 305p],  
[ -, -, -, -, 305p, 322p, 327p, 335p],  
[ -, -, -, -, 335p, 352p, 357p, 405p],  
[ -, -, -, -, 405p, 422p, 427p, 435p],  
[ -, -, -, -, 435p, 452p, 457p, 505p],  
[ -, -, -, -, 505p, 522p, 527p, 535p],  
[ -, -, -, -, 535p, 552p, 557p, 605p],  
[ -, -, -, -, 605p, 622p, 627p, 635p],  
[ -, -, -, -, 635p, 652p, 657p, 705p],  
[ -, -, -, -, 735p, 752p, 757p, 805p],  
[ -, -, -, -, 835p, 852p, 857p, 905p],  
[ -, -, -, -, 935p, 952p, 957p, 1005p],  
[ -, -, -, -, 1035p, 1052p, 1057p, 1105p],  
[ -, -, -, -, 1135p, 1152p, 1157p, 1205x]  
]  
 
short_name: 20  
long_name: To Mumford / Downtown  
time_points: [ 7121, 6859, 6800, 7284, 8150, 6087, 8414, 6572 ]  
between_stops:  
7284-8150: [ 7274, 6409, 6403, 6407, 8135, 8133, 8136, 8147, 8149 ]  
stop_times: [  
[ 540a, 547a, 552a, 610a, 618a, 630a, 632a, -],  
[ 600a, 607a, 612a, 630a, 638a, 650a, 652a, -],  
[ -, 622a, 627a, 645a, 653a, 705a, 707a, -],  
[ 630a, 637a, 642a, 700a, 708a, 720a, 722a, 725a],  
[ -, 652a, 657a, 715a, 723a, 735a, 737a, -],  
[ 705a, 712a, 717a, 735a, 743a, 755a, 757a, -],  
[ -, 727a, 732a, 750a, 758a, 810a, 812a, -],  
[ 735a, 742a, 747a, 805a, 813a, 825a, 827a, -],  
[ -, 757a, 802a, 820a, 828a, 840a, 842a, -],  
[ 805a, 812a, 817a, 835a, 843a, 855a, 857a, -],  
[ -, 825a, 830a, 848a, 856a, 908a, 910a, -],  
[ 835a, 842a, 847a, 905a, 913a, 925a, 927a, -],  
[ -, 857a, 902a, 920a, 928a, 940a, 942a, -],  
[ 905a, 912a, 917a, 935a, 943a, 955a, 957a, -],  
[ 935a, 942a, 947a, 1005a, 1013a, 1025a, 1027a, -],  
[ 1005a, 1012a, 1017a, 1035a, 1043a, 1055a, 1057a, -],  
[ 1035a, 1042a, 1047a, 1105a, 1113a, 1125a, 1127a, -],  
[ 1105a, 1112a, 1117a, 1135a, 1143a, 1155a, 1157a, -],  
[ 1135a, 1142a, 1147a, 1205p, 1213p, 1225p, 1227p, -],  
[ 1205p, 1212p, 1217p, 1235p, 1243p, 1255p, 1257p, -],  
[ 1235p, 1242p, 1247p, 105p, 113p, 125p, 127p, -],  
[ 104p, 111p, 116p, 134p, 142p, 154p, 156p, -],  
[ 135p, 142p, 147p, 205p, 213p, 225p, 227p, -],  
[ 205p, 212p, 217p, 235p, 243p, 255p, 257p, -],  
[ 235p, 242p, 247p, 305p, 313p, 325p, 327p, -],  
[ 305p, 312p, 317p, 335p, 343p, 355p, 357p, -],  
[ 335p, 342p, 347p, 405p, 413p, 425p, 427p, -],  
[ 355p, 402p, 407p, 425p, 433p, 445p, 447p, -],  
[ 415p, 422p, 427p, 445p, 453p, 505p, 507p, -],  
[ 435p, 442p, 447p, 505p, 513p, 525p, 527p, -],  
[ 455p, 502p, 507p, 525p, 533p, 545p, 547p, -],  
[ 515p, 522p, 527p, 545p, 553p, 605p, 607p, -],  
[ 535p, 542p, 547p, 605p, 613p, 625p, 627p, -],  
[ 605p, 612p, 617p, 635p, 643p, 655p, 657p, -],  
[ 635p, 642p, 647p, 705p, 713p, 725p, 727p, -],  
[ 705p, 711p, 716p, 733p, 741p, 753p, 755p, -],  
[ 740p, 746p, 751p, 808p, 816p, 828p, 830p, -],  
[ 809p, 815p, 820p, 837p, 845p, 857p, 859p, -],  
[ 839p, 845p, 850p, 907p, 915p, 927p, 929p, -],  
[ 909p, 915p, 920p, 937p, 945p, 957p, 959p, -],  
[ 939p, 945p, 950p, 1007p, 1015p, 1027p, 1029p, -],  
[ 1009p, 1015p, 1020p, 1037p, 1045p, 1057p, 1059p, -],  
[ 1039p, 1045p, 1050p, 1107p, 1115p, 1127p, 1129p, -],  
[ 1109p, 1115p, 1120p, 1137p, 1145p, 1157p, 1159p, -],  
[ 1139p, 1145p, 1150p, 1207x, 1215x, 1227x, 1229x, -],  
[ 1209x, 1215x, 1220x, 1237x, -, -, -, -]  
]  
stop_times_saturday: [  
[ 600a, 605a, 610a, 627a, -, -, -, -],  
[ 705a, 710a, 715a, 732a, -, -, -, -],  
[ 735a, 740a, 745a, 802a, -, -, -, -],  
[ 805a, 810a, 815a, 832a, -, -, -, -],  
[ 835a, 840a, 845a, 902a, -, -, -, -],  
[ 905a, 910a, 915a, 932a, -, -, -, -],  
[ 935a, 940a, 945a, 1002a, -, -, -, -],  
[ 1005a, 1010a, 1015a, 1032a, -, -, -, -],  
[ 1035a, 1040a, 1045a, 1102a, -, -, -, -],  
[ 1105a, 1110a, 1115a, 1132a, -, -, -, -],  
[ 1135a, 1140a, 1145a, 1202p, -, -, -, -],  
[ 1205p, 1210p, 1215p, 1232p, -, -, -, -],  
[ 1235p, 1240p, 1245p, 102p, -, -, -, -],  
[ 105p, 110p, 115p, 132p, -, -, -, -],  
[ 135p, 140p, 145p, 202p, -, -, -, -],  
[ 205p, 210p, 215p, 232p, -, -, -, -],  
[ 235p, 240p, 245p, 302p, -, -, -, -],  
[ 305p, 310p, 315p, 332p, -, -, -, -],  
[ 335p, 340p, 345p, 402p, -, -, -, -],  
[ 405p, 410p, 415p, 432p, -, -, -, -],  
[ 435p, 440p, 445p, 502p, -, -, -, -],  
[ 505p, 510p, 515p, 532p, -, -, -, -],  
[ 535p, 540p, 545p, 602p, -, -, -, -],  
[ 605p, 610p, 615p, 632p, -, -, -, -],  
[ 635p, 640p, 645p, 702p, -, -, -, -],  
[ 705p, 710p, 715p, 732p, -, -, -, -],  
[ 740p, 745p, 750p, 807p, -, -, -, -],  
[ 810p, 815p, 820p, 837p, -, -, -, -],  
[ 840p, 845p, 850p, 907p, -, -, -, -],  
[ 910p, 915p, 920p, 937p, -, -, -, -],  
[ 940p, 945p, 950p, 1007p, -, -, -, -],  
[ 1010p, 1015p, 1020p, 1037p, -, -, -, -],  
[ 1110p, 1115p, 1120p, 1137p, -, -, -, -],  
[ 1210x, 1215x, 1220x, 1237x, -, -, -, -]  
]  
stop_times_sunday: [  
[ 705a, 710a, 715a, 730a, -, -, -, -],  
[ 805a, 810a, 815a, 830a, -, -, -, -],  
[ 905a, 910a, 915a, 930a, -, -, -, -],  
[ 935a, 940a, 945a, 1000a, -, -, -, -],  
[ 1005a, 1010a, 1015a, 1030a, -, -, -, -],  
[ 1035a, 1040a, 1045a, 1100a, -, -, -, -],  
[ 1105a, 1110a, 1115a, 1130a, -, -, -, -],  
[ 1135a, 1140a, 1145a, 1200p, -, -, -, -],  
[ 1205p, 1210p, 1215p, 1230p, -, -, -, -],  
[ 1235p, 1240p, 1245p, 100p, -, -, -, -],  
[ 105p, 110p, 115p, 130p, -, -, -, -],  
[ 135p, 140p, 145p, 200p, -, -, -, -],  
[ 205p, 210p, 215p, 230p, -, -, -, -],  
[ 235p, 240p, 245p, 300p, -, -, -, -],  
[ 305p, 310p, 315p, 330p, -, -, -, -],  
[ 335p, 340p, 345p, 400p, -, -, -, -],  
[ 405p, 410p, 415p, 430p, -, -, -, -],  
[ 435p, 440p, 445p, 500p, -, -, -, -],  
[ 505p, 510p, 515p, 530p, -, -, -, -],  
[ 535p, 540p, 545p, 600p, -, -, -, -],  
[ 605p, 610p, 615p, 630p, -, -, -, -],  
[ 635p, 640p, 645p, 700p, -, -, -, -],  
[ 705p, 710p, 715p, 730p, -, -, -, -],  
[ 805p, 810p, 815p, 830p, -, -, -, -],  
[ 905p, 910p, 915p, 930p, -, -, -, -],  
[ 1005p, 1010p, 1015p, 1030p, -, -, -, -],  
[ 1105p, 1110p, 1115p, 1130p, -, -, -, -],  
[ 1205x, 1210x, 1215x, 1230x, -, -, -, -]  
]  
 
short_name: 21  
long_name: To Lacewood / Halifax  
time_points: [ 6317, 6189, 7087, 8364 ]  
# FIXME: should start at 6722, 5 minutes before  
between_stops:  
7087-8364: [ 6983, 8631, 6783, 6776, 6777, 6781, 6774, 6780, 6786, 6790, 6771, 6084, 6103, 6122, 8331, 8330, 8334, 8335 ]  
stop_times: [  
[ 550a, 602a, 615a, 651a],  
[ 625a, 637a, 650a, 726a],  
[ 655a, 707a, 720a, 756a],  
[ 730a, 742a, 755a, 831a],  
[ 755a, 807a, 820a, 856a],  
[ 825a, 837a, 850a, -],  
[ 855a, 907a, 920a, -],  
[ 925a, 937a, 950a, -],  
[ 955a, 1007a, 1020a, -],  
[ 1025a, 1037a, 1050a, -],  
[ 1055a, 1107a, 1120a, -],  
[ 1125a, 1137a, 1150a, -],  
[ 1155a, 1207p, 1220p, -],  
[ 1229p, 1241p, 1254p, -],  
[ 103p, 111p, 123p, -],  
[ 133p, 141p, 153p, -],  
[ 203p, 211p, 223p, -],  
[ 233p, 241p, 253p, -],  
[ 303p, 311p, 323p, -],  
[ 333p, 341p, 353p, -],  
[ 403p, 411p, 423p, -],  
[ 443p, 451p, 503p, -],  
[ 513p, 521p, 533p, -],  
[ 543p, 551p, 603p, -],  
[ 613p, 621p, 633p, -],  
[ 643p, 651p, 703p, -],  
[ 713p, 721p, 733p, -],  
[ 737p, 745p, 757p, -],  
[ 803p, 811p, 823p, -],  
[ 833p, 841p, 853p, -],  
[ 903p, 911p, 923p, -],  
[ 933p, 941p, 953p, -],  
[ 1003p, 1011p, 1023p, -],  
[ 1033p, 1041p, 1053p, -],  
[ 1103p, 1111p, 1123p, -],  
[ 1133p, 1141p, 1153p, -],  
[ 1203a, 1211x, 1223x, -],  
[ 1233a, 1241x, 1253x, -]  
]  
stop_times_saturday: [  
[ 625a, 633a, 645a, -],  
[ 655a, 703a, 715a, -],  
[ 725a, 733a, 745a, -],  
[ 755a, 803a, 815a, -],  
[ 825a, 833a, 845a, -],  
[ 855a, 903a, 915a, -],  
[ 925a, 933a, 945a, -],  
[ 955a, 1003a, 1015a, -],  
[ 1025a, 1033a, 1045a, -],  
[ 1055a, 1103a, 1115a, -],  
[ 1125a, 1133a, 1145a, -],  
[ 1155a, 1203p, 1215p, -],  
[ 1225p, 1233p, 1245p, -],  
[ 1255p, 103p, 115p, -],  
[ 125p, 133p, 145p, -],  
[ 155p, 203p, 215p, -],  
[ 225p, 233p, 245p, -],  
[ 255p, 303p, 315p, -],  
[ 325p, 333p, 345p, -],  
[ 355p, 403p, 415p, -],  
[ 425p, 433p, 445p, -],  
[ 455p, 503p, 515p, -],  
[ 525p, 533p, 545p, -],  
[ 555p, 603p, 615p, -],  
[ 625p, 633p, 645p, -],  
[ 655p, 703p, 715p, -],  
[ 725p, 733p, 745p, -],  
[ 800p, 808p, 820p, -],  
[ 830p, 838p, 850p, -],  
[ 900p, 908p, 920p, -],  
[ 930p, 938p, 950p, -],  
[ 1000p, 1008p, 1020p, -],  
[ 1030p, 1038p, 1050p, -],  
[ 1100p, 1108p, 1120p, -],  
[ 1130p, 1138p, 1150p, -],  
[ 1200x, 1208x, 1220x, -],  
[ 1230x, 1238x, 1250x, -]  
]  
stop_times_sunday: [  
[ 645a, 653a, 705a, -],  
[ 745a, 753a, 805a, -],  
[ 845a, 853a, 905a, -],  
[ 945a, 953a, 1005a, -],  
[ 1045a, 1053a, 1105a, -],  
[ 1145a, 1153a, 1205p, -],  
[ 1245p, 1253p, 105p, -],  
[ 145p, 153p, 205p, -],  
[ 245p, 253p, 305p, -],  
[ 345p, 353p, 405p, -],  
[ 445p, 453p, 505p, -],  
[ 545p, 553p, 605p, -],  
[ 645p, 653p, 705p, -],  
[ 745p, 753p, 805p, -],  
[ 845p, 853p, 905p, -],  
[ 945p, 953p, 1005p, -],  
[ 1045p, 1053p, 1105p, -],  
[ 1145p, 1153p, 1205x, -]  
]  
 
short_name: 21  
long_name: To Timberlea  
time_points: [ 8363, 7086, 6160, 6315, 6722 ]  
between_stops:  
8363-7086: [ 8337, 8333, 8336, 8327, 8338, 6121, 6086, 6106, 6455, 6773, 6778, 6779, 6775, 6787, 6769, 6785, 6768, 6782, 8632, 8192 ]  
stop_times: [  
[ -, 525a, 531a, 540a, 545a],  
[ -, 600a, 606a, 615a, 620a],  
[ -, 627a, 633a, 642a, 650a],  
[ -, 705a, 711a, 720a, 725a],  
[ -, 727a, 733a, 742a, 750a],  
[ -, 800a, 806a, 815a, 820a],  
[ -, 830a, 836a, 845a, 850a],  
[ -, 900a, 906a, 915a, 920a],  
[ -, 930a, 936a, 945a, 950a],  
[ -, 1000a, 1006a, 1015a, 1020a],  
[ -, 1030a, 1036a, 1045a, 1050a],  
[ -, 1100a, 1106a, 1115a, 1120a],  
[ -, 1130a, 1136a, 1145a, 1150a],  
[ -, 1200p, 1206p, 1215p, 1224p],  
[ -, 1230p, 1236p, 1245p, 1254p],  
[ -, 100p, 106p, 115p, 124p],  
[ -, 130p, 136p, 145p, 154p],  
[ -, 200p, 206p, 215p, 224p],  
[ -, 230p, 236p, 245p, 254p],  
[ -, 300p, 308p, 321p, 328p],  
[ -, 330p, 338p, 351p, 358p],  
[ 331p, 410p, 418p, 431p, 438p],  
[ 401p, 440p, 448p, 501p, 508p],  
[ 431p, 510p, 518p, 531p, 538p],  
[ 501p, 540p, 548p, 601p, 608p],  
[ 531p, 610p, 618p, 631p, 638p],  
[ 601p, 640p, 648p, 701p, 708p],  
[ -, 705p, 713p, 726p, 732p],  
[ -, 735p, 743p, 753p, 758p],  
[ -, 805p, 813p, 823p, 828p],  
[ -, 835p, 843p, 853p, 858p],  
[ -, 905p, 913p, 923p, 928p],  
[ -, 935p, 943p, 953p, 958p],  
[ -, 1005p, 1013p, 1023p, 1028p],  
[ -, 1035p, 1043p, 1053p, 1058p],  
[ -, 1105p, 1113p, 1123p, 1128p],  
[ -, 1135p, 1143p, 1153p, 1158p],  
[ -, 1205x, 1213x, 1223x, 1228x]  
]  
stop_times_saturday: [  
[ -, 555a, 602a, 615a, 620a],  
[ -, 625a, 632a, 645a, 650a],  
[ -, 655a, 702a, 715a, 720a],  
[ -, 725a, 732a, 745a, 750a],  
[ -, 755a, 802a, 815a, 820a],  
[ -, 825a, 832a, 845a, 850a],  
[ -, 855a, 902a, 915a, 920a],  
[ -, 925a, 932a, 945a, 950a],  
[ -, 955a, 1002a, 1015a, 1020a],  
[ -, 1025a, 1032a, 1045a, 1050a],  
[ -, 1055a, 1102a, 1115a, 1120a],  
[ -, 1055a, 1102a, 1115a, 1120a],  
[ -, 1125a, 1132a, 1145a, 1150a],  
[ -, 1155a, 1202p, 1215p, 1220p],  
[ -, 1225p, 1232p, 1245p, 1250p],  
[ -, 1255p, 102p, 115p, 120p],  
[ -, 125p, 132p, 145p, 150p],  
[ -, 155p, 202p, 215p, 220p],  
[ -, 225p, 232p, 245p, 250p],  
[ -, 255p, 302p, 315p, 320p],  
[ -, 325p, 332p, 345p, 350p],  
[ -, 355p, 402p, 415p, 420p],  
[ -, 425p, 432p, 445p, 450p],  
[ -, 455p, 502p, 515p, 520p],  
[ -, 525p, 532p, 545p, 550p],  
[ -, 555p, 602p, 615p, 620p],  
[ -, 625p, 632p, 645p, 650p],  
[ -, 655p, 702p, 715p, 720p],  
[ -, 730p, 737p, 750p, 755p],  
[ -, 800p, 807p, 820p, 825p],  
[ -, 830p, 837p, 850p, 855p],  
[ -, 900p, 907p, 920p, 925p],  
[ -, 930p, 937p, 950p, 955p],  
[ -, 1000p, 1007p, 1020p, 1025p],  
[ -, 1030p, 1037p, 1050p, 1055p],  
[ -, 1100p, 1107p, 1120p, 1125p],  
[ -, 1130p, 1137p, 1150p, 1155p],  
[ -, 1200x, 1207x, 1220x, 1225x]  
]  
stop_times_sunday: [  
[ -, 615a, 622a, 635a, 640a],  
[ -, 715a, 722a, 735a, 740a],  
[ -, 815a, 822a, 835a, 840a],  
[ -, 915a, 922a, 935a, 940a],  
[ -, 1015a, 1022a, 1035a, 1040a],  
[ -, 1115a, 1122a, 1135a, 1140a],  
[ -, 1115a, 1122a, 1135a, 1140a],  
[ -, 1215p, 1222p, 1235p, 1240p],  
[ -, 115p, 122p, 135p, 140p],  
[ -, 215p, 222p, 235p, 240p],  
[ -, 315p, 322p, 335p, 340p],  
[ -, 415p, 422p, 435p, 440p],  
[ -, 515p, 522p, 535p, 540p],  
[ -, 615p, 622p, 635p, 640p],  
[ -, 715p, 722p, 735p, 740p],  
[ -, 815p, 822p, 835p, 840p],  
[ -, 915p, 922p, 935p, 940p],  
[ -, 1115p, 1122p, 1135p, 1140p]  
]  
 
short_name: 23  
long_name: To Mumford / Halifax  
time_points: [ 6722, 6317, 6189, 7284, 8414 ]  
between_stops:  
6189-7284: [ 7276 ]  
7284-8414: [ 7274, 6409, 6403, 6407, 6406, 6545, 8205, 8337, 8333, 8336, 8327, 8338, 6087 ]  
stop_times: [  
[ 605a, 610a, 617a, 632a, 656a],  
[ 635a, 640a, 647a, 703a, 729a],  
[ 705a, 710a, 717a, 737a, 803a],  
[ 735a, 740a, 747a, 807a, 833a],  
[ 805a, 810a, 817a, 837a, 903a],  
[ 835a, 840a, 847a, 907a, 933a],  
[ 447p, 452p, 459p, 514p, -],  
[ 517p, 522p, 529p, 544p, -],  
[ 547p, 552p, 559p, 614p, -],  
[ 617p, 622p, 629p, 644p, -],  
[ 645p, 650p, 657p, 712p, -],  
[ 714p, 719p, 726p, 741p, -]  
]  
 
short_name: 23  
long_name: To Timberlea  
time_points: [ 8414, 8643, 6160, 6315, 6722 ]  
between_stops:  
8414-8643: [ 6125, 6105, 6108, 6103, 6122, 8331, 8330, 8334, 8335, 8184, 8206, 6544, 6405, 6404, 6413, 6414, 7275 ]  
8643-6160: [ 7273 ]  
 
stop_times: [  
[ -, 533a, 548a, 554a, 600a],  
[ -, 603a, 618a, 624a, 630a],  
[ -, 633a, 648a, 654a, 700a],  
[ -, 703a, 718a, 724a, 730a],  
[ -, 733a, 748a, 754a, 800a],  
[ -, 803a, 818a, 824a, 830a],  
[ 346p, 417p, 432p, 438p, 444p],  
[ 416p, 447p, 502p, 508p, 514p],  
[ 446p, 517p, 532p, 538p, 544p],  
[ 516p, 547p, 602p, 608p, 614p],  
[ 546p, 614p, 629p, 635p, 641p],  
[ 616p, 644p, 659p, 705p, 711p]  
]  
 
short_name: 3  
long_name: To Manors  
time_points: [ 7284, 6563, 8164, 6505, 6105, 8334, 8430 ]  
between_stops:  
8164-6505: [ 7367, 7382, 7364, 6770, 6783, 6776, 6777, 6781, 6774, 6780, 6786 ]  
6105-8337: [ 6108, 6103, 6102, 6122, 8331, 8330, 8334 ]  
stop_times: [  
[ 957a, 1012a, 1026a, 1037a, 1040a, 1047a, 1055a],  
[ 1207p, 1222p, 1236p, 1247p, 1250p, 1257p, 105p],  
[ 217p, 232p, 246p, 257p, 300p, 307p, 315p],  
[ 247p, 302p, 316p, 327p, 330p, 337p, 345p]  
]  
 
short_name: 3  
long_name: To Shopping Malls  
time_points: [ 8430, 6791, 8337, 6087, 6505, 8165, 6564, 7284 ]  
between_stops:  
6791-8337: [ 8328 ]  
8337-6087: [ 8333, 8336, 8327, 8338 ]  
6505-8165: [ 6775, 6787, 6769, 6785, 6768, 6782, 7377, 7381, 7373, 7376, 7380 ]  
6564-7284: [ 6197, 6193 ]  
6087-6505: [ 6455, 6773, 6778 ]  
8165-6564: [ 6199, 6198, 6564, 6563, 6565, 6984 ]  
stop_times: [  
[ 855a, 858a, 904a, 913a, 916a, 927a, 941a, 950a],  
[ 1105a, 1108a, 1114a, 1123a, 1126a, 1137a, 1151a, 1200p],  
[ 115p, 118p, 124p, 133p, 136p, 147p, 201p, 210p],  
[ 145p, 148p, 154p, 203p, 206p, 217p, 231p, 240p],  
[ 317p, 320p, -, -, -, -, -, -],  
[ 347p, 350p, -, -, -, -, -, -]  
]  
 
short_name: 4  
long_name: To Downtown via North  
time_points: [ 6601, 7087, 6611, 6564, 7284, 7351, 6105, 8435 ]  
between_stops:  
7284-7351: [ 7274, 6409, 6403, 6407, 6406, 7355, 7345, 7357, 7352, 7342, 7354, 7347 ]  
7351-6105: [ 7343, 6088, 6104, 6125 ]  
6105-8435: [ 6108, 6733 ]  
stop_times: [  
[ 538a, 549a, 558a, 602a, 611a, 620a, 625a, 628a],  
[ 624a, 635a, 645a, 649a, 657a, 707a, 712a, 715a],  
[ 654a, 705a, 715a, 719a, 727a, 737a, 742a, 745a],  
[ 724a, 735a, 745a, 749a, 757a, 807a, 812a, 815a],  
[ 754a, 805a, 815a, 819a, 827a, 837a, 842a, 845a],  
[ 824a, 835a, 845a, 849a, 857a, 907a, 913a, 916a],  
[ 854a, 905a, 915a, 920a, 928a, 938a, 944a, 947a],  
[ 924a, 935a, 945a, 950a, 958a, 1008a, 1014a, 1017a],  
[ 954a, 1005a, 1015a, 1020a, 1028a, 1038a, 1044a, 1047a],  
[ 1024a, 1035a, 1045a, 1050a, 1058a, 1108a, 1114a, 1117a],  
[ 1054a, 1105a, 1115a, 1120a, 1128a, 1138a, 1144a, 1147a],  
[ 1124a, 1135a, 1145a, 1150a, 1158a, 1208p, 1214p, 1217p],  
[ 1154a, 1205p, 1215p, 1220p, 1228p, 1238p, 1244p, 1247p],  
[ 1224p, 1235p, 1245p, 1250p, 1258p, 108p, 114p, 117p],  
[ 1254p, 105p, 115p, 120p, 128p, 138p, 144p, 147p],  
[ 124p, 135p, 145p, 150p, 158p, 208p, 214p, 217p],  
[ 154p, 205p, 215p, 220p, 228p, 238p, 244p, 247p],  
[ 224p, 235p, 245p, 250p, 258p, 308p, 314p, 317p],  
[ 254p, 305p, 315p, 320p, 328p, 338p, 344p, 347p],  
[ 324p, 335p, 345p, 350p, 358p, 408p, 414p, 417p],  
[ 354p, 405p, 415p, 420p, 428p, 438p, 444p, 447p],  
[ 424p, 435p, 445p, 450p, 458p, 508p, 514p, 517p],  
[ 454p, 505p, 515p, 520p, 528p, 538p, 543p, 546p],  
[ 524p, 535p, 545p, 550p, 558p, 606p, 610p, 614p],  
[ 554p, 605p, 615p, 618p, 624p, 632p, 636p, 640p],  
[ 626p, 637p, 647p, 650p, 656p, 704p, 708p, 712p],  
[ 709p, 720p, 730p, 733p, 739p, 747p, 751p, 755p],  
[ 809p, 820p, 830p, 833p, 839p, 847p, 851p, 855p],  
[ 909p, 920p, 930p, 933p, 939p, 947p, 951p, 955p],  
[ 1009p, 1020p, 1030p, 1033p, 1039p, 1047p, 1051p, 1055p],  
[ 1109p, 1120p, 1130p, 1133p, 1139p, 1147p, 1151p, 1155p],  
[ 1209x, 1220x, -, -, -, -, -, -]  
]  
 
short_name: 4  
long_name: To Farnham Gate via Rosedale  
time_points: [ 8435, 7348, 7284, 6563, 6611, 7087, 6601 ]  
between_stops:  
8435-7348: [ 6089, 6116 ]  
7348-7284: [ 7346, 7341, 7353, 7358, 7344, 7356, 6405, 6404, 6413, 6414, 7275 ]  
6563-6611: [ 6565, 6984 ]  
stop_times: [  
[ -, -, -, -, 520a, 529a, 537a],  
[ -, -, -, -, 606a, 615a, 623a],  
[ 610a, 617a, 626a, 632a, 636a, 645a, 653a],  
[ 640a, 647a, 656a, 702a, 706a, 715a, 723a],  
[ 710a, 717a, 726a, 732a, 736a, 745a, 753a],  
[ 740a, 747a, 756a, 802a, 806a, 815a, 823a],  
[ 807a, 814a, 823a, 829a, 834a, 845a, 853a],  
[ 832a, 839a, 852a, 859a, 904a, 915a, 923a],  
[ 902a, 909a, 922a, 929a, 934a, 945a, 953a],  
[ 932a, 939a, 952a, 959a, 1004a, 1015a, 1023a],  
[ 1002a, 1009a, 1022a, 1029a, 1034a, 1045a, 1053a],  
[ 1032a, 1039a, 1052a, 1059a, 1104a, 1115a, 1123a],  
[ 1102a, 1109a, 1122a, 1129a, 1134a, 1145a, 1153a],  
[ 1132a, 1139a, 1152a, 1159a, 1204p, 1215p, 1223p],  
[ 1202p, 1209p, 1222p, 1229p, 1234p, 1245p, 1253p],  
[ 1232p, 1239p, 1252p, 1259p, 104p, 115p, 123p],  
[ 102p, 109p, 122p, 129p, 134p, 145p, 153p],  
[ 132p, 139p, 152p, 159p, 204p, 215p, 223p],  
[ 201p, 208p, 222p, 229p, 234p, 245p, 253p],  
[ 231p, 238p, 252p, 259p, 304p, 315p, 323p],  
[ 300p, 307p, 322p, 329p, 334p, 344p, 353p],  
[ 329p, 337p, 352p, 359p, 404p, 415p, 423p],  
[ 359p, 407p, 422p, 429p, 434p, 445p, 453p],  
[ 429p, 437p, 452p, 459p, 504p, 515p, 523p],  
[ 459p, 507p, 522p, 529p, 534p, 545p, 553p],  
[ 533p, 540p, 554p, 600p, 605p, 617p, 625p],  
[ 624p, 631p, 640p, 646p, 650p, 700p, 708p],  
[ 724p, 731p, 740p, 746p, 750p, 800p, 808p],  
[ 824p, 831p, 840p, 846p, 850p, 900p, 908p],  
[ 924p, 931p, 940p, 946p, 950p, 1000p, 1008p],  
[ 1024p, 1031p, 1040p, 1046p, 1050p, 1100p, 1108p],  
[ 1124p, 1131p, 1140p, 1146p, 1150p, 1200x, 1208x]  
]  
 
short_name: 41  
long_name: To Bridge Terminal  
time_points: [ 7144, 6096, 6087, 8642 ]  
between_stops:  
7144-6096: [ 8296, 8303, 8305, 8295, 8299, 8293 ]  
6096-6087: [ 6113, 6124, 6121, 6106 ]  
6087-8642: [ 6455, 6773, 6778, 6779, 6775, 6787, 7351 ]  
stop_times: [  
[ 715a, 721a, 728a, 738a],  
[ 807a, 813a, 820a, 830a],  
[ 827a, 833a, 840a, 850a],  
[ 845a, 851a, 858a, 908a],  
[ 907a, 913a, 920a, 930a],  
[ 924a, 930a, 937a, 947a],  
[ 944a, 950a, 957a, 1007a],  
[ 1004a, 1010a, 1017a, 1027a],  
[ 1024a, 1030a, 1037a, 1047a],  
[ 1044a, 1050a, 1057a, 1107a],  
[ 1104a, 1110a, 1117a, 1127a],  
[ 1124a, 1130a, 1137a, 1147a],  
[ 1144a, 1150a, 1157a, 1207p],  
[ 1204p, 1210p, 1217p, 1227p],  
[ 1224p, 1230p, 1237p, 1247p],  
[ 1244p, 1250p, 1257p, 107p],  
[ 104p, 110p, 117p, 127p],  
[ 124p, 130p, 137p, 147p],  
[ 144p, 150p, 157p, 207p],  
[ 204p, 210p, 217p, 227p],  
[ 224p, 230p, 237p, 247p],  
[ 244p, 250p, 257p, 307p],  
[ 304p, 310p, 317p, 327p],  
[ 324p, 330p, 337p, 347p],  
[ 344p, 350p, 357p, 407p],  
[ 407p, 413p, 420p, 430p],  
[ 427p, 433p, 440p, 450p],  
[ 447p, 453p, 500p, 510p],  
[ 507p, 513p, 520p, 530p],  
[ 527p, 533p, 540p, 550p],  
[ 547p, 553p, 600p, 610p],  
[ 629p, 635p, 642p, 652p],  
[ 649p, 655p, 702p, 712p],  
[ 709p, 715p, 722p, 732p]  
]  
 
# No service Saturdays, Sundays or Holidays  
 
short_name: 41  
long_name: To Dalhousie  
time_points: [ 8642, 6105, 6114, 7144 ]  
between_stops:  
8642-6105: [ 8638, 6088, 6104, 6125 ]  
6105-6114: [ 6108, 6103, 6102 ]  
6114-7144: [ 6097, 8294, 8292, 8300, 8301, 8298, 8297, 8317 ]  
stop_times: [  
[ 650a, 700a, 707a, 713a],  
[ 745a, 755a, 802a, 807a],  
[ 815a, 825a, 832a, 838a],  
[ 835a, 845a, 852a, 858a],  
[ 855a, 905a, 912a, 918a],  
[ 915a, 925a, 932a, 938a],  
[ 935a, 945a, 952a, 958a],  
[ 952a, 1002a, 1009a, 1015a],  
[ 1012a, 1022a, 1029a, 1035a],  
[ 1032a, 1042a, 1049a, 1055a],  
[ 1052a, 1102a, 1109a, 1115a],  
[ 1112a, 1122a, 1129a, 1135a],  
[ 1132a, 1142a, 1149a, 1155a],  
[ 1152a, 1202p, 1209p, 1215p],  
[ 1212p, 1222p, 1229p, 1235p],  
[ 1232p, 1242p, 1249p, 1255p],  
[ 1252p, 102p, 109p, 115p],  
[ 112p, 122p, 129p, 135p],  
[ 132p, 142p, 149p, 155p],  
[ 152p, 202p, 209p, 215p],  
[ 212p, 222p, 229p, 235p],  
[ 232p, 242p, 249p, 255p],  
[ 252p, 302p, 309p, 315p],  
[ 312p, 322p, 329p, 335p],  
[ 332p, 342p, 349p, 355p],  
[ 352p, 402p, 409p, 415p],  
[ 412p, 422p, 429p, 435p],  
[ 435p, 445p, 452p, 458p],  
[ 455p, 505p, 512p, 518p],  
[ 515p, 525p, 532p, 538p],  
[ 535p, 545p, 552p, 558p],  
[ 555p, 605p, 612p, 618p]  
]  
 
# No service Saturdays, Sundays or Holidays  
 
short_name: 42  
long_name: To Dalhousie  
time_points: [ 7086, 7166, 8193, 8214, 7144 ]  
between_stops:  
8193-8214: [ 8202, 8182, 8213, 8178, 8205, 8190 ]  
8214-7144: [ 8183, 8196, 8195, 8194, 8186, 8188, 8317 ]  
stop_times: [  
[ 655a, 701a, 708a, 716a, 722a],  
[ 755a, 801a, 808a, 816a, 822a],  
[ 815a, 821a, 828a, 836a, 842a],  
[ 835a, 841a, 848a, 856a, 902a],  
[ 855a, 901a, 906a, 913a, 919a],  
[ 915a, 921a, 926a, 933a, 939a],  
[ 935a, 941a, 946a, 953a, 959a],  
[ 955a, 1001a, 1006a, 1013a, 1019a],  
[ 1015a, 1021a, 1026a, 1033a, 1039a],  
[ 1035a, 1041a, 1046a, 1053a, 1059a],  
[ 1055a, 1101a, 1106a, 1113a, 1119a],  
[ 1115a, 1121a, 1126a, 1133a, 1139a],  
[ 1135a, 1141a, 1146a, 1153a, 1159a],  
[ 1155a, 1201p, 1206p, 1213p, 1219p],  
[ 1215p, 1221p, 1226p, 1233p, 1239p],  
[ 1235p, 1241p, 1246p, 1253p, 1259p],  
[ 1255p, 101p, 106p, 113p, 119p],  
[ 115p, 121p, 126p, 133p, 139p],  
[ 135p, 141p, 146p, 153p, 159p],  
[ 155p, 201p, 206p, 213p, 219p],  
[ 215p, 221p, 226p, 233p, 239p],  
[ 235p, 241p, 246p, 253p, 259p],  
[ 255p, 301p, 306p, 313p, 319p],  
[ 315p, 321p, 326p, 333p, 339p],  
[ 335p, 341p, 348p, 356p, 402p],  
[ 355p, 401p, 408p, 416p, 422p],  
[ 415p, 421p, 428p, 436p, 442p],  
[ 435p, 441p, 448p, 456p, 502p],  
[ 455p, 501p, 508p, 516p, 522p],  
[ 515p, 521p, 528p, 536p, 542p],  
[ 537p, 543p, 550p, 558p, 604p],  
[ 557p, 603p, 610p, 618p, 624p],  
[ 617p, 623p, 630p, 638p, 644p],  
[ 637p, 643p, 650p, 658p, 704p]  
]  
 
# No service Saturdays, Sundays or Holidays  
 
short_name: 42  
long_name: To Lacewood  
time_points: [ 7144, 8184, 8629, 6032, 7086 ]  
between_stops:  
7144-8184: [ 8220, 8187, 8185, 8219, 8179 ]  
8184-8629: [ 8206, 8221, 8222, 8181, 8210, 8201, 8251 ]  
stop_times: [  
[ 722a, 728a, 736a, 744a, 751a],  
[ 843a, 849a, 857a, 904a, 911a],  
[ 903a, 909a, 916a, 922a, 929a],  
[ 923a, 929a, 936a, 942a, 949a],  
[ 943a, 949a, 956a, 1002a, 1009a],  
[ 1003a, 1009a, 1016a, 1022a, 1029a],  
[ 1020a, 1026a, 1033a, 1039a, 1046a],  
[ 1040a, 1046a, 1053a, 1059a, 1106a],  
[ 1100a, 1106a, 1113a, 1119a, 1126a],  
[ 1120a, 1126a, 1133a, 1139a, 1146a],  
[ 1140a, 1146a, 1153a, 1159a, 1206p],  
[ 1200p, 1206p, 1213p, 1219p, 1226p],  
[ 1220p, 1226p, 1233p, 1239p, 1246p],  
[ 1240p, 1246p, 1253p, 1259p, 106p],  
[ 100p, 106p, 113p, 119p, 126p],  
[ 120p, 126p, 133p, 139p, 146p],  
[ 140p, 146p, 153p, 159p, 206p],  
[ 200p, 206p, 213p, 219p, 226p],  
[ 220p, 226p, 233p, 239p, 246p],  
[ 240p, 246p, 253p, 259p, 306p],  
[ 300p, 306p, 313p, 319p, 326p],  
[ 320p, 326p, 333p, 341p, 348p],  
[ 340p, 346p, 354p, 402p, 409p],  
[ 400p, 406p, 414p, 422p, 429p],  
[ 420p, 426p, 434p, 442p, 449p],  
[ 440p, 446p, 454p, 502p, 509p],  
[ 503p, 509p, 517p, 525p, 532p],  
[ 523p, 529p, 537p, 545p, 552p],  
[ 543p, 549p, 557p, 605p, 612p],  
[ 603p, 609p, 617p, 625p, 632p],  
[ 623p, 629p, 637p, 645p, 652p]  
]  
 
# No service Saturdays, Sundays or Holidays  
 
short_name: 5  
long_name: To Downtown  
time_points: [ 6578, 7284, 6397, 8435 ]  
between_stops:  
7284-6397: [ 6409, 6403, 6407, 6406 ]  
6397-8435: [ 6545, 6108 ]  
stop_times: [  
[ 720a, 730a, 735a, 745a],  
[ 750a, 800a, 805a, 815a],  
[ 822a, 832a, 837a, 847a],  
[ 405p, 415p, -, -],  
[ 435p, 445p, -, -],  
[ 540p, 550p, -, -]  
]  
 
short_name: 5  
long_name: To Springvale  
time_points: [ 8435, 6396, 7284, 6578 ]  
between_stops:  
8435-6396: [ 6544 ]  
6396-7284: [ 6404, 6413, 6414, 7275 ]  
stop_times: [  
[ -, -, 710a, 720a],  
[ -, -, 740a, 750a],  
[ -, -, 817a, 822a],  
[ -, -, 355p, 405p],  
[ 410p, 420p, 425p, 435p],  
[ 515p, 525p, 530p, 540p]  
]  
 
short_name: 52  
long_name: To Bridge Terminal - Burnside  
time_points: [ 6390, 7087, 7285, 7351, 8641, 6923, 6949, 7153, 6767 ]  
between_stops:  
7285-7351: [ 7274, 6409, 6403, 6407, 6406, 7355, 7345, 7357, 7352, 7342, 7354, 7347 ]  
stop_times: [  
[ -, 553a, 609a, 619a, 625a, 636a, 642a, 646a, -],  
[ 608a, 623a, 639a, 649a, 655a, 706a, 712a, 716a, -],  
[ -, 638a, 654a, 704a, 710a, 721a, 727a, 731a, -],  
[ 638a, 653a, 709a, 719a, 725a, 736a, 742a, 746a, -],  
[ -, 708a, 724a, 734a, 740a, 751a, 757a, 801a, -],  
[ 708a, 723a, 739a, 749a, 755a, 806a, 812a, 816a, -],  
[ -, 738a, 754a, 804a, 810a, 820a, 825a, 829a, -],  
[ 738a, 753a, 809a, 819a, 825a, 836a, 842a, 843a, -],  
[ 753a, 808a, 823a, 832a, 838a, 848a, 853a, 857a, -],  
[ 810a, 825a, 840a, 849a, 855a, 905a, 910a, -, 921a],  
[ 820a, 834a, -, -, -, -, -, -, -],  
[ 840a, 855a, 910a, 919a, 925a, 935a, 940a, -, 951a],  
[ 850a, 904a, -, -, -, -, -, -, -],  
[ 910a, 925a, 940a, 949a, 955a, 1005a, 1010a, -, 1021a],  
[ 920a, 934a, -, -, -, -, -, -, -],  
[ 940a, 955a, 1010a, 1019a, 1025a, 1035a, 1040a, -, 1051a],  
[ 945a, 959a, -, -, -, -, -, -, -],  
[ 958a, 1012a, -, -, -, -, -, -, -],  
[ 1010a, 1025a, 1040a, 1049a, 1055a, 1105a, 1110a, -, 1121a],  
[ 1040a, 1055a, 1110a, 1119a, 1125a, 1135a, 1140a, -, 1151a],  
[ 1110a, 1125a, 1140a, 1149a, 1155a, 1205p, 1210p, -, 1221p],  
[ 1140a, 1155a, 1210p, 1219p, 1225p, 1235p, 1240p, -, 1251p],  
[ 1210p, 1225p, 1240p, 1249p, 1255p, 105p, 110p, -, 121p],  
[ 1240p, 1255p, 110p, 119p, 125p, 135p, 140p, -, 151p],  
[ 110p, 125p, 140p, 149p, 155p, 205p, 210p, -, 221p],  
[ 140p, 155p, 210p, 219p, 225p, 235p, 240p, -, 251p],  
[ 210p, 225p, 240p, 249p, 255p, 305p, 310p, -, 321p],  
[ 238p, 253p, 309p, 319p, 325p, 336p, 342p, 346p, -],  
[ -, -, -, -, -, -, 357p, 401p, -],  
[ 308p, 323p, 339p, 349p, 355p, 406p, 412p, 416p, -],  
[ -, -, -, -, -, -, 427p, 431p, -],  
[ 338p, 353p, 409p, 419p, 425p, 436p, 442p, 446p, -],  
[ -, -, -, -, -, -, 457p, 501p, -],  
[ 408p, 423p, 439p, 449p, 455p, 506p, 512p, 516p, -],  
[ -, -, -, -, -, -, 527p, 531p, -],  
[ 438p, 453p, 509p, 519p, 525p, 536p, 542p, 543p, -],  
[ -, -, -, -, -, -, 557p, 601p, -],  
[ 510p, 525p, 540p, 549p, 555p, 605p, 610p, -, 621p],  
[ 525p, 540p, 555p, 604p, 610p, 620p, 625p, -, -],  
[ 540p, 555p, 610p, 619p, 625p, 635p, 640p, -, 651p],  
[ 555p, 610p, 625p, 634p, 640p, 650p, 655p, -, -],  
[ 610p, 625p, 640p, 649p, 655p, 705p, 710p, -, 721p],  
[ 625p, 640p, 655p, 704p, 710p, 720p, 725p, -, -],  
[ 640p, 655p, 710p, 719p, 725p, 735p, 740p, -, 751p],  
[ 650p, 704p, -, -, -, -, -, -, -],  
[ 700p, 714p, -, -, -, -, -, -, -],  
[ 710p, 725p, 740p, 749p, 755p, 805p, 810p, -, 821p],  
[ 740p, 755p, 810p, 819p, 825p, 835p, 840p, -, 851p],  
[ 810p, 825p, 840p, 849p, 855p, 905p, 910p, -, 921p],  
[ 840p, 855p, 910p, 919p, 925p, 935p, 940p, -, 951p],  
[ 910p, 925p, 940p, 949p, 955p, 1005p, 1010p, -, -],  
[ 940p, 955p, 1010p, 1019p, 1025p, 1035p, 1040p, -, -],  
[ 1010p, 1025p, 1040p, 1049p, 1055p, 1105p, 1110p, -, -],  
[ 1110p, 1125p, 1140p, 1149p, 1155p, 1205x, 1210x, -, -],  
[ 1210x, 1225x, 1240x, 1249x, 1255x, 105x, 110x, -, -]  
]  
stop_times_saturday: [  
[ -, -, 640a, 649a, 655a, 705a, 710a, -, 721a],  
[ 710a, 725a, 740a, 749a, 755a, 805a, 810a, -, 821a],  
[ 810a, 825a, 840a, 849a, 855a, 905a, 910a, -, 921a],  
[ 840a, 855a, 910a, 919a, 925a, 935a, 940a, -, 951a],  
[ 910a, 925a, 940a, 949a, 955a, 1005a, 1010a, -, 1021a],  
[ 940a, 955a, 1010a, 1019a, 1025a, 1035a, 1040a, -, 1051a],  
[ 1010a, 1025a, 1040a, 1049a, 1055a, 1105a, 1110a, -, 1121a],  
[ 1040a, 1055a, 1110a, 1119a, 1125a, 1135a, 1140a, -, 1151a],  
[ 1110a, 1125a, 1140a, 1149a, 1155a, 1205p, 1210p, -, 1221p],  
[ 1140a, 1155a, 1210p, 1219p, 1225p, 1235p, 1240p, -, 1251p],  
[ 1210p, 1225p, 1240p, 1249p, 1255p, 105p, 110p, -, 121p],  
[ 1240p, 1255p, 110p, 119p, 125p, 135p, 140p, -, 151p],  
[ 110p, 125p, 140p, 149p, 155p, 205p, 210p, -, 221p],  
[ 140p, 155p, 210p, 219p, 225p, 235p, 240p, -, 251p],  
[ 210p, 225p, 240p, 249p, 255p, 305p, 310p, -, 321p],  
[ 240p, 255p, 310p, 319p, 325p, 335p, 340p, -, 351p],  
[ 310p, 325p, 340p, 349p, 355p, 405p, 410p, -, 421p],  
[ 340p, 355p, 410p, 419p, 425p, 435p, 440p, -, 451p],  
[ 410p, 425p, 440p, 449p, 455p, 505p, 510p, -, 521p],  
[ 440p, 455p, 510p, 519p, 525p, 535p, 540p, -, 551p],  
[ 510p, 525p, 540p, 549p, 555p, 605p, 610p, -, 621p],  
[ 540p, 555p, 610p, 619p, 625p, 635p, 640p, -, 651p],  
[ 610p, 625p, 640p, 649p, 655p, 705p, 710p, -, 721p],  
[ 640p, 655p, 710p, 719p, 725p, 735p, 740p, -, 751p],  
[ 710p, 725p, 740p, 749p, 755p, 805p, 810p, -, 821p],  
[ 740p, 755p, 810p, 819p, 825p, 835p, 840p, -, -],  
[ 810p, 825p, 840p, 849p, 855p, 905p, 910p, -, 921p],  
[ 910p, 925p, 940p, 949p, 955p, 1005p, 1010p, -, 1021p],  
[ 1010p, 1025p, 1040p, 1049p, 1055p, 1105p, 1110p, -, 1121p],  
[ 1110p, 1125p, 1140p, 1149p, 1155p, 1205x, 1210x, -, -],  
[ 1210x, 1225x, 1240x, 1249x, 1255x, 105x, 110x, -, -]  
]  
stop_times_sunday: [  
[ -, 745a, 800a, 809a, 815a, 823a, 828a, -, -],  
[ 800a, 815a, 830a, 839a, 845a, 853a, 858a, -, -],  
[ 830a, 845a, 900a, 909a, 915a, 923a, 928a, -, -],  
[ 900a, 915a, 930a, 939a, 945a, 953a, 958a, -, -],  
[ 930a, 945a, 1000a, 1009a, 1015a, 1023a, 1028a, -, -],  
[ 1000a, 1015a, 1030a, 1039a, 1045a, 1053a, 1058a, -, -],  
[ 1030a, 1045a, 1100a, 1109a, 1115a, 1123a, 1128a, -, -],  
[ 1100a, 1115a, 1130a, 1139a, 1145a, 1153a, 1158a, -, -],  
[ 1130a, 1145a, 1200p, 1209p, 1215p, 1223p, 1228p, -, -],  
[ 1200p, 1215p, 1230p, 1239p, 1245p, 1253p, 1258p, -, -],  
[ 1230p, 1245p, 100p, 109p, 115p, 123p, 128p, -, -],  
[ 100p, 115p, 130p, 139p, 145p, 153p, 158p, -, -],  
[ 130p, 145p, 200p, 209p, 215p, 223p, 228p, -, -],  
[ 200p, 215p, 230p, 239p, 245p, 253p, 258p, -, -],  
[ 230p, 245p, 300p, 309p, 315p, 323p, 328p, -, -],  
[ 300p, 315p, 330p, 339p, 345p, 353p, 358p, -, -],  
[ 330p, 345p, 400p, 409p, 415p, 423p, 428p, -, -],  
[ 400p, 415p, 430p, 439p, 445p, 453p, 458p, -, -],  
[ 430p, 445p, 500p, 509p, 515p, 523p, 528p, -, -],  
[ 500p, 515p, 530p, 539p, 545p, 553p, 558p, -, -],  
[ 530p, 545p, 600p, 609p, 615p, 623p, 628p, -, -],  
[ 600p, 615p, 630p, 639p, 645p, 653p, 658p, -, -],  
[ 630p, 645p, 700p, 709p, 715p, 723p, 728p, -, -],  
[ 700p, 715p, 730p, 739p, 745p, 753p, 758p, -, -],  
[ 730p, 745p, 800p, 809p, 815p, 823p, 828p, -, -],  
[ 800p, 815p, 830p, 839p, 845p, 853p, 858p, -, -],  
[ 830p, 845p, 900p, 909p, 915p, 923p, 928p, -, -],  
[ 900p, 915p, 930p, 939p, 945p, 953p, 958p, -, -],  
[ 930p, 945p, 1000p, 1009p, 1015p, 1023p, 1028p, -, -],  
[ 1000p, 1015p, 1030p, 1039p, 1045p, 1053p, 1058p, -, -],  
[ 1030p, 1045p, 1100p, 1109p, 1115p, 1123p, 1128p, -, -],  
[ 1100p, 1115p, 1130p, 1139p, 1145p, 1153p, 1158p, -, -],  
[ 1130p, 1145p, 1200x, 1209x, 1215x, 1223x, 1228x, -, -],  
[ 1200x, 1215x, 1230x, 1239x, 1245x, 1253x, 1258x, -, -],  
[ 1230x, 1245x, 100x, 109x, 115x, 123x, 128x, -, -]  
]  
 
short_name: 52  
long_name: To Lacewood - Chain Lake Drive  
time_points: [ 6767, 7153, 7205, 6918, 7151, 7285, 6032, 7086, 6390 ]  
between_stops:  
7151-7285: [ 7346, 7341, 7353, 7358, 7344, 7356, 6405, 6404, 6413, 6414, 7275 ]  
7285-6032: [ 6984 ]  
stop_times: [  
[ -, -, -, -, -, -, -, 558a, 608a],  
[ -, -, -, -, -, -, -, 628a, 638a],  
[ -, -, 550a, 601a, 612a, 632a, 639a, 649a, 659a],  
[ -, -, 620a, 631a, 642a, 702a, 709a, 719a, 729a],  
[ -, -, 635a, 646a, 657a, 717a, 724a, 734a, 744a],  
[ -, 646a, 653a, 704a, 715a, 735a, 742a, 752a, 802a],  
[ -, -, 706a, 717a, 728a, 748a, 755a, 805a, 815a],  
[ -, 716a, 723a, 734a, 745a, 805a, 812a, 822a, 832a],  
[ -, 731a, 738a, 749a, 800a, 820a, 827a, 837a, 847a],  
[ -, 746a, 753a, 804a, 815a, 835a, 842a, 852a, 902a],  
[ -, 801a, 808a, 819a, 830a, 850a, 857a, 907a, 917a],  
[ -, 816a, 823a, 834a, 845a, 905a, 912a, 922a, 932a],  
[ -, 829a, 836a, 847a, 858a, 918a, 925a, 932a, 942a],  
[ -, 843a, 850a, 901a, 912a, 930a, 938a, 945a, 955a],  
[ -, 857a, 904a, 915a, 926a, 941a, 949a, 956a, 1006a],  
[ 921a, 929a, 940a, 945a, 955a, 1010a, 1018a, 1025a, 1035a],  
[ 951a, 959a, 1010a, 1015a, 1025a, 1040a, 1048a, 1055a, 1105a],  
[ 1021a, 1029a, 1040a, 1045a, 1055a, 1110a, 1118a, 1125a, 1135a],  
[ 1051a, 1059a, 1110a, 1115a, 1125a, 1140a, 1148a, 1155a, 1205p],  
[ 1121a, 1129a, 1140a, 1145a, 1155a, 1210p, 1218p, 1225p, 1235p],  
[ 1151a, 1159p, 1210p, 1215p, 1225p, 1240p, 1248p, 1255p, 105p],  
[ 1221p, 1229p, 1240p, 1245p, 1255p, 110p, 118p, 125p, 135p],  
[ 1251p, 1259p, 110p, 115p, 125p, 140p, 148p, 155p, 205p],  
[ 121p, 129p, 140p, 145p, 155p, 210p, 218p, 225p, 235p],  
[ 151p, 159p, 210p, 215p, 225p, 240p, 248p, 255p, 305p],  
[ 221p, 229p, 240p, 245p, 255p, 310p, 318p, 325p, 335p],  
[ 251p, 259p, 310p, 315p, 325p, 340p, 348p, 358p, 405p],  
[ 321p, 329p, 340p, 345p, 355p, 416p, 419p, 433p, 435p],  
[ -, 346p, 353p, 404p, 415p, 435p, 442p, 452p, 502p],  
[ -, 401p, 408p, 419p, 430p, 450p, 457p, 507p, 517p],  
[ -, 416p, 423p, 434p, 445p, 505p, 512p, 522p, 532p],  
[ -, 431p, 438p, 449p, 500p, 520p, 527p, 537p, 547p],  
[ -, 446p, 453p, 504p, 515p, 535p, 542p, 552p, 602p],  
[ -, 501p, 508p, 519p, 530p, 550p, 557p, 607p, 617p],  
[ -, 516p, 523p, 534p, 545p, 605p, 612p, 622p, 632p],  
[ -, 531p, 538p, 549p, 600p, 620p, 627p, 634p, 644p],  
[ -, 543p, 550p, 601p, 612p, 630p, 638p, 645p, 655p],  
[ -, 601p, 608p, 619p, 630p, 645p, 653p, 700p, 710p],  
[ 621p, 629p, 640p, 645p, 655p, 710p, 718p, 725p, 735p],  
[ 651p, 659p, 710p, 715p, 725p, 740p, 748p, 755p, 805p],  
[ 721p, 729p, 740p, 745p, 755p, 810p, 818p, 825p, 835p],  
[ 751p, 759p, 810p, 815p, 825p, 840p, 848p, 855p, 905p],  
[ 821p, 829p, 840p, 845p, 855p, 910p, 918p, 925p, 935p],  
[ 851p, 859p, 910p, 915p, 925p, 940p, 948p, 955p, 1005p],  
[ 951p, 959p, 1010p, 1015p, 1025p, 1040p, 1048p, 1055p, 1105p],  
[ -, -, 1110p, 1115p, 1125p, 1140p, 1148p, 1155p, 1205x]  
]  
stop_times_saturday: [  
[ -, -, 610a, 615a, 625a, 640a, 648a, 655a, 705a],  
[ -, -, 710a, 715a, 725a, 740a, 748a, 755a, 805a],  
[ 721a, 731a, 740a, 745a, 755a, 810a, 818a, 825a, 835a],  
[ 751a, 801a, 810a, 815a, 825a, 840a, 848a, 855a, 905a],  
[ 821a, 831a, 840a, 845a, 855a, 910a, 918a, 925a, 935a],  
[ 851a, 901a, 910a, 915a, 925a, 940a, 948a, 955a, 1005a],  
[ 921a, 931a, 940a, 945a, 955a, 1010a, 1018a, 1025a, 1035a],  
[ 951a, 1001a, 1010a, 1015a, 1025a, 1040a, 1048a, 1055a, 1105a],  
[ 1021a, 1031a, 1040a, 1045a, 1055a, 1110a, 1118a, 1125a, 1135a],  
[ 1051a, 1101a, 1110a, 1115a, 1125a, 1140a, 1148a, 1155a, 1205p],  
[ 1121a, 1131a, 1140a, 1145a, 1155a, 1210p, 1218p, 1225p, 1235p],  
[ 1151a, 1201p, 1210p, 1215p, 1225p, 1240p, 1248p, 1255p, 105p],  
[ 1221p, 1231p, 1240p, 1245p, 1255p, 110p, 118p, 125p, 135p],  
[ 1251p, 101p, 110p, 115p, 125p, 140p, 148p, 155p, 205p],  
[ 121p, 131p, 140p, 145p, 155p, 210p, 218p, 225p, 235p],  
[ 151p, 201p, 210p, 215p, 225p, 240p, 248p, 255p, 305p],  
[ 221p, 231p, 240p, 245p, 255p, 310p, 318p, 325p, 335p],  
[ 251p, 301p, 310p, 315p, 325p, 340p, 348p, 355p, 405p],  
[ 321p, 331p, 340p, 345p, 355p, 410p, 418p, 425p, 435p],  
[ 351p, 401p, 410p, 415p, 425p, 440p, 448p, 455p, 505p],  
[ 421p, 431p, 440p, 445p, 455p, 510p, 518p, 525p, 535p],  
[ 451p, 501p, 510p, 515p, 525p, 540p, 548p, 555p, 605p],  
[ 521p, 531p, 540p, 545p, 555p, 610p, 618p, 625p, 635p],  
[ 551p, 601p, 610p, 615p, 625p, 640p, 648p, 655p, 705p],  
[ 621p, 631p, 640p, 645p, 655p, 710p, 718p, 725p, 735p],  
[ 651p, 701p, 710p, 715p, 725p, 740p, 748p, 755p, 805p],  
[ 721p, 731p, 740p, 745p, 752p, -, -, -, -],  
[ 751p, 801p, 810p, 815p, 825p, 840p, 848p, 855p, 905p],  
[ 821p, 831p, 840p, 845p, 852p, -, -, -, -],  
[ 851p, 901p, 910p, 915p, 925p, 940p, 948p, 955p, 1005p],  
[ 951p, 1001p, 1010p, 1015p, 1025p, 1040p, 1048p, 1055p, 1105p],  
[ 1051p, 1101p, 1110p, 1115p, 1125p, 1140p, 1148p, 1155p, 1205x]  
]  
stop_times_sunday: [  
[ -, -, 700a, 705a, 715a, 730a, 738a, 745a, 755a],  
[ -, -, 730a, 735a, 745a, 800a, 808a, 815a, 825a],  
[ -, -, 800a, 805a, 815a, 830a, 838a, 845a, 855a],  
[ -, -, 830a, 835a, 845a, 900a, 908a, 915a, 925a],  
[ -, -, 900a, 905a, 915a, 930a, 938a, 945a, 955a],  
[ -, -, 930a, 935a, 945a, 1000a, 1008a, 1015a, 1025a],  
[ -, -, 1000a, 1005a, 1015a, 1030a, 1038a, 1045a, 1055a],  
[ -, -, 1030a, 1035a, 1045a, 1100a, 1108a, 1115a, 1125a],  
[ -, -, 1100a, 1105a, 1115a, 1130a, 1138a, 1145a, 1155a],  
[ -, -, 1130a, 1135a, 1145a, 1200p, 1208p, 1215p, 1225p],  
[ -, -, 1200p, 1205p, 1215p, 1230p, 1238p, 1245p, 1255p],  
[ -, -, 1230p, 1235p, 1245p, 100p, 108p, 115p, 125p],  
[ -, -, 100p, 105p, 115p, 130p, 138p, 145p, 155p],  
[ -, -, 130p, 135p, 145p, 200p, 208p, 215p, 225p],  
[ -, -, 200p, 205p, 215p, 230p, 238p, 245p, 255p],  
[ -, -, 230p, 235p, 245p, 300p, 308p, 315p, 325p],  
[ -, -, 300p, 305p, 315p, 330p, 338p, 345p, 355p],  
[ -, -, 330p, 335p, 345p, 400p, 408p, 415p, 425p],  
[ -, -, 400p, 405p, 415p, 430p, 438p, 445p, 455p],  
[ -, -, 430p, 435p, 445p, 500p, 508p, 515p, 525p],  
[ -, -, 500p, 505p, 515p, 530p, 538p, 545p, 555p],  
[ -, -, 530p, 535p, 545p, 600p, 608p, 615p, 625p],  
[ -, -, 600p, 605p, 615p, 630p, 638p, 645p, 655p],  
[ -, -, 630p, 635p, 645p, 700p, 708p, 715p, 725p],  
[ -, -, 700p, 705p, 715p, 730p, 738p, 745p, 755p],  
[ -, -, 730p, 735p, 745p, 800p, 808p, 815p, 825p],  
[ -, -, 800p, 805p, 815p, 830p, 838p, 845p, 855p],  
[ -, -, 830p, 835p, 845p, 900p, 908p, 915p, 925p],  
[ -, -, 900p, 905p, 915p, 930p, 938p, 945p, 955p],  
[ -, -, 930p, 935p, 945p, 1000p, 1008p, 1015p, 1025p],  
[ -, -, 1000p, 1005p, 1015p, 1030p, 1038p, 1045p, 1055p],  
[ -, -, 1030p, 1035p, 1045p, 1100p, 1108p, 1115p, 1125p],  
[ -, -, 1100p, 1105p, 1115p, 1130p, 1138p, 1145p, 1155p],  
[ -, -, 1130p, 1135p, 1145p, 1200x, 1208x, 1215x, 1225x]  
]  
 
short_name: 58  
long_name: To Lucien Drive  
time_points: [ 7284, 7412, 6087, 8640, 6031, 7445, 6575 ]  
between_stops:  
7284-7412: [ 6203, 7423 ]  
# nb: I haven't checked that 8328-6106 actually are served by the #58, but I'd  
# be shocked if they weren't  
7412-6087: [ 7419, 7409, 7402, 6453, 6447, 6449, 6454, 6452, 8328, 8337, 8333, 8336, 8327, 8338, 6121, 6106 ]  
stop_times: [  
[ -, -, -, -, -, 540a, 552a],  
[ -, -, -, 555a, 600a, 610a, 622a],  
[ -, -, -, 625a, 630a, 640a, 652a],  
[ -, -, -, 645a, 650a, 700a, 712a],  
[ -, -, -, 705a, 710a, 720a, 732a],  
[ -, -, -, 725a, 730a, 740a, 752a],  
[ -, -, -, 755a, 800a, 810a, 822a],  
[ -, -, -, 825a, 830a, 840a, 852a],  
[ -, -, -, 855a, 900a, 910a, 922a],  
[ -, -, -, 955a, 1000a, 1010a, 1022a],  
[ -, -, -, 1055a, 1100a, 1110a, 1122a],  
[ -, -, -, 1155a, 1200p, 1210p, 1222p],  
[ -, -, -, 1255p, 100p, 110p, 122p],  
[ -, -, -, 155p, 200p, 210p, 222p],  
[ -, -, -, 255p, 300p, 310p, 322p],  
[ -, -, -, 325p, 330p, 340p, 352p],  
[ 310p, 323p, 340p, 352p, 357p, 407p, 419p],  
[ 330p, 343p, 400p, 412p, 417p, 427p, 439p],  
[ 350p, 403p, 420p, 432p, 437p, 447p, 459p],  
[ 410p, 423p, 440p, 452p, 457p, 507p, 519p],  
[ 440p, 453p, 510p, 522p, 527p, 537p, 549p],  
[ -, -, -, 555p, 600p, 610p, 622p],  
[ -, -, -, 655p, 700p, 710p, 722p],  
[ -, -, -, 755p, 800p, 810p, 822p],  
[ -, -, -, 855p, 900p, 910p, 922p],  
[ -, -, -, 955p, 1000p, 1010p, 1022p],  
[ -, -, -, 1055p, 1100p, 1110p, 1122p],  
[ -, -, -, 1155p, 1200x, 1210x, 1222x]  
]  
 
short_name: 6  
long_name: To Downtown  
time_points: [ 8361, 7285, 8136, 6105, 8435 ]  
between_stops:  
7285-8136: [ 7274, 8135, 8133 ]  
8136-6105: [ 8147, 8149, 8150 ]  
6105-8435: [ 6108 ]  
stop_times: [  
[ 615a, 627a, 634a, 645a, 648a],  
[ 645a, 657a, 704a, 715a, 718a],  
[ 716a, 728a, 735a, 746a, 749a],  
[ 748a, 800a, 807a, 818a, 821a],  
[ 818a, 830a, 837a, 848a, 851a],  
[ 903a, 913a, 920a, 931a, 934a],  
[ 932a, 942a, 949a, 1000a, 1003a],  
[ 1032a, 1042a, 1049a, 1100a, 1103a],  
[ 1132a, 1142a, 1149a, 1200p, 1203p],  
[ 1232p, 1242p, 1249p, 100p, 103p],  
[ 132p, 142p, 149p, 200p, 203p],  
[ 232p, 242p, 249p, 300p, 303p],  
[ 336p, 348p, 355p, 406p, 409p],  
[ 406p, 418p, 425p, 436p, 439p],  
[ 436p, 448p, 455p, 506p, 509p],  
[ 506p, 518p, 525p, 536p, 539p],  
[ 536p, 548p, 555p, 604p, 607p],  
[ 606p, 616p, 623p, 630p, 633p],  
[ 632p, 642p, 649p, 656p, 659p],  
[ 732p, 742p, 749p, 756p, 759p],  
[ 832p, 842p, 849p, 856p, 859p],  
[ 932p, 942p, 949p, 956p, 959p],  
[ 1032p, 1042p, 1049p, 1056p, 1059p],  
[ 1132p, 1142p, 1149p, 1156p, 1159p],  
[ 1232x, 1242x, -, -, -]  
]  
 
short_name: 6  
long_name: To Stonehaven  
time_points: [ 8435, 8137, 8643, 8361 ]  
between_stops:  
8435-8137: [ 8138, 8148 ]  
8137-8643: [ 8134, 8146, 7275 ]  
stop_times: [  
[ -, -, 604a, 614a],  
[ -, -, 634a, 644a],  
[ 648a, 658a, 705a, 715a],  
[ 722a, 730a, 737a, 747a],  
[ 752a, 800a, 807a, 817a],  
[ 835a, 845a, 852a, 901a],  
[ 905a, 915a, 922a, 931a],  
[ 1005a, 1015a, 1022a, 1031a],  
[ 1105a, 1115a, 1122a, 1131a],  
[ 1205p, 1215p, 1222p, 1231p],  
[ 105p, 115p, 122p, 131p],  
[ 205p, 215p, 222p, 231p],  
[ 308p, 318p, 325p, 335p],  
[ 338p, 348p, 355p, 405p],  
[ 408p, 418p, 425p, 435p],  
[ 438p, 448p, 455p, 505p],  
[ 508p, 518p, 525p, 535p],  
[ 538p, 548p, 555p, 605p],  
[ 605p, 615p, 622p, 631p],  
[ 705p, 715p, 722p, 731p],  
[ 805p, 815p, 822p, 831p],  
[ 905p, 915p, 922p, 931p],  
[ 1005p, 1015p, 1022p, 1031p],  
[ 1105p, 1115p, 1122p, 1131p],  
[ 1205x, 1215x, 1222x, 1231x]  
]  
 
short_name: 7  
long_name: Gottingen to Robie via Downtown and South Street  
time_points: [ 7378, 6770, 6105, 6114, 8184, 8180, 8165 ]  
between_stops:  
7378-6770: [ 7368, 7361, 7382, 7370, 7362, 7365, 7364 ]  
6770-6105: [ 6783, 6776, 6777, 6781, 6774, 6780, 6786, 6790, 6771 ]  
6105-6114: [ 6108, 6103, 6102 ]  
6114-8184: [ 6097, 8294, 8292, 8300, 8301, 8298, 8297, 8220, 8187, 8185, 8219, 8179 ]  
8184-8180: [ 8206, 8221, 8222, 8181, 8210, 8201, 8251, 8192, 8209, 8217, 8204, 8207 ]  
8180-8165: [ 8211, 7131 ]  
stop_times: [  
[ 605a, 612a, 620a, 627a, 636a, 643a, 647a],  
[ 625a, 632a, 640a, 647a, 656a, 703a, 707a],  
[ 650a, 657a, 705a, 712a, 721a, 728a, 732a],  
[ 710a, 717a, 725a, 732a, 741a, 748a, 752a],  
[ 730a, 737a, 745a, 752a, 801a, 808a, 812a],  
[ 750a, 757a, 805a, 812a, 821a, 828a, 832a],  
[ 810a, 817a, 825a, 832a, 841a, 848a, 852a],  
[ 830a, 837a, 845a, 852a, 901a, 908a, 912a],  
[ 850a, 857a, 905a, 912a, 921a, 928a, 932a],  
[ 920a, 927a, 937a, 944a, 952a, 1001a, 1005a],  
[ 950a, 957a, 1007a, 1014a, 1023a, 1031a, 1035a],  
[ 1020a, 1027a, 1037a, 1044a, 1053a, 1101a, 1105a],  
[ 1050a, 1057a, 1107a, 1114a, 1123a, 1131a, 1135a],  
[ 1120a, 1127a, 1137a, 1144a, 1153a, 1201p, 1205p],  
[ 1150a, 1157a, 1207p, 1214p, 1223p, 1231p, 1235p],  
[ 1220p, 1227p, 1237p, 1244p, 1253p, 102p, 106p],  
[ 1250p, 1257p, 107p, 114p, 124p, 136p, 140p],  
[ 120p, 127p, 137p, 144p, 154p, 206p, 210p],  
[ 150p, 157p, 207p, 214p, 224p, 236p, 240p],  
[ 220p, 227p, 237p, 244p, 254p, 306p, 310p],  
[ 240p, 247p, 257p, 304p, 314p, 326p, 330p],  
[ 300p, 307p, 317p, 324p, 334p, 346p, 350p],  
[ 320p, 327p, 337p, 344p, 354p, 406p, 410p],  
[ 340p, 347p, 357p, 404p, 414p, 426p, 430p],  
[ 400p, 407p, 417p, 424p, 434p, 446p, 450p],  
[ 420p, 427p, 437p, 444p, 454p, 506p, 510p],  
[ 440p, 447p, 457p, 504p, 514p, 526p, 530p],  
[ 500p, 507p, 517p, 524p, 534p, 540p, 544p],  
[ 520p, 527p, 535p, 541p, 551p, 556p, 600p],  
[ 550p, 557p, 605p, 611p, 620p, 626p, 630p],  
[ 620p, 627p, 635p, 641p, 650p, 656p, 700p],  
[ 650p, 657p, 705p, 711p, 720p, 726p, 730p],  
[ 720p, 727p, 735p, 741p, 750p, 756p, 800p],  
[ 750p, 757p, 805p, 811p, 820p, 826p, 830p],  
[ 820p, 827p, 835p, 841p, 850p, 856p, 900p],  
[ 850p, 857p, 905p, 911p, 920p, 926p, 930p],  
[ 920p, 927p, 935p, 941p, 950p, 956p, 1000p],  
[ 950p, 957p, 1005p, 1011p, 1020p, 1026p, 1030p],  
[ 1020p, 1027p, 1035p, 1041p, 1050p, 1056p, 1100p],  
[ 1050p, 1057p, 1105p, 1111p, 1120p, 1126p, 1130p],  
[ 1120p, 1127p, 1135p, 1141p, 1150p, 1156p, 1200x],  
[ 1150p, 1157p, 1205x, 1211x, 1220x, 1226x, 1230x]  
]  
stop_times_saturday: [  
[ 655a, 702a, 710a, 716a, 725a, 731a, 735a],  
[ 755a, 802a, 810a, 816a, 825a, 831a, 835a],  
[ 825a, 832a, 840a, 846a, 855a, 901a, 905a],  
[ 855a, 902a, 910a, 916a, 925a, 931a, 935a],  
[ 925a, 932a, 940a, 946a, 955a, 1001a, 1005a],  
[ 955a, 1002a, 1010a, 1016a, 1025a, 1031a, 1035a],  
[ 1025a, 1032a, 1040a, 1046a, 1055a, 1101a, 1105a],  
[ 1055a, 1102a, 1110a, 1116a, 1125a, 1131a, 1135a],  
[ 1125a, 1132a, 1140a, 1146a, 1155a, 1201p, 1205p],  
[ 1155a, 1202p, 1210p, 1216p, 1225p, 1231p, 1235p],  
[ 1225p, 1232p, 1240p, 1246p, 1255p, 101p, 105p],  
[ 1255p, 102p, 110p, 116p, 125p, 131p, 135p],  
[ 125p, 132p, 140p, 146p, 155p, 201p, 205p],  
[ 155p, 202p, 210p, 216p, 225p, 231p, 235p],  
[ 225p, 232p, 240p, 246p, 255p, 301p, 305p],  
[ 255p, 302p, 310p, 316p, 325p, 331p, 335p],  
[ 325p, 332p, 340p, 346p, 355p, 401p, 405p],  
[ 355p, 402p, 410p, 416p, 425p, 431p, 435p],  
[ 425p, 432p, 440p, 446p, 455p, 501p, 505p],  
[ 455p, 502p, 510p, 516p, 525p, 531p, 535p],  
[ 525p, 532p, 540p, 546p, 555p, 601p, 605p],  
[ 555p, 602p, 610p, 616p, 625p, 631p, 635p],  
[ 625p, 632p, 640p, 646p, 655p, 701p, 705p],  
[ 655p, 702p, 710p, 716p, 725p, 731p, 735p],  
[ 725p, 732p, 740p, 746p, 755p, 801p, 805p],  
[ 755p, 802p, 810p, 816p, 825p, 831p, 835p],  
[ 825p, 832p, 840p, 846p, 855p, 901p, 905p],  
[ 855p, 902p, 910p, 916p, 925p, 931p, 935p],  
[ 925p, 932p, 940p, 946p, 955p, 1001p, 1005p],  
[ 955p, 1002p, 1010p, 1016p, 1025p, 1031p, 1035p],  
[ 1025p, 1032p, 1040p, 1046p, 1055p, 1101p, 1105p],  
[ 1055p, 1102p, 1110p, 1116p, 1125p, 1131p, 1135p],  
[ 1155p, 1202x, 1210x, 1216x, 1225x, 1231x, 1235x]  
]  
stop_times_sunday: [  
[ 745a, 752a, 800a, 805a, 814a, 820a, 824a],  
[ 830a, 837a, 845a, 850a, 859a, 905a, 909a],  
[ 915a, 922a, 930a, 935a, 944a, 950a, 954a],  
[ 1000a, 1007a, 1015a, 1020a, 1029a, 1035a, 1039a],  
[ 1045a, 1052a, 1100a, 1105a, 1114a, 1120a, 1124a],  
[ 1130a, 1137a, 1145a, 1150a, 1159a, 1205p, 1209p],  
[ 1215p, 1222p, 1230p, 1235p, 1244p, 1250p, 1254p],  
[ 100p, 107p, 115p, 120p, 129p, 135p, 139p],  
[ 145p, 152p, 200p, 205p, 214p, 220p, 224p],  
[ 230p, 237p, 245p, 250p, 259p, 305p, 309p],  
[ 315p, 322p, 330p, 335p, 344p, 350p, 354p],  
[ 400p, 407p, 415p, 420p, 429p, 435p, 439p],  
[ 445p, 452p, 500p, 505p, 514p, 520p, 524p],  
[ 530p, 537p, 545p, 550p, 559p, 605p, 609p],  
[ 615p, 622p, 630p, 635p, 644p, 650p, 654p],  
[ 700p, 707p, 715p, 720p, 729p, 735p, 739p],  
[ 745p, 752p, 800p, 805p, 814p, 820p, 824p],  
[ 830p, 837p, 845p, 850p, 859p, 905p, 909p],  
[ 915p, 922p, 930p, 935p, 944p, 950p, 954p],  
[ 1000p, 1007p, 1015p, 1020p, 1029p, 1035p, 1039p],  
[ 1045p, 1052p, 1100p, 1105p, 1114p, 1120p, 1124p],  
[ 1130p, 1137p, 1145p, 1150p, 1159p, 1205x, 1209x]  
]  
 
short_name: 7  
long_name: Robie to Gottingen via South Street and Downtown  
time_points: [ 8165, 8208, 8214, 6096, 6087, 7366, 7378 ]  
between_stops:  
8165-8208: [ 7133, 8212 ]  
8208-8214: [ 8203, 8197, 8218, 8193, 8202, 8182, 8213, 8178, 8205, 8190 ]  
8214-6096: [ 8183, 8196, 8195, 8194, 8186, 8188, 8296, 8303, 8305, 8295, 8299, 8293 ]  
6096-6087: [ 6113, 6124 ]  
6087-7366: [ 6455, 6773, 6778, 6779, 6775, 6787, 6769, 6785, 6768, 6782 ]  
7366-7378: [ 7377, 7381, 7374, 7369, 7373, 7376, 7360 ]  
 
stop_times: [  
[ 600a, 604a, 614a, 621a, 628a, 637a, 645a],  
[ 620a, 624a, 634a, 641a, 648a, 657a, 705a],  
[ 640a, 644a, 654a, 701a, 708a, 717a, 725a],  
[ 700a, 704a, 714a, 721a, 728a, 737a, 745a],  
[ 720a, 724a, 734a, 741a, 748a, 757a, 805a],  
[ 740a, 744a, 754a, 801a, 808a, 817a, 825a],  
[ 800a, 804a, 814a, 821a, 828a, 837a, 845a],  
[ 820a, 824a, 834a, 841a, 848a, 857a, 905a],  
[ 840a, 844a, 854a, 901a, 908a, 917a, 925a],  
[ 900a, 904a, 914a, 921a, 928a, 937a, 945a],  
[ 930a, 934a, 944a, 951a, 958a, 1007a, 1015a],  
[ 1000a, 1004a, 1014a, 1021a, 1028a, 1037a, 1045a],  
[ 1030a, 1034a, 1044a, 1051a, 1058a, 1107a, 1115a],  
[ 1100a, 1104a, 1114a, 1121a, 1128a, 1137a, 1145a],  
[ 1130a, 1134a, 1144a, 1151a, 1158a, 1207p, 1215p],  
[ 1200p, 1204p, 1214p, 1221p, 1228p, 1237p, 1245p],  
[ 1230p, 1234p, 1244p, 1251p, 1258p, 108p, 116p],  
[ 100p, 104p, 116p, 124p, 132p, 142p, 150p],  
[ 130p, 134p, 146p, 154p, 202p, 212p, 220p],  
[ 200p, 204p, 216p, 224p, 232p, 242p, 250p],  
[ 230p, 234p, 246p, 254p, 302p, 312p, 320p],  
[ 250p, 254p, 306p, 314p, 322p, 332p, 340p],  
[ 310p, 314p, 326p, 334p, 342p, 352p, 400p],  
[ 330p, 334p, 346p, 354p, 402p, 412p, 420p],  
[ 350p, 354p, 406p, 414p, 422p, 432p, 440p],  
[ 410p, 414p, 426p, 434p, 442p, 452p, 500p],  
[ 430p, 434p, 446p, 454p, 502p, 512p, 520p],  
[ 450p, 454p, 506p, 514p, 522p, 531p, 539p],  
[ 510p, 514p, 526p, 534p, 540p, 547p, 555p],  
[ 530p, 534p, 541p, 548p, 555p, 602p, 610p],  
[ 550p, 554p, 601p, 608p, 615p, 622p, 630p],  
[ 610p, 614p, 621p, 628p, 635p, 642p, 650p],  
[ 640p, 644p, 651p, 658p, 705p, 712p, 720p],  
[ 710p, 714p, 721p, 728p, 735p, 742p, 750p],  
[ 740p, 744p, 751p, 758p, 805p, 812p, 820p],  
[ 810p, 814p, 821p, 828p, 835p, 842p, 850p],  
[ 840p, 844p, 851p, 858p, 905p, 912p, 920p],  
[ 910p, 914p, 921p, 928p, 935p, 942p, 950p],  
[ 940p, 944p, 951p, 958p, 1005p, 1012p, 1020p],  
[ 1010p, 1014p, 1021p, 1028p, 1035p, 1042p, 1050p],  
[ 1040p, 1044p, 1051p, 1058p, 1105p, 1112p, 1120p],  
[ 1110p, 1114p, 1121p, 1128p, 1135p, 1142p, 1150p],  
[ 1140p, 1144p, 1151p, 1158p, 1205x, 1212x, 1220x],  
[ 1210x, 1214x, 1221x, 1228x, 1235x, 1242x, 1250x]  
]  
 
short_name: 80  
long_name: To Bedford - Halifax  
time_points: [ 8260, 8646, 6236, 6216, 6564, 8214, 6087, 8414 ]  
between_stops:  
6216-6564: [ 6982, 6985, 8262 ]  
6564-8214: [ 6197, 6193, 6203, 8633, 8193, 8202, 8182, 8213, 8178, 8205, 8190 ]  
8214-6087: [ 8183, 8196, 8195, 8194, 8328, 8337, 8333, 8336, 8327, 8338, 6121, 6106 ]  
stop_times: [  
[ 542a, 554a, 602a, 618a, 625a, 635a, 645a, 647a],  
[ 633a, 645a, 653a, 708a, 718a, 729a, 746a, 748a],  
[ 706a, 721a, 728a, 743a, 753a, 804a, 821a, 823a],  
[ 733a, 748a, 755a, 810a, 820a, 831a, 848a, 850a],  
[ 800a, 815a, 822a, 837a, 845a, 856a, 913a, 915a],  
[ 829a, 844a, 851a, 906a, 914a, 925a, 942a, 944a],  
[ 859a, 914a, 921a, 936a, 944a, 955a, 1012a, 1014a],  
[ 929a, 944a, 951a, 1006a, 1014a, 1025a, 1042a, 1044a],  
[ 959a, 1014a, 1021a, 1036a, 1044a, 1055a, 1112a, 1114a],  
[ 1029a, 1044a, 1051a, 1106a, 1114a, 1125a, 1142a, 1144a],  
[ 1059a, 1114a, 1121a, 1136a, 1144a, 1155a, 1212p, 1214p],  
[ 1129a, 1144a, 1151a, 1206p, 1214p, 1225p, 1242p, 1244p],  
[ 1159a, 1214p, 1221p, 1236p, 1244p, 1255p, 112p, 114p],  
[ 1229p, 1244p, 1251p, 106p, 114p, 125p, 142p, 144p],  
[ 1259p, 114p, 121p, 136p, 144p, 155p, 212p, 214p],  
[ 129p, 144p, 151p, 206p, 214p, 225p, 242p, 244p],  
[ 159p, 214p, 221p, 236p, 244p, 255p, 312p, 314p],  
[ 229p, 244p, 251p, 306p, 314p, 325p, 342p, 344p],  
[ 259p, 314p, 321p, 336p, 344p, 355p, 412p, 414p],  
[ 329p, 344p, 351p, 406p, 414p, 425p, 442p, 444p],  
[ 359p, 414p, 421p, 436p, 444p, 455p, 512p, 514p],  
[ 429p, 444p, 451p, 506p, 514p, 525p, 542p, 544p],  
[ 459p, 514p, 521p, 536p, 544p, 555p, 607p, 609p],  
[ 526p, 541p, 548p, 603p, 607p, 618p, 628p, 630p],  
[ 551p, 605p, 610p, 626p, 630p, 641p, 651p, 653p],  
[ 621p, 633p, 638p, 654p, 658p, 709p, 719p, 721p],  
[ 651p, 703p, 708p, 724p, 728p, 739p, 749p, 751p],  
[ 721p, 733p, 738p, 754p, 758p, 809p, 819p, 821p],  
[ 751p, 803p, 808p, 824p, 828p, 839p, 849p, 851p],  
[ 821p, 833p, 838p, 854p, 858p, 909p, 919p, 921p],  
[ 851p, 903p, 908p, 924p, 928p, 939p, 949p, 951p],  
[ 921p, 933p, 938p, 954p, 958p, 1009p, 1019p, 1021p],  
[ 951p, 1003p, 1008p, 1024p, 1028p, 1039p, 1049p, 1051p],  
[ 1021p, 1033p, 1038p, 1054p, 1058p, 1109p, 1119p, 1121p],  
[ 1121p, 1133p, 1138p, 1154p, 1158p, 1209x, 1219x, 1221x],  
[ 1216x, 1228x, -, -, -, -, -, -],  
[ 116x, 128x, -, -, -, -, -, -]  
]  
stop_times_saturday: [  
[ 545a, 557a, 603a, 613a, 622a, 633a, 643a, 645a],  
[ 615a, 627a, 633a, 643a, 652a, 703a, 713a, 715a],  
[ 645a, 657a, 703a, 713a, 722a, 734a, 744a, 745a],  
[ 725a, 738a, 744a, 754a, 803a, 815a, 825a, 827a],  
[ 755a, 808a, 814a, 824a, 833a, 845a, 855a, 857a],  
[ 825a, 838a, 844a, 854a, 903a, 915a, 925a, 927a],  
[ 855a, 908a, 914a, 924a, 933a, 945a, 955a, 957a],  
[ 925a, 938a, 944a, 954a, 1003a, 1015a, 1025a, 1027a],  
[ 955a, 1008a, 1014a, 1024a, 1033a, 1045a, 1055a, 1057a],  
[ 1025a, 1038a, 1044a, 1054a, 1103a, 1115a, 1125a, 1127a],  
[ 1055a, 1108a, 1114a, 1124a, 1133a, 1145a, 1155a, 1157a],  
[ 1125a, 1138a, 1144a, 1154a, 1203p, 1215p, 1225p, 1227p],  
[ 1155a, 1208p, 1214p, 1224p, 1233p, 1245p, 1255p, 1257p],  
[ 1225p, 1238p, 1244p, 1254p, 103p, 115p, 125p, 127p],  
[ 1255p, 108p, 114p, 124p, 133p, 145p, 155p, 157p],  
[ 125p, 138p, 144p, 154p, 203p, 215p, 225p, 227p],  
[ 155p, 208p, 214p, 224p, 233p, 245p, 255p, 257p],  
[ 225p, 238p, 244p, 254p, 303p, 315p, 325p, 327p],  
[ 255p, 308p, 314p, 324p, 333p, 345p, 355p, 357p],  
[ 325p, 338p, 344p, 354p, 403p, 415p, 425p, 427p],  
[ 355p, 408p, 414p, 424p, 433p, 445p, 455p, 457p],  
[ 425p, 438p, 444p, 454p, 503p, 515p, 525p, 527p],  
[ 455p, 508p, 514p, 524p, 533p, 545p, 555p, 557p],  
[ 525p, 538p, 544p, 554p, 603p, 615p, 625p, 627p],  
[ 555p, 608p, 614p, 624p, 633p, 645p, 655p, 657p],  
[ 635p, 648p, 654p, 704p, 713p, 725p, 735p, 737p],  
[ 705p, 718p, 724p, 734p, 743p, 755p, 805p, 807p],  
[ 735p, 748p, 754p, 804p, 813p, 825p, 835p, 837p],  
[ 805p, 818p, 824p, 834p, 843p, 855p, 905p, 907p],  
[ 835p, 848p, 854p, 904p, 913p, 925p, 935p, 937p],  
[ 905p, 918p, 924p, 934p, 943p, 955p, 1005p, 1007p],  
[ 935p, 948p, 954p, 1004p, 1013p, 1023p, 1033p, 1035p],  
[ 1005p, 1017p, 1023p, 1033p, 1042p, 1052p, 1102p, 1104p],  
[ 1107p, 1119p, 1125p, 1135p, 1144p, 1154p, 1204x, 1206x],  
[ 1207x, 1219x, 1225x, -, -, -, -, -],  
[ 107x, 119x, 125x, -, -, -, -, -]  
]  
stop_times_sunday: [  
[ 545a, 605a, 610a, 622a, 630a, 640a, 650a, 652a],  
[ 645a, 705a, 710a, 722a, 730a, 740a, 750a, 752a],  
[ 715a, 735a, 740a, 752a, 800a, 810a, 820a, 822a],  
[ 745a, 805a, 810a, 822a, 830a, 840a, 850a, 852a],  
[ 815a, 835a, 840a, 852a, 900a, 910a, 920a, 922a],  
[ 845a, 905a, 910a, 922a, 930a, 940a, 950a, 952a],  
[ 915a, 935a, 940a, 952a, 1000a, 1010a, 1020a, 1022a],  
[ 945a, 1005a, 1010a, 1022a, 1030a, 1040a, 1050a, 1052a],  
[ 1015a, 1035a, 1040a, 1052a, 1100a, 1110a, 1120a, 1122a],  
[ 1045a, 1105a, 1110a, 1122a, 1130a, 1140a, 1150a, 1152a],  
[ 1115a, 1135a, 1140a, 1152a, 1200p, 1210p, 1220p, 1222p],  
[ 1135a, 1155a, 1200p, 1212p, 1220p, 1230p, 1240p, 1242p],  
[ 1155a, 1215p, 1220p, 1232p, 1240p, 1250p, 100p, 102p],  
[ 1215p, 1235p, 1240p, 1252p, 100p, 110p, 120p, 122p],  
[ 1235p, 1255p, 100p, 112p, 120p, 130p, 140p, 142p],  
[ 1255p, 115p, 120p, 132p, 140p, 150p, 200p, 202p],  
[ 115p, 135p, 140p, 152p, 200p, 210p, 220p, 222p],  
[ 135p, 155p, 200p, 212p, 220p, 230p, 240p, 242p],  
[ 155p, 215p, 220p, 232p, 240p, 250p, 300p, 302p],  
[ 215p, 235p, 240p, 252p, 300p, 310p, 320p, 322p],  
[ 235p, 255p, 300p, 312p, 320p, 330p, 340p, 342p],  
[ 255p, 315p, 320p, 332p, 340p, 350p, 400p, 402p],  
[ 315p, 335p, 340p, 352p, 400p, 410p, 420p, 422p],  
[ 335p, 355p, 400p, 412p, 420p, 430p, 440p, 442p],  
[ 355p, 415p, 420p, 432p, 440p, 450p, 500p, 502p],  
[ 415p, 435p, 440p, 452p, 500p, 510p, 520p, 522p],  
[ 435p, 455p, 500p, 512p, 520p, 530p, 540p, 542p],  
[ 455p, 515p, 520p, 532p, 540p, 550p, 600p, 602p],  
[ 515p, 535p, 540p, 552p, 600p, 610p, 620p, 622p],  
[ 535p, 555p, 600p, 612p, 620p, 630p, 640p, 642p],  
[ 555p, 615p, 620p, 632p, 640p, 650p, 700p, 702p],  
[ 615p, 635p, 640p, 652p, 700p, 710p, 720p, 722p],  
[ 635p, 655p, 700p, 712p, 720p, 730p, 740p, 742p],  
[ 655p, 715p, 720p, 732p, 740p, 750p, 800p, 802p],  
[ 715p, 735p, 740p, 752p, 800p, 810p, 820p, 822p],  
[ 735p, 755p, 800p, 812p, 820p, 830p, 840p, 842p],  
[ 755p, 815p, 820p, 832p, 840p, 850p, 900p, 902p],  
[ 815p, 835p, 840p, 852p, 900p, 910p, 920p, 922p],  
[ 835p, 855p, 900p, 912p, 920p, 930p, 940p, 942p],  
[ 855p, 915p, 920p, 932p, 940p, 950p, 1000p, 1002p],  
[ 915p, 935p, 940p, 952p, 1000p, 1010p, 1020p, 1022p],  
[ 945p, 1005p, 1010p, 1022p, 1030p, 1040p, 1050p, 1052p],  
[ 1015p, 1035p, 1040p, 1052p, 1100p, 1110p, 1120p, 1122p],  
[ 1115p, 1135p, 1140p, 1152p, 1200x, 1210x, 1220x, 1222x],  
[ 1215x, 1235x, 1240x, -, -, -, -, -]  
]  
 
short_name: 80  
long_name: To Bedford - Sackville  
time_points: [ 8414, 6105, 8184, 6563, 6219, 6238, 6445, 8260 ]  
between_stops:  
6105-8184: [ 6108, 6103, 6102, 6122, 8331, 8330, 8334, 8335, 8329, 8185, 8219, 8179 ]  
8184-6563: [ 8206, 8221, 8222, 8181, 8210, 8201, 8251, 8629, 8634, 6192, 6196, 6201, 6200, 6199, 6198 ]  
6563-6219: [ 6565, 6984, 6983 ]  
stop_times: [  
[ -, -, -, -, -, 519a, 525a, -],  
[ -, -, -, -, -, 608a, 615a, 628a],  
[ 552a, 555a, 605a, 615a, 619a, 634a, 640a, 658a],  
[ 618a, 621a, 631a, 641a, 645a, 701a, 709a, 725a],  
[ 642a, 645a, 655a, 708a, 713a, 731a, 738a, 752a],  
[ 707a, 710a, 722a, 737a, 742a, 800a, 808a, 821a],  
[ 737a, 740a, 752a, 807a, 812a, 830a, 838a, 851a],  
[ 807a, 810a, 822a, 837a, 842a, 900a, 908a, 921a],  
[ 837a, 840a, 852a, 907a, 912a, 930a, 938a, 951a],  
[ 907a, 910a, 922a, 937a, 942a, 1000a, 1008a, 1021a],  
[ 937a, 940a, 952a, 1007a, 1012a, 1030a, 1038a, 1051a],  
[ 1007a, 1010a, 1022a, 1037a, 1042a, 1100a, 1108a, 1121a],  
[ 1037a, 1040a, 1052a, 1107a, 1112a, 1130a, 1138a, 1151a],  
[ 1107a, 1110a, 1122a, 1137a, 1142a, 1200p, 1208p, 1221p],  
[ 1137a, 1140a, 1152a, 1207p, 1212p, 1230p, 1238p, 1251p],  
[ 1207p, 1210p, 1222p, 1237p, 1242p, 100p, 108p, 121p],  
[ 1237p, 1240p, 1252p, 107p, 112p, 130p, 138p, 151p],  
[ 107p, 110p, 122p, 137p, 142p, 200p, 208p, 221p],  
[ 127p, 130p, 142p, 157p, 202p, 220p, 228p, 241p],  
[ 147p, 150p, 202p, 217p, 222p, 240p, 248p, 301p],  
[ 207p, 210p, 222p, 237p, 242p, 300p, 308p, 321p],  
[ 222p, 225p, 237p, 252p, 257p, 315p, 323p, 336p],  
[ 235p, 238p, 250p, 305p, 310p, 328p, 338p, 351p],  
[ 249p, 252p, 304p, 319p, 324p, 343p, 353p, 406p],  
[ 303p, 306p, 318p, 334p, 342p, 401p, 411p, 424p],  
[ 316p, 319p, 331p, 350p, 358p, 417p, 427p, 440p],  
[ 331p, 334p, 346p, 405p, 413p, 432p, 442p, 455p],  
[ 346p, 349p, 401p, 420p, 428p, 447p, 457p, 510p],  
[ 401p, 404p, 416p, 435p, 443p, 502p, 512p, 525p],  
[ 416p, 419p, 431p, 450p, 458p, 517p, 527p, 540p],  
[ 431p, 434p, 446p, 505p, 513p, 532p, 542p, 555p],  
[ 446p, 449p, 501p, 520p, 528p, 546p, 553p, 606p],  
[ 502p, 505p, 517p, 536p, 544p, 557p, 604p, 617p],  
[ 522p, 525p, 537p, 553p, 558p, 611p, 618p, 631p],  
[ 542p, 545p, 555p, 608p, 613p, 626p, 633p, 646p],  
[ 608p, 610p, 620p, 633p, 638p, 651p, 658p, 711p],  
[ 638p, 640p, 650p, 703p, 708p, 721p, 728p, 741p],  
[ 708p, 710p, 720p, 733p, 738p, 751p, 758p, 811p],  
[ 738p, 740p, 750p, 803p, 808p, 821p, 828p, 841p],  
[ 808p, 810p, 820p, 833p, 838p, 851p, 858p, 911p],  
[ 838p, 840p, 850p, 903p, 908p, 921p, 928p, 941p],  
[ 908p, 910p, 920p, 933p, 938p, 951p, 958p, 1011p],  
[ 1008p, 1010p, 1020p, 1033p, 1038p, 1051p, 1058p, 1111p],  
[ 1108p, 1110p, 1120p, 1133p, 1138p, 1151p, 1158p, 1211x],  
[ 1208x, 1210x, 1220x, 1233x, 1238x, 1251x, 1258x, 111x]  
]  
stop_times_saturday: [  
[ -, -, -, -, -, 553a, 602a, 615a],  
[ -, -, -, -, -, 623a, 632a, 645a],  
[ 615a, 618a, 626a, 638a, 644a, 653a, 702a, 714a],  
[ 645a, 648a, 658a, 710a, 716a, 725a, 734a, 747a],  
[ 715a, 718a, 726a, 738a, 744a, 753a, 802a, 814a],  
[ 745a, 748a, 758a, 810a, 816a, 825a, 834a, 847a],  
[ 813a, 816a, 826a, 838a, 844a, 853a, 902a, 914a],  
[ 837a, 840a, 852a, 907a, 913a, 922a, 931a, 944a],  
[ 907a, 910a, 922a, 937a, 943a, 952a, 1001a, 1014a],  
[ 937a, 940a, 952a, 1007a, 1013a, 1022a, 1031a, 1044a],  
[ 1007a, 1010a, 1022a, 1037a, 1043a, 1052a, 1101a, 1114a],  
[ 1037a, 1040a, 1052a, 1107a, 1113a, 1122a, 1131a, 1144a],  
[ 1107a, 1110a, 1122a, 1137a, 1143a, 1152a, 1201p, 1214p],  
[ 1137a, 1140a, 1152a, 1207p, 1213p, 1222p, 1231p, 1244p],  
[ 1207p, 1210p, 1222p, 1237p, 1243p, 1252p, 101p, 114p],  
[ 1237p, 1240p, 1252p, 107p, 113p, 122p, 131p, 144p],  
[ 107p, 110p, 122p, 137p, 143p, 152p, 201p, 214p],  
[ 137p, 140p, 152p, 207p, 213p, 222p, 231p, 244p],  
[ 207p, 210p, 222p, 237p, 243p, 252p, 301p, 314p],  
[ 237p, 240p, 252p, 307p, 313p, 322p, 331p, 344p],  
[ 307p, 310p, 322p, 337p, 343p, 352p, 401p, 414p],  
[ 337p, 340p, 352p, 407p, 413p, 422p, 431p, 444p],  
[ 407p, 410p, 422p, 437p, 443p, 452p, 501p, 514p],  
[ 437p, 440p, 452p, 507p, 513p, 522p, 531p, 544p],  
[ 507p, 510p, 522p, 537p, 543p, 552p, 601p, 614p],  
[ 537p, 540p, 552p, 607p, 613p, 622p, 631p, 644p],  
[ 607p, 610p, 622p, 637p, 643p, 652p, 701p, 714p],  
[ 637p, 640p, 652p, 707p, 713p, 722p, 731p, 744p],  
[ 707p, 710p, 722p, 737p, 743p, 752p, 801p, 814p],  
[ 737p, 740p, 752p, 807p, 813p, 822p, 831p, 844p],  
[ 807p, 810p, 822p, 837p, 843p, 852p, 901p, 914p],  
[ 837p, 840p, 852p, 907p, 913p, 922p, 931p, 944p],  
[ 907p, 910p, 922p, 937p, 943p, 952p, 1001p, 1014p],  
[ 937p, 940p, 952p, 1006p, 1012p, 1020p, 1028p, 1041p],  
[ 1007p, 1010p, 1020p, 1032p, 1038p, 1046p, 1054p, 1107p],  
[ 1037p, 1040p, 1050p, 1102p, 1108p, 1116p, 1124p, 1137p],  
[ 1107p, 1110p, 1120p, 1132p, 1138p, 1146p, 1154p, 1207x],  
[ 1207x, 1210x, 1220x, 1232x, 1238x, 1246x, 1254x, 107x]  
]  
stop_times_sunday: [  
[ -, -, -, -, -, 642a, 650a, 707a],  
[ -, -, -, -, 659a, 712a, 720a, 737a],  
[ 657a, 700a, 710a, 722a, 729a, 742a, 750a, 807a],  
[ 727a, 730a, 740a, 752a, 759a, 812a, 820a, 837a],  
[ 757a, 800a, 810a, 822a, 829a, 842a, 850a, 907a],  
[ 827a, 830a, 840a, 852a, 859a, 912a, 920a, 937a],  
[ 857a, 900a, 910a, 922a, 929a, 942a, 950a, 1007a],  
[ 927a, 930a, 940a, 952a, 959a, 1012a, 1020a, 1037a],  
[ 957a, 1000a, 1010a, 1022a, 1029a, 1042a, 1050a, 1107a],  
[ 1027a, 1030a, 1040a, 1052a, 1059a, 1112a, 1120a, 1137a],  
[ 1057a, 1100a, 1110a, 1122a, 1129a, 1142a, 1150a, 1207p],  
[ 1127a, 1130a, 1140a, 1152a, 1159a, 1212p, 1220p, 1237p],  
[ 1157a, 1200p, 1210p, 1222p, 1229p, 1242p, 1250p, 107p],  
[ 1227p, 1230p, 1240p, 1252p, 1259p, 112p, 120p, 137p],  
[ 1257p, 100p, 110p, 122p, 129p, 142p, 150p, 207p],  
[ 127p, 130p, 140p, 152p, 159p, 212p, 220p, 237p],  
[ 157p, 200p, 210p, 222p, 229p, 242p, 250p, 307p],  
[ 227p, 230p, 240p, 252p, 259p, 312p, 320p, 337p],  
[ 257p, 300p, 310p, 322p, 329p, 342p, 350p, 407p],  
[ 327p, 330p, 340p, 352p, 359p, 412p, 420p, 437p],  
[ 357p, 400p, 410p, 422p, 429p, 442p, 450p, 507p],  
[ 427p, 430p, 440p, 452p, 459p, 512p, 520p, 537p],  
[ 457p, 500p, 510p, 522p, 529p, 542p, 550p, 607p],  
[ 527p, 530p, 540p, 552p, 559p, 612p, 620p, 637p],  
[ 557p, 600p, 610p, 622p, 629p, 642p, 650p, 707p],  
[ 627p, 630p, 640p, 652p, 659p, 712p, 720p, 737p],  
[ 657p, 700p, 710p, 722p, 729p, 742p, 750p, 807p],  
[ 727p, 730p, 740p, 752p, 759p, 812p, 820p, 837p],  
[ 757p, 800p, 810p, 822p, 829p, 842p, 850p, 907p],  
[ 827p, 830p, 840p, 852p, 859p, 912p, 920p, 937p],  
[ 857p, 900p, 910p, 922p, 929p, 942p, 950p, 1007p],  
[ 957p, 1000p, 1010p, 1022p, 1029p, 1042p, 1050p, 1107p],  
[ 1057p, 1100p, 1110p, 1122p, 1129p, 1142p, 1150p, 1207x]  
]  
 
short_name: 81  
long_name: To Downtown Halifax  
time_points: [ 7125, 6216, 6564, 8214, 6087, 8414 ]  
between_stops:  
6216-6564: [ 6982, 6985, 8262 ]  
6564-8214: [ 6197, 6193, 6203, 8633, 8193, 8202, 8182, 8213, 8178, 8205, 8190 ]  
8214-6087: [ 8183, 8196, 8195, 8194, 8328, 8337, 8333, 8336, 8327, 8338 ]  
stop_times: [  
[ 610a, 620a, 627a, 637a, 647a, 649a],  
[ 640a, 650a, 657a, 708a, 725a, 727a],  
[ 710a, 720a, 728a, 739a, 756a, 758a],  
[ 740a, 750a, 758a, 809a, 826a, 828a],  
[ 810a, 820a, 828a, 839a, 856a, 858a],  
[ 840a, 850a, 858a, 909a, 926a, 928a],  
[ 910a, 920a, 928a, 939a, 956a, 958a],  
[ 940a, 950a, 958a, 1009a, 1026a, 1028a],  
[ 1010a, 1020a, 1028a, 1039a, 1056a, 1058a],  
[ 1040a, 1050a, 1058a, 1109a, 1126a, 1128a],  
[ 1110a, 1120a, 1128a, 1139a, 1156a, 1158a],  
[ 1140a, 1150a, 1158a, 1209p, 1226p, 1228p],  
[ 1210p, 1220p, 1228p, 1239p, 1256p, 1258p],  
[ 1240p, 1250p, 1258p, 109p, 126p, 128p],  
[ 110p, 120p, 128p, 139p, 156p, 158p],  
[ 140p, 150p, 158p, 209p, 226p, 228p],  
[ 210p, 220p, 228p, 239p, 256p, 258p],  
[ 240p, 250p, 258p, 309p, 326p, 328p],  
[ 310p, 320p, 328p, 339p, 356p, 358p],  
[ 340p, 350p, 358p, 409p, 426p, 428p],  
[ 414p, 424p, 432p, 443p, 500p, 502p],  
[ 444p, 454p, 502p, 513p, 530p, 532p],  
[ 514p, 524p, 532p, 543p, 600p, 602p],  
[ 544p, 554p, 602p, 613p, 623p, 625p],  
[ 610p, 620p, 624p, 635p, 645p, 647p],  
[ 640p, 650p, 654p, 705p, 715p, 717p],  
[ 710p, 720p, 724p, 735p, 745p, 747p],  
[ 740p, 750p, 754p, 805p, 815p, 817p]  
]  
 
short_name: 81  
long_name: To Hemlock Ravine  
time_points: [ 8414, 6105, 8184, 6563, 6219, 7125 ]  
between_stops:  
6105-8184: [ 6108, 6103, 6102, 6122, 8331, 8330, 8334, 8335, 8329 ]  
8184-6563: [ 8206, 8221, 8222, 8181, 8210, 8201, 8251, 8629, 8634, 6192, 6196, 6201, 6200, 6199, 6198 ]  
6563-6219: [ 6565, 6984, 6983 ]  
stop_times: [  
[ -, -, -, -, 600a, 610a],  
[ 603a, 606a, 616a, 626a, 630a, 640a],  
[ 633a, 636a, 646a, 656a, 700a, 710a],  
[ 655a, 658a, 710a, 725a, 730a, 740a],  
[ 725a, 728a, 740a, 755a, 800a, 810a],  
[ 755a, 758a, 810a, 825a, 830a, 840a],  
[ 825a, 828a, 840a, 855a, 900a, 910a],  
[ 855a, 858a, 910a, 925a, 930a, 940a],  
[ 925a, 928a, 940a, 955a, 1000a, 1010a],  
[ 955a, 958a, 1010a, 1025a, 1030a, 1040a],  
[ 1025a, 1028a, 1040a, 1055a, 1100a, 1110a],  
[ 1055a, 1058a, 1110a, 1125a, 1130a, 1140a],  
[ 1125a, 1128a, 1140a, 1155a, 1200p, 1210p],  
[ 1155a, 1158a, 1210p, 1225p, 1230p, 1240p],  
[ 1225p, 1228p, 1240p, 1255p, 100p, 110p],  
[ 1255p, 1258p, 110p, 125p, 130p, 140p],  
[ 125p, 128p, 140p, 155p, 200p, 210p],  
[ 155p, 158p, 210p, 225p, 230p, 240p],  
[ 225p, 228p, 240p, 255p, 300p, 310p],  
[ 255p, 258p, 310p, 325p, 330p, 340p],  
[ 322p, 325p, 337p, 356p, 404p, 414p],  
[ 352p, 355p, 407p, 426p, 434p, 444p],  
[ 422p, 425p, 437p, 456p, 504p, 514p],  
[ 452p, 455p, 507p, 526p, 534p, 544p],  
[ 525p, 528p, 540p, 555p, 600p, 610p],  
[ 600p, 602p, 612p, 625p, 630p, 640p],  
[ 630p, 632p, 642p, 655p, 700p, 710p],  
[ 700p, 702p, 712p, 725p, 730p, 740p]  
]  
 
short_name: 9  
long_name: To Mumford Terminal  
time_points: [ 8649, 8409, 6087, 6583, 7284 ]  
between_stops:  
6087-6583: [ 6089, 6116, 6091, 6127, 6094, 6110, 6119, 6128, 6580, 6588, 6584, 6583 ]  
6583-7284: [ 6585, 7096, 8560 ]  
8409-6087: [ 6096, 6113, 6124 ]  
8649-6087: [ 6096, 6113, 6124 ]  
stop_times: [  
[ 620a, -, 630a, 641a, 652a],  
[ 650a, -, 703a, 714a, 725a],  
[ 715a, -, 728a, 739a, 750a],  
[ 735a, -, 748a, 759a, 810a],  
[ 755a, -, 808a, 819a, 830a],  
[ 815a, -, 828a, 839a, 850a],  
[ 837a, -, 850a, 901a, 912a],  
[ 907a, -, 920a, 931a, 942a],  
[ 937a, -, 950a, 1001a, 1012a],  
[ 1007a, -, 1020a, 1031a, 1042a],  
[ 1037a, -, 1050a, 1101a, 1112a],  
[ 1107a, -, 1120a, 1131a, 1142a],  
[ 1137a, -, 1150a, 1201p, 1212p],  
[ 1207p, -, 1220p, 1231p, 1242p],  
[ 1237p, -, 1250p, 101p, 112p],  
[ 107p, -, 120p, 131p, 142p],  
[ 137p, -, 150p, 201p, 212p],  
[ 207p, -, 220p, 231p, 242p],  
[ 237p, -, 250p, 301p, 312p],  
[ 307p, -, 320p, 331p, 342p],  
[ 327p, -, 340p, 351p, 402p],  
[ 347p, -, 400p, 411p, 422p],  
[ 407p, -, 420p, 431p, 442p],  
[ 427p, -, 440p, 451p, 502p],  
[ 447p, -, 500p, 511p, 522p],  
[ 507p, -, 520p, 531p, 542p],  
[ 537p, -, 550p, 601p, 612p],  
[ 608p, -, 620p, 631p, 640p],  
[ 658p, -, 710p, 721p, 732p],  
[ 758p, -, 810p, 821p, 832p],  
[ -, 859p, 910p, 920p, 931p],  
[ -, 1000p, 1010p, 1019p, 1030p],  
[ -, 1100p, 1110p, 1119p, 1130p],  
[ -, 1200x, 1210x, 1219x, 1230x]  
]  
 
short_name: 9  
long_name: To Point Pleasant Park  
time_points: [ 7284, 7094, 6105, 8649 ]  
between_stops:  
7284-7094: [ 7274, 6409, 6403, 6407, 8552, 8563, 8553 ]  
7094-6105: [ 6581, 6582, 6586, 6587, 6100, 6120, 6109, 6095, 6090, 6107, 6115, 6088, 6104, 6125 ]  
6105-8649: [ 6108, 6103, 6102, 6114, 6097 ]  
stop_times: [  
[ 550a, 600a, 610a, 619a],  
[ 615a, 625a, 635a, 646a],  
[ 635a, 646a, 659a, 713a],  
[ 655a, 707a, 720a, 734a],  
[ 715a, 727a, 740a, 754a],  
[ 735a, 747a, 800a, 814a],  
[ 755a, 807a, 820a, 834a],  
[ 825a, 837a, 850a, 904a],  
[ 855a, 906a, 919a, 933a],  
[ 925a, 935a, 948a, 1002a],  
[ 955a, 1005a, 1018a, 1032a],  
[ 1025a, 1035a, 1048a, 1102a],  
[ 1055a, 1105a, 1118a, 1132a],  
[ 1125a, 1135a, 1148a, 1202p],  
[ 1155a, 1205p, 1218p, 1232p],  
[ 1225p, 1235p, 1248p, 102p],  
[ 1255p, 105p, 118p, 132p],  
[ 125p, 135p, 148p, 202p],  
[ 155p, 205p, 218p, 232p],  
[ 225p, 237p, 250p, 304p],  
[ 245p, 257p, 310p, 324p],  
[ 305p, 317p, 330p, 344p],  
[ 325p, 337p, 350p, 404p],  
[ 345p, 357p, 410p, 424p],  
[ 405p, 417p, 430p, 444p],  
[ 425p, 437p, 450p, 504p],  
[ 455p, 507p, 520p, 534p],  
[ 525p, 537p, 550p, 602p],  
[ 622p, 632p, 645p, 657p],  
[ 722p, 732p, 745p, 757p],  
[ 822p, 832p, 845p, -],  
[ 922p, 932p, 942p, -],  
[ 1022p, 1032p, 1042p, -],  
[ 1122p, 1132p, 1142p, -]  
]  
 
default: hfxfeed.zip  
 
hfxfeed.zip: hfxtable.yml createfeed.py  
./createfeed.py --input=hfxtable.yml --output=hfxfeed.zip  
 
ROUTE_FILES=1-to-dartmouth.yml 1-to-mumford.yml \  
2-to-downtown-via-north.yml 2-to-wedgewood-via-main.yml \  
3-to-shopping-malls.yml 3-to-manors.yml \  
4-to-farnham-gate-via-rosedale.yml 4-to-downtown-via-north.yml \  
5-to-springvale.yml 5-to-downtown.yml \  
6-to-stonehaven.yml 6-to-downtown.yml \  
7-robie-to-gottingen.yml 7-gottingen-to-robie.yml \  
9-to-point-pleasant-park.yml 9-to-mumford.yml \  
10-to-westphal.yml 10-to-dalhousie.yml \  
14-to-leiblin-park.yml 14-to-universities-downtown.yml \  
17-to-hospitals-universities.yml 17-to-lacewood.yml \  
18-to-smu.yml 18-to-lacewood.yml \  
20-to-herring-cove.yml 20-to-mumford-downtown.yml \  
21-to-timberlea.yml 21-to-lacewood-halifax.yml \  
23-to-timberlea.yml 23-to-mumford-halifax.yml \  
41-to-dalhousie.yml 41-to-bridge-terminal.yml \  
42-to-lacewood.yml 42-to-dalhousie.yml \  
52-to-bridge-terminal-burnside.yml 52-to-lacewood-chain-lake-drive.yml \  
58-to-lucien-drive.yml \  
80-to-bedford-halifax.yml 80-to-bedford-sackville.yml \  
81-to-downtown-halifax.yml 81-to-hemlock-ravine.yml  
 
hfxtable.yml: hfxtable.yml.in $(ROUTE_FILES) indent-route.pl  
cp hfxtable.yml.in hfxtable.yml  
@$(foreach ROUTE_FILE, $(ROUTE_FILES), \  
echo "Parsing $(ROUTE_FILE)"; \  
./indent-route.pl < $(ROUTE_FILE) >> hfxtable.yml;)  
 
clean:  
rm -f hfxtable.yml hfxfeed.zip *~  
 
=== Introduction ===  
 
This distribution contains everything required to build a basic google transit  
feed for Halifax Metro Transit, Nova Scotia, Canada. Note that it is woefully  
incomplete at the moment.  
 
Requirements: GNU Make, Perl, Python 2.5.  
 
=== Usage ===  
 
First, grab a copy of google transit feed tools:  
 
cd $HOME/src  
wget http://googletransitdatafeed.googlecode.com/files/transitfeed-1.1.7.tar.gz  
tar zxvf transitfeed-1.1.7.tar.gz  
 
Set PYTHONPATH to the python directory in the above checkout:  
 
export PYTHONPATH=$HOME/src/transitfeed-1.1.7/python  
 
Then just type "make" to build the feed. The output at the end is "feed.zip".  
For fun, you can view this feed using the snazzy transit feed view application:  
 
$HOME/src/transitfeed-1.1.7/python/schedule_viewer.py --feed=hfxfeed.zip  
 
=== Copyright ===  
 
With the exception of createfeed.py, which is licensed under the Apache Public  
License, please consider all software tools in distribution to be in the public  
domain. Use them for what you will.  
 
I believe the Metro Transit route data is considered factual information  
which can not be copyrighted. Note, however, that Metro Transit and/or  
the city of Halifax may have claim over its own name and other trademarks.  
 
#!/usr/bin/perl  
 
use strict;  
 
sub parse_time {  
my ($time) = @_;  
 
my ($hour, $minute);  
 
if ($time =~ /a\Z/) {  
$time =~ m/([0-9]+)([0-9][0-9])a/;  
($hour, $minute) = ($1, $2);  
} elsif ($time =~ /p\Z/) {  
$time =~ m/([0-9]+)([0-9][0-9])p/;  
($hour, $minute) = ($1, $2);  
if ($hour < 12) {  
$hour += 12;  
}  
} elsif ($time =~ /x\Z/) {  
$time =~ m/([0-9]+)([0-9][0-9])x/;  
($hour, $minute) = ($1, $2);  
if ($hour == 12) {  
$hour += 12;  
} else {  
$hour += 24;  
}  
} elsif ($time =~ /^\ *-\Z/) {  
($hour, $minute) = (0, 0);  
# no stop at this time  
} else {  
print "Should not happen! Time ('$time') misformed.\n";  
exit;  
}  
 
return ($hour, $minute);  
}  
 
my $num_intervals = $ARGV[0] or die "No num intervals given!";  
my $interval = $ARGV[1] or die "No interval given!";  
 
my @times;  
 
$_ = <STDIN>;  
print $_;  
 
if ($_ !~ /^\#/) {  
my @timestrs;  
if ($_ =~ m/\[(.*)\]/) {  
my $inner = $1;  
@timestrs = split (/\,/, $inner);  
 
} else {  
@timestrs = split /\ /;  
}  
 
foreach (@timestrs) {  
my ($hour, $minute) = parse_time($_);  
push @times, [ $hour, $minute ];  
}  
}  
 
for (my $i=1; $i<($num_intervals+1); $i++) {  
my $first = 1;  
foreach (@times) {  
my $mytime = $_;  
my ($hour, $minute) = (@$mytime[0], @$mytime[1]);  
if ($hour > 0 || $minute > 0) {  
$minute += $interval * $i;  
if ($minute > 59) {  
$hour += int($minute / 60);  
$minute = $minute % 60;  
if ($minute < 10) {  
$minute = "0" . $minute;  
}  
}  
}  
 
sub print_time {  
my ($hour, $minute) = @_;  
if ($hour == 0 && $minute == 0) {  
print "-";  
} else {  
if ($hour < 12) {  
print "$hour$minute" . "a";  
} else {  
if ($hour > 12) {  
$hour -= 12;  
}  
print "$hour$minute" . "p";  
}  
}  
}  
 
if (!$first) {  
print " ";  
print_time($hour, $minute);  
} else {  
$first = 0;  
print_time($hour, $minute);  
}  
}  
print "\n";  
}  
 
#!/usr/bin/python  
 
# Copyright (C) 2007 Google Inc.  
# Copyright (C) 2008-2009 William Lachance  
#  
# Licensed under the Apache License, Version 2.0 (the "License");  
# you may not use this file except in compliance with the License.  
# You may obtain a copy of the License at  
#  
# http://www.apache.org/licenses/LICENSE-2.0  
#  
# Unless required by applicable law or agreed to in writing, software  
# distributed under the License is distributed on an "AS IS" BASIS,  
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
# See the License for the specific language governing permissions and  
# limitations under the License.  
 
import transitfeed  
from transitfeed import ServicePeriod  
from optparse import OptionParser  
import yaml, sys, os.path  
import re  
 
stops = {}  
 
def ProcessOptions(schedule, options):  
 
# the follow features are REQUIRED  
agency_name = options.get('agency_name')  
agency_url = options.get('agency_url')  
agency_timezone = options.get('agency_timezone')  
 
service_periods = []  
 
service_periods.append(ServicePeriod(id="weekday"))  
service_periods[0].SetWeekdayService()  
service_periods.append(ServicePeriod(id="saturday"))  
service_periods[1].SetDayOfWeekHasService(5)  
service_periods.append(ServicePeriod(id="sunday"))  
service_periods[2].SetDayOfWeekHasService(6)  
 
# the service period options are, well, optional  
for service_period in service_periods:  
if options.get('start_date'):  
service_period.SetStartDate(options['start_date'])  
if options.get('end_date'):  
service_period.SetEndDate(options['end_date'])  
if options.get('add_date'):  
service_period.SetDateHasService(options['add_date'])  
if options.get('remove_date'):  
service_period.SetDateHasService(options['remove_date'],  
has_service=False)  
 
# Add all service period objects to the schedule  
schedule.SetDefaultServicePeriod(service_periods[0], validate=False)  
schedule.AddServicePeriodObject(service_periods[1], validate=False)  
schedule.AddServicePeriodObject(service_periods[2], validate=False)  
 
if not (agency_name and agency_url and agency_timezone):  
print "You must provide agency information"  
 
schedule.NewDefaultAgency(agency_name=agency_name, agency_url=agency_url,  
agency_timezone=agency_timezone)  
 
 
# Remove any stops from stopsdata that aren't serviced by any routes in  
# routedata.  
def PruneStops(stopsdata, routedata):  
stopset = set()  
for route in routedata:  
stopset.update(route['time_points'])  
for between_list in route['between_stops']:  
stopset.update(route['between_stops'][between_list])  
 
toprune = list()  
for i, stop in enumerate(stopsdata):  
if stop['stop_code'] not in stopset:  
print "Pruning unused stop %s " % stop['stop_code']  
toprune.append(i)  
 
# Prune the list in reverse order, as the indices will change otherwise.  
toprune.sort()  
toprune.reverse()  
for prunee in toprune:  
del stopsdata[prunee]  
 
def AddStops(schedule, stopsdata):  
for stopdata in stopsdata:  
stop_code = stopdata['stop_code']  
# we have to manually add the stop instead of using AddStop, cause  
# we want the stop_code  
stop_id = unicode(len(schedule.stops))  
stop = transitfeed.Stop(stop_id=stop_id, lat=stopdata['lat'],  
lng=stopdata['lng'], name=stopdata['name'],  
stop_code=stop_code)  
schedule.AddStopObject(stop)  
stops[stop_code] = stop  
 
 
def AddTripsToSchedule(schedule, route, routedata, service_id, stop_times):  
 
service_period = schedule.GetServicePeriod(service_id)  
timerex = re.compile('^(\d+)(\d\d)([a-z])$')  
 
for trip in stop_times:  
t = route.AddTrip(schedule, headsign=routedata['long_name'], service_period=service_period)  
 
if len(trip) > len(routedata['time_points']):  
print "Length of trip (%s) exceeds number of time points (%s)!" % (len(trip), len(routedata['time_points']))  
class StopTimesError(Exception): pass  
raise StopTimesError()  
else:  
trip_stops = [] # Build a list of (time, stop_code) tuples  
i = 0  
for stop_time in trip:  
matches = timerex.match(str(stop_time))  
if matches and len(matches.groups()) == 3:  
hour, minute, shift = (int(matches.group(1)),  
str(matches.group(2)),  
matches.group(3))  
if shift == 'p' and hour < 12:  
hour += 12  
elif shift == 'x':  
if hour == 12:  
hour += 12  
else:  
hour += 24  
 
# munge hours and minutes if they're < 10  
if hour < 10:  
hour = "0" + str(hour)  
 
clock_time = str(hour) + ":" + minute + ":00"  
seconds = transitfeed.TimeToSecondsSinceMidnight(clock_time)  
trip_stops.append((seconds, routedata['time_points'][i]) )  
elif re.search(r'^\-$', str(stop_time)):  
pass  
else:  
class InvalidStopTimeError(Exception): pass  
raise InvalidStopTimeError, 'Bad stoptime "%s"' % stop_time  
i = i + 1  
 
trip_stops.sort() # Sort by time  
prev_stop_code = None  
between_stops = routedata.get('between_stops')  
 
for (time, stop_code) in trip_stops:  
if prev_stop_code and between_stops:  
between_stop_list = between_stops.get('%s-%s' % (prev_stop_code, stop_code))  
if between_stop_list:  
for between_stop_code in between_stop_list:  
t.AddStopTime(stop=stops[between_stop_code])  
 
t.AddStopTime(stop=stops[stop_code], arrival_secs=time,  
departure_secs=time)  
prev_stop_code = stop_code  
 
 
 
def AddRouteToSchedule(schedule, routedata):  
r = schedule.AddRoute(short_name=str(routedata['short_name']),  
long_name=routedata['long_name'],  
route_type='Bus')  
AddTripsToSchedule(schedule, r, routedata, "weekday", routedata['stop_times'])  
if routedata.get('stop_times_saturday'):  
AddTripsToSchedule(schedule, r, routedata, "saturday", routedata['stop_times_saturday'])  
if routedata.get('stop_times_sunday'):  
AddTripsToSchedule(schedule, r, routedata, "sunday", routedata['stop_times_sunday'])  
 
def main():  
parser = OptionParser()  
parser.add_option('--input', dest='input',  
help='Path of input file')  
parser.add_option('--output', dest='output',  
help='Path of output file, should end in .zip')  
parser.set_defaults(output='feed.zip')  
(options, args) = parser.parse_args()  
 
schedule = transitfeed.Schedule()  
stream = open(options.input, 'r')  
data = yaml.load(stream)  
ProcessOptions(schedule, data['options'])  
PruneStops(data['stops'], data['routes'])  
AddStops(schedule, data['stops'])  
 
for route in data['routes']:  
AddRouteToSchedule(schedule, route)  
 
schedule.WriteGoogleTransitFeed(options.output)  
 
 
if __name__ == '__main__':  
main()  
 
options:  
start_date: 20080315  
end_date: 20081215  
remove_date: 20080704  
agency_name: Halifax Metro Transit  
agency_url: http://www.halifax.ca/metrotransit/  
agency_timezone: America/Halifax  
 
stops:  
# the following waypoints are derived from google maps / google earth  
- { name: Robie & Lady Hammond, stop_code: 8208, lat: 44.6647155, lng: -63.61677 }  
- { name: Kearney Lake & Grosvenor, stop_code: 7019, lat: 44.681611, lng: -63.667767 }  
- { name: Kearney Lake & Wedgewood, stop_code: 7023, lat: 44.681611, lng: -63.667767 }  
- { name: Lacewood Terminal, stop_code: 7087, lat: 44.661511, lng: -63.656975 }  
- { name: Lacewood Terminal, stop_code: 7086, lat: 44.661511, lng: -63.656975 }  
- { name: Mumford Road & Joseph Howe, stop_code: 6612, lat: 44.648528, lng: -63.629597 }  
- { name: Alma & Dutch Village, stop_code: 6032, lat: 44.659581, lng: -63.630681 }  
- { name: Dunbrack & Main, stop_code: 6597, lat: 44.652714, lng: -63.649692 }  
- { name: Joseph Howe Manor, stop_code: 8430, lat: 44.634822, lng: -63.576186 }  
- { name: J.H. MacKenzie Manor, stop_code: 6791, lat: 44.637589, lng: -63.571281 }  
- { name: Gordon B. Isnor Manor, stop_code: 6505, lat: 44.651589, lng: -63.585292 }  
- { name: Ross Street & Dunbrack, stop_code: 6601, lat: 44.676468, lng: -63.66354 }  
- { name: Dutch Village & Deal Street, stop_code: 6611, lat: 44.659069, lng: -63.631546 }  
- { name: Downs & Milson, stop_code: 6578, lat: 44.641788, lng: -63.636932 }  
- { name: Chebucto & Oxford (north bound), stop_code: 6396, lat: 44.648689, lng: -63.601871 }  
- { name: Chebucto & Oxford (south bound), stop_code: 6397, lat: 44.648689, lng: -63.601871 }  
- { name: Point Pleasant Park, stop_code: 8649, lat: 44.625298, lng: -63.56406 }  
- { name: Tower Road Turing Loop, stop_code: 8409, lat: 44.6259, lng: -63.574524 }  
# the following waypoints are derived from geobase  
- { name: Sunnyside (Bedford Highway & Dartmouth), stop_code: 6236, lat: 44.731726, lng: -63.657578 }  
- { name: Sunnyside (Bedford Highway & Dartmouth), stop_code: 6238, lat: 44.731726, lng: -63.657578 }  
- { name: Stonehaven & Glenmore, stop_code: 8361, lat: 44.635224, lng: -63.630198 }  
- { name: Seton Road & Bedford Highway (Mount Saint Vincent University), stop_code: 6216, lat: 44.670526, lng: -63.641589 }  
- { name: Seton Road & Bedford Highway (Mount Saint Vincent University), stop_code: 6219, lat: 44.670526, lng: -63.641589 }  
- { name: Walker Avenue & Old Sackville Road (Sackville Terminal), stop_code: 8260, lat: 44.769474, lng: -63.696749 }  
- { name: Cobequid Drive and Memory Lane (Cobequid Terminal), stop_code: 8646, lat: 44.753835, lng: -63.66313 }  
- { name: Cobequid Drive and Memory Lane (Cobequid Terminal), stop_code: 6445, lat: 44.753835, lng: -63.66313 }  
- { name: Ash Lake & Chain Lake Drive (TeleTech), stop_code: 6390, lat: 44.637817, lng: -63.664118 }  
- { name: Victoria Road & Highfield Park Drive (Highfield Terminal), stop_code: 6923, lat: 44.682821, lng: -63.590579 }  
- { name: Victoria Road & Highfield Park Drive (Highfield Terminal), stop_code: 6918, lat: 44.682821, lng: -63.590579 }  
- { name: Macdonald Avenue & Ilsley Avenue (near Metro Transit H.Q.), stop_code: 6949, lat: 44.695728, lng: -63.583946 }  
- { name: Macdonald Avenue & Ilsley Avenue (near Metro Transit H.Q.), stop_code: 7205, lat: 44.695728, lng: -63.583946 }  
- { name: Wright Avenue & Macdonald, stop_code: 7153, lat: 44.701754, lng: -63.600508 }  
- { name: Akerley & Colford, stop_code: 6767, lat: 44.716152, lng: -63.586565 }  
- { name: Cowie Hill & Ridge Valley, stop_code: 8167, lat: 44.63064, lng: -63.622718 }  
- { name: Cowie Hill & Ridge Valley, stop_code: 8168, lat: 44.63064, lng: -63.622718 }  
- { name: Juniper Crescent & Leiblin Drive, stop_code: 7143, lat: 44.595027, lng: -63.636932 }  
 
# major timepoints for the 20  
# this is a big lie... I have no actual idea exactly where the dockyards are  
# (not really wanting to waltz around a military installation with a gps),  
# and decided to put them on some random place on provo wallis  
- { name: Dockyard, stop_code: 6568, lat: 44.654879, lng: -63.580571, bad: 1 }  
- { name: Dockyard, stop_code: 6572, lat: 44.654879, lng: -63.580571, bad: 1 }  
- { name: Greystone (turning loop), stop_code: 6797, lat: 44.599446, lng: -63.614456 }  
- { name: Greystone (turning loop), stop_code: 6800, lat: 44.599446, lng: -63.614456 }  
- { name: Herring Cove & Fotherby, stop_code: 6851, lat: 44.588541, lng: -63.593062 }  
- { name: Herring Cove & Fotherby, stop_code: 6859, lat: 44.588541, lng: -63.593062 }  
- { name: Herring Cove (St. Paul's Ave & School), stop_code: 7121, lat: 44.571368, lng: -63.561739 }  
# the following waypoints are derived from openstreetmap  
- { name: Titus & Main, stop_code: 7166, lat: 44.6594, lng: -63.6343 }  
- { name: Spring Garden & South Park, stop_code: 8308, lat: 44.6422, lng: -63.5797 }  
- { name: Romans & Bayers, stop_code: 6197, lat: 44.6526, lng: -63.6214 }  
- { name: Coleman & Bayers, stop_code: 6193, lat: 44.6516, lng: -63.6178 }  
- { name: Connolly & Bayers, stop_code: 6203, lat: 44.6530, lng: -63.6132 }  
- { name: Upper Water & Cornwallis, stop_code: 8414, lat: 44.6539, lng: -63.5814 }  
- { name: Oxford & Young, stop_code: 7423, lat: 44.6543, lng: -63.6097 }  
- { name: Larry Uteck Boulevard & Bedford Highway, stop_code: 7125, lat: 44.6989, lng: -63.6639 }  
- { name: Dorothea & Lucien, stop_code: 6575, lat: 44.6784, lng: -63.5109, bad: 1 }  
- { name: Penhorn Terminal, stop_code: 7445, lat: 44.6730, lng: -63.5413, bad: 1 }  
- { name: Alderney Ferry Terminal, stop_code: 6031, lat: 44.6645, lng: -63.5685 }  
- { name: South & LeMarchant, stop_code: 7144, lat: 44.6359, lng: -63.5895 }  
- { name: Robie & Young, stop_code: 8269, lat: 44.6597, lng: -63.6021 }  
- { name: Robie & Spring Garden (north bound), stop_code: 8185, lat: 44.6407, lng: -63.5867 }  
- { name: Summer Street (QEII Health Sciences), stop_code: 8363, lat: 44.6457, lng: -63.5856, bad: 1 }  
- { name: Chain Lake & Lakelands, stop_code: 6160, lat: 44.6375, lng: -63.6691 }  
- { name: Greenwood Heights, stop_code: 6315, lat: 44.6553, lng: -63.7361, bad: 1 }  
- { name: Glengary Gardens, stop_code: 6722, lat: 44.6605, lng: -63.7467, bad: 1 }  
- { name: Summer Street (QEII Health Sciences), stop_code: 8364, lat: 44.6457, lng: -63.5856, bad: 1 }  
- { name: Chain Lake & Lakelands, stop_code: 6189, lat: 44.6375, lng: -63.6691 }  
- { name: Greenwood Heights, stop_code: 6317, lat: 44.6553, lng: -63.7361, bad: 1 }  
 
# the following were taken by wlach's GPS device  
 
# mumford rd. and chebucto, moving to terminal (going downtown afterwards)  
- { name: Mumford & Chebucto, stop_code: 7276, lat: 44.64591, lng: -63.61571 }  
 
# mumford rd. and chebucto, moving out of terminal (going away from dwntwn)  
- { name: Mumford & Leppert, stop_code: 7273, lat: 44.64604, lng: -63.61616 }  
 
# robie stops  
- { name: Robie & Spring Garden, stop_code: 8332, lat: 44.64055, lng: -63.58652 }  
- { name: Robie & Binney (north bound), stop_code: 8219, lat: 44.64235, lng: -63.58776 }  
- { name: Robie & Cherry (north bound), stop_code: 8179, lat: 44.64426, lng: -63.58869 }  
- { name: North & Gottingen, stop_code: 7346, lat: 44.65704, lng: -63.59146 }  
- { name: North & Gottingen, stop_code: 6781, lat: 44.65768, lng: -63.59172 }  
- { name: North & Gottingen, stop_code: 6769, lat: 44.65748, lng: -63.59123 }  
- { name: Robie & Bliss (south bound), stop_code: 8194, lat: 44.64158, lng: -63.58758 }  
- { name: Robie & Jubilee (south bound), stop_code: 8195, lat: 44.64328, lng: -63.58837 }  
- { name: Robie & Cherry (south bound), stop_code: 8196, lat: 44.64467, lng: -63.58923 }  
- { name: Robie & Shirley (south bound), stop_code: 8183, lat: 44.64612, lng: -63.59004 }  
- { name: Robie & Quinpool (south bound), stop_code: 8214, lat: 44.64768, lng: -63.59078 }  
- { name: Robie & Welsford (south bound), stop_code: 8190, lat: 44.64857, lng: -63.59114 }  
- { name: Robie & Cunard (south bound), stop_code: 8205, lat: 44.65038, lng: -63.59227 }  
- { name: Robie & Charles (south bound), stop_code: 8178, lat: 44.65305, lng: -63.59373 }  
- { name: Robie & North (south bound), stop_code: 8213, lat: 44.65498, lng: -63.59537 }  
- { name: Robie & May (south bound), stop_code: 8182, lat: 44.65603, lng: -63.59684 }  
- { name: Robie & Almon (south bound), stop_code: 8202, lat: 44.65759, lng: -63.59930 }  
- { name: Robie & Young (south bound), stop_code: 8193, lat: 44.65899, lng: -63.60136 }  
 
- { name: Robie & North, stop_code: 7341, lat: 44.65499, lng: -63.59449 }  
- { name: North & Windsor, stop_code: 7358, lat: 44.65234, lng: -63.59830 }  
- { name: North & Clifton, stop_code: 7353, lat: 44.65381, lng: -63.59615 }  
 
- { name: North & Gottingen, stop_code: 7347, lat: 44.65706, lng: -63.59150 }  
- { name: North & Maynard, stop_code: 7354, lat: 44.65610, lng: -63.59275 }  
- { name: North & Robie, stop_code: 7342, lat: 44.65448, lng: -63.59507 }  
- { name: North & Clifton, stop_code: 7352, lat: 44.65361, lng: -63.59630 }  
- { name: North & Windsor, stop_code: 7357, lat: 44.65211, lng: -63.59844 }  
- { name: Robie & Quinpool (north bound), stop_code: 8184, lat: 44.64795, lng: -63.59068 }  
- { name: Robie & Cunard (north bound), stop_code: 8206, lat: 44.65001, lng: -63.59176 }  
- { name: Robie & Garrick (north bound), stop_code: 8221, lat: 44.65171, lng: -63.59281 }  
- { name: Robie & Willow (north bound), stop_code: 8222, lat: 44.65372, lng: -63.59403 }  
- { name: Robie & North (north bound), stop_code: 8181, lat: 44.65494, lng: -63.59510 }  
- { name: Robie & May (north bound), stop_code: 8210, lat: 44.65609, lng: -63.59674 }  
- { name: Robie & Almon (north bound), stop_code: 8201, lat: 44.65724, lng: -63.59846 }  
- { name: Robie & Russell (north bound), stop_code: 8251, lat: 44.65879, lng: -63.60080 }  
 
- { name: North & Brunswick, stop_code: 7348, lat: 44.65833, lng: -63.59029 }  
- { name: Novalea & Duffus, stop_code: 6583, lat: 44.66729, lng: -63.60655 }  
- { name: Gottingen & Black, stop_code: 6785, lat: 44.65825, lng: -63.59252 }  
- { name: Gottingen & Bloomfield, stop_code: 6768, lat: 44.65982, lng: -63.59452 }  
- { name: Gottingen & Macara, stop_code: 6782, lat: 44.66113, lng: -63.59659 }  
# all of these are headed towards the mackay bridge  
- { name: Novalea & Livingstone, stop_code: 7377, lat: 44.66388, lng: -63.60046 }  
- { name: Novalea & Stanley, stop_code: 7381, lat: 44.66479, lng: -63.60187 }  
- { name: Novalea & Cabot, stop_code: 7374, lat: 44.66624, lng: -63.60420 }  
- { name: Novalea & Devonshire, stop_code: 7369, lat: 44.66717, lng: -63.60568 }  
- { name: Novalea & Vestby, stop_code: 7373, lat: 44.66871, lng: -63.60773 }  
- { name: Novalea & Leeds, stop_code: 7376, lat: 44.67042, lng: -63.61035 }  
- { name: Novalea (Samuel Prince Manor), stop_code: 7380, lat: 44.67160, lng: -63.61214 }  
- { name: Novalea (Samuel Prince Manor), stop_code: 7379, lat: 44.67160, lng: -63.61214 }  
- { name: Novalea (Samuel Prince Manor), stop_code: 7378, lat: 44.67176, lng: -63.61225 }  
# the following three are headed AWAY from the mackay bridge  
- { name: Novalea (Samuel Prince Manor), stop_code: 7367, lat: 44.67160, lng: -63.61234 }  
- { name: Novalea (Samuel Prince Manor), stop_code: 7368, lat: 44.67160, lng: -63.61234 }  
- { name: Novalea & Vestby, stop_code: 7382, lat: 44.66854, lng: -63.60771 }  
- { name: Novalea & Duffus, stop_code: 7370, lat: 44.66755, lng: -63.60648 }  
- { name: Novalea & Cabot, stop_code: 7362, lat: 44.66645, lng: -63.60485 }  
- { name: Novalea & Stanley, stop_code: 7365, lat: 44.66493, lng: -63.60239 }  
- { name: Novalea & Livingstone, stop_code: 7364, lat: 44.66404, lng: -63.60110 }  
- { name: Gottingen & Young, stop_code: 6770, lat: 44.66227, lng: -63.59841 }  
- { name: Gottingen & Sullivan, stop_code: 6783, lat: 44.66177, lng: -63.59768 }  
- { name: Gottingen & Almon, stop_code: 6776, lat: 44.66018, lng: -63.59534 }  
- { name: Gottingen & Black, stop_code: 6777, lat: 44.65850, lng: -63.59289 }  
- { name: North & Brunswick, stop_code: 7351, lat: 44.65810, lng: -63.58967 }  
- { name: North & Barrington (south bound), stop_code: 7343, lat: 44.65865, lng: -63.58818 }  
- { name: Barrington & Duke (south bound), stop_code: 6105, lat: 44.64973, lng: -63.57519 }  
- { name: Barrington & Duke (north bound), stop_code: 6087, lat: 44.65066, lng: -63.57561 }  
# headed towards the north end on barrington  
- { name: Barrington & Duke (north bound), stop_code: 6086, lat: 44.65041, lng: -63.57559 }  
- { name: Barrington & Cornwallis (north bound), stop_code: 6089, lat: 44.65436, lng: -63.58181 }  
# on barrington and north, just east of the macdonald bridge  
- { name: Barrington & North, stop_code: 6116, lat: 44.65875, lng: -63.58761 }  
# ditto, just west of the bridge  
- { name: Barrington & North, stop_code: 6091, lat: 44.66043, lng: -63.58963 }  
# headed west on barrington from north, up towards duffus (following the 9)  
- { name: Barrington & Russell, stop_code: 6127, lat: 44.66310, lng: -63.59233 }  
 
# now headed towards the macdonald bridge from the west, on barrington  
- { name: Barrington & Russell (south bound), stop_code: 6090, lat: 44.66327, lng: -63.59279 }  
- { name: Barrington (south bound), stop_code: 6107, lat: 44.66067, lng: -63.59007 }  
- { name: Barrington & North (south bound), stop_code: 6115, lat: 44.65940, lng: -63.58880 }  
- { name: Gottingen & Young (north bound), stop_code: 7366, lat: 44.66267, lng: -63.59887 }  
- { name: North & Brunswick (south bound), stop_code: 8638, lat: 44.65853, lng: -63.58986 }  
- { name: Barrington (south bound), stop_code: 6088, lat: 44.65675, lng: -63.58524 }  
- { name: Barrington & Cornwallis (south bound), stop_code: 6104, lat: 44.65441, lng: -63.58209 }  
- { name: Barrington & Cornwallis (south bound), stop_code: 6125, lat: 44.65348, lng: -63.58080 }  
- { name: Northridge Road (Richmond Manor), stop_code: 8165, lat: 44.67192, lng: -63.61618 }  
- { name: Northridge Road (Richmond Manor), stop_code: 8164, lat: 44.67193, lng: -63.61618 }  
- { name: Novalea & Sentinel, stop_code: 7361, lat: 44.67318, lng: -63.61473 }  
- { name: Novalea & Ridge, stop_code: 7360, lat: 44.67323, lng: -63.61551 }  
 
- { name: Windsor & Charles (south bound), stop_code: 8559, lat: 44.65146, lng: -63.59704 }  
- { name: Hunter & Cunard (south bound), stop_code: 6545, lat: 44.65035, lng: -63.59433 }  
- { name: Hunter & Cunard (north bound), stop_code: 6544, lat: 44.65039, lng: -63.59469 }  
- { name: Windsor & Charles (north bound), stop_code: 8558, lat: 44.65127, lng: -63.59656 }  
 
- { name: Windsor & North (north bound), stop_code: 8554, lat: 44.65252, lng: -63.59893 }  
- { name: Windsor & Summit (north bound), stop_code: 8568, lat: 44.65307, lng: -63.60000 }  
- { name: Windsor & Almon (north bound), stop_code: 8556, lat: 44.65420, lng: -63.60240 }  
- { name: Windsor & London (north bound), stop_code: 8572, lat: 44.65505, lng: -63.60432 }  
- { name: Windsor & Young (north bound), stop_code: 8571, lat: 44.65581, lng: -63.60568 }  
 
- { name: Windsor & Bayers (north bound), stop_code: 8574, lat: 44.65717, lng: -63.60773 }  
- { name: Windsor & Ashton (north bound), stop_code: 8550, lat: 44.65829, lng: -63.60944 }  
- { name: Windsor & Maxwell (north bound), stop_code: 8549, lat: 44.66015, lng: -63.61264 }  
- { name: Windsor & Hood (north bound), stop_code: 8567, lat: 44.66087, lng: -63.61576 }  
- { name: Windsor & Connolly (north bound), stop_code: 8570, lat: 44.66040, lng: -63.61868 }  
- { name: Windsor & Strawberry (north bound), stop_code: 8552, lat: 44.66066, lng: -63.62020 }  
 
- { name: Windsor & Kempt (north bound), stop_code: 8563, lat: 44.66192, lng: -63.62175 }  
- { name: Windsor & Kempt (north bound), stop_code: 8553, lat: 44.66236, lng: -63.62236 }  
- { name: Windsor & Connaught, stop_code: 8560, lat: 44.66040, lng: -63.62022 }  
 
- { name: Windsor & Connolly (south bound), stop_code: 8551, lat: 44.66026, lng: -63.61910 }  
- { name: Windsor & Hood (south bound), stop_code: 8562, lat: 44.66074, lng: -63.61580 }  
- { name: Windsor & Maxwell (south bound), stop_code: 8565, lat: 44.66006, lng: -63.61291 }  
- { name: Windsor & Ashton (south bound), stop_code: 8573, lat: 44.65826, lng: -63.60962 }  
- { name: Windsor & Bayers (south bound), stop_code: 8555, lat: 44.65711, lng: -63.60793 }  
 
- { name: Windsor & Young (south bound), stop_code: 8561, lat: 44.65604, lng: -63.60638 }  
- { name: Windsor & London (south bound), stop_code: 8564, lat: 44.65511, lng: -63.60471 }  
- { name: Windsor & Almon (south bound), stop_code: 8557, lat: 44.65430, lng: -63.60298 }  
# - { name: Windsor & Summit (south bound), stop_code: 856x, lat: 44.65322, lng: -63.60061 }  
- { name: Windsor & North (south bound), stop_code: 8566, lat: 44.65227, lng: -63.59863 }  
 
- { name: Cogswell & Brunswick (north bound), stop_code: 6455, lat: 44.65094, lng: -63.57983 }  
- { name: Cogswell & Gottingen (north bound), stop_code: 6773, lat: 44.65095, lng: -63.58157 }  
- { name: Gottingen & Cornwallis (north bound), stop_code: 6778, lat: 44.65198, lng: -63.58330 }  
- { name: Gottingen & Cunard (north bound), stop_code: 6779, lat: 44.65325, lng: -63.58519 }  
- { name: Gottingen & Gerrish (north bound), stop_code: 6775, lat: 44.65407, lng: -63.58622 }  
- { name: Gottingen & Charles (north bound), stop_code: 6787, lat: 44.65573, lng: -63.58866 }  
 
- { name: Gottingen & Charles (south bound), stop_code: 6774, lat: 44.65557, lng: -63.58865 }  
- { name: Gottingen & Gerrish (south bound), stop_code: 6780, lat: 44.65489, lng: -63.58771 }  
- { name: Gottingen & Cunard (south bound), stop_code: 6786, lat: 44.65361, lng: -63.58581 }  
- { name: Gottigen & Cornwallis (south bound), stop_code: 6790, lat: 44.65200, lng: -63.58332 }  
- { name: Gottingen & Falkland (south bound), stop_code: 6771, lat: 44.65089, lng: -63.58185 }  
 
# following stops are for routes heading from dartmouth to mumford  
- { name: North & Dublin, stop_code: 7344, lat: 44.65061, lng: -63.60074 }  
- { name: North & Oxford, stop_code: 7356, lat: 44.64929, lng: -63.60253 }  
- { name: Chebucto & Connolly, stop_code: 6405, lat: 44.64818, lng: -63.60497 }  
- { name: Chebucto & Connaught, stop_code: 6404, lat: 44.64759, lng: -63.60729 }  
- { name: Chebucto & Arm Crescent, stop_code: 6413, lat: 44.64631, lng: -63.61047 }  
- { name: Chebucto & Quinn, stop_code: 6414, lat: 44.64602, lng: -63.61234 }  
- { name: Mumford & Chebucto, stop_code: 7275, lat: 44.64592, lng: -63.61570 }  
- { name: Mumford Terminal, stop_code: 7284, lat: 44.64786, lng: -63.62035 }  
- { name: Mumford Terminal, stop_code: 7285, lat: 44.64786, lng: -63.62035 }  
- { name: Mumford Terminal, stop_code: 8643, lat: 44.64786, lng: -63.62035 }  
 
# following stops are for routes heading from mumford towards dartmouth  
- { name: Mumford & Leppert, stop_code: 7274, lat: 44.64599, lng: -63.61618 }  
- { name: Chebucto & Quinn, stop_code: 6409, lat: 44.64571, lng: -63.61272 }  
- { name: Chebucto & Arm Crescent, stop_code: 6403, lat: 44.64599, lng: -63.61064 }  
- { name: Chebucto & Newton, stop_code: 6407, lat: 44.64664, lng: -63.60843 }  
- { name: Chebucto & Elm, stop_code: 6406, lat: 44.64787, lng: -63.60564 }  
- { name: North & Oxford, stop_code: 7355, lat: 44.64896, lng: -63.60284 }  
- { name: North & Dublin, stop_code: 7345, lat: 44.65013, lng: -63.60110 }  
 
# following stops are for routes heading from scotia square towards spring garden  
- { name: Barrington & George, stop_code: 6108, lat: 44.64848, lng: -63.57482 }  
- { name: Barrington & Prince, stop_code: 6084, lat: 44.64760, lng: -63.57435 }  
- { name: Barrington & Sackville, stop_code: 6103, lat: 44.64660, lng: -63.57368 }  
- { name: Barrington & Blowers, stop_code: 6102, lat: 44.64557, lng: -63.57322 }  
- { name: Barrington & Spring Garden, stop_code: 6122, lat: 44.64454, lng: -63.57279 }  
 
# following stops heading from scotia square to water street terminal / ferry terminal  
- { name: George & Hollis, stop_code: 6733, lat: 44.64851, lng: -63.57341 }  
- { name: Water Street Terminal, stop_code: 8435, lat: 44.64922, lng: -63.57225 }  
 
# following stops are for routes heading on spring garden, barrington to robie  
- { name: Spring Garden & Queen, stop_code: 8331, lat: 44.64348, lng: -63.57551 }  
- { name: Spring Garden & Dresden Row, stop_code: 8330, lat: 44.64288, lng: -63.57759 }  
- { name: Spring Garden & South Park, stop_code: 8334, lat: 44.64247, lng: -63.57942 }  
- { name: Spring Garden & Summer, stop_code: 8335, lat: 44.64144, lng: -63.58316 }  
- { name: Spring Garden & Carlton, stop_code: 8329, lat: 44.64105, lng: -63.58481 }  
 
# following stop data was collected going along robie, onto south, onto barrington  
- { name: Robie & Coburg, stop_code: 8186, lat: 44.63979, lng: -63.58671 }  
- { name: Robie & University, stop_code: 8188, lat: 44.63776, lng: -63.58559 }  
- { name: Robie & South, stop_code: 8296, lat: 44.63665, lng: -63.58400 }  
- { name: South & Wellington, stop_code: 8303, lat: 44.63715, lng: -63.58187 }  
- { name: South & Tower, stop_code: 8305, lat: 44.63778, lng: -63.57941 }  
- { name: South & South Park, stop_code: 8295, lat: 44.63840, lng: -63.57627 }  
- { name: South & Queen, stop_code: 8299, lat: 44.63886, lng: -63.57421 }  
- { name: South & Barrington, stop_code: 8293, lat: 44.63972, lng: -63.57165 }  
- { name: South & Barrington, stop_code: 6096, lat: 44.64023, lng: -63.57041 }  
- { name: Barrington & Morris, stop_code: 6113, lat: 44.64155, lng: -63.57109 }  
- { name: Barrington & Spring Garden, stop_code: 6124, lat: 44.64404, lng: -63.57232 }  
 
# following stop is what you get continuing into south, towards lemarchant  
- { name: Robie & South, stop_code: 8317, lat: 44.63633, lng: -63.58584 }  
 
# following stop data was collected going along barrington, onto south, onto robie  
- { name: Barrington & Morris, stop_code: 6114, lat: 44.64188, lng: -63.57140 }  
- { name: Barrington & South, stop_code: 6097, lat: 44.64024, lng: -63.57055 }  
- { name: South & Church, stop_code: 8294, lat: 44.63949, lng: -63.57253 }  
- { name: South & Queen, stop_code: 8292, lat: 44.63894, lng: -63.57462 }  
- { name: South & South Park, stop_code: 8300, lat: 44.63836, lng: -63.57711 }  
- { name: South & Tower, stop_code: 8301, lat: 44.63795, lng: -63.57863 }  
- { name: South & Wellington, stop_code: 8298, lat: 44.63723, lng: -63.58183 }  
- { name: South & Robie, stop_code: 8297, lat: 44.63684, lng: -63.58358 }  
- { name: South & Robie, stop_code: 8220, lat: 44.63685, lng: -63.58488 }  
- { name: Robie & University, stop_code: 8187, lat: 44.63857, lng: -63.58576 }  
 
# ~quinpool and oxford, heading to spring garden and robie  
- { name: Quinpool & Oxford, stop_code: 7412, lat: 44.64424, lng: -63.60031 }  
- { name: Oxford & Norwood, stop_code: 7419, lat: 44.64296, lng: -63.59948 }  
- { name: Oxford & Jubilee, stop_code: 7409, lat: 44.64031, lng: -63.59805 }  
- { name: Oxford & Jennings, stop_code: 7402, lat: 44.63898, lng: -63.59738 }  
- { name: Coburg & Oxford, stop_code: 6453, lat: 44.63778, lng: -63.59617 }  
- { name: Coburg & Lilac, stop_code: 6447, lat: 44.63842, lng: -63.59361 }  
- { name: Coburg & Lemarchant, stop_code: 6449, lat: 44.63903, lng: -63.59137 }  
- { name: Coburg & Henry, stop_code: 6454, lat: 44.63957, lng: -63.58905 }  
- { name: Coburg & Robie, stop_code: 6452, lat: 44.64007, lng: -63.58723 }  
 
# from ~ Young and Robie to the Bedford Hwy  
- { name: Young & Monaghan, stop_code: 8629, lat: 44.65816, lng: -63.60450 }  
- { name: Young & Windsor, stop_code: 8634, lat: 44.65684, lng: -63.60654 }  
- { name: Bayers & Dublin, stop_code: 6192, lat: 44.65630, lng: -63.60857 }  
- { name: Bayers & Oxford, stop_code: 6196, lat: 44.65519, lng: -63.60994 }  
- { name: Bayers & Connolly, stop_code: 6201, lat: 44.65365, lng: -63.61245 }  
- { name: Bayers & Connaught, stop_code: 6200, lat: 44.65252, lng: -63.61456 }  
- { name: Bayers & Vaughan, stop_code: 6199, lat: 44.65202, lng: -63.61846 }  
- { name: Bayers & Romans, stop_code: 6198, lat: 44.65318, lng: -63.62294 }  
# forgot to get the stop code for this one, it's between  
#- { name: Village at Bayers Road, stop_code: xxxx, lat: 44.65380, lng: -63.62662 }  
- { name: Village at Bayers Road, stop_code: 6563, lat: 44.65469, lng: -63.62804 }  
- { name: Desmond & Scott, stop_code: 6565, lat: 44.65629, lng: -63.62758 }  
- { name: Joseph Howe & Dutch Village, stop_code: 6984, lat: 44.65830, lng: -63.62902 }  
- { name: Joseph Howe & Dutch Village, stop_code: 6983, lat: 44.66037, lng: -63.62809 }  
 
# from ~bedford highway to young and robie (partial)  
- { name: Joseph Howe & Dutch Village, stop_code: 6982, lat: 44.65839, lng: -63.62920 }  
- { name: Joseph Howe & Scot, stop_code: 6985, lat: 44.65692, lng: -63.62963 }  
- { name: Scot & Desmond, stop_code: 8262, lat: 44.65638, lng: -63.62809 }  
- { name: Village at Bayers Road, stop_code: 6564, lat: 44.65470, lng: -63.62797 }  
- { name: Young & Monaghan, stop_code: 8633, lat: 44.65808, lng: -63.60435 }  
 
# robie -> barrington on spring garden  
- { name: Spring Garden & Carlton, stop_code: 8328, lat: 44.64091, lng: -63.58551 }  
- { name: Spring Garden & Summer, stop_code: 8337, lat: 44.64141, lng: -63.58288 }  
- { name: Spring Garden & South Park, stop_code: 8333, lat: 44.64217, lng: -63.57999 }  
- { name: Spring Garden & Dresden Row, stop_code: 8336, lat: 44.64302, lng: -63.57741 }  
- { name: Spring Garden & Queen, stop_code: 8327, lat: 44.64342, lng: -63.57547 }  
- { name: Spring Garden & Barrington, stop_code: 8338, lat: 44.64393, lng: -63.57325 }  
 
# barrington, from spring garden to duke  
- { name: Barrington & Sackville, stop_code: 6121, lat: 44.64590, lng: -63.57344 }  
# I have marked down 6086 as being the gotime id for the stop below, but  
# that can't be right: 6086 is for barrington & duke (south bound). the  
# schedules say so  
#- { name: Barrington & Prince, stop_code: xxxx, lat: 44.64671, lng: -63.57383 }  
- { name: Barrington & George, stop_code: 6106, lat: 44.64871, lng: -63.57474 }  
 
# dartmouth  
- { name: Bridge Terminal (Dartmouth Sportsplex), stop_code: 6842, lat: 44.67016, lng: -63.57624 }  
- { name: Bridge Terminal (Dartmouth Sportsplex), stop_code: 7151, lat: 44.67016, lng: -63.57624 }  
- { name: Bridge Terminal (Dartmouth Sportsplex), stop_code: 8640, lat: 44.67016, lng: -63.57624 }  
- { name: Bridge Terminal (Dartmouth Sportsplex), stop_code: 8641, lat: 44.67016, lng: -63.57624 }  
- { name: Bridge Terminal (Dartmouth Sportsplex), stop_code: 8642, lat: 44.67016, lng: -63.57624 }  
 
# following the #10, from bridge terminal to mic mac mall  
- { name: Wyse & Dawson, stop_code: 8616, lat: 44.67162, lng: -63.58015 }  
- { name: Boland & Cairn, stop_code: 6304, lat: 44.67344, lng: -63.57982 }  
- { name: Boland & Victoria, stop_code: 6303, lat: 44.67510, lng: -63.57797 }  
- { name: Boland & Frances, stop_code: 8428, lat: 44.67642, lng: -63.57897 }  
- { name: Slayter & Woodland, stop_code: 8587, lat: 44.67776, lng: -63.57929 }  
- { name: Sheridan & Woodland, stop_code: 8580, lat: 44.67969, lng: -63.57693 }  
- { name: Frederick & Woodland, stop_code: 8586, lat: 44.68060, lng: -63.57579 }  
- { name: Laurier & Woodland, stop_code: 8582, lat: 44.68202, lng: -63.57399 }  
- { name: Woodland & Micmac, stop_code: 7214, lat: 44.68501, lng: -63.56801 }  
- { name: Micmac & Glencarin, stop_code: 7213, lat: 44.68667, lng: -63.56355 }  
- { name: Mic Mac Terminal (Mic Mac Mall), stop_code: 7219, lat: 44.68536, lng: -63.56081 }  
 
# following the #10, Micmac Mall -> Tacoma Center  
- { name: Micmac & Brookdale, stop_code: 7210, lat: 44.68456, lng: -63.55681 }  
# the following stop doesn't come between 15:30-17:30, leave it out until  
# we can express this in GTFS (or alternately, just leave this mostly  
# useless top out indefinitely-- 7173 comes right after it)  
#- { name: Main & Gordon, stop_code: 7174, lat: 44.68137, lng: -63.54327 }  
- { name: Main & Gordon, stop_code: 7173, lat: 44.68169, lng: -63.54023 }  
- { name: Main & Hartlen, stop_code: 6834, lat: 44.68168, lng: -63.53737 }  
- { name: Tacoma Center, stop_code: 8369, lat: 44.68039, lng: -63.53747 }  
 
# following the #10, Tacoma Center -> Woodlawn & Main  
- { name: Valleyfield & Oakwood, stop_code: 8416, lat: 44.67932, lng: -63.53463 }  
- { name: Spikenard & Margaree Parkway, stop_code: 8323, lat: 44.68022, lng: -63.53151 }  
- { name: Spikenard & Woodlawn, stop_code: 8320, lat: 44.68092, lng: -63.52837 }  
- { name: Spikenard & Woodlawn, stop_code: 8603, lat: 44.68174, lng: -63.52757 }  
- { name: Woodlawn & Main, stop_code: 8598, lat: 44.68351, lng: -63.52875 }  
 
# Following #10, Woodlawn & Main -> Inverary & Strath  
- { name: Booth & Main, stop_code: 6306, lat: 44.68593, lng: -63.52412 }  
- { name: Booth & Scotsburn, stop_code: 6305, lat: 44.68786, lng: -63.52550 }  
- { name: Booth & David, stop_code: 7053, lat: 44.68977, lng: -63.52740 }  
- { name: Kennedy, stop_code: 7052, lat: 44.69088, lng: -63.52839 }  
- { name: Kennedy, stop_code: 7051, lat: 44.69151, lng: -63.53071 }  
- { name: Caladonia, stop_code: 6369, lat: 44.69199, lng: -63.53286 }  
- { name: Caladonia & Dumbarton, stop_code: 6591, lat: 44.69308, lng: -63.53429 }  
- { name: Kincardine & Dumbarton, stop_code: 6592, lat: 44.69247, lng: -63.53681 }  
- { name: Kincardine & Greenoch, stop_code: 7057, lat: 44.68988, lng: -63.53612 }  
- { name: Inverary & Strath, stop_code: 6974, lat: 44.68847, lng: -63.53599 }  
 
# following #10, iverary & strath -> tacoma  
- { name: Strath & Raymoor, stop_code: 8160, lat: 44.68717, lng: -63.53591 }  
- { name: Raymoor, stop_code: 8161, lat: 44.68559, lng: -63.53323 }  
- { name: Raymoor & Main, stop_code: 8162, lat: 44.68428, lng: -63.53158 }  
- { name: Weyburn & Main, stop_code: 8483, lat: 44.68355, lng: -63.53236 }  
- { name: Weyburn & Athabaskan, stop_code: 8484, lat: 44.68215, lng: -63.53176 }  
- { name: Weyburn & Spikenard, stop_code: 8482, lat: 44.68078, lng: -63.53111 }  
- { name: Spikenard & Valleyfield, stop_code: 8319, lat: 44.67957, lng: -63.53369 }  
- { name: Tacoma Center, stop_code: 8368, lat: 44.67997, lng: -63.53717 }  
 
# following #10, tacoma -> micmac  
- { name: Hartlen & Main, stop_code: 6835, lat: 44.68165, lng: -63.53725 }  
- { name: Major & Main, stop_code: 7175, lat: 44.68195, lng: -63.54001 }  
- { name: Micmac & Brookdlae, stop_code: 7209, lat: 44.68466, lng: -63.55729 }  
- { name: Micmac & Glencairn, stop_code: 7218, lat: 44.68576, lng: -63.56118 }  
 
# following #10, micmac -> bridge terminal  
- { name: Micmac & Glencairn, stop_code: 7211, lat: 44.68671, lng: -63.56299 }  
- { name: Micmac & Woodland, stop_code: 7215, lat: 44.68532, lng: -63.56827 }  
- { name: Woodland & Laurier, stop_code: 8581, lat: 44.68175, lng: -63.57462 }  
- { name: Woodland & Pinehill, stop_code: 8583, lat: 44.68072, lng: -63.57587 }  
- { name: Woodland & Sheridan, stop_code: 8584, lat: 44.67979, lng: -63.57703 }  
- { name: Woodland & Slayter, stop_code: 8585, lat: 44.67778, lng: -63.57946 }  
- { name: Victoria & Francse, stop_code: 8424, lat: 44.67623, lng: -63.57887 }  
- { name: Victoria & Boland, stop_code: 8419, lat: 44.67515, lng: -63.57724 }  
- { name: Nantucket & Victoria, stop_code: 8429, lat: 44.67296, lng: -63.57360 }  
- { name: Thistle & Victoria, stop_code: 8427, lat: 44.67185, lng: -63.57202 }  
- { name: Thistle & Victoria, stop_code: 8389, lat: 44.67106, lng: -63.57202 }  
- { name: Wyse & Thistle, stop_code: 8392, lat: 44.66898, lng: -63.57436 }  
- { name: Wyse & Thistle, stop_code: 8614, lat: 44.66898, lng: -63.57540 }  
 
# ~coburg and Henry -> quinpool and oxford  
- { name: Coburg & Henry, stop_code: 6448, lat: 44.63967, lng: -63.58873 }  
- { name: Coburg & Lemarchant, stop_code: 6450, lat: 44.63914, lng: -63.59097 }  
- { name: Coburg & Lilac, stop_code: 6451, lat: 44.63833, lng: -63.59454 }  
- { name: Oxford & Coburg, stop_code: 7401, lat: 44.63822, lng: -63.59685 }  
- { name: Oxford & Jennings, stop_code: 7403, lat: 44.63940, lng: -63.59741 }  
- { name: Oxford & Cornwall, stop_code: 7410, lat: 44.64129, lng: -63.59843 }  
- { name: Oxford & Norwood, stop_code: 7406, lat: 44.64270, lng: -63.59924 }  
- { name: Quinpool & Oxford, stop_code: 7421, lat: 44.64444, lng: -63.60015 }  
 
# ~ quinpool and oxford, to young and oxford  
- { name: Oxford & Allan, stop_code: 7404, lat: 44.64699, lng: -63.60142 }  
 
# south & dalhousie -> spring garden & south park (following #10)  
- { name: South & Dalhousie, stop_code: 8304, lat: 44.63488, lng: -63.59253 }  
- { name: Beaufort & South, stop_code: 6206, lat: 44.63380, lng: -63.59510 }  
- { name: Beaufort & Oakland, stop_code: 6209, lat: 44.63272, lng: -63.59301 }  
- { name: Beaufort & Inglis, stop_code: 6208, lat: 44.63124, lng: -63.58960 }  
- { name: Inglis & Greenwood, stop_code: 6961, lat: 44.63194, lng: -63.58596 }  
- { name: Inglis & Robie, stop_code: 6962, lat: 44.63272, lng: -63.58260 }  
- { name: Inglis & Wellington, stop_code: 6965, lat: 44.63311, lng: -63.58089 }  
- { name: Tower & Inglis, stop_code: 6969, lat: 44.63378, lng: -63.57829 }  
- { name: South Park & Victoria, stop_code: 8314, lat: 44.63568, lng: -63.57665 }  
- { name: South Park & South, stop_code: 8306, lat: 44.63739, lng: -63.57736 }  
- { name: South Park & South, stop_code: 8307, lat: 44.63846, lng: -63.57769 }  
- { name: South Park & University, stop_code: 8309, lat: 44.64016, lng: -63.57856 }  
- { name: South Park & Spring Garden, stop_code: 8312, lat: 44.64203, lng: -63.57956 }  
 
# south park and spring garden -> robie and inglis (following #10)  
- { name: Spring Garden & South Park, stop_code: 8308, lat: 44.64172, lng: -63.57946 }  
- { name: South Park & Morris, stop_code: 8313, lat: 44.64017, lng: -63.57877 }  
- { name: South Park & South, stop_code: 8311, lat: 44.63837, lng: -63.57793 }  
- { name: South Park & Fenwick, stop_code: 8315, lat: 44.63687, lng: -63.57716 }  
# (two between stops with no gotime id #'s...)  
- { name: Inglis (SMU), stop_code: 6960, lat: 44.63326, lng: -63.58090 }  
- { name: Inglish & Robie, stop_code: 6966, lat: 44.63280, lng: -63.58262 }  
 
# robie & young -> Leeds & Rosemeade  
- { name: Robie & Young, stop_code: 8192, lat: 44.66001, lng: -63.60277 }  
- { name: Robie & Livingstone, stop_code: 8209, lat: 44.66097, lng: -63.60419 }  
- { name: Robie & Stanley, stop_code: 8217, lat: 44.66197, lng: -63.60570 }  
- { name: Robie & Cabot, stop_code: 8204, lat: 44.66341, lng: -63.60783 }  
- { name: Robie & Duffus, stop_code: 8207, lat: 44.66454, lng: -63.60950 }  
- { name: Robie & Lady Hammond, stop_code: 8180, lat: 44.66556, lng: -63.61093 }  
- { name: Robie & Normandy, stop_code: 8211, lat: 44.66670, lng: -63.61254 }  
- { name: Leeds & Rosemeade, stop_code: 7131, lat: 44.66823, lng: -63.61368 }  
 
# Leeds & Rosemeade -> Robie & Young  
- { name: Leeds & Rosemeade, stop_code: 7133, lat: 44.66856, lng: -63.61347 }  
- { name: Robie & Normandy, stop_code: 8212, lat: 44.66695, lng: -63.61309 }  
- { name: Robie & Lady Hammond, stop_code: 8208, lat: 44.66551, lng: -63.61100 }  
- { name: Robie & Cabot, stop_code: 8203, lat: 44.66370, lng: -63.60844 }  
- { name: Robie & Stanley, stop_code: 8197, lat: 44.66168, lng: -63.60543 }  
- { name: Robie & Kaye, stop_code: 8218, lat: 44.66006, lng: -63.60306 }  
 
# Quinpool & Robie -> Quinpool & Connaught  
- { name: Quinpool & Robie, stop_code: 8151, lat: 44.64716, lng: -63.59127 }  
- { name: Quinpool & Monastery, stop_code: 8138, lat: 44.64620, lng: -63.59458 }  
- { name: Quinpool & Preston, stop_code: 8148, lat: 44.64528, lng: -63.59772 }  
- { name: Quinpool & Oxford, stop_code: 8137, lat: 44.64446, lng: -63.60074 }  
- { name: Quinpool & Beech, stop_code: 8134, lat: 44.64408, lng: -63.60197 }  
- { name: Quinpool & Poplar, stop_code: 8146, lat: 44.64353, lng: -63.60386 }  
 
# Quinpool & Connaught -> Quinpool & Robie  
- { name: Quinpool & Poplar, stop_code: 8135, lat: 44.64339, lng: -63.60391 }  
- { name: Quinpool & Beech, stop_code: 8133, lat: 44.64389, lng: -63.60237 }  
- { name: Quinpool & Oxford, stop_code: 8136, lat: 44.64460, lng: -63.59996 }  
- { name: Quinpool & Preston, stop_code: 8147, lat: 44.64531, lng: -63.59756 }  
- { name: Quinpool & Vernon, stop_code: 8149, lat: 44.64639, lng: -63.59360 }  
- { name: Quinpool & Robie, stop_code: 8150, lat: 44.64702, lng: -63.59167 }  
 
# heading away from bayer's road, onto gottingen (at least for #21)  
- { name: Young & Isleville, stop_code: 8632, lat: 44.66144, lng: -63.59985 }  
 
# heading towards bayer's road, from gottingen (at least for #21)  
- { name: Young & Agricola, stop_code: 8631, lat: 44.66096, lng: -63.60080 }  
 
# robie and lady hammond -> barrington, following the #9  
- { name: Robie & Lady Hammond, stop_code: 7094, lat: 44.66531, lng: -63.60980 }  
- { name: Duffus & Isleville, stop_code: 6581, lat: 44.66669, lng: -63.60707 }  
- { name: Novalea & Duffus, stop_code: 6582, lat: 44.66782, lng: -63.60558 }  
- { name: Albert & Duffus, stop_code: 6586, lat: 44.66926, lng: -63.60375 }  
- { name: Duffus & Barrington, stop_code: 6587, lat: 44.67051, lng: -63.60189 }  
- { name: Barrington & Marginal, stop_code: 6100, lat: 44.66868, lng: -63.60024 }  
- { name: Barrington & Richmond, stop_code: 6120, lat: 44.66799, lng: -63.59873 }  
- { name: Barrington & Hannover, stop_code: 6109, lat: 44.66677, lng: -63.59710 }  
- { name: Barrington & Young, stop_code: 6095, lat: 44.66502, lng: -63.59504 }  
 
# barrington -> robie and lady hammond, following the #9  
- { name: Barrington & Young, stop_code: 6094, lat: 44.66523, lng: -63.59504 }  
- { name: Barrington & Hanover, stop_code: 6110, lat: 44.66667, lng: -63.59676 }  
- { name: Barrington & Richmond, stop_code: 6119, lat: 44.66803, lng: -63.59848 }  
- { name: Barrington & Marginal, stop_code: 6128, lat: 44.66892, lng: -63.60026 }  
- { name: Barrington & Duffus, stop_code: 6580, lat: 44.67064, lng: -63.60203 }  
- { name: Duffus & Albert, stop_code: 6588, lat: 44.66975, lng: -63.60318 }  
- { name: Duffus & Acadia, stop_code: 6584, lat: 44.66852, lng: -63.60486 }  
- { name: Duffus & Novalea, stop_code: 6583, lat: 44.66728, lng: -63.60654 }  
- { name: Duffus & Agricola, stop_code: 6585, lat: 44.66585, lng: -63.60852 }  
- { name: Robie & Lady Hammond, stop_code: 7096, lat: 44.66546, lng: -63.61008 }  
 
 
routes:  
 
#!/usr/bin/perl  
 
use strict;  
 
my $first = 1;  
while (<STDIN>) {  
if ($first) {  
$first = 0;  
print " - $_";  
} else {  
print " $_";  
}  
}  
 
#!/usr/bin/perl  
 
use strict;  
 
my $first = 1;  
my $prev_comment = 0;  
while (<STDIN>) {  
if ($_ !~ /^\#/) {  
if (!$first && !$prev_comment) {  
print ",\n";  
} else {  
$first = 0;  
$prev_comment = 0;  
}  
chomp;  
my @times = split /\ +/;  
print " [ ";  
my $first = 1;  
foreach (@times) {  
if (!$first) {  
print ", ";  
} else {  
$first = 0;  
}  
print $_;  
}  
print "]";  
} else {  
# yes, this conditional is loaded with assumptions...  
print ",\n" . $_;  
$prev_comment = 1;  
}  
}  
 
 
 Binary files a/origin-src/wlach-libroutez-272ef93.tar.gz and /dev/null differ
*.o  
*.routez  
*~  
.*.swp  
aclocal.m4  
autom4te.cache  
config.log  
config.mk  
config.status  
configure  
libroutez.so  
python/libroutez/tripgraph.py  
python/libroutez/tripgraph_wrap_py.cc  
python/libroutez/_tripgraph.so  
ruby/routez.so  
ruby/routez_wrap_rb.cc  
ruby/routez_wrap_rb.o  
tags  
examples/testgraph  
 
=== Current maintainer and primary author ===  
 
William Lachance <wrlach@gmail.com>  
 
=== Contributors ===  
 
Brandon Martin Anderson <badhill@gmail.com>  
- Core concepts of a trip planning library (in graphserver:  
http://graphserver.sourceforge.net)  
- Python OSM parsing library  
 
Peter McCurdy <petermccurdy@alumni.uwaterloo.ca>  
- Support for delaying walking to a stop at the start of a trip.  
 
Jason Madigan <jason@jasonmadigan.com>  
- Some updates to the README regarding building, and updates to  
the ruby examples.  
 
Copyright (c) 2008-2009 William Lachance, Brandon Martin Anderson, and others.  
 
Permission is hereby granted, free of charge, to any person  
obtaining a copy of this software and associated documentation  
files (the "Software"), to deal in the Software without  
restriction, including without limitation the rights to use,  
copy, modify, merge, publish, distribute, sublicense, and/or sell  
copies of the Software, and to permit persons to whom the  
Software is furnished to do so, subject to the following  
conditions:  
 
The above copyright notice and this permission notice shall be  
included in all copies or substantial portions of the Software.  
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES  
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT  
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,  
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR  
OTHER DEALINGS IN THE SOFTWARE.  
 
include config.mk  
 
default: libroutez.so examples/loadgraph examples/testgraph \  
python/libroutez/tripgraph.py python/libroutez/_tripgraph.so \  
ruby/routez.so  
 
include install.mk  
 
# Always always compile with fPIC  
CFLAGS += -fPIC  
CXXFLAGS += -fPIC  
 
# libroutez should be compiled as a shared library by default  
ifeq (${OS},MACOS)  
LDFLAGS += -dynamiclib  
else  
LDFLAGS += -shared  
endif  
 
config.mk:  
@echo "Please run ./configure. Stop."  
@exit 1  
 
%.o: %.cc  
g++ $< -c -o $@ $(CXXFLAGS) $(PYTHON_CFLAGS) $(RUBY_CFLAGS) -D WVTEST_CONFIGURED -I./include -I./wvtest/cpp -g  
@g++ $< -MM $(CXXFLAGS) $(PYTHON_CFLAGS) $(RUBY_CFLAGS) -D WVTEST_CONFIGURED -I./include -I./wvtest/cpp > $*.d  
@mv -f $*.d $*.d.tmp  
@sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d  
@sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \  
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d  
@rm -f $*.d.tmp  
 
TRIPGRAPH_OBJECTS=lib/tripgraph.o lib/trippath.o lib/tripstop.o lib/serviceperiod.o  
 
# libroutez: the main library  
libroutez.so: $(TRIPGRAPH_OBJECTS)  
g++ $(TRIPGRAPH_OBJECTS) $(LDFLAGS) -o libroutez.so -fPIC -g  
 
# python bindings  
python/libroutez/tripgraph.py python/libroutez/tripgraph_wrap_py.cc: tripgraph.i  
swig -classic -c++ -python -I./include -outdir python/libroutez -o python/libroutez/tripgraph_wrap_py.cc $<  
python/libroutez/_tripgraph.so: libroutez.so python/libroutez/tripgraph_wrap_py.o  
g++ -o $@ python/libroutez/tripgraph_wrap_py.o libroutez.so $(LDFLAGS) $(PYTHON_LDFLAGS) -fPIC  
 
# ruby bindings  
ruby/routez_wrap_rb.cc: routez.i tripgraph.i  
swig -c++ -ruby -I./include -o $@ $<  
 
ruby/routez.so: libroutez.so ruby/routez_wrap_rb.o  
g++ -o ruby/routez.so ruby/routez_wrap_rb.o libroutez.so $(LDFLAGS) $(RUBY_LDFLAGS) -I./include -fPIC  
 
# stupid test programs  
examples/loadgraph: examples/loadgraph.o libroutez.so  
g++ $< -o $@ libroutez.so -fPIC -g -I./include  
examples/testgraph: examples/testgraph.o libroutez.so  
g++ $< -o $@ libroutez.so -fPIC -g -I./include  
 
# unit test suite  
TEST_OBJS=t/tripgraph.t.o t/tripstop.t.o t/all.t.o  
WVTEST_OBJS=wvtest/cpp/wvtest.o wvtest/cpp/wvtestmain.o  
t/all.t: $(TEST_OBJS) $(WVTEST_OBJS) libroutez.so  
g++ $(TEST_OBJS) $(WVTEST_OBJS) -o $@ libroutez.so -fPIC -g  
 
.PHONY: test test-cpp test-python  
test: test-cpp test-python  
 
test-cpp: t/all.t  
LD_LIBRARY_PATH=$(PWD) valgrind --tool=memcheck wvtest/wvtestrun t/all.t  
 
test-python: python/libroutez/tripgraph.py python/libroutez/_tripgraph.so  
LD_LIBRARY_PATH=$(PWD) PYTHONPATH=$(PWD)/t:$(PWD)/python:$(PYTHONPATH) wvtest/wvtestrun python wvtest/python/wvtestmain.py pytest.py  
 
clean:  
rm -f *.so lib/*.o python/*.pyc */*.pyc examples/testgraph \  
python/libroutez/_tripgraph.so python/libroutez/tripgraph.py \  
python/libroutez/tripgraph_wrap_py.cc python/libroutez/*.o \  
ruby/routez.so ruby/*.o ruby/routez_wrap_rb.cc \  
wvtest/cpp/*.o wvtest/cpp/*.d \  
t/*.o t/*.d t/all.t *.d  
 
-include $(TRIPGRAPH_OBJECTS:.o=.d)  
 
=== About ===  
 
libroutez is a library written to help plan trips. Currently, its focus is  
on providing directions for using public transit, but it could be easily  
extended to cover other things (e.g. cycle-path planning). Specifically,  
it provides an interface to solving the following problems:  
 
- Finding the closest point in a road/transportation network to a specific  
latitude-longitude pair.  
- Finding the shortest path between two points in a road/transportation  
network.  
 
The design of libroutez is based on the following principles:  
 
- Focus on solving user and developer problems, not data structures or  
algorithms. For example, though libroutez uses the astar algorithm internally,  
we try to expose the interface to that through a simple method called  
"find_path".  
- Be extensible, but only in response to demonstrative developer need.  
- Be fast. libroutez uses an internal graph representation that, after being  
generated, can be loaded very quickly on program startup. Trips on a modest  
sized transit network can be generated in a fraction of a second on modern  
hardware (and there are plans to speed things up further).  
- Minimize memory use. Obviously the scale of public transit systems will  
incur some overhead here, but we want to be maximally useful on embedded  
systems and virtual servers where such resources may be scarce.  
- Minimize dependancies. For example, we don't assume the user wants to use a  
PostGRES database to store trip planning data (though they can if the want to).  
libroutez itself has no run-time dependancies beyond the C++ standard library.  
 
The libroutez has utility functions for converting Google Transit Feed  
(http://code.google.com/p/googletransitdatafeed) and OpenStreetMap  
(http://openstreetmap.org) data into its own format. It should be very easy  
to add a simple converter for your preferred data type.  
 
=== Setup and use ===  
 
These instructions assume you are on a UNIX-based system (e.g. Linux or  
MacOS X).  
 
1. Download and install the following packages:  
- Boost  
- Probably any recent version should do. We need shared_ptr, unordered_set,  
and unordered_map (unordered_map.hpp is included in debian/ubuntu packages  
libboost1.37-dev & libboost1.38-dev)  
- Google Transit Data Feed (http://code.google.com/p/googletransitdatafeed/)  
- As of this writing you need what's in SVN, as it has a fix that I made  
to actually handle interpolated stops correctly. The next version after  
1.1.9 should have my fix.  
- SWIG  
- A recentish version is desirable. I used 1.3.36.  
 
Helpful hint: To install a python package in a local prefix, do:  
 
"python setup.py install --home=$HOME --prefix=" when inside the package  
 
You may need to set PYTHONPATH to $HOME/lib/python first.  
 
2. Build the C++ graph module and the bindings.  
 
The usual...  
 
- ./autogen.sh && ./configure && make  
 
For an install into your home directory, try running ./configure like so:  
 
- ./configure --prefix=$HOME --libdir=$HOME/lib  
 
or maybe:  
 
- ./configure --prefix=$HOME --libdir=$HOME/lib64 # (for many 64-bit systems)  
 
3. Set up your language environment.  
 
You can either 'make install' to install the binding source to the library  
directory you chose with './configure', or set your library and ruby/python  
path to the libroutez source directory of your choice. e.g.:  
 
export LD_LIBRARY_PATH=/path/to/libroutez and  
export PYTHONPATH=/path/to/libroutez/python  
export RUBYLIB=/path/to/libroutez/ruby  
 
(setting RUBYLIB is only necessary if you want to use ruby, python is used  
by the graph creation utility, so you almost certainly do want that in your  
path)  
 
4. Build a graph.  
 
To reduce application start up time, libroutez uses a custom graph format  
which is created from GTFS and OpenStreetMap data. The creategraph utility  
is used to create this.  
 
The invocation is pretty simple. If you want to create a graph file called  
'mygraph.routez', simply invoke creategraph.py as follows:  
 
./creategraph.py /path/to/gtfsfeed.zip --osm="/path/to/osmfile.osm" \  
mygraph.routez mygraph-gtfsmapping.yml  
 
Want some sample data to play with? You can download the combination of  
William Lachance's Halifax GTFS and Geobase data:  
 
- http://wlach.masalalabs.ca/hfxfeed.zip  
- http://wlach.masalalabs.ca/greater-hrm-geobase.osm.gz  
 
The Halifax GTFS feed is produced by me, based on information provided  
by the city of Halifax. For more information, please see:  
http://github.com/wlach/halifax-transit-feed.  
 
The OSM data is derived from the GeoBase dataset provided by the  
government of Canada, and is distributed under the following terms:  
http://geobase.ca/geobase/en/licence.jsp  
 
5. Starting playing with the library.  
 
Now that you've built a graph, you can start planning trips. Try the  
'testgraph' mini program in examples. The following corresponds to  
a trip from Cogswell and Maynard to Glengarry Gardens at 9am on Monday,  
September 14th 2009 in Halifax, Nova Scotia, Canada:  
 
"testgraph mygraph.routez 44.649942 -63.583457 44.6605 -63.7467 1252933200"  
 
You should get a bunch of directions in "routezspeak" in response. :) Note that  
no attempt is currently made to prettify the output, but hopefully this will at  
least give you a starting point (perhaps that would be a fun little first  
project for someone who wants to contribute?). Correlating the descriptive  
information contained within a Google Transit feed with libroutez's internal  
data structures will necessitate using the gtfs mapping yaml file generated  
by the creategraph utility.  
 
For those who like programming in ruby and python, there are examples of both  
in the same directory as 'testgraph'.  
 
=== Contributing ===  
 
Contributions to libroutez are gratefully accepted. The easiest thing to do  
is fork my repository on github (http://github.com/wlach/libroutez), apply  
your change (make sure to add your name and nature of contribution to  
AUTHORS), then either email me (at wrlach@gmail.com) or the libroutez mailing  
list (http://groups.google.com/group/libroutez) to let us know about what you  
did. Patch files sent directly to wrlach@gmail.com are also welcome.  
 
In order for changes to be committed, they will need to be licensed under the  
same terms as the rest of libroutez (the MIT license). Please note that you  
consent to this in your git commit message or mail the libroutez mailing list  
saying that this (or all) your contributions are released under the MIT  
license.  
 
# ===========================================================================  
# http://autoconf-archive.cryp.to/ax_with_prog.html  
# ===========================================================================  
#  
# SYNOPSIS  
#  
# AX_WITH_PROG([VARIABLE],[program],[VALUE-IF-NOT-FOUND],[PATH])  
#  
# DESCRIPTION  
#  
# Locates an installed program binary, placing the result in the precious  
# variable VARIABLE. Accepts a present VARIABLE, then --with-program, and  
# failing that searches for program in the given path (which defaults to  
# the system path). If program is found, VARIABLE is set to the full path  
# of the binary; if it is not found VARIABLE is set to VALUE-IF-NOT-FOUND  
# if provided, unchanged otherwise.  
#  
# A typical example could be the following one:  
#  
# AX_WITH_PROG(PERL,perl)  
#  
# NOTE: This macro is based upon the original AX_WITH_PYTHON macro from  
# Dustin J. Mitchell <dustin@cs.uchicago.edu>.  
#  
# LAST MODIFICATION  
#  
# 2008-05-05  
#  
# COPYLEFT  
#  
# Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>  
# Copyright (c) 2008 Dustin J. Mitchell <dustin@cs.uchicago.edu>  
#  
# Copying and distribution of this file, with or without modification, are  
# permitted in any medium without royalty provided the copyright notice  
# and this notice are preserved.  
 
AC_DEFUN([AX_WITH_PROG],[  
AC_PREREQ([2.61])  
 
pushdef([VARIABLE],$1)  
pushdef([EXECUTABLE],$2)  
pushdef([VALUE_IF_NOT_FOUND],$3)  
pushdef([PATH_PROG],$4)  
 
AC_ARG_VAR(VARIABLE,Absolute path to EXECUTABLE executable)  
 
AS_IF(test -z "$VARIABLE",[  
AC_MSG_CHECKING(whether EXECUTABLE executable path has been provided)  
AC_ARG_WITH(EXECUTABLE,AS_HELP_STRING([--with-EXECUTABLE=[[[[PATH]]]]],absolute path to EXECUTABLE executable), [  
AS_IF([test "$withval" != "yes"],[  
VARIABLE="$withval"  
AC_MSG_RESULT($VARIABLE)  
],[  
VARIABLE=""  
AC_MSG_RESULT([no])  
])  
],[  
AC_MSG_RESULT([no])  
])  
 
AS_IF(test -z "$VARIABLE",[  
AC_PATH_PROG([]VARIABLE[],[]EXECUTABLE[],[]VALUE_IF_NOT_FOUND[],[]PATH_PROG[])  
])  
])  
 
popdef([PATH_PROG])  
popdef([VALUE_IF_NOT_FOUND])  
popdef([EXECUTABLE])  
popdef([VARIABLE])  
])  
 
# ===========================================================================  
# http://www.nongnu.org/autoconf-archive/ax_python_devel.html  
# ===========================================================================  
#  
# SYNOPSIS  
#  
# AX_PYTHON_DEVEL([version])  
#  
# DESCRIPTION  
#  
# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it  
# in your configure.ac.  
#  
# This macro checks for Python and tries to get the include path to  
# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS)  
# output variables. It also exports $(PYTHON_EXTRA_LIBS) and  
# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code.  
#  
# You can search for some particular version of Python by passing a  
# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please  
# note that you *have* to pass also an operator along with the version to  
# match, and pay special attention to the single quotes surrounding the  
# version number. Don't use "PYTHON_VERSION" for this: that environment  
# variable is declared as precious and thus reserved for the end-user.  
#  
# This macro should work for all versions of Python >= 2.1.0. As an end  
# user, you can disable the check for the python version by setting the  
# PYTHON_NOVERSIONCHECK environment variable to something else than the  
# empty string.  
#  
# If you need to use this macro for an older Python version, please  
# contact the authors. We're always open for feedback.  
#  
# LICENSE  
#  
# Copyright (c) 2009 Sebastian Huber <sebastian-huber@web.de>  
# Copyright (c) 2009 Alan W. Irwin <irwin@beluga.phys.uvic.ca>  
# Copyright (c) 2009 Rafael Laboissiere <rafael@laboissiere.net>  
# Copyright (c) 2009 Andrew Collier <colliera@ukzn.ac.za>  
# Copyright (c) 2009 Matteo Settenvini <matteo@member.fsf.org>  
# Copyright (c) 2009 Horst Knorr <hk_classes@knoda.org>  
#  
# This program is free software: you can redistribute it and/or modify it  
# under the terms of the GNU General Public License as published by the  
# Free Software Foundation, either version 3 of the License, or (at your  
# option) any later version.  
#  
# This program is distributed in the hope that it will be useful, but  
# WITHOUT ANY WARRANTY; without even the implied warranty of  
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  
# Public License for more details.  
#  
# You should have received a copy of the GNU General Public License along  
# with this program. If not, see <http://www.gnu.org/licenses/>.  
#  
# As a special exception, the respective Autoconf Macro's copyright owner  
# gives unlimited permission to copy, distribute and modify the configure  
# scripts that are the output of Autoconf when processing the Macro. You  
# need not follow the terms of the GNU General Public License when using  
# or distributing such scripts, even though portions of the text of the  
# Macro appear in them. The GNU General Public License (GPL) does govern  
# all other use of the material that constitutes the Autoconf Macro.  
#  
# This special exception to the GPL applies to versions of the Autoconf  
# Macro released by the Autoconf Archive. When you make and distribute a  
# modified version of the Autoconf Macro, you may extend this special  
# exception to the GPL to apply to your modified version as well.  
 
AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])  
AC_DEFUN([AX_PYTHON_DEVEL],[  
#  
# Allow the use of a (user set) custom python version  
#  
AC_ARG_VAR([PYTHON_VERSION],[The installed Python  
version to use, for example '2.3'. This string  
will be appended to the Python interpreter  
canonical name.])  
 
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])  
if test -z "$PYTHON"; then  
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])  
PYTHON_VERSION=""  
fi  
 
#  
# Check for a version of Python >= 2.1.0  
#  
AC_MSG_CHECKING([for a version of Python >= '2.1.0'])  
ac_supports_python_ver=`$PYTHON -c "import sys; \  
ver = sys.version.split ()[[0]]; \  
print (ver >= '2.1.0')"`  
if test "$ac_supports_python_ver" != "True"; then  
if test -z "$PYTHON_NOVERSIONCHECK"; then  
AC_MSG_RESULT([no])  
AC_MSG_FAILURE([  
This version of the AC@&t@_PYTHON_DEVEL macro  
doesn't work properly with versions of Python before  
2.1.0. You may need to re-run configure, setting the  
variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,  
PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.  
Moreover, to disable this check, set PYTHON_NOVERSIONCHECK  
to something else than an empty string.  
])  
else  
AC_MSG_RESULT([skip at user request])  
fi  
else  
AC_MSG_RESULT([yes])  
fi  
 
#  
# if the macro parameter ``version'' is set, honour it  
#  
if test -n "$1"; then  
AC_MSG_CHECKING([for a version of Python $1])  
ac_supports_python_ver=`$PYTHON -c "import sys; \  
ver = sys.version.split ()[[0]]; \  
print (ver $1)"`  
if test "$ac_supports_python_ver" = "True"; then  
AC_MSG_RESULT([yes])  
else  
AC_MSG_RESULT([no])  
AC_MSG_ERROR([this package requires Python $1.  
If you have it installed, but it isn't the default Python  
interpreter in your system path, please pass the PYTHON_VERSION  
variable to configure. See ``configure --help'' for reference.  
])  
PYTHON_VERSION=""  
fi  
fi  
 
#  
# Check if you have distutils, else fail  
#  
AC_MSG_CHECKING([for the distutils Python package])  
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`  
if test -z "$ac_distutils_result"; then  
AC_MSG_RESULT([yes])  
else  
AC_MSG_RESULT([no])  
AC_MSG_ERROR([cannot import Python module "distutils".  
Please check your Python installation. The error was:  
$ac_distutils_result])  
PYTHON_VERSION=""  
fi  
 
#  
# Check for Python include path  
#  
AC_MSG_CHECKING([for Python include path])  
if test -z "$PYTHON_CPPFLAGS"; then  
python_path=`$PYTHON -c "import distutils.sysconfig; \  
print (distutils.sysconfig.get_python_inc ());"`  
if test -n "${python_path}"; then  
python_path="-I$python_path"  
fi  
PYTHON_CPPFLAGS=$python_path  
fi  
AC_MSG_RESULT([$PYTHON_CPPFLAGS])  
AC_SUBST([PYTHON_CPPFLAGS])  
 
#  
# Check for Python library path  
#  
AC_MSG_CHECKING([for Python library path])  
if test -z "$PYTHON_LDFLAGS"; then  
# (makes two attempts to ensure we've got a version number  
# from the interpreter)  
ac_python_version=`cat<<EOD | $PYTHON -  
 
# join all versioning strings, on some systems  
# major/minor numbers could be in different list elements  
from distutils.sysconfig import *  
ret = ''  
for e in get_config_vars ('VERSION'):  
if (e != None):  
ret += e  
print (ret)  
EOD`  
 
if test -z "$ac_python_version"; then  
if test -n "$PYTHON_VERSION"; then  
ac_python_version=$PYTHON_VERSION  
else  
ac_python_version=`$PYTHON -c "import sys; \  
print (sys.version[[:3]])"`  
fi  
fi  
 
# Make the versioning information available to the compiler  
AC_DEFINE_UNQUOTED([HAVE_PYTHON], ["$ac_python_version"],  
[If available, contains the Python version number currently in use.])  
 
# First, the library directory:  
ac_python_libdir=`cat<<EOD | $PYTHON -  
 
# There should be only one  
import distutils.sysconfig  
for e in distutils.sysconfig.get_config_vars ('LIBDIR'):  
if e != None:  
print (e)  
break  
EOD`  
 
# Before checking for libpythonX.Y, we need to know  
# the extension the OS we're on uses for libraries  
# (we take the first one, if there's more than one fix me!):  
ac_python_soext=`$PYTHON -c \  
"import distutils.sysconfig; \  
print (distutils.sysconfig.get_config_vars('SO')[[0]])"`  
 
# Now, for the library:  
ac_python_soname=`$PYTHON -c \  
"import distutils.sysconfig; \  
print (distutils.sysconfig.get_config_vars('LDLIBRARY')[[0]])"`  
 
# Strip away extension from the end to canonicalize its name:  
ac_python_library=`echo "$ac_python_soname" | sed "s/${ac_python_soext}$//"`  
 
# This small piece shamelessly adapted from PostgreSQL python macro;  
# credits goes to momjian, I think. I'd like to put the right name  
# in the credits, if someone can point me in the right direction... ?  
#  
if test -n "$ac_python_libdir" -a -n "$ac_python_library" \  
-a x"$ac_python_library" != x"$ac_python_soname"  
then  
# use the official shared library  
ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`  
PYTHON_LDFLAGS="-L$ac_python_libdir -l$ac_python_library"  
else  
# old way: use libpython from python_configdir  
ac_python_libdir=`$PYTHON -c \  
"from distutils.sysconfig import get_python_lib as f; \  
import os; \  
print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`  
PYTHON_LDFLAGS="-L$ac_python_libdir -lpython$ac_python_version"  
fi  
 
if test -z "PYTHON_LDFLAGS"; then  
AC_MSG_ERROR([  
Cannot determine location of your Python DSO. Please check it was installed with  
dynamic libraries enabled, or try setting PYTHON_LDFLAGS by hand.  
])  
fi  
fi  
AC_MSG_RESULT([$PYTHON_LDFLAGS])  
AC_SUBST([PYTHON_LDFLAGS])  
 
#  
# Check for site packages  
#  
AC_MSG_CHECKING([for Python site-packages path])  
if test -z "$PYTHON_SITE_PKG"; then  
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \  
print (distutils.sysconfig.get_python_lib(0,0));"`  
fi  
AC_MSG_RESULT([$PYTHON_SITE_PKG])  
AC_SUBST([PYTHON_SITE_PKG])  
 
#  
# libraries which must be linked in when embedding  
#  
AC_MSG_CHECKING(python extra libraries)  
if test -z "$PYTHON_EXTRA_LIBS"; then  
PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \  
conf = distutils.sysconfig.get_config_var; \  
print (conf('LOCALMODLIBS') + ' ' + conf('LIBS'))"`  
fi  
AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])  
AC_SUBST(PYTHON_EXTRA_LIBS)  
 
#  
# linking flags needed when embedding  
#  
AC_MSG_CHECKING(python extra linking flags)  
if test -z "$PYTHON_EXTRA_LDFLAGS"; then  
PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \  
conf = distutils.sysconfig.get_config_var; \  
print (conf('LINKFORSHARED'))"`  
fi  
AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])  
AC_SUBST(PYTHON_EXTRA_LDFLAGS)  
 
#  
# final check to see if everything compiles alright  
#  
AC_MSG_CHECKING([consistency of all components of python development environment])  
# save current global flags  
ac_save_LIBS="$LIBS"  
ac_save_CPPFLAGS="$CPPFLAGS"  
LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS"  
CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"  
AC_LANG_PUSH([C])  
AC_LINK_IFELSE([  
AC_LANG_PROGRAM([[#include <Python.h>]],  
[[Py_Initialize();]])  
],[pythonexists=yes],[pythonexists=no])  
AC_LANG_POP([C])  
# turn back to default flags  
CPPFLAGS="$ac_save_CPPFLAGS"  
LIBS="$ac_save_LIBS"  
 
AC_MSG_RESULT([$pythonexists])  
 
if test ! "x$pythonexists" = "xyes"; then  
AC_MSG_FAILURE([  
Could not link test program to Python. Maybe the main Python library has been  
installed in some non-standard library path. If so, pass it to configure,  
via the LDFLAGS environment variable.  
Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib"  
============================================================================  
ERROR!  
You probably have to install the development version of the Python package  
for your distribution. The exact name of this package varies among them.  
============================================================================  
])  
PYTHON_VERSION=""  
fi  
 
#  
# all done!  
#  
])  
 
# ===========================================================================  
# http://autoconf-archive.cryp.to/ax_with_ruby.html  
# ===========================================================================  
#  
# SYNOPSIS  
#  
# AX_WITH_RUBY([VALUE-IF-NOT-FOUND],[PATH])  
#  
# DESCRIPTION  
#  
# Locates an installed Ruby binary, placing the result in the precious  
# variable $RUBY. Accepts a present $RUBY, then --with-ruby, and failing  
# that searches for ruby in the given path (which defaults to the system  
# path). If ruby is found, $RUBY is set to the full path of the binary; if  
# it is not found $RUBY is set to VALUE-IF-NOT-FOUND if provided,  
# unchanged otherwise.  
#  
# A typical use could be the following one:  
#  
# AX_WITH_RUBY  
#  
# LAST MODIFICATION  
#  
# 2008-05-05  
#  
# COPYLEFT  
#  
# Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>  
#  
# Copying and distribution of this file, with or without modification, are  
# permitted in any medium without royalty provided the copyright notice  
# and this notice are preserved.  
 
AC_DEFUN([AX_WITH_RUBY],[  
AX_WITH_PROG(RUBY,ruby,$1,$2)  
])  
 
# ===========================================================================  
# http://autoconf-archive.cryp.to/ax_compare_version.html  
# ===========================================================================  
#  
# SYNOPSIS  
#  
# AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])  
#  
# DESCRIPTION  
#  
# This macro compares two version strings. Due to the various number of  
# minor-version numbers that can exist, and the fact that string  
# comparisons are not compatible with numeric comparisons, this is not  
# necessarily trivial to do in a autoconf script. This macro makes doing  
# these comparisons easy.  
#  
# The six basic comparisons are available, as well as checking equality  
# limited to a certain number of minor-version levels.  
#  
# The operator OP determines what type of comparison to do, and can be one  
# of:  
#  
# eq - equal (test A == B)  
# ne - not equal (test A != B)  
# le - less than or equal (test A <= B)  
# ge - greater than or equal (test A >= B)  
# lt - less than (test A < B)  
# gt - greater than (test A > B)  
#  
# Additionally, the eq and ne operator can have a number after it to limit  
# the test to that number of minor versions.  
#  
# eq0 - equal up to the length of the shorter version  
# ne0 - not equal up to the length of the shorter version  
# eqN - equal up to N sub-version levels  
# neN - not equal up to N sub-version levels  
#  
# When the condition is true, shell commands ACTION-IF-TRUE are run,  
# otherwise shell commands ACTION-IF-FALSE are run. The environment  
# variable 'ax_compare_version' is always set to either 'true' or 'false'  
# as well.  
#  
# Examples:  
#  
# AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])  
# AX_COMPARE_VERSION([3.15],[lt],[3.15.8])  
#  
# would both be true.  
#  
# AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])  
# AX_COMPARE_VERSION([3.15],[gt],[3.15.8])  
#  
# would both be false.  
#  
# AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])  
#  
# would be true because it is only comparing two minor versions.  
#  
# AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])  
#  
# would be true because it is only comparing the lesser number of minor  
# versions of the two values.  
#  
# Note: The characters that separate the version numbers do not matter. An  
# empty string is the same as version 0. OP is evaluated by autoconf, not  
# configure, so must be a string, not a variable.  
#  
# The author would like to acknowledge Guido Draheim whose advice about  
# the m4_case and m4_ifvaln functions make this macro only include the  
# portions necessary to perform the specific comparison specified by the  
# OP argument in the final configure script.  
#  
# LAST MODIFICATION  
#  
# 2008-04-12  
#  
# COPYLEFT  
#  
# Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>  
#  
# Copying and distribution of this file, with or without modification, are  
# permitted in any medium without royalty provided the copyright notice  
# and this notice are preserved.  
 
dnl #########################################################################  
AC_DEFUN([AX_COMPARE_VERSION], [  
AC_PROG_AWK  
 
# Used to indicate true or false condition  
ax_compare_version=false  
 
# Convert the two version strings to be compared into a format that  
# allows a simple string comparison. The end result is that a version  
# string of the form 1.12.5-r617 will be converted to the form  
# 0001001200050617. In other words, each number is zero padded to four  
# digits, and non digits are removed.  
AS_VAR_PUSHDEF([A],[ax_compare_version_A])  
A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \  
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \  
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \  
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \  
-e 's/[[^0-9]]//g'`  
 
AS_VAR_PUSHDEF([B],[ax_compare_version_B])  
B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \  
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \  
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \  
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \  
-e 's/[[^0-9]]//g'`  
 
dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary  
dnl # then the first line is used to determine if the condition is true.  
dnl # The sed right after the echo is to remove any indented white space.  
m4_case(m4_tolower($2),  
[lt],[  
ax_compare_version=`echo "x$A  
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`  
],  
[gt],[  
ax_compare_version=`echo "x$A  
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`  
],  
[le],[  
ax_compare_version=`echo "x$A  
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`  
],  
[ge],[  
ax_compare_version=`echo "x$A  
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`  
],[  
dnl Split the operator from the subversion count if present.  
m4_bmatch(m4_substr($2,2),  
[0],[  
# A count of zero means use the length of the shorter version.  
# Determine the number of characters in A and B.  
ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`  
ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`  
 
# Set A to no more than B's length and B to no more than A's length.  
A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`  
B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`  
],  
[[0-9]+],[  
# A count greater than zero means use only that many subversions  
A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`  
B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`  
],  
[.+],[  
AC_WARNING(  
[illegal OP numeric parameter: $2])  
],[])  
 
# Pad zeros at end of numbers to make same length.  
ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"  
B="$B`echo $A | sed 's/./0/g'`"  
A="$ax_compare_version_tmp_A"  
 
# Check for equality or inequality as necessary.  
m4_case(m4_tolower(m4_substr($2,0,2)),  
[eq],[  
test "x$A" = "x$B" && ax_compare_version=true  
],  
[ne],[  
test "x$A" != "x$B" && ax_compare_version=true  
],[  
AC_WARNING([illegal OP parameter: $2])  
])  
])  
 
AS_VAR_POPDEF([A])dnl  
AS_VAR_POPDEF([B])dnl  
 
dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.  
if test "$ax_compare_version" = "true" ; then  
m4_ifvaln([$4],[$4],[:])dnl  
m4_ifvaln([$5],[else $5])dnl  
fi  
]) dnl AX_COMPARE_VERSION  
 
 
# ===========================================================================  
# http://autoconf-archive.cryp.to/ax_prog_ruby_version.html  
# ===========================================================================  
#  
# SYNOPSIS  
#  
# AX_PROG_RUBY_VERSION([VERSION],[ACTION-IF-TRUE],[ACTION-IF-FALSE])  
#  
# DESCRIPTION  
#  
# Makes sure that ruby supports the version indicated. If true the shell  
# commands in ACTION-IF-TRUE are executed. If not the shell commands in  
# ACTION-IF-FALSE are run. Note if $RUBY is not set (for example by  
# running AC_CHECK_PROG or AC_PATH_PROG),  
#  
# Example:  
#  
# AC_PATH_PROG([RUBY],[ruby])  
# AC_PROG_RUBY_VERSION([1.8.0],[ ... ],[ ... ])  
#  
# This will check to make sure that the ruby you have supports at least  
# version 1.6.0.  
#  
# NOTE: This macro uses the $RUBY variable to perform the check.  
# AX_WITH_RUBY can be used to set that variable prior to running this  
# macro. The $RUBY_VERSION variable will be valorized with the detected  
# version.  
#  
# LAST MODIFICATION  
#  
# 2008-04-12  
#  
# COPYLEFT  
#  
# Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>  
#  
# Copying and distribution of this file, with or without modification, are  
# permitted in any medium without royalty provided the copyright notice  
# and this notice are preserved.  
 
AC_DEFUN([AX_PROG_RUBY_VERSION],[  
AC_REQUIRE([AC_PROG_SED])  
AC_REQUIRE([AC_PROG_GREP])  
 
AS_IF([test -n "$RUBY"],[  
ax_ruby_version="$1"  
 
AC_MSG_CHECKING([for ruby version])  
changequote(<<,>>)  
ruby_version=`$RUBY --version 2>&1 | $GREP "^ruby " | $SED -e 's/^.* \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/'`  
changequote([,])  
AC_MSG_RESULT($ruby_version)  
 
AC_SUBST([RUBY_VERSION],[$ruby_version])  
 
AX_COMPARE_VERSION([$ax_ruby_version],[le],[$ruby_version],[  
:  
$2  
],[  
:  
$3  
])  
],[  
AC_MSG_WARN([could not find the ruby interpreter])  
$3  
])  
])  
 
# ===========================================================================  
# http://autoconf-archive.cryp.to/ax_ruby_devel.html  
# ===========================================================================  
#  
# SYNOPSIS  
#  
# AX_RUBY_DEVEL([version])  
#  
# DESCRIPTION  
#  
# This macro checks for Ruby and tries to get the include path to  
# 'ruby.h'. It provides the $(RUBY_CPPFLAGS) and $(RUBY_LDFLAGS) output  
# variables. It also exports $(RUBY_EXTRA_LIBS) for embedding Ruby in your  
# code.  
#  
# You can search for some particular version of Ruby by passing a  
# parameter to this macro, for example "1.8.6".  
#  
# LAST MODIFICATION  
#  
# 2008-04-12  
#  
# COPYLEFT  
#  
# Copyright (c) 2008 Rafal Rzepecki <divided.mind@gmail.com>  
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>  
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>  
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>  
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>  
# Copyright (c) 2008 Matteo Settenvini <matteo@member.fsf.org>  
# Copyright (c) 2008 Horst Knorr <hk_classes@knoda.org>  
#  
# This program is free software: you can redistribute it and/or modify it  
# under the terms of the GNU General Public License as published by the  
# Free Software Foundation, either version 3 of the License, or (at your  
# option) any later version.  
#  
# This program is distributed in the hope that it will be useful, but  
# WITHOUT ANY WARRANTY; without even the implied warranty of  
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  
# Public License for more details.  
#  
# You should have received a copy of the GNU General Public License along  
# with this program. If not, see <http://www.gnu.org/licenses/>.  
#  
# As a special exception, the respective Autoconf Macro's copyright owner  
# gives unlimited permission to copy, distribute and modify the configure  
# scripts that are the output of Autoconf when processing the Macro. You  
# need not follow the terms of the GNU General Public License when using  
# or distributing such scripts, even though portions of the text of the  
# Macro appear in them. The GNU General Public License (GPL) does govern  
# all other use of the material that constitutes the Autoconf Macro.  
#  
# This special exception to the GPL applies to versions of the Autoconf  
# Macro released by the Autoconf Macro Archive. When you make and  
# distribute a modified version of the Autoconf Macro, you may extend this  
# special exception to the GPL to apply to your modified version as well.  
 
AC_DEFUN([AX_RUBY_DEVEL],[  
AC_REQUIRE([AX_WITH_RUBY])  
AS_IF([test -n "$1"], [AX_PROG_RUBY_VERSION([$1])])  
 
#  
# Check if you have mkmf, else fail  
#  
AC_MSG_CHECKING([for the mkmf Ruby package])  
ac_mkmf_result=`$RUBY -rmkmf -e ";" 2>&1`  
if test -z "$ac_mkmf_result"; then  
AC_MSG_RESULT([yes])  
else  
AC_MSG_RESULT([no])  
AC_MSG_ERROR([cannot import Ruby module "mkmf".  
Please check your Ruby installation. The error was:  
$ac_distutils_result])  
fi  
 
#  
# Check for Ruby include path  
#  
AC_MSG_CHECKING([for Ruby include path])  
if test -z "$RUBY_CPPFLAGS"; then  
ruby_path=`$RUBY -rmkmf -e 'print Config::CONFIG[["archdir"]]'`  
if test -n "${ruby_path}"; then  
ruby_path="-I$ruby_path"  
fi  
RUBY_CPPFLAGS=$ruby_path  
fi  
AC_MSG_RESULT([$RUBY_CPPFLAGS])  
AC_SUBST([RUBY_CPPFLAGS])  
 
#  
# Check for Ruby library path  
#  
AC_MSG_CHECKING([for Ruby library path])  
if test -z "$RUBY_LDFLAGS"; then  
RUBY_LDFLAGS=`$RUBY -rmkmf -e 'print Config::CONFIG[["LIBRUBYARG_SHARED"]]'`  
fi  
AC_MSG_RESULT([$RUBY_LDFLAGS])  
AC_SUBST([RUBY_LDFLAGS])  
 
#  
# Check for site packages  
#  
AC_MSG_CHECKING([for Ruby site-packages path])  
if test -z "$RUBY_SITE_PKG"; then  
RUBY_SITE_PKG=`$RUBY -rmkmf -e 'print Config::CONFIG[["sitearchdir"]]'`  
fi  
AC_MSG_RESULT([$RUBY_SITE_PKG])  
AC_SUBST([RUBY_SITE_PKG])  
 
#  
# libraries which must be linked in when embedding  
#  
AC_MSG_CHECKING(ruby extra libraries)  
if test -z "$RUBY_EXTRA_LIBS"; then  
RUBY_EXTRA_LIBS=`$RUBY -rmkmf -e 'print Config::CONFIG[["SOLIBS"]]'`  
fi  
AC_MSG_RESULT([$RUBY_EXTRA_LIBS])  
AC_SUBST(RUBY_EXTRA_LIBS)  
 
#  
# linking flags needed when embedding  
# (is it even needed for Ruby?)  
#  
# AC_MSG_CHECKING(ruby extra linking flags)  
# if test -z "$RUBY_EXTRA_LDFLAGS"; then  
# RUBY_EXTRA_LDFLAGS=`$RUBY -rmkmf -e 'print Config::CONFIG[["LINKFORSHARED"]]'`  
# fi  
# AC_MSG_RESULT([$RUBY_EXTRA_LDFLAGS])  
# AC_SUBST(RUBY_EXTRA_LDFLAGS)  
 
# this flags breaks ruby.h, and is sometimes defined by KDE m4 macros  
CFLAGS="`echo "$CFLAGS" | sed -e 's/-std=iso9899:1990//g;'`"  
#  
# final check to see if everything compiles alright  
#  
AC_MSG_CHECKING([consistency of all components of ruby development environment])  
AC_LANG_PUSH([C])  
# save current global flags  
ac_save_LIBS="$LIBS"  
LIBS="$ac_save_LIBS $RUBY_LDFLAGS"  
ac_save_CPPFLAGS="$CPPFLAGS"  
CPPFLAGS="$ac_save_CPPFLAGS $RUBY_CPPFLAGS"  
AC_TRY_LINK([  
#include <ruby.h>  
],[  
ruby_init();  
],[rubyexists=yes],[rubyexists=no])  
 
AC_MSG_RESULT([$rubyexists])  
 
if test ! "$rubyexists" = "yes"; then  
AC_MSG_ERROR([  
Could not link test program to Ruby. Maybe the main Ruby library has been  
installed in some non-standard library path. If so, pass it to configure,  
via the LDFLAGS environment variable.  
Example: ./configure LDFLAGS="-L/usr/non-standard-path/ruby/lib"  
============================================================================  
ERROR!  
You probably have to install the development version of the Ruby package  
for your distribution. The exact name of this package varies among them.  
============================================================================  
])  
RUBY_VERSION=""  
fi  
AC_LANG_POP  
# turn back to default flags  
CPPFLAGS="$ac_save_CPPFLAGS"  
LIBS="$ac_save_LIBS"  
 
#  
# all done!  
#  
])  
 
#!/bin/sh  
 
aclocal  
autoconf  
#! /bin/sh  
# Attempt to guess a canonical system name.  
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,  
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.  
 
timestamp='2005-08-03'  
 
# This file is free software; you can redistribute it and/or modify it  
# under the terms of the GNU General Public License as published by  
# the Free Software Foundation; either version 2 of the License, or  
# (at your option) any later version.  
#  
# This program is distributed in the hope that it will be useful, but  
# WITHOUT ANY WARRANTY; without even the implied warranty of  
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
# General Public License for more details.  
#  
# You should have received a copy of the GNU General Public License  
# along with this program; if not, write to the Free Software  
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  
# 02110-1301, USA.  
#  
# As a special exception to the GNU General Public License, if you  
# distribute this file as part of a program that contains a  
# configuration script generated by Autoconf, you may include it under  
# the same distribution terms that you use for the rest of that program.  
 
 
# Originally written by Per Bothner <per@bothner.com>.  
# Please send patches to <config-patches@gnu.org>. Submit a context  
# diff and a properly formatted ChangeLog entry.  
#  
# This script attempts to guess a canonical system name similar to  
# config.sub. If it succeeds, it prints the system name on stdout, and  
# exits with 0. Otherwise, it exits with 1.  
#  
# The plan is that this can be called by configure scripts if you  
# don't specify an explicit build system type.  
 
me=`echo "$0" | sed -e 's,.*/,,'`  
 
usage="\  
Usage: $0 [OPTION]  
 
Output the configuration name of the system \`$me' is run on.  
 
Operation modes:  
-h, --help print this help, then exit  
-t, --time-stamp print date of last modification, then exit  
-v, --version print version number, then exit  
 
Report bugs and patches to <config-patches@gnu.org>."  
 
version="\  
GNU config.guess ($timestamp)  
 
Originally written by Per Bothner.  
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  
Free Software Foundation, Inc.  
 
This is free software; see the source for copying conditions. There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."  
 
help="  
Try \`$me --help' for more information."  
 
# Parse command line  
while test $# -gt 0 ; do  
case $1 in  
--time-stamp | --time* | -t )  
echo "$timestamp" ; exit ;;  
--version | -v )  
echo "$version" ; exit ;;  
--help | --h* | -h )  
echo "$usage"; exit ;;  
-- ) # Stop option processing  
shift; break ;;  
- ) # Use stdin as input.  
break ;;  
-* )  
echo "$me: invalid option $1$help" >&2  
exit 1 ;;  
* )  
break ;;  
esac  
done  
 
if test $# != 0; then  
echo "$me: too many arguments$help" >&2  
exit 1  
fi  
 
trap 'exit 1' 1 2 15  
 
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a  
# compiler to aid in system detection is discouraged as it requires  
# temporary files to be created and, as you can see below, it is a  
# headache to deal with in a portable fashion.  
 
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still  
# use `HOST_CC' if defined, but it is deprecated.  
 
# Portable tmp directory creation inspired by the Autoconf team.  
 
set_cc_for_build='  
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;  
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;  
: ${TMPDIR=/tmp} ;  
{ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||  
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||  
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||  
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;  
dummy=$tmp/dummy ;  
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;  
case $CC_FOR_BUILD,$HOST_CC,$CC in  
,,) echo "int x;" > $dummy.c ;  
for c in cc gcc c89 c99 ; do  
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then  
CC_FOR_BUILD="$c"; break ;  
fi ;  
done ;  
if test x"$CC_FOR_BUILD" = x ; then  
CC_FOR_BUILD=no_compiler_found ;  
fi  
;;  
,,*) CC_FOR_BUILD=$CC ;;  
,*,*) CC_FOR_BUILD=$HOST_CC ;;  
esac ; set_cc_for_build= ;'  
 
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.  
# (ghazi@noc.rutgers.edu 1994-08-24)  
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then  
PATH=$PATH:/.attbin ; export PATH  
fi  
 
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown  
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown  
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown  
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown  
 
# Note: order is significant - the case branches are not exclusive.  
 
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  
*:NetBSD:*:*)  
# NetBSD (nbsd) targets should (where applicable) match one or  
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,  
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently  
# switched to ELF, *-*-netbsd* would select the old  
# object file format. This provides both forward  
# compatibility and a consistent mechanism for selecting the  
# object file format.  
#  
# Note: NetBSD doesn't particularly care about the vendor  
# portion of the name. We always set it to "unknown".  
sysctl="sysctl -n hw.machine_arch"  
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \  
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`  
case "${UNAME_MACHINE_ARCH}" in  
armeb) machine=armeb-unknown ;;  
arm*) machine=arm-unknown ;;  
sh3el) machine=shl-unknown ;;  
sh3eb) machine=sh-unknown ;;  
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;  
esac  
# The Operating System including object format, if it has switched  
# to ELF recently, or will in the future.  
case "${UNAME_MACHINE_ARCH}" in  
arm*|i386|m68k|ns32k|sh3*|sparc|vax)  
eval $set_cc_for_build  
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \  
| grep __ELF__ >/dev/null  
then  
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).  
# Return netbsd for either. FIX?  
os=netbsd  
else  
os=netbsdelf  
fi  
;;  
*)  
os=netbsd  
;;  
esac  
# The OS release  
# Debian GNU/NetBSD machines have a different userland, and  
# thus, need a distinct triplet. However, they do not need  
# kernel version information, so it can be replaced with a  
# suitable tag, in the style of linux-gnu.  
case "${UNAME_VERSION}" in  
Debian*)  
release='-gnu'  
;;  
*)  
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`  
;;  
esac  
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:  
# contains redundant information, the shorter form:  
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.  
echo "${machine}-${os}${release}"  
exit ;;  
*:OpenBSD:*:*)  
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`  
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}  
exit ;;  
*:ekkoBSD:*:*)  
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}  
exit ;;  
macppc:MirBSD:*:*)  
echo powerppc-unknown-mirbsd${UNAME_RELEASE}  
exit ;;  
*:MirBSD:*:*)  
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}  
exit ;;  
alpha:OSF1:*:*)  
case $UNAME_RELEASE in  
*4.0)  
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`  
;;  
*5.*)  
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`  
;;  
esac  
# According to Compaq, /usr/sbin/psrinfo has been available on  
# OSF/1 and Tru64 systems produced since 1995. I hope that  
# covers most systems running today. This code pipes the CPU  
# types through head -n 1, so we only detect the type of CPU 0.  
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`  
case "$ALPHA_CPU_TYPE" in  
"EV4 (21064)")  
UNAME_MACHINE="alpha" ;;  
"EV4.5 (21064)")  
UNAME_MACHINE="alpha" ;;  
"LCA4 (21066/21068)")  
UNAME_MACHINE="alpha" ;;  
"EV5 (21164)")  
UNAME_MACHINE="alphaev5" ;;  
"EV5.6 (21164A)")  
UNAME_MACHINE="alphaev56" ;;  
"EV5.6 (21164PC)")  
UNAME_MACHINE="alphapca56" ;;  
"EV5.7 (21164PC)")  
UNAME_MACHINE="alphapca57" ;;  
"EV6 (21264)")  
UNAME_MACHINE="alphaev6" ;;  
"EV6.7 (21264A)")  
UNAME_MACHINE="alphaev67" ;;  
"EV6.8CB (21264C)")  
UNAME_MACHINE="alphaev68" ;;  
"EV6.8AL (21264B)")  
UNAME_MACHINE="alphaev68" ;;  
"EV6.8CX (21264D)")  
UNAME_MACHINE="alphaev68" ;;  
"EV6.9A (21264/EV69A)")  
UNAME_MACHINE="alphaev69" ;;  
"EV7 (21364)")  
UNAME_MACHINE="alphaev7" ;;  
"EV7.9 (21364A)")  
UNAME_MACHINE="alphaev79" ;;  
esac  
# A Pn.n version is a patched version.  
# A Vn.n version is a released version.  
# A Tn.n version is a released field test version.  
# A Xn.n version is an unreleased experimental baselevel.  
# 1.2 uses "1.2" for uname -r.  
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`  
exit ;;  
Alpha\ *:Windows_NT*:*)  
# How do we know it's Interix rather than the generic POSIX subsystem?  
# Should we change UNAME_MACHINE based on the output of uname instead  
# of the specific Alpha model?  
echo alpha-pc-interix  
exit ;;  
21064:Windows_NT:50:3)  
echo alpha-dec-winnt3.5  
exit ;;  
Amiga*:UNIX_System_V:4.0:*)  
echo m68k-unknown-sysv4  
exit ;;  
*:[Aa]miga[Oo][Ss]:*:*)  
echo ${UNAME_MACHINE}-unknown-amigaos  
exit ;;  
*:[Mm]orph[Oo][Ss]:*:*)  
echo ${UNAME_MACHINE}-unknown-morphos  
exit ;;  
*:OS/390:*:*)  
echo i370-ibm-openedition  
exit ;;  
*:z/VM:*:*)  
echo s390-ibm-zvmoe  
exit ;;  
*:OS400:*:*)  
echo powerpc-ibm-os400  
exit ;;  
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)  
echo arm-acorn-riscix${UNAME_RELEASE}  
exit ;;  
arm:riscos:*:*|arm:RISCOS:*:*)  
echo arm-unknown-riscos  
exit ;;  
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)  
echo hppa1.1-hitachi-hiuxmpp  
exit ;;  
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)  
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.  
if test "`(/bin/universe) 2>/dev/null`" = att ; then  
echo pyramid-pyramid-sysv3  
else  
echo pyramid-pyramid-bsd  
fi  
exit ;;  
NILE*:*:*:dcosx)  
echo pyramid-pyramid-svr4  
exit ;;  
DRS?6000:unix:4.0:6*)  
echo sparc-icl-nx6  
exit ;;  
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)  
case `/usr/bin/uname -p` in  
sparc) echo sparc-icl-nx7; exit ;;  
esac ;;  
sun4H:SunOS:5.*:*)  
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  
exit ;;  
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)  
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  
exit ;;  
i86pc:SunOS:5.*:*)  
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  
exit ;;  
sun4*:SunOS:6*:*)  
# According to config.sub, this is the proper way to canonicalize  
# SunOS6. Hard to guess exactly what SunOS6 will be like, but  
# it's likely to be more like Solaris than SunOS4.  
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  
exit ;;  
sun4*:SunOS:*:*)  
case "`/usr/bin/arch -k`" in  
Series*|S4*)  
UNAME_RELEASE=`uname -v`  
;;  
esac  
# Japanese Language versions have a version number like `4.1.3-JL'.  
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`  
exit ;;  
sun3*:SunOS:*:*)  
echo m68k-sun-sunos${UNAME_RELEASE}  
exit ;;  
sun*:*:4.2BSD:*)  
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`  
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3  
case "`/bin/arch`" in  
sun3)  
echo m68k-sun-sunos${UNAME_RELEASE}  
;;  
sun4)  
echo sparc-sun-sunos${UNAME_RELEASE}  
;;  
esac  
exit ;;  
aushp:SunOS:*:*)  
echo sparc-auspex-sunos${UNAME_RELEASE}  
exit ;;  
# The situation for MiNT is a little confusing. The machine name  
# can be virtually everything (everything which is not  
# "atarist" or "atariste" at least should have a processor  
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"  
# to the lowercase version "mint" (or "freemint"). Finally  
# the system name "TOS" denotes a system which is actually not  
# MiNT. But MiNT is downward compatible to TOS, so this should  
# be no problem.  
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)  
echo m68k-atari-mint${UNAME_RELEASE}  
exit ;;  
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)  
echo m68k-atari-mint${UNAME_RELEASE}  
exit ;;  
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)  
echo m68k-atari-mint${UNAME_RELEASE}  
exit ;;  
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)  
echo m68k-milan-mint${UNAME_RELEASE}  
exit ;;  
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)  
echo m68k-hades-mint${UNAME_RELEASE}  
exit ;;  
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)  
echo m68k-unknown-mint${UNAME_RELEASE}  
exit ;;  
m68k:machten:*:*)  
echo m68k-apple-machten${UNAME_RELEASE}  
exit ;;  
powerpc:machten:*:*)  
echo powerpc-apple-machten${UNAME_RELEASE}  
exit ;;  
RISC*:Mach:*:*)  
echo mips-dec-mach_bsd4.3  
exit ;;  
RISC*:ULTRIX:*:*)  
echo mips-dec-ultrix${UNAME_RELEASE}  
exit ;;  
VAX*:ULTRIX*:*:*)  
echo vax-dec-ultrix${UNAME_RELEASE}  
exit ;;  
2020:CLIX:*:* | 2430:CLIX:*:*)  
echo clipper-intergraph-clix${UNAME_RELEASE}  
exit ;;  
mips:*:*:UMIPS | mips:*:*:RISCos)  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
#ifdef __cplusplus  
#include <stdio.h> /* for printf() prototype */  
int main (int argc, char *argv[]) {  
#else  
int main (argc, argv) int argc; char *argv[]; {  
#endif  
#if defined (host_mips) && defined (MIPSEB)  
#if defined (SYSTYPE_SYSV)  
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);  
#endif  
#if defined (SYSTYPE_SVR4)  
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);  
#endif  
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)  
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);  
#endif  
#endif  
exit (-1);  
}  
EOF  
$CC_FOR_BUILD -o $dummy $dummy.c &&  
dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&  
SYSTEM_NAME=`$dummy $dummyarg` &&  
{ echo "$SYSTEM_NAME"; exit; }  
echo mips-mips-riscos${UNAME_RELEASE}  
exit ;;  
Motorola:PowerMAX_OS:*:*)  
echo powerpc-motorola-powermax  
exit ;;  
Motorola:*:4.3:PL8-*)  
echo powerpc-harris-powermax  
exit ;;  
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)  
echo powerpc-harris-powermax  
exit ;;  
Night_Hawk:Power_UNIX:*:*)  
echo powerpc-harris-powerunix  
exit ;;  
m88k:CX/UX:7*:*)  
echo m88k-harris-cxux7  
exit ;;  
m88k:*:4*:R4*)  
echo m88k-motorola-sysv4  
exit ;;  
m88k:*:3*:R3*)  
echo m88k-motorola-sysv3  
exit ;;  
AViiON:dgux:*:*)  
# DG/UX returns AViiON for all architectures  
UNAME_PROCESSOR=`/usr/bin/uname -p`  
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]  
then  
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \  
[ ${TARGET_BINARY_INTERFACE}x = x ]  
then  
echo m88k-dg-dgux${UNAME_RELEASE}  
else  
echo m88k-dg-dguxbcs${UNAME_RELEASE}  
fi  
else  
echo i586-dg-dgux${UNAME_RELEASE}  
fi  
exit ;;  
M88*:DolphinOS:*:*) # DolphinOS (SVR3)  
echo m88k-dolphin-sysv3  
exit ;;  
M88*:*:R3*:*)  
# Delta 88k system running SVR3  
echo m88k-motorola-sysv3  
exit ;;  
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)  
echo m88k-tektronix-sysv3  
exit ;;  
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)  
echo m68k-tektronix-bsd  
exit ;;  
*:IRIX*:*:*)  
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`  
exit ;;  
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.  
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id  
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '  
i*86:AIX:*:*)  
echo i386-ibm-aix  
exit ;;  
ia64:AIX:*:*)  
if [ -x /usr/bin/oslevel ] ; then  
IBM_REV=`/usr/bin/oslevel`  
else  
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}  
fi  
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}  
exit ;;  
*:AIX:2:3)  
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
#include <sys/systemcfg.h>  
 
main()  
{  
if (!__power_pc())  
exit(1);  
puts("powerpc-ibm-aix3.2.5");  
exit(0);  
}  
EOF  
if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`  
then  
echo "$SYSTEM_NAME"  
else  
echo rs6000-ibm-aix3.2.5  
fi  
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then  
echo rs6000-ibm-aix3.2.4  
else  
echo rs6000-ibm-aix3.2  
fi  
exit ;;  
*:AIX:*:[45])  
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`  
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then  
IBM_ARCH=rs6000  
else  
IBM_ARCH=powerpc  
fi  
if [ -x /usr/bin/oslevel ] ; then  
IBM_REV=`/usr/bin/oslevel`  
else  
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}  
fi  
echo ${IBM_ARCH}-ibm-aix${IBM_REV}  
exit ;;  
*:AIX:*:*)  
echo rs6000-ibm-aix  
exit ;;  
ibmrt:4.4BSD:*|romp-ibm:BSD:*)  
echo romp-ibm-bsd4.4  
exit ;;  
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and  
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to  
exit ;; # report: romp-ibm BSD 4.3  
*:BOSX:*:*)  
echo rs6000-bull-bosx  
exit ;;  
DPX/2?00:B.O.S.:*:*)  
echo m68k-bull-sysv3  
exit ;;  
9000/[34]??:4.3bsd:1.*:*)  
echo m68k-hp-bsd  
exit ;;  
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)  
echo m68k-hp-bsd4.4  
exit ;;  
9000/[34678]??:HP-UX:*:*)  
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`  
case "${UNAME_MACHINE}" in  
9000/31? ) HP_ARCH=m68000 ;;  
9000/[34]?? ) HP_ARCH=m68k ;;  
9000/[678][0-9][0-9])  
if [ -x /usr/bin/getconf ]; then  
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`  
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`  
case "${sc_cpu_version}" in  
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0  
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1  
532) # CPU_PA_RISC2_0  
case "${sc_kernel_bits}" in  
32) HP_ARCH="hppa2.0n" ;;  
64) HP_ARCH="hppa2.0w" ;;  
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20  
esac ;;  
esac  
fi  
if [ "${HP_ARCH}" = "" ]; then  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
 
#define _HPUX_SOURCE  
#include <stdlib.h>  
#include <unistd.h>  
 
int main ()  
{  
#if defined(_SC_KERNEL_BITS)  
long bits = sysconf(_SC_KERNEL_BITS);  
#endif  
long cpu = sysconf (_SC_CPU_VERSION);  
 
switch (cpu)  
{  
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;  
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;  
case CPU_PA_RISC2_0:  
#if defined(_SC_KERNEL_BITS)  
switch (bits)  
{  
case 64: puts ("hppa2.0w"); break;  
case 32: puts ("hppa2.0n"); break;  
default: puts ("hppa2.0"); break;  
} break;  
#else /* !defined(_SC_KERNEL_BITS) */  
puts ("hppa2.0"); break;  
#endif  
default: puts ("hppa1.0"); break;  
}  
exit (0);  
}  
EOF  
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`  
test -z "$HP_ARCH" && HP_ARCH=hppa  
fi ;;  
esac  
if [ ${HP_ARCH} = "hppa2.0w" ]  
then  
eval $set_cc_for_build  
 
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating  
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler  
# generating 64-bit code. GNU and HP use different nomenclature:  
#  
# $ CC_FOR_BUILD=cc ./config.guess  
# => hppa2.0w-hp-hpux11.23  
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess  
# => hppa64-hp-hpux11.23  
 
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |  
grep __LP64__ >/dev/null  
then  
HP_ARCH="hppa2.0w"  
else  
HP_ARCH="hppa64"  
fi  
fi  
echo ${HP_ARCH}-hp-hpux${HPUX_REV}  
exit ;;  
ia64:HP-UX:*:*)  
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`  
echo ia64-hp-hpux${HPUX_REV}  
exit ;;  
3050*:HI-UX:*:*)  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
#include <unistd.h>  
int  
main ()  
{  
long cpu = sysconf (_SC_CPU_VERSION);  
/* The order matters, because CPU_IS_HP_MC68K erroneously returns  
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct  
results, however. */  
if (CPU_IS_PA_RISC (cpu))  
{  
switch (cpu)  
{  
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;  
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;  
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;  
default: puts ("hppa-hitachi-hiuxwe2"); break;  
}  
}  
else if (CPU_IS_HP_MC68K (cpu))  
puts ("m68k-hitachi-hiuxwe2");  
else puts ("unknown-hitachi-hiuxwe2");  
exit (0);  
}  
EOF  
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&  
{ echo "$SYSTEM_NAME"; exit; }  
echo unknown-hitachi-hiuxwe2  
exit ;;  
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )  
echo hppa1.1-hp-bsd  
exit ;;  
9000/8??:4.3bsd:*:*)  
echo hppa1.0-hp-bsd  
exit ;;  
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)  
echo hppa1.0-hp-mpeix  
exit ;;  
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )  
echo hppa1.1-hp-osf  
exit ;;  
hp8??:OSF1:*:*)  
echo hppa1.0-hp-osf  
exit ;;  
i*86:OSF1:*:*)  
if [ -x /usr/sbin/sysversion ] ; then  
echo ${UNAME_MACHINE}-unknown-osf1mk  
else  
echo ${UNAME_MACHINE}-unknown-osf1  
fi  
exit ;;  
parisc*:Lites*:*:*)  
echo hppa1.1-hp-lites  
exit ;;  
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)  
echo c1-convex-bsd  
exit ;;  
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)  
if getsysinfo -f scalar_acc  
then echo c32-convex-bsd  
else echo c2-convex-bsd  
fi  
exit ;;  
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)  
echo c34-convex-bsd  
exit ;;  
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)  
echo c38-convex-bsd  
exit ;;  
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)  
echo c4-convex-bsd  
exit ;;  
CRAY*Y-MP:*:*:*)  
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'  
exit ;;  
CRAY*[A-Z]90:*:*:*)  
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \  
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \  
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \  
-e 's/\.[^.]*$/.X/'  
exit ;;  
CRAY*TS:*:*:*)  
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'  
exit ;;  
CRAY*T3E:*:*:*)  
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'  
exit ;;  
CRAY*SV1:*:*:*)  
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'  
exit ;;  
*:UNICOS/mp:*:*)  
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'  
exit ;;  
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)  
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`  
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`  
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`  
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"  
exit ;;  
5000:UNIX_System_V:4.*:*)  
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`  
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`  
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"  
exit ;;  
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)  
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}  
exit ;;  
sparc*:BSD/OS:*:*)  
echo sparc-unknown-bsdi${UNAME_RELEASE}  
exit ;;  
*:BSD/OS:*:*)  
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}  
exit ;;  
*:FreeBSD:*:*)  
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`  
exit ;;  
i*:CYGWIN*:*)  
echo ${UNAME_MACHINE}-pc-cygwin  
exit ;;  
i*:MINGW*:*)  
echo ${UNAME_MACHINE}-pc-mingw32  
exit ;;  
i*:windows32*:*)  
# uname -m includes "-pc" on this system.  
echo ${UNAME_MACHINE}-mingw32  
exit ;;  
i*:PW*:*)  
echo ${UNAME_MACHINE}-pc-pw32  
exit ;;  
x86:Interix*:[34]*)  
echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'  
exit ;;  
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)  
echo i${UNAME_MACHINE}-pc-mks  
exit ;;  
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)  
# How do we know it's Interix rather than the generic POSIX subsystem?  
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we  
# UNAME_MACHINE based on the output of uname instead of i386?  
echo i586-pc-interix  
exit ;;  
i*:UWIN*:*)  
echo ${UNAME_MACHINE}-pc-uwin  
exit ;;  
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)  
echo x86_64-unknown-cygwin  
exit ;;  
p*:CYGWIN*:*)  
echo powerpcle-unknown-cygwin  
exit ;;  
prep*:SunOS:5.*:*)  
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`  
exit ;;  
*:GNU:*:*)  
# the GNU system  
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`  
exit ;;  
*:GNU/*:*:*)  
# other systems with GNU libc and userland  
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu  
exit ;;  
i*86:Minix:*:*)  
echo ${UNAME_MACHINE}-pc-minix  
exit ;;  
arm*:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
cris:Linux:*:*)  
echo cris-axis-linux-gnu  
exit ;;  
crisv32:Linux:*:*)  
echo crisv32-axis-linux-gnu  
exit ;;  
frv:Linux:*:*)  
echo frv-unknown-linux-gnu  
exit ;;  
ia64:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
m32r*:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
m68*:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
mips:Linux:*:*)  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
#undef CPU  
#undef mips  
#undef mipsel  
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)  
CPU=mipsel  
#else  
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)  
CPU=mips  
#else  
CPU=  
#endif  
#endif  
EOF  
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`  
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }  
;;  
mips64:Linux:*:*)  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
#undef CPU  
#undef mips64  
#undef mips64el  
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)  
CPU=mips64el  
#else  
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)  
CPU=mips64  
#else  
CPU=  
#endif  
#endif  
EOF  
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`  
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }  
;;  
or32:Linux:*:*)  
echo or32-unknown-linux-gnu  
exit ;;  
ppc:Linux:*:*)  
echo powerpc-unknown-linux-gnu  
exit ;;  
ppc64:Linux:*:*)  
echo powerpc64-unknown-linux-gnu  
exit ;;  
alpha:Linux:*:*)  
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in  
EV5) UNAME_MACHINE=alphaev5 ;;  
EV56) UNAME_MACHINE=alphaev56 ;;  
PCA56) UNAME_MACHINE=alphapca56 ;;  
PCA57) UNAME_MACHINE=alphapca56 ;;  
EV6) UNAME_MACHINE=alphaev6 ;;  
EV67) UNAME_MACHINE=alphaev67 ;;  
EV68*) UNAME_MACHINE=alphaev68 ;;  
esac  
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null  
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi  
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}  
exit ;;  
parisc:Linux:*:* | hppa:Linux:*:*)  
# Look for CPU level  
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in  
PA7*) echo hppa1.1-unknown-linux-gnu ;;  
PA8*) echo hppa2.0-unknown-linux-gnu ;;  
*) echo hppa-unknown-linux-gnu ;;  
esac  
exit ;;  
parisc64:Linux:*:* | hppa64:Linux:*:*)  
echo hppa64-unknown-linux-gnu  
exit ;;  
s390:Linux:*:* | s390x:Linux:*:*)  
echo ${UNAME_MACHINE}-ibm-linux  
exit ;;  
sh64*:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
sh*:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
sparc:Linux:*:* | sparc64:Linux:*:*)  
echo ${UNAME_MACHINE}-unknown-linux-gnu  
exit ;;  
x86_64:Linux:*:*)  
echo x86_64-unknown-linux-gnu  
exit ;;  
i*86:Linux:*:*)  
# The BFD linker knows what the default object file format is, so  
# first see if it will tell us. cd to the root directory to prevent  
# problems with other programs or directories called `ld' in the path.  
# Set LC_ALL=C to ensure ld outputs messages in English.  
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \  
| sed -ne '/supported targets:/!d  
s/[ ][ ]*/ /g  
s/.*supported targets: *//  
s/ .*//  
p'`  
case "$ld_supported_targets" in  
elf32-i386)  
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"  
;;  
a.out-i386-linux)  
echo "${UNAME_MACHINE}-pc-linux-gnuaout"  
exit ;;  
coff-i386)  
echo "${UNAME_MACHINE}-pc-linux-gnucoff"  
exit ;;  
"")  
# Either a pre-BFD a.out linker (linux-gnuoldld) or  
# one that does not give us useful --help.  
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"  
exit ;;  
esac  
# Determine whether the default compiler is a.out or elf  
eval $set_cc_for_build  
sed 's/^ //' << EOF >$dummy.c  
#include <features.h>  
#ifdef __ELF__  
# ifdef __GLIBC__  
# if __GLIBC__ >= 2  
LIBC=gnu  
# else  
LIBC=gnulibc1  
# endif  
# else  
LIBC=gnulibc1  
# endif  
#else  
#ifdef __INTEL_COMPILER  
LIBC=gnu  
#else  
LIBC=gnuaout  
#endif  
#endif  
#ifdef __dietlibc__  
LIBC=dietlibc  
#endif  
EOF  
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`  
test x"${LIBC}" != x && {  
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"  
exit  
}  
test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }  
;;  
i*86:DYNIX/ptx:4*:*)  
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  
# earlier versions are messed up and put the nodename in both  
# sysname and nodename.  
echo i386-sequent-sysv4  
exit ;;  
i*86:UNIX_SV:4.2MP:2.*)  
# Unixware is an offshoot of SVR4, but it has its own version  
# number series starting with 2...  
# I am not positive that other SVR4 systems won't match this,  
# I just have to hope. -- rms.  
# Use sysv4.2uw... so that sysv4* matches it.  
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}  
exit ;;  
i*86:OS/2:*:*)  
# If we were able to find `uname', then EMX Unix compatibility  
# is probably installed.  
echo ${UNAME_MACHINE}-pc-os2-emx  
exit ;;  
i*86:XTS-300:*:STOP)  
echo ${UNAME_MACHINE}-unknown-stop  
exit ;;  
i*86:atheos:*:*)  
echo ${UNAME_MACHINE}-unknown-atheos  
exit ;;  
i*86:syllable:*:*)  
echo ${UNAME_MACHINE}-pc-syllable  
exit ;;  
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)  
echo i386-unknown-lynxos${UNAME_RELEASE}  
exit ;;  
i*86:*DOS:*:*)  
echo ${UNAME_MACHINE}-pc-msdosdjgpp  
exit ;;  
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)  
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`  
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then  
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}  
else  
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}  
fi  
exit ;;  
i*86:*:5:[678]*)  
# UnixWare 7.x, OpenUNIX and OpenServer 6.  
case `/bin/uname -X | grep "^Machine"` in  
*486*) UNAME_MACHINE=i486 ;;  
*Pentium) UNAME_MACHINE=i586 ;;  
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;  
esac  
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}  
exit ;;  
i*86:*:3.2:*)  
if test -f /usr/options/cb.name; then  
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`  
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL  
elif /bin/uname -X 2>/dev/null >/dev/null ; then  
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`  
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486  
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \  
&& UNAME_MACHINE=i586  
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \  
&& UNAME_MACHINE=i686  
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \  
&& UNAME_MACHINE=i686  
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL  
else  
echo ${UNAME_MACHINE}-pc-sysv32  
fi  
exit ;;  
pc:*:*:*)  
# Left here for compatibility:  
# uname -m prints for DJGPP always 'pc', but it prints nothing about  
# the processor, so we play safe by assuming i386.  
echo i386-pc-msdosdjgpp  
exit ;;  
Intel:Mach:3*:*)  
echo i386-pc-mach3  
exit ;;  
paragon:*:*:*)  
echo i860-intel-osf1  
exit ;;  
i860:*:4.*:*) # i860-SVR4  
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then  
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4  
else # Add other i860-SVR4 vendors below as they are discovered.  
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4  
fi  
exit ;;  
mini*:CTIX:SYS*5:*)  
# "miniframe"  
echo m68010-convergent-sysv  
exit ;;  
mc68k:UNIX:SYSTEM5:3.51m)  
echo m68k-convergent-sysv  
exit ;;  
M680?0:D-NIX:5.3:*)  
echo m68k-diab-dnix  
exit ;;  
M68*:*:R3V[5678]*:*)  
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;  
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)  
OS_REL=''  
test -r /etc/.relid \  
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`  
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \  
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }  
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \  
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;  
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)  
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \  
&& { echo i486-ncr-sysv4; exit; } ;;  
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)  
echo m68k-unknown-lynxos${UNAME_RELEASE}  
exit ;;  
mc68030:UNIX_System_V:4.*:*)  
echo m68k-atari-sysv4  
exit ;;  
TSUNAMI:LynxOS:2.*:*)  
echo sparc-unknown-lynxos${UNAME_RELEASE}  
exit ;;  
rs6000:LynxOS:2.*:*)  
echo rs6000-unknown-lynxos${UNAME_RELEASE}  
exit ;;  
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)  
echo powerpc-unknown-lynxos${UNAME_RELEASE}  
exit ;;  
SM[BE]S:UNIX_SV:*:*)  
echo mips-dde-sysv${UNAME_RELEASE}  
exit ;;  
RM*:ReliantUNIX-*:*:*)  
echo mips-sni-sysv4  
exit ;;  
RM*:SINIX-*:*:*)  
echo mips-sni-sysv4  
exit ;;  
*:SINIX-*:*:*)  
if uname -p 2>/dev/null >/dev/null ; then  
UNAME_MACHINE=`(uname -p) 2>/dev/null`  
echo ${UNAME_MACHINE}-sni-sysv4  
else  
echo ns32k-sni-sysv  
fi  
exit ;;  
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort  
# says <Richard.M.Bartel@ccMail.Census.GOV>  
echo i586-unisys-sysv4  
exit ;;  
*:UNIX_System_V:4*:FTX*)  
# From Gerald Hewes <hewes@openmarket.com>.  
# How about differentiating between stratus architectures? -djm  
echo hppa1.1-stratus-sysv4  
exit ;;  
*:*:*:FTX*)  
# From seanf@swdc.stratus.com.  
echo i860-stratus-sysv4  
exit ;;  
i*86:VOS:*:*)  
# From Paul.Green@stratus.com.  
echo ${UNAME_MACHINE}-stratus-vos  
exit ;;  
*:VOS:*:*)  
# From Paul.Green@stratus.com.  
echo hppa1.1-stratus-vos  
exit ;;  
mc68*:A/UX:*:*)  
echo m68k-apple-aux${UNAME_RELEASE}  
exit ;;  
news*:NEWS-OS:6*:*)  
echo mips-sony-newsos6  
exit ;;  
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)  
if [ -d /usr/nec ]; then  
echo mips-nec-sysv${UNAME_RELEASE}  
else  
echo mips-unknown-sysv${UNAME_RELEASE}  
fi  
exit ;;  
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.  
echo powerpc-be-beos  
exit ;;  
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.  
echo powerpc-apple-beos  
exit ;;  
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.  
echo i586-pc-beos  
exit ;;  
SX-4:SUPER-UX:*:*)  
echo sx4-nec-superux${UNAME_RELEASE}  
exit ;;  
SX-5:SUPER-UX:*:*)  
echo sx5-nec-superux${UNAME_RELEASE}  
exit ;;  
SX-6:SUPER-UX:*:*)  
echo sx6-nec-superux${UNAME_RELEASE}  
exit ;;  
Power*:Rhapsody:*:*)  
echo powerpc-apple-rhapsody${UNAME_RELEASE}  
exit ;;  
*:Rhapsody:*:*)  
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}  
exit ;;  
*:Darwin:*:*)  
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown  
case $UNAME_PROCESSOR in  
*86) UNAME_PROCESSOR=i686 ;;  
unknown) UNAME_PROCESSOR=powerpc ;;  
esac  
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}  
exit ;;  
*:procnto*:*:* | *:QNX:[0123456789]*:*)  
UNAME_PROCESSOR=`uname -p`  
if test "$UNAME_PROCESSOR" = "x86"; then  
UNAME_PROCESSOR=i386  
UNAME_MACHINE=pc  
fi  
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}  
exit ;;  
*:QNX:*:4*)  
echo i386-pc-qnx  
exit ;;  
NSE-?:NONSTOP_KERNEL:*:*)  
echo nse-tandem-nsk${UNAME_RELEASE}  
exit ;;  
NSR-?:NONSTOP_KERNEL:*:*)  
echo nsr-tandem-nsk${UNAME_RELEASE}  
exit ;;  
*:NonStop-UX:*:*)  
echo mips-compaq-nonstopux  
exit ;;  
BS2000:POSIX*:*:*)  
echo bs2000-siemens-sysv  
exit ;;  
DS/*:UNIX_System_V:*:*)  
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}  
exit ;;  
*:Plan9:*:*)  
# "uname -m" is not consistent, so use $cputype instead. 386  
# is converted to i386 for consistency with other x86  
# operating systems.  
if test "$cputype" = "386"; then  
UNAME_MACHINE=i386  
else  
UNAME_MACHINE="$cputype"  
fi  
echo ${UNAME_MACHINE}-unknown-plan9  
exit ;;  
*:TOPS-10:*:*)  
echo pdp10-unknown-tops10  
exit ;;  
*:TENEX:*:*)  
echo pdp10-unknown-tenex  
exit ;;  
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)  
echo pdp10-dec-tops20  
exit ;;  
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)  
echo pdp10-xkl-tops20  
exit ;;  
*:TOPS-20:*:*)  
echo pdp10-unknown-tops20  
exit ;;  
*:ITS:*:*)  
echo pdp10-unknown-its  
exit ;;  
SEI:*:*:SEIUX)  
echo mips-sei-seiux${UNAME_RELEASE}  
exit ;;  
*:DragonFly:*:*)  
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`  
exit ;;  
*:*VMS:*:*)  
UNAME_MACHINE=`(uname -p) 2>/dev/null`  
case "${UNAME_MACHINE}" in  
A*) echo alpha-dec-vms ; exit ;;  
I*) echo ia64-dec-vms ; exit ;;  
V*) echo vax-dec-vms ; exit ;;  
esac ;;  
*:XENIX:*:SysV)  
echo i386-pc-xenix  
exit ;;  
i*86:skyos:*:*)  
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'  
exit ;;  
esac  
 
#echo '(No uname command or uname output not recognized.)' 1>&2  
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2  
 
eval $set_cc_for_build  
cat >$dummy.c <<EOF  
#ifdef _SEQUENT_  
# include <sys/types.h>  
# include <sys/utsname.h>  
#endif  
main ()  
{  
#if defined (sony)  
#if defined (MIPSEB)  
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,  
I don't know.... */  
printf ("mips-sony-bsd\n"); exit (0);  
#else  
#include <sys/param.h>  
printf ("m68k-sony-newsos%s\n",  
#ifdef NEWSOS4  
"4"  
#else  
""  
#endif  
); exit (0);  
#endif  
#endif  
 
#if defined (__arm) && defined (__acorn) && defined (__unix)  
printf ("arm-acorn-riscix\n"); exit (0);  
#endif  
 
#if defined (hp300) && !defined (hpux)  
printf ("m68k-hp-bsd\n"); exit (0);  
#endif  
 
#if defined (NeXT)  
#if !defined (__ARCHITECTURE__)  
#define __ARCHITECTURE__ "m68k"  
#endif  
int version;  
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;  
if (version < 4)  
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);  
else  
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);  
exit (0);  
#endif  
 
#if defined (MULTIMAX) || defined (n16)  
#if defined (UMAXV)  
printf ("ns32k-encore-sysv\n"); exit (0);  
#else  
#if defined (CMU)  
printf ("ns32k-encore-mach\n"); exit (0);  
#else  
printf ("ns32k-encore-bsd\n"); exit (0);  
#endif  
#endif  
#endif  
 
#if defined (__386BSD__)  
printf ("i386-pc-bsd\n"); exit (0);  
#endif  
 
#if defined (sequent)  
#if defined (i386)  
printf ("i386-sequent-dynix\n"); exit (0);  
#endif  
#if defined (ns32000)  
printf ("ns32k-sequent-dynix\n"); exit (0);  
#endif  
#endif  
 
#if defined (_SEQUENT_)  
struct utsname un;  
 
uname(&un);  
 
if (strncmp(un.version, "V2", 2) == 0) {  
printf ("i386-sequent-ptx2\n"); exit (0);  
}  
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */  
printf ("i386-sequent-ptx1\n"); exit (0);  
}  
printf ("i386-sequent-ptx\n"); exit (0);  
 
#endif  
 
#if defined (vax)  
# if !defined (ultrix)  
# include <sys/param.h>  
# if defined (BSD)  
# if BSD == 43  
printf ("vax-dec-bsd4.3\n"); exit (0);  
# else  
# if BSD == 199006  
printf ("vax-dec-bsd4.3reno\n"); exit (0);  
# else  
printf ("vax-dec-bsd\n"); exit (0);  
# endif  
# endif  
# else  
printf ("vax-dec-bsd\n"); exit (0);  
# endif  
# else  
printf ("vax-dec-ultrix\n"); exit (0);  
# endif  
#endif  
 
#if defined (alliant) && defined (i860)  
printf ("i860-alliant-bsd\n"); exit (0);  
#endif  
 
exit (1);  
}  
EOF  
 
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&  
{ echo "$SYSTEM_NAME"; exit; }  
 
# Apollos put the system type in the environment.  
 
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }  
 
# Convex versions that predate uname can use getsysinfo(1)  
 
if [ -x /usr/convex/getsysinfo ]  
then  
case `getsysinfo -f cpu_type` in  
c1*)  
echo c1-convex-bsd  
exit ;;  
c2*)  
if getsysinfo -f scalar_acc  
then echo c32-convex-bsd  
else echo c2-convex-bsd  
fi  
exit ;;  
c34*)  
echo c34-convex-bsd  
exit ;;  
c38*)  
echo c38-convex-bsd  
exit ;;  
c4*)  
echo c4-convex-bsd  
exit ;;  
esac  
fi  
 
cat >&2 <<EOF  
$0: unable to guess system type  
 
This script, last modified $timestamp, has failed to recognize  
the operating system you are using. It is advised that you  
download the most up to date version of the config scripts from  
 
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess  
and  
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub  
 
If the version you run ($0) is already up to date, please  
send the following data and any information you think might be  
pertinent to <config-patches@gnu.org> in order to provide the needed  
information to handle your system.  
 
config.guess timestamp = $timestamp  
 
uname -m = `(uname -m) 2>/dev/null || echo unknown`  
uname -r = `(uname -r) 2>/dev/null || echo unknown`  
uname -s = `(uname -s) 2>/dev/null || echo unknown`  
uname -v = `(uname -v) 2>/dev/null || echo unknown`  
 
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`  
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`  
 
hostinfo = `(hostinfo) 2>/dev/null`  
/bin/universe = `(/bin/universe) 2>/dev/null`  
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`  
/bin/arch = `(/bin/arch) 2>/dev/null`  
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`  
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`  
 
UNAME_MACHINE = ${UNAME_MACHINE}  
UNAME_RELEASE = ${UNAME_RELEASE}  
UNAME_SYSTEM = ${UNAME_SYSTEM}  
UNAME_VERSION = ${UNAME_VERSION}  
EOF  
 
exit 1  
 
# Local variables:  
# eval: (add-hook 'write-file-hooks 'time-stamp)  
# time-stamp-start: "timestamp='"  
# time-stamp-format: "%:y-%02m-%02d"  
# time-stamp-end: "'"  
# End:  
 
OS=@OS@  
 
PYTHON_LDFLAGS=@PYTHON_LDFLAGS@  
PYTHON_CFLAGS=@PYTHON_CPPFLAGS@  
RUBY_LDFLAGS=@RUBY_LDFLAGS@  
RUBY_CFLAGS=@RUBY_CPPFLAGS@  
RUBY_VERSION=@RUBY_VERSION@  
INSTALL=@INSTALL@  
INSTALL_DATA=@INSTALL_DATA@  
INSTALL_PROGRAM=@INSTALL_PROGRAM@  
INSTALL_SCRIPT=@INSTALL_SCRIPT@  
 
prefix=@prefix@  
exec_prefix=@exec_prefix@  
bindir=@bindir@  
libdir=@libdir@  
libexecdir=@libexecdir@  
sbindir=@sbindir@  
 
#! /bin/sh  
# Configuration validation subroutine script.  
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,  
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.  
 
timestamp='2005-07-08'  
 
# This file is (in principle) common to ALL GNU software.  
# The presence of a machine in this file suggests that SOME GNU software  
# can handle that machine. It does not imply ALL GNU software can.  
#  
# This file is free software; you can redistribute it and/or modify  
# it under the terms of the GNU General Public License as published by  
# the Free Software Foundation; either version 2 of the License, or  
# (at your option) any later version.  
#  
# This program is distributed in the hope that it will be useful,  
# but WITHOUT ANY WARRANTY; without even the implied warranty of  
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
# GNU General Public License for more details.  
#  
# You should have received a copy of the GNU General Public License  
# along with this program; if not, write to the Free Software  
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  
# 02110-1301, USA.  
#  
# As a special exception to the GNU General Public License, if you  
# distribute this file as part of a program that contains a  
# configuration script generated by Autoconf, you may include it under  
# the same distribution terms that you use for the rest of that program.  
 
 
# Please send patches to <config-patches@gnu.org>. Submit a context  
# diff and a properly formatted ChangeLog entry.  
#  
# Configuration subroutine to validate and canonicalize a configuration type.  
# Supply the specified configuration type as an argument.  
# If it is invalid, we print an error message on stderr and exit with code 1.  
# Otherwise, we print the canonical config type on stdout and succeed.  
 
# This file is supposed to be the same for all GNU packages  
# and recognize all the CPU types, system types and aliases  
# that are meaningful with *any* GNU software.  
# Each package is responsible for reporting which valid configurations  
# it does not support. The user should be able to distinguish  
# a failure to support a valid configuration from a meaningless  
# configuration.  
 
# The goal of this file is to map all the various variations of a given  
# machine specification into a single specification in the form:  
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM  
# or in some cases, the newer four-part form:  
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM  
# It is wrong to echo any other type of specification.  
 
me=`echo "$0" | sed -e 's,.*/,,'`  
 
usage="\  
Usage: $0 [OPTION] CPU-MFR-OPSYS  
$0 [OPTION] ALIAS  
 
Canonicalize a configuration name.  
 
Operation modes:  
-h, --help print this help, then exit  
-t, --time-stamp print date of last modification, then exit  
-v, --version print version number, then exit  
 
Report bugs and patches to <config-patches@gnu.org>."  
 
version="\  
GNU config.sub ($timestamp)  
 
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  
Free Software Foundation, Inc.  
 
This is free software; see the source for copying conditions. There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."  
 
help="  
Try \`$me --help' for more information."  
 
# Parse command line  
while test $# -gt 0 ; do  
case $1 in  
--time-stamp | --time* | -t )  
echo "$timestamp" ; exit ;;  
--version | -v )  
echo "$version" ; exit ;;  
--help | --h* | -h )  
echo "$usage"; exit ;;  
-- ) # Stop option processing  
shift; break ;;  
- ) # Use stdin as input.  
break ;;  
-* )  
echo "$me: invalid option $1$help"  
exit 1 ;;  
 
*local*)  
# First pass through any local machine types.  
echo $1  
exit ;;  
 
* )  
break ;;  
esac  
done  
 
case $# in  
0) echo "$me: missing argument$help" >&2  
exit 1;;  
1) ;;  
*) echo "$me: too many arguments$help" >&2  
exit 1;;  
esac  
 
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).  
# Here we must recognize all the valid KERNEL-OS combinations.  
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`  
case $maybe_os in  
nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \  
kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)  
os=-$maybe_os  
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`  
;;  
*)  
basic_machine=`echo $1 | sed 's/-[^-]*$//'`  
if [ $basic_machine != $1 ]  
then os=`echo $1 | sed 's/.*-/-/'`  
else os=; fi  
;;  
esac  
 
### Let's recognize common machines as not being operating systems so  
### that things like config.sub decstation-3100 work. We also  
### recognize some manufacturers as not being operating systems, so we  
### can provide default operating systems below.  
case $os in  
-sun*os*)  
# Prevent following clause from handling this invalid input.  
;;  
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \  
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \  
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \  
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\  
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \  
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \  
-apple | -axis | -knuth | -cray)  
os=  
basic_machine=$1  
;;  
-sim | -cisco | -oki | -wec | -winbond)  
os=  
basic_machine=$1  
;;  
-scout)  
;;  
-wrs)  
os=-vxworks  
basic_machine=$1  
;;  
-chorusos*)  
os=-chorusos  
basic_machine=$1  
;;  
-chorusrdb)  
os=-chorusrdb  
basic_machine=$1  
;;  
-hiux*)  
os=-hiuxwe2  
;;  
-sco5)  
os=-sco3.2v5  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-sco4)  
os=-sco3.2v4  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-sco3.2.[4-9]*)  
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-sco3.2v[4-9]*)  
# Don't forget version if it is 3.2v4 or newer.  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-sco*)  
os=-sco3.2v2  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-udk*)  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-isc)  
os=-isc2.2  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-clix*)  
basic_machine=clipper-intergraph  
;;  
-isc*)  
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`  
;;  
-lynx*)  
os=-lynxos  
;;  
-ptx*)  
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`  
;;  
-windowsnt*)  
os=`echo $os | sed -e 's/windowsnt/winnt/'`  
;;  
-psos*)  
os=-psos  
;;  
-mint | -mint[0-9]*)  
basic_machine=m68k-atari  
os=-mint  
;;  
esac  
 
# Decode aliases for certain CPU-COMPANY combinations.  
case $basic_machine in  
# Recognize the basic CPU types without company name.  
# Some are omitted here because they have special meanings below.  
1750a | 580 \  
| a29k \  
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \  
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \  
| am33_2.0 \  
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \  
| bfin \  
| c4x | clipper \  
| d10v | d30v | dlx | dsp16xx \  
| fr30 | frv \  
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \  
| i370 | i860 | i960 | ia64 \  
| ip2k | iq2000 \  
| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \  
| mips | mipsbe | mipseb | mipsel | mipsle \  
| mips16 \  
| mips64 | mips64el \  
| mips64vr | mips64vrel \  
| mips64orion | mips64orionel \  
| mips64vr4100 | mips64vr4100el \  
| mips64vr4300 | mips64vr4300el \  
| mips64vr5000 | mips64vr5000el \  
| mips64vr5900 | mips64vr5900el \  
| mipsisa32 | mipsisa32el \  
| mipsisa32r2 | mipsisa32r2el \  
| mipsisa64 | mipsisa64el \  
| mipsisa64r2 | mipsisa64r2el \  
| mipsisa64sb1 | mipsisa64sb1el \  
| mipsisa64sr71k | mipsisa64sr71kel \  
| mipstx39 | mipstx39el \  
| mn10200 | mn10300 \  
| ms1 \  
| msp430 \  
| ns16k | ns32k \  
| or32 \  
| pdp10 | pdp11 | pj | pjl \  
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \  
| pyramid \  
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \  
| sh64 | sh64le \  
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \  
| sparcv8 | sparcv9 | sparcv9b \  
| strongarm \  
| tahoe | thumb | tic4x | tic80 | tron \  
| v850 | v850e \  
| we32k \  
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \  
| z8k)  
basic_machine=$basic_machine-unknown  
;;  
m32c)  
basic_machine=$basic_machine-unknown  
;;  
m6811 | m68hc11 | m6812 | m68hc12)  
# Motorola 68HC11/12.  
basic_machine=$basic_machine-unknown  
os=-none  
;;  
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)  
;;  
 
# We use `pc' rather than `unknown'  
# because (1) that's what they normally are, and  
# (2) the word "unknown" tends to confuse beginning users.  
i*86 | x86_64)  
basic_machine=$basic_machine-pc  
;;  
# Object if more than one company name word.  
*-*-*)  
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2  
exit 1  
;;  
# Recognize the basic CPU types with company name.  
580-* \  
| a29k-* \  
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \  
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \  
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \  
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \  
| avr-* \  
| bfin-* | bs2000-* \  
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \  
| clipper-* | craynv-* | cydra-* \  
| d10v-* | d30v-* | dlx-* \  
| elxsi-* \  
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \  
| h8300-* | h8500-* \  
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \  
| i*86-* | i860-* | i960-* | ia64-* \  
| ip2k-* | iq2000-* \  
| m32r-* | m32rle-* \  
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \  
| m88110-* | m88k-* | maxq-* | mcore-* \  
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \  
| mips16-* \  
| mips64-* | mips64el-* \  
| mips64vr-* | mips64vrel-* \  
| mips64orion-* | mips64orionel-* \  
| mips64vr4100-* | mips64vr4100el-* \  
| mips64vr4300-* | mips64vr4300el-* \  
| mips64vr5000-* | mips64vr5000el-* \  
| mips64vr5900-* | mips64vr5900el-* \  
| mipsisa32-* | mipsisa32el-* \  
| mipsisa32r2-* | mipsisa32r2el-* \  
| mipsisa64-* | mipsisa64el-* \  
| mipsisa64r2-* | mipsisa64r2el-* \  
| mipsisa64sb1-* | mipsisa64sb1el-* \  
| mipsisa64sr71k-* | mipsisa64sr71kel-* \  
| mipstx39-* | mipstx39el-* \  
| mmix-* \  
| ms1-* \  
| msp430-* \  
| none-* | np1-* | ns16k-* | ns32k-* \  
| orion-* \  
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \  
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \  
| pyramid-* \  
| romp-* | rs6000-* \  
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \  
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \  
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \  
| sparclite-* \  
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \  
| tahoe-* | thumb-* \  
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \  
| tron-* \  
| v850-* | v850e-* | vax-* \  
| we32k-* \  
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \  
| xstormy16-* | xtensa-* \  
| ymp-* \  
| z8k-*)  
;;  
m32c-*)  
;;  
# Recognize the various machine names and aliases which stand  
# for a CPU type and a company and sometimes even an OS.  
386bsd)  
basic_machine=i386-unknown  
os=-bsd  
;;  
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)  
basic_machine=m68000-att  
;;  
3b*)  
basic_machine=we32k-att  
;;  
a29khif)  
basic_machine=a29k-amd  
os=-udi  
;;  
abacus)  
basic_machine=abacus-unknown  
;;  
adobe68k)  
basic_machine=m68010-adobe  
os=-scout  
;;  
alliant | fx80)  
basic_machine=fx80-alliant  
;;  
altos | altos3068)  
basic_machine=m68k-altos  
;;  
am29k)  
basic_machine=a29k-none  
os=-bsd  
;;  
amd64)  
basic_machine=x86_64-pc  
;;  
amd64-*)  
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
amdahl)  
basic_machine=580-amdahl  
os=-sysv  
;;  
amiga | amiga-*)  
basic_machine=m68k-unknown  
;;  
amigaos | amigados)  
basic_machine=m68k-unknown  
os=-amigaos  
;;  
amigaunix | amix)  
basic_machine=m68k-unknown  
os=-sysv4  
;;  
apollo68)  
basic_machine=m68k-apollo  
os=-sysv  
;;  
apollo68bsd)  
basic_machine=m68k-apollo  
os=-bsd  
;;  
aux)  
basic_machine=m68k-apple  
os=-aux  
;;  
balance)  
basic_machine=ns32k-sequent  
os=-dynix  
;;  
c90)  
basic_machine=c90-cray  
os=-unicos  
;;  
convex-c1)  
basic_machine=c1-convex  
os=-bsd  
;;  
convex-c2)  
basic_machine=c2-convex  
os=-bsd  
;;  
convex-c32)  
basic_machine=c32-convex  
os=-bsd  
;;  
convex-c34)  
basic_machine=c34-convex  
os=-bsd  
;;  
convex-c38)  
basic_machine=c38-convex  
os=-bsd  
;;  
cray | j90)  
basic_machine=j90-cray  
os=-unicos  
;;  
craynv)  
basic_machine=craynv-cray  
os=-unicosmp  
;;  
cr16c)  
basic_machine=cr16c-unknown  
os=-elf  
;;  
crds | unos)  
basic_machine=m68k-crds  
;;  
crisv32 | crisv32-* | etraxfs*)  
basic_machine=crisv32-axis  
;;  
cris | cris-* | etrax*)  
basic_machine=cris-axis  
;;  
crx)  
basic_machine=crx-unknown  
os=-elf  
;;  
da30 | da30-*)  
basic_machine=m68k-da30  
;;  
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)  
basic_machine=mips-dec  
;;  
decsystem10* | dec10*)  
basic_machine=pdp10-dec  
os=-tops10  
;;  
decsystem20* | dec20*)  
basic_machine=pdp10-dec  
os=-tops20  
;;  
delta | 3300 | motorola-3300 | motorola-delta \  
| 3300-motorola | delta-motorola)  
basic_machine=m68k-motorola  
;;  
delta88)  
basic_machine=m88k-motorola  
os=-sysv3  
;;  
djgpp)  
basic_machine=i586-pc  
os=-msdosdjgpp  
;;  
dpx20 | dpx20-*)  
basic_machine=rs6000-bull  
os=-bosx  
;;  
dpx2* | dpx2*-bull)  
basic_machine=m68k-bull  
os=-sysv3  
;;  
ebmon29k)  
basic_machine=a29k-amd  
os=-ebmon  
;;  
elxsi)  
basic_machine=elxsi-elxsi  
os=-bsd  
;;  
encore | umax | mmax)  
basic_machine=ns32k-encore  
;;  
es1800 | OSE68k | ose68k | ose | OSE)  
basic_machine=m68k-ericsson  
os=-ose  
;;  
fx2800)  
basic_machine=i860-alliant  
;;  
genix)  
basic_machine=ns32k-ns  
;;  
gmicro)  
basic_machine=tron-gmicro  
os=-sysv  
;;  
go32)  
basic_machine=i386-pc  
os=-go32  
;;  
h3050r* | hiux*)  
basic_machine=hppa1.1-hitachi  
os=-hiuxwe2  
;;  
h8300hms)  
basic_machine=h8300-hitachi  
os=-hms  
;;  
h8300xray)  
basic_machine=h8300-hitachi  
os=-xray  
;;  
h8500hms)  
basic_machine=h8500-hitachi  
os=-hms  
;;  
harris)  
basic_machine=m88k-harris  
os=-sysv3  
;;  
hp300-*)  
basic_machine=m68k-hp  
;;  
hp300bsd)  
basic_machine=m68k-hp  
os=-bsd  
;;  
hp300hpux)  
basic_machine=m68k-hp  
os=-hpux  
;;  
hp3k9[0-9][0-9] | hp9[0-9][0-9])  
basic_machine=hppa1.0-hp  
;;  
hp9k2[0-9][0-9] | hp9k31[0-9])  
basic_machine=m68000-hp  
;;  
hp9k3[2-9][0-9])  
basic_machine=m68k-hp  
;;  
hp9k6[0-9][0-9] | hp6[0-9][0-9])  
basic_machine=hppa1.0-hp  
;;  
hp9k7[0-79][0-9] | hp7[0-79][0-9])  
basic_machine=hppa1.1-hp  
;;  
hp9k78[0-9] | hp78[0-9])  
# FIXME: really hppa2.0-hp  
basic_machine=hppa1.1-hp  
;;  
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)  
# FIXME: really hppa2.0-hp  
basic_machine=hppa1.1-hp  
;;  
hp9k8[0-9][13679] | hp8[0-9][13679])  
basic_machine=hppa1.1-hp  
;;  
hp9k8[0-9][0-9] | hp8[0-9][0-9])  
basic_machine=hppa1.0-hp  
;;  
hppa-next)  
os=-nextstep3  
;;  
hppaosf)  
basic_machine=hppa1.1-hp  
os=-osf  
;;  
hppro)  
basic_machine=hppa1.1-hp  
os=-proelf  
;;  
i370-ibm* | ibm*)  
basic_machine=i370-ibm  
;;  
# I'm not sure what "Sysv32" means. Should this be sysv3.2?  
i*86v32)  
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`  
os=-sysv32  
;;  
i*86v4*)  
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`  
os=-sysv4  
;;  
i*86v)  
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`  
os=-sysv  
;;  
i*86sol2)  
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`  
os=-solaris2  
;;  
i386mach)  
basic_machine=i386-mach  
os=-mach  
;;  
i386-vsta | vsta)  
basic_machine=i386-unknown  
os=-vsta  
;;  
iris | iris4d)  
basic_machine=mips-sgi  
case $os in  
-irix*)  
;;  
*)  
os=-irix4  
;;  
esac  
;;  
isi68 | isi)  
basic_machine=m68k-isi  
os=-sysv  
;;  
m88k-omron*)  
basic_machine=m88k-omron  
;;  
magnum | m3230)  
basic_machine=mips-mips  
os=-sysv  
;;  
merlin)  
basic_machine=ns32k-utek  
os=-sysv  
;;  
mingw32)  
basic_machine=i386-pc  
os=-mingw32  
;;  
miniframe)  
basic_machine=m68000-convergent  
;;  
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)  
basic_machine=m68k-atari  
os=-mint  
;;  
mips3*-*)  
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`  
;;  
mips3*)  
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown  
;;  
monitor)  
basic_machine=m68k-rom68k  
os=-coff  
;;  
morphos)  
basic_machine=powerpc-unknown  
os=-morphos  
;;  
msdos)  
basic_machine=i386-pc  
os=-msdos  
;;  
mvs)  
basic_machine=i370-ibm  
os=-mvs  
;;  
ncr3000)  
basic_machine=i486-ncr  
os=-sysv4  
;;  
netbsd386)  
basic_machine=i386-unknown  
os=-netbsd  
;;  
netwinder)  
basic_machine=armv4l-rebel  
os=-linux  
;;  
news | news700 | news800 | news900)  
basic_machine=m68k-sony  
os=-newsos  
;;  
news1000)  
basic_machine=m68030-sony  
os=-newsos  
;;  
news-3600 | risc-news)  
basic_machine=mips-sony  
os=-newsos  
;;  
necv70)  
basic_machine=v70-nec  
os=-sysv  
;;  
next | m*-next )  
basic_machine=m68k-next  
case $os in  
-nextstep* )  
;;  
-ns2*)  
os=-nextstep2  
;;  
*)  
os=-nextstep3  
;;  
esac  
;;  
nh3000)  
basic_machine=m68k-harris  
os=-cxux  
;;  
nh[45]000)  
basic_machine=m88k-harris  
os=-cxux  
;;  
nindy960)  
basic_machine=i960-intel  
os=-nindy  
;;  
mon960)  
basic_machine=i960-intel  
os=-mon960  
;;  
nonstopux)  
basic_machine=mips-compaq  
os=-nonstopux  
;;  
np1)  
basic_machine=np1-gould  
;;  
nsr-tandem)  
basic_machine=nsr-tandem  
;;  
op50n-* | op60c-*)  
basic_machine=hppa1.1-oki  
os=-proelf  
;;  
openrisc | openrisc-*)  
basic_machine=or32-unknown  
;;  
os400)  
basic_machine=powerpc-ibm  
os=-os400  
;;  
OSE68000 | ose68000)  
basic_machine=m68000-ericsson  
os=-ose  
;;  
os68k)  
basic_machine=m68k-none  
os=-os68k  
;;  
pa-hitachi)  
basic_machine=hppa1.1-hitachi  
os=-hiuxwe2  
;;  
paragon)  
basic_machine=i860-intel  
os=-osf  
;;  
pbd)  
basic_machine=sparc-tti  
;;  
pbb)  
basic_machine=m68k-tti  
;;  
pc532 | pc532-*)  
basic_machine=ns32k-pc532  
;;  
pentium | p5 | k5 | k6 | nexgen | viac3)  
basic_machine=i586-pc  
;;  
pentiumpro | p6 | 6x86 | athlon | athlon_*)  
basic_machine=i686-pc  
;;  
pentiumii | pentium2 | pentiumiii | pentium3)  
basic_machine=i686-pc  
;;  
pentium4)  
basic_machine=i786-pc  
;;  
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)  
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
pentiumpro-* | p6-* | 6x86-* | athlon-*)  
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)  
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
pentium4-*)  
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
pn)  
basic_machine=pn-gould  
;;  
power) basic_machine=power-ibm  
;;  
ppc) basic_machine=powerpc-unknown  
;;  
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
ppcle | powerpclittle | ppc-le | powerpc-little)  
basic_machine=powerpcle-unknown  
;;  
ppcle-* | powerpclittle-*)  
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
ppc64) basic_machine=powerpc64-unknown  
;;  
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
ppc64le | powerpc64little | ppc64-le | powerpc64-little)  
basic_machine=powerpc64le-unknown  
;;  
ppc64le-* | powerpc64little-*)  
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`  
;;  
ps2)  
basic_machine=i386-ibm  
;;  
pw32)  
basic_machine=i586-unknown  
os=-pw32  
;;  
rom68k)  
basic_machine=m68k-rom68k  
os=-coff  
;;  
rm[46]00)  
basic_machine=mips-siemens  
;;  
rtpc | rtpc-*)  
basic_machine=romp-ibm  
;;  
s390 | s390-*)  
basic_machine=s390-ibm  
;;  
s390x | s390x-*)  
basic_machine=s390x-ibm  
;;  
sa29200)  
basic_machine=a29k-amd  
os=-udi  
;;  
sb1)  
basic_machine=mipsisa64sb1-unknown  
;;  
sb1el)  
basic_machine=mipsisa64sb1el-unknown  
;;  
sei)  
basic_machine=mips-sei  
os=-seiux  
;;  
sequent)  
basic_machine=i386-sequent  
;;  
sh)  
basic_machine=sh-hitachi  
os=-hms  
;;  
sh64)  
basic_machine=sh64-unknown  
;;  
sparclite-wrs | simso-wrs)  
basic_machine=sparclite-wrs  
os=-vxworks  
;;  
sps7)  
basic_machine=m68k-bull  
os=-sysv2  
;;  
spur)  
basic_machine=spur-unknown  
;;  
st2000)  
basic_machine=m68k-tandem  
;;  
stratus)  
basic_machine=i860-stratus  
os=-sysv4  
;;  
sun2)  
basic_machine=m68000-sun  
;;  
sun2os3)  
basic_machine=m68000-sun  
os=-sunos3  
;;  
sun2os4)  
basic_machine=m68000-sun  
os=-sunos4  
;;  
sun3os3)  
basic_machine=m68k-sun  
os=-sunos3  
;;  
sun3os4)  
basic_machine=m68k-sun  
os=-sunos4  
;;  
sun4os3)  
basic_machine=sparc-sun  
os=-sunos3  
;;  
sun4os4)  
basic_machine=sparc-sun  
os=-sunos4  
;;  
sun4sol2)  
basic_machine=sparc-sun  
os=-solaris2  
;;  
sun3 | sun3-*)  
basic_machine=m68k-sun  
;;  
sun4)  
basic_machine=sparc-sun  
;;  
sun386 | sun386i | roadrunner)  
basic_machine=i386-sun  
;;  
sv1)  
basic_machine=sv1-cray  
os=-unicos  
;;  
symmetry)  
basic_machine=i386-sequent  
os=-dynix  
;;  
t3e)  
basic_machine=alphaev5-cray  
os=-unicos  
;;  
t90)  
basic_machine=t90-cray  
os=-unicos  
;;  
tic54x | c54x*)  
basic_machine=tic54x-unknown  
os=-coff  
;;  
tic55x | c55x*)  
basic_machine=tic55x-unknown  
os=-coff  
;;  
tic6x | c6x*)  
basic_machine=tic6x-unknown  
os=-coff  
;;  
tx39)  
basic_machine=mipstx39-unknown  
;;  
tx39el)  
basic_machine=mipstx39el-unknown  
;;  
toad1)  
basic_machine=pdp10-xkl  
os=-tops20  
;;  
tower | tower-32)  
basic_machine=m68k-ncr  
;;  
tpf)  
basic_machine=s390x-ibm  
os=-tpf  
;;  
udi29k)  
basic_machine=a29k-amd  
os=-udi  
;;  
ultra3)  
basic_machine=a29k-nyu  
os=-sym1  
;;  
v810 | necv810)  
basic_machine=v810-nec  
os=-none  
;;  
vaxv)  
basic_machine=vax-dec  
os=-sysv  
;;  
vms)  
basic_machine=vax-dec  
os=-vms  
;;  
vpp*|vx|vx-*)  
basic_machine=f301-fujitsu  
;;  
vxworks960)  
basic_machine=i960-wrs  
os=-vxworks  
;;  
vxworks68)  
basic_machine=m68k-wrs  
os=-vxworks  
;;  
vxworks29k)  
basic_machine=a29k-wrs  
os=-vxworks  
;;  
w65*)  
basic_machine=w65-wdc  
os=-none  
;;  
w89k-*)  
basic_machine=hppa1.1-winbond  
os=-proelf  
;;  
xbox)  
basic_machine=i686-pc  
os=-mingw32  
;;  
xps | xps100)  
basic_machine=xps100-honeywell  
;;  
ymp)  
basic_machine=ymp-cray  
os=-unicos  
;;  
z8k-*-coff)  
basic_machine=z8k-unknown  
os=-sim  
;;  
none)  
basic_machine=none-none  
os=-none  
;;  
 
# Here we handle the default manufacturer of certain CPU types. It is in  
# some cases the only manufacturer, in others, it is the most popular.  
w89k)  
basic_machine=hppa1.1-winbond  
;;  
op50n)  
basic_machine=hppa1.1-oki  
;;  
op60c)  
basic_machine=hppa1.1-oki  
;;  
romp)  
basic_machine=romp-ibm  
;;  
mmix)  
basic_machine=mmix-knuth  
;;  
rs6000)  
basic_machine=rs6000-ibm  
;;  
vax)  
basic_machine=vax-dec  
;;  
pdp10)  
# there are many clones, so DEC is not a safe bet  
basic_machine=pdp10-unknown  
;;  
pdp11)  
basic_machine=pdp11-dec  
;;  
we32k)  
basic_machine=we32k-att  
;;  
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)  
basic_machine=sh-unknown  
;;  
sparc | sparcv8 | sparcv9 | sparcv9b)  
basic_machine=sparc-sun  
;;  
cydra)  
basic_machine=cydra-cydrome  
;;  
orion)  
basic_machine=orion-highlevel  
;;  
orion105)  
basic_machine=clipper-highlevel  
;;  
mac | mpw | mac-mpw)  
basic_machine=m68k-apple  
;;  
pmac | pmac-mpw)  
basic_machine=powerpc-apple  
;;  
*-unknown)  
# Make sure to match an already-canonicalized machine name.  
;;  
*)  
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2  
exit 1  
;;  
esac  
 
# Here we canonicalize certain aliases for manufacturers.  
case $basic_machine in  
*-digital*)  
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`  
;;  
*-commodore*)  
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`  
;;  
*)  
;;  
esac  
 
# Decode manufacturer-specific aliases for certain operating systems.  
 
if [ x"$os" != x"" ]  
then  
case $os in  
# First match some system type aliases  
# that might get confused with valid system types.  
# -solaris* is a basic system type, with this one exception.  
-solaris1 | -solaris1.*)  
os=`echo $os | sed -e 's|solaris1|sunos4|'`  
;;  
-solaris)  
os=-solaris2  
;;  
-svr4*)  
os=-sysv4  
;;  
-unixware*)  
os=-sysv4.2uw  
;;  
-gnu/linux*)  
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`  
;;  
# First accept the basic system types.  
# The portable systems comes first.  
# Each alternative MUST END IN A *, to match a version number.  
# -sysv* is not here because it comes later, after sysvr4.  
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \  
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\  
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \  
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \  
| -aos* \  
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \  
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \  
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \  
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \  
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \  
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \  
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \  
| -chorusos* | -chorusrdb* \  
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \  
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \  
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \  
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \  
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \  
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \  
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \  
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \  
| -skyos* | -haiku*)  
# Remember, each alternative MUST END IN *, to match a version number.  
;;  
-qnx*)  
case $basic_machine in  
x86-* | i*86-*)  
;;  
*)  
os=-nto$os  
;;  
esac  
;;  
-nto-qnx*)  
;;  
-nto*)  
os=`echo $os | sed -e 's|nto|nto-qnx|'`  
;;  
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \  
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \  
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)  
;;  
-mac*)  
os=`echo $os | sed -e 's|mac|macos|'`  
;;  
-linux-dietlibc)  
os=-linux-dietlibc  
;;  
-linux*)  
os=`echo $os | sed -e 's|linux|linux-gnu|'`  
;;  
-sunos5*)  
os=`echo $os | sed -e 's|sunos5|solaris2|'`  
;;  
-sunos6*)  
os=`echo $os | sed -e 's|sunos6|solaris3|'`  
;;  
-opened*)  
os=-openedition  
;;  
-os400*)  
os=-os400  
;;  
-wince*)  
os=-wince  
;;  
-osfrose*)  
os=-osfrose  
;;  
-osf*)  
os=-osf  
;;  
-utek*)  
os=-bsd  
;;  
-dynix*)  
os=-bsd  
;;  
-acis*)  
os=-aos  
;;  
-atheos*)  
os=-atheos  
;;  
-syllable*)  
os=-syllable  
;;  
-386bsd)  
os=-bsd  
;;  
-ctix* | -uts*)  
os=-sysv  
;;  
-nova*)  
os=-rtmk-nova  
;;  
-ns2 )  
os=-nextstep2  
;;  
-nsk*)  
os=-nsk  
;;  
# Preserve the version number of sinix5.  
-sinix5.*)  
os=`echo $os | sed -e 's|sinix|sysv|'`  
;;  
-sinix*)  
os=-sysv4  
;;  
-tpf*)  
os=-tpf  
;;  
-triton*)  
os=-sysv3  
;;  
-oss*)  
os=-sysv3  
;;  
-svr4)  
os=-sysv4  
;;  
-svr3)  
os=-sysv3  
;;  
-sysvr4)  
os=-sysv4  
;;  
# This must come after -sysvr4.  
-sysv*)  
;;  
-ose*)  
os=-ose  
;;  
-es1800*)  
os=-ose  
;;  
-xenix)  
os=-xenix  
;;  
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)  
os=-mint  
;;  
-aros*)  
os=-aros  
;;  
-kaos*)  
os=-kaos  
;;  
-zvmoe)  
os=-zvmoe  
;;  
-none)  
;;  
*)  
# Get rid of the `-' at the beginning of $os.  
os=`echo $os | sed 's/[^-]*-//'`  
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2  
exit 1  
;;  
esac  
else  
 
# Here we handle the default operating systems that come with various machines.  
# The value should be what the vendor currently ships out the door with their  
# machine or put another way, the most popular os provided with the machine.  
 
# Note that if you're going to try to match "-MANUFACTURER" here (say,  
# "-sun"), then you have to tell the case statement up towards the top  
# that MANUFACTURER isn't an operating system. Otherwise, code above  
# will signal an error saying that MANUFACTURER isn't an operating  
# system, and we'll never get to this point.  
 
case $basic_machine in  
*-acorn)  
os=-riscix1.2  
;;  
arm*-rebel)  
os=-linux  
;;  
arm*-semi)  
os=-aout  
;;  
c4x-* | tic4x-*)  
os=-coff  
;;  
# This must come before the *-dec entry.  
pdp10-*)  
os=-tops20  
;;  
pdp11-*)  
os=-none  
;;  
*-dec | vax-*)  
os=-ultrix4.2  
;;  
m68*-apollo)  
os=-domain  
;;  
i386-sun)  
os=-sunos4.0.2  
;;  
m68000-sun)  
os=-sunos3  
# This also exists in the configure program, but was not the  
# default.  
# os=-sunos4  
;;  
m68*-cisco)  
os=-aout  
;;  
mips*-cisco)  
os=-elf  
;;  
mips*-*)  
os=-elf  
;;  
or32-*)  
os=-coff  
;;  
*-tti) # must be before sparc entry or we get the wrong os.  
os=-sysv3  
;;  
sparc-* | *-sun)  
os=-sunos4.1.1  
;;  
*-be)  
os=-beos  
;;  
*-haiku)  
os=-haiku  
;;  
*-ibm)  
os=-aix  
;;  
*-knuth)  
os=-mmixware  
;;  
*-wec)  
os=-proelf  
;;  
*-winbond)  
os=-proelf  
;;  
*-oki)  
os=-proelf  
;;  
*-hp)  
os=-hpux  
;;  
*-hitachi)  
os=-hiux  
;;  
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)  
os=-sysv  
;;  
*-cbm)  
os=-amigaos  
;;  
*-dg)  
os=-dgux  
;;  
*-dolphin)  
os=-sysv3  
;;  
m68k-ccur)  
os=-rtu  
;;  
m88k-omron*)  
os=-luna  
;;  
*-next )  
os=-nextstep  
;;  
*-sequent)  
os=-ptx  
;;  
*-crds)  
os=-unos  
;;  
*-ns)  
os=-genix  
;;  
i370-*)  
os=-mvs  
;;  
*-next)  
os=-nextstep3  
;;  
*-gould)  
os=-sysv  
;;  
*-highlevel)  
os=-bsd  
;;  
*-encore)  
os=-bsd  
;;  
*-sgi)  
os=-irix  
;;  
*-siemens)  
os=-sysv4  
;;  
*-masscomp)  
os=-rtu  
;;  
f30[01]-fujitsu | f700-fujitsu)  
os=-uxpv  
;;  
*-rom68k)  
os=-coff  
;;  
*-*bug)  
os=-coff  
;;  
*-apple)  
os=-macos  
;;  
*-atari*)  
os=-mint  
;;  
*)  
os=-none  
;;  
esac  
fi  
 
# Here we handle the case where we know the os, and the CPU type, but not the  
# manufacturer. We pick the logical manufacturer.  
vendor=unknown  
case $basic_machine in  
*-unknown)  
case $os in  
-riscix*)  
vendor=acorn  
;;  
-sunos*)  
vendor=sun  
;;  
-aix*)  
vendor=ibm  
;;  
-beos*)  
vendor=be  
;;  
-hpux*)  
vendor=hp  
;;  
-mpeix*)  
vendor=hp  
;;  
-hiux*)  
vendor=hitachi  
;;  
-unos*)  
vendor=crds  
;;  
-dgux*)  
vendor=dg  
;;  
-luna*)  
vendor=omron  
;;  
-genix*)  
vendor=ns  
;;  
-mvs* | -opened*)  
vendor=ibm  
;;  
-os400*)  
vendor=ibm  
;;  
-ptx*)  
vendor=sequent  
;;  
-tpf*)  
vendor=ibm  
;;  
-vxsim* | -vxworks* | -windiss*)  
vendor=wrs  
;;  
-aux*)  
vendor=apple  
;;  
-hms*)  
vendor=hitachi  
;;  
-mpw* | -macos*)  
vendor=apple  
;;  
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)  
vendor=atari  
;;  
-vos*)  
vendor=stratus  
;;  
esac  
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`  
;;  
esac  
 
echo $basic_machine$os  
exit  
 
# Local variables:  
# eval: (add-hook 'write-file-hooks 'time-stamp)  
# time-stamp-start: "timestamp='"  
# time-stamp-format: "%:y-%02m-%02d"  
# time-stamp-end: "'"  
# End:  
 
# Process this file with autoconf to produce a configure script.  
AC_PREREQ(2.57)  
AC_INIT(libroutez, 0.1.0, libroutez@googlegroups.com, libroutez)  
AC_CONFIG_SRCDIR(lib/tripgraph.cc)  
 
AC_PROG_CC  
AC_PROG_CXX  
AC_PROG_CPP  
AC_PROG_CXXCPP  
AC_PROG_INSTALL  
 
# Detect target build environment  
AC_CANONICAL_TARGET  
case "$target" in  
*-linux*)  
OS="LINUX"  
;;  
*-sunos*|*-solaris*)  
OS="SOLARIS"  
;;  
*-win*)  
OS="WIN32"  
;;  
*-apple*)  
OS="MACOS"  
;;  
*)  
OS="OTHER"  
;;  
esac  
 
AC_SUBST(OS)  
 
AX_PYTHON_DEVEL  
AX_WITH_RUBY  
AX_RUBY_DEVEL  
 
AC_CHECK_PROG(SWIG, swig, swig)  
 
if test x"$SWIG" = "x"; then  
AC_MSG_ERROR("swig not found")  
fi  
 
if test x"$PYTHON_CPPFLAGS" = "x"; then  
AC_MSG_ERROR("python not found")  
fi  
 
if test x"$RUBY_CPPFLAGS" = "x"; then  
AC_MSG_ERROR("ruby not found")  
fi  
 
AC_CONFIG_FILES(config.mk)  
 
AC_OUTPUT  
 
 
#include <stdlib.h>  
#include "tripgraph.h"  
 
using namespace std;  
 
 
int main(int argc, char *argv[])  
{  
// this example does nothing other than simply load a graph into memory  
// useful for profiling memory usage  
 
if (argc < 2)  
{  
printf("Usage: %s <graph file> ", argv[0]);  
return 1;  
}  
 
printf("Loading graph...\n");  
TripGraph g;  
g.load(argv[1]);  
 
return 0;  
}  
 
#include <stdlib.h>  
#include "tripgraph.h"  
 
using namespace std;  
using namespace tr1;  
 
 
void print_actions(shared_ptr<TripAction> &action)  
{  
shared_ptr<TripAction> parent(action->parent);  
if (parent)  
print_actions(parent);  
 
printf("%d->%d; route: %d; start time: %.2f; end time: %.2f\n",  
action->src_id, action->dest_id, action->route_id,  
action->start_time, action->end_time);  
}  
 
 
int main(int argc, char *argv[])  
{  
if (argc < 7)  
{  
printf("Usage: %s <graph file> <src lat> <src lng> <dest lat> "  
"<dest lng> <start time>\n", argv[0]);  
return 1;  
}  
 
float src_lat = atof(argv[2]);  
float src_lng = atof(argv[3]);  
float dest_lat = atof(argv[4]);  
float dest_lng = atof(argv[5]);  
int start_time = atoi(argv[6]);  
 
printf("Loading graph...\n");  
TripGraph g;  
g.load(argv[1]);  
 
printf("Calculating path...\n");  
TripPath *p = g.find_path(start_time, false, src_lat, src_lng,  
dest_lat, dest_lng);  
 
if (p)  
print_actions(p->last_action);  
else  
printf("Couldn't find path.\n");  
 
delete p;  
 
return 0;  
}  
 
#!/usr/bin/python  
 
# This example is just to give a quick example of using the API for python  
# hackers.  
 
# FIXME: flesh this out a bit more  
 
from libroutez.tripgraph import *  
 
 
if __name__ == '__main__':  
g = TripGraph()  
 
g.add_tripstop(0, TripStop.GTFS, 0.0, 0.0)  
g.add_tripstop(1, TripStop.GTFS, 0.5, 0.0)  
s = ServicePeriod(0, 1, 0, 0, 7, 0, 100, 2000, True, True, True)  
g.add_service_period(s);  
g.add_triphop(500, 1000, 0, 1, 1, 1, 0)  
g.add_walkhop(0, 1)  
 
path = g.find_path(0, False, 0.0, 0.0, 0.5, 0.0)  
 
for action in path.get_actions():  
print "src: %s dest: %s st: %s et: %s rid: %s" % \  
(action.src_id, action.dest_id, action.start_time, action.end_time,  
action.route_id)  
 
 
#!/usr/bin/ruby  
 
# This example is just here to give a simple example of using the ruby  
# API.  
 
# FIXME: It would be nice to have some more ruby examples, but I'll leave  
# that to the ruby hackers.  
 
# This is all slightly icky, but it's probably enough to  
# help you get started  
 
require 'routez'  
 
g = Routez::TripGraph.new()  
g.add_tripstop(0, Routez::TripStop::OSM, 0.0, 0.0)  
g.add_tripstop(1, Routez::TripStop::OSM, 1.0, 0.0)  
g.add_walkhop(0, 1)  
 
path = g.find_path(0, false, 0.0, 0.0, 1.0, 0.0)  
 
path.get_actions().each do |action|  
puts "src: #{action.src_id} dest: #{action.dest_id} st: #{action.start_time} et: #{action.end_time} rid: #{action.route_id}"  
end  
 
s = Routez::ServicePeriod.new(0, 1, 0, 0, 7, 0, 100, 2000, true, true, true)  
g.add_service_period(s);  
g.add_triphop(500, 1000, 0, 1, 1, 1, 0)  
path2 = g.find_path(0, false, 0.0, 0.0, 1.0, 0.0)  
 
path2.get_actions().each do |action|  
puts "src: #{action.src_id} dest: #{action.dest_id} st: #{action.start_time} et: #{action.end_time} rid: #{action.route_id}"  
end  
 
 
g = Routez::TripGraph.new()  
 
g.add_tripstop(0, Routez::TripStop::GTFS, 44.6554236, -63.5936968) # north and agricola  
g.add_tripstop(1, Routez::TripStop::OSM, 44.6546407, -63.5948438) # north and robie (just north of north&agricola)  
g.add_tripstop(2, Routez::TripStop::GTFS, 44.6567144, -63.5919115) # north and northwood (just south of north&agricola)  
g.add_tripstop(3, Routez::TripStop::GTFS, 44.6432423, -63.6045261) # Quinpool and Connaught (a few kms away from north&agricola)  
 
stops = g.find_tripstops_in_range(44.6554236, -63.5936968, Routez::TripStop::GTFS, 500.0)  
 
stops.each do |stop|  
puts "id: #{stop.id} lat: #{stop.lat} lon: #{stop.lng} type: #{stop.type}"  
end  
 
#ifndef __DEFUNS_H  
#define __DEFUNS_H  
 
// max length of an identifier field (i.e. a service period)  
// this simplifies the saving/loading code considerably  
const int MAX_ID_LEN = 20;  
 
#endif // __DEFUNS_H  
 
#ifndef __SERVICEPERIOD_H  
#define __SERVICEPERIOD_H  
#include <stdint.h>  
#include <stdio.h>  
#include <time.h>  
#include <vector>  
 
 
struct ServicePeriodException  
{  
ServicePeriodException(int32_t _tm_mday, int32_t _tm_mon, int32_t _tm_year);  
ServicePeriodException();  
 
int32_t tm_mday;  
int32_t tm_mon;  
int32_t tm_year;  
};  
 
class ServicePeriod  
{  
public:  
ServicePeriod(int32_t id,  
int32_t start_mday, int32_t start_mon, int32_t start_year,  
int32_t end_mday, int32_t end_mon, int32_t end_year,  
int32_t duration, bool weekday, bool saturday, bool sunday);  
ServicePeriod(const ServicePeriod &s);  
ServicePeriod();  
ServicePeriod(FILE *fp);  
 
void add_exception_on(int32_t tm_mday, int32_t tm_mon, int32_t tm_year);  
void add_exception_off(int32_t tm_mday, int32_t tm_mon, int32_t tm_year);  
 
bool is_turned_on(int32_t tm_mday, int32_t tm_mon, int32_t tm_year);  
bool is_turned_off(int32_t tm_mday, int32_t tm_mon, int32_t tm_year);  
 
void write(FILE *fp);  
 
int32_t id;  
 
// start/end time: the range of dates for which the service period is  
// valid (e.g. Jan 2008 - Sep 2009)  
time_t start_time;  
time_t end_time;  
 
// duration and days of the week that the service period is active  
int32_t duration;  
bool weekday;  
bool saturday;  
bool sunday;  
 
// days that the service period is off (regardless of what the normal  
// schedule) says. E.g. a weekday sched on Xmas  
std::vector<ServicePeriodException> exceptions_off;  
 
// days that the service period is on (regardless of what the normal  
// schedule) says. E.g. a sunday sched on Xmas  
std::vector<ServicePeriodException> exceptions_on;  
};  
 
#endif // __SERVICEPERIOD_H  
 
#ifndef __TRIPGRAPH_H  
#define __TRIPGRAPH_H  
#include <queue>  
#include <stdint.h>  
#include <string>  
#include <tr1/memory>  
#include <tr1/unordered_map>  
#include <vector>  
 
#include "serviceperiod.h"  
#include "trippath.h"  
#include "tripstop.h"  
 
 
class TripGraph  
{  
public:  
TripGraph();  
void load(std::string fname);  
void save(std::string fname);  
 
void set_timezone(std::string timezone);  
void add_service_period(ServicePeriod &service_period);  
void add_triphop(int32_t start_time, int32_t end_time, int32_t src_id,  
int32_t dest_id, int32_t route_id, int32_t trip_id,  
int32_t service_id);  
void add_tripstop(int32_t id, TripStop::Type type, float lat, float lng);  
void add_walkhop(int32_t src_id, int32_t dest_id);  
 
void link_osm_gtfs();  
 
TripStop get_tripstop(int32_t id);  
 
std::vector<std::pair<int, int> > get_service_period_ids_for_time(int secs);  
 
#ifdef SWIG  
%newobject find_path;  
#endif  
TripPath * find_path(double start, bool walkonly,  
double src_lat, double src_lng,  
double dest_lat, double dest_lng);  
// various internal types  
struct PathCompare  
{  
inline bool operator() (const std::tr1::shared_ptr<TripPath> &x,  
const std::tr1::shared_ptr<TripPath> &y)  
{  
return x->heuristic_weight > y->heuristic_weight;  
}  
};  
 
typedef std::vector<std::tr1::shared_ptr<TripPath> > TripPathList;  
typedef std::tr1::unordered_map<int32_t, std::tr1::unordered_map<int, std::tr1::shared_ptr<TripPath> > > VisitedRouteMap;  
typedef std::tr1::unordered_map<int32_t, std::tr1::unordered_map<int32_t, std::tr1::shared_ptr<TripPath> > > VisitedWalkMap;  
typedef std::priority_queue<std::tr1::shared_ptr<TripPath>, std::vector<std::tr1::shared_ptr<TripPath> >, PathCompare> PathQueue;  
 
typedef std::vector<ServicePeriod> ServicePeriodList;  
typedef std::vector<std::tr1::shared_ptr<TripStop> > TripStopList;  
 
std::vector<TripStop> find_tripstops_in_range(double lat, double lng,  
TripStop::Type type,  
double range);  
 
private:  
// internal copy of get_tripstop: returns a pointer, not a copy, so  
// much faster (when called many times)  
std::tr1::shared_ptr<TripStop> _get_tripstop(int32_t id);  
std::tr1::shared_ptr<TripStop> get_nearest_stop(double lat, double lng);  
 
void extend_path(std::tr1::shared_ptr<TripPath> &path,  
bool walkonly, int32_t end_id, int &num_paths_considered,  
VisitedRouteMap &visited_routes,  
VisitedWalkMap &visited_walks,  
PathQueue &uncompleted_paths, PathQueue &completed_paths);  
 
std::string timezone;  
TripStopList tripstops;  
ServicePeriodList splist;  
};  
 
#endif // __TRIPGRAPH_H  
 
#ifndef __TRIPPATH_H  
#define __TRIPPATH_H  
#include <tr1/unordered_set>  
#include <tr1/memory>  
#include <deque>  
#include "tripstop.h"  
 
 
struct TripAction  
{  
TripAction(int32_t _src_id, int32_t _dest_id, int _route_id,  
double _start_time, double _end_time);  
TripAction() {} // for swig, which wants to call resize for some dumb reason  
TripAction(const TripAction &other);  
~TripAction() { }  
 
TripAction &operator=(const TripAction &other);  
 
int32_t src_id, dest_id;  
double start_time, end_time;  
int route_id;  
 
// pointer to the action which preceded this one  
std::tr1::shared_ptr<TripAction> parent;  
};  
 
 
struct TripPath  
{  
public:  
TripPath(double _time, double _fastest_speed,  
std::tr1::shared_ptr<TripStop> &_dest_stop,  
std::tr1::shared_ptr<TripStop> &_last_stop);  
TripPath() {}  
 
std::tr1::shared_ptr<TripPath> add_action(  
std::tr1::shared_ptr<TripAction> &action,  
std::deque<int> &_possible_route_ids,  
std::tr1::shared_ptr<TripStop> &_last_stop);  
 
// the following are mostly for the benefit of language bindings  
// C++ code should be able to access this directly with less overhead...  
std::deque<TripAction> get_actions();  
//tr1python::object get_last_action();  
 
double time;  
double fastest_speed;  
std::tr1::shared_ptr<TripStop> dest_stop;  
std::tr1::shared_ptr<TripStop> last_stop;  
std::tr1::shared_ptr<TripAction> last_action;  
 
double walking_time;  
double route_time;  
int traversed_route_ids;  
std::tr1::unordered_set<int> possible_route_ids;  
int last_route_id;  
double weight;  
double heuristic_weight;  
 
private:  
void _get_heuristic_weight();  
 
// Given an action just after the end of a walk in the path, delays  
// that walk by the given number of seconds.  
void delay_walk(std::tr1::shared_ptr<TripAction> walk, float secs);  
};  
 
#endif // __TRIPPATH_H  
 
#ifndef __TRIPSTOP_H  
#define __TRIPSTOP_H  
#include <assert.h>  
#include <tr1/memory>  
#include <tr1/unordered_map>  
#include <string.h>  
#include <string>  
#include <stdint.h>  
#include <vector>  
#include <deque>  
#include <list>  
 
 
// a triphop represents a hop to a specific node on the graph at a  
// particular time (with a particular duration)  
struct TripHop  
{  
TripHop() { }  
 
TripHop(int32_t _start_time, int32_t _end_time, int32_t _dest_id,  
int32_t _trip_id)  
{  
start_time = _start_time;  
end_time = _end_time;  
dest_id = _dest_id;  
trip_id = _trip_id;  
}  
 
int32_t start_time;  
int32_t end_time;  
int32_t dest_id;  
int32_t trip_id;  
};  
 
 
struct WalkHop  
{  
WalkHop() { }  
WalkHop(int32_t _dest_id, float _walktime)  
{  
dest_id = _dest_id;  
walktime = _walktime;  
}  
 
int32_t dest_id;  
float walktime;  
};  
 
 
struct TripStop  
{  
int32_t id;  
enum Type { OSM, GTFS };  
Type type;  
float lat, lng;  
 
TripStop(FILE *fp);  
TripStop(int32_t _id, Type _type, float _lat, float _lng);  
TripStop();  
 
void write(FILE *fp);  
 
void add_triphop(int32_t start_time, int32_t end_time, int32_t dest_id,  
int32_t route_id, int32_t trip_id, int32_t service_id);  
void add_walkhop(int32_t dest_id, float walktime);  
std::deque<int> get_routes(int32_t service_id);  
const TripHop * find_triphop(int time, int route_id, int32_t service_id);  
std::vector<TripHop> find_triphops(  
int time, int route_id, int32_t service_id, int num);  
 
typedef std::vector<TripHop> TripHopList;  
typedef std::tr1::unordered_map<int, TripHopList> TripHopDict;  
typedef std::tr1::unordered_map<int32_t, TripHopDict> ServiceDict;  
 
// we keep a shared pointer to a tdict, as most nodes won't have one and  
// we don't want the memory overhead of one if not strictly needed  
// (note: we use a shared pointer instead of a standard pointer because  
// the same tripstop may have multiple instances, but we only want one  
// instance of its internal servicedict because it can be really huge...)  
std::tr1::shared_ptr<ServiceDict> tdict;  
 
typedef std::list<WalkHop> WalkHopList;  
WalkHopList wlist;  
};  
 
#endif // __TRIPSTOP_H  
 
#!/bin/sh  
 
#  
# install - install a program, script, or datafile  
# This comes from X11R5; it is not part of GNU.  
#  
# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $  
#  
# This script is compatible with the BSD install script, but was written  
# from scratch.  
#  
 
 
# set DOITPROG to echo to test this script  
 
# Don't use :- since 4.3BSD and earlier shells don't like it.  
doit="${DOITPROG-}"  
 
 
# put in absolute paths if you don't have them in your path; or use env. vars.  
 
mvprog="${MVPROG-mv}"  
cpprog="${CPPROG-cp}"  
chmodprog="${CHMODPROG-chmod}"  
chownprog="${CHOWNPROG-chown}"  
chgrpprog="${CHGRPPROG-chgrp}"  
stripprog="${STRIPPROG-strip}"  
rmprog="${RMPROG-rm}"  
 
instcmd="$mvprog"  
chmodcmd=""  
chowncmd=""  
chgrpcmd=""  
stripcmd=""  
rmcmd="$rmprog -f"  
mvcmd="$mvprog"  
src=""  
dst=""  
 
while [ x"$1" != x ]; do  
case $1 in  
-c) instcmd="$cpprog"  
shift  
continue;;  
 
-m) chmodcmd="$chmodprog $2"  
shift  
shift  
continue;;  
 
-o) chowncmd="$chownprog $2"  
shift  
shift  
continue;;  
 
-g) chgrpcmd="$chgrpprog $2"  
shift  
shift  
continue;;  
 
-s) stripcmd="$stripprog"  
shift  
continue;;  
 
*) if [ x"$src" = x ]  
then  
src=$1  
else  
dst=$1  
fi  
shift  
continue;;  
esac  
done  
 
if [ x"$src" = x ]  
then  
echo "install: no input file specified"  
exit 1  
fi  
 
if [ x"$dst" = x ]  
then  
echo "install: no destination specified"  
exit 1  
fi  
 
 
# If destination is a directory, append the input filename; if your system  
# does not like double slashes in filenames, you may need to add some logic  
 
if [ -d $dst ]  
then  
dst="$dst"/`basename $src`  
fi  
 
# Make a temp file name in the proper directory.  
 
dstdir=`dirname $dst`  
dsttmp=$dstdir/#inst.$$#  
 
# Move or copy the file name to the temp name  
 
$doit $instcmd $src $dsttmp  
 
# and set any options; do chmod last to preserve setuid bits  
 
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi  
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi  
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi  
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi  
 
# Now rename the file to the real destination.  
 
$doit $rmcmd $dst  
$doit $mvcmd $dsttmp $dst  
 
 
exit 0  
 
install-libroutez: libroutez.so  
$(INSTALL) -d $(DESTDIR)$(libdir)  
$(INSTALL_PROGRAM) libroutez.so $(DESTDIR)$(libdir)/ ;  
 
# note: this is very non-idiomatic way of installing a python library. it  
# probably doesn't handle edge cases well. but it works for me.  
install-python: python/libroutez/_tripgraph.so python/libroutez/tripgraph.py  
$(INSTALL) -d $(DESTDIR)$(libdir)/python/libroutez  
$(INSTALL) python/libroutez/osm.py $(DESTDIR)$(libdir)/python/libroutez  
$(INSTALL) python/libroutez/_tripgraph.so $(DESTDIR)$(libdir)/python/libroutez  
$(INSTALL) python/libroutez/tripgraph.py $(DESTDIR)$(libdir)/python/libroutez  
$(INSTALL) python/libroutez/__init__.py $(DESTDIR)$(libdir)/python/libroutez  
 
# likewise, this is a very non idiomatic way of installing a ruby module...  
install-ruby:  
$(INSTALL) -d $(DESTDIR)$(libdir)/ruby  
$(INSTALL) ruby/routez.so $(DESTDIR)$(libdir)/ruby  
 
install-util:  
$(INSTALL) -d $(DESTDIR)$(bindir)  
$(INSTALL) utils/creategraph.py $(DESTDIR)$(bindir)  
$(INSTALL) utils/get-gtfs-bounds.py $(DESTDIR)$(bindir)  
 
 
install: install-libroutez install-python install-util install-ruby  
 
#include <string.h>  
#include <assert.h>  
#include "serviceperiod.h"  
#include "defuns.h"  
 
using namespace std;  
 
 
static time_t get_time_t(int tm_mday, int tm_mon, int tm_year)  
{  
struct tm t;  
t.tm_sec = 0;  
t.tm_min = 0;  
t.tm_hour = 0;  
t.tm_mday = tm_mday;  
t.tm_mon = tm_mon;  
t.tm_year = tm_year;  
t.tm_wday = -1;  
t.tm_yday = -1;  
t.tm_isdst = -1;  
 
return mktime(&t);  
}  
 
 
ServicePeriodException::ServicePeriodException(int32_t _tm_mday, int32_t _tm_mon,  
int32_t _tm_year)  
{  
tm_mday = _tm_mday;  
tm_mon = _tm_mon;  
tm_year = _tm_year;  
}  
 
 
ServicePeriodException::ServicePeriodException()  
{  
tm_mday = 0;  
tm_mon = 0;  
tm_year = 0;  
}  
 
 
ServicePeriod::ServicePeriod(int32_t _id, int32_t _start_mday,  
int32_t _start_mon, int32_t _start_year,  
int32_t _end_mday, int32_t _end_mon,  
int32_t _end_year, int32_t _duration,  
bool _weekday, bool _saturday,  
bool _sunday)  
{  
id = _id;  
 
start_time = get_time_t(_start_mday, _start_mon, _start_year);  
end_time = get_time_t(_end_mday, _end_mon, _end_year);  
 
duration = _duration;  
weekday = _weekday;  
saturday = _saturday;  
sunday = _sunday;  
}  
 
 
ServicePeriod::ServicePeriod(const ServicePeriod &s)  
{  
id = s.id;  
 
start_time = s.start_time;  
end_time = s.end_time;  
 
duration = s.duration;  
weekday = s.weekday;  
saturday = s.saturday;  
sunday = s.sunday;  
 
for (vector<ServicePeriodException>::const_iterator i = s.exceptions_on.begin();  
i != s.exceptions_on.end(); i++)  
add_exception_on(i->tm_mday, i->tm_mon, i->tm_year);  
 
for (vector<ServicePeriodException>::const_iterator i = s.exceptions_off.begin();  
i != s.exceptions_off.end(); i++)  
add_exception_off(i->tm_mday, i->tm_mon, i->tm_year);  
}  
 
 
ServicePeriod::ServicePeriod()  
{  
// blank service period object  
start_time = 0;  
end_time = 0;  
 
duration = 0;  
weekday = false;  
saturday = false;  
sunday = false;  
}  
 
 
ServicePeriod::ServicePeriod(FILE *fp)  
{  
assert(fread(&id, sizeof(int32_t), 1, fp) == 1);  
 
assert(fread(&start_time, sizeof(time_t), 1, fp) == 1);  
assert(fread(&end_time, sizeof(time_t), 1, fp) == 1);  
 
assert(fread(&duration, sizeof(int32_t), 1, fp) == 1);  
assert(fread(&weekday, sizeof(bool), 1, fp) == 1);  
assert(fread(&saturday, sizeof(bool), 1, fp) == 1);  
assert(fread(&sunday, sizeof(bool), 1, fp) == 1);  
 
uint32_t num_exceptions_on;  
assert(fread(&num_exceptions_on, sizeof(uint32_t), 1, fp) == 1);  
for (int i=0; i < num_exceptions_on; i++)  
{  
ServicePeriodException e;  
assert(fread(&e, sizeof(ServicePeriodException), 1, fp) == 1);  
add_exception_on(e.tm_mday, e.tm_mon, e.tm_year);  
}  
 
uint32_t num_exceptions_off;  
assert(fread(&num_exceptions_off, sizeof(uint32_t), 1, fp) == 1);  
for (int i=0; i < num_exceptions_off; i++)  
{  
ServicePeriodException e;  
assert(fread(&e, sizeof(ServicePeriodException), 1, fp) == 1);  
add_exception_off(e.tm_mday, e.tm_mon, e.tm_year);  
}  
}  
 
 
void ServicePeriod::write(FILE *fp)  
{  
assert(fwrite(&id, sizeof(int32_t), 1, fp) == 1);  
 
assert(fwrite(&start_time, sizeof(time_t), 1, fp) == 1);  
assert(fwrite(&end_time, sizeof(time_t), 1, fp) == 1);  
 
assert(fwrite(&duration, sizeof(int32_t), 1, fp) == 1);  
assert(fwrite(&weekday, sizeof(bool), 1, fp) == 1);  
assert(fwrite(&saturday, sizeof(bool), 1, fp) == 1);  
assert(fwrite(&sunday, sizeof(bool), 1, fp) == 1);  
 
uint32_t num_exceptions_on = exceptions_on.size();  
assert(fwrite(&num_exceptions_on, sizeof(uint32_t), 1, fp) == 1);  
for (vector<ServicePeriodException>::iterator i = exceptions_on.begin();  
i != exceptions_on.end(); i++)  
{  
ServicePeriodException &e = (*i);  
assert(fwrite(&e, sizeof(ServicePeriodException), 1, fp) == 1);  
}  
 
uint32_t num_exceptions_off = exceptions_off.size();  
assert(fwrite(&num_exceptions_off, sizeof(uint32_t), 1, fp) == 1);  
for (vector<ServicePeriodException>::iterator i = exceptions_off.begin();  
i != exceptions_off.end(); i++)  
{  
ServicePeriodException &e = (*i);  
assert(fwrite(&e, sizeof(ServicePeriodException), 1, fp) == 1);  
}  
}  
 
 
void ServicePeriod::add_exception_on(int32_t tm_mday, int32_t tm_mon, int32_t tm_year)  
{  
exceptions_on.push_back(ServicePeriodException(tm_mday, tm_mon, tm_year));  
}  
 
 
void ServicePeriod::add_exception_off(int32_t tm_mday, int32_t tm_mon, int32_t tm_year)  
{  
exceptions_off.push_back(ServicePeriodException(tm_mday, tm_mon, tm_year));  
}  
 
 
bool ServicePeriod::is_turned_on(int32_t tm_mday, int32_t tm_mon, int32_t tm_year)  
{  
for (vector<ServicePeriodException>::iterator i = exceptions_on.begin();  
i != exceptions_on.end(); i++)  
{  
if ((*i).tm_mday == tm_mday && (*i).tm_mon == tm_mon &&  
(*i).tm_year == tm_year)  
return true;  
}  
 
return false;  
}  
 
 
bool ServicePeriod::is_turned_off(int32_t tm_mday, int32_t tm_mon, int32_t tm_year)  
{  
for (vector<ServicePeriodException>::iterator i = exceptions_off.begin();  
i != exceptions_off.end(); i++)  
{  
if ((*i).tm_mday == tm_mday && (*i).tm_mon == tm_mon &&  
(*i).tm_year == tm_year)  
return true;  
}  
 
return false;  
}  
 
#include "tripgraph.h"  
#include <assert.h>  
#include <errno.h>  
#include <map>  
#include <math.h>  
#include <stdlib.h>  
 
using namespace std;  
using namespace tr1;  
 
// set to 1 to see what find_path is doing (VERY verbose)  
#if 0  
# define DEBUGPATH(fmt, args...) fprintf(stderr, fmt, ## args)  
#else  
# define DEBUGPATH  
#endif  
 
// Estimated walking speed in m/s  
static const float EST_WALK_SPEED = 1.1f;  
static int SECS_IN_DAY = (60*60*24);  
 
 
static inline double radians(double degrees)  
{  
return degrees/180.0f*M_PI;  
}  
 
static inline double degrees(double radians)  
{  
return radians*180.0f/M_PI;  
}  
 
static double distance(double src_lat, double src_lng, double dest_lat,  
double dest_lng)  
{  
// returns distance in meters  
static const double EPSILON = 0.00005;  
 
if (fabs(src_lat - dest_lat) < EPSILON && fabs(src_lng - dest_lng) < EPSILON) {  
return 0.0f;  
}  
 
double theta = src_lng - dest_lng;  
double src_lat_radians = radians(src_lat);  
double dest_lat_radians = radians(dest_lat);  
double dist = sin(src_lat_radians) * sin(dest_lat_radians) +  
cos(src_lat_radians) * cos(dest_lat_radians) *  
cos(radians(theta));  
dist = acos(dist);  
dist = degrees(dist);  
dist *= (60.0f * 1.1515 * 1.609344 * 1000.0f);  
return dist;  
}  
 
 
TripGraph::TripGraph()  
{  
set_timezone("UTC");  
}  
 
 
void TripGraph::load(string fname)  
{  
FILE *fp = fopen(fname.c_str(), "r");  
if (!fp)  
{  
printf("Error: Couldn't open graph file %s: %s (%d).\n",  
fname.c_str(), strerror(errno), errno);  
return;  
}  
 
uint32_t timezone_len;  
assert(fread(&timezone_len, sizeof(uint32_t), 1, fp) == 1);  
char tz[timezone_len+1];  
assert(fread(tz, sizeof(char), timezone_len, fp) == timezone_len);  
tz[timezone_len] = '\0';  
set_timezone(tz);  
 
uint32_t num_service_periods;  
if (fread(&num_service_periods, sizeof(uint32_t), 1, fp) != 1)  
{  
printf("Error: Couldn't read the number of service periods.\n");  
return;  
}  
for (int i=0; i < num_service_periods; i++)  
{  
ServicePeriod s(fp);  
add_service_period(s);  
}  
 
uint32_t num_tripstops;  
if (fread(&num_tripstops, sizeof(uint32_t), 1, fp) != 1)  
{  
printf("Error: Couldn't read the number of tripstops.\n");  
return;  
}  
 
tripstops.reserve(num_tripstops);  
for (uint32_t i=0; i < num_tripstops; i++)  
{  
shared_ptr<TripStop> s(new TripStop(fp));  
assert(tripstops.size() == s->id);  
tripstops.push_back(s);  
}  
 
fclose(fp);  
}  
 
 
void TripGraph::save(string fname)  
{  
FILE *fp = fopen(fname.c_str(), "w");  
if (!fp)  
{  
printf("Error: Couldn't open graph %s for writing: %s (%d).\n",  
fname.c_str(), strerror(errno), errno);  
return;  
}  
 
// write timezone  
uint32_t timezone_len = timezone.size();  
assert(fwrite(&timezone_len, sizeof(uint32_t), 1, fp) == 1);  
assert(fwrite(timezone.c_str(), sizeof(char), timezone_len, fp) ==  
timezone_len);  
 
// write service periods  
uint32_t num_service_periods = splist.size();  
assert(fwrite(&num_service_periods, sizeof(uint32_t), 1, fp) == 1);  
for (ServicePeriodList::iterator i = splist.begin(); i != splist.end();  
i++)  
i->write(fp);  
 
// write tripstops  
uint32_t num_tripstops = tripstops.size();  
assert(fwrite(&num_tripstops, sizeof(uint32_t), 1, fp) == 1);  
for (TripStopList::iterator i = tripstops.begin();  
i != tripstops.end(); i++)  
{  
(*i)->write(fp);  
}  
 
fclose(fp);  
}  
 
 
void TripGraph::set_timezone(std::string _timezone)  
{  
timezone = _timezone;  
setenv("TZ", timezone.c_str(), 1);  
tzset();  
}  
 
 
void TripGraph::add_service_period(ServicePeriod &service_period)  
{  
assert(service_period.id == splist.size());  
splist.push_back(service_period);  
}  
 
 
void TripGraph::add_triphop(int32_t start_time, int32_t end_time,  
int32_t src_id, int32_t dest_id, int32_t route_id,  
int32_t trip_id, int32_t service_id)  
{  
// will assert if src_id doesn't exist!!  
_get_tripstop(src_id)->add_triphop(start_time, end_time, dest_id, route_id,  
trip_id, service_id);  
}  
 
 
void TripGraph::add_tripstop(int32_t id, TripStop::Type type, float lat, float lng)  
{  
// id must equal size of tripstops  
assert(id == tripstops.size());  
 
tripstops.push_back(shared_ptr<TripStop>(new TripStop(id, type, lat, lng)));  
}  
 
 
void TripGraph::add_walkhop(int32_t src_id, int32_t dest_id)  
{  
// will assert if src_id or dest_id doesn't exist!!  
shared_ptr<TripStop> ts_src = _get_tripstop(src_id);  
shared_ptr<TripStop> ts_dest = _get_tripstop(dest_id);  
 
double dist = distance(ts_src->lat, ts_src->lng,  
ts_dest->lat, ts_dest->lng);  
 
ts_src->add_walkhop(dest_id, dist / EST_WALK_SPEED);  
}  
 
 
struct Point  
{  
Point(double _lat, double _lng) { lat=_lat; lng=_lng; }  
double lat;  
double lng;  
};  
 
bool operator==(const Point &p1, const Point &p2)  
{  
// We say that anything within a distance of 1 meter is identical.  
return (distance(p1.lat, p1.lng, p2.lat, p2.lng) < 1.0f);  
}  
 
Point get_closest_point(Point &a, Point &b, Point &c)  
{  
// Given a line made up of a and b, and a point c,  
// return the point on the line closest to c (may be a or b).  
double ab2 = pow((b.lat - a.lat), 2) + pow((b.lng - a.lng), 2);  
double ap_ab = (c.lat - a.lat)*(b.lat-a.lat) + (c.lng-a.lng)*(b.lng-a.lng);  
double t = ap_ab / ab2;  
 
// Clamp t to be between a and b.  
if (t < 0.0f)  
t = 0.0f;  
else if (t>1.0f)  
t = 1.0f;  
 
return Point(a.lat + (b.lat - a.lat)*t, a.lng + (b.lng - a.lng)*t);  
}  
 
 
// This complicated-looking method attempts to link gtfs stops to osm nodes.  
// If a stop lies between two osm nodes on a polyline, we will link the gtfs  
// stop to both of them.  
void TripGraph::link_osm_gtfs()  
{  
map<int32_t, pair<int32_t, int32_t> > new_walkhops;  
 
// do some counting of the actual number of gtfs  
int gtfs_tripstop_count = 0;  
int gtfs_tripstop_total = 0;  
for (TripStopList::iterator i = tripstops.begin();  
i != tripstops.end(); i++)  
{  
if ((*i)->type == TripStop::GTFS)  
gtfs_tripstop_total++;  
}  
 
for (TripStopList::iterator i = tripstops.begin();  
i != tripstops.end(); i++)  
{  
gtfs_tripstop_count++;  
// For each GTFS stop...  
if ((*i)->type == TripStop::GTFS)  
{  
Point gtfs_pt((*i)->lat, (*i)->lng);  
 
pair<int32_t, int32_t> nearest_walkhop(-1, -1);  
double min_dist;  
 
// Check each other trip stop and all its walkhops...  
// FIXME: This is begging to be optimized. We need some way to  
// exclude the bulk of tripstops that are a million miles away.  
// One idea is to do some sort of quadtree-like partitioning of  
// the tripstops; then we'd mostly only have to check other stops  
// within our partition.  
// Another idea is to put a bounding box around each tripstop and  
// its associated walkhops, saving us from having to examine each  
// walkhop of some faraway triphop.  
for (TripStopList::iterator j = tripstops.begin();  
j != tripstops.end(); j++)  
{  
for (TripStop::WalkHopList::iterator k = (*j)->wlist.begin();  
k != (*j)->wlist.end(); k++)  
{  
Point trip_pt((*j)->lat, (*j)->lng);  
 
shared_ptr<TripStop> dest_stop = _get_tripstop(k->dest_id);  
Point walk_pt(dest_stop->lat, dest_stop->lng);  
 
Point p = get_closest_point(trip_pt, walk_pt, gtfs_pt);  
 
// Find the closest OSM hop to the GTFS stop  
double dist = distance(gtfs_pt.lat, gtfs_pt.lng,  
p.lat, p.lng);  
if ((nearest_walkhop.first == (-1) &&  
nearest_walkhop.second == (-1)) || dist < min_dist)  
{  
nearest_walkhop = pair<int32_t,int32_t>(-1, -1);  
// If the GTFS stop is on one of the OSM nodes, use  
// that node. Otherwise remember both nodes.  
if (trip_pt == p)  
nearest_walkhop.first = (*j)->id;  
else if (walk_pt == p)  
nearest_walkhop.first = k->dest_id;  
else  
{  
nearest_walkhop.first = (*j)->id;  
nearest_walkhop.second = k->dest_id;  
}  
 
min_dist = dist;  
}  
}  
}  
 
new_walkhops[(*i)->id] = nearest_walkhop;  
printf("%02.2f%% done: Linking %d -> %d, %d\n",  
((float)gtfs_tripstop_count * 100.0f) / ((float)gtfs_tripstop_total),  
(*i)->id,  
nearest_walkhop.first,  
nearest_walkhop.second);  
}  
}  
 
for (map<int32_t, pair<int32_t, int32_t> >::iterator i = new_walkhops.begin();  
i != new_walkhops.end(); i++)  
{  
int32_t osmstop1 = i->second.first;  
int32_t osmstop2 = i->second.second;  
 
assert(osmstop1 >= 0);  
add_walkhop(i->first, osmstop1);  
add_walkhop(osmstop1, i->first);  
 
if (osmstop2 >= 0)  
{  
add_walkhop(i->first, osmstop2);  
add_walkhop(osmstop2, i->first);  
}  
}  
}  
 
 
shared_ptr<TripStop> TripGraph::get_nearest_stop(double lat, double lng)  
{  
// FIXME: use a quadtree to speed this up, see link_osm_gtfs() for  
// more thoughts on this  
 
shared_ptr<TripStop> closest_stop;  
double min_dist = 0.0f;  
for (TripStopList::iterator i = tripstops.begin();  
i != tripstops.end(); i++)  
{  
double dist = pow(((*i)->lat - lat), 2) + pow(((*i)->lng - lng), 2);  
if (!closest_stop || dist < min_dist)  
{  
closest_stop = (*i);  
min_dist = dist;  
}  
}  
 
return closest_stop;  
}  
 
 
TripStop TripGraph::get_tripstop(int32_t id)  
{  
shared_ptr<TripStop> ts = _get_tripstop(id);  
return TripStop(*ts);  
}  
 
 
vector<pair<int, int> > TripGraph::get_service_period_ids_for_time(int secs)  
{  
vector<pair<int, int> > vsp;  
 
for (ServicePeriodList::iterator i = splist.begin(); i != splist.end(); i++)  
{  
for (int offset = 0; offset < i->duration; offset += SECS_IN_DAY)  
{  
time_t mysecs = secs - offset;  
struct tm * t = localtime(&mysecs);  
if (i->start_time <= mysecs &&  
i->end_time >= mysecs &&  
(((t->tm_wday == 6 && i->saturday) ||  
(t->tm_wday == 0 && i->sunday) ||  
(t->tm_wday > 0 && t->tm_wday < 6 && i->weekday)) &&  
!i->is_turned_off(t->tm_mday, t->tm_mon, t->tm_year)) ||  
i->is_turned_on(t->tm_mday, t->tm_mon, t->tm_year))  
{  
vsp.push_back(pair<int, int>(i->id, offset));  
}  
}  
}  
 
return vsp;  
}  
 
 
TripPath * TripGraph::find_path(double start, bool walkonly,  
double src_lat, double src_lng,  
double dest_lat, double dest_lng)  
{  
PathQueue uncompleted_paths;  
PathQueue completed_paths;  
 
VisitedRouteMap visited_routes;  
VisitedWalkMap visited_walks;  
 
shared_ptr<TripStop> start_node = get_nearest_stop(src_lat, src_lng);  
shared_ptr<TripStop> end_node = get_nearest_stop(dest_lat, dest_lng);  
DEBUGPATH("Find path. Secs: %f walkonly: %d "  
"src lat: %f src lng: %f dest_lat: %f dest_lng: %f\n",  
start, walkonly, src_lat, src_lng, dest_lat, dest_lng);  
DEBUGPATH("- Start: %d End: %d\n", start_node->id, end_node->id);  
 
//DEBUGPATH("..service period determination..");  
 
// Consider the distance required to reach the start node from the  
// beginning, and add that to our start time.  
double dist_from_start = distance(src_lat, src_lng,  
start_node->lat, start_node->lng);  
start += (dist_from_start / EST_WALK_SPEED);  
 
DEBUGPATH("- Start time - %f (dist from start: %f)\n", start, dist_from_start);  
shared_ptr<TripPath> start_path(new TripPath(start, EST_WALK_SPEED,  
end_node, start_node));  
if (start_node == end_node)  
return new TripPath(*start_path);  
 
uncompleted_paths.push(start_path);  
 
int num_paths_considered = 0;  
 
while (uncompleted_paths.size() > 0)  
{  
DEBUGPATH("Continuing\n");  
shared_ptr<TripPath> path = uncompleted_paths.top();  
uncompleted_paths.pop();  
extend_path(path, walkonly, end_node->id, num_paths_considered,  
visited_routes, visited_walks, uncompleted_paths,  
completed_paths);  
 
// If we've still got open paths, but their weight exceeds that  
// of the weight of a completed path, break.  
if (uncompleted_paths.size() > 0 && completed_paths.size() > 0 &&  
uncompleted_paths.top()->heuristic_weight >  
completed_paths.top()->heuristic_weight)  
{  
DEBUGPATH("Breaking with %d uncompleted paths (paths "  
"considered: %d).\n", uncompleted_paths.size(),  
num_paths_considered);  
return new TripPath(*(completed_paths.top()));  
}  
 
//if len(completed_paths) > 0 and len(uncompleted_paths) > 0:  
// print "Weight of best completed path: %s, uncompleted: %s" % \  
// (completed_paths[0].heuristic_weight, uncompleted_paths[0].heuristic_weight)  
}  
 
if (completed_paths.size())  
return new TripPath(*(completed_paths.top()));  
 
return NULL;  
}  
 
 
shared_ptr<TripStop> TripGraph::_get_tripstop(int32_t id)  
{  
assert(id < tripstops.size());  
 
return tripstops[id];  
}  
 
 
void TripGraph::extend_path(shared_ptr<TripPath> &path,  
bool walkonly,  
int32_t goal_id,  
int &num_paths_considered,  
VisitedRouteMap &visited_routes,  
VisitedWalkMap &visited_walks,  
PathQueue &uncompleted_paths,  
PathQueue &completed_paths)  
{  
TripPathList newpaths;  
int32_t src_id = path->last_stop->id;  
int last_route_id = path->last_route_id;  
 
#if 0  
if (path->last_action)  
{  
string last_src_id = path->last_action->src_id;  
if (cb)  
python::call<void>(cb, tripstops[last_src_id]->lat,  
tripstops[last_src_id]->lng,  
tripstops[src_id]->lat,  
tripstops[src_id]->lng,  
last_route_id);  
}  
#endif  
time_t mysecs = (time_t)path->time;  
struct tm * tm = localtime(&mysecs);  
double elapsed_daysecs = tm->tm_sec + (60*tm->tm_min) + (60*60*tm->tm_hour);  
double daystart = path->time - elapsed_daysecs;  
 
// Figure out service period based on start time, then figure out  
// seconds since midnight on our particular day  
vector<pair<int, int> > vsp = get_service_period_ids_for_time(path->time);  
 
DEBUGPATH("Extending path at vertex %d (on %d) @ %f (walktime: %f, "  
"routetime: %f elapsed_daysecs: %f)\n", src_id, last_route_id, path->time,  
path->walking_time, path->route_time, elapsed_daysecs);  
shared_ptr<TripStop> src_stop = _get_tripstop(src_id);  
 
// Keep track of outgoing route ids at this node: make sure that we  
// don't get on a route later when we could have gotten on here.  
deque<int> outgoing_route_ids;  
if (!walkonly)  
{  
for (vector<pair<int, int> >::iterator i = vsp.begin(); i != vsp.end(); i++)  
{  
deque<int> route_ids = src_stop->get_routes(i->first);  
for (deque<int>::iterator j = route_ids.begin(); j != route_ids.end(); j++)  
outgoing_route_ids.push_back(*j);  
}  
}  
 
// Explore walkhops that are better than the ones we've already visited.  
// If we're on a bus, don't allow a transfer if we've been on for  
// less than 5 minutes (FIXME: probably better to measure distance  
// travelled?)  
if (last_route_id == -1 || path->route_time > (2 * 60))  
{  
for (TripStop::WalkHopList::iterator i = src_stop->wlist.begin();  
i != src_stop->wlist.end(); i++)  
{  
int32_t dest_id = i->dest_id;  
double walktime = i->walktime;  
 
// Do a quick test to make sure that the potential basis for a  
// new path isn't worse than what we have already, before  
// incurring the cost of creating a new path and evaluating it.  
unordered_map<int32_t, shared_ptr<TripPath> > vsrc = visited_walks[src_id];  
unordered_map<int32_t, shared_ptr<TripPath> >::iterator v1 = vsrc.find(dest_id);  
if (v1 != vsrc.end() && path->heuristic_weight > v1->second->heuristic_weight)  
continue;  
 
shared_ptr<TripAction> action(  
new TripAction(src_id, dest_id, -1, path->time,  
(path->time + walktime)));  
shared_ptr<TripStop> ds = _get_tripstop(dest_id);  
shared_ptr<TripPath> path2 = path->add_action(  
action, outgoing_route_ids, ds);  
 
DEBUGPATH("- Considering walkpath to %d\n", dest_id);  
 
if (v1 == vsrc.end() ||  
v1->second->heuristic_weight > path2->heuristic_weight ||  
((v1->second->heuristic_weight - path2->heuristic_weight) < 1.0f &&  
v1->second->walking_time > path2->walking_time))  
{  
DEBUGPATH("-- Adding walkpath to %d (walktime: %f (%f, %f))\n", dest_id, walktime, action->start_time, action->end_time);  
if (dest_id == goal_id)  
completed_paths.push(path2);  
else  
uncompleted_paths.push(path2);  
 
num_paths_considered++;  
visited_walks[src_id][dest_id] = path2;  
}  
}  
}  
 
 
// If we're doing a walkonly path (mostly for generating shapes?), stop  
// and return here.  
if (walkonly)  
return;  
 
// Find outgoing triphops from the source and get a list of paths to them.  
for (vector<pair<int, int> >::iterator sp = vsp.begin(); sp != vsp.end();  
sp++)  
{  
deque<int> route_ids = src_stop->get_routes(sp->first);  
for (deque<int>::iterator j = route_ids.begin(); j != route_ids.end(); j++)  
{  
int LEEWAY = 0;  
if ((*j) != last_route_id)  
LEEWAY = (5*60); // give 5 mins to make a transfer  
 
const TripHop * t = src_stop->find_triphop(  
elapsed_daysecs + sp->second + LEEWAY, (*j), sp->first);  
if (t)  
{  
// If we've been on the route before (or could have been),  
// don't get on again.  
if ((*j) != last_route_id && path->possible_route_ids.count(*j))  
{  
// pass  
}  
// Disallow more than three transfers.  
else if ((*j) != last_route_id &&  
path->traversed_route_ids > 3)  
{  
// pass  
}  
else  
{  
// Do a quick test to make sure that the potential basis for a  
// new path isn't worse than what we have already, before  
// incurring the cost of creating a new path and evaluating it.  
unordered_map<int, shared_ptr<TripPath> >::iterator v = visited_routes[src_id].find(*j);  
if (v != visited_routes[src_id].end() && path->heuristic_weight > v->second->heuristic_weight)  
continue;  
 
shared_ptr<TripAction> action = shared_ptr<TripAction>(  
new TripAction(src_id, t->dest_id, (*j), daystart + t->start_time,  
daystart + t->end_time));  
shared_ptr<TripStop> ds = _get_tripstop(t->dest_id);  
shared_ptr<TripPath> path2 = path->add_action(  
action, outgoing_route_ids, ds);  
 
 
if (v == visited_routes[src_id].end() ||  
v->second->heuristic_weight > path2->heuristic_weight ||  
((v->second->heuristic_weight - path2->heuristic_weight) < 1.0f &&  
v->second->walking_time > path2->walking_time))  
{  
if (t->dest_id == goal_id)  
completed_paths.push(path2);  
else  
uncompleted_paths.push(path2);  
 
num_paths_considered++;  
visited_routes[src_id][(*j)] = path2;  
}  
}  
}  
}  
}  
}  
 
 
vector<TripStop> TripGraph::find_tripstops_in_range(double lat, double lng,  
TripStop::Type type,  
double range)  
{  
vector<TripStop> tripstops_in_range;  
 
for (TripStopList::iterator i = tripstops.begin();  
i != tripstops.end(); i++)  
{  
if ((*i)->type != type)  
continue;  
 
double dist = distance((*i)->lat, (*i)->lng, lat, lng);  
if (dist <= range)  
tripstops_in_range.push_back(*(*i));  
}  
 
return tripstops_in_range;  
}  
 
#include "trippath.h"  
#include <math.h>  
 
#if 0  
#define LOG(...) fprintf(stderr, __VA_ARGS__)  
#else  
#define LOG(...)  
#endif  
 
using namespace std;  
using namespace tr1;  
 
static inline double radians(double degrees)  
{  
return degrees/180.0f*M_PI;  
}  
 
static inline double degrees(double radians)  
{  
return radians*180.0f/M_PI;  
}  
 
static double distance(double src_lat, double src_lng, double dest_lat, double dest_lng)  
{  
if (src_lat == dest_lat && src_lng == dest_lng)  
return 0.0f;  
 
double theta = src_lng - dest_lng;  
double src_lat_radians = radians(src_lat);  
double dest_lat_radians = radians(dest_lat);  
double dist = sin(src_lat_radians) * sin(dest_lat_radians) +  
cos(src_lat_radians) * cos(dest_lat_radians) *  
cos(radians(theta));  
dist = acos(dist);  
dist = degrees(dist);  
dist *= (60.0f * 1.1515 * 1.609344 * 1000.0f);  
return dist;  
}  
 
 
TripAction::TripAction(int32_t _src_id, int32_t _dest_id,  
int _route_id, double _start_time, double _end_time) :  
src_id(_src_id),  
dest_id(_dest_id),  
route_id(_route_id),  
start_time(_start_time),  
end_time(_end_time),  
parent()  
{  
}  
 
 
TripAction::TripAction(const TripAction &other):  
src_id(other.src_id),  
dest_id(other.dest_id),  
route_id(other.route_id),  
start_time(other.start_time),  
end_time(other.end_time),  
parent(other.parent)  
{  
}  
 
 
TripAction& TripAction::operator=(const TripAction &other)  
{  
src_id = other.src_id;  
dest_id = other.dest_id;  
route_id = other.route_id;  
start_time = other.start_time;  
end_time = other.end_time;  
parent = other.parent;  
}  
 
TripPath::TripPath(double _time, double _fastest_speed,  
shared_ptr<TripStop> &_dest_stop,  
shared_ptr<TripStop> &_last_stop)  
{  
fastest_speed = _fastest_speed;  
dest_stop = _dest_stop;  
last_stop = _last_stop;  
time = _time;  
 
walking_time = 0.0f;  
weight = _time;  
traversed_route_ids = 0;  
last_route_id = -1;  
route_time = 0.0f;  
_get_heuristic_weight();  
}  
 
#if 0  
python::object TripPath::get_last_action()  
{  
if (last_action)  
return python::object(*last_action);  
 
return python::object();  
}  
#endif  
 
void TripPath::_get_heuristic_weight()  
{  
// start off with heuristic weight being equivalent to its real weight  
heuristic_weight = weight;  
 
// then, calculate the time remaining based on going directly  
// from the last vertex to the destination vertex at the fastest  
// possible speed in the graph  
double remaining_distance = distance(last_stop->lat, last_stop->lng,  
dest_stop->lat, dest_stop->lng);  
heuristic_weight += remaining_distance / 5; //(fastest_speed / 3);  
 
// now, add 5 minutes per each transfer, multiplied to the power of 2  
// (to make transfers exponentially more painful)  
if (traversed_route_ids > 1)  
heuristic_weight += (pow(2.0f, (int)(traversed_route_ids-2)) * 5.0f * 60.0f);  
 
// double the cost of walking after 5 mins, quadruple after 10 mins,  
// octuple after 15, etc. (up to a maximum of 20 iterations of this, to  
// make sure we don't freeze for particularly long walking times-- mostly  
// useful for obscure test cases)  
double excess_walking_time = walking_time - 300.0f;  
int iter = 0;  
while (excess_walking_time > 0 && iter < 20)  
{  
double iter_walking_time = 0;  
if (excess_walking_time > 300.0f)  
iter_walking_time = 300.0f;  
else  
iter_walking_time = excess_walking_time;  
heuristic_weight += (iter_walking_time * pow(2.0f, iter));  
excess_walking_time -= 300.0f;  
iter++;  
}  
 
// add 5 mins to our weight if we were walking and remaining distance  
// >1000m, to account for the fact that we're probably going to  
// want to wait for another bus. this prevents us from repeatedly  
// getting out of the bus and walking around  
if (last_route_id == -1 && remaining_distance > 1000)  
heuristic_weight += (5*60);  
}  
 
static void _add_actions_to_list(deque<TripAction> &l,  
shared_ptr<TripAction> &action)  
{  
if (action)  
{  
if (action->parent)  
_add_actions_to_list(l, action->parent);  
l.push_back(TripAction(*action));  
}  
}  
 
deque<TripAction> TripPath::get_actions()  
{  
deque<TripAction> l;  
 
// recursively add actions to list, so we get them back in the  
// correct order  
_add_actions_to_list(l, last_action);  
 
return l;  
}  
 
shared_ptr<TripPath> TripPath::add_action(shared_ptr<TripAction> &action,  
deque<int> &_possible_route_ids,  
shared_ptr<TripStop> &_last_stop)  
{  
shared_ptr<TripPath> new_trippath(new TripPath(*this));  
 
float departure_delay = 0.0f;  
 
if (action->route_id == -1)  
{  
new_trippath->walking_time += (action->end_time - action->start_time);  
new_trippath->route_time = 0;  
}  
else if (new_trippath->last_action)  
{  
// Starting first bus route, adjust the start time to match.  
if (new_trippath->traversed_route_ids == 0)  
{  
departure_delay =  
action->start_time - new_trippath->last_action->end_time;  
// Aim to be at the bus stop 3 minutes early.  
departure_delay -= 3*60;  
}  
 
if (action->route_id != new_trippath->last_action->route_id)  
{  
new_trippath->traversed_route_ids++;  
new_trippath->route_time = 0;  
}  
}  
 
for (deque<int>::iterator i = _possible_route_ids.begin();  
i != _possible_route_ids.end(); i++)  
{  
new_trippath->possible_route_ids.insert(*i);  
}  
 
new_trippath->route_time += (action->end_time - action->start_time);  
new_trippath->weight += (action->end_time - action->start_time);  
new_trippath->weight += (action->start_time - time);  
 
if (new_trippath->last_action)  
action->parent = new_trippath->last_action;  
new_trippath->last_action = shared_ptr<TripAction>(new TripAction(*action));  
new_trippath->last_stop = _last_stop;  
new_trippath->last_route_id = action->route_id;  
new_trippath->_get_heuristic_weight();  
new_trippath->time = action->end_time;  
 
if (departure_delay > 0.0f)  
{  
LOG("Delaying start by %f seconds\n", departure_delay);  
new_trippath->delay_walk(new_trippath->last_action, departure_delay);  
}  
 
return new_trippath;  
}  
 
 
void TripPath::delay_walk(shared_ptr<TripAction> walk, float secs)  
{  
if (!walk)  
return;  
 
// Don't delay partial walks; we need to be given the element *after*  
// the final walk.  
if (walk->route_id == -1)  
return;  
 
// Only delay actual walks.  
if (!walk->parent || walk->parent->route_id != -1)  
return;  
 
shared_ptr<TripAction> w(walk);  
while (w && w->parent && w->parent->route_id == -1)  
{  
// We need to clone the actions, as they're no longer safe to share  
// (for instance, they could be shared by another bus trip that leaves  
// earlier).  
w->parent = shared_ptr<TripAction>(new TripAction(*(w->parent)));  
w = w->parent;  
 
w->start_time += secs;  
w->end_time += secs;  
}  
 
// If we delayed the initial walk, then we've reduced the total trip time.  
if (!w)  
{  
weight -= secs;  
_get_heuristic_weight();  
}  
}  
 
 
#include "defuns.h"  
#include "tripstop.h"  
#include <algorithm>  
#include <stdio.h>  
 
 
using namespace std;  
using namespace tr1;  
 
 
TripStop::TripStop(FILE *fp)  
{  
assert(fread(&id, sizeof(int32_t), 1, fp) == 1);  
assert(fread(&type, sizeof(Type), 1, fp) == 1);  
assert(fread(&lat, sizeof(float), 1, fp) == 1);  
assert(fread(&lng, sizeof(float), 1, fp) == 1);  
 
uint8_t have_triphops;  
assert(fread(&have_triphops, sizeof(uint8_t), 1, fp) == 1);  
 
if (have_triphops)  
{  
tdict = shared_ptr<ServiceDict>(new ServiceDict);  
 
uint32_t num_service_periods;  
assert(fread(&num_service_periods, sizeof(uint32_t), 1, fp) == 1);  
for (uint32_t i=0; i<num_service_periods; i++)  
{  
int32_t sp_id;  
assert(fread(&sp_id, sizeof(int32_t), 1, fp) == 1);  
 
uint32_t num_route_ids;  
assert(fread(&num_route_ids, sizeof(uint32_t), 1, fp) == 1);  
for (uint32_t j=0; j<num_route_ids; j++)  
{  
int32_t route_id;  
assert(fread(&route_id, sizeof(int32_t), 1, fp) == 1);  
 
uint32_t num_triphops = 0;  
assert(fread(&num_triphops, sizeof(uint32_t), 1, fp) == 1);  
(*tdict)[sp_id][route_id].reserve(num_triphops);  
for (uint32_t k=0; k<num_triphops; k++)  
{  
TripHop t;  
assert(fread(&t, sizeof(TripHop), 1, fp) == 1);  
assert(t.end_time >= t.start_time); // FIXME: should be >, no?  
(*tdict)[sp_id][route_id].push_back(t);  
}  
}  
 
}  
}  
 
uint32_t num_walkhops = 0;  
assert(fread(&num_walkhops, sizeof(uint32_t), 1, fp) == 1);  
for (int i=0; i<num_walkhops; i++)  
{  
int32_t dest_id;  
float walktime;  
assert(fread(&dest_id, sizeof(int32_t), 1, fp) == 1);  
assert(fread(&walktime, sizeof(float), 1, fp) == 1);  
assert(walktime >= 0.0f); // FIXME, should be >, no?  
add_walkhop(dest_id, walktime);  
}  
}  
 
 
TripStop::TripStop(int32_t _id, Type _type, float _lat, float _lng)  
{  
id = _id;  
type = _type;  
lat = _lat;  
lng = _lng;  
}  
 
 
TripStop::TripStop()  
{  
}  
 
 
void TripStop::write(FILE *fp)  
{  
assert(fwrite(&id, sizeof(int32_t), 1, fp) == 1);  
assert(fwrite(&type, sizeof(Type), 1, fp) == 1);  
assert(fwrite(&lat, sizeof(float), 1, fp) == 1);  
assert(fwrite(&lng, sizeof(float), 1, fp) == 1);  
 
uint8_t have_triphops = tdict ? 1 : 0;  
assert(fwrite(&have_triphops, sizeof(uint8_t), 1, fp) == 1);  
 
if (tdict)  
{  
uint32_t num_service_periods = tdict->size();  
assert(fwrite(&num_service_periods, sizeof(uint32_t), 1, fp) == 1);  
 
for (ServiceDict::iterator i = tdict->begin(); i != tdict->end(); i++)  
{  
assert(fwrite(&(i->first), sizeof(int32_t), 1, fp) == 1);  
uint32_t num_route_ids = i->second.size();  
assert(fwrite(&num_route_ids, sizeof(uint32_t), 1, fp) == 1);  
for (TripHopDict::iterator j = i->second.begin();  
j != i->second.end(); j++)  
{  
int32_t route_id = j->first;  
assert(fwrite(&route_id, sizeof(int32_t), 1, fp) == 1);  
uint32_t num_triphops = j->second.size();  
assert(fwrite(&num_triphops, sizeof(uint32_t), 1, fp) == 1);  
for (TripHopList::iterator k = j->second.begin();  
k != j->second.end(); k++)  
{  
assert(fwrite(&(*k), sizeof(TripHop), 1, fp) == 1);  
}  
}  
}  
}  
 
uint32_t num_walkhops = wlist.size();  
assert(fwrite(&num_walkhops, sizeof(uint32_t), 1, fp) == 1);  
for (WalkHopList::iterator i = wlist.begin(); i != wlist.end(); i++)  
{  
assert(fwrite(&(*i), sizeof(WalkHop), 1, fp) == 1);  
}  
}  
 
 
static bool sort_triphops(const TripHop &x,  
const TripHop &y)  
{  
return x.start_time < y.start_time;  
}  
 
 
void TripStop::add_triphop(int32_t start_time, int32_t end_time,  
int32_t dest_id, int32_t route_id, int32_t trip_id,  
int32_t service_id)  
{  
if (!tdict)  
tdict = shared_ptr<ServiceDict>(new ServiceDict);  
 
(*tdict)[service_id][route_id].push_back(TripHop(start_time, end_time,  
dest_id, trip_id));  
::sort((*tdict)[service_id][route_id].begin(),  
(*tdict)[service_id][route_id].end(), sort_triphops);  
}  
 
 
void TripStop::add_walkhop(int32_t dest_id, float walktime)  
{  
wlist.push_front(WalkHop(dest_id, walktime));  
}  
 
 
const TripHop * TripStop::find_triphop(int time, int route_id,  
int32_t service_id)  
{  
if (tdict)  
{  
for (TripHopList::iterator i = (*tdict)[service_id][route_id].begin();  
i != (*tdict)[service_id][route_id].end(); i++)  
{  
if ((*i).start_time >= time)  
return &(*i);  
}  
}  
 
return NULL;  
}  
 
 
vector<TripHop> TripStop::find_triphops(int time, int route_id,  
int32_t service_id,  
int num)  
{  
vector<TripHop> tlist;  
 
if (tdict)  
{  
for (TripHopList::iterator i = (*tdict)[service_id][route_id].begin();  
(i != ((*tdict)[service_id][route_id].end()) && tlist.size() < num);  
i++)  
{  
if ((*i).start_time >= time)  
tlist.push_back(*i);  
}  
}  
 
return tlist;  
}  
 
 
deque<int> TripStop::get_routes(int32_t service_id)  
{  
deque<int> routes;  
 
if (tdict)  
{  
for (TripHopDict::iterator i = (*tdict)[service_id].begin();  
i != (*tdict)[service_id].end(); i++)  
{  
routes.push_back(i->first);  
}  
}  
 
return routes;  
}  
 
 
#!/usr/bin/python  
 
# The code in this module was gratuitously stolen from  
# graphserver (http://graphserver.sourceforge.net/)  
# Copyright (c) 2007, Brandon Martin-Anderson  
 
import xml.sax  
import copy  
import sys  
from math import *  
 
class Node:  
def __init__(self, id, lon, lat):  
self.id = id  
self.lon = lon  
self.lat = lat  
self.tags = {}  
 
class Way:  
def __init__(self, id, osm):  
self.osm = osm  
self.id = id  
self.nds = []  
self.tags = {}  
 
def split(self, dividers):  
# slice the node-array using this nifty recursive function  
def slice_array(ar, dividers):  
for i in range(1,len(ar)-1):  
if dividers[ar[i]]>1:  
#print "slice at %s"%ar[i]  
left = ar[:i+1]  
right = ar[i:]  
 
rightsliced = slice_array(right, dividers)  
 
return [left]+rightsliced  
return [ar]  
 
slices = slice_array(self.nds, dividers)  
 
# create a way object for each node-array slice  
ret = []  
i=0  
for slice in slices:  
littleway = copy.copy( self )  
littleway.id += "-%d"%i  
littleway.nds = slice  
ret.append( littleway )  
i += 1  
 
return ret  
 
def get_projected_points(self, reprojection_func=lambda x,y:(x,y)):  
"""nodedir is a dictionary of nodeid->node objects. If reprojection_func is None, returns unprojected points"""  
ret = []  
 
for nodeid in self.nds:  
node = self.osm.nodes[ nodeid ]  
ret.append( reprojection_func(node.lon,node.lat) )  
 
return ret  
 
def to_canonical(self, srid, reprojection_func=None):  
"""Returns canonical string for this geometry"""  
 
return "SRID=%d;LINESTRING(%s)"%(srid, ",".join( ["%f %f"%(x,y) for x,y in self.get_projected_points()] ) )  
 
@property  
def fromv(self):  
return self.nds[0]  
 
@property  
def tov(self):  
return self.nds[-1]  
 
class OSM:  
 
def __init__(self, filename_or_stream):  
""" File can be either a filename or stream/file object."""  
nodes = {}  
ways = {}  
 
superself = self  
 
class OSMHandler(xml.sax.ContentHandler):  
@classmethod  
def setDocumentLocator(self,loc):  
pass  
 
@classmethod  
def startDocument(self):  
pass  
 
@classmethod  
def endDocument(self):  
pass  
 
@classmethod  
def startElement(self, name, attrs):  
if name=='node':  
if (int(attrs['id']) % 1000) == 0:  
print "Parsing node %s" % attrs['id']  
self.currElem = Node(attrs['id'], float(attrs['lon']), float(attrs['lat']))  
elif name=='way':  
if (int(attrs['id']) % 1000) == 0:  
print "Parsing way %s" % attrs['id']  
self.currElem = Way(attrs['id'], superself)  
elif name=='tag':  
pass  
#self.currElem.tags[attrs['k']] = attrs['v']  
elif name=='nd':  
self.currElem.nds.append( attrs['ref'] )  
 
@classmethod  
def endElement(self,name):  
if name=='node':  
nodes[self.currElem.id] = self.currElem  
elif name=='way':  
ways[self.currElem.id] = self.currElem  
 
@classmethod  
def characters(self, chars):  
pass  
 
xml.sax.parse(filename_or_stream, OSMHandler)  
 
self.nodes = nodes  
self.ways = ways  
 
#count times each node is used  
node_histogram = dict.fromkeys( self.nodes.keys(), 0 )  
print "Counting and pruning ways"  
for way in self.ways.values():  
#if a way has only one node, delete it out of the osm collection  
#similarly if it's not a road  
if len(way.nds) < 2:# or not way.tags.get('highway') or way.tags['highway'] == 'footway':  
del self.ways[way.id]  
else:  
for node in way.nds:  
# toss out any ways that don't have all nodes on map  
if not self.nodes.get(node) and self.ways.get(way.id):  
del self.ways[way.id]  
elif self.ways.get(way.id):  
node_histogram[node] += 1  
 
# delete nodes that don't appear in ways  
for node in self.nodes.values():  
if node_histogram[node.id] == 0:  
del self.nodes[node.id]  
 
#use that histogram to split all ways, replacing the member set of ways  
print "Splitting ways"  
new_ways = {}  
for id, way in self.ways.iteritems():  
split_ways = way.split(node_histogram)  
for split_way in split_ways:  
new_ways[split_way.id] = split_way  
self.ways = new_ways  
 
@property  
def connecting_nodes(self):  
"""List of nodes that are the endpoint of one or more ways"""  
 
ret = {}  
for way in self.ways.values():  
ret[way.fromv] = self.nodes[way.fromv]  
ret[way.tov] = self.nodes[way.tov]  
 
return ret  
 
%module routez  
%include tripgraph.i  
// just a blank file to get the unit test main function going  
 
#!/usr/bin/python  
 
# This is here mostly just to test that the python bindings actually work  
 
from libroutez.tripgraph import *  
import time  
from wvtest import *  
 
last=None  
 
@wvtest  
def basic_find_path():  
graph = TripGraph()  
graph.add_tripstop(0, TripStop.OSM, 0.0, 0.0)  
graph.add_tripstop(1, TripStop.OSM, 1.0, 0.0)  
 
# no path available  
p = graph.find_path(0, True, 0.0, 0.0, 1.0, 0.0)  
WVPASSEQ(p, None)  
 
# walking only  
graph.add_walkhop(0, 1)  
p = graph.find_path(0, True, 0.0, 0.0, 1.0, 0.0)  
actions = p.get_actions()  
WVPASSEQ(len(actions), 1)  
 
 
@wvtest  
def get_service_period_offsets():  
graph = TripGraph()  
graph.add_service_period(ServicePeriod(0, 1, 0, 108, 7, 0, 108, 2000,  
False, True, False))  
t = time.mktime((2008, 1, 5, 0, 0, 0, 0, 0, -1))  
splist = graph.get_service_period_ids_for_time(int(t))  
WVPASSEQ(splist[0][0], 0)  
WVPASSEQ(splist[0][1], 0)  
 
 
@wvtest  
def tripstop():  
ts = TripStop(0, TripStop.OSM, 0.0, 0.0);  
ts.add_triphop(500, 1000, 1, 1, 1, 0);  
route_ids = ts.get_routes(0)  
WVPASSEQ(len(route_ids), 1)  
WVPASSEQ(route_ids[0], 1)  
 
#include "wvtest.h"  
#include "tripgraph.h"  
 
using namespace std;  
 
 
WVTEST_MAIN("basic_graph_pathfinding")  
{  
TripGraph g;  
 
// simple path, just walking  
g.add_tripstop(0, TripStop::OSM, 0.0f, 0.0f);  
g.add_tripstop(1, TripStop::OSM, 1.0f, 0.0f);  
g.add_walkhop(0, 1);  
 
{  
TripPath *p = g.find_path(0, false, 0.0, 0.0, 1.0, 0.0);  
 
std::deque<TripAction> actions = p->get_actions();  
WVPASSEQ(actions.size(), 1);  
 
TripAction action = actions.front();  
WVPASSEQ(action.src_id, 0);  
WVPASSEQ(action.dest_id, 1);  
 
delete p;  
}  
 
// take the triphop if we have it  
{  
ServicePeriod s(0, 0, 0, 0, 7, 0, 100, 2000, true, true, true);  
g.add_service_period(s);  
g.add_triphop(500, 1000, 0, 1, 1, 1, 0);  
}  
 
{  
TripPath *p = g.find_path(0, false, 0.0, 0.0, 1.0, 0.0);  
 
std::deque<TripAction> actions = p->get_actions();  
WVPASSEQ(actions.size(), 1);  
 
TripAction action = actions.front();  
WVPASSEQ(action.src_id, 0);  
WVPASSEQ(action.dest_id, 1);  
WVPASSEQ(action.start_time, 500.0f);  
WVPASSEQ(action.end_time, 1000.0f);  
 
delete p;  
}  
}  
 
 
WVTEST_MAIN("basic_graph_saveload")  
{  
TripGraph g;  
g.add_tripstop(0, TripStop::OSM, 0.0f, 0.0f);  
g.add_tripstop(1, TripStop::OSM, 1.0f, 0.0f);  
g.add_walkhop(0, 1);  
 
ServicePeriod s(0, 1, 0, 0, 7, 0, 100, 2000, true, true, true);  
g.add_service_period(s);  
g.add_triphop(500, 1000, 0, 1, 1, 1, 0);  
 
char *tmpgraphname = tmpnam(NULL); // security issues in unit tests? bah.  
unlink(tmpgraphname);  
g.save(tmpgraphname);  
 
TripGraph g2;  
g2.load(tmpgraphname);  
 
// verify that we have two tripstops  
for (int i=0; i<2; i++)  
{  
TripStop ts = g2.get_tripstop(i);  
WVPASSEQ(ts.type, TripStop::OSM);  
}  
 
// verify that we can still solve a basic path  
{  
TripPath *p = g.find_path(0, false, 0.0, 0.0, 1.0, 0.0);  
 
std::deque<TripAction> actions = p->get_actions();  
WVPASSEQ(actions.size(), 1);  
 
TripAction action = actions.front();  
WVPASSEQ(action.src_id, 0);  
WVPASSEQ(action.dest_id, 1);  
WVPASSEQ(action.start_time, 500.0f);  
WVPASSEQ(action.end_time, 1000.0f);  
 
delete p;  
}  
}  
 
 
WVTEST_MAIN("impossible_path")  
{  
TripGraph g;  
g.add_tripstop(0, TripStop::OSM, 0.0f, 0.0f);  
g.add_tripstop(1, TripStop::OSM, 1.0f, 0.0f);  
g.add_tripstop(2, TripStop::OSM, 0.0f, 1.0f);  
g.add_walkhop(0, 1);  
 
TripPath *p = g.find_path(0, false, 0.0, 0.0, 0.0, 1.0);  
WVPASS(!p);  
}  
 
 
WVTEST_MAIN("tripstops_in_range")  
{  
TripGraph g;  
// north and agricola  
g.add_tripstop(0, TripStop::GTFS, 44.6554236f, -63.5936968f);  
// north and robie (just north of north&agricola)  
g.add_tripstop(1, TripStop::OSM, 44.6546407f, -63.5948438f);  
// north and northwood (just south of north&agricola)  
g.add_tripstop(2, TripStop::GTFS, 44.6567144f, -63.5919115f);  
// Quinpool and Connaught (a few kms away from north&agricola)  
g.add_tripstop(3, TripStop::GTFS, 44.6432423f, -63.6045261f);  
 
{  
vector<TripStop> v = g.find_tripstops_in_range(44.6554236f,  
-63.5936968f,  
TripStop::GTFS,  
500.0f);  
WVPASSEQ(v.size(), 2);  
WVPASS(v[0].id == 0 || v[0].id == 2);  
WVPASS(v[1].id == 0 || v[1].id == 2);  
}  
}  
 
 
static time_t get_time_t(int tm_mday, int tm_mon, int tm_year)  
{  
struct tm t;  
t.tm_sec = 0;  
t.tm_min = 0;  
t.tm_hour = 0;  
t.tm_mday = tm_mday;  
t.tm_mon = tm_mon;  
t.tm_year = tm_year;  
t.tm_wday = -1;  
t.tm_yday = -1;  
t.tm_isdst = -1;  
 
return mktime(&t);  
}  
 
WVTEST_MAIN("service_periods")  
{  
TripGraph g;  
 
// from the 1st to the 7th (i.e. 1st saturday only)  
{  
ServicePeriod s(0, 1, 0, 108, 7, 0, 108, 2000, false, true, false);  
g.add_service_period(s);  
}  
 
// test something that's within a supported service period  
// Saturday Midnight Jan 5th 2008  
{  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(5, 0, 108));  
WVPASSEQ(vsp.size(), 1);  
WVPASSEQ(vsp[0].first, 0);  
}  
 
// test something outside a supported service period: day  
// Saturday Midnight Jan 11th 2008  
{  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(11, 0, 108));  
WVPASSEQ(vsp.size(), 0);  
}  
// test something outside a supported service period: month  
// Saturday Midnight Feb 5th 2008  
{  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(5, 1, 108));  
WVPASSEQ(vsp.size(), 0);  
}  
 
// test something outside a supported service period: year  
// Saturday Midnight Jan 11th 2009  
{  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(5, 1, 109));  
WVPASSEQ(vsp.size(), 0);  
}  
 
// add another service period (saturdays for month of january)  
{  
ServicePeriod s(1, 1, 0, 108, 31, 0, 108, 2000, false, true,  
false);  
g.add_service_period(s);  
}  
 
// test something that's within _two_ supported service periods  
// Saturday Midnight Jan 5th 2008  
{  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(5, 0, 108));  
WVPASSEQ(vsp.size(), 2);  
WVPASS(vsp[0].first==0 || vsp[0].first==1);  
WVPASS(vsp[1].first==0 || vsp[1].first==1);  
WVFAILEQ(vsp[0].first, vsp[1].first);  
}  
 
// save graph, reload, make sure service periods are still there  
}  
 
 
WVTEST_MAIN("service_periods_overlapping")  
{  
TripGraph g;  
 
// from the 1st to the 7th (i.e. 1st saturday only)  
// (weekday and saturday schedules)  
{  
ServicePeriod s1(0, 1, 0, 108, 7, 0, 108, 90000, false, true, false);  
g.add_service_period(s1);  
ServicePeriod s2(1, 1, 0, 108, 7, 0, 108, 90000, true, false, false);  
g.add_service_period(s2);  
}  
 
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(5, 0, 108));  
WVPASSEQ(vsp.size(), 2);  
WVPASS(vsp[0].first==0 || vsp[0].first==1);  
WVPASS(vsp[1].first==0 || vsp[1].first==1);  
WVFAILEQ(vsp[0].first, vsp[1].first);  
 
int weekday_index = (vsp[0].first == 1) ? 0 : 1;  
WVPASSEQ(vsp[weekday_index].second, 86400);  
}  
 
 
WVTEST_MAIN("service_periods_turned_on_or_off")  
{  
TripGraph g;  
 
// from the 1st to the 7th (i.e. 1st saturday only)  
// turn off weekday service on the 2nd (wednesday)  
// turn on saturday service on the 3rd (keeping weekday service)  
{  
ServicePeriod s1(0, 1, 0, 108, 7, 0, 108, 80000, false, true, false);  
s1.add_exception_on(3, 0, 108);  
WVPASSEQ(s1.is_turned_on(3, 0, 108), true);  
WVPASSEQ(s1.is_turned_on(4, 0, 108), false);  
g.add_service_period(s1);  
ServicePeriod s2(1, 1, 0, 108, 7, 0, 108, 80000, true, false, false);  
s2.add_exception_off(2, 0, 108);  
WVPASSEQ(s2.is_turned_off(2, 0, 108), true);  
WVPASSEQ(s2.is_turned_off(3, 0, 108), false);  
g.add_service_period(s2);  
}  
 
{  
// should be no service on the 2nd  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(2, 0, 108));  
WVPASSEQ(vsp.size(), 0);  
}  
 
{  
// should be two service periods on the 3rd (saturday and weekday)  
vector<pair<int, int> > vsp = g.get_service_period_ids_for_time(get_time_t(3, 0, 108));  
WVPASSEQ(vsp.size(), 2);  
WVPASS(vsp[0].first==0 || vsp[0].first==1);  
WVPASS(vsp[1].first==0 || vsp[1].first==1);  
WVFAILEQ(vsp[0].first, vsp[1].first);  
}  
}  
 
 
WVTEST_MAIN("service_periods_save_load")  
{  
TripGraph g;  
 
// use the same setup as the previous test: saturday and weekday schedules  
// with a few exceptions  
 
// from the 1st to the 7th (i.e. 1st saturday only)  
// turn off weekday service on the 2nd (wednesday)  
// turn on saturday service on the 3rd (keeping weekday service)  
{  
ServicePeriod s1(0, 1, 0, 108, 7, 0, 108, 80000, false, true, false);  
s1.add_exception_on(3, 0, 108);  
g.add_service_period(s1);  
ServicePeriod s2(1, 1, 0, 108, 7, 0, 108, 80000, true, false, false);  
s2.add_exception_off(2, 0, 108);  
g.add_service_period(s2);  
}  
 
char *tmpgraphname = tmpnam(NULL); // security issues in unit tests? bah.  
unlink(tmpgraphname);  
g.save(tmpgraphname);  
 
TripGraph g2;  
g2.load(tmpgraphname);  
 
{  
// should be no service on the 2nd  
vector<pair<int, int> > vsp = g2.get_service_period_ids_for_time(get_time_t(2, 0, 108));  
WVPASSEQ(vsp.size(), 0);  
}  
 
{  
// should be two service periods on the 3rd (saturday and weekday)  
vector<pair<int, int> > vsp = g2.get_service_period_ids_for_time(get_time_t(3, 0, 108));  
WVPASSEQ(vsp.size(), 2);  
WVPASS(vsp[0].first==0 || vsp[0].first==1);  
WVPASS(vsp[1].first==0 || vsp[1].first==1);  
WVFAILEQ(vsp[0].first, vsp[1].first);  
}  
}  
 
#include "wvtest.h"  
#include "tripstop.h"  
#include <stdio.h>  
 
using namespace std;  
using namespace tr1;  
 
 
WVTEST_MAIN("save/load")  
{  
TripStop t1(1, TripStop::OSM, 44.5f, 54.4f);  
t1.add_triphop(500, 550, 0, 0, 0, 0);  
t1.add_triphop(550, 600, 0, 0, 0, 0);  
 
char *tmpname = tmpnam(NULL); // security issues in unit tests? bah.  
unlink(tmpname);  
FILE *fp1 = fopen(tmpname, "w");  
t1.write(fp1);  
fclose(fp1);  
 
FILE *fp2 = fopen(tmpname, "r");  
TripStop t2(fp2);  
 
WVPASSEQ(t2.id, t1.id);  
WVPASSEQ(t2.type, t1.type);  
WVPASSEQ(t2.lat, t1.lat);  
WVPASSEQ(t2.lng, t1.lng);  
shared_ptr<TripStop::ServiceDict> tdict = t2.tdict;  
WVPASSEQ(tdict->size(), 1);  
WVPASSEQ(((*tdict))[0].size(), 1);  
WVPASSEQ(((*tdict))[0][0].size(), 2);  
WVPASSEQ(((*tdict))[0][0][0].start_time, 500);  
WVPASSEQ(((*tdict))[0][0][1].start_time, 550);  
 
fclose(fp2);  
}  
 
 
WVTEST_MAIN("get_multiple_triphops")  
{  
TripStop t;  
t.add_triphop(500, 550, 0, 0, 0, 0);  
t.add_triphop(550, 600, 0, 0, 0, 0);  
t.add_triphop(600, 650, 0, 0, 0, 0);  
t.add_triphop(600, 650, 0, 0, 0, 1);  
 
// Ask for different amounts...  
 
vector<TripHop> v = t.find_triphops(499, 0, 0, 3);  
WVPASSEQ(v.size(), 3);  
WVPASSEQ(v[0].start_time, 500);  
WVPASSEQ(v[1].start_time, 550);  
WVPASSEQ(v[2].start_time, 600);  
 
v = t.find_triphops(499, 0, 0, 2);  
WVPASSEQ(v.size(), 2);  
WVPASSEQ(v[0].start_time, 500);  
WVPASSEQ(v[1].start_time, 550);  
 
v = t.find_triphops(499, 0, 0, 4);  
WVPASSEQ(v.size(), 3);  
WVPASSEQ(v[0].start_time, 500);  
WVPASSEQ(v[1].start_time, 550);  
WVPASSEQ(v[2].start_time, 600);  
 
v = t.find_triphops(551, 0, 0, 2);  
WVPASSEQ(v.size(), 1);  
WVPASSEQ(v[0].start_time, 600);  
 
}  
 
%module tripgraph  
 
%{  
#include "serviceperiod.h"  
#include "tripgraph.h"  
#include "trippath.h"  
#include "tripstop.h"  
%}  
 
%include "std_string.i"  
%include "std_deque.i"  
%include "std_vector.i"  
%include "std_pair.i"  
%include "inttypes.i"  
%template(ListTripAction) std::deque<TripAction>;  
%template(ListId) std::deque<int>;  
%template(ListTripHop) std::vector<TripHop>;  
%template(ListTripStop) std::vector<TripStop>;  
%template(ServicePeriodTuple) std::pair<int, int>;  
%template(ListServicePeriodTuple) std::vector<std::pair<int, int> >;  
%include "serviceperiod.h"  
%include "tripgraph.h"  
%include "trippath.h"  
%include "tripstop.h"  
 
#!/usr/bin/python  
 
import transitfeed  
import libroutez.osm as osm  
import time  
import sys  
from libroutez.tripgraph import *  
from optparse import OptionParser  
 
class IdMap:  
'''class which maps from gtfs ids -> libroutez ids'''  
def __init__(self):  
self.spmap = {}  
self.stopmap = {}  
self.routemap = {}  
self.tripmap = {}  
 
def save(self, fname):  
f = open(fname, 'w')  
 
print >> f, "Service Periods: {"  
for gtfs_sp_id in sorted(self.spmap.keys()):  
print >>f, " '%s': %s," % (gtfs_sp_id, self.spmap[gtfs_sp_id])  
print >> f, "}"  
 
print >> f, "Stops: {"  
for gtfs_stop_id in sorted(self.stopmap.keys()):  
print >>f, " '%s': %s," % (gtfs_stop_id, self.stopmap[gtfs_stop_id])  
print >> f, "}"  
 
print >> f, "Routes: {"  
for gtfs_route_id in sorted(self.routemap.keys()):  
print >>f, " '%s': %s," % (gtfs_route_id,  
self.routemap[gtfs_route_id])  
print >> f, "}"  
 
print >> f, "Trips: {"  
for gtfs_trip_id in sorted(self.tripmap.keys()):  
print >> f, " '%s': %s," % (gtfs_trip_id, self.tripmap[gtfs_trip_id])  
print >> f, "}"  
 
f.close()  
 
def load_gtfs(tripgraph, sched, idmap):  
print "Setting timezone to %s" % sched.GetDefaultAgency().agency_timezone  
tripgraph.set_timezone(str(sched.GetDefaultAgency().agency_timezone))  
 
stops = sched.GetStopList()  
for stop in stops:  
idmap.stopmap[stop.stop_id] = len(idmap.stopmap)  
tripgraph.add_tripstop(idmap.stopmap[stop.stop_id], TripStop.GTFS,  
stop.stop_lat, stop.stop_lon)  
 
for sp_id in sched.service_periods.keys():  
idmap.spmap[sp_id] = len(idmap.spmap)  
 
service_period_bounds = {}  
 
trips = sched.GetTripList()  
for trip in trips:  
interpolated_stops = trip.GetTimeInterpolatedStops()  
prevstop = None  
prevsecs = 0  
for (secs, stoptime, is_timepoint) in interpolated_stops:  
stop = stoptime.stop  
if prevstop:  
# stupid side-effect of google's transit feed python script being broken  
if int(secs) < int(prevsecs):  
print "WARNING: Negative edge in gtfs. This probably means you "  
"need a more recent version of the google transit feed "  
"package (see README)"  
if not idmap.tripmap.has_key(trip.trip_id):  
idmap.tripmap[trip.trip_id] = len(idmap.tripmap)  
if not idmap.routemap.has_key(trip.route_id):  
idmap.routemap[trip.route_id] = len(idmap.routemap)  
 
if not service_period_bounds.has_key(trip.service_id):  
service_period_bounds[trip.service_id] = prevsecs  
elif prevsecs > service_period_bounds[trip.service_id]:  
service_period_bounds[trip.service_id] = prevsecs  
 
if prevstop.stop_id != stop.stop_id:  
# only add triphop if we're not going to ourselves. there are  
# some feeds (cough, cough, Halifax) which actually do this  
tripgraph.add_triphop(prevsecs, secs, idmap.stopmap[prevstop.stop_id],  
idmap.stopmap[stop.stop_id],  
idmap.routemap[trip.route_id],  
idmap.tripmap[trip.trip_id],  
idmap.spmap[trip.service_id])  
prevstop = stop  
prevsecs = secs  
 
for sp_id in sched.service_periods.keys():  
sp = sched.service_periods[sp_id]  
if not sp.start_date or not sp.end_date:  
continue  
tm_start = time.strptime(sp.start_date, "%Y%m%d")  
tm_end = time.strptime(sp.end_date, "%Y%m%d")  
# FIXME: currently assume weekday service is uniform, i.e.  
# monday service == mon-fri service  
if service_period_bounds.has_key(sp_id):  
s = ServicePeriod(idmap.spmap[sp_id],  
tm_start.tm_mday, tm_start.tm_mon - 1,  
(tm_start.tm_year - 1900),  
tm_end.tm_mday, tm_end.tm_mon - 1,  
(tm_end.tm_year - 1900),  
int(service_period_bounds[sp_id]),  
sp.day_of_week[0], sp.day_of_week[5],  
sp.day_of_week[6])  
for ex in sp.date_exceptions.keys():  
tm_ex = time.strptime(ex, "%Y%m%d")  
if sp.date_exceptions[ex] == 1:  
s.add_exception_on(tm_ex.tm_mday, tm_ex.tm_mon - 1,  
tm_ex.tm_year - 1900)  
else:  
s.add_exception_off(tm_ex.tm_mday, tm_ex.tm_mon - 1,  
tm_ex.tm_year - 1900)  
 
tripgraph.add_service_period(s)  
else:  
print "WARNING: It appears as if we have a service period with no "  
"bound. This implies that it's not actually being used for anything."  
 
 
def load_osm(tripgraph, map, idmap):  
# map of osm ids -> libroutez ids. libroutez ids are positive integers,  
# starting from the last gtfs id. I'm assuming that OSM ids can be pretty  
# much anything  
osm_nodemap = {}  
for node in map.nodes.values():  
osm_nodemap[node.id] = len(osm_nodemap) + len(idmap.stopmap)  
tripgraph.add_tripstop(osm_nodemap[node.id], TripStop.OSM,  
node.lat, node.lon)  
 
for way in map.ways.values():  
previd = None  
for id in way.nds:  
if previd:  
tripgraph.add_walkhop(osm_nodemap[previd], osm_nodemap[id])  
tripgraph.add_walkhop(osm_nodemap[id], osm_nodemap[previd])  
previd = id  
 
if __name__ == '__main__':  
 
usage = "usage: %prog [options] <gtfs feed> <graph> <gtfs mapping>"  
parser = OptionParser(usage)  
parser.add_option('--osm', dest='osm',  
help='Path of OSM file (optional)')  
 
(options, args) = parser.parse_args()  
 
if len(args) < 3:  
parser.error("incorrect number of arguments")  
exit(1)  
 
print "Loading schedule."  
schedule = transitfeed.Schedule(  
problem_reporter=transitfeed.ProblemReporter())  
schedule.Load(args[0])  
print "Creating graph"  
g = TripGraph()  
print "Inserting gtfs into graph"  
idmap = IdMap()  
load_gtfs(g, schedule, idmap)  
 
if options.osm:  
print "Loading OSM."  
map = osm.OSM(options.osm)  
print "Inserting osm into graph"  
load_osm(g, map, idmap)  
print "Linking osm with gtfs"  
g.link_osm_gtfs()  
 
print "Saving idmap"  
idmap.save(args[2])  
 
print "Saving graph"  
g.save(args[1])  
 
#!/usr/bin/python  
 
import zipfile  
from optparse import OptionParser  
 
if __name__ == '__main__':  
parser = OptionParser()  
(options, args) = parser.parse_args()  
 
zip = zipfile.ZipFile(args[0], mode='r')  
stoptext = zip.read("stops.txt")  
lines = stoptext.split('\n')  
 
descriptors = lines[0].split(',')  
(stop_lat_descriptor, stop_lng_descriptor) = (-1, -1)  
id = 0  
for descriptor in descriptors:  
if descriptor == "stop_lat":  
stop_lat_descriptor = id  
elif descriptor == "stop_lon":  
stop_lng_descriptor = id  
id+=1  
 
(min_lat, min_lng, max_lat, max_lng) = (0.0, 0.0, 0.0, 0.0)  
for line in lines[1:-2:]:  
stop_info = line.split(',')  
(lat, lng) = (float(stop_info[stop_lat_descriptor]),  
float(stop_info[stop_lng_descriptor]))  
if min_lat == 0.0 or lat < min_lat:  
min_lat = lat  
if min_lng == 0.0 or lng < min_lng:  
min_lng = lng  
if max_lat == 0.0 or lat > max_lat:  
max_lat = lat  
if max_lng == 0.0 or lng > max_lng:  
max_lng = lng  
 
print "Polygon:"  
print "%s\t%s" % (min_lat, min_lng)  
print "%s\t%s" % (min_lat, max_lng)  
print "%s\t%s" % (max_lat, max_lng)  
print "%s\t%s" % (max_lat, min_lng)  
print "min_lat, min_lng, max_lat, max_lng: %s %s %s %s" % \  
(min_lat, min_lng, max_lat, max_lng)  
 
GNU LIBRARY GENERAL PUBLIC LICENSE  
Version 2, June 1991  
 
Copyright (C) 1991 Free Software Foundation, Inc.  
675 Mass Ave, Cambridge, MA 02139, USA  
Everyone is permitted to copy and distribute verbatim copies  
of this license document, but changing it is not allowed.  
 
[This is the first released version of the library GPL. It is  
numbered 2 because it goes with version 2 of the ordinary GPL.]  
 
Preamble  
 
The licenses for most software are designed to take away your  
freedom to share and change it. By contrast, the GNU General Public  
Licenses are intended to guarantee your freedom to share and change  
free software--to make sure the software is free for all its users.  
 
This license, the Library General Public License, applies to some  
specially designated Free Software Foundation software, and to any  
other libraries whose authors decide to use it. You can use it for  
your libraries, too.  
 
When we speak of free software, we are referring to freedom, not  
price. Our General Public Licenses are designed to make sure that you  
have the freedom to distribute copies of free software (and charge for  
this service if you wish), that you receive source code or can get it  
if you want it, that you can change the software or use pieces of it  
in new free programs; and that you know you can do these things.  
 
To protect your rights, we need to make restrictions that forbid  
anyone to deny you these rights or to ask you to surrender the rights.  
These restrictions translate to certain responsibilities for you if  
you distribute copies of the library, or if you modify it.  
 
For example, if you distribute copies of the library, whether gratis  
or for a fee, you must give the recipients all the rights that we gave  
you. You must make sure that they, too, receive or can get the source  
code. If you link a program with the library, you must provide  
complete object files to the recipients so that they can relink them  
with the library, after making changes to the library and recompiling  
it. And you must show them these terms so they know their rights.  
 
Our method of protecting your rights has two steps: (1) copyright  
the library, and (2) offer you this license which gives you legal  
permission to copy, distribute and/or modify the library.  
 
Also, for each distributor's protection, we want to make certain  
that everyone understands that there is no warranty for this free  
library. If the library is modified by someone else and passed on, we  
want its recipients to know that what they have is not the original  
version, so that any problems introduced by others will not reflect on  
the original authors' reputations.  
 
Finally, any free program is threatened constantly by software  
patents. We wish to avoid the danger that companies distributing free  
software will individually obtain patent licenses, thus in effect  
transforming the program into proprietary software. To prevent this,  
we have made it clear that any patent must be licensed for everyone's  
free use or not licensed at all.  
 
Most GNU software, including some libraries, is covered by the ordinary  
GNU General Public License, which was designed for utility programs. This  
license, the GNU Library General Public License, applies to certain  
designated libraries. This license is quite different from the ordinary  
one; be sure to read it in full, and don't assume that anything in it is  
the same as in the ordinary license.  
 
The reason we have a separate public license for some libraries is that  
they blur the distinction we usually make between modifying or adding to a  
program and simply using it. Linking a program with a library, without  
changing the library, is in some sense simply using the library, and is  
analogous to running a utility program or application program. However, in  
a textual and legal sense, the linked executable is a combined work, a  
derivative of the original library, and the ordinary General Public License  
treats it as such.  
 
Because of this blurred distinction, using the ordinary General  
Public License for libraries did not effectively promote software  
sharing, because most developers did not use the libraries. We  
concluded that weaker conditions might promote sharing better.  
 
However, unrestricted linking of non-free programs would deprive the  
users of those programs of all benefit from the free status of the  
libraries themselves. This Library General Public License is intended to  
permit developers of non-free programs to use free libraries, while  
preserving your freedom as a user of such programs to change the free  
libraries that are incorporated in them. (We have not seen how to achieve  
this as regards changes in header files, but we have achieved it as regards  
changes in the actual functions of the Library.) The hope is that this  
will lead to faster development of free libraries.  
 
The precise terms and conditions for copying, distribution and  
modification follow. Pay close attention to the difference between a  
"work based on the library" and a "work that uses the library". The  
former contains code derived from the library, while the latter only  
works together with the library.  
 
Note that it is possible for a library to be covered by the ordinary  
General Public License rather than by this special one.  
 
GNU LIBRARY GENERAL PUBLIC LICENSE  
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION  
 
0. This License Agreement applies to any software library which  
contains a notice placed by the copyright holder or other authorized  
party saying it may be distributed under the terms of this Library  
General Public License (also called "this License"). Each licensee is  
addressed as "you".  
 
A "library" means a collection of software functions and/or data  
prepared so as to be conveniently linked with application programs  
(which use some of those functions and data) to form executables.  
 
The "Library", below, refers to any such software library or work  
which has been distributed under these terms. A "work based on the  
Library" means either the Library or any derivative work under  
copyright law: that is to say, a work containing the Library or a  
portion of it, either verbatim or with modifications and/or translated  
straightforwardly into another language. (Hereinafter, translation is  
included without limitation in the term "modification".)  
 
"Source code" for a work means the preferred form of the work for  
making modifications to it. For a library, complete source code means  
all the source code for all modules it contains, plus any associated  
interface definition files, plus the scripts used to control compilation  
and installation of the library.  
 
Activities other than copying, distribution and modification are not  
covered by this License; they are outside its scope. The act of  
running a program using the Library is not restricted, and output from  
such a program is covered only if its contents constitute a work based  
on the Library (independent of the use of the Library in a tool for  
writing it). Whether that is true depends on what the Library does  
and what the program that uses the Library does.  
 
1. You may copy and distribute verbatim copies of the Library's  
complete source code as you receive it, in any medium, provided that  
you conspicuously and appropriately publish on each copy an  
appropriate copyright notice and disclaimer of warranty; keep intact  
all the notices that refer to this License and to the absence of any  
warranty; and distribute a copy of this License along with the  
Library.  
 
You may charge a fee for the physical act of transferring a copy,  
and you may at your option offer warranty protection in exchange for a  
fee.  
 
2. You may modify your copy or copies of the Library or any portion  
of it, thus forming a work based on the Library, and copy and  
distribute such modifications or work under the terms of Section 1  
above, provided that you also meet all of these conditions:  
 
a) The modified work must itself be a software library.  
 
b) You must cause the files modified to carry prominent notices  
stating that you changed the files and the date of any change.  
 
c) You must cause the whole of the work to be licensed at no  
charge to all third parties under the terms of this License.  
 
d) If a facility in the modified Library refers to a function or a  
table of data to be supplied by an application program that uses  
the facility, other than as an argument passed when the facility  
is invoked, then you must make a good faith effort to ensure that,  
in the event an application does not supply such function or  
table, the facility still operates, and performs whatever part of  
its purpose remains meaningful.  
 
(For example, a function in a library to compute square roots has  
a purpose that is entirely well-defined independent of the  
application. Therefore, Subsection 2d requires that any  
application-supplied function or table used by this function must  
be optional: if the application does not supply it, the square  
root function must still compute square roots.)  
 
These requirements apply to the modified work as a whole. If  
identifiable sections of that work are not derived from the Library,  
and can be reasonably considered independent and separate works in  
themselves, then this License, and its terms, do not apply to those  
sections when you distribute them as separate works. But when you  
distribute the same sections as part of a whole which is a work based  
on the Library, the distribution of the whole must be on the terms of  
this License, whose permissions for other licensees extend to the  
entire whole, and thus to each and every part regardless of who wrote  
it.  
 
Thus, it is not the intent of this section to claim rights or contest  
your rights to work written entirely by you; rather, the intent is to  
exercise the right to control the distribution of derivative or  
collective works based on the Library.  
 
In addition, mere aggregation of another work not based on the Library  
with the Library (or with a work based on the Library) on a volume of  
a storage or distribution medium does not bring the other work under  
the scope of this License.  
 
3. You may opt to apply the terms of the ordinary GNU General Public  
License instead of this License to a given copy of the Library. To do  
this, you must alter all the notices that refer to this License, so  
that they refer to the ordinary GNU General Public License, version 2,  
instead of to this License. (If a newer version than version 2 of the  
ordinary GNU General Public License has appeared, then you can specify  
that version instead if you wish.) Do not make any other change in  
these notices.  
 
Once this change is made in a given copy, it is irreversible for  
that copy, so the ordinary GNU General Public License applies to all  
subsequent copies and derivative works made from that copy.  
 
This option is useful when you wish to copy part of the code of  
the Library into a program that is not a library.  
 
4. You may copy and distribute the Library (or a portion or  
derivative of it, under Section 2) in object code or executable form  
under the terms of Sections 1 and 2 above provided that you accompany  
it with the complete corresponding machine-readable source code, which  
must be distributed under the terms of Sections 1 and 2 above on a  
medium customarily used for software interchange.  
 
If distribution of object code is made by offering access to copy  
from a designated place, then offering equivalent access to copy the  
source code from the same place satisfies the requirement to  
distribute the source code, even though third parties are not  
compelled to copy the source along with the object code.  
 
5. A program that contains no derivative of any portion of the  
Library, but is designed to work with the Library by being compiled or  
linked with it, is called a "work that uses the Library". Such a  
work, in isolation, is not a derivative work of the Library, and  
therefore falls outside the scope of this License.  
 
However, linking a "work that uses the Library" with the Library  
creates an executable that is a derivative of the Library (because it  
contains portions of the Library), rather than a "work that uses the  
library". The executable is therefore covered by this License.  
Section 6 states terms for distribution of such executables.  
 
When a "work that uses the Library" uses material from a header file  
that is part of the Library, the object code for the work may be a  
derivative work of the Library even though the source code is not.  
Whether this is true is especially significant if the work can be  
linked without the Library, or if the work is itself a library. The  
threshold for this to be true is not precisely defined by law.  
 
If such an object file uses only numerical parameters, data  
structure layouts and accessors, and small macros and small inline  
functions (ten lines or less in length), then the use of the object  
file is unrestricted, regardless of whether it is legally a derivative  
work. (Executables containing this object code plus portions of the  
Library will still fall under Section 6.)  
 
Otherwise, if the work is a derivative of the Library, you may  
distribute the object code for the work under the terms of Section 6.  
Any executables containing that work also fall under Section 6,  
whether or not they are linked directly with the Library itself.  
 
6. As an exception to the Sections above, you may also compile or  
link a "work that uses the Library" with the Library to produce a  
work containing portions of the Library, and distribute that work  
under terms of your choice, provided that the terms permit  
modification of the work for the customer's own use and reverse  
engineering for debugging such modifications.  
 
You must give prominent notice with each copy of the work that the  
Library is used in it and that the Library and its use are covered by  
this License. You must supply a copy of this License. If the work  
during execution displays copyright notices, you must include the  
copyright notice for the Library among them, as well as a reference  
directing the user to the copy of this License. Also, you must do one  
of these things:  
 
a) Accompany the work with the complete corresponding  
machine-readable source code for the Library including whatever  
changes were used in the work (which must be distributed under  
Sections 1 and 2 above); and, if the work is an executable linked  
with the Library, with the complete machine-readable "work that  
uses the Library", as object code and/or source code, so that the  
user can modify the Library and then relink to produce a modified  
executable containing the modified Library. (It is understood  
that the user who changes the contents of definitions files in the  
Library will not necessarily be able to recompile the application  
to use the modified definitions.)  
 
b) Accompany the work with a written offer, valid for at  
least three years, to give the same user the materials  
specified in Subsection 6a, above, for a charge no more  
than the cost of performing this distribution.  
 
c) If distribution of the work is made by offering access to copy  
from a designated place, offer equivalent access to copy the above  
specified materials from the same place.  
 
d) Verify that the user has already received a copy of these  
materials or that you have already sent this user a copy.  
 
For an executable, the required form of the "work that uses the  
Library" must include any data and utility programs needed for  
reproducing the executable from it. However, as a special exception,  
the source code distributed need not include anything that is normally  
distributed (in either source or binary form) with the major  
components (compiler, kernel, and so on) of the operating system on  
which the executable runs, unless that component itself accompanies  
the executable.  
 
It may happen that this requirement contradicts the license  
restrictions of other proprietary libraries that do not normally  
accompany the operating system. Such a contradiction means you cannot  
use both them and the Library together in an executable that you  
distribute.  
 
7. You may place library facilities that are a work based on the  
Library side-by-side in a single library together with other library  
facilities not covered by this License, and distribute such a combined  
library, provided that the separate distribution of the work based on  
the Library and of the other library facilities is otherwise  
permitted, and provided that you do these two things:  
 
a) Accompany the combined library with a copy of the same work  
based on the Library, uncombined with any other library  
facilities. This must be distributed under the terms of the  
Sections above.  
 
b) Give prominent notice with the combined library of the fact  
that part of it is a work based on the Library, and explaining  
where to find the accompanying uncombined form of the same work.  
 
8. You may not copy, modify, sublicense, link with, or distribute  
the Library except as expressly provided under this License. Any  
attempt otherwise to copy, modify, sublicense, link with, or  
distribute the Library is void, and will automatically terminate your  
rights under this License. However, parties who have received copies,  
or rights, from you under this License will not have their licenses  
terminated so long as such parties remain in full compliance.  
 
9. You are not required to accept this License, since you have not  
signed it. However, nothing else grants you permission to modify or  
distribute the Library or its derivative works. These actions are  
prohibited by law if you do not accept this License. Therefore, by  
modifying or distributing the Library (or any work based on the  
Library), you indicate your acceptance of this License to do so, and  
all its terms and conditions for copying, distributing or modifying  
the Library or works based on it.  
 
10. Each time you redistribute the Library (or any work based on the  
Library), the recipient automatically receives a license from the  
original licensor to copy, distribute, link with or modify the Library  
subject to these terms and conditions. You may not impose any further  
restrictions on the recipients' exercise of the rights granted herein.  
You are not responsible for enforcing compliance by third parties to  
this License.  
 
11. If, as a consequence of a court judgment or allegation of patent  
infringement or for any other reason (not limited to patent issues),  
conditions are imposed on you (whether by court order, agreement or  
otherwise) that contradict the conditions of this License, they do not  
excuse you from the conditions of this License. If you cannot  
distribute so as to satisfy simultaneously your obligations under this  
License and any other pertinent obligations, then as a consequence you  
may not distribute the Library at all. For example, if a patent  
license would not permit royalty-free redistribution of the Library by  
all those who receive copies directly or indirectly through you, then  
the only way you could satisfy both it and this License would be to  
refrain entirely from distribution of the Library.  
 
If any portion of this section is held invalid or unenforceable under any  
particular circumstance, the balance of the section is intended to apply,  
and the section as a whole is intended to apply in other circumstances.  
 
It is not the purpose of this section to induce you to infringe any  
patents or other property right claims or to contest validity of any  
such claims; this section has the sole purpose of protecting the  
integrity of the free software distribution system which is  
implemented by public license practices. Many people have made  
generous contributions to the wide range of software distributed  
through that system in reliance on consistent application of that  
system; it is up to the author/donor to decide if he or she is willing  
to distribute software through any other system and a licensee cannot  
impose that choice.  
 
This section is intended to make thoroughly clear what is believed to  
be a consequence of the rest of this License.  
 
12. If the distribution and/or use of the Library is restricted in  
certain countries either by patents or by copyrighted interfaces, the  
original copyright holder who places the Library under this License may add  
an explicit geographical distribution limitation excluding those countries,  
so that distribution is permitted only in or among countries not thus  
excluded. In such case, this License incorporates the limitation as if  
written in the body of this License.  
 
13. The Free Software Foundation may publish revised and/or new  
versions of the Library General Public License from time to time.  
Such new versions will be similar in spirit to the present version,  
but may differ in detail to address new problems or concerns.  
 
Each version is given a distinguishing version number. If the Library  
specifies a version number of this License which applies to it and  
"any later version", you have the option of following the terms and  
conditions either of that version or of any later version published by  
the Free Software Foundation. If the Library does not specify a  
license version number, you may choose any version ever published by  
the Free Software Foundation.  
 
14. If you wish to incorporate parts of the Library into other free  
programs whose distribution conditions are incompatible with these,  
write to the author to ask for permission. For software which is  
copyrighted by the Free Software Foundation, write to the Free  
Software Foundation; we sometimes make exceptions for this. Our  
decision will be guided by the two goals of preserving the free status  
of all derivatives of our free software and of promoting the sharing  
and reuse of software generally.  
 
NO WARRANTY  
 
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO  
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR  
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY  
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE  
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE  
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME  
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.  
 
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN  
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY  
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU  
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR  
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE  
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING  
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A  
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF  
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH  
DAMAGES.  
 
END OF TERMS AND CONDITIONS  
 
Appendix: How to Apply These Terms to Your New Libraries  
 
If you develop a new library, and you want it to be of the greatest  
possible use to the public, we recommend making it free software that  
everyone can redistribute and change. You can do so by permitting  
redistribution under these terms (or, alternatively, under the terms of the  
ordinary General Public License).  
 
To apply these terms, attach the following notices to the library. It is  
safest to attach them to the start of each source file to most effectively  
convey the exclusion of warranty; and each file should have at least the  
"copyright" line and a pointer to where the full notice is found.  
 
<one line to give the library's name and a brief idea of what it does.>  
Copyright (C) <year> <name of author>  
 
This library is free software; you can redistribute it and/or  
modify it under the terms of the GNU Library General Public  
License as published by the Free Software Foundation; either  
version 2 of the License, or (at your option) any later version.  
 
This library is distributed in the hope that it will be useful,  
but WITHOUT ANY WARRANTY; without even the implied warranty of  
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
Library General Public License for more details.  
 
You should have received a copy of the GNU Library General Public  
License along with this library; if not, write to the Free  
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 
Also add information on how to contact you by electronic and paper mail.  
 
You should also get your employer (if you work as a programmer) or your  
school, if any, to sign a "copyright disclaimer" for the library, if  
necessary. Here is a sample; alter the names:  
 
Yoyodyne, Inc., hereby disclaims all copyright interest in the  
library `Frob' (a library for tweaking knobs) written by James Random Hacker.  
 
<signature of Ty Coon>, 1 April 1990  
Ty Coon, President of Vice  
 
That's all there is to it!  
 
This is a snapshot of various files from the wvtest project that we use  
to test libroutez. It is licensed under the LGPL. For more information,  
see here:  
 
http://github.com/apenwarr/wvtest/tree/master  
 
/*  
* WvTest:  
* Copyright (C) 1997-2009 Net Integration Technologies, Inc.  
* Licensed under the GNU Library General Public License, version 2.  
* See the included file named LICENSE for license information.  
*/  
#include "wvtest.h"  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <ctype.h>  
#ifdef _WIN32  
#include <direct.h>  
#else  
#include <unistd.h>  
#include <sys/wait.h>  
#endif  
#include <errno.h>  
#include <signal.h>  
 
#include <cstdlib>  
 
#ifdef HAVE_VALGRIND_MEMCHECK_H  
# include <valgrind/memcheck.h>  
# include <valgrind/valgrind.h>  
#else  
# define VALGRIND_COUNT_ERRORS 0  
# define VALGRIND_DO_LEAK_CHECK  
# define VALGRIND_COUNT_LEAKS(a,b,c,d) (a=b=c=d=0)  
#endif  
 
#define MAX_TEST_TIME 40 // max seconds for a single test to run  
#define MAX_TOTAL_TIME 120*60 // max seconds for the entire suite to run  
 
#define TEST_START_FORMAT "! %s:%-5d %-40s "  
 
static int memerrs()  
{  
return (int)VALGRIND_COUNT_ERRORS;  
}  
 
static int memleaks()  
{  
int leaked = 0, dubious = 0, reachable = 0, suppressed = 0;  
VALGRIND_DO_LEAK_CHECK;  
VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed);  
printf("memleaks: sure:%d dubious:%d reachable:%d suppress:%d\n",  
leaked, dubious, reachable, suppressed);  
fflush(stdout);  
 
// dubious+reachable are normally non-zero because of globals...  
// return leaked+dubious+reachable;  
return leaked;  
}  
 
// Return 1 if no children are running or zombies, 0 if there are any running  
// or zombie children.  
// Will wait for any already-terminated children first.  
// Passes if no rogue children were running, fails otherwise.  
// If your test gets a failure in here, either you're not killing all your  
// children, or you're not calling waitpid(2) on all of them.  
static bool no_running_children()  
{  
#ifndef _WIN32  
pid_t wait_result;  
 
// Acknowledge and complain about any zombie children  
do  
{  
int status = 0;  
wait_result = waitpid(-1, &status, WNOHANG);  
 
if (wait_result > 0)  
{  
char buf[256];  
snprintf(buf, sizeof(buf) - 1, "%d", wait_result);  
buf[sizeof(buf)-1] = '\0';  
WVFAILEQ("Unclaimed dead child process", buf);  
}  
} while (wait_result > 0);  
 
// There should not be any running children, so waitpid should return -1  
WVPASSEQ(errno, ECHILD);  
WVPASSEQ(wait_result, -1);  
return (wait_result == -1 && errno == ECHILD);  
#endif  
return true;  
}  
 
 
WvTest *WvTest::first, *WvTest::last;  
int WvTest::fails, WvTest::runs;  
time_t WvTest::start_time;  
bool WvTest::run_twice = false;  
 
void WvTest::alarm_handler(int)  
{  
printf("\n! WvTest Current test took longer than %d seconds! FAILED\n",  
MAX_TEST_TIME);  
fflush(stdout);  
abort();  
}  
 
 
static const char *pathstrip(const char *filename)  
{  
const char *cptr;  
cptr = strrchr(filename, '/');  
if (cptr) filename = cptr + 1;  
cptr = strrchr(filename, '\\');  
if (cptr) filename = cptr + 1;  
return filename;  
}  
 
 
WvTest::WvTest(const char *_descr, const char *_idstr, MainFunc *_main,  
int _slowness) :  
descr(_descr),  
idstr(pathstrip(_idstr)),  
main(_main),  
slowness(_slowness),  
next(NULL)  
{  
if (first)  
last->next = this;  
else  
first = this;  
last = this;  
}  
 
 
static bool prefix_match(const char *s, const char * const *prefixes)  
{  
for (const char * const *prefix = prefixes; prefix && *prefix; prefix++)  
{  
if (!strncasecmp(s, *prefix, strlen(*prefix)))  
return true;  
}  
return false;  
}  
 
 
int WvTest::run_all(const char * const *prefixes)  
{  
int old_valgrind_errs = 0, new_valgrind_errs;  
int old_valgrind_leaks = 0, new_valgrind_leaks;  
 
#ifdef _WIN32  
/* I should be doing something to do with SetTimer here,  
* not sure exactly what just yet */  
#else  
char *disable(getenv("WVTEST_DISABLE_TIMEOUT"));  
if (disable != NULL && disable[0] != '\0' && disable[0] != '0')  
signal(SIGALRM, SIG_IGN);  
else  
signal(SIGALRM, alarm_handler);  
alarm(MAX_TEST_TIME);  
#endif  
start_time = time(NULL);  
 
// make sure we can always start out in the same directory, so tests have  
// access to their files. If a test uses chdir(), we want to be able to  
// reverse it.  
char wd[1024];  
if (!getcwd(wd, sizeof(wd)))  
strcpy(wd, ".");  
 
const char *slowstr1 = getenv("WVTEST_MIN_SLOWNESS");  
const char *slowstr2 = getenv("WVTEST_MAX_SLOWNESS");  
int min_slowness = 0, max_slowness = 65535;  
if (slowstr1) min_slowness = atoi(slowstr1);  
if (slowstr2) max_slowness = atoi(slowstr2);  
 
#ifdef _WIN32  
run_twice = false;  
#else  
char *parallel_str = getenv("WVTEST_PARALLEL");  
if (parallel_str)  
run_twice = atoi(parallel_str) > 0;  
#endif  
 
// there are lots of fflush() calls in here because stupid win32 doesn't  
// flush very often by itself.  
fails = runs = 0;  
for (WvTest *cur = first; cur; cur = cur->next)  
{  
if (cur->slowness <= max_slowness  
&& cur->slowness >= min_slowness  
&& (!prefixes  
|| prefix_match(cur->idstr, prefixes)  
|| prefix_match(cur->descr, prefixes)))  
{  
#ifndef _WIN32  
// set SIGPIPE back to default, helps catch tests which don't set  
// this signal to SIG_IGN (which is almost always what you want)  
// on startup  
signal(SIGPIPE, SIG_DFL);  
 
pid_t child = 0;  
if (run_twice)  
{  
// I see everything twice!  
printf("Running test in parallel.\n");  
child = fork();  
}  
#endif  
 
printf("\nTesting \"%s\" in %s:\n", cur->descr, cur->idstr);  
fflush(stdout);  
 
cur->main();  
chdir(wd);  
 
new_valgrind_errs = memerrs();  
WVPASS(new_valgrind_errs == old_valgrind_errs);  
old_valgrind_errs = new_valgrind_errs;  
 
new_valgrind_leaks = memleaks();  
WVPASS(new_valgrind_leaks == old_valgrind_leaks);  
old_valgrind_leaks = new_valgrind_leaks;  
 
fflush(stderr);  
printf("\n");  
fflush(stdout);  
 
#ifndef _WIN32  
if (run_twice)  
{  
if (!child)  
{  
// I see everything once!  
printf("Child exiting.\n");  
_exit(0);  
}  
else  
{  
printf("Waiting for child to exit.\n");  
int result;  
while ((result = waitpid(child, NULL, 0)) == -1 &&  
errno == EINTR)  
printf("Waitpid interrupted, retrying.\n");  
}  
}  
#endif  
 
WVPASS(no_running_children());  
}  
}  
 
WVPASS(runs > 0);  
 
if (prefixes && *prefixes && **prefixes)  
printf("WvTest: WARNING: only ran tests starting with "  
"specifed prefix(es).\n");  
else  
printf("WvTest: ran all tests.\n");  
printf("WvTest: %d test%s, %d failure%s.\n",  
runs, runs==1 ? "" : "s",  
fails, fails==1 ? "": "s");  
fflush(stdout);  
 
return fails != 0;  
}  
 
 
// If we aren't running in parallel, we want to output the name of the test  
// before we run it, so we know what happened if it crashes. If we are  
// running in parallel, outputting this information in multiple printf()s  
// can confuse parsers, so we want to output everything in one printf().  
//  
// This function gets called by both start() and check(). If we're not  
// running in parallel, just print the data. If we're running in parallel,  
// and we're starting a test, save a copy of the file/line/description until  
// the test is done and we can output it all at once.  
//  
// Yes, this is probably the worst API of all time.  
void WvTest::print_result(bool start, const char *_file, int _line,  
const char *_condstr, bool result)  
{  
static char *file;  
static char *condstr;  
static int line;  
 
if (start)  
{  
if (file)  
free(file);  
if (condstr)  
free(condstr);  
file = strdup(pathstrip(_file));  
condstr = strdup(_condstr);  
line = _line;  
 
for (char *cptr = condstr; *cptr; cptr++)  
{  
if (!isprint((unsigned char)*cptr))  
*cptr = '!';  
}  
}  
 
const char *result_str = result ? "ok\n" : "FAILED\n";  
if (run_twice)  
{  
if (!start)  
printf(TEST_START_FORMAT "%s", file, line, condstr, result_str);  
}  
else  
{  
if (start)  
printf(TEST_START_FORMAT, file, line, condstr);  
else  
printf("%s", result_str);  
}  
fflush(stdout);  
 
if (!start)  
{  
if (file)  
free(file);  
if (condstr)  
free(condstr);  
file = condstr = NULL;  
}  
}  
 
 
void WvTest::start(const char *file, int line, const char *condstr)  
{  
// Either print the file, line, and condstr, or save them for later.  
print_result(true, file, line, condstr, 0);  
}  
 
 
void WvTest::check(bool cond)  
{  
#ifndef _WIN32  
alarm(MAX_TEST_TIME); // restart per-test timeout  
#endif  
if (!start_time) start_time = time(NULL);  
 
if (time(NULL) - start_time > MAX_TOTAL_TIME)  
{  
printf("\n! WvTest Total run time exceeded %d seconds! FAILED\n",  
MAX_TOTAL_TIME);  
fflush(stdout);  
abort();  
}  
 
runs++;  
 
print_result(false, NULL, 0, NULL, cond);  
 
if (!cond)  
{  
fails++;  
 
if (getenv("WVTEST_DIE_FAST"))  
abort();  
}  
}  
 
 
bool WvTest::start_check_eq(const char *file, int line,  
const char *a, const char *b, bool expect_pass)  
{  
if (!a) a = "";  
if (!b) b = "";  
 
size_t len = strlen(a) + strlen(b) + 8 + 1;  
char *str = new char[len];  
sprintf(str, "[%s] %s [%s]", a, expect_pass ? "==" : "!=", b);  
 
start(file, line, str);  
delete[] str;  
 
bool cond = !strcmp(a, b);  
if (!expect_pass)  
cond = !cond;  
 
check(cond);  
return cond;  
}  
 
 
bool WvTest::start_check_eq(const char *file, int line,  
const std::string &a, const std::string &b,  
bool expect_pass)  
{  
return start_check_eq(file, line, a.c_str(), b.c_str(), expect_pass);  
}  
 
 
bool WvTest::start_check_eq(const char *file, int line,  
int a, int b, bool expect_pass)  
{  
size_t len = 128 + 128 + 8 + 1;  
char *str = new char[len];  
sprintf(str, "%d %s %d", a, expect_pass ? "==" : "!=", b);  
 
start(file, line, str);  
delete[] str;  
 
bool cond = (a == b);  
if (!expect_pass)  
cond = !cond;  
 
check(cond);  
return cond;  
}  
 
 
bool WvTest::start_check_lt(const char *file, int line,  
const char *a, const char *b)  
{  
if (!a) a = "";  
if (!b) b = "";  
 
size_t len = strlen(a) + strlen(b) + 8 + 1;  
char *str = new char[len];  
sprintf(str, "[%s] < [%s]", a, b);  
 
start(file, line, str);  
delete[] str;  
 
bool cond = strcmp(a, b) < 0;  
check(cond);  
return cond;  
}  
 
 
bool WvTest::start_check_lt(const char *file, int line, int a, int b)  
{  
size_t len = 128 + 128 + 8 + 1;  
char *str = new char[len];  
sprintf(str, "%d < %d", a, b);  
 
start(file, line, str);  
delete[] str;  
 
bool cond = a < b;  
check(cond);  
return cond;  
}  
 
/* -*- Mode: C++ -*-  
* WvTest:  
* Copyright (C) 1997-2009 Net Integration Technologies, Inc.  
* Licensed under the GNU Library General Public License, version 2.  
* See the included file named LICENSE for license information.  
*/  
#ifndef __WVTEST_H  
#define __WVTEST_H  
 
#ifndef WVTEST_CONFIGURED  
# error "Missing settings: HAVE_VALGRIND_MEMCHECK_H HAVE_WVCRASH WVTEST_CONFIGURED"  
#endif  
 
#include <time.h>  
#include <string>  
 
class WvTest  
{  
typedef void MainFunc();  
const char *descr, *idstr;  
MainFunc *main;  
int slowness;  
WvTest *next;  
static WvTest *first, *last;  
static int fails, runs;  
static time_t start_time;  
static bool run_twice;  
 
static void alarm_handler(int sig);  
 
static void print_result(bool start, const char *file, int line,  
const char *condstr, bool result);  
public:  
WvTest(const char *_descr, const char *_idstr, MainFunc *_main, int _slow);  
static int run_all(const char * const *prefixes = NULL);  
static void start(const char *file, int line, const char *condstr);  
static void check(bool cond);  
static inline bool start_check(const char *file, int line,  
const char *condstr, bool cond)  
{ start(file, line, condstr); check(cond); return cond; }  
static bool start_check_eq(const char *file, int line,  
const char *a, const char *b, bool expect_pass);  
static bool start_check_eq(const char *file, int line,  
const std::string &a, const std::string &b,  
bool expect_pass);  
static bool start_check_eq(const char *file, int line, int a, int b,  
bool expect_pass);  
static bool start_check_lt(const char *file, int line,  
const char *a, const char *b);  
static bool start_check_lt(const char *file, int line, int a, int b);  
};  
 
 
#define WVPASS(cond) \  
WvTest::start_check(__FILE__, __LINE__, #cond, (cond))  
#define WVPASSEQ(a, b) \  
WvTest::start_check_eq(__FILE__, __LINE__, (a), (b), true)  
#define WVPASSLT(a, b) \  
WvTest::start_check_lt(__FILE__, __LINE__, (a), (b))  
#define WVFAIL(cond) \  
WvTest::start_check(__FILE__, __LINE__, "NOT(" #cond ")", !(cond))  
#define WVFAILEQ(a, b) \  
WvTest::start_check_eq(__FILE__, __LINE__, (a), (b), false)  
#define WVPASSNE(a, b) WVFAILEQ(a, b)  
#define WVFAILNE(a, b) WVPASSEQ(a, b)  
 
#define WVTEST_MAIN3(descr, ff, ll, slowness) \  
static void _wvtest_main_##ll(); \  
static WvTest _wvtest_##ll(descr, ff, _wvtest_main_##ll, slowness); \  
static void _wvtest_main_##ll()  
#define WVTEST_MAIN2(descr, ff, ll, slowness) \  
WVTEST_MAIN3(descr, ff, ll, slowness)  
#define WVTEST_MAIN(descr) WVTEST_MAIN2(descr, __FILE__, __LINE__, 0)  
#define WVTEST_SLOW_MAIN(descr) WVTEST_MAIN2(descr, __FILE__, __LINE__, 1)  
 
 
#endif // __WVTEST_H  
 
/*  
* WvTest:  
* Copyright (C) 1997-2009 Net Integration Technologies, Inc.  
* Licensed under the GNU Library General Public License, version 2.  
* See the included file named LICENSE for license information.  
*/  
#include "wvtest.h"  
#ifdef HAVE_WVCRASH  
# include "wvcrash.h"  
#endif  
#include <stdlib.h>  
#include <stdio.h>  
#ifdef _WIN32  
#include <io.h>  
#include <windows.h>  
#else  
#include <unistd.h>  
#include <fcntl.h>  
#endif  
 
static bool fd_is_valid(int fd)  
{  
#ifdef _WIN32  
if ((HANDLE)_get_osfhandle(fd) != INVALID_HANDLE_VALUE) return true;  
#endif  
int nfd = dup(fd);  
if (nfd >= 0)  
{  
close(nfd);  
return true;  
}  
return false;  
 
}  
 
 
static int fd_count(const char *when)  
{  
int count = 0;  
 
printf("fds open at %s:", when);  
 
for (int fd = 0; fd < 1024; fd++)  
{  
if (fd_is_valid(fd))  
{  
count++;  
printf(" %d", fd);  
fflush(stdout);  
}  
}  
printf("\n");  
 
return count;  
}  
 
 
int main(int argc, char **argv)  
{  
char buf[200];  
#if defined(_WIN32) && defined(HAVE_WVCRASH)  
setup_console_crash();  
#endif  
 
// test wvtest itself. Not very thorough, but you have to draw the  
// line somewhere :)  
WVPASS(true);  
WVPASS(1);  
WVFAIL(false);  
WVFAIL(0);  
int startfd, endfd;  
char * const *prefixes = NULL;  
 
if (argc > 1)  
prefixes = argv + 1;  
 
startfd = fd_count("start");  
int ret = WvTest::run_all(prefixes);  
 
if (ret == 0) // don't pollute the strace output if we failed anyway  
{  
endfd = fd_count("end");  
 
WVPASS(startfd == endfd);  
#ifndef _WIN32  
if (startfd != endfd)  
{  
sprintf(buf, "ls -l /proc/%d/fd", getpid());  
system(buf);  
}  
#endif  
}  
 
// keep 'make' from aborting if this environment variable is set  
if (getenv("WVTEST_NO_FAIL"))  
return 0;  
else  
return ret;  
}  
 
#!/usr/bin/perl -w  
#  
# WvTest:  
# Copyright (C)2007-2009 Versabanq Innovations Inc. and contributors.  
# Licensed under the GNU Library General Public License, version 2.  
# See the included file named LICENSE for license information.  
#  
use strict;  
use Time::HiRes qw(time);  
 
# always flush  
$| = 1;  
 
if (@ARGV < 1) {  
print STDERR "Usage: $0 <command line...>\n";  
exit 127;  
}  
 
print STDERR "Testing \"all\" in @ARGV:\n";  
 
my $pid = open(my $fh, "-|");  
if (!$pid) {  
# child  
setpgrp();  
open STDERR, '>&STDOUT' or die("Can't dup stdout: $!\n");  
exec(@ARGV);  
exit 126; # just in case  
}  
 
my $istty = -t STDOUT;  
my @log = ();  
my ($gpasses, $gfails) = (0,0);  
 
sub bigkill($)  
{  
my $pid = shift;  
 
if (@log) {  
print "\n" . join("\n", @log) . "\n";  
}  
 
print STDERR "\n! Killed by signal FAILED\n";  
 
($pid > 0) || die("pid is '$pid'?!\n");  
 
local $SIG{CHLD} = sub { }; # this will wake us from sleep() faster  
kill 15, $pid;  
sleep(2);  
 
if ($pid > 1) {  
kill 9, -$pid;  
}  
kill 9, $pid;  
 
exit(125);  
}  
 
# parent  
local $SIG{INT} = sub { bigkill($pid); };  
local $SIG{TERM} = sub { bigkill($pid); };  
local $SIG{ALRM} = sub {  
print STDERR "Alarm timed out! No test results for too long.\n";  
bigkill($pid);  
};  
 
sub colourize($)  
{  
my $result = shift;  
my $pass = ($result eq "ok");  
 
if ($istty) {  
my $colour = $pass ? "\e[32;1m" : "\e[31;1m";  
return "$colour$result\e[0m";  
} else {  
return $result;  
}  
}  
 
sub mstime($$$)  
{  
my ($floatsec, $warntime, $badtime) = @_;  
my $ms = int($floatsec * 1000);  
my $str = sprintf("%d.%03ds", $ms/1000, $ms % 1000);  
 
if ($istty && $ms > $badtime) {  
return "\e[31;1m$str\e[0m";  
} elsif ($istty && $ms > $warntime) {  
return "\e[33;1m$str\e[0m";  
} else {  
return "$str";  
}  
}  
 
sub resultline($$)  
{  
my ($name, $result) = @_;  
return sprintf("! %-65s %s", $name, colourize($result));  
}  
 
my $allstart = time();  
my ($start, $stop);  
 
sub endsect()  
{  
$stop = time();  
if ($start) {  
printf " %s %s\n", mstime($stop - $start, 500, 1000), colourize("ok");  
}  
}  
 
while (<$fh>)  
{  
chomp;  
s/\r//g;  
 
if (/^\s*Testing "(.*)" in (.*):\s*$/)  
{  
alarm(120);  
my ($sect, $file) = ($1, $2);  
 
endsect();  
 
printf("! %s %s: ", $file, $sect);  
@log = ();  
$start = $stop;  
}  
elsif (/^!\s*(.*?)\s+(\S+)\s*$/)  
{  
alarm(120);  
 
my ($name, $result) = ($1, $2);  
my $pass = ($result eq "ok");  
 
if (!$start) {  
printf("\n! Startup: ");  
$start = time();  
}  
 
push @log, resultline($name, $result);  
 
if (!$pass) {  
$gfails++;  
if (@log) {  
print "\n" . join("\n", @log) . "\n";  
@log = ();  
}  
} else {  
$gpasses++;  
print ".";  
}  
}  
else  
{  
push @log, $_;  
}  
}  
 
endsect();  
 
my $newpid = waitpid($pid, 0);  
if ($newpid != $pid) {  
die("waitpid returned '$newpid', expected '$pid'\n");  
}  
 
my $code = $?;  
my $ret = ($code >> 8);  
 
# return death-from-signal exits as >128. This is what bash does if you ran  
# the program directly.  
if ($code && !$ret) { $ret = $code | 128; }  
 
if ($ret && @log) {  
print "\n" . join("\n", @log) . "\n";  
}  
 
if ($code != 0) {  
print resultline("Program returned non-zero exit code ($ret)", "FAILED");  
}  
 
my $gtotal = $gpasses+$gfails;  
printf("\nWvTest: %d test%s, %d failure%s, total time %s.\n",  
$gtotal, $gtotal==1 ? "" : "s",  
$gfails, $gfails==1 ? "" : "s",  
mstime(time() - $allstart, 2000, 5000));  
print STDERR "\nWvTest result code: $ret\n";  
exit( $ret ? $ret : ($gfails ? 125 : 0) );