def execute_request(self, request): instruction = request.get('inst') now_string = request.get('now', None) if now_string: now = cet_from_string(now_string) test_file = request.get('file', 'ignore') else: now = now_cet() test_file = None if instruction == 'avt': if self.answer_avt(now): increase_counter('req_avt_answered') self.perform_avt(now, test_file) else: increase_counter('req_avt_denied') elif instruction == 'prio': if self.answer_prio(now): increase_counter('req_prio_answered') self.perform_avt(now, test_file) else: increase_counter('req_prio_denied') elif instruction == 'check': mission_id = request.get('sender') exp_s = request.get('expected') if exp_s: expected = cet_from_string(exp_s) else: expected = now_cet() + timedelta(days=1) self.perform_check(mission_id, now, expected, test_file) elif instruction == 'console': self.perform_avt(now, test_file)
def get(self): increase_counter('req_trajectory') origin_id = self.request.get('from') if not self.validateID(origin_id): return destination_id = self.request.get('to') if not self.validateID(destination_id): return time_string = self.request.get('start', None) if time_string is None: start_time = now_cet() - timedelta(hours=1) else: if not self.validateDatetime(time_string): return start_time = cet_from_string(time_string) span_string = self.request.get('span', None) if span_string is None: time_span = timedelta(hours=3) else: if not self.validateDigit(span_string): return time_span = timedelta(hours=int(span_string)) output_string = json.dumps( self.trajectory_dict(origin_id, destination_id, start_time, time_span)) self.response.out.write(output_string)
def next_stop_index(self, now=None): if not now: now = now_cet() for index in range(len(self.stops)): if now < self.stops[index].est_departure: return index return None
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 activate_mission(self, now=None): if now is None: now = now_cet() if self.offset is None: self.offset = time(0) self.needs_datastore_put = True self.nominalDate = now.date() if self.destination_id is None: self.stops = [] else: self.awake_stops() self.check_mission_announcements(now)
def get(self): user = users.get_current_user() if user: logging.info('stats request by logged in user: %s' % user.nickname()) else: logging.info('stats request by anonymous user') now_string = self.request.get('now') if now_string: now = cet_from_string(now_string) else: now = now_cet() self.response.out.write(json.dumps(TASeries.statistics(now)))
def test_object_creation(self): now = now_cet() agent = TSStationAgent.get('nl.test') logging.info('New agent: %s' % agent) agent.updated = now agent.cache_set() agent = TSStationAgent.get('nl.test') self.assertEqual(agent.id_, 'nl.test') self.assertEqual(agent.code, 'test') self.assertEqual(agent.country, 'nl') self.assertEqual(agent.updated, now) logging.info('Updated agent: %s' % agent)
def delete_point(self, station_id): expired_point = self.point_for_station(station_id) if expired_point: logging.info('Delete point %s' % station_id) tasks = [] issue_time_cet = now_cet() for mission_id in self.all_mission_ids(Direction.up) + self.all_mission_ids(Direction.down): issue_time_cet += timedelta(seconds=config.INTERVAL_BETWEEN_UPDATE_MSG) tasks.append(self.stop_task(TAStop.revoked_stop(mission_id, station_id), issue_time_cet)) issue_tasks(tasks) expired_point.delete() self.reset_points() else: logging.warning('Point %s could not be found for deletion' % station_id)
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 get(self): increase_counter('req_departures') series_id = self.request.get('series') if not self.validateID(series_id): self.reject() return origin_id = self.request.get('from') if not self.validateID(origin_id): self.reject() return direction_string = self.request.get('dir') if direction_string == 'up': direction = Direction.up elif direction_string == 'down': direction = Direction.down else: self.reject() return time_string = self.request.get('start', None) if time_string is None: start_time = now_cet() - timedelta(hours=1) else: if not self.validateDatetime(time_string): return start_time = cet_from_string(time_string) span_string = self.request.get('span', None) if span_string is None: time_span = timedelta(hours=3) else: if not self.validateDigit(span_string): return time_span = timedelta(hours=int(span_string)) series = TASeries.get(series_id) if not series: self.reject() return output_string = json.dumps( self.departures_dict(series, origin_id, direction, start_time, time_span)) self.response.out.write(output_string)
def status_at_time(self, now=None): if len(self.stops) == 0: return MissionStatuses.inactive, 0.0 if now is None: now = now_cet() if now > self.est_arrival_cet: return MissionStatuses.arrived, self.last_stop.delay_dep index = self.next_stop_index(now) stop = self.stops[index] if stop.status == StopStatuses.canceled: return MissionStatuses.canceled, stop.delay_dep if index == 0: if stop.status == StopStatuses.announced: return MissionStatuses.announced, stop.delay_dep else: return MissionStatuses.inactive, 0.0 return MissionStatuses.running, stop.delay_dep
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 current_mission_ids(self, direction, now=None): if now is None: now = now_cet() if direction == Direction.up: start_time = now - timedelta(minutes=(self.last_point.upArrival + 30)) end_time = now - timedelta(minutes=self.first_point.upDeparture) else: start_time = now - timedelta(minutes=(self.first_point.downArrival + 30)) end_time = now - timedelta(minutes=self.last_point.downDeparture) min_time = (now - timedelta(hours=3)).replace(hour=0, minute=0, second=0) if start_time < min_time: start_time = min_time max_time = min_time.replace(hour=23, minute=59, second=59) if end_time > max_time: end_time = max_time source = self.mission_lists[direction] start_index = bisect.bisect_left(source, (start_time.time(), 0)) end_index = bisect.bisect_right(source, (end_time.time(), 999999), lo=start_index) output = [] for index in range(start_index, end_index): offset, number = source[index] output.append('%s.%d' % (self.country, number)) return output
def perform(self): instruction = self.request.get('inst') if instruction == 'check': self.resource.check_mission_announcements(now_cet())
def update_stop(self, updated): now = updated.now if now is None: now = now_cet() status, delay = self.status_at_time(now) if status == MissionStatuses.arrived: logging.info('Update was ignored because mission has already arrived') return changes = False small_changes = False self.issue_time = now index = self.index_for_stop(updated) if index is not None: existing = self.stops[index] self.tasks = [] if existing.status != updated.status: logging.info('Change status at %s from %s to %s.' % (existing.station_id, StopStatuses.s[existing.status], StopStatuses.s[updated.status])) if updated.status == StopStatuses.revoked: self.remove_stop(index) existing = None changes = True else: if existing.status == StopStatuses.planned and updated.status == StopStatuses.announced: small_changes = True elif existing.status == StopStatuses.altDestination and updated.status == StopStatuses.announced: self.reset_destination() changes = True else: if updated.status == StopStatuses.canceled: self.check_for_canceled(index - 1) self.check_for_canceled(index + 1) elif existing.status == StopStatuses.canceled: self.check_for_uncanceled(index - 1) self.check_for_uncanceled(index + 1) changes = True existing.status = updated.status if existing is not None: if existing.delay_dep != updated.delay_dep: logging.info('Change delay at %s from %.1f to %.1f.' % (existing.station_id, existing.delay_dep, updated.delay_dep)) next_index = self.next_stop_index(now) if index == next_index: increasing = bool(existing.delay_dep < updated.delay_dep) self.update_delay(index, updated.delay_dep, increasing) self.schedule_more_updates(updated, now) else: if next_index is not None and existing.delay_dep == 0: next_stop = self.stops[next_index] self.issue_time += timedelta(seconds=config.INTERVAL_BETWEEN_UPDATE_MSG) self.tasks.append(self.instruction_task(next_stop.station_url, 'prio', self.issue_time)) existing.delay_dep = updated.delay_dep changes = True if existing.platform != updated.platform and updated.platform is not None: logging.info('Change platform at %s from %s to %s.' % (existing.station_id, existing.platform, updated.platform)) existing.platform = updated.platform changes = True if existing.platformChange != updated.platformChange: existing.platformChange = updated.platformChange if existing.destination != updated.destination and updated.destination is not None: logging.info('Change destination at %s from %s to %s.' % (existing.station_id, existing.destination, updated.destination)) existing.destination = updated.destination changes = True self.update_destination(updated.destination) if existing.alteredDestination != updated.alteredDestination: logging.info('Change altered destination at %s from %s to %s.' % (existing.station_id, existing.alteredDestination, updated.alteredDestination)) if updated.alteredDestination is None: self.reset_destination() else: self.alter_destination(updated.alteredDestination) existing.alteredDestination = updated.alteredDestination changes = True if existing.departure != updated.departure and updated.departure is not None: logging.info('Change departure at %s from %s to %s.' % (existing.station_id, existing.departure.strftime('%H:%M'), updated.departure.strftime('%H:%M'))) logging.info('%s ==> %s' % (existing.departure, updated.departure)) delta = updated.departure - existing.departure existing.arrival += delta existing.departure = updated.departure changes = True issue_tasks(self.tasks) self.tasks = None else: if updated.status == StopStatuses.announced or updated.status == StopStatuses.extra: self.anterior_stops(updated) changes = True if changes: increase_counter('mission_changes') self.put() else: if small_changes: increase_counter('mission_small_changes') self.cache_set() else: increase_counter('mission_no_changes')
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)