def test_fetch_multiple_entities_by_ids_and_models(self):

        # Save a few explorations.
        self.save_new_valid_exploration(self.EXP_ID_0,
                                        self.owner_id,
                                        title='Bridges in England',
                                        category='Architecture',
                                        language_code='en')
        self.save_new_valid_exploration(self.EXP_ID_1,
                                        self.owner_id,
                                        title='Sillat Suomi',
                                        category='Architecture',
                                        language_code='fi')

        # Save a few collections.
        self.save_new_default_collection(self.COL_ID_0,
                                         self.owner_id,
                                         title='Bridges',
                                         category='Architecture')
        self.save_new_default_collection(self.COL_ID_1,
                                         self.owner_id,
                                         title='Introduce Oppia',
                                         category='Welcome')

        # Fetch the summaries of the collections and explorations.
        summary_models = (
            gae_datastore_services.fetch_multiple_entities_by_ids_and_models([
                ('ExpSummaryModel', [self.EXP_ID_0, self.EXP_ID_1]),
                ('CollectionSummaryModel', [self.COL_ID_0, self.COL_ID_1])
            ]))

        exploration_summary_models = summary_models[0]
        collection_summary_models = summary_models[1]

        exploration_summaries = ([
            exp_fetchers.get_exploration_summary_from_model(model)
            if model else None for model in exploration_summary_models
        ])
        collection_summaries = ([
            collection_services.get_collection_summary_from_model(model)
            if model else None for model in collection_summary_models
        ])

        # Check that we have received the summaries of multiple entities of
        # different types correctly.
        self.assertEqual(exploration_summaries[0].title, 'Bridges in England')
        self.assertEqual(exploration_summaries[1].title, 'Sillat Suomi')
        self.assertEqual(collection_summaries[0].title, 'Bridges')
        self.assertEqual(collection_summaries[1].title, 'Introduce Oppia')
