def test_import_schedule_sbl_has_wrong_nodes(self):
        """
        StopByLine has a bad node, but the stop is found

        In Aug 2012 signup, 508 was just nodes, and wrong
        """
        self.setup_100()
        line = self.lines["100"]
        line.line_type = "FL"
        line.save()
        stop2 = self.stops[5440]
        StopByLine.objects.filter(stop=stop2).delete()
        StopByPattern.objects.filter(stop=stop2).delete()
        stop3 = self.stops[5478]
        StopByLine.objects.filter(stop=stop3).update(seq=2)
        schedule = self.schedules["100"].replace("Adm/MemE", "ADMMEM")
        mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "100.txt")
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        tripday = TripDay.objects.get()
        ts0, ts1, ts2 = TripStop.objects.all()
        self.assertEqual(ts0.stop, self.stops[5498])
        self.assertEqual(ts0.node, self.nodes[635])
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop, stop2)
        self.assertEqual(ts1.node, None)
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop, stop3)
        self.assertEqual(ts2.node, self.nodes[736])
    def test_import_schedule_100_sbl_is_just_nodes(self):
        """
        The import succeeds if the StopByLine is just nodes

        In Aug 2012 signup, 508 was just nodes, but some stops were unique
        """
        self.setup_100()
        line = self.lines["100"]
        line.line_type = "FL"
        line.save()
        stop2 = self.stops[5440]
        StopByLine.objects.filter(stop=stop2).delete()
        StopByPattern.objects.filter(stop=stop2).delete()
        stop3 = self.stops[5478]
        StopByLine.objects.filter(stop=stop3).update(seq=2)
        mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(self.schedules["100"]))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "100.txt")
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        tripday = TripDay.objects.get()
        ts0, ts1, ts2 = TripStop.objects.all()
        self.assertEqual(ts0.stop, self.stops[5498])
        self.assertEqual(ts0.node, self.nodes[635])
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop, stop2)
        self.assertEqual(ts1.node, None)
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop, stop3)
        self.assertEqual(ts2.node, self.nodes[736])
    def test_import_schedule_sbl_has_wrong_nodes(self):
        '''
        StopByLine has a bad node, but the stop is found

        In Aug 2012 signup, 508 was just nodes, and wrong
        '''
        self.setup_100()
        line = self.lines['100']
        line.line_type = 'FL'
        line.save()
        stop2 = self.stops[5440]
        StopByLine.objects.filter(stop=stop2).delete()
        StopByPattern.objects.filter(stop=stop2).delete()
        stop3 = self.stops[5478]
        StopByLine.objects.filter(stop=stop3).update(seq=2)
        schedule = self.schedules['100'].replace('Adm/MemE', 'ADMMEM')
        mtta.models._mockable_open('100.txt', 'rb').AndReturn(
            StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '100.txt')
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        tripday = TripDay.objects.get()
        ts0, ts1, ts2 = TripStop.objects.all()
        self.assertEqual(ts0.stop, self.stops[5498])
        self.assertEqual(ts0.node, self.nodes[635])
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop, stop2)
        self.assertEqual(ts1.node, None)
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop, stop3)
        self.assertEqual(ts2.node, self.nodes[736])
    def test_import_schedule_100_sbl_is_just_nodes(self):
        '''
        The import succeeds if the StopByLine is just nodes

        In Aug 2012 signup, 508 was just nodes, but some stops were unique
        '''
        self.setup_100()
        line = self.lines['100']
        line.line_type = 'FL'
        line.save()
        stop2 = self.stops[5440]
        StopByLine.objects.filter(stop=stop2).delete()
        StopByPattern.objects.filter(stop=stop2).delete()
        stop3 = self.stops[5478]
        StopByLine.objects.filter(stop=stop3).update(seq=2)
        mtta.models._mockable_open('100.txt', 'rb').AndReturn(
            StringIO.StringIO(self.schedules['100']))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '100.txt')
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        tripday = TripDay.objects.get()
        ts0, ts1, ts2 = TripStop.objects.all()
        self.assertEqual(ts0.stop, self.stops[5498])
        self.assertEqual(ts0.node, self.nodes[635])
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop, stop2)
        self.assertEqual(ts1.node, None)
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop, stop3)
        self.assertEqual(ts2.node, self.nodes[736])
    def test_import_schedule_sbl_is_just_nodes_one_in_service_candidate(self):
        '''
        StopByPattern is nodes, a stop-only column has one in-service option.
        The in-service stop is assigned, and the column will be exported.

        In Aug 2012 signup, 508 was just nodes, but some stops were ambiguous
        '''
        self.setup_100()
        line = self.lines['100']
        line.line_type = 'FL'
        line.save()
        stop2 = self.stops[5440]
        StopByLine.objects.filter(stop=stop2).delete()
        StopByPattern.objects.filter(stop=stop2).delete()
        stop3 = self.stops[5478]
        StopByLine.objects.filter(stop=stop3).update(seq=2)
        Stop.objects.create(
            signup=self.signup, stop_id=stop2.stop_id + 1,
            stop_abbr=stop2.stop_abbr, site_name=stop2.site_name,
            lon=stop2.lon, lat=stop2.lat, stop_name=stop2.stop_name,
            in_service=False)

        mtta.models._mockable_open('100.txt', 'rb').AndReturn(
            StringIO.StringIO(self.schedules['100']))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '100.txt')
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        ts1 = TripStop.objects.get(seq=1)
        self.assertEqual(ts1.stop, stop2)
    def test_import_schedule_sbl_is_just_nodes_one_in_service_candidate(self):
        """
        StopByPattern is nodes, a stop-only column has one in-service option.
        The in-service stop is assigned, and the column will be exported.

        In Aug 2012 signup, 508 was just nodes, but some stops were ambiguous
        """
        self.setup_100()
        line = self.lines["100"]
        line.line_type = "FL"
        line.save()
        stop2 = self.stops[5440]
        StopByLine.objects.filter(stop=stop2).delete()
        StopByPattern.objects.filter(stop=stop2).delete()
        stop3 = self.stops[5478]
        StopByLine.objects.filter(stop=stop3).update(seq=2)
        Stop.objects.create(
            signup=self.signup,
            stop_id=stop2.stop_id + 1,
            stop_abbr=stop2.stop_abbr,
            site_name=stop2.site_name,
            lon=stop2.lon,
            lat=stop2.lat,
            stop_name=stop2.stop_name,
            in_service=False,
        )

        mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(self.schedules["100"]))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "100.txt")
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        ts1 = TripStop.objects.get(seq=1)
        self.assertEqual(ts1.stop, stop2)
    def test_880F_bad_node_one_valid_candidate(self):
        '''For some flex lines, the stop matches but the node doesn't

        In Nov 2012 signup, the schedule node is StFr/1286, but the timing
        point (node 1037, stop 1286) is STFRSB/StFrSB. Stop 1286's node_abbr
        is 'STFRSB' as well.  So, we just match by the stop abbreviation.
        '''

        self.setup_880F()
        # Setup the new node
        self.stops[1286] = self.signup.stop_set.create(
            stop_id=1286, in_service=True, lat='36.071389', lon='-95.920445',
            node_abbr='STFRSB', stop_abbr='StFrSB',
            stop_name='Saint Francis Hosp S-SW')
        self.nodes[75] = self.signup.node_set.create(
            node_id=75, node_abbr='StFr',
            node_name='St Francis Hospital')
        self.nodes[75].stops.add(self.stops[1286])
        self.nodes[1037] = self.signup.node_set.create(
            node_id=1037, node_abbr='STFRSB',
            node_name='ST FRANCIS SOUTHBOUND')
        self.nodes[1037].stops.add(self.stops[1286])
        # Replace the 11Uti/11Uti timing node
        self.linedirs['880F-0'].stopbyline_set.filter(seq=2).update(
            stop=self.stops[1286], node=self.nodes[1037])
        self.patterns['880F-01'].stopbypattern_set.filter(seq=2).update(
            stop=self.stops[1286], node=self.nodes[1037])
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       AUG 2012
Service:      1
Line:         880
Exception:    Off
Printed:      08-21-2012 15:18

