Ejemplo n.º 1
0
    def test_get_weekly_dashboard_stats(self):
        exploration = self.save_new_valid_exploration(self.EXP_ID,
                                                      self.owner_id,
                                                      end_state_name='End')
        init_state_name = exploration.init_state_name
        event_services.StartExplorationEventHandler.record(
            self.EXP_ID, 1, init_state_name, self.USER_SESSION_ID, {},
            feconf.PLAY_TYPE_NORMAL)
        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         start_computation())
        self.process_and_flush_pending_tasks()

        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services, 'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            user_services.update_dashboard_stats_log(self.owner_id)

        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), [{
                self.CURRENT_DATE_AS_STRING: {
                    'total_plays': 1,
                    'num_ratings': 0,
                    'average_ratings': None
                }
            }])
Ejemplo n.º 2
0
    def test_weekly_stats_if_continuous_stats_job_has_not_been_run(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID_1, self.owner_id)
        exp_id = exploration.id
        init_state_name = exploration.init_state_name
        self._record_play(exp_id, init_state_name)
        self._rate_exploration('user1', exp_id, 5)

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services,
                       'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            self._run_one_off_job()

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        expected_results_list = [{
            self._mock_get_current_date_as_string(): {
                'num_ratings': 0,
                'average_ratings': None,
                'total_plays': 0
            }
        }]
        self.assertEqual(weekly_stats, expected_results_list)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id),
            expected_results_list[0])
Ejemplo n.º 3
0
    def test_weekly_stats_if_continuous_stats_job_has_not_been_run(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID_1, self.owner_id)
        exp_id = exploration.id
        init_state_name = exploration.init_state_name
        self._record_play(exp_id, init_state_name)
        self._rate_exploration('user1', exp_id, 5)

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services,
                       'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            self._run_one_off_job()

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        expected_results_list = [{
            self._mock_get_current_date_as_string(): {
                'num_ratings': 0,
                'average_ratings': None,
                'total_plays': 0
            }
        }]
        self.assertEqual(weekly_stats, expected_results_list)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id),
            expected_results_list[0])
Ejemplo n.º 4
0
    def test_get_weekly_dashboard_stats(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID, self.owner_id, end_state_name='End')
        init_state_name = exploration.init_state_name
        event_services.StartExplorationEventHandler.record(
            self.EXP_ID, 1, init_state_name, self.USER_SESSION_ID, {},
            feconf.PLAY_TYPE_NORMAL)
        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        (user_jobs_continuous_test.ModifiedUserStatsAggregator
         .start_computation())
        self.process_and_flush_pending_tasks()

        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services,
                       'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            user_services.update_dashboard_stats_log(self.owner_id)

        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), [{
                self.CURRENT_DATE_AS_STRING: {
                    'total_plays': 1,
                    'num_ratings': 0,
                    'average_ratings': None
                }
            }])
Ejemplo n.º 5
0
    def test_weekly_stats(self):
        exploration = self.save_new_valid_exploration(self.EXP_ID_1,
                                                      self.owner_id)
        exp_id = exploration.id
        init_state_name = exploration.init_state_name
        self._record_play(exp_id, init_state_name)
        self._rate_exploration('user1', exp_id, 5)

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, None)
        self.assertEqual(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services, 'get_current_date_as_string',
                       self.mock_get_current_date_as_string):
            self._run_one_off_job()

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, [{
            self.mock_get_current_date_as_string(): {
                'num_ratings': 1,
                'average_ratings': 5.0,
                'total_plays': 1
            }
        }])
        self.assertEqual(
            user_services.get_last_week_dashboard_stats(self.owner_id), {
                self.mock_get_current_date_as_string(): {
                    'num_ratings': 1,
                    'average_ratings': 5.0,
                    'total_plays': 1
                }
            })
Ejemplo n.º 6
0
    def test_get_weekly_dashboard_stats_when_stats_model_is_none(self):
        exploration = self.save_new_valid_exploration(self.EXP_ID,
                                                      self.owner_id,
                                                      end_state_name='End')
        init_state_name = exploration.init_state_name
        event_services.StartExplorationEventHandler.record(
            self.EXP_ID, 1, init_state_name, self.USER_SESSION_ID, {},
            feconf.PLAY_TYPE_NORMAL)
        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services, 'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            user_services.update_dashboard_stats_log(self.owner_id)

        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), [{
                self.CURRENT_DATE_AS_STRING: {
                    'total_plays': 0,
                    'num_ratings': 0,
                    'average_ratings': None
                }
            }])