def get_activity_progress(user_id):
    """Returns the progress of the learners - the explorations and collections
    completed by the user and those in progress.

    Args:
        user_id: str. The id of the learner.

    Returns:
        (LearnerProgress, dict, list(str)). The first return value is the
            learner progress domain object corresponding to the particular
            learner. The second return value is the numbers of the activities
            that are no longer present. It contains four keys:
            - incomplete_explorations: int. The number of incomplete
                explorations no longer present.
            - incomplete_collections: int. The number of incomplete collections
                no longer present.
            - completed_explorations: int. The number of completed explorations
                no longer present.
            - completed_collections: int. The number of completed collections no
                longer present.
            The third return value is the titles of the collections to which new
            explorations have been added.
    """
    activity_ids_in_learner_dashboard = (
        get_learner_dashboard_activities(user_id))
    completed_exploration_ids = (
        activity_ids_in_learner_dashboard.completed_exploration_ids)
    completed_collection_ids = (
        activity_ids_in_learner_dashboard.completed_collection_ids)
    incomplete_exploration_ids = (
        activity_ids_in_learner_dashboard.incomplete_exploration_ids)
    incomplete_collection_ids = (
        activity_ids_in_learner_dashboard.incomplete_collection_ids)
    exploration_playlist_ids = (
        activity_ids_in_learner_dashboard.exploration_playlist_ids)
    collection_playlist_ids = (
        activity_ids_in_learner_dashboard.collection_playlist_ids)

    activity_models = (
        datastore_services.fetch_multiple_entities_by_ids_and_models([
            ('ExpSummaryModel', incomplete_exploration_ids),
            ('CollectionSummaryModel', incomplete_collection_ids),
            ('ExpSummaryModel', completed_exploration_ids),
            ('CollectionSummaryModel', completed_collection_ids),
            ('ExpSummaryModel', exploration_playlist_ids),
            ('CollectionSummaryModel', collection_playlist_ids)
        ]))

    incomplete_exploration_models = activity_models[0]
    incomplete_collection_models = activity_models[1]
    completed_exploration_models = activity_models[2]
    completed_collection_models = activity_models[3]
    exploration_playlist_models = activity_models[4]
    collection_playlist_models = activity_models[5]

    incomplete_exp_summaries = ([
        exp_services.get_exploration_summary_from_model(model)
        if model else None for model in incomplete_exploration_models
    ])
    incomplete_collection_summaries = ([
        collection_services.get_collection_summary_from_model(model)
        if model else None for model in incomplete_collection_models
    ])
    completed_exp_summaries = ([
        exp_services.get_exploration_summary_from_model(model)
        if model else None for model in completed_exploration_models
    ])
    completed_collection_summaries = ([
        collection_services.get_collection_summary_from_model(model)
        if model else None for model in completed_collection_models
    ])
    exploration_playlist_summaries = ([
        exp_services.get_exploration_summary_from_model(model)
        if model else None for model in exploration_playlist_models
    ])
    collection_playlist_summaries = ([
        collection_services.get_collection_summary_from_model(model)
        if model else None for model in collection_playlist_models
    ])

    filtered_incomplete_exp_summaries, nonexistent_incomplete_exp_ids = (
        _get_filtered_incomplete_exp_summaries(incomplete_exp_summaries,
                                               incomplete_exploration_ids))

    filtered_completed_exp_summaries, nonexistent_completed_exp_ids = (
        _get_filtered_completed_exp_summaries(completed_exp_summaries,
                                              completed_exploration_ids))

    (filtered_completed_collection_summaries,
     nonexistent_completed_collection_ids,
     completed_to_incomplete_collection_summaries) = (
         _get_filtered_completed_collection_summaries(
             user_id, completed_collection_summaries,
             completed_collection_ids))

    completed_to_incomplete_collection_titles = []
    for collection_summary in completed_to_incomplete_collection_summaries:
        incomplete_collection_summaries.append(collection_summary)
        completed_to_incomplete_collection_titles.append(
            collection_summary.title)
        incomplete_collection_ids.append(collection_summary.id)

    (filtered_incomplete_collection_summaries,
     nonexistent_incomplete_collection_ids) = (
         _get_filtered_incomplete_collection_summaries(
             incomplete_collection_summaries, incomplete_collection_ids))

    filtered_exp_playlist_summaries, nonexistent_playlist_exp_ids = (
        _get_filtered_exp_playlist_summaries(exploration_playlist_summaries,
                                             exploration_playlist_ids))

    (filtered_collection_playlist_summaries,
     nonexistent_playlist_collection_ids) = (
         _get_filtered_collection_playlist_summaries(
             collection_playlist_summaries, collection_playlist_ids))

    number_of_deleted_activities = {
        'incomplete_explorations': len(nonexistent_incomplete_exp_ids),
        'incomplete_collections': len(nonexistent_incomplete_collection_ids),
        'completed_explorations': len(nonexistent_completed_exp_ids),
        'completed_collections': len(nonexistent_completed_collection_ids),
        'exploration_playlist': len(nonexistent_playlist_exp_ids),
        'collection_playlist': len(nonexistent_playlist_collection_ids)
    }

    _remove_activity_ids_from_incomplete_list(
        user_id, nonexistent_incomplete_exp_ids,
        nonexistent_incomplete_collection_ids)
    _remove_activity_ids_from_completed_list(
        user_id, nonexistent_completed_exp_ids,
        nonexistent_completed_collection_ids)
    _remove_activity_ids_from_playlist(user_id, nonexistent_playlist_exp_ids,
                                       nonexistent_playlist_collection_ids)

    learner_progress = learner_progress_domain.LearnerProgress(
        filtered_incomplete_exp_summaries,
        filtered_incomplete_collection_summaries,
        filtered_completed_exp_summaries,
        filtered_completed_collection_summaries,
        filtered_exp_playlist_summaries,
        filtered_collection_playlist_summaries)

    return (learner_progress, number_of_deleted_activities,
            completed_to_incomplete_collection_titles)
 def _get_model_domain_object_instance(cls, item):
     return collection_services.get_collection_summary_from_model(item)