Direction:    From Downtown

Pattern    DAS1             6BUE      11PE     StFr               WHM
          DBAY1   Ch5SB   6stBld   11stPeo   StFrSB   Utic12st    WHM
~~~~~~~  ~~~~~~  ~~~~~~  ~~~~~~~  ~~~~~~~~  ~~~~~~~  ~~~~~~~~~  ~~~~~

     01   20:00   20:01    20:01     20:06    20:08      20:08  20:43
"""

        mtta.models._mockable_open('880F.txt', 'rb').AndReturn(
            StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '880F.txt')
        self.mox.VerifyAll()
        ts4 = TripStop.objects.get(seq=4)
        self.assertEqual(ts4.stop_abbr, 'StFrSB')
        self.assertEqual(ts4.stop, self.stops[1286])
        self.assertEqual(ts4.node_abbr, 'StFr')
        self.assertEqual(ts4.node, self.nodes[75])
        self.assertTrue(ts4.scheduled, True)
    def test_880F_bad_node_one_valid_candidate(self):
        """For some flex lines, the stop matches but the node doesn't

        In Nov 2012 signup, the schedule node is StFr/1286, but the timing
        point (node 1037, stop 1286) is STFRSB/StFrSB. Stop 1286's node_abbr
        is 'STFRSB' as well.  So, we just match by the stop abbreviation.
        """

        self.setup_880F()
        # Setup the new node
        self.stops[1286] = self.signup.stop_set.create(
            stop_id=1286,
            in_service=True,
            lat="36.071389",
            lon="-95.920445",
            node_abbr="STFRSB",
            stop_abbr="StFrSB",
            stop_name="Saint Francis Hosp S-SW",
        )
        self.nodes[75] = self.signup.node_set.create(node_id=75, node_abbr="StFr", node_name="St Francis Hospital")
        self.nodes[75].stops.add(self.stops[1286])
        self.nodes[1037] = self.signup.node_set.create(
            node_id=1037, node_abbr="STFRSB", node_name="ST FRANCIS SOUTHBOUND"
        )
        self.nodes[1037].stops.add(self.stops[1286])
        # Replace the 11Uti/11Uti timing node
        self.linedirs["880F-0"].stopbyline_set.filter(seq=2).update(stop=self.stops[1286], node=self.nodes[1037])
        self.patterns["880F-01"].stopbypattern_set.filter(seq=2).update(stop=self.stops[1286], node=self.nodes[1037])
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       AUG 2012
Service:      1
Line:         880
Exception:    Off
Printed:      08-21-2012 15:18

Direction:    From Downtown

Pattern    DAS1             6BUE      11PE     StFr               WHM
          DBAY1   Ch5SB   6stBld   11stPeo   StFrSB   Utic12st    WHM
~~~~~~~  ~~~~~~  ~~~~~~  ~~~~~~~  ~~~~~~~~  ~~~~~~~  ~~~~~~~~~  ~~~~~

     01   20:00   20:01    20:01     20:06    20:08      20:08  20:43
"""

        mtta.models._mockable_open("880F.txt", "rb").AndReturn(StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "880F.txt")
        self.mox.VerifyAll()
        ts4 = TripStop.objects.get(seq=4)
        self.assertEqual(ts4.stop_abbr, "StFrSB")
        self.assertEqual(ts4.stop, self.stops[1286])
        self.assertEqual(ts4.node_abbr, "StFr")
        self.assertEqual(ts4.node, self.nodes[75])
        self.assertTrue(ts4.scheduled, True)
 def test_import_schedule_flex(self):
     """Schedule NNN matches NNNFLEX, like 508 -> 508FLEX"""
     self.setup_100()
     line = self.lines["100"]
     line.line_abbr = "100FLEX"
     line.save()
     mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(self.schedules["100"]))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, "100.txt")
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
 def test_import_schedule_sflx(self):
     """Schedule NNNS matches NNNSFLX, like 860S -> 860SFLX"""
     self.setup_100()
     schedule = self.schedules["100"].replace("Line:         100", "Line:         100S")
     line = self.lines["100"]
     line.line_abbr = "100SFLX"
     line.save()
     mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(schedule))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, "100.txt")
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
 def test_import_schedule_flex(self):
     '''Schedule NNN matches NNNFLEX, like 508 -> 508FLEX'''
     self.setup_100()
     line = self.lines['100']
     line.line_abbr = '100FLEX'
     line.save()
     mtta.models._mockable_open('100.txt', 'rb').AndReturn(
         StringIO.StringIO(self.schedules['100']))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, '100.txt')
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
 def test_import_schedule_sflx(self):
     '''Schedule NNNS matches NNNSFLX, like 860S -> 860SFLX'''
     self.setup_100()
     schedule = self.schedules['100'].replace(
         'Line:         100', 'Line:         100S')
     line = self.lines['100']
     line.line_abbr = '100SFLX'
     line.save()
     mtta.models._mockable_open('100.txt', 'rb').AndReturn(
         StringIO.StringIO(schedule))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, '100.txt')
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
 def test_import_100_basic(self):
     self.setup_100()
     mtta.models._mockable_open('100.txt', 'rb').AndReturn(
         StringIO.StringIO(self.schedules['100']))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, '100.txt')
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
     service = Service.objects.get(signup=self.signup)
     self.assertEqual(service.service_id, 1)
     tripday = TripDay.objects.get()
     self.assertEqual(tripday.linedir, self.linedirs['100-0'])
     self.assertEqual(tripday.service, service)
     ts0, ts1, ts2 = TripStop.objects.all()
     # 123Ar/Arch124a - Timing node
     self.assertEqual(ts0.seq, 0)
     self.assertEqual(ts0.tripday, tripday)
     self.assertEqual(ts0.stop_abbr, 'Arch124a')
     self.assertEqual(ts0.stop, self.stops[5498])
     self.assertEqual(ts0.node_abbr, '123Ar')
     self.assertEqual(ts0.node, self.nodes[635])
     # Adm106p - Stop
     self.assertEqual(ts1.seq, 1)
     self.assertEqual(ts1.tripday, tripday)
     self.assertEqual(ts1.stop_abbr, 'Adm106p')
     self.assertEqual(ts1.stop, self.stops[5440])
     self.assertEqual(ts1.node_abbr, '')
     self.assertEqual(ts1.node, None)
     # Adm/MemE / AdmMem - Timing Node
     self.assertEqual(ts2.tripday, tripday)
     self.assertEqual(ts2.seq, 2)
     self.assertEqual(ts2.stop_abbr, 'AdmMem')
     self.assertEqual(ts2.stop, self.stops[5478])
     self.assertEqual(ts2.node_abbr, 'Adm/MemE')
     self.assertEqual(ts2.node, self.nodes[736])
     trip = Trip.objects.get()
     self.assertEqual(trip.seq, 0)
     self.assertEqual(trip.tripday, tripday)
     self.assertEqual(trip.pattern, self.patterns['100-01'])
     tt0, tt1, tt2 = TripTime.objects.all()
     self.assertEqual(tt0.trip, trip)
     self.assertEqual(tt0.tripstop, ts0)
     self.assertEqual(tt0.time, '7:00')
     self.assertEqual(tt1.trip, trip)
     self.assertEqual(tt1.tripstop, ts1)
     self.assertEqual(tt1.time, '7:30')
     self.assertEqual(tt2.trip, trip)
     self.assertEqual(tt2.tripstop, ts2)
     self.assertEqual(tt2.time, '8:00')
 def test_import_100_basic(self):
     self.setup_100()
     mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(self.schedules["100"]))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, "100.txt")
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
     service = Service.objects.get(signup=self.signup)
     self.assertEqual(service.service_id, 1)
     tripday = TripDay.objects.get()
     self.assertEqual(tripday.linedir, self.linedirs["100-0"])
     self.assertEqual(tripday.service, service)
     ts0, ts1, ts2 = TripStop.objects.all()
     # 123Ar/Arch124a - Timing node
     self.assertEqual(ts0.seq, 0)
     self.assertEqual(ts0.tripday, tripday)
     self.assertEqual(ts0.stop_abbr, "Arch124a")
     self.assertEqual(ts0.stop, self.stops[5498])
     self.assertEqual(ts0.node_abbr, "123Ar")
     self.assertEqual(ts0.node, self.nodes[635])
     # Adm106p - Stop
     self.assertEqual(ts1.seq, 1)
     self.assertEqual(ts1.tripday, tripday)
     self.assertEqual(ts1.stop_abbr, "Adm106p")
     self.assertEqual(ts1.stop, self.stops[5440])
     self.assertEqual(ts1.node_abbr, "")
     self.assertEqual(ts1.node, None)
     # Adm/MemE / AdmMem - Timing Node
     self.assertEqual(ts2.tripday, tripday)
     self.assertEqual(ts2.seq, 2)
     self.assertEqual(ts2.stop_abbr, "AdmMem")
     self.assertEqual(ts2.stop, self.stops[5478])
     self.assertEqual(ts2.node_abbr, "Adm/MemE")
     self.assertEqual(ts2.node, self.nodes[736])
     trip = Trip.objects.get()
     self.assertEqual(trip.seq, 0)
     self.assertEqual(trip.tripday, tripday)
     self.assertEqual(trip.pattern, self.patterns["100-01"])
     tt0, tt1, tt2 = TripTime.objects.all()
     self.assertEqual(tt0.trip, trip)
     self.assertEqual(tt0.tripstop, ts0)
     self.assertEqual(tt0.time, "7:00")
     self.assertEqual(tt1.trip, trip)
     self.assertEqual(tt1.tripstop, ts1)
     self.assertEqual(tt1.time, "7:30")
     self.assertEqual(tt2.trip, trip)
     self.assertEqual(tt2.tripstop, ts2)
     self.assertEqual(tt2.time, "8:00")
 def test_import_schedule_100_node_on_stop(self):
     """The import succeeds if the node abbr is on the stop instead"""
     self.setup_100()
     stop1 = self.stops[5498]
     stop1.node_abbr = "123Ar"
     stop1.save()
     StopByLine.objects.filter(stop=stop1).update(node=None)
     mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(self.schedules["100"]))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, "100.txt")
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
     ts0, ts1, ts2 = TripStop.objects.all()
     self.assertEqual(ts0.stop, stop1)
     self.assertEqual(ts0.node, None)
     self.assertEqual(ts2.stop, self.stops[5478])
     self.assertEqual(ts2.node, self.nodes[736])
 def test_import_schedule_100_node_on_stop(self):
     '''The import succeeds if the node abbr is on the stop instead'''
     self.setup_100()
     stop1 = self.stops[5498]
     stop1.node_abbr = '123Ar'
     stop1.save()
     StopByLine.objects.filter(stop=stop1).update(node=None)
     mtta.models._mockable_open('100.txt', 'rb').AndReturn(
         StringIO.StringIO(self.schedules['100']))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, '100.txt')
     self.mox.VerifyAll()
     self.assert_expected_trip_object_counts_100()
     ts0, ts1, ts2 = TripStop.objects.all()
     self.assertEqual(ts0.stop, stop1)
     self.assertEqual(ts0.node, None)
     self.assertEqual(ts2.stop, self.stops[5478])
     self.assertEqual(ts2.node, self.nodes[736])
    def test_100_node_with_arrival_and_departure(self):
        """If a node had arrival and departure, add to import

        In the Aug 2012 signup, the MMS2 node has an arrival and departure

        TODO: It seems that the check should fail if the stop abbreviations
        do not match.  However, this might be a FLEX line timing node
        matching issue, not a arrival/departure matching issue.
        """
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       TEST SEP 2012
Service:      1
Line:         100
Exception:    Off
Printed:      09-09-2012 17:08

