forked from oppia/oppia
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix part of oppia#1366: Implement realtime layer for UserStats contin…
…uous job (oppia#2238) * Basic implementation; yet to be completed * Partial implementation * Branching in map based on different models * Revert branching in map; Update UserStats model * Realtime layer and model changes * Add num_ratings in stats; resolve TODO for self * Minor fixess in code * Remove session id from rate exploration event model * Minor fixes * Fix unused argument * Updations to realtime layer backend * Display num ratings in view * Fix backend tests * Check num_ratings increase for same rating twice * Use user_id as entity key as well * Add tests using events for realtime layer * Add tests for realtime layer * Handle case when user rating already exists * Minor changes to RateExplorationEventLogEntryModel * Partially address review comments * Address review comments * Fix commented out backend test
- Loading branch information
1 parent
9f34971
commit 6f84fcd
Showing
19 changed files
with
525 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -111,8 +111,8 @@ def _rate_exploration(self, exp_id, ratings): | |
"""Create num_ratings ratings for exploration with exp_id, | ||
of values from ratings. | ||
""" | ||
# Each user id needs to be unique since each user can only give an | ||
# exploration one rating. | ||
# Generate unique user ids to rate an exploration. Each user id needs | ||
# to be unique since each user can only give an exploration one rating. | ||
user_ids = ['user%d' % i for i in range(len(ratings))] | ||
self.process_and_flush_pending_tasks() | ||
for ind, user_id in enumerate(user_ids): | ||
|
@@ -177,6 +177,7 @@ def test_one_play_for_single_exploration(self): | |
self.assertEquals(user_model.total_plays, 1) | ||
self.assertEquals( | ||
user_model.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model.num_ratings, 0) | ||
self.assertIsNone(user_model.average_ratings) | ||
self.logout() | ||
|
||
|
@@ -196,6 +197,7 @@ def test_one_rating_for_single_exploration(self): | |
self.assertEquals(user_model.total_plays, 0) | ||
self.assertEquals( | ||
user_model.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model.num_ratings, 1) | ||
self.assertEquals(user_model.average_ratings, 4) | ||
self.logout() | ||
|
||
|
@@ -222,6 +224,7 @@ def test_one_play_and_rating_for_single_exploration(self): | |
self.assertEquals(user_model.total_plays, 1) | ||
self.assertEquals( | ||
user_model.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model.num_ratings, 1) | ||
self.assertEquals(user_model.average_ratings, 3) | ||
self.logout() | ||
|
||
|
@@ -250,6 +253,7 @@ def test_multiple_plays_and_ratings_for_single_exploration(self): | |
self.assertEquals(user_model.total_plays, 4) | ||
self.assertEquals( | ||
user_model.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model.num_ratings, 3) | ||
self.assertEquals(user_model.average_ratings, 4) | ||
self.logout() | ||
|
||
|
@@ -278,13 +282,13 @@ def test_one_play_and_rating_for_multiple_explorations(self): | |
self.assertEquals(user_model.total_plays, 1) | ||
self.assertEquals( | ||
user_model.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model.num_ratings, 1) | ||
self.assertEquals(user_model.average_ratings, 4) | ||
self.logout() | ||
|
||
def test_multiple_plays_and_ratings_for_multiple_explorations(self): | ||
exploration_1 = self.save_new_default_exploration( | ||
self.EXP_ID_1, self.owner_id_1, title=self.EXP_TITLE_1) | ||
|
||
exploration_2 = self.save_new_default_exploration( | ||
self.EXP_ID_2, self.owner_id_1, title=self.EXP_TITLE_2) | ||
|
||
|
@@ -302,17 +306,19 @@ def test_multiple_plays_and_ratings_for_multiple_explorations(self): | |
self._record_start(exp_id_1, exp_version, state_1) | ||
self._record_start(exp_id_2, exp_version, state_2) | ||
self._record_start(exp_id_2, exp_version, state_2) | ||
self._run_stats_aggregator_jobs() | ||
|
||
self._rate_exploration(exp_id_1, [4]) | ||
self._rate_exploration(exp_id_2, [3]) | ||
self._rate_exploration(exp_id_2, [3, 3]) | ||
|
||
self._run_stats_aggregator_jobs() | ||
self._run_user_stats_aggregator_job() | ||
|
||
user_model = user_models.UserStatsModel.get(self.owner_id_1) | ||
self.assertEquals(user_model.total_plays, 3) | ||
self.assertEquals( | ||
user_model.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model.average_ratings, 3.5) | ||
self.assertEquals(user_model.num_ratings, 3) | ||
self.assertEquals(user_model.average_ratings, 10/3.0) | ||
self.logout() | ||
|
||
def test_stats_for_single_exploration_with_multiple_owners(self): | ||
|
@@ -351,13 +357,15 @@ def test_stats_for_single_exploration_with_multiple_owners(self): | |
self.assertEquals(user_model_1.total_plays, 2) | ||
self.assertEquals( | ||
user_model_1.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model_1.num_ratings, 3) | ||
self.assertEquals(user_model_1.average_ratings, 4) | ||
|
||
user_model_2 = user_models.UserStatsModel.get( | ||
self.owner_id_2) | ||
self.assertEquals(user_model_2.total_plays, 2) | ||
self.assertEquals( | ||
user_model_2.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model_2.num_ratings, 3) | ||
self.assertEquals(user_model_2.average_ratings, 4) | ||
self.logout() | ||
|
||
|
@@ -389,30 +397,47 @@ def test_stats_for_multiple_explorations_with_multiple_owners(self): | |
self._record_start(exp_id_1, exp_version, state_1) | ||
self._record_start(exp_id_2, exp_version, state_2) | ||
self._record_start(exp_id_2, exp_version, state_2) | ||
self._record_start(exp_id_2, exp_version, state_2) | ||
self._run_stats_aggregator_jobs() | ||
|
||
self._rate_exploration(exp_id_1, [3]) | ||
self._rate_exploration(exp_id_2, [2]) | ||
self._rate_exploration(exp_id_1, [5, 3]) | ||
self._rate_exploration(exp_id_2, [5, 5]) | ||
|
||
self._run_user_stats_aggregator_job() | ||
|
||
expected_results = { | ||
'total_plays': 5, | ||
'num_ratings': 4, | ||
'average_ratings': 18/4.0 | ||
} | ||
|
||
user_model_2 = user_models.UserStatsModel.get(self.owner_id_2) | ||
self.assertEquals(user_model_2.total_plays, 4) | ||
self.assertEquals( | ||
user_model_2.total_plays, expected_results['total_plays']) | ||
self.assertEquals( | ||
user_model_2.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model_2.average_ratings, 2.5) | ||
self.assertEquals( | ||
user_model_2.num_ratings, expected_results['num_ratings']) | ||
self.assertEquals( | ||
user_model_2.average_ratings, expected_results['average_ratings']) | ||
self.logout() | ||
|
||
self.login(self.OWNER_EMAIL_1) | ||
response = self.get_json(feconf.DASHBOARD_DATA_URL) | ||
self.assertEqual(len(response['explorations_list']), 2) | ||
|
||
user_model_1 = user_models.UserStatsModel.get(self.owner_id_1) | ||
self.assertEquals(user_model_1.total_plays, 4) | ||
self.assertEquals( | ||
user_model_1.total_plays, expected_results['total_plays']) | ||
self.assertEquals( | ||
user_model_1.impact_score, self.USER_IMPACT_SCORE_DEFAULT) | ||
self.assertEquals(user_model_1.average_ratings, 2.5) | ||
self.assertEquals( | ||
user_model_1.num_ratings, expected_results['num_ratings']) | ||
self.assertEquals( | ||
user_model_1.average_ratings, expected_results['average_ratings']) | ||
self.logout() | ||
|
||
|
||
class DashboardHandlerTest(test_utils.GenericTestBase): | ||
|
||
COLLABORATOR_EMAIL = '[email protected]' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.