def test_odids(self): # FRS 10.4 setting originID and destinationID # 1) Creating the dictionary mission = TAMission.new('nl.1234') self.assertEqual(mission.odIDs_dictionary, {'d': [None, None]}) # 2) Reading and writing mission.nominalDate = now_cet().date() mission.odIDs_dictionary['d'] = ['nl.asd', 'nl.ehv'] mission.origin_id = 'nl.asd' mission.destination_id = 'nl.ehv' self.assertFalse(mission.needs_datastore_put) mission.put() mission = TAMission.get('nl.1234') self.assertEqual(mission.origin_id, 'nl.asd') self.assertEqual(mission.destination_id, 'nl.ehv') self.assertEqual(mission.get_odIDs_string(0), 'nl.asd-nl.ehv') self.assertEqual(len(mission.odIDs_dictionary), 1) mission.set_odIDs_string(5, 'nl.asd-nl.ht') mission.set_odIDs_string(6, '-') self.assertTrue(mission.needs_datastore_put) self.assertEqual(mission.get_odIDs_for_weekday(5), ['nl.asd', 'nl.ht']) self.assertEqual(mission.get_odIDs_for_weekday(6), [None, None]) self.assertEqual(len(mission.odIDs_dictionary), 3) # 3) Optimizing the dictionary for weekday in range(6): mission.set_odIDs_string(weekday, 'nl.asd-nl.mt') self.assertEqual(len(mission.odIDs_dictionary), 8) mission.optimize_odIDs_dictionary() self.assertEqual(len(mission.odIDs_dictionary), 2) self.assertTrue(mission.needs_datastore_put)
def update_stops_from_file(self, filename): stops_file = open(filename, 'r') array = json.load(stops_file) for element in array: mission = TAMission.get(str(element['id'])) stop = TAStop.fromRepr(element['payload']) mission.update_stop(stop)
def change_offsets(self, deltaOffsets): new_list = [[], []] processed_objects = [] processed_missions = {} processed_points = {} for point in self.points: point.upArrival += deltaOffsets[Direction.up] point.upDeparture += deltaOffsets[Direction.up] point.downArrival += deltaOffsets[Direction.down] point.downDeparture += deltaOffsets[Direction.down] processed_points[point.id] = point processed_objects.append(point) for direction in (Direction.up, Direction.down): if deltaOffsets[direction]: for missionID in self.all_mission_ids(direction): mission = TAMission.get(missionID) old_offset = datetime(2002, 2, 2).replace(hour=mission.offset_time.hour, minute=mission.offset_time.minute) new_offset = round_mission_offset(old_offset - timedelta(minutes=deltaOffsets[direction])) mission.offset_time = new_offset.time() new_list[direction].append((mission.offset_time, mission.number)) processed_missions[missionID] = mission processed_objects.append(mission) self._missions_list = new_list memcache.set_multi(processed_points, namespace='TAScheduledPoint') memcache.set_multi(processed_missions, namespace='TAMission') db.put(processed_objects) self.cache_set()
def correctedOffsetUTC(archivedMission): ''' Replaces the offset time as stored in the TAArchivedMission with that from the corresponding TAMission, while retaining the date. ''' originalMission = TAMission.get('%s.%d' % (archivedMission.country, archivedMission.baseNumber)) offsetCET = mark_cet(datetime.combine(archivedMission.offset_CET.date(), originalMission.offset)) return utc_from_cet(offsetCET)
def xml_missions(self): element = self.xml missions_tag = XMLElement('missions') for missionID in self.planned_mission_ids: mission = TAMission.get(missionID) missions_tag.add(mission.xml) element.add(missions_tag) return element
def test_mission_management(self): TASeries.import_xml('TestTASeries.data/series_005.xml') series = TASeries.get('nl.005') self.assertEqual( series.nr_of_missions, 12, "FRS 9.6.1 TASeries must show how much missions it contains") mission = TAMission.get('nl.300527', create=True) mission.put() series = TASeries.get('nl.005') self.assertEqual( series.nr_of_missions, 13, "FRS 9.6.2 TASeries must make it possible to add a new mission") expected = [ 'nl.523', 'nl.527', 'nl.300527', 'nl.531', 'nl.535', 'nl.539', 'nl.543' ] result = series.all_mission_ids(Direction.up) self.assertEqual( expected, result, "FRS 9.6.3 TASeries must provide all missions belonging to a series.\nExpected: %s\nResult: %s" % (expected, result)) now = datetime(2011, 1, 11, 11, 11) expected = ['nl.527', 'nl.300527', 'nl.531', 'nl.535', 'nl.539'] result = series.current_mission_ids(Direction.up, now) self.assertEqual( expected, result, "FRS 9.6.4 TASeries must provide its current missions.\nExpected: %s\nResult: %s" % (expected, result)) expected = ['nl.528', 'nl.532', 'nl.536'] result = series.current_mission_ids(Direction.down, now) self.assertEqual( expected, result, "FRS 9.6.4 TASeries must provide its current missions.\nExpected: %s\nResult: %s" % (expected, result)) searchStart = datetime(2011, 1, 11, 8, 8) searchSpan = timedelta(hours=2) expected = [(datetime(2011, 1, 11, 8, 50), 'nl.527'), (datetime(2011, 1, 11, 8, 50), 'nl.300527'), (datetime(2011, 1, 11, 9, 50), 'nl.531')] result = series.relevant_mission_tuples('nl.ut', searchStart, searchSpan, destinationID='nl.zl') self.assertEqual( expected, result, "FRS 9.6.5 TASeries must provide a list of relevant missions.\nExpected: %s\nResult: %s" % (expected, result)) expected = [(datetime(2011, 1, 11, 8, 18), 'nl.524'), (datetime(2011, 1, 11, 9, 18), 'nl.528')] result = series.relevant_mission_tuples('nl.zl', searchStart, searchSpan, destinationID='nl.ut') self.assertEqual( expected, result, "FRS 9.6.5 TASeries must provide a list of relevant missions.\nExpected: %s\nResult: %s" % (expected, result))
def get(self): increase_counter('req_mission') mission_id = self.request.get('id') if not self.validateID(mission_id): return mission = TAMission.get(mission_id) if not mission: self.reject() return output_string = json.dumps(mission.repr) self.response.out.write(output_string)
def get_missions(self, direction, current=False): array = [] if current: id_list = self.current_mission_ids(direction) else: id_list = self.all_mission_ids(direction) for missionID in id_list: mission = TAMission.get(missionID) if not mission: continue array.append(mission) return array
def statistics(cls, now=None): if now is None: now = now_cet() status_hist = {} delay_hist = {} for seriesID in TASeries.all_ids(): series = TASeries.get(seriesID) for mission_id in series.current_mission_ids(Direction.up, now) + series.current_mission_ids(Direction.down, now): mission = TAMission.get(mission_id) status, delay = mission.status_at_time(now) data = MissionStatuses.s[status] status_hist[data] = status_hist.get(data, 0) + 1 if status == MissionStatuses.running: data = '%.0f' % delay delay_hist[data] = delay_hist.get(data, 0) + 1 return {'status': status_hist, 'delay': delay_hist, 'counter': counter_dict()}
def test_revoke_stops(self): """ FRS 10.10 Revoking stops """ # Load sample data: TSStation.update_stations('TestTAMission.data/stations.xml') TASeries.import_xml('TestTAMission.data/series.xml') mission = TAMission.get('nl.3046') mission.activate_mission(mark_cet(datetime(2013, 2, 18, 2))) self.assertEqual(len(mission.stops), 5) self.assertEqual(mission.origin_id, 'nl.ah') self.assertEqual(mission.destination_id, 'nl.asd') mission.put() # STEP 10a revoke Ede self.post_stops_from_file('TestTAMission.data/step_10_10a.json') mission = TAMission.get('nl.3046') self.assertEqual(len(mission.stops), 4) self.assertEqual(mission.origin_id, 'nl.ah') self.assertEqual(mission.destination_id, 'nl.asd') # ...and set a delay for Arnhem - this must not cause an error when revoking Arnhem self.assertEqual(mission.first_stop.station_id, 'nl.ah') self.assertEqual(mission.first_stop.delay_dep, 15.0) # STEP 10b revoke Arnhem self.post_stops_from_file('TestTAMission.data/step_10_10b.json') mission = TAMission.get('nl.3046') self.assertEqual(len(mission.stops), 3) self.assertEqual(mission.origin_id, 'nl.klp') # STEP 10c revoke Utrecht and Veenendaal De Klomp self.post_stops_from_file('TestTAMission.data/step_10_10c.json') mission = TAMission.get('nl.3046') self.assertEqual(len(mission.stops), 0) self.assertEqual(mission.origin_id, None) self.assertEqual(mission.destination_id, None) mission = TAMission.get('nl.3046') mission.activate_mission(mark_cet(datetime(2013, 2, 19, 2))) self.assertEqual(len(mission.stops), 8) self.assertEqual(mission.origin_id, 'nl.ah') self.assertEqual(mission.destination_id, 'nl.amr') mission.put() # STEP 10d reset Arnhem self.post_stops_from_file('TestTAMission.data/step_10_10d.json') mission = TAMission.get('nl.3046') self.assertEqual(len(mission.stops), 5) self.assertEqual(mission.origin_id, 'nl.ah') self.assertEqual(mission.destination_id, 'nl.asd') self.assertEqual(mission.stops[4].status, StopStatuses.finalDestination)
def test_object_fetch(self): # Create sample data: missionData = ['nl.2641', 'nl.2642', 'nl.2643'] for id in missionData: mission = TAMission.new(id) mission.put() # Fetch object url and parse as JSON: response = self.missionApp.get('/TAMission/%s' % id) dictionary = json.loads(response.body) self.assertEqual(dictionary['id'], id) # Fetch the catalog: response = self.missionApp.get('/TAMission') self.assertEqual(response.body, '["nl.2641", "nl.2642", "nl.2643"]')
def processMissions(self, missionIDs, direction, table): if self.deltaOffset[direction]: for missionID in missionIDs: # Change mission offset time: mission = TAMission.get(missionID) oldOffset = datetime(2002, 2, 2).replace(hour=mission.offset.hour, minute=mission.offset.minute) newOffset = round_mission_offset(oldOffset - timedelta(minutes=self.deltaOffset[direction]), self.round[direction]) mission.offset = newOffset.time() # Add mission to queue for saveChanges self.processedMissions[missionID] = mission self.processedObjects.append(mission) # Report the changes: row = table.add_row() row.add_to_cell(0, missionID) row.add_to_cell(1, '%s %s %s' % (oldOffset.strftime('%H:%M'), change_string(-self.deltaOffset[direction]), newOffset.strftime('%H:%M')))
def test_import_export(self): """ FRS 9.2 Importing and exporting a series """ TASeries.import_xml('TestTASeries.data/series_basic.xml') # Supplementary missions must not appear in xml output mission = TAMission.get('nl.300546', create=True) mission.put() series = TASeries.get('nl.005') self.assertEqual( series.name, '500', "FRS 9.1.1 A TASeries name property must provide the series number in hundreds" ) # FRS 9.3.1 A TASeries object must provide its contents in xml-format. input_xml = open('TestTASeries.data/series_basic.xml', 'r').read() output_xml = series.xml_document.write(lf=True) self.assertEqual(input_xml.strip(), output_xml.strip())
def startElement(self, name, attrs): self.data = [] if name == 'series': id = attrs['id'] logging.info('import series: %s', id) self.series = TASeries.new(id) self.series.type = attrs.get('type') self.routePoints = {} if self.series: if name == 'station': point = TAScheduledPoint.new_with(self.series.id, attrs['id']) point.km = float(attrs['km']) stationName = attrs.get('name', None) if stationName: point.stationName = stationName self.routePoints[attrs['id']] = point if name == 'up': point = self.routePoints[attrs['station']] point.upArrival = minutes_from_string(attrs['arr']) point.upDeparture = minutes_from_string(attrs['dep']) point.set_platform_string(Direction.up, attrs.get('platform', '-')) if name == 'down': point = self.routePoints[attrs['station']] point.downArrival = minutes_from_string(attrs['arr']) point.downDeparture = minutes_from_string(attrs['dep']) point.set_platform_string(Direction.down, attrs.get('platform', '-')) if name == 'mission': self.mission = TAMission.new(attrs['id']) self.mission.series_id = self.series.id self.mission.offset_string = attrs['offset'] if self.mission: if name == 'od': origin = attrs['from'] if origin == 'None': origin = None destination = attrs['to'] if destination == 'None': destination = None self.mission.odIDs_dictionary[str(attrs['day'])] = [origin, destination]
def analyzeOffset(self, missionIDs): self.offset = [None, None] self.data=[[], []] firstHalfHist = dict() firstHalfItems = 0 secondHalfHist = dict() secondHalfItems = 0 for missionID in missionIDs: mission = TAMission.get(missionID) num = mission.number if bool(num % 2): num -= 1 key = mission.offset.minute if bool(num % 4): firstHalfHist[key] = firstHalfHist.get(key, 0) + 1 firstHalfItems += 1 else: secondHalfHist[key] = secondHalfHist.get(key, 0) + 1 secondHalfItems += 1 self.generateData(FIRST_HALF, firstHalfHist, firstHalfItems) self.generateData(SECND_HALF, secondHalfHist, secondHalfItems)
def perform(self): instruction = self.request.get('inst') if instruction == 'fetch': if self.resource: self.resource.import_schedule() self.response.out.write('<a href=\"/console/series?id=%s\">terug naar serie</a>' % self.resource.id) else: TASeries.import_xml('series.data/series.xml') self.redirect('/console/series') return if not self.resource: logging.warning('Resource not found.') return if instruction == 'new_day': now_string = self.request.get('now') if now_string: now = cet_from_string(self.request.get('now')) else: now = now_cet() self.resource.activate_new_day(now) elif instruction == 'delete_point': sender = self.request.get('sender') self.resource.delete_point(sender) self.response.out.write('<a href=\"/console/series?id=%s\">terug naar serie</a>' % self.resource.id) elif instruction == 'optimize_odids': changed_missions = [] for mission in self.resource.up_missions + self.resource.down_missions: mission.optimize_odIDs_dictionary() if mission.needs_datastore_put: changed_missions.append(mission) memcache.set_multi(TAMission.dictionary_from_list(changed_missions), namespace='TAMission') db.put(changed_missions) self.response.out.write('<a href=\"/console/missions?kind=pattern&series=%s\">terug naar serie</a>' % self.resource.id)
def test_new_day(self): """ FRS 9.5 Activating new day FRS 9.8 Providing statistics """ TSStation.update_stations('TestTASeries.data/stations_020.xml') TASeries.import_xml('TestTASeries.data/series_020.xml') supplementary_mission = TAMission.new('nl.302020') supplementary_mission.offset_cet = datetime(2013, 5, 17, 8, 0) series = TASeries.get('nl.020') series.add_mission(supplementary_mission) self.assertEqual( series.nr_of_missions, 14, "A supplementary mission must be added to the series") response = self.seriesApp.post('/TASeries/nl.020', { 'inst': 'new_day', 'now': '2013-05-18T02:00:00+0100' }) self.assertEqual(response.status, '200 OK') series = TASeries.get('nl.020') self.assertEqual(series.nr_of_missions, 13, "FRS 9.5.2 Supplementary missions must be removed") mission_2024 = TAMission.get('nl.2024') self.assertEqual( len(mission_2024.stops), 3, "FRS 9.5.3 Stops for the next day must be added to the mission") point_gd = TAScheduledPoint.get('nl.020_gd') self.assertEqual(point_gd.scheduled_times, (26, 27, 33, 34)) self.assertEqual(point_gd.platform_list, [['10'], ['5']]) self.update_stops_from_file('TestTASeries.data/stops_020.json') # FRS 9.8.1 TASeries must provide statistics result = TASeries.statistics(mark_cet(datetime(2013, 5, 18, 8, 30))) expected = { 'status': { 'running': 2 }, 'delay': { '0': 1, '2': 1 }, 'counter': { 'mission_changes': 13, 'mission_no_changes': 0, 'mission_small_changes': 0, 'req_api_success': 0, 'req_api_total': 0, 'req_avt_answered': 0, 'req_avt_denied': 0, 'req_check_confirmed': 0, 'req_check_denied': 0, 'req_check_refetched': 0, 'req_check_revoked': 0, 'req_departures': 0, 'req_mission': 0, 'req_prio_answered': 0, 'req_prio_denied': 0, 'req_trajectory': 0 } } self.assertEqual(expected, result) response = self.seriesApp.post('/TASeries/nl.020', { 'inst': 'new_day', 'now': '2013-05-19T02:00:00+0100' }) self.assertEqual(response.status, '200 OK') self.assertEqual(series.nr_of_missions, 13) chart = TAChart.get('nl.020_201320') expected = { 'pattern_up': { 'nl.gvc': { '9': 2 }, 'nl.gd': { '30': 2 }, 'nl.ut': { '46': 2 } }, 'pattern_down': { 'nl.gd': { '35': 11 }, 'nl.gvc': { '52': 11 }, 'nl.ut': { '14': 11 } }, 'delay_up': { 'nl.gvc': { '0.0': 2 }, 'nl.gd': { '2.0': 2 }, 'nl.ut': { '0.0': 2 } }, 'delay_down': { 'nl.gd': { '0.0': 8, '2.0': 3 }, 'nl.gvc': { '0.0': 11 }, 'nl.ut': { '0.0': 11 } }, 'platform_up': { 'nl.gvc': { '5': 2 }, 'nl.gd': { '4': 2 }, 'nl.ut': {} }, 'platform_down': { 'nl.gd': { '8': 10, '10': 1 }, 'nl.gvc': {}, 'nl.ut': { '9': 11 } } } result = chart._dataDictionary self.assertEqual( expected, result, "FRS 9.5.1 Data over the past day must be processed in a chart.\nExpected: %s\nResult: %s" % (expected, result)) mission_2024 = TAMission.get('nl.2024') self.assertEqual( len(mission_2024.stops), 0, "FRS 9.5.3 Stops for the next day must be added to the mission") point_gd = TAScheduledPoint.get('nl.020_gd') self.assertEqual( point_gd.scheduled_times, (26, 27, 34, 35), "FRS 9.5.4 TAChart must verify points and modify when needed.") self.assertEqual( point_gd.platform_list, [['8'], ['4']], "FRS 9.5.4 TAChart must verify points and modify when needed.") # FRS 9.9 TASeries must delete references to a station taskq = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME) taskq.FlushQueue('default') series = TASeries.get('nl.020') self.assertEqual(len(series.points), 3) response = self.seriesApp.post('/TASeries/nl.020', { 'inst': 'delete_point', 'sender': 'nl.gd' }) self.assertEqual(response.status, '200 OK') series = TASeries.get('nl.020') self.assertEqual(len(series.points), 2) tasks = taskq.GetTasks('default') self.assertEqual(len(tasks), 13)
def receive(self, dictionary): stop = TAStop.fromRepr(dictionary) mission = TAMission.get(self.resource_id, create=True) mission.update_stop(stop)
def test_discover_mission(self): # Load sample data: TSStation.update_stations('TestTAMission.data/stations.xml') TASeries.import_xml('TestTAMission.data/series.xml') # FRS 10.6 Discover new mission, from scratch self.post_stops_from_file('TestTAMission.data/step_10_6a.json') mission_orphan = TAMission.get('nl.9046') self.assertNotEqual(mission_orphan, None, "FRS 10.6.1 TAMission must receive updates") self.assertEqual(len(mission_orphan.stops), 1, "FRS 10.6.2 TAMission must create new mission") self.post_stops_from_file('TestTAMission.data/step_10_6b.json') self.post_stops_from_file('TestTAMission.data/step_10_6c.json') mission_orphan = TAMission.get('nl.9046') self.assertEqual(len(mission_orphan.stops), 3, "FRS 10.6.3 TAMission must insert new stops") self.assertEqual( mission_orphan.stops[0].station_id, 'nl.ah', "FRS 10.6.3 TAMission must place stops in the right order") self.assertEqual( mission_orphan.stops[1].station_id, 'nl.klp', "FRS 10.6.3 TAMission must place stops in the right order") self.assertEqual( mission_orphan.stops[2].station_id, 'nl.ut', "FRS 10.6.3 TAMission must place stops in the right order") for stop in mission_orphan.stops: self.assertEqual( stop.status, StopStatuses.announced, "FRS 10.6.4 Updated stops must get 'announced' as status") memcache.delete('nl.9046', namespace='TAMission') mission_orphan = TAMission.get('nl.9046') self.assertEqual( len(mission_orphan.stops), 3, "FRS 10.6.5 After significant changes, missions must be stored in the datastore" ) # FRS 10.7 Discover new mission, from series series = TASeries.get('nl.030') series.activate_new_day(mark_cet(datetime(2013, 2, 19, 2, 0))) # Check sample data mission_44 = TAMission.get('nl.3044') self.assertEqual(mission_44, None) # STEP 7a: insert Veenendaal De Klomp self.post_stops_from_file('TestTAMission.data/step_10_7a.json') mission_44 = TAMission.get('nl.3044') self.log_mission(mission_44) self.assertEqual(mission_44.series.id, 'nl.030') self.assertEqual(mission_44.offset_time.strftime('%H:%M'), '13:00') self.assertEqual(mission_44.origin_id, 'nl.klp') self.assertEqual(mission_44.destination_id, 'nl.asd') # FRS 10.7.3 Mission must create stops self.assertEqual(len(mission_44.stops), 3) stop_klp = mission_44.stops[0] self.assertEqual(stop_klp.station_id, 'nl.klp') self.assertEqual(stop_klp.status, StopStatuses.announced) self.assertEqual(stop_klp.departure.strftime('%H:%M'), '13:46') self.assertEqual(mission_44.stops[1].station_id, 'nl.ut') self.assertEqual(mission_44.stops[1].status, StopStatuses.planned) self.assertEqual(mission_44.stops[2].station_id, 'nl.asd') self.assertEqual(mission_44.stops[2].status, StopStatuses.finalDestination) self.assertEqual(mission_44.odIDs, ['nl.klp', 'nl.asd']) # STEP 7b: insert Arnhem self.post_stops_from_file('TestTAMission.data/step_10_7b.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(mission_44.origin_id, 'nl.ah') self.assertEqual(mission_44.destination_id, 'nl.asd') # FRS 10.7.4 Mission must insert new stops prior to current stops self.assertEqual(len(mission_44.stops), 5) self.assertEqual(mission_44.stops[0].station_id, 'nl.ah') self.assertEqual(mission_44.stops[0].status, StopStatuses.announced) self.assertEqual(mission_44.stops[1].station_id, 'nl.ed') self.assertEqual(mission_44.stops[1].status, StopStatuses.planned) self.assertEqual(mission_44.stops[4].station_id, 'nl.asd') self.assertEqual(mission_44.stops[4].status, StopStatuses.finalDestination) self.assertEqual(mission_44.odIDs, ['nl.ah', 'nl.asd']) # STEP 7c: update Ede Wageningen (should already be there) self.post_stops_from_file('TestTAMission.data/step_10_7c.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(mission_44.origin_id, 'nl.ah') self.assertEqual(mission_44.destination_id, 'nl.asd') # FRS 10.7.5 Mission must update stops self.assertEqual(len(mission_44.stops), 5) self.assertEqual(mission_44.stops[1].station_id, 'nl.ed') self.assertEqual(mission_44.stops[1].status, StopStatuses.announced) # FRS 10.7.6 Update from planned to announced may not cause datastore put memcache.delete('nl.3044', namespace='TAMission') mission_44 = TAMission.get('nl.3044') self.assertEqual(len(mission_44.stops), 5) self.assertEqual(mission_44.stops[1].station_id, 'nl.ed') self.assertEqual(mission_44.stops[1].status, StopStatuses.planned) # STEP 7Rc: revoke Ede Wageningen self.post_stops_from_file('TestTAMission.data/step_10_7Rc.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(len(mission_44.stops), 4) # STEP 7c again: update Ede Wageningen, inserting a scheduled stop may not cause resetting of origin self.post_stops_from_file('TestTAMission.data/step_10_7c.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(len(mission_44.stops), 5) self.assertEqual(mission_44.origin_id, 'nl.ah') self.assertEqual(mission_44.destination_id, 'nl.asd') # STEP 7d: update Utrecht (should already be there) self.post_stops_from_file('TestTAMission.data/step_10_7d.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(mission_44.origin_id, 'nl.ah') self.assertEqual(mission_44.destination_id, 'nl.asd') self.assertEqual(len(mission_44.stops), 5) self.assertEqual(mission_44.stops[3].station_id, 'nl.ut') self.assertEqual(mission_44.stops[3].status, StopStatuses.announced) # STEP 7e: update Amsterdam (should already be there) self.post_stops_from_file('TestTAMission.data/step_10_7e.json') mission_44 = TAMission.get('nl.3044') # FRS 10.7.7 Mission must insert new stops after current stops self.assertEqual(len(mission_44.stops), 8) self.assertEqual(mission_44.stops[4].station_id, 'nl.asd') self.assertEqual(mission_44.stops[6].station_id, 'nl.zd') self.assertEqual(mission_44.stops[7].station_id, 'nl.amr') #FRS 10.7.8 Satus of last_stop must be finalDestination self.assertEqual(mission_44.stops[4].status, StopStatuses.announced) self.assertEqual(mission_44.stops[6].status, StopStatuses.planned) self.assertEqual(mission_44.stops[7].status, StopStatuses.finalDestination) self.assertEqual(mission_44.odIDs, ['nl.ah', 'nl.amr']) # STEP 7f: insert Amstel (intermediate station, not in series) self.post_stops_from_file('TestTAMission.data/step_10_7f.json') mission_44 = TAMission.get('nl.3044') # FRS 10.7.9 Mission must receive intermediate stop self.assertEqual(len(mission_44.stops), 9) self.assertEqual(mission_44.stops[4].station_id, 'nl.asa') self.assertEqual(mission_44.odIDs, ['nl.ah', 'nl.amr']) # STEP 7g: insert Nijmegen (starting station, not in series) self.post_stops_from_file('TestTAMission.data/step_10_7g.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(mission_44.odIDs, ['nl.ah', 'nl.amr']) # FRS 10.7.10 Mission must receive new starting station self.assertEqual(len(mission_44.stops), 10) self.assertEqual(mission_44.stops[0].station_id, 'nl.nm') # STEP 7h: update Alkmaar (destination of series, but indicating a further destination) self.post_stops_from_file('TestTAMission.data/step_10_7h.json') mission_44 = TAMission.get('nl.3044') # FRS 10.7.11 Mission must receive finalDestination outside of series self.assertEqual(len(mission_44.stops), 10) self.assertEqual(mission_44.stops[9].station_id, 'nl.amr') self.assertEqual(mission_44.stops[9].status, StopStatuses.announced) self.assertEqual(mission_44.odIDs, ['nl.ah', 'nl.amr']) # STEP 7i: insert Schagen (after Alkmaar, not in series) self.post_stops_from_file('TestTAMission.data/step_10_7i.json') mission_44 = TAMission.get('nl.3044') # FRS 10.7.12/13 Mission must receive extra intermediate stop self.assertEqual(len(mission_44.stops), 11) self.assertEqual(mission_44.stops[10].station_id, 'nl.sgn') self.assertEqual(mission_44.stops[10].status, StopStatuses.extra) self.assertEqual(mission_44._odIDsDictionary, { '1': ['nl.ah', 'nl.amr'], 'd': [None, None] }) # STEP 7j: insert Veenendaal De Klomp for the next day self.post_stops_from_file('TestTAMission.data/step_10_7j.json') mission_44 = TAMission.get('nl.3044') self.assertEqual(mission_44.stops[3].station_id, 'nl.klp') self.assertEqual(mission_44.stops[3].departure.replace(tzinfo=None), datetime(2013, 2, 19, 13, 46)) # test counters self.assertEqual(read_counter('mission_changes'), 12) self.assertEqual(read_counter('mission_small_changes'), 2) self.assertEqual(read_counter('mission_no_changes'), 0)
def test_disruptions(self): # Load sample data: TSStation.update_stations('TestTAMission.data/stations.xml') TASeries.import_xml('TestTAMission.data/series.xml') mission = TAMission.get('nl.3046') self.assertNotEqual(mission, None) mission.activate_mission(mark_cet(datetime(2013, 2, 19, 2))) mission.put() taskq = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME) taskq.FlushQueue('default') # STEP 8a De Klomp +8 self.post_stops_from_file('TestTAMission.data/step_10_8a.json') mission = TAMission.get('nl.3046') self.assertEqual(mission.stops[2].station_id, 'nl.klp') self.assertEqual(mission.stops[2].delay_dep, 8.0, "FRS 10.8.1 Stop must receive delay in update") self.assertEqual( mission.next_stop_index(mark_cet(datetime(2013, 2, 19, 14, 0))), 0, "FRS 10.8.2 Stop must indicate current position") self.assertEqual( mission.next_stop_index(mark_cet(datetime(2013, 2, 19, 14, 20))), 2, "FRS 10.8.2 Stop must indicate current position") self.assertEqual( mission.next_stop_index(mark_cet(datetime(2013, 2, 19, 14, 25))), 3, "FRS 10.8.2 Stop must indicate current position") self.assertEqual(mission.delay, 0.0, "FRS 10.8.5 Only nextStop must set mission delay") tasks = taskq.GetTasks('default') self.assertEqual( len(tasks), 1, "FRS 10.8.3 After receiving delay mission must queue task for current next stop" ) task0 = tasks[0] self.assertEqual(task0['url'], '/agent/station/nl.ah') self.assertEqual(task0['name'], '19_1300_41_prio_3046') taskq.FlushQueue('default') # STEP 8b Arnhem +10 self.post_stops_from_file('TestTAMission.data/step_10_8b.json') mission = TAMission.get('nl.3046') self.assertEqual(mission.stops[0].station_id, 'nl.ah') self.assertEqual(mission.stops[0].delay_dep, 5.0, "FRS 10.8.1 Stop must receive delay in update") self.assertEqual(mission.stops[1].station_id, 'nl.ed') self.assertAlmostEqual( mission.stops[1].delay_dep, 4.0, places=1, msg="FRS 10.8.4 Mission must adapt delay in next stops") self.assertAlmostEqual( mission.stops[2].delay_dep, 8.0, places=1, msg="FRS 10.8.6 With increasing delay, values may only be increased" ) self.assertEqual(mission.stops[3].station_id, 'nl.ut') self.assertAlmostEqual( mission.stops[3].delay_dep, 0.4, places=1, msg="FRS 10.8.4 Mission must adapt delay in next stops") self.assertEqual(mission.stops[4].station_id, 'nl.asd') self.assertEqual(mission.stops[4].delay_dep, 0.0, "FRS 10.8.1 Stop must receive delay in update") self.assertEqual(mission.delay, 5.0, "FRS 10.8.5 nextStop must set mission delay") tasks = taskq.GetTasks('default') self.assertEqual(len(tasks), 6) task0 = tasks[0] self.assertEqual(task0['url'], '/agent/station/nl.ed') self.assertEqual(task0['name'], '19_1309_xx_prio_3046') taskq.FlushQueue('default') # STEP 8c Arnhem +15 self.post_stops_from_file('TestTAMission.data/step_10_8c.json') mission = TAMission.get('nl.3046') self.assertAlmostEqual( mission.stops[1].delay_dep, 14.0, places=1, msg="FRS 10.8.4 Mission must adapt delay in next stops") self.assertAlmostEqual( mission.stops[2].delay_dep, 13.5, places=1, msg="FRS 10.8.4 Mission must adapt delay in next stops") tasks = taskq.GetTasks('default') self.assertEqual(len(tasks), 5) taskq.FlushQueue('default') # STEP 8d Arnhem +0 self.post_stops_from_file('TestTAMission.data/step_10_8d.json') mission = TAMission.get('nl.3046') for stop in mission.stops: self.assertEqual(stop.delay_dep, 0.0) self.assertEqual(mission.delay, 0.0, "FRS 10.8.5 nextStop must set mission delay") # STEP 9a Zaandam canceled self.post_stops_from_file('TestTAMission.data/step_10_9a.json') mission = TAMission.get('nl.3046') self.assertEqual(mission.stops[6].station_id, 'nl.zd') self.assertEqual(mission.stops[6].status, StopStatuses.canceled, "FRS 10.9.1 Stop must be marked canceled") tasks = taskq.GetTasks('default') self.assertEqual( len(tasks), 1, "FRS 10.9.2 Must send priority update to neighbour station") task0 = tasks[0] self.assertEqual(task0['url'], '/agent/station/nl.ass') taskq.FlushQueue('default') # STEP 9b Zaandam reconfirmed self.post_stops_from_file('TestTAMission.data/step_10_9b.json') mission = TAMission.get('nl.3046') self.assertEqual(mission.stops[6].status, StopStatuses.announced, "FRS 10.9.3 Stop must be marked announced") tasks = taskq.GetTasks('default') self.assertEqual( len(tasks), 2, "FRS 10.9.4 Must send priority update to neighbour station") task0 = tasks[0] self.assertEqual(task0['url'], '/agent/station/nl.asd') task1 = tasks[1] self.assertEqual(task1['url'], '/agent/station/nl.ass') taskq.FlushQueue('default') # STEP 9c altDestination for orphaned mission and non-existing altDestination (may not cause errors) self.post_stops_from_file('TestTAMission.data/step_10_9c.json') # STEP 9d Utrecht says Amsterdam is altDestination self.post_stops_from_file('TestTAMission.data/step_10_9d.json') mission = TAMission.get('nl.3046') self.assertEqual(mission.stops[4].status, StopStatuses.altDestination, "FRS 10.9.5 Stop must be shortened") for index in range(5, 8): self.assertEqual(mission.stops[index].status, StopStatuses.canceled, "FRS 10.9.5 Stop must be shortened") tasks = taskq.GetTasks('default') self.assertEqual( len(tasks), 1, "FRS 10.9.6 Must send priority update to altered Destination") task0 = tasks[0] self.assertEqual(task0['url'], '/agent/station/nl.asd') # STEP 9e Amsterdam says Alkmaar is finalDestination > FRS 10.9.7 self.post_stops_from_file('TestTAMission.data/step_10_9e.json') mission = TAMission.get('nl.3046') self.assertEqual(mission.stops[4].status, StopStatuses.announced) self.assertEqual(mission.stops[5].status, StopStatuses.planned) self.assertEqual(mission.stops[6].status, StopStatuses.planned) self.assertEqual(mission.stops[7].status, StopStatuses.finalDestination) # STEP 9f self.post_stops_from_file('TestTAMission.data/step_10_9f.json') mission = TAMission.get('nl.3046') self.log_mission(mission) mission_s = TAMission.get('nl.303046') self.log_mission(mission_s) # STEP 9g self.post_stops_from_file('TestTAMission.data/step_10_9g.json') mission = TAMission.get('nl.3046') self.log_mission(mission) mission_s = TAMission.get('nl.303046') self.log_mission(mission_s) # test counters self.assertEqual(read_counter('mission_changes'), 15) self.assertEqual(read_counter('mission_small_changes'), 0) self.assertEqual(read_counter('mission_no_changes'), 0)
def test_activate_mission(self): """ FRS 10.5 Activating a mission and maintaining its status """ # Load sample data: TSStation.update_stations('TestTAMission.data/stations.xml') TASeries.import_xml('TestTAMission.data/series.xml') taskq = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME) # FRS 10.5.1 If not specified, activate_mission must set nominalDate to the current date now = now_cet().replace(hour=2) mission = TAMission.get('nl.3046') mission.activate_mission() self.assertEqual(mission.nominalDate, now.date()) taskq.FlushQueue('default') # FRS 10.5.2/3 activate_mission must generate origin_id, destination_id and stops test_set = ((mark_cet(datetime(2013, 2, 24, 2)), None, 0), (mark_cet(datetime(2013, 2, 18, 2)), 'nl.asd', 5), (mark_cet(datetime(2013, 2, 19, 2)), 'nl.amr', 8)) for (testDate, destination, nr_of_stops) in test_set: mission.activate_mission(testDate) self.assertEqual(mission.destination_id, destination) self.assertEqual(len(mission.stops), nr_of_stops) mission.put() self.assertEqual(mission.origin_id, 'nl.ah') self.assertEqual(mission.last_stop.arrival_string, '15:48') # FRS 10.5.4 activated stops must get 'planned' status, last stop 'finalDestination' for index in range(0, 6): self.assertEqual(mission.stops[index].status, StopStatuses.planned) self.assertEqual(mission.stops[7].status, StopStatuses.finalDestination) # FRS 10.5.5 TAMission must queue a check-task while awaking a mission. tasks = taskq.GetTasks('default') self.assertEqual(len(tasks), 2) self.assertEqual(tasks[1]['url'], '/TAMission/nl.3046') self.assertEqual(tasks[1]['name'], '19_1231_xx_check_3046') taskq.FlushQueue('default') # FRS 10.5.6 Mission must check announcement of stops check_time = mark_cet(datetime(2013, 2, 19, 13, 41, 22)) mission.stops[0].status = StopStatuses.announced mission.check_mission_announcements(check_time) tasks = taskq.GetTasks('default') self.assertEqual(len(tasks), 2) self.assertEqual(tasks[0]['url'], '/agent/station/nl.ed') self.assertEqual(tasks[0]['name'], '19_1241_25_check_3046') self.assertEqual(tasks[1]['url'], '/TAMission/nl.3046') self.assertEqual(tasks[1]['name'], '19_1246_xx_check_3046') taskq.FlushQueue('default') check_time = mark_cet(datetime(2013, 2, 19, 14, 02, 22)) mission.stops[0].status = StopStatuses.planned mission.stops[1].status = StopStatuses.announced mission.stops[2].status = StopStatuses.announced mission.stops[3].status = StopStatuses.announced mission.stops[4].status = StopStatuses.announced mission.check_mission_announcements(check_time) tasks = taskq.GetTasks('default') self.assertEqual(len(tasks), 1) self.assertEqual(tasks[0]['url'], '/TAMission/nl.3046') self.assertEqual(tasks[0]['name'], '19_1348_xx_check_3046') # FRS 10.5.7 Mission must provide status and delay (status, delay) = mission.status_at_time(mark_cet(datetime(2013, 2, 19, 14, 0))) self.assertEqual(status, MissionStatuses.inactive) self.assertEqual(delay, 0) mission.first_stop.status = StopStatuses.announced (status, delay) = mission.status_at_time(mark_cet(datetime(2013, 2, 19, 14, 0))) self.assertEqual(delay, 0) self.assertEqual(status, MissionStatuses.announced) (status, delay) = mission.status_at_time( mark_cet(datetime(2013, 2, 19, 14, 30))) self.assertEqual(status, MissionStatuses.running) self.assertEqual(delay, 0) (status, delay) = mission.status_at_time( mark_cet(datetime(2013, 2, 19, 15, 49))) self.assertEqual(mission.est_arrival_cet, mark_cet(datetime(2013, 2, 19, 15, 48))) self.assertEqual(status, MissionStatuses.arrived) self.assertEqual(MissionStatuses.s[status], 'arrived') self.assertEqual(delay, 0)
def get(self): mission_id = self.request.get('mission') series_id = self.request.get('series') if mission_id: the_mission = TAMission.get(mission_id) if the_mission.up: label = 'heen' else: label = 'terug' document = ConsoleDocument('Trein %d (%s)' % (the_mission.number, label)) the_series = the_mission.series if the_series: label = '%d treinen in serie %s' % (the_series.nr_of_missions, the_series.name) document.add_reference('/console/missions?kind=active&series=%s' % the_series.id, label) table = document.add_table('stops_table', ['s', 'A', 'V', 'dV', 'station', 'perron']) for the_stop in the_mission.stops: row = table.add_row() row.add_to_cell(0, the_stop.status) row.add_to_cell(1, the_stop.arrival_string) row.add_to_cell(2, the_stop.departure_string) delay = the_stop.delay_dep if delay > 0: row.add_to_cell(3, '+%d' % delay) else: row.add_to_cell(3, '-') row.add_link_to_cell(4, '/console/departures?station=%s' % the_stop.station.code, the_stop.station.name) if the_stop.platformChange: row.add_to_cell(5, '%s <<' % the_stop.platform) else: row.add_to_cell(5, the_stop.platform) self.response.out.write(document.write()) elif series_id: the_series = TASeries.get(series_id) up = self.request.get('direction') != 'down' if up: label = 'heen' reverse = 'down' reverse_label = 'toon terugrichting' points_list = the_series.points else: label = 'terug' reverse = 'up' reverse_label = 'toon heenrichting' points_list = reversed(the_series.points) document = ConsoleDocument('Treinserie %s (%s)' % (the_series.name, label)) document.add_reference('/console/schedule?series=%s&direction=%s' % (series_id, reverse),reverse_label) table = document.add_table('stops_table', ['km', 'station', 'aankomst', 'vertrek', 'perron', 'Jan', 'Feb']) for point in points_list: row = table.add_row() row.add_to_cell(0, '%.1f' % point.km) row.add_to_cell(1, point.stationName) if up: row.add_to_cell(2, str(point.upArrival)) row.add_to_cell(3, str(point.upDeparture)) row.add_to_cell(4, point.platform_string(Direction.up)) avarage, delay = point.delayStats(Direction.up, 1) if avarage != None: row.add_to_cell(5, '%.1f - %.1f' % (avarage, delay)) avarage, delay = point.delayStats(Direction.up, 2) if avarage != None: row.add_to_cell(6, '%.1f - %.1f' % (avarage, delay)) else: row.add_to_cell(2, str(point.downArrival)) row.add_to_cell(3, str(point.downDeparture)) row.add_to_cell(4, point.platform_string(Direction.down)) avarage, delay = point.delayStats(Direction.down, 1) if avarage != None: row.add_to_cell(5, '%.1f - %.1f' % (avarage, delay)) avarage, delay = point.delayStats(Direction.down, 2) if avarage != None: row.add_to_cell(6, '%.1f - %.1f' % (avarage, delay)) self.response.out.write(document.write())
def test_mission_basics(self): # Create series series_d14 = TASeries.new('eu.d14') series_d14.put() series123 = TASeries.new('nl.123') series123.put() memcache.delete('nl.123', namespace='TASeries') # Create international train mission241 = TAMission.get('eu.241', create=True) mission241.nominalDate = date(2010, 1, 31) mission241.offset_time = time(12, 0) self.assertTrue( mission241.needs_datastore_put, "FRS 10.3.7 After changing offset_time mission must be marked as needs_datastore_put" ) mission241.put() # Create standard up train mission12301 = TAMission.get(code='12301', create=True) mission12301.offset_cet = mark_cet(datetime(2010, 1, 31, 14)) mission12301.delay = 5.0 self.assertTrue( mission12301.needs_datastore_put, "FRS 10.3.7 After changing offset_time mission must be marked as needs_datastore_put" ) mission12301.put() series123 = mission12301.series self.assertEqual(series123.id, 'nl.123') # Create orphaned down train mission12402 = TAMission.get(code='12402', create=True) mission12402.put() # Create supplementary mission mission312301 = TAMission.get(code='312301', create=True) self.assertFalse(mission312301.needs_datastore_put, "Supplementary mission need no datastore put") # FRS 10.1 Mission creation self.assertNotEqual( mission12301, None, "FRS 10.1.1 A mission must be created with the get command") self.assertEqual( mission241.series_id, 'eu.d14', "FRS 10.1.2 Trainnumbers lower than 500 must be international trains" ) self.assertEqual( mission12301.series_id, 'nl.123', "FRS 10.1.3 At creation, the correct series must be assigned") self.assertEqual( mission312301.series_id, 'nl.123', "FRS 10.1.3 At creation, the correct series must be assigned") self.assertEqual( mission12402.series_id, 'orphan', "FRS 10.1.3 When the corresponding series does not exist, the mission must be marked as orphan" ) # FRS 10.2 Properties deduced from train number self.assertTrue(mission12301.up, "FRS 10.2.1 Missions with odd numbers are running up") self.assertFalse( mission12402.up, "FRS 10.2.1 Missions with even numbers are running down") self.assertEqual( mission241.ordinal, 1, "FRS 10.2.2 In international trains the last digit is the ordinal") self.assertEqual( mission12402.ordinal, 2, "FRS 10.2.2 In normal trains the last two digits are the ordinal") self.assertEqual(mission241.series_number, 24, "FRS 10.2.3 TAMission must deduce the series number") self.assertEqual(mission12301.series_number, 123, "FRS 10.2.3 TAMission must deduce the series number") self.assertEqual(mission312301.series_number, 123, "FRS 10.2.3 TAMission must deduce the series number") self.assertEqual( mission12301.base_number, 12301, "FRS 10.2.4 The last five digits form the base number") self.assertEqual( mission312301.base_number, 12301, "FRS 10.2.4 The last five digits form the base number") self.assertFalse( mission12301.supplementary, "FRS 10.2.5 Missions with five digit numbers are not supplementary" ) self.assertEqual( mission312301.supplementary, 3, "FRS 10.2.5 Missions with six digit numbers are supplementary") # FRS 10.3 Setting nominalDate and offset_time self.assertEqual(mission12301.nominalDate, date(2010, 1, 31), "FRS 10.3.1 TAMission must provide nominalDate") self.assertEqual(mission12301.date_string, '31-01-2010', "FRS 10.3.2 TAMission must provide dateString") self.assertEqual(mission12301.offset_time, time(14), "FRS 10.3.3 TAMission must provide offset_time") self.assertEqual(mission12301.offset_string, '14:00', "FRS 10.3.4 TAMission must provide offsetString") self.assertEqual(mission241.offset_cet, mark_cet(datetime(2010, 1, 31, 12)), "FRS 10.3.5 TAMission must provide offset_cet") self.assertEqual( mission312301.offset_time, time(14), "Supplementary mission must copy original mission offset") self.assertEqual(mission312301.delay, 0.0) testSet = (('09:57', '09:57'), ('09:58', '10:00'), ('10:02', '10:00'), ('10:03', '10:03'), ('10:27', '10:27'), ('10:28', '10:30'), ('10:32', '10:30'), ('10:33', '10:33')) for (timeIn, timeOut) in testSet: mission12301.offset_cet = mark_cet( datetime.strptime('2010-01-31T' + timeIn, '%Y-%m-%dT%H:%M')) self.assertEqual( mission12301.offset_string, timeOut, "FRS 10.3.6 offset_time must be rounded within two minutes %s -> %s" % (timeIn, timeOut)) # Missions must be registered correctly series_d14 = TASeries.get('eu.d14') self.assertEqual(series_d14.all_mission_ids(Direction.up), ['eu.241']) series123 = TASeries.get('nl.123') self.assertEqual(series123.all_mission_ids(Direction.up), ['nl.12301', 'nl.312301'])