Direction:    To Downtown

Pattern      123Ar            Arr MMS2  Lv MMS2  Adm/MemE
          Arch124a   Adm106p     MBAY2    MBAY2    AdmMem
~~~~~~~  ~~~~~~~~~  ~~~~~~~~  ~~~~~~~~  ~~~~~~~  ~~~~~~~~

     01       7:00      7:30      7:35     7:44      8:00

"""
        self.setup_100()
        # Move Adm/MemE to 5
        self.linedirs["100-0"].stopbyline_set.filter(seq=3).update(seq=5)
        self.patterns["100-01"].stopbypattern_set.filter(seq=3).update(seq=5)
        # Arr MMS2/MBAY2
        self.stops[6650] = self.signup.stop_set.create(
            stop_id=6650,
            stop_abbr="MBAY2",
            stop_name="MMS Bay2",
            node_abbr="LV MMS2",
            site_name="Midtown Memorial Station",
            lat="36.113915",
            lon="-95.888784",
            in_service=True,
        )
        self.nodes[787] = self.signup.node_set.create(node_id=787, node_abbr="Arr MMS2", node_name="MMS BAY 02")
        self.nodes[787].stops.add(self.stops[6650])
        self.linedirs["100-0"].stopbyline_set.create(stop=self.stops[6650], node=self.nodes[787], seq=3)
        self.patterns["100-01"].stopbypattern_set.create(
            stop=self.stops[6650], node=self.nodes[787], seq=3, linedir=self.linedirs["100-0"]
        )
        # Lv MMS2/MBAY2
        self.nodes[788] = self.signup.node_set.create(node_id=788, node_abbr="Lv MMS2", node_name="MMS Bay 2")
        self.nodes[788].stops.add(self.stops[6650])
        self.linedirs["100-0"].stopbyline_set.create(stop=self.stops[6650], node=self.nodes[788], seq=4)
        self.patterns["100-01"].stopbypattern_set.create(
            stop=self.stops[6650], node=self.nodes[788], seq=4, linedir=self.linedirs["100-0"]
        )
        mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "100.txt")
        self.mox.VerifyAll()
        arr = TripStop.objects.get(seq=2)
        self.assertEqual(arr.stop_abbr, "MBAY2")
        self.assertEqual(arr.stop, self.stops[6650])
        self.assertEqual(arr.node_abbr, "Arr MMS2")
        self.assertEqual(arr.node, self.nodes[787])
        self.assertTrue(arr.scheduled, True)
        lv = TripStop.objects.get(seq=3)
        self.assertEqual(lv.stop_abbr, "MBAY2")
        self.assertEqual(lv.stop, self.stops[6650])
        self.assertEqual(lv.node_abbr, "Lv MMS2")
        self.assertEqual(lv.node, self.nodes[788])
        self.assertTrue(lv.scheduled, True)
        self.assertEqual(arr.departure, lv)
    def test_880F_non_timing_nodes_with_stop_ids(self):
        """
        If the stops use stop IDs, everything gets easier

        The Nov 2012 signup used stop IDs"""
        self.setup_880F()
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       AUG 2012
Service:      1
Line:         880
Exception:    Off
Printed:      08-21-2012 15:18

Direction:    From Downtown

Pattern    DAS1             6BUE      11PE   11Uti               WHM
           6639    3732     6392      5109    4156       5856    133
~~~~~~~  ~~~~~~  ~~~~~~  ~~~~~~~  ~~~~~~~~  ~~~~~~  ~~~~~~~~~  ~~~~~

     01   20:00   20:01    20:01     20:06   20:08      20:08  20:43
"""

        mtta.models._mockable_open("880F.txt", "rb").AndReturn(StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "880F.txt")
        self.mox.VerifyAll()
        service = self.signup.service_set.get()
        tripday = TripDay.objects.get()
        self.assertEqual(tripday.linedir, self.linedirs["880F-0"])
        self.assertEqual(tripday.service, service)
        ts0, ts1, ts2, ts3, ts4, ts5, ts6 = TripStop.objects.all()
        # DAS1 / DBAY1 - Timing node
        self.assertEqual(ts0.seq, 0)
        self.assertEqual(ts0.tripday, tripday)
        self.assertEqual(ts0.stop_abbr, "6639")
        self.assertEqual(ts0.stop, self.stops[6639])
        self.assertEqual(ts0.node_abbr, "DAS1")
        self.assertEqual(ts0.node, self.nodes[738])
        # Ch5SB - Non-timing stop
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop_abbr, "3732")
        self.assertEqual(ts1.stop, self.stops[3732])
        self.assertEqual(ts1.node_abbr, "")
        self.assertEqual(ts1.node, None)
        # 6BUE/6stBld - Non-timing node
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop_abbr, "6392")
        self.assertEqual(ts2.stop, self.stops[6392])
        self.assertEqual(ts2.node_abbr, "6BUE")
        self.assertEqual(ts2.node, self.nodes[856])
        # 11PE/11stPeo - Non-timing node
        self.assertEqual(ts3.tripday, tripday)
        self.assertEqual(ts3.seq, 3)
        self.assertEqual(ts3.stop_abbr, "5109")
        self.assertEqual(ts3.stop, self.stops[5109])
        self.assertEqual(ts3.node_abbr, "11PE")
        self.assertEqual(ts3.node, self.nodes[38])
        # 11Uti/11Uti - Timing node
        self.assertEqual(ts4.tripday, tripday)
        self.assertEqual(ts4.seq, 4)
        self.assertEqual(ts4.stop_abbr, "4156")
        self.assertEqual(ts4.stop, self.stops[4156])
        self.assertEqual(ts4.node_abbr, "11Uti")
        self.assertEqual(ts4.node, self.nodes[705])
        # Utic12st - Non-timing stop with 2 matches
        self.assertEqual(ts5.tripday, tripday)
        self.assertEqual(ts5.seq, 5)
        self.assertEqual(ts5.stop_abbr, "5856")
        self.assertEqual(ts5.stop, self.stops[5856])
        self.assertEqual(ts5.node_abbr, "")
        self.assertEqual(ts5.node, None)
        # WHM/WHM - Timing node
        self.assertEqual(ts6.tripday, tripday)
        self.assertEqual(ts6.seq, 6)
        self.assertEqual(ts6.stop_abbr, "133")
        self.assertEqual(ts6.stop, self.stops[133])
        self.assertEqual(ts6.node_abbr, "WHM")
        self.assertEqual(ts6.node, self.nodes[515])
        trip = Trip.objects.get()
        self.assertEqual(trip.seq, 0)
        self.assertEqual(trip.tripday, tripday)
        self.assertEqual(trip.pattern, self.patterns["880F-01"])
        tt0, tt1, tt2, tt3, tt4, tt5, tt6 = TripTime.objects.all()
        self.assertEqual(tt0.trip, trip)
        self.assertEqual(tt0.tripstop, ts0)
        self.assertEqual(tt0.time, "20:00")
        self.assertEqual(tt1.trip, trip)
        self.assertEqual(tt1.tripstop, ts1)
        self.assertEqual(tt1.time, "20:01")
        self.assertEqual(tt2.trip, trip)
        self.assertEqual(tt2.tripstop, ts2)
        self.assertEqual(tt2.time, "20:01")
        self.assertEqual(tt3.trip, trip)
        self.assertEqual(tt3.tripstop, ts3)
        self.assertEqual(tt3.time, "20:06")
        self.assertEqual(tt4.trip, trip)
        self.assertEqual(tt4.tripstop, ts4)
        self.assertEqual(tt4.time, "20:08")
        self.assertEqual(tt5.trip, trip)
        self.assertEqual(tt5.tripstop, ts5)
        self.assertEqual(tt5.time, "20:08")
        self.assertEqual(tt6.trip, trip)
        self.assertEqual(tt6.tripstop, ts6)
        self.assertEqual(tt6.time, "20:43")
 def test_880F_non_timing_nodes(self):
     """For some flex lines, nodes are not timing nodes"""
     self.setup_880F()
     mtta.models._mockable_open("880F.txt", "rb").AndReturn(StringIO.StringIO(self.schedules["880F"]))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, "880F.txt")
     self.mox.VerifyAll()
     service = self.signup.service_set.get()
     tripday = TripDay.objects.get()
     self.assertEqual(tripday.linedir, self.linedirs["880F-0"])
     self.assertEqual(tripday.service, service)
     ts0, ts1, ts2, ts3, ts4, ts5, ts6 = TripStop.objects.all()
     # DAS1 / DBAY1 - Timing node
     self.assertEqual(ts0.seq, 0)
     self.assertEqual(ts0.tripday, tripday)
     self.assertEqual(ts0.stop_abbr, "DBAY1")
     self.assertEqual(ts0.stop, self.stops[6639])
     self.assertEqual(ts0.node_abbr, "DAS1")
     self.assertEqual(ts0.node, self.nodes[738])
     # Ch5SB - Non-timing stop
     self.assertEqual(ts1.seq, 1)
     self.assertEqual(ts1.tripday, tripday)
     self.assertEqual(ts1.stop_abbr, "Ch5SB")
     self.assertEqual(ts1.stop, self.stops[3732])
     self.assertEqual(ts1.node_abbr, "")
     self.assertEqual(ts1.node, None)
     # 6BUE/6stBld - Non-timing node
     self.assertEqual(ts2.tripday, tripday)
     self.assertEqual(ts2.seq, 2)
     self.assertEqual(ts2.stop_abbr, "6stBld")
     self.assertEqual(ts2.stop, self.stops[6392])
     self.assertEqual(ts2.node_abbr, "6BUE")
     self.assertEqual(ts2.node, self.nodes[856])
     # 11PE/11stPeo - Non-timing node
     self.assertEqual(ts3.tripday, tripday)
     self.assertEqual(ts3.seq, 3)
     self.assertEqual(ts3.stop_abbr, "11stPeo")
     self.assertEqual(ts3.stop, self.stops[5109])
     self.assertEqual(ts3.node_abbr, "11PE")
     self.assertEqual(ts3.node, self.nodes[38])
     # 11Uti/11Uti - Timing node
     self.assertEqual(ts4.tripday, tripday)
     self.assertEqual(ts4.seq, 4)
     self.assertEqual(ts4.stop_abbr, "11Uti")
     self.assertEqual(ts4.stop, self.stops[4156])
     self.assertEqual(ts4.node_abbr, "11Uti")
     self.assertEqual(ts4.node, self.nodes[705])
     # Utic12st - Non-timing stop with 2 matches
     self.assertEqual(ts5.tripday, tripday)
     self.assertEqual(ts5.seq, 5)
     self.assertEqual(ts5.stop_abbr, "Utic12st")
     self.assertEqual(ts5.stop, None)
     self.assertEqual(ts5.node_abbr, "")
     self.assertEqual(ts5.node, None)
     # WHM/WHM - Timing node
     self.assertEqual(ts6.tripday, tripday)
     self.assertEqual(ts6.seq, 6)
     self.assertEqual(ts6.stop_abbr, "WHM")
     self.assertEqual(ts6.stop, self.stops[133])
     self.assertEqual(ts6.node_abbr, "WHM")
     self.assertEqual(ts6.node, self.nodes[515])
     trip = Trip.objects.get()
     self.assertEqual(trip.seq, 0)
     self.assertEqual(trip.tripday, tripday)
     self.assertEqual(trip.pattern, self.patterns["880F-01"])
     tt0, tt1, tt2, tt3, tt4, tt5, tt6 = TripTime.objects.all()
     self.assertEqual(tt0.trip, trip)
     self.assertEqual(tt0.tripstop, ts0)
     self.assertEqual(tt0.time, "20:00")
     self.assertEqual(tt1.trip, trip)
     self.assertEqual(tt1.tripstop, ts1)
     self.assertEqual(tt1.time, "20:01")
     self.assertEqual(tt2.trip, trip)
     self.assertEqual(tt2.tripstop, ts2)
     self.assertEqual(tt2.time, "20:01")
     self.assertEqual(tt3.trip, trip)
     self.assertEqual(tt3.tripstop, ts3)
     self.assertEqual(tt3.time, "20:06")
     self.assertEqual(tt4.trip, trip)
     self.assertEqual(tt4.tripstop, ts4)
     self.assertEqual(tt4.time, "20:08")
     self.assertEqual(tt5.trip, trip)
     self.assertEqual(tt5.tripstop, ts5)
     self.assertEqual(tt5.time, "20:08")
     self.assertEqual(tt6.trip, trip)
     self.assertEqual(tt6.tripstop, ts6)
     self.assertEqual(tt6.time, "20:43")
 def test_880F_non_timing_nodes(self):
     '''For some flex lines, nodes are not timing nodes'''
     self.setup_880F()
     mtta.models._mockable_open('880F.txt', 'rb').AndReturn(
         StringIO.StringIO(self.schedules['880F']))
     self.mox.ReplayAll()
     TripDay.import_schedule(self.signup, '880F.txt')
     self.mox.VerifyAll()
     service = self.signup.service_set.get()
     tripday = TripDay.objects.get()
     self.assertEqual(tripday.linedir, self.linedirs['880F-0'])
     self.assertEqual(tripday.service, service)
     ts0, ts1, ts2, ts3, ts4, ts5, ts6 = TripStop.objects.all()
     # DAS1 / DBAY1 - Timing node
     self.assertEqual(ts0.seq, 0)
     self.assertEqual(ts0.tripday, tripday)
     self.assertEqual(ts0.stop_abbr, 'DBAY1')
     self.assertEqual(ts0.stop, self.stops[6639])
     self.assertEqual(ts0.node_abbr, 'DAS1')
     self.assertEqual(ts0.node, self.nodes[738])
     # Ch5SB - Non-timing stop
     self.assertEqual(ts1.seq, 1)
     self.assertEqual(ts1.tripday, tripday)
     self.assertEqual(ts1.stop_abbr, 'Ch5SB')
     self.assertEqual(ts1.stop, self.stops[3732])
     self.assertEqual(ts1.node_abbr, '')
     self.assertEqual(ts1.node, None)
     # 6BUE/6stBld - Non-timing node
     self.assertEqual(ts2.tripday, tripday)
     self.assertEqual(ts2.seq, 2)
     self.assertEqual(ts2.stop_abbr, '6stBld')
     self.assertEqual(ts2.stop, self.stops[6392])
     self.assertEqual(ts2.node_abbr, '6BUE')
     self.assertEqual(ts2.node, self.nodes[856])
     # 11PE/11stPeo - Non-timing node
     self.assertEqual(ts3.tripday, tripday)
     self.assertEqual(ts3.seq, 3)
     self.assertEqual(ts3.stop_abbr, '11stPeo')
     self.assertEqual(ts3.stop, self.stops[5109])
     self.assertEqual(ts3.node_abbr, '11PE')
     self.assertEqual(ts3.node, self.nodes[38])
     # 11Uti/11Uti - Timing node
     self.assertEqual(ts4.tripday, tripday)
     self.assertEqual(ts4.seq, 4)
     self.assertEqual(ts4.stop_abbr, '11Uti')
     self.assertEqual(ts4.stop, self.stops[4156])
     self.assertEqual(ts4.node_abbr, '11Uti')
     self.assertEqual(ts4.node, self.nodes[705])
     # Utic12st - Non-timing stop with 2 matches
     self.assertEqual(ts5.tripday, tripday)
     self.assertEqual(ts5.seq, 5)
     self.assertEqual(ts5.stop_abbr, 'Utic12st')
     self.assertEqual(ts5.stop, None)
     self.assertEqual(ts5.node_abbr, '')
     self.assertEqual(ts5.node, None)
     # WHM/WHM - Timing node
     self.assertEqual(ts6.tripday, tripday)
     self.assertEqual(ts6.seq, 6)
     self.assertEqual(ts6.stop_abbr, 'WHM')
     self.assertEqual(ts6.stop, self.stops[133])
     self.assertEqual(ts6.node_abbr, 'WHM')
     self.assertEqual(ts6.node, self.nodes[515])
     trip = Trip.objects.get()
     self.assertEqual(trip.seq, 0)
     self.assertEqual(trip.tripday, tripday)
     self.assertEqual(trip.pattern, self.patterns['880F-01'])
     tt0, tt1, tt2, tt3, tt4, tt5, tt6 = TripTime.objects.all()
     self.assertEqual(tt0.trip, trip)
     self.assertEqual(tt0.tripstop, ts0)
     self.assertEqual(tt0.time, '20:00')
     self.assertEqual(tt1.trip, trip)
     self.assertEqual(tt1.tripstop, ts1)
     self.assertEqual(tt1.time, '20:01')
     self.assertEqual(tt2.trip, trip)
     self.assertEqual(tt2.tripstop, ts2)
     self.assertEqual(tt2.time, '20:01')
     self.assertEqual(tt3.trip, trip)
     self.assertEqual(tt3.tripstop, ts3)
     self.assertEqual(tt3.time, '20:06')
     self.assertEqual(tt4.trip, trip)
     self.assertEqual(tt4.tripstop, ts4)
     self.assertEqual(tt4.time, '20:08')
     self.assertEqual(tt5.trip, trip)
     self.assertEqual(tt5.tripstop, ts5)
     self.assertEqual(tt5.time, '20:08')
     self.assertEqual(tt6.trip, trip)
     self.assertEqual(tt6.tripstop, ts6)
     self.assertEqual(tt6.time, '20:43')
    def test_880F_non_timing_nodes_with_stop_ids(self):
        '''
        If the stops use stop IDs, everything gets easier

        The Nov 2012 signup used stop IDs'''
        self.setup_880F()
        schedule = '''\
Stop Trips
~~~~~~~~~~

SignUp:       AUG 2012
Service:      1
Line:         880
Exception:    Off
Printed:      08-21-2012 15:18

Direction:    From Downtown

Pattern    DAS1             6BUE      11PE   11Uti               WHM
           6639    3732     6392      5109    4156       5856    133
~~~~~~~  ~~~~~~  ~~~~~~  ~~~~~~~  ~~~~~~~~  ~~~~~~  ~~~~~~~~~  ~~~~~

     01   20:00   20:01    20:01     20:06   20:08      20:08  20:43
'''

        mtta.models._mockable_open('880F.txt', 'rb').AndReturn(
            StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '880F.txt')
        self.mox.VerifyAll()
        service = self.signup.service_set.get()
        tripday = TripDay.objects.get()
        self.assertEqual(tripday.linedir, self.linedirs['880F-0'])
        self.assertEqual(tripday.service, service)
        ts0, ts1, ts2, ts3, ts4, ts5, ts6 = TripStop.objects.all()
        # DAS1 / DBAY1 - Timing node
        self.assertEqual(ts0.seq, 0)
        self.assertEqual(ts0.tripday, tripday)
        self.assertEqual(ts0.stop_abbr, '6639')
        self.assertEqual(ts0.stop, self.stops[6639])
        self.assertEqual(ts0.node_abbr, 'DAS1')
        self.assertEqual(ts0.node, self.nodes[738])
        # Ch5SB - Non-timing stop
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop_abbr, '3732')
        self.assertEqual(ts1.stop, self.stops[3732])
        self.assertEqual(ts1.node_abbr, '')
        self.assertEqual(ts1.node, None)
        # 6BUE/6stBld - Non-timing node
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop_abbr, '6392')
        self.assertEqual(ts2.stop, self.stops[6392])
        self.assertEqual(ts2.node_abbr, '6BUE')
        self.assertEqual(ts2.node, self.nodes[856])
        # 11PE/11stPeo - Non-timing node
        self.assertEqual(ts3.tripday, tripday)
        self.assertEqual(ts3.seq, 3)
        self.assertEqual(ts3.stop_abbr, '5109')
        self.assertEqual(ts3.stop, self.stops[5109])
        self.assertEqual(ts3.node_abbr, '11PE')
        self.assertEqual(ts3.node, self.nodes[38])
        # 11Uti/11Uti - Timing node
        self.assertEqual(ts4.tripday, tripday)
        self.assertEqual(ts4.seq, 4)
        self.assertEqual(ts4.stop_abbr, '4156')
        self.assertEqual(ts4.stop, self.stops[4156])
        self.assertEqual(ts4.node_abbr, '11Uti')
        self.assertEqual(ts4.node, self.nodes[705])
        # Utic12st - Non-timing stop with 2 matches
        self.assertEqual(ts5.tripday, tripday)
        self.assertEqual(ts5.seq, 5)
        self.assertEqual(ts5.stop_abbr, '5856')
        self.assertEqual(ts5.stop, self.stops[5856])
        self.assertEqual(ts5.node_abbr, '')
        self.assertEqual(ts5.node, None)
        # WHM/WHM - Timing node
        self.assertEqual(ts6.tripday, tripday)
        self.assertEqual(ts6.seq, 6)
        self.assertEqual(ts6.stop_abbr, '133')
        self.assertEqual(ts6.stop, self.stops[133])
        self.assertEqual(ts6.node_abbr, 'WHM')
        self.assertEqual(ts6.node, self.nodes[515])
        trip = Trip.objects.get()
        self.assertEqual(trip.seq, 0)
        self.assertEqual(trip.tripday, tripday)
        self.assertEqual(trip.pattern, self.patterns['880F-01'])
        tt0, tt1, tt2, tt3, tt4, tt5, tt6 = TripTime.objects.all()
        self.assertEqual(tt0.trip, trip)
        self.assertEqual(tt0.tripstop, ts0)
        self.assertEqual(tt0.time, '20:00')
        self.assertEqual(tt1.trip, trip)
        self.assertEqual(tt1.tripstop, ts1)
        self.assertEqual(tt1.time, '20:01')
        self.assertEqual(tt2.trip, trip)
        self.assertEqual(tt2.tripstop, ts2)
        self.assertEqual(tt2.time, '20:01')
        self.assertEqual(tt3.trip, trip)
        self.assertEqual(tt3.tripstop, ts3)
        self.assertEqual(tt3.time, '20:06')
        self.assertEqual(tt4.trip, trip)
        self.assertEqual(tt4.tripstop, ts4)
        self.assertEqual(tt4.time, '20:08')
        self.assertEqual(tt5.trip, trip)
        self.assertEqual(tt5.tripstop, ts5)
        self.assertEqual(tt5.time, '20:08')
        self.assertEqual(tt6.trip, trip)
        self.assertEqual(tt6.tripstop, ts6)
        self.assertEqual(tt6.time, '20:43')
    def test_100_node_with_arrival_and_departure(self):
        '''If a node had arrival and departure, add to import

        In the Aug 2012 signup, the MMS2 node has an arrival and departure

        TODO: It seems that the check should fail if the stop abbreviations
        do not match.  However, this might be a FLEX line timing node
        matching issue, not a arrival/departure matching issue.
        '''
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       TEST SEP 2012
Service:      1
Line:         100
Exception:    Off
Printed:      09-09-2012 17:08