Ejemplo n.º 7
0
    def test_get_weekly_dashboard_stats_when_stats_model_is_none(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID, self.owner_id, end_state_name='End')
        init_state_name = exploration.init_state_name
        event_services.StartExplorationEventHandler.record(
            self.EXP_ID, 1, init_state_name, self.USER_SESSION_ID, {},
            feconf.PLAY_TYPE_NORMAL)
        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), None)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id), None)

        with self.swap(user_services,
                       'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            user_services.update_dashboard_stats_log(self.owner_id)

        self.assertEquals(
            user_services.get_weekly_dashboard_stats(self.owner_id), [{
                self.CURRENT_DATE_AS_STRING: {
                    'total_plays': 0,
                    'num_ratings': 0,
                    'average_ratings': None
                }
            }])
Ejemplo n.º 8
0
    def test_stats_for_multiple_weeks(self):
        exploration = self.save_new_valid_exploration(self.EXP_ID_1,
                                                      self.owner_id)
        exp_id = exploration.id
        init_state_name = exploration.init_state_name
        self._rate_exploration('user1', exp_id, 4)
        self._record_play(exp_id, init_state_name)
        self._record_play(exp_id, init_state_name)
        event_services.StatsEventsHandler.record(
            self.EXP_ID_1, 1, {
                'num_starts': 2,
                'num_actual_starts': 0,
                'num_completions': 0,
                'state_stats_mapping': {}
            })

        self.process_and_flush_pending_tasks()

        with self.swap(user_services, 'get_current_date_as_string',
                       self.mock_get_current_date_as_string):
            self._run_one_off_job()

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, [{
            self.mock_get_current_date_as_string(): {
                'num_ratings': 1,
                'average_ratings': 4.0,
                'total_plays': 2
            }
        }])

        self._rate_exploration('user2', exp_id, 2)

        def _mock_get_date_after_one_week():
            """Returns the date of the next week."""
            return self.DATE_AFTER_ONE_WEEK

        with self.swap(user_services, 'get_current_date_as_string',
                       _mock_get_date_after_one_week):
            self._run_one_off_job()

        expected_results_list = [{
            self.mock_get_current_date_as_string(): {
                'num_ratings': 1,
                'average_ratings': 4.0,
                'total_plays': 2
            }
        }, {
            _mock_get_date_after_one_week(): {
                'num_ratings': 2,
                'average_ratings': 3.0,
                'total_plays': 2
            }
        }]
        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, expected_results_list)
        self.assertEqual(
            user_services.get_last_week_dashboard_stats(self.owner_id),
            expected_results_list[1])
