def test_unresolved_answers_count_for_multiple_states(self): with self.swap(jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CC_MANAGERS_FOR_TESTS): exp_1 = self._create_and_update_fake_exploration('eid1') self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers(['eid1'])) self._record_answer('a1', exp_1, exp_1.init_state_name) self._record_answer('a1', exp_1, self.STATE_2_NAME) self._record_answer('a2', exp_1, self.STATE_2_NAME) self._run_aggregator_job() self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), { 'eid1': { 'frequency': 3, 'unresolved_answers': [{ 'frequency': 1, 'answer': 'a1', 'state': exp_1.init_state_name }, { 'frequency': 1, 'answer': 'a1', 'state': self.STATE_2_NAME }, { 'frequency': 1, 'answer': 'a2', 'state': self.STATE_2_NAME }] } })
def test_unresolved_answers_count_for_multiple_states(self): with self.swap( jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CC_MANAGERS_FOR_TESTS): exp_1 = self._create_and_update_fake_exploration('eid1') self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers(['eid1'])) self._record_answer('a1', exp_1, exp_1.init_state_name) self._record_answer('a1', exp_1, self.STATE_2_NAME) self._record_answer('a2', exp_1, self.STATE_2_NAME) self._run_aggregator_job() self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), { 'eid1': { 'frequency': 3, 'unresolved_answers': [{ 'frequency': 1, 'answer': 'a1', 'state': exp_1.init_state_name }, { 'frequency': 1, 'answer': 'a1', 'state': self.STATE_2_NAME }, { 'frequency': 1, 'answer': 'a2', 'state': self.STATE_2_NAME }] } })
def test_unresolved_answers_for_multiple_explorations(self): exp_1 = self._create_and_update_fake_exploration('eid1') exp_2 = self._create_and_update_fake_exploration('eid2') exp_3 = self._create_and_update_fake_exploration('eid3') self.assertEquals( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1', 'eid2', 'eid3']), self._get_default_dict_when_no_unresolved_answers( ['eid1', 'eid2', 'eid3'])) event_services.AnswerSubmissionEventHandler.record( 'eid1', 1, exp_1.init_state_name, self.DEFAULT_RULESPEC_STR, 'a1') event_services.AnswerSubmissionEventHandler.record( 'eid2', 1, exp_2.init_state_name, self.DEFAULT_RULESPEC_STR, 'a3') event_services.AnswerSubmissionEventHandler.record( 'eid2', 1, exp_2.init_state_name, self.DEFAULT_RULESPEC_STR, 'a2') event_services.AnswerSubmissionEventHandler.record( 'eid3', 1, exp_3.init_state_name, self.DEFAULT_RULESPEC_STR, 'a2') self.assertEquals( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1', 'eid2', 'eid3']), { 'eid1': {'count': 1, 'unresolved_answers': [ {'count': 1, 'value': 'a1', 'state': exp_1.init_state_name} ]}, 'eid2': {'count': 2, 'unresolved_answers': [ {'count': 1, 'value': 'a3', 'state': exp_2.init_state_name}, {'count': 1, 'value': 'a2', 'state': exp_2.init_state_name} ]}, 'eid3': {'count': 1, 'unresolved_answers': [ {'count': 1, 'value': 'a2', 'state': exp_3.init_state_name} ]} })
def test_unresolved_answers_count_for_non_default_rules(self): exp_1 = self._create_and_update_fake_exploration('eid1') self.assertEquals( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers( ['eid1'])) event_services.AnswerSubmissionEventHandler.record( 'eid1', 1, exp_1.init_state_name, self.CLASSIFIER_RULESPEC_STR, 'a1' ) event_services.AnswerSubmissionEventHandler.record( 'eid1', 1, self.STATE_2_NAME, self.CLASSIFIER_RULESPEC_STR, 'a1') self.assertEquals( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers( ['eid1']))
def test_unresolved_answers_count_for_non_default_rules(self): with self.swap( jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CC_MANAGERS_FOR_TESTS): exp_1 = self._create_and_update_fake_exploration('eid1') self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers(['eid1'])) self._record_answer( 'a1', exp_1, exp_1.init_state_name, classification=exp_domain.STATISTICAL_CLASSIFICATION) self._record_answer( 'a1', exp_1, self.STATE_2_NAME, classification=exp_domain.STATISTICAL_CLASSIFICATION) self._run_aggregator_job() self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers(['eid1']))
def test_unresolved_answers_count_for_non_default_rules(self): with self.swap(jobs_registry, 'ALL_CONTINUOUS_COMPUTATION_MANAGERS', self.ALL_CC_MANAGERS_FOR_TESTS): exp_1 = self._create_and_update_fake_exploration('eid1') self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers(['eid1'])) self._record_answer( 'a1', exp_1, exp_1.init_state_name, classification=exp_domain.STATISTICAL_CLASSIFICATION) self._record_answer( 'a1', exp_1, self.STATE_2_NAME, classification=exp_domain.STATISTICAL_CLASSIFICATION) self._run_aggregator_job() self.assertEqual( stats_services.get_exps_unresolved_answers_for_default_rule( ['eid1']), self._get_default_dict_when_no_unresolved_answers(['eid1']))
def get(self): """Handles GET requests.""" if self.user_id is None: raise self.PageNotFoundException def _get_intro_card_color(category): return ( feconf.CATEGORIES_TO_COLORS[category] if category in feconf.CATEGORIES_TO_COLORS else feconf.DEFAULT_COLOR) def _round_average_ratings(rating): return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION) exploration_ids_subscribed_to = ( subscription_services.get_exploration_ids_subscribed_to( self.user_id)) subscribed_exploration_summaries = filter(None, ( exp_services.get_exploration_summaries_matching_ids( exploration_ids_subscribed_to))) subscribed_collection_summaries = filter(None, ( collection_services.get_collection_summaries_matching_ids( subscription_services.get_collection_ids_subscribed_to( self.user_id)))) exp_summary_list = summary_services.get_displayable_exp_summary_dicts( subscribed_exploration_summaries) collection_summary_list = [] feedback_thread_analytics = ( feedback_services.get_thread_analytics_multi( exploration_ids_subscribed_to)) unresolved_answers_dict = ( stats_services.get_exps_unresolved_answers_for_default_rule( exploration_ids_subscribed_to)) total_unresolved_answers = 0 for ind, exploration in enumerate(exp_summary_list): exploration.update(feedback_thread_analytics[ind].to_dict()) exploration.update({ 'num_unresolved_answers': ( unresolved_answers_dict[exploration['id']]['count'] if exploration['id'] in unresolved_answers_dict else 0 ), 'top_unresolved_answers': ( unresolved_answers_dict[exploration['id']] ['unresolved_answers'] [:feconf.TOP_UNRESOLVED_ANSWERS_COUNT_DASHBOARD] ) }) total_unresolved_answers += exploration['num_unresolved_answers'] exp_summary_list = sorted( exp_summary_list, key=lambda x: (x['num_open_threads'], x['last_updated_msec']), reverse=True) if (self.username in config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value): for collection_summary in subscribed_collection_summaries: # TODO(sll): Reuse _get_displayable_collection_summary_dicts() # in summary_services, instead of replicating it like this. collection_summary_list.append({ 'id': collection_summary.id, 'title': collection_summary.title, 'category': collection_summary.category, 'objective': collection_summary.objective, 'language_code': collection_summary.language_code, 'last_updated': utils.get_time_in_millisecs( collection_summary.collection_model_last_updated), 'created_on': utils.get_time_in_millisecs( collection_summary.collection_model_created_on), 'status': collection_summary.status, 'node_count': collection_summary.node_count, 'community_owned': collection_summary.community_owned, 'thumbnail_icon_url': ( utils.get_thumbnail_icon_url_for_category( collection_summary.category)), 'thumbnail_bg_color': utils.get_hex_color_for_category( collection_summary.category), }) dashboard_stats = ( user_jobs_continuous.UserStatsAggregator.get_dashboard_stats( self.user_id)) dashboard_stats.update({ 'total_open_feedback': feedback_services.get_total_open_threads( feedback_thread_analytics), 'total_unresolved_answers': total_unresolved_answers }) if dashboard_stats and dashboard_stats.get('average_ratings'): dashboard_stats['average_ratings'] = ( _round_average_ratings(dashboard_stats['average_ratings'])) last_week_stats = ( user_services.get_last_week_dashboard_stats(self.user_id)) if last_week_stats and last_week_stats.get('average_ratings'): last_week_stats['average_ratings'] = ( _round_average_ratings(last_week_stats['average_ratings'])) self.values.update({ 'explorations_list': exp_summary_list, 'collections_list': collection_summary_list, 'dashboard_stats': dashboard_stats, 'last_week_stats': last_week_stats }) self.render_json(self.values)
def get(self): """Handles GET requests.""" if self.user_id is None: raise self.PageNotFoundException def _get_intro_card_color(category): return (feconf.CATEGORIES_TO_COLORS[category] if category in feconf.CATEGORIES_TO_COLORS else feconf.DEFAULT_COLOR) def _round_average_ratings(rating): return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION) exploration_ids_subscribed_to = ( subscription_services.get_exploration_ids_subscribed_to( self.user_id)) subscribed_exploration_summaries = filter( None, (exp_services.get_exploration_summaries_matching_ids( exploration_ids_subscribed_to))) subscribed_collection_summaries = filter( None, (collection_services.get_collection_summaries_matching_ids( subscription_services.get_collection_ids_subscribed_to( self.user_id)))) exp_summary_list = summary_services.get_displayable_exp_summary_dicts( subscribed_exploration_summaries) collection_summary_list = [] feedback_thread_analytics = ( feedback_services.get_thread_analytics_multi( exploration_ids_subscribed_to)) unresolved_answers_dict = ( stats_services.get_exps_unresolved_answers_for_default_rule( exploration_ids_subscribed_to)) total_unresolved_answers = 0 for ind, exploration in enumerate(exp_summary_list): exploration.update(feedback_thread_analytics[ind].to_dict()) exploration.update({ 'num_unresolved_answers': (unresolved_answers_dict[exploration['id']]['count'] if exploration['id'] in unresolved_answers_dict else 0), 'top_unresolved_answers': (unresolved_answers_dict[ exploration['id']]['unresolved_answers'] [:feconf.TOP_UNRESOLVED_ANSWERS_COUNT_DASHBOARD]) }) total_unresolved_answers += exploration['num_unresolved_answers'] exp_summary_list = sorted( exp_summary_list, key=lambda x: (x['num_open_threads'], x['last_updated_msec']), reverse=True) if (self.username in config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value): for collection_summary in subscribed_collection_summaries: # TODO(sll): Reuse _get_displayable_collection_summary_dicts() # in summary_services, instead of replicating it like this. collection_summary_list.append({ 'id': collection_summary.id, 'title': collection_summary.title, 'category': collection_summary.category, 'objective': collection_summary.objective, 'language_code': collection_summary.language_code, 'last_updated': utils.get_time_in_millisecs( collection_summary.collection_model_last_updated), 'created_on': utils.get_time_in_millisecs( collection_summary.collection_model_created_on), 'status': collection_summary.status, 'node_count': collection_summary.node_count, 'community_owned': collection_summary.community_owned, 'thumbnail_icon_url': (utils.get_thumbnail_icon_url_for_category( collection_summary.category)), 'thumbnail_bg_color': utils.get_hex_color_for_category( collection_summary.category), }) dashboard_stats = ( user_jobs_continuous.UserStatsAggregator.get_dashboard_stats( self.user_id)) dashboard_stats.update({ 'total_open_feedback': feedback_services.get_total_open_threads( feedback_thread_analytics), 'total_unresolved_answers': total_unresolved_answers }) if dashboard_stats and dashboard_stats.get('average_ratings'): dashboard_stats['average_ratings'] = (_round_average_ratings( dashboard_stats['average_ratings'])) last_week_stats = (user_services.get_last_week_dashboard_stats( self.user_id)) if last_week_stats and last_week_stats.get('average_ratings'): last_week_stats['average_ratings'] = (_round_average_ratings( last_week_stats['average_ratings'])) self.values.update({ 'explorations_list': exp_summary_list, 'collections_list': collection_summary_list, 'dashboard_stats': dashboard_stats, 'last_week_stats': last_week_stats }) self.render_json(self.values)