def test_nonhuman_committers_not_counted(self): """Test that only human committers are counted as contributors. """ # Create a commit with the system user id. exploration = self.save_new_valid_exploration( self.EXP_ID, feconf.SYSTEM_COMMITTER_ID, title='Original Title') # Run the job to compute the contributor ids. job_id = exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new() exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Check that the system id was not added to the exploration's # contributor ids. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertNotIn( feconf.SYSTEM_COMMITTER_ID, exploration_summary.contributor_ids) # Create a commit with the migration bot user id. exploration_model = exp_models.ExplorationModel.get( self.EXP_ID, strict=True, version=None) exploration_model.title = 'New title' exploration_model.commit( feconf.MIGRATION_BOT_USERNAME, 'Changed title.', []) # Run the job to compute the contributor ids. job_id = exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new() exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Check that the migration bot id was not added to the exploration's # contributor ids. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertNotIn( feconf.MIGRATION_BOT_USERNAME, exploration_summary.contributor_ids)
def test_nonhuman_committers_not_counted(self): """Test that only human committers are counted as contributors. """ # Create a commit with the system user id. exploration = self.save_new_valid_exploration( self.EXP_ID, feconf.SYSTEM_COMMITTER_ID, title='Original Title') # Run the job to compute the contributor ids. job_id = exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new() exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Check that the system id was not added to the exploration's # contributor ids. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertNotIn( feconf.SYSTEM_COMMITTER_ID, exploration_summary.contributor_ids) # Create a commit with the migration bot user id. exploration_model = exp_models.ExplorationModel.get( self.EXP_ID, strict=True, version=None) exploration_model.title = 'New title' exploration_model.commit( feconf.MIGRATION_BOT_USERNAME, 'Changed title.', []) # Run the job to compute the contributor ids. job_id = exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new() exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Check that the migration bot id was not added to the exploration's # contributor ids. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertNotIn( feconf.MIGRATION_BOT_USERNAME, exploration_summary.contributor_ids)
def test_search_ranks_cannot_be_negative(self): self.save_new_valid_exploration(self.EXP_ID, self.owner_id) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) base_search_rank = 20 self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), base_search_rank) # A user can (down-)rate an exploration at most once. for i in xrange(50): rating_services.assign_rating_to_exploration( 'user_id_1', self.EXP_ID, 1) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), base_search_rank - 5) for i in xrange(50): rating_services.assign_rating_to_exploration( 'user_id_%s' % i, self.EXP_ID, 1) # The rank will be at least 0. exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), 0)
def test_get_search_rank(self): self.save_new_valid_exploration(self.EXP_ID, self.owner_id) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) base_search_rank = 20 self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), base_search_rank) rights_manager.publish_exploration(self.owner, self.EXP_ID) self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), base_search_rank) rating_services.assign_rating_to_exploration(self.owner_id, self.EXP_ID, 5) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), base_search_rank + 10) rating_services.assign_rating_to_exploration(self.user_id_admin, self.EXP_ID, 2) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( search_services.get_search_rank_from_exp_summary(exp_summary), base_search_rank + 8)
def test_nonhuman_committers_not_counted(self): """Test that only human committers are counted as contributors. """ # Create a commit with the system user id. exploration = self.save_new_valid_exploration( self.EXP_ID, feconf.SYSTEM_COMMITTER_ID, title='Original Title') # Create commits with all the system user ids for system_id in feconf.SYSTEM_USER_IDS: exp_services.update_exploration( system_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'Title changed by %s' % system_id }], 'Changed title.') # Run the job to compute the contributor summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Check that no system id was added to the exploration's # contributor's summary exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) for system_id in feconf.SYSTEM_USER_IDS: self.assertNotIn( system_id, exploration_summary.contributors_summary)
def test_repeat_contributors(self): """Test that if the same user makes more than one commit that changes the content of an exploration, the user is only represented once in the list of contributors for that exploration. """ self.signup(self.EMAIL_A, self.USERNAME_A) user_a_id = self.get_user_id_from_email(self.EMAIL_A) # Have one user make two commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Original Title') exploration_model = exp_models.ExplorationModel.get( self.EXP_ID, strict=True, version=None) exploration_model.title = 'New title' exploration_model.commit( user_a_id, 'Changed title.', []) # Run the job to compute the contributor ids. job_id = ( exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Verify that the length of the contributor list is one, and that # the list contains the user who made these commits. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual( [user_a_id], exploration_summary.contributor_ids)
def test_repeat_contributors(self): """Test that if the same user makes more than one commit that changes the content of an exploration, the user is only represented once in the list of contributors for that exploration. """ self.signup(self.EMAIL_A, self.USERNAME_A) user_a_id = self.get_user_id_from_email(self.EMAIL_A) # Have one user make two commits. exploration = self.save_new_valid_exploration(self.EXP_ID, user_a_id, title='Original Title') exploration_model = exp_models.ExplorationModel.get(self.EXP_ID, strict=True, version=None) exploration_model.title = 'New title' exploration_model.commit(user_a_id, 'Changed title.', []) # Run the job to compute the contributor ids. job_id = ( exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Verify that the length of the contributor list is one, and that # the list contains the user who made these commits. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual([user_a_id], exploration_summary.contributor_ids)
def test_nonhuman_committers_not_counted(self): """Test that only human committers are counted as contributors.""" # Create a commit with the system user id. exploration = self.save_new_valid_exploration( self.EXP_ID, feconf.SYSTEM_COMMITTER_ID, title='Original Title') # Create commits with all the system user ids. for system_id in feconf.SYSTEM_USER_IDS: exp_services.update_exploration(system_id, self.EXP_ID, [ exp_domain.ExplorationChange( { 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'Title changed by %s' % system_id }) ], 'Changed title.') # Run the job to compute the contributor summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue( job_id) self.process_and_flush_pending_tasks() # Check that no system id was added to the exploration's # contributor's summary. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) for system_id in feconf.SYSTEM_USER_IDS: self.assertNotIn(system_id, exploration_summary.contributors_summary)
def test_contributors_with_only_reverts_not_counted(self): """Test that contributors who have only done reverts do not have their user id appear in the contributor list. """ # Sign up two users. self.signup(self.EMAIL_A, self.USERNAME_A) user_a_id = self.get_user_id_from_email(self.EMAIL_A) self.signup(self.EMAIL_B, self.USERNAME_B) user_b_id = self.get_user_id_from_email(self.EMAIL_B) # Have one user make two commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Original Title') change_list = [{ 'cmd': exp_domain.CMD_EDIT_EXPLORATION_PROPERTY, 'property_name': 'title', 'new_value': 'New title' }] exp_services.update_exploration( user_a_id, self.EXP_ID, change_list, 'Changed title.') # Have the second user revert version 2 to version 1 exp_services.revert_exploration(user_b_id, self.EXP_ID, 2, 1) # Run the job to compute the contributor ids. job_id = ( exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Verify that the committer list does not contain the user # who only reverted. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual([user_a_id], exploration_summary.contributor_ids)
def assign_rating_to_exploration(user_id, exploration_id, new_rating): """Records the rating awarded by the user to the exploration in both the user-specific data and exploration summary. This function validates the exploration id but not the user id. Args: user_id: str. The id of the user assigning the rating. exploration_id: str. The id of the exploration that is assigned a rating. new_rating: int. Value of assigned rating, should be between 1 and 5 inclusive. """ if not isinstance(new_rating, int): raise ValueError('Expected the rating to be an integer, received %s' % new_rating) if new_rating not in ALLOWED_RATINGS: raise ValueError('Expected a rating 1-5, received %s.' % new_rating) try: exp_services.get_exploration_by_id(exploration_id) except: raise Exception('Invalid exploration id %s' % exploration_id) def _update_user_rating(): """Updates the user rating of the exploration. Returns the old rating before updation. """ exp_user_data_model = user_models.ExplorationUserDataModel.get( user_id, exploration_id) if exp_user_data_model: old_rating = exp_user_data_model.rating else: old_rating = None exp_user_data_model = user_models.ExplorationUserDataModel.create( user_id, exploration_id) exp_user_data_model.rating = new_rating exp_user_data_model.rated_on = datetime.datetime.utcnow() exp_user_data_model.put() return old_rating old_rating = transaction_services.run_in_transaction(_update_user_rating) exploration_summary = exp_services.get_exploration_summary_by_id( exploration_id) if not exploration_summary.ratings: exploration_summary.ratings = feconf.get_empty_ratings() exploration_summary.ratings[str(new_rating)] += 1 if old_rating: exploration_summary.ratings[str(old_rating)] -= 1 event_services.RateExplorationEventHandler.record(exploration_id, user_id, new_rating, old_rating) exploration_summary.scaled_average_rating = ( exp_services.get_scaled_average_rating(exploration_summary.ratings)) exp_services.save_exploration_summary(exploration_summary)
def test_contributors_with_only_reverts_not_counted(self): """Test that contributors who have only done reverts do not have their user id appear in the contributor list. """ # Sign up two users. self.signup(self.EMAIL_A, self.USERNAME_A) user_a_id = self.get_user_id_from_email(self.EMAIL_A) self.signup(self.EMAIL_B, self.USERNAME_B) user_b_id = self.get_user_id_from_email(self.EMAIL_B) # Have one user make two commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Original Title') exploration_model = exp_models.ExplorationModel.get( self.EXP_ID, strict=True, version=None) exploration_model.title = 'New title' exploration_model.commit( user_a_id, 'Changed title.', []) # Have the second user revert version 2 to version 1 exp_services.revert_exploration(user_b_id, self.EXP_ID, 2, 1) # Run the job to compute the contributor ids. job_id = ( exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Verify that the committer list does not contain the user # who only reverted. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual([user_a_id], exploration_summary.contributor_ids)
def get_item_similarity(reference_exp_id, compared_exp_id): """Returns the ranking of compared_exp_id to reference_exp_id as a recommendation. This returns a value between 0.0 to 10.0. A higher value indicates the compared_exp is a better recommendation as an exploration to start after completing reference_exp. Comparison of similarity is based on the similarity of exploration topics, whether the explorations have the same language or author. The ranking of compared_exp is increased if it is publicized or is newly updated. It returns 0.0 if compared_exp is private.""" try: reference_exp_summary = exp_services.get_exploration_summary_by_id( reference_exp_id) except: raise Exception('Invalid reference_exp_id %s' % reference_exp_id) try: compared_exp_summary = exp_services.get_exploration_summary_by_id( compared_exp_id) except: raise Exception('Invalid compared_exp_id %s' % compared_exp_id) similarity_score = 0 if (compared_exp_summary.status == rights_manager.EXPLORATION_STATUS_PRIVATE): return 0 elif (compared_exp_summary.status == rights_manager.EXPLORATION_STATUS_PUBLICIZED): similarity_score += 1 similarity_score += get_topic_similarity( reference_exp_summary.category, compared_exp_summary.category) * 5 if reference_exp_summary.owner_ids == compared_exp_summary.owner_ids: similarity_score += 1 if (reference_exp_summary.language_code == compared_exp_summary.language_code): similarity_score += 2 time_now = datetime.datetime.utcnow() time_delta_days = int( (time_now - compared_exp_summary.exploration_model_last_updated).days) if time_delta_days <= 7: similarity_score += 1 return similarity_score
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration.""" exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0}) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( exp_summary.scaled_average_rating, 0) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating_to_exploration( self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertAlmostEqual( exp_summary.scaled_average_rating, 1.5667471839848, places=4) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 1, '4': 1, '5': 0}) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 2, '5': 0})
def map(item): if item.deleted: return summary = exp_services.get_exploration_summary_by_id(item.id) summary.contributors_summary = ( exp_services.compute_exploration_contributors_summary(item.id)) exp_services.save_exploration_summary(summary)
def map(item): if item.deleted: return summary = exp_services.get_exploration_summary_by_id(item.id) summary.contributors_summary = ( exp_services.compute_exploration_contributors_summary(item.id)) exp_services.save_exploration_summary(summary)
def test_rating_assignation(self): """Check ratings are correctly assigned to an exploration""" exp_services.save_new_exploration( self.EXP_ID, exp_domain.Exploration.create_default_exploration(self.EXP_ID)) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0}) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertEqual( exp_summary.scaled_average_rating, 0) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), None) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 2) rating_services.assign_rating_to_exploration( self.USER_ID_2, self.EXP_ID, 4) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 3) exp_summary = exp_services.get_exploration_summary_by_id(self.EXP_ID) self.assertAlmostEqual( exp_summary.scaled_average_rating, 1.5667471839848, places=4) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_1, self.EXP_ID), 3) self.assertEqual( rating_services.get_user_specific_rating_for_exploration( self.USER_ID_2, self.EXP_ID), 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 1, '4': 1, '5': 0}) rating_services.assign_rating_to_exploration( self.USER_ID_1, self.EXP_ID, 4) self.assertEqual( rating_services.get_overall_ratings_for_exploration(self.EXP_ID), {'1': 0, '2': 0, '3': 0, '4': 2, '5': 0})
def assign_rating_to_exploration(user_id, exploration_id, new_rating): """Records the rating awarded by the user to the exploration in both the user-specific data and exploration summary. This function validates the exploration id but not the user id. Args: user_id: str. The id of the user assigning the rating. exploration_id: str. The id of the exploration that is assigned a rating. new_rating: int. Value of assigned rating, should be between 1 and 5 inclusive. """ if not isinstance(new_rating, int): raise ValueError( 'Expected the rating to be an integer, received %s' % new_rating) if new_rating not in ALLOWED_RATINGS: raise ValueError('Expected a rating 1-5, received %s.' % new_rating) try: exp_services.get_exploration_by_id(exploration_id) except: raise Exception('Invalid exploration id %s' % exploration_id) def _update_user_rating(): exp_user_data_model = user_models.ExplorationUserDataModel.get( user_id, exploration_id) if exp_user_data_model: old_rating = exp_user_data_model.rating else: old_rating = None exp_user_data_model = user_models.ExplorationUserDataModel.create( user_id, exploration_id) exp_user_data_model.rating = new_rating exp_user_data_model.rated_on = datetime.datetime.utcnow() exp_user_data_model.put() return old_rating old_rating = transaction_services.run_in_transaction(_update_user_rating) exploration_summary = exp_services.get_exploration_summary_by_id( exploration_id) if not exploration_summary.ratings: exploration_summary.ratings = feconf.get_empty_ratings() exploration_summary.ratings[str(new_rating)] += 1 if old_rating: exploration_summary.ratings[str(old_rating)] -= 1 event_services.RateExplorationEventHandler.record( exploration_id, user_id, new_rating, old_rating) exploration_summary.scaled_average_rating = ( exp_services.get_scaled_average_rating( exploration_summary.ratings)) exp_services.save_exploration_summary(exploration_summary)
def _handle_incoming_event(cls, active_realtime_layer, event_type, *args): exp_id = args[0] def _refresh_average_ratings(user_id, rating, old_rating): realtime_class = cls._get_realtime_datastore_class() realtime_model_id = realtime_class.get_realtime_id( active_realtime_layer, user_id) model = realtime_class.get(realtime_model_id, strict=False) if model is None: realtime_class( id=realtime_model_id, average_ratings=rating, num_ratings=1, realtime_layer=active_realtime_layer).put() else: num_ratings = model.num_ratings average_ratings = model.average_ratings num_ratings += 1 if average_ratings is not None: sum_of_ratings = ( average_ratings * (num_ratings - 1) + rating) if old_rating is not None: sum_of_ratings -= old_rating num_ratings -= 1 model.average_ratings = sum_of_ratings/(num_ratings * 1.0) else: model.average_ratings = rating model.num_ratings = num_ratings model.put() def _increment_total_plays_count(user_id): realtime_class = cls._get_realtime_datastore_class() realtime_model_id = realtime_class.get_realtime_id( active_realtime_layer, user_id) model = realtime_class.get(realtime_model_id, strict=False) if model is None: realtime_class( id=realtime_model_id, total_plays=1, realtime_layer=active_realtime_layer).put() else: model.total_plays += 1 model.put() exp_summary = exp_services.get_exploration_summary_by_id(exp_id) if exp_summary: for user_id in exp_summary.owner_ids: if event_type == feconf.EVENT_TYPE_START_EXPLORATION: transaction_services.run_in_transaction( _increment_total_plays_count, user_id) elif event_type == feconf.EVENT_TYPE_RATE_EXPLORATION: rating = args[2] old_rating = args[3] transaction_services.run_in_transaction( _refresh_average_ratings, user_id, rating, old_rating)
def get_overall_ratings_for_exploration(exploration_id): """Fetches all ratings for an exploration. Args: exploration_id: str. The id of the exploration. Returns: a dict whose keys are '1', '2', '3', '4', '5' and whose values are nonnegative integers representing the frequency counts of each rating. """ exp_summary = exp_services.get_exploration_summary_by_id(exploration_id) return exp_summary.ratings
def get_overall_ratings_for_exploration(exploration_id): """Fetches all ratings for an exploration. Args: exploration_id: str. The id of the exploration. Returns: a dict whose keys are '1', '2', '3', '4', '5' and whose values are nonnegative integers representing the frequency counts of each rating. """ exp_summary = exp_services.get_exploration_summary_by_id(exploration_id) return exp_summary.ratings
def assign_rating_to_exploration(user_id, exploration_id, new_rating): """Records the rating awarded by the user to the exploration in both the user-specific data and exploration summary. It validates the exploration id but not the user id. - 'new_rating' should be an integer between 1 and 5 """ if not isinstance(new_rating, int): raise ValueError('Expected the rating to be an integer, received %s' % new_rating) if new_rating not in ALLOWED_RATINGS: raise ValueError('Expected a rating 1-5, received %s.' % new_rating) try: exp_services.get_exploration_by_id(exploration_id) except: raise Exception('Invalid exploration id %s' % exploration_id) def _update_user_rating(): exp_user_data_model = user_models.ExplorationUserDataModel.get( user_id, exploration_id) if exp_user_data_model: old_rating = exp_user_data_model.rating else: old_rating = None exp_user_data_model = user_models.ExplorationUserDataModel.create( user_id, exploration_id) exp_user_data_model.rating = new_rating exp_user_data_model.rated_on = datetime.datetime.utcnow() exp_user_data_model.put() return old_rating old_rating = transaction_services.run_in_transaction(_update_user_rating) exploration_summary = exp_services.get_exploration_summary_by_id( exploration_id) if not exploration_summary.ratings: exploration_summary.ratings = feconf.get_empty_ratings() exploration_summary.ratings[str(new_rating)] += 1 if old_rating: exploration_summary.ratings[str(old_rating)] -= 1 exploration_summary.scaled_average_rating = ( exp_services.get_scaled_average_rating(exploration_summary.ratings)) exp_services.save_exploration_summary(exploration_summary)
def map(item): if item.deleted: return exploration_impact_score = ( UserImpactMRJobManager._get_exp_impact_score(item.id)) if exploration_impact_score > 0: # Get exploration summary and contributor ids, # yield for each contributor. exploration_summary = exp_services.get_exploration_summary_by_id( item.id) contributor_ids = exploration_summary.contributor_ids for contributor_id in contributor_ids: yield (contributor_id, exploration_impact_score)
def map(item): if item.deleted: return exploration_impact_score = ( UserImpactMRJobManager._get_exp_impact_score(item.id)) if exploration_impact_score > 0: # Get exploration summary and contributor ids, # yield for each contributor. exploration_summary = exp_services.get_exploration_summary_by_id( item.id) contributor_ids = exploration_summary.contributor_ids for contributor_id in contributor_ids: yield (contributor_id, exploration_impact_score)
def test_contributors_for_valid_contribution(self): """Test that if only one commit is made, that the contributor list consists of that contributor's user id. """ self.signup(self.EMAIL_A, self.USERNAME_A) user_a_id = self.get_user_id_from_email(self.EMAIL_A) exploration = self.save_new_valid_exploration(self.EXP_ID, user_a_id) job_id = ( exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new()) exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual([user_a_id], exploration_summary.contributor_ids)
def map(item): if item.deleted: return exponent = 2.0/3 # Get average rating and value per user total_rating = 0 for ratings_value in item.ratings: total_rating += item.ratings[ratings_value] * int(ratings_value) if not sum(item.ratings.itervalues()): return average_rating = total_rating / sum(item.ratings.itervalues()) value_per_user = average_rating - 2 if value_per_user <= 0: return statistics = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( item.id, stats_jobs_continuous.VERSION_ALL)) answer_count = 0 # Find number of users per state (card), and subtract no answer # This will not count people who have been back to a state twice # but did not give an answer the second time, but is probably the # closest we can get with current statistics to "number of users # who gave an answer" since it is "number of users who always gave # an answer". for state_name in statistics['state_hit_counts']: state_stats = statistics['state_hit_counts'][state_name] first_entry_count = state_stats.get('first_entry_count', 0) no_answer_count = state_stats.get('no_answer_count', 0) answer_count += first_entry_count - no_answer_count # Turn answer count into reach reach = answer_count**exponent exploration_summary = exp_services.get_exploration_summary_by_id( item.id) contributors = exploration_summary.contributors_summary total_commits = sum(contributors.itervalues()) if total_commits == 0: return for contrib_id in contributors: # Find fractional contribution for each contributor contribution = contributors[contrib_id] / float(total_commits) # Find score for this specific exploration exploration_impact_score = value_per_user * reach * contribution yield (contrib_id, exploration_impact_score)
def test_contributors_for_valid_contribution(self): """Test that if only one commit is made, that the contributor list consists of that contributor's user id. """ self.signup(self.EMAIL_A, self.USERNAME_A) self.user_a_id = self.get_user_id_from_email(self.EMAIL_A) exploration = self.save_new_valid_exploration( self.EXP_ID, self.user_a_id) job_id = exp_jobs_one_off.ExpSummariesContributorsOneOffJob.create_new() exp_jobs_one_off.ExpSummariesContributorsOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual( [self.user_a_id], exploration_summary.contributor_ids)
def test_contributors_with_only_reverts_not_included(self): """Test that if only reverts are made by contributor then the contributions summary shouldn’t contain that contributor’s ID. """ user_a_id = self.get_user_id_from_email(self.EMAIL_A) user_b_id = self.get_user_id_from_email(self.EMAIL_B) # Let USER A make three commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Exploration Title 1') exp_services.update_exploration(user_a_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New Exploration Title' }) ], 'Changed title.') exp_services.update_exploration(user_a_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'New Objective' }) ], 'Changed Objective.') # Let the second user revert version 3 to version 2. exp_services.revert_exploration(user_b_id, self.EXP_ID, 3, 2) # Run the job to compute the contributors summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue( job_id) self.process_and_flush_pending_tasks() exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) # Check that the contributors_summary does not contains user_b_id. self.assertNotIn(user_b_id, exploration_summary.contributors_summary) # Check that the User A has only 2 commits after user b has reverted # to version 2. self.assertEquals(2, exploration_summary.contributors_summary[user_a_id]) # pylint: disable=line-too-long
def assign_rating(user_id, exploration_id, new_rating): """Records the rating awarded by the user to the exploration in both the user-specific data and exploration summary. It validates the exploration id but not the user id. - 'new_rating' should be an integer between 1 and 5 """ if not isinstance(new_rating, int): raise ValueError( 'Expected the rating to be an integer, received %s' % new_rating) ALLOWED_RATINGS = [1, 2, 3, 4, 5] if new_rating not in ALLOWED_RATINGS: raise ValueError('Expected a rating 1-5, received: %s.' % new_rating) try: exp_services.get_exploration_by_id(exploration_id) except: raise Exception('Invalid exploration id %s' % exploration_id) def _update_user_rating(): exp_user_data_model = user_models.ExplorationUserDataModel.get( user_id, exploration_id) if exp_user_data_model: old_rating = exp_user_data_model.rating else: old_rating = None exp_user_data_model = user_models.ExplorationUserDataModel.create( user_id, exploration_id) exp_user_data_model.rating = new_rating exp_user_data_model.rated_on = datetime.datetime.utcnow() exp_user_data_model.put() return old_rating old_rating = transaction_services.run_in_transaction(_update_user_rating) exploration_summary = exp_services.get_exploration_summary_by_id( exploration_id) if not exploration_summary.ratings: exploration_summary.ratings = feconf.get_empty_ratings() exploration_summary.ratings[str(new_rating)] += 1 if old_rating: exploration_summary.ratings[str(old_rating)] -= 1 exp_services.save_exploration_summary(exploration_summary)
def test_reverts_not_counted(self): """Test that if both non-revert commits and revert are made by contributor then the contributions summary shows only non-revert commits for that contributor. However, the commits made after the version to which we have reverted shouldn't be counted either. """ user_a_id = self.get_user_id_from_email(self.EMAIL_A) # Let USER A make 3 non-revert commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Exploration Title') exp_services.update_exploration(user_a_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New Exploration Title' }) ], 'Changed title.') exp_services.update_exploration(user_a_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'New Objective' }) ], 'Changed Objective.') # Let USER A revert version 3 to version 2. exp_services.revert_exploration(user_a_id, self.EXP_ID, 3, 2) # Run the job to compute the contributor summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue( job_id) self.process_and_flush_pending_tasks() # Check that USER A's number of contributions is equal to 2. exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual(2, exploration_summary.contributors_summary[user_a_id])
def test_contributors_with_only_reverts_not_included(self): """Test that if only reverts are made by contributor then the contributions summary shouldn’t contain that contributor’s ID """ user_a_id = self.get_user_id_from_email(self.EMAIL_A) user_b_id = self.get_user_id_from_email(self.EMAIL_B) # Let USER A make three commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Exploration Title 1') exp_services.update_exploration( user_a_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New Exploration Title' }], 'Changed title.') exp_services.update_exploration( user_a_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'New Objective' }], 'Changed Objective.') # Let the second user revert version 3 to version 2 exp_services.revert_exploration(user_b_id, self.EXP_ID, 3, 2) # Run the job to compute the contributors summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) # Check that the contributors_summary does not contains user_b_id self.assertNotIn(user_b_id, exploration_summary.contributors_summary) # Check that the User A has only 2 commits after user b has reverted # to version 2 self.assertEquals(2, exploration_summary.contributors_summary[user_a_id]) # pylint: disable=line-too-long
def test_contributors_for_valid_nonrevert_contribution(self): """Test that if only non-revert commits are made by contributor then the contributions summary shows same exact number of commits for that contributor's ID. """ user_a_id = self.get_user_id_from_email(self.EMAIL_A) # Let USER A make three commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Exploration Title') exp_services.update_exploration(user_a_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New Exploration Title' }) ], 'Changed title.') exp_services.update_exploration(user_a_id, self.EXP_ID, [ exp_domain.ExplorationChange({ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'New Objective' }) ], 'Changed Objective.') # Run the job to compute contributors summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue( job_id) self.process_and_flush_pending_tasks() exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual(3, exploration_summary.contributors_summary[user_a_id])
def test_reverts_not_counted(self): """Test that if both non-revert commits and revert are made by contributor then the contributions summary shows only non-revert commits for that contributor. However, the commits made after the version to which we have reverted shouldn't be counted either. """ user_a_id = self.get_user_id_from_email(self.EMAIL_A) # Let USER A make 3 non-revert commits exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Exploration Title') exp_services.update_exploration( user_a_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New Exploration Title' }], 'Changed title.') exp_services.update_exploration( user_a_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'New Objective' }], 'Changed Objective.') # Let USER A revert version 3 to version 2 exp_services.revert_exploration(user_a_id, self.EXP_ID, 3, 2) # Run the job to compute the contributor summary. job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() # Check that USER A's number of contributions is equal to 2 exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual(2, exploration_summary.contributors_summary[user_a_id])
def test_contributors_for_valid_nonrevert_contribution(self): """Test that if only non-revert commits are made by contributor then the contributions summary shows same exact number of commits for that contributor's ID """ user_a_id = self.get_user_id_from_email(self.EMAIL_A) # Let USER A make three commits. exploration = self.save_new_valid_exploration( self.EXP_ID, user_a_id, title='Exploration Title') exp_services.update_exploration( user_a_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'title', 'new_value': 'New Exploration Title' }], 'Changed title.') exp_services.update_exploration( user_a_id, self.EXP_ID, [{ 'cmd': 'edit_exploration_property', 'property_name': 'objective', 'new_value': 'New Objective' }], 'Changed Objective.') # Run the job to compute contributors summary job_id = exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.create_new() # pylint: disable=line-too-long exp_jobs_one_off.ExplorationContributorsSummaryOneOffJob.enqueue(job_id) self.process_and_flush_pending_tasks() exploration_summary = exp_services.get_exploration_summary_by_id( exploration.id) self.assertEqual( 3, exploration_summary.contributors_summary[user_a_id])
def map(item): """Implements the map function (generator). Computes exploration data for every contributor and owner of the exploration. Args: item: ExpSummaryModel. An instance of ExpSummaryModel. Yields: This function may yield as many times as appropriate 2-tuples in the format (str, dict), where - str. The unique ID of the user. - dict: A dict that includes entries for all the explorations that this user contributes to or owns. Each entry has the following keys: - 'exploration_impact_score': float. The impact score of all the explorations contributed to by the user. - 'total_plays_for_owned_exp': int. Total plays of all explorations owned by the user. - 'average_rating_for_owned_exp': float. Average of average ratings of all explorations owned by the user. - 'num_ratings_for_owned_exp': int. Total number of ratings of all explorations owned by the user. """ if item.deleted: return exponent = 2.0 / 3 # This is set to False only when the exploration impact score is not # valid to be calculated. calculate_exploration_impact_score = True # Get average rating and value per user. total_rating = 0 for ratings_value in item.ratings: total_rating += item.ratings[ratings_value] * int(ratings_value) sum_of_ratings = sum(item.ratings.itervalues()) average_rating = ((total_rating / sum_of_ratings) if sum_of_ratings else None) if average_rating is not None: value_per_user = average_rating - 2 if value_per_user <= 0: calculate_exploration_impact_score = False else: calculate_exploration_impact_score = False exploration_stats = stats_services.get_exploration_stats( item.id, item.version) # For each state, find the number of first entries to the state. # This is considered to be approximately equal to the number of # users who answered the state because very few users enter a state # and leave without answering anything at all. answer_count = exploration_stats.get_sum_of_first_hit_counts() num_starts = exploration_stats.num_starts # Turn answer count into reach. reach = answer_count**exponent exploration_summary = exp_services.get_exploration_summary_by_id( item.id) contributors = exploration_summary.contributors_summary total_commits = sum(contributors.itervalues()) if total_commits == 0: calculate_exploration_impact_score = False mapped_owner_ids = [] for contrib_id in contributors: exploration_data = {} # Set the value of exploration impact score only if it needs to be # calculated. if calculate_exploration_impact_score: # Find fractional contribution for each contributor. contribution = (contributors[contrib_id] / float(total_commits)) # Find score for this specific exploration. exploration_data.update({ 'exploration_impact_score': (value_per_user * reach * contribution) }) # if the user is an owner for the exploration, then update dict with # 'average ratings' and 'total plays' as well. if contrib_id in exploration_summary.owner_ids: mapped_owner_ids.append(contrib_id) # Get num starts (total plays) for the exploration. exploration_data.update({ 'total_plays_for_owned_exp': num_starts, }) # Update data with average rating only if it is not None. if average_rating is not None: exploration_data.update({ 'average_rating_for_owned_exp': average_rating, 'num_ratings_for_owned_exp': sum_of_ratings }) yield (contrib_id, exploration_data) for owner_id in exploration_summary.owner_ids: if owner_id not in mapped_owner_ids: mapped_owner_ids.append(owner_id) # Get num starts (total plays) for the exploration. exploration_data = { 'total_plays_for_owned_exp': num_starts, } # Update data with average rating only if it is not None. if average_rating is not None: exploration_data.update({ 'average_rating_for_owned_exp': average_rating, 'num_ratings_for_owned_exp': sum_of_ratings }) yield (owner_id, exploration_data)
def _handle_incoming_event(cls, active_realtime_layer, event_type, *args): """Records incoming events in the given realtime layer. Args: active_realtime_layer: int. The currently active realtime datastore layer. event_type: str. The event triggered by a student. For example, when a student starts an exploration, an event of type `start` is triggered and the total play count is incremented. If he/she rates an exploration, an event of type `rate` is triggered and average rating of the realtime model is refreshed. *args: If event_type is 'start', then this is a 1-element list with following entry: - str. The ID of the exploration currently being played. If event_type is 'rate_exploration', then this is a 3-element list with following entries: - str. The ID of the exploration currently being played. - float. The rating given by user to the exploration. - float. The old rating of the exploration, before it is refreshed. """ exp_id = args[0] def _refresh_average_ratings(user_id, rating, old_rating): realtime_class = cls._get_realtime_datastore_class() realtime_model_id = realtime_class.get_realtime_id( active_realtime_layer, user_id) model = realtime_class.get(realtime_model_id, strict=False) if model is None: realtime_class(id=realtime_model_id, average_ratings=rating, num_ratings=1, realtime_layer=active_realtime_layer).put() else: num_ratings = model.num_ratings average_ratings = model.average_ratings num_ratings += 1 if average_ratings is not None: sum_of_ratings = (average_ratings * (num_ratings - 1) + rating) if old_rating is not None: sum_of_ratings -= old_rating num_ratings -= 1 model.average_ratings = sum_of_ratings / (num_ratings * 1.0) else: model.average_ratings = rating model.num_ratings = num_ratings model.put() def _increment_total_plays_count(user_id): realtime_class = cls._get_realtime_datastore_class() realtime_model_id = realtime_class.get_realtime_id( active_realtime_layer, user_id) model = realtime_class.get(realtime_model_id, strict=False) if model is None: realtime_class(id=realtime_model_id, total_plays=1, realtime_layer=active_realtime_layer).put() else: model.total_plays += 1 model.put() exp_summary = exp_services.get_exploration_summary_by_id(exp_id) if exp_summary: for user_id in exp_summary.owner_ids: if event_type == feconf.EVENT_TYPE_START_EXPLORATION: transaction_services.run_in_transaction( _increment_total_plays_count, user_id) elif event_type == feconf.EVENT_TYPE_RATE_EXPLORATION: rating = args[2] old_rating = args[3] transaction_services.run_in_transaction( _refresh_average_ratings, user_id, rating, old_rating)
def map(item): """Implements the map function (generator). Computes exploration data for every contributor and owner of the exploration. Args: item: ExpSummaryModel. An instance of ExpSummaryModel. Yields: This function may yield as many times as appropriate 2-tuples in the format (str, dict), where - str. The unique ID of the user. - dict: A dict that includes entries for all the explorations that this user contributes to or owns. Each entry has the following keys: - 'exploration_impact_score': float. The impact score of all the explorations contributed to by the user. - 'total_plays_for_owned_exp': int. Total plays of all explorations owned by the user. - 'average_rating_for_owned_exp': float. Average of average ratings of all explorations owned by the user. - 'num_ratings_for_owned_exp': int. Total number of ratings of all explorations owned by the user. """ if item.deleted: return exponent = 2.0 / 3 # This is set to False only when the exploration impact score is not # valid to be calculated. calculate_exploration_impact_score = True # Get average rating and value per user total_rating = 0 for ratings_value in item.ratings: total_rating += item.ratings[ratings_value] * int(ratings_value) sum_of_ratings = sum(item.ratings.itervalues()) average_rating = ((total_rating / sum_of_ratings) if sum_of_ratings else None) if average_rating is not None: value_per_user = average_rating - 2 if value_per_user <= 0: calculate_exploration_impact_score = False else: calculate_exploration_impact_score = False statistics = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( item.id, stats_jobs_continuous.VERSION_ALL)) answer_count = 0 # Find number of users per state (card), and subtract no answer # This will not count people who have been back to a state twice # but did not give an answer the second time, but is probably the # closest we can get with current statistics to "number of users # who gave an answer" since it is "number of users who always gave # an answer". for state_name in statistics['state_hit_counts']: state_stats = statistics['state_hit_counts'][state_name] first_entry_count = state_stats.get('first_entry_count', 0) no_answer_count = state_stats.get('no_answer_count', 0) answer_count += first_entry_count - no_answer_count # Turn answer count into reach reach = answer_count**exponent exploration_summary = exp_services.get_exploration_summary_by_id( item.id) contributors = exploration_summary.contributors_summary total_commits = sum(contributors.itervalues()) if total_commits == 0: calculate_exploration_impact_score = False mapped_owner_ids = [] for contrib_id in contributors: exploration_data = {} # Set the value of exploration impact score only if it needs to be # calculated. if calculate_exploration_impact_score: # Find fractional contribution for each contributor contribution = (contributors[contrib_id] / float(total_commits)) # Find score for this specific exploration exploration_data.update({ 'exploration_impact_score': (value_per_user * reach * contribution) }) # if the user is an owner for the exploration, then update dict with # 'average ratings' and 'total plays' as well. if contrib_id in exploration_summary.owner_ids: mapped_owner_ids.append(contrib_id) # Get num starts (total plays) for the exploration exploration_data.update({ 'total_plays_for_owned_exp': (statistics['start_exploration_count']), }) # Update data with average rating only if it is not None. if average_rating is not None: exploration_data.update({ 'average_rating_for_owned_exp': average_rating, 'num_ratings_for_owned_exp': sum_of_ratings }) yield (contrib_id, exploration_data) for owner_id in exploration_summary.owner_ids: if owner_id not in mapped_owner_ids: mapped_owner_ids.append(owner_id) # Get num starts (total plays) for the exploration exploration_data = { 'total_plays_for_owned_exp': (statistics['start_exploration_count']), } # Update data with average rating only if it is not None. if average_rating is not None: exploration_data.update({ 'average_rating_for_owned_exp': average_rating, 'num_ratings_for_owned_exp': sum_of_ratings }) yield (owner_id, exploration_data)
def map(item): if item.deleted: return exponent = 2.0/3 # This is set to False only when the exploration impact score is not # valid to be calculated. calculate_exploration_impact_score = True # Get average rating and value per user total_rating = 0 for ratings_value in item.ratings: total_rating += item.ratings[ratings_value] * int(ratings_value) sum_of_ratings = sum(item.ratings.itervalues()) average_rating = ((total_rating / sum_of_ratings) if sum_of_ratings else None) if average_rating is not None: value_per_user = average_rating - 2 if value_per_user <= 0: calculate_exploration_impact_score = False else: calculate_exploration_impact_score = False statistics = ( stats_jobs_continuous.StatisticsAggregator.get_statistics( item.id, stats_jobs_continuous.VERSION_ALL)) answer_count = 0 # Find number of users per state (card), and subtract no answer # This will not count people who have been back to a state twice # but did not give an answer the second time, but is probably the # closest we can get with current statistics to "number of users # who gave an answer" since it is "number of users who always gave # an answer". for state_name in statistics['state_hit_counts']: state_stats = statistics['state_hit_counts'][state_name] first_entry_count = state_stats.get('first_entry_count', 0) no_answer_count = state_stats.get('no_answer_count', 0) answer_count += first_entry_count - no_answer_count # Turn answer count into reach reach = answer_count**exponent exploration_summary = exp_services.get_exploration_summary_by_id( item.id) contributors = exploration_summary.contributors_summary total_commits = sum(contributors.itervalues()) if total_commits == 0: calculate_exploration_impact_score = False mapped_owner_ids = [] for contrib_id in contributors: exploration_data = {} # Set the value of exploration impact score only if it needs to be # calculated. if calculate_exploration_impact_score: # Find fractional contribution for each contributor contribution = ( contributors[contrib_id] / float(total_commits)) # Find score for this specific exploration exploration_data.update({ 'exploration_impact_score': ( value_per_user * reach * contribution) }) # if the user is an owner for the exploration, then update dict with # 'average ratings' and 'total plays' as well. if contrib_id in exploration_summary.owner_ids: mapped_owner_ids.append(contrib_id) # Get num starts (total plays) for the exploration exploration_data.update({ 'total_plays_for_owned_exp': ( statistics['start_exploration_count']), }) # Update data with average rating only if it is not None. if average_rating is not None: exploration_data.update({ 'average_rating_for_owned_exp': average_rating }) yield (contrib_id, exploration_data) for owner_id in exploration_summary.owner_ids: if owner_id not in mapped_owner_ids: mapped_owner_ids.append(owner_id) # Get num starts (total plays) for the exploration exploration_data = { 'total_plays_for_owned_exp': ( statistics['start_exploration_count']), } # Update data with average rating only if it is not None. if average_rating is not None: exploration_data.update({ 'average_rating_for_owned_exp': average_rating }) yield (owner_id, exploration_data)
def get_overall_ratings(exploration_id): exp_summary = exp_services.get_exploration_summary_by_id(exploration_id) return exp_summary.ratings
def get_overall_ratings_for_exploration(exploration_id): exp_summary = exp_services.get_exploration_summary_by_id(exploration_id) return exp_summary.ratings