Ejemplo n.º 9
0
    def get(self):
        """Handles GET requests."""
        def _round_average_ratings(rating):
            """Returns the rounded average rating to display on the creator
            dashboard.

            Args:
                rating: float. The rating of the lesson.

            Returns:
                float. The rounded average value of rating.
            """
            return python_utils.ROUND(
                rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        subscribed_exploration_summaries = (
            exp_fetchers.get_exploration_summaries_subscribed_to(self.user_id))
        subscribed_collection_summaries = (
            collection_services.get_collection_summaries_subscribed_to(
                self.user_id))

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries
        ]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            topic_summaries = topic_services.get_all_topic_summaries()
            topic_summary_dicts = [
                summary.to_dict() for summary in topic_summaries
            ]

        if role_services.ACTION_CREATE_COLLECTION in self.user.actions:
            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_dicts.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_msec':
                    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)
        })
        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 len(list(last_week_stats.keys())) != 1:
            logging.error(
                '\'last_week_stats\' should contain only one key-value pair'
                ' denoting last week dashboard stats of the user keyed by a'
                ' datetime string.')
            last_week_stats = None

        if last_week_stats:
            # 'last_week_stats' is a dict with only one key-value pair denoting
            # last week dashboard stats of the user keyed by a datetime string.
            datetime_of_stats = list(last_week_stats.keys())[0]
            last_week_stats_average_ratings = (list(
                last_week_stats.values())[0].get('average_ratings'))
            if last_week_stats_average_ratings:
                last_week_stats[datetime_of_stats]['average_ratings'] = (
                    _round_average_ratings(last_week_stats_average_ratings))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url':
                (subscriber_settings.profile_picture_data_url),
                'subscriber_username':
                subscriber_settings.username,
                'subscriber_impact':
                (user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        user_settings = user_services.get_user_settings(self.user_id,
                                                        strict=False)
        creator_dashboard_display_pref = (
            user_settings.creator_dashboard_display_pref)

        suggestions_created_by_user = suggestion_services.query_suggestions([
            ('author_id', self.user_id),
            ('suggestion_type',
             suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT)
        ])
        suggestions_which_can_be_reviewed = (
            suggestion_services.
            get_all_suggestions_that_can_be_reviewed_by_user(self.user_id))

        for s in suggestions_created_by_user:
            s.populate_old_value_of_change()

        for s in suggestions_which_can_be_reviewed:
            s.populate_old_value_of_change()

        suggestion_dicts_created_by_user = ([
            s.to_dict() for s in suggestions_created_by_user
        ])
        suggestion_dicts_which_can_be_reviewed = ([
            s.to_dict() for s in suggestions_which_can_be_reviewed
        ])

        ids_of_suggestions_created_by_user = ([
            s['suggestion_id'] for s in suggestion_dicts_created_by_user
        ])
        ids_of_suggestions_which_can_be_reviewed = ([
            s['suggestion_id'] for s in suggestion_dicts_which_can_be_reviewed
        ])

        threads_linked_to_suggestions_by_user = ([
            t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_created_by_user)
        ])
        threads_linked_to_suggestions_which_can_be_reviewed = ([
            t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_which_can_be_reviewed)
        ])

        self.values.update({
            'explorations_list':
            exp_summary_dicts,
            'collections_list':
            collection_summary_dicts,
            'dashboard_stats':
            dashboard_stats,
            'last_week_stats':
            last_week_stats,
            'subscribers_list':
            subscribers_list,
            'display_preference':
            creator_dashboard_display_pref,
            'threads_for_created_suggestions_list':
            (threads_linked_to_suggestions_by_user),
            'threads_for_suggestions_to_review_list':
            (threads_linked_to_suggestions_which_can_be_reviewed),
            'created_suggestions_list':
            suggestion_dicts_created_by_user,
            'suggestions_to_review_list':
            suggestion_dicts_which_can_be_reviewed
        })
        if constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            self.values.update({'topic_summary_dicts': topic_summary_dicts})
        self.render_json(self.values)
Ejemplo n.º 10
0
    def test_stats_for_multiple_weeks(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID_1, self.owner_id)
        exp_id = exploration.id
        init_state_name = exploration.init_state_name
        self._rate_exploration('user1', exp_id, 4)
        self._record_play(exp_id, init_state_name)
        self._record_play(exp_id, init_state_name)

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         start_computation())
        self.process_and_flush_pending_tasks()

        with self.swap(user_services,
                       'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            self._run_one_off_job()

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, [{
            self._mock_get_current_date_as_string(): {
                'num_ratings': 1,
                'average_ratings': 4.0,
                'total_plays': 2
            }
        }])

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         stop_computation(self.owner_id))
        self.process_and_flush_pending_tasks()

        self._rate_exploration('user2', exp_id, 2)

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         start_computation())
        self.process_and_flush_pending_tasks()

        def _mock_get_date_after_one_week():
            """Returns the date of the next week."""
            return self.DATE_AFTER_ONE_WEEK

        with self.swap(user_services,
                       'get_current_date_as_string',
                       _mock_get_date_after_one_week):
            self._run_one_off_job()

        expected_results_list = [
            {
                self._mock_get_current_date_as_string(): {
                    'num_ratings': 1,
                    'average_ratings': 4.0,
                    'total_plays': 2
                }
            },
            {
                _mock_get_date_after_one_week(): {
                    'num_ratings': 2,
                    'average_ratings': 3.0,
                    'total_plays': 2
                }
            }
        ]
        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, expected_results_list)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id),
            expected_results_list[1])