Direction:    To Downtown

Pattern      123Ar            Arr MMS2  Lv MMS2  Adm/MemE
          Arch124a   Adm106p     MBAY2    MBAY2    AdmMem
~~~~~~~  ~~~~~~~~~  ~~~~~~~~  ~~~~~~~~  ~~~~~~~  ~~~~~~~~

     01       7:00      7:30      7:35     7:44      8:00

"""
        self.setup_100()
        # Move Adm/MemE to 5
        self.linedirs['100-0'].stopbyline_set.filter(seq=3).update(seq=5)
        self.patterns['100-01'].stopbypattern_set.filter(seq=3).update(seq=5)
        # Arr MMS2/MBAY2
        self.stops[6650] = self.signup.stop_set.create(
            stop_id=6650, stop_abbr='MBAY2', stop_name='MMS Bay2',
            node_abbr='LV MMS2', site_name='Midtown Memorial Station',
            lat='36.113915', lon='-95.888784', in_service=True)
        self.nodes[787] = self.signup.node_set.create(
            node_id=787, node_abbr='Arr MMS2', node_name='MMS BAY 02')
        self.nodes[787].stops.add(self.stops[6650])
        self.linedirs['100-0'].stopbyline_set.create(
            stop=self.stops[6650], node=self.nodes[787], seq=3)
        self.patterns['100-01'].stopbypattern_set.create(
            stop=self.stops[6650], node=self.nodes[787], seq=3,
            linedir=self.linedirs['100-0'])
        # Lv MMS2/MBAY2
        self.nodes[788] = self.signup.node_set.create(
            node_id=788, node_abbr='Lv MMS2', node_name='MMS Bay 2')
        self.nodes[788].stops.add(self.stops[6650])
        self.linedirs['100-0'].stopbyline_set.create(
            stop=self.stops[6650], node=self.nodes[788], seq=4)
        self.patterns['100-01'].stopbypattern_set.create(
            stop=self.stops[6650], node=self.nodes[788], seq=4,
            linedir=self.linedirs['100-0'])
        mtta.models._mockable_open('100.txt', 'rb').AndReturn(
            StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '100.txt')
        self.mox.VerifyAll()
        arr = TripStop.objects.get(seq=2)
        self.assertEqual(arr.stop_abbr, 'MBAY2')
        self.assertEqual(arr.stop, self.stops[6650])
        self.assertEqual(arr.node_abbr, 'Arr MMS2')
        self.assertEqual(arr.node, self.nodes[787])
        self.assertTrue(arr.scheduled, True)
        lv = TripStop.objects.get(seq=3)
        self.assertEqual(lv.stop_abbr, 'MBAY2')
        self.assertEqual(lv.stop, self.stops[6650])
        self.assertEqual(lv.node_abbr, 'Lv MMS2')
        self.assertEqual(lv.node, self.nodes[788])
        self.assertTrue(lv.scheduled, True)
        self.assertEqual(arr.departure, lv)
    def test_import_100_stop_ids(self):
        '''
        Import a schedule where stops are listed by ID

        The Nov 2012 signup used this format
        '''
        self.setup_100()
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       TEST SEP 2012
Service:      1
Line:         100
Exception:    Off
Printed:      09-09-2012 17:08

Direction:    To Downtown

Pattern      123Ar         Adm/MemE
              5498   5440      5478
~~~~~~~  ~~~~~~~~~  ~~~~~  ~~~~~~~~

     01       7:00   7:30      8:00

"""
        mtta.models._mockable_open('100.txt', 'rb').AndReturn(
            StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, '100.txt')
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        service = Service.objects.get(signup=self.signup)
        self.assertEqual(service.service_id, 1)
        tripday = TripDay.objects.get()
        self.assertEqual(tripday.linedir, self.linedirs['100-0'])
        self.assertEqual(tripday.service, service)
        ts0, ts1, ts2 = TripStop.objects.all()
        # 123Ar/Arch124a - Timing node
        self.assertEqual(ts0.seq, 0)
        self.assertEqual(ts0.tripday, tripday)
        self.assertEqual(ts0.stop_abbr, '5498')
        self.assertEqual(ts0.stop, self.stops[5498])
        self.assertEqual(ts0.node_abbr, '123Ar')
        self.assertEqual(ts0.node, self.nodes[635])
        # Adm106p - Stop
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop_abbr, '5440')
        self.assertEqual(ts1.stop, self.stops[5440])
        self.assertEqual(ts1.node_abbr, '')
        self.assertEqual(ts1.node, None)
        # Adm/MemE / AdmMem - Timing Node
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop_abbr, '5478')
        self.assertEqual(ts2.stop, self.stops[5478])
        self.assertEqual(ts2.node_abbr, 'Adm/MemE')
        self.assertEqual(ts2.node, self.nodes[736])
        trip = Trip.objects.get()
        self.assertEqual(trip.seq, 0)
        self.assertEqual(trip.tripday, tripday)
        self.assertEqual(trip.pattern, self.patterns['100-01'])
        tt0, tt1, tt2 = TripTime.objects.all()
        self.assertEqual(tt0.trip, trip)
        self.assertEqual(tt0.tripstop, ts0)
        self.assertEqual(tt0.time, '7:00')
        self.assertEqual(tt1.trip, trip)
        self.assertEqual(tt1.tripstop, ts1)
        self.assertEqual(tt1.time, '7:30')
        self.assertEqual(tt2.trip, trip)
        self.assertEqual(tt2.tripstop, ts2)
        self.assertEqual(tt2.time, '8:00')
    def test_import_100_stop_ids(self):
        """
        Import a schedule where stops are listed by ID

        The Nov 2012 signup used this format
        """
        self.setup_100()
        schedule = """\
Stop Trips
~~~~~~~~~~

SignUp:       TEST SEP 2012
Service:      1
Line:         100
Exception:    Off
Printed:      09-09-2012 17:08

Direction:    To Downtown

Pattern      123Ar         Adm/MemE
              5498   5440      5478
~~~~~~~  ~~~~~~~~~  ~~~~~  ~~~~~~~~

     01       7:00   7:30      8:00

"""
        mtta.models._mockable_open("100.txt", "rb").AndReturn(StringIO.StringIO(schedule))
        self.mox.ReplayAll()
        TripDay.import_schedule(self.signup, "100.txt")
        self.mox.VerifyAll()
        self.assert_expected_trip_object_counts_100()
        service = Service.objects.get(signup=self.signup)
        self.assertEqual(service.service_id, 1)
        tripday = TripDay.objects.get()
        self.assertEqual(tripday.linedir, self.linedirs["100-0"])
        self.assertEqual(tripday.service, service)
        ts0, ts1, ts2 = TripStop.objects.all()
        # 123Ar/Arch124a - Timing node
        self.assertEqual(ts0.seq, 0)
        self.assertEqual(ts0.tripday, tripday)
        self.assertEqual(ts0.stop_abbr, "5498")
        self.assertEqual(ts0.stop, self.stops[5498])
        self.assertEqual(ts0.node_abbr, "123Ar")
        self.assertEqual(ts0.node, self.nodes[635])
        # Adm106p - Stop
        self.assertEqual(ts1.seq, 1)
        self.assertEqual(ts1.tripday, tripday)
        self.assertEqual(ts1.stop_abbr, "5440")
        self.assertEqual(ts1.stop, self.stops[5440])
        self.assertEqual(ts1.node_abbr, "")
        self.assertEqual(ts1.node, None)
        # Adm/MemE / AdmMem - Timing Node
        self.assertEqual(ts2.tripday, tripday)
        self.assertEqual(ts2.seq, 2)
        self.assertEqual(ts2.stop_abbr, "5478")
        self.assertEqual(ts2.stop, self.stops[5478])
        self.assertEqual(ts2.node_abbr, "Adm/MemE")
        self.assertEqual(ts2.node, self.nodes[736])
        trip = Trip.objects.get()
        self.assertEqual(trip.seq, 0)
        self.assertEqual(trip.tripday, tripday)
        self.assertEqual(trip.pattern, self.patterns["100-01"])
        tt0, tt1, tt2 = TripTime.objects.all()
        self.assertEqual(tt0.trip, trip)
        self.assertEqual(tt0.tripstop, ts0)
        self.assertEqual(tt0.time, "7:00")
        self.assertEqual(tt1.trip, trip)
        self.assertEqual(tt1.tripstop, ts1)
        self.assertEqual(tt1.time, "7:30")
        self.assertEqual(tt2.trip, trip)
        self.assertEqual(tt2.tripstop, ts2)
        self.assertEqual(tt2.time, "8:00")