Ejemplo n.º 11
0
    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)

        # We need to do the filtering because some activities that were
        # originally subscribed to may have been deleted since.
        subscribed_exploration_summaries = [
            summary for summary in
            exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id))
            if summary is not None]
        subscribed_collection_summaries = [
            summary for summary in
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id))
            if summary is not None]

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            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_dicts.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)
        })
        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']))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url': (
                    subscriber_settings.profile_picture_data_url),
                'subscriber_username': subscriber_settings.username,
                'subscriber_impact': (
                    user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        self.values.update({
            'explorations_list': exp_summary_dicts,
            'collections_list': collection_summary_dicts,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats,
            'subscribers_list': subscribers_list
        })
        self.render_json(self.values)
Ejemplo n.º 12
0
    def get(self):
        """Handles GET requests."""

        def _get_intro_card_color(category):
            return (
                constants.CATEGORIES_TO_COLORS[category] if
                category in constants.CATEGORIES_TO_COLORS else
                constants.DEFAULT_COLOR)

        def _round_average_ratings(rating):
            return round(rating, feconf.AVERAGE_RATINGS_DASHBOARD_PRECISION)

        # We need to do the filtering because some activities that were
        # originally subscribed to may have been deleted since.
        subscribed_exploration_summaries = [
            summary for summary in
            exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id))
            if summary is not None]
        subscribed_collection_summaries = [
            summary for summary in
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id))
            if summary is not None]

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            key=lambda x: (x['num_open_threads'], x['last_updated_msec']),
            reverse=True)

        if constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            topic_summaries = topic_services.get_all_topic_summaries()
            topic_summary_dicts = [
                summary.to_dict() for summary in topic_summaries]

        if role_services.ACTION_CREATE_COLLECTION in self.user.actions:
            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_dicts.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)
        })
        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']))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url': (
                    subscriber_settings.profile_picture_data_url),
                'subscriber_username': subscriber_settings.username,
                'subscriber_impact': (
                    user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        user_settings = user_services.get_user_settings(
            self.user_id, strict=False)
        creator_dashboard_display_pref = (
            user_settings.creator_dashboard_display_pref)

        suggestions_created_by_user = suggestion_services.query_suggestions(
            [('author_id', self.user_id),
             (
                 'suggestion_type',
                 suggestion_models.SUGGESTION_TYPE_EDIT_STATE_CONTENT)])
        suggestions_which_can_be_reviewed = (
            suggestion_services
            .get_all_suggestions_that_can_be_reviewed_by_user(self.user_id))

        for s in suggestions_created_by_user:
            s.populate_old_value_of_change()

        for s in suggestions_which_can_be_reviewed:
            s.populate_old_value_of_change()

        suggestion_dicts_created_by_user = (
            [s.to_dict() for s in suggestions_created_by_user])
        suggestion_dicts_which_can_be_reviewed = (
            [s.to_dict() for s in suggestions_which_can_be_reviewed])

        ids_of_suggestions_created_by_user = (
            [s['suggestion_id'] for s in suggestion_dicts_created_by_user])
        ids_of_suggestions_which_can_be_reviewed = (
            [s['suggestion_id']
             for s in suggestion_dicts_which_can_be_reviewed])

        threads_linked_to_suggestions_by_user = (
            [t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_created_by_user)])
        threads_linked_to_suggestions_which_can_be_reviewed = (
            [t.to_dict() for t in feedback_services.get_multiple_threads(
                ids_of_suggestions_which_can_be_reviewed)])

        self.values.update({
            'explorations_list': exp_summary_dicts,
            'collections_list': collection_summary_dicts,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats,
            'subscribers_list': subscribers_list,
            'display_preference': creator_dashboard_display_pref,
            'threads_for_created_suggestions_list': (
                threads_linked_to_suggestions_by_user),
            'threads_for_suggestions_to_review_list': (
                threads_linked_to_suggestions_which_can_be_reviewed),
            'created_suggestions_list': suggestion_dicts_created_by_user,
            'suggestions_to_review_list': suggestion_dicts_which_can_be_reviewed
        })
        if constants.ENABLE_NEW_STRUCTURE_PLAYERS:
            self.values.update({
                'topic_summary_dicts': topic_summary_dicts
            })
        self.render_json(self.values)
Ejemplo n.º 13
0
    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_count_for_default_rule(
                exploration_ids_subscribed_to))

        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']]
                    if exploration['id'] in unresolved_answers_dict else 0
                )
            })

        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,
                    '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)
        })
        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)
Ejemplo n.º 14
0
    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)

        # We need to do the filtering because some activities that were
        # originally subscribed to may have been deleted since.
        subscribed_exploration_summaries = [
            summary
            for summary in exp_services.get_exploration_summaries_matching_ids(
                subscription_services.get_exploration_ids_subscribed_to(
                    self.user_id)) if summary is not None
        ]
        subscribed_collection_summaries = [
            summary for summary in
            collection_services.get_collection_summaries_matching_ids(
                subscription_services.get_collection_ids_subscribed_to(
                    self.user_id)) if summary is not None
        ]

        exploration_ids_subscribed_to = [
            summary.id for summary in subscribed_exploration_summaries
        ]

        exp_summary_dicts = summary_services.get_displayable_exp_summary_dicts(
            subscribed_exploration_summaries)
        collection_summary_dicts = []

        feedback_thread_analytics = (
            feedback_services.get_thread_analytics_multi(
                exploration_ids_subscribed_to))

        # TODO(bhenning): Update this to use unresolved answers from
        # stats_services once the training interface is enabled and it's cheaper
        # to retrieve top answers from stats_services.
        for ind, exploration in enumerate(exp_summary_dicts):
            exploration.update(feedback_thread_analytics[ind].to_dict())

        exp_summary_dicts = sorted(
            exp_summary_dicts,
            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_dicts.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)
        })
        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']))

        subscriber_ids = subscription_services.get_all_subscribers_of_creator(
            self.user_id)
        subscribers_settings = user_services.get_users_settings(subscriber_ids)
        subscribers_list = []
        for index, subscriber_settings in enumerate(subscribers_settings):
            subscriber_summary = {
                'subscriber_picture_data_url':
                (subscriber_settings.profile_picture_data_url),
                'subscriber_username':
                subscriber_settings.username,
                'subscriber_impact':
                (user_services.get_user_impact_score(subscriber_ids[index]))
            }

            subscribers_list.append(subscriber_summary)

        self.values.update({
            'explorations_list': exp_summary_dicts,
            'collections_list': collection_summary_dicts,
            'dashboard_stats': dashboard_stats,
            'last_week_stats': last_week_stats,
            'subscribers_list': subscribers_list
        })
        self.render_json(self.values)
Ejemplo n.º 15
0
    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)
Ejemplo n.º 16
0
    def test_stats_for_multiple_weeks(self):
        exploration = self.save_new_valid_exploration(
            self.EXP_ID_1, self.owner_id)
        exp_id = exploration.id
        init_state_name = exploration.init_state_name
        self._rate_exploration('user1', exp_id, 4)
        self._record_play(exp_id, init_state_name)
        self._record_play(exp_id, init_state_name)

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         start_computation())
        self.process_and_flush_pending_tasks()

        with self.swap(user_services,
                       'get_current_date_as_string',
                       self._mock_get_current_date_as_string):
            self._run_one_off_job()

        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, [{
            self._mock_get_current_date_as_string(): {
                'num_ratings': 1,
                'average_ratings': 4.0,
                'total_plays': 2
            }
        }])

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         stop_computation(self.owner_id))
        self.process_and_flush_pending_tasks()

        self._rate_exploration('user2', exp_id, 2)

        (user_jobs_continuous_test.ModifiedUserStatsAggregator.
         start_computation())
        self.process_and_flush_pending_tasks()

        def _mock_get_date_after_one_week():
            """Returns the date of the next week."""
            return self.DATE_AFTER_ONE_WEEK

        with self.swap(user_services,
                       'get_current_date_as_string',
                       _mock_get_date_after_one_week):
            self._run_one_off_job()

        expected_results_list = [
            {
                self._mock_get_current_date_as_string(): {
                    'num_ratings': 1,
                    'average_ratings': 4.0,
                    'total_plays': 2
                }
            },
            {
                _mock_get_date_after_one_week(): {
                    'num_ratings': 2,
                    'average_ratings': 3.0,
                    'total_plays': 2
                }
            }
        ]
        weekly_stats = user_services.get_weekly_dashboard_stats(self.owner_id)
        self.assertEqual(weekly_stats, expected_results_list)
        self.assertEquals(
            user_services.get_last_week_dashboard_stats(self.owner_id),
            expected_results_list[1])