{"action":"created","comment":{"url":"https://api.github.com/repos/oppia/oppia/pulls/comments/44375538","id":44375538,"diff_hunk":"@@ -116,6 +117,180 @@ def test_get_collection_titles_and_categories(self):\n                 })\n \n \n+class ExplorationInCollectionContextUnitTests(CollectionServicesUnitTests):\n+    \"\"\"Tests query and recording methods related to explorations which are\n+    played in the context of a collection.\n+    \"\"\"\n+\n+    COL_ID_0 = '0_collection_id'\n+    COL_ID_1 = '1_collection_id'\n+    EXP_ID_0 = '0_exploration_id'\n+    EXP_ID_1 = '1_exploration_id'\n+    EXP_ID_2 = '2_exploration_id'\n+\n+    def _get_completion_model(self, user_id, collection_id):\n+        return user_models.ExplorationInCollectionCompletionModel.get(\n+            user_id, collection_id)\n+\n+    def _record_completion(self, user_id, collection_id, exploration_id):\n+        collection_services.record_played_exploration_in_collection_context(\n+            user_id, collection_id, exploration_id)\n+\n+    def setUp(self):\n+        super(ExplorationInCollectionContextUnitTests, self).setUp()\n+\n+        # Create a new collection and exploration.\n+        self.save_new_valid_collection(\n+            self.COL_ID_0, self.OWNER_ID, exploration_id=self.EXP_ID_0)\n+\n+        # Create another two explorations and add them to the collection.\n+        for exp_id in [self.EXP_ID_1, self.EXP_ID_2]:\n+            self.save_new_valid_exploration(exp_id, self.OWNER_ID)\n+            collection_services.update_collection(\n+                self.OWNER_ID, self.COL_ID_0, [{\n+                    'cmd': collection_domain.CMD_ADD_COLLECTION_NODE,\n+                    'exploration_id': exp_id\n+                }], 'Added new exploration')\n+\n+    def test_get_completed_exploration_ids(self):\n+        # There should be no exception if the user or collection do not exist.","path":"core/domain/collection_services_test.py","position":50,"original_position":50,"commit_id":"49bcf8ce4b3049df90a808d15bbf032a8f7a3257","original_commit_id":"49bcf8ce4b3049df90a808d15bbf032a8f7a3257","user":{"login":"seanlip","id":10575562,"avatar_url":"https://avatars.githubusercontent.com/u/10575562?v=3","gravatar_id":"","url":"https://api.github.com/users/seanlip","html_url":"https://github.com/seanlip","followers_url":"https://api.github.com/users/seanlip/followers","following_url":"https://api.github.com/users/seanlip/following{/other_user}","gists_url":"https://api.github.com/users/seanlip/gists{/gist_id}","starred_url":"https://api.github.com/users/seanlip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seanlip/subscriptions","organizations_url":"https://api.github.com/users/seanlip/orgs","repos_url":"https://api.github.com/users/seanlip/repos","events_url":"https://api.github.com/users/seanlip/events{/privacy}","received_events_url":"https://api.github.com/users/seanlip/received_events","type":"User","site_admin":false},"body":"Ah -- I think this should, at least, be added to the docstring of get_completed_exploration_ids -- that they will return [] if the collection id or user id doesn't exist. Something along the lines of (from our chat): \"A progress model isn't added until the first exploration of a collection is completed, so, if a model is missing, there isn't enough information to infer whether that means the collection doesn't exist, the user doesn't exist, or if they just haven't made any progress in that collection yet. Thus, we just assume the user and collection exist for the sake of this call, so it returns an empty list, indicating that no progress has yet been made.\"\r\n\r\nRe the deletion question: I think it's fine to not do anything for now, but please note this in the documentation for the progress model in core/storage (i.e. that progress models for collections will continue to exist even after the collection has been deleted, and what needs to be done if this policy is changed in the future).","created_at":"2015-11-10T07:07:31Z","updated_at":"2015-11-10T07:07:31Z","html_url":"https://github.com/oppia/oppia/pull/1056#discussion_r44375538","pull_request_url":"https://api.github.com/repos/oppia/oppia/pulls/1056","_links":{"self":{"href":"https://api.github.com/repos/oppia/oppia/pulls/comments/44375538"},"html":{"href":"https://github.com/oppia/oppia/pull/1056#discussion_r44375538"},"pull_request":{"href":"https://api.github.com/repos/oppia/oppia/pulls/1056"}}},"pull_request":{"url":"https://api.github.com/repos/oppia/oppia/pulls/1056","id":48617821,"html_url":"https://github.com/oppia/oppia/pull/1056","diff_url":"https://github.com/oppia/oppia/pull/1056.diff","patch_url":"https://github.com/oppia/oppia/pull/1056.patch","issue_url":"https://api.github.com/repos/oppia/oppia/issues/1056","number":1056,"state":"open","locked":false,"title":"Collections learner view","user":{"login":"BenHenning","id":12983742,"avatar_url":"https://avatars.githubusercontent.com/u/12983742?v=3","gravatar_id":"","url":"https://api.github.com/users/BenHenning","html_url":"https://github.com/BenHenning","followers_url":"https://api.github.com/users/BenHenning/followers","following_url":"https://api.github.com/users/BenHenning/following{/other_user}","gists_url":"https://api.github.com/users/BenHenning/gists{/gist_id}","starred_url":"https://api.github.com/users/BenHenning/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BenHenning/subscriptions","organizations_url":"https://api.github.com/users/BenHenning/orgs","repos_url":"https://api.github.com/users/BenHenning/repos","events_url":"https://api.github.com/users/BenHenning/events{/privacy}","received_events_url":"https://api.github.com/users/BenHenning/received_events","type":"User","site_admin":false},"body":"The first iteration of the collections learner view. These commits include an end-to-end working experience of playing collections. Collections must be accessed manually via a URL. In order to test the learner view and play through a collection, please follow the following steps:\r\n\r\n1. Log into admin panel and click 'Reload' for the example collection.\r\n\r\n1. Go to: http://localhost:8181/collection/0 (or a different base URL depending on your local runtime configuration). This will bring up the collection player page (which will look similar to the gallery).\r\n\r\n1. Play through the explorations it suggests. As part of the playthrough experience, you may continue playing explorations after you finish previous ones either by clicking on them in the recommend explorations area or by going back to the collection learner page and continuing from there.\r\n\r\n1. When the collection has been finished, the learner page will change and show all of the explorations in the collection, allowing the learner to go back and play any of them again.\r\n\r\nIf you have any questions about the current learner view, what yet needs to be completed, or have suggestions to improve the first iteration, please let me know.\r\n\r\nThanks!","created_at":"2015-10-23T19:05:45Z","updated_at":"2015-11-10T07:07:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a856a1a0c9a43dd70df0d52c7e01b6ce44f4c8e9","assignee":{"login":"seanlip","id":10575562,"avatar_url":"https://avatars.githubusercontent.com/u/10575562?v=3","gravatar_id":"","url":"https://api.github.com/users/seanlip","html_url":"https://github.com/seanlip","followers_url":"https://api.github.com/users/seanlip/followers","following_url":"https://api.github.com/users/seanlip/following{/other_user}","gists_url":"https://api.github.com/users/seanlip/gists{/gist_id}","starred_url":"https://api.github.com/users/seanlip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seanlip/subscriptions","organizations_url":"https://api.github.com/users/seanlip/orgs","repos_url":"https://api.github.com/users/seanlip/repos","events_url":"https://api.github.com/users/seanlip/events{/privacy}","received_events_url":"https://api.github.com/users/seanlip/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/oppia/oppia/pulls/1056/commits","review_comments_url":"https://api.github.com/repos/oppia/oppia/pulls/1056/comments","review_comment_url":"https://api.github.com/repos/oppia/oppia/pulls/comments{/number}","comments_url":"https://api.github.com/repos/oppia/oppia/issues/1056/comments","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/49bcf8ce4b3049df90a808d15bbf032a8f7a3257","head":{"label":"oppia:collections-learner-view","ref":"collections-learner-view","sha":"49bcf8ce4b3049df90a808d15bbf032a8f7a3257","user":{"login":"oppia","id":11620230,"avatar_url":"https://avatars.githubusercontent.com/u/11620230?v=3","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"repo":{"id":40687563,"name":"oppia","full_name":"oppia/oppia","owner":{"login":"oppia","id":11620230,"avatar_url":"https://avatars.githubusercontent.com/u/11620230?v=3","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/oppia/oppia","description":"Tool for collaboratively building interactive tutors.","fork":false,"url":"https://api.github.com/repos/oppia/oppia","forks_url":"https://api.github.com/repos/oppia/oppia/forks","keys_url":"https://api.github.com/repos/oppia/oppia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oppia/oppia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oppia/oppia/teams","hooks_url":"https://api.github.com/repos/oppia/oppia/hooks","issue_events_url":"https://api.github.com/repos/oppia/oppia/issues/events{/number}","events_url":"https://api.github.com/repos/oppia/oppia/events","assignees_url":"https://api.github.com/repos/oppia/oppia/assignees{/user}","branches_url":"https://api.github.com/repos/oppia/oppia/branches{/branch}","tags_url":"https://api.github.com/repos/oppia/oppia/tags","blobs_url":"https://api.github.com/repos/oppia/oppia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oppia/oppia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oppia/oppia/git/refs{/sha}","trees_url":"https://api.github.com/repos/oppia/oppia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/{sha}","languages_url":"https://api.github.com/repos/oppia/oppia/languages","stargazers_url":"https://api.github.com/repos/oppia/oppia/stargazers","contributors_url":"https://api.github.com/repos/oppia/oppia/contributors","subscribers_url":"https://api.github.com/repos/oppia/oppia/subscribers","subscription_url":"https://api.github.com/repos/oppia/oppia/subscription","commits_url":"https://api.github.com/repos/oppia/oppia/commits{/sha}","git_commits_url":"https://api.github.com/repos/oppia/oppia/git/commits{/sha}","comments_url":"https://api.github.com/repos/oppia/oppia/comments{/number}","issue_comment_url":"https://api.github.com/repos/oppia/oppia/issues/comments{/number}","contents_url":"https://api.github.com/repos/oppia/oppia/contents/{+path}","compare_url":"https://api.github.com/repos/oppia/oppia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oppia/oppia/merges","archive_url":"https://api.github.com/repos/oppia/oppia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oppia/oppia/downloads","issues_url":"https://api.github.com/repos/oppia/oppia/issues{/number}","pulls_url":"https://api.github.com/repos/oppia/oppia/pulls{/number}","milestones_url":"https://api.github.com/repos/oppia/oppia/milestones{/number}","notifications_url":"https://api.github.com/repos/oppia/oppia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oppia/oppia/labels{/name}","releases_url":"https://api.github.com/repos/oppia/oppia/releases{/id}","created_at":"2015-08-14T00:16:14Z","updated_at":"2015-11-09T11:03:31Z","pushed_at":"2015-11-10T05:33:38Z","git_url":"git://github.com/oppia/oppia.git","ssh_url":"git@github.com:oppia/oppia.git","clone_url":"https://github.com/oppia/oppia.git","svn_url":"https://github.com/oppia/oppia","homepage":"https://www.oppia.org","size":44676,"stargazers_count":52,"watchers_count":52,"language":"Python","has_issues":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":66,"mirror_url":null,"open_issues_count":208,"forks":66,"open_issues":208,"watchers":52,"default_branch":"develop"}},"base":{"label":"oppia:develop","ref":"develop","sha":"5a2ec42ca64cddb06e1354d0ce72fc2f5ba31914","user":{"login":"oppia","id":11620230,"avatar_url":"https://avatars.githubusercontent.com/u/11620230?v=3","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"repo":{"id":40687563,"name":"oppia","full_name":"oppia/oppia","owner":{"login":"oppia","id":11620230,"avatar_url":"https://avatars.githubusercontent.com/u/11620230?v=3","gravatar_id":"","url":"https://api.github.com/users/oppia","html_url":"https://github.com/oppia","followers_url":"https://api.github.com/users/oppia/followers","following_url":"https://api.github.com/users/oppia/following{/other_user}","gists_url":"https://api.github.com/users/oppia/gists{/gist_id}","starred_url":"https://api.github.com/users/oppia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oppia/subscriptions","organizations_url":"https://api.github.com/users/oppia/orgs","repos_url":"https://api.github.com/users/oppia/repos","events_url":"https://api.github.com/users/oppia/events{/privacy}","received_events_url":"https://api.github.com/users/oppia/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/oppia/oppia","description":"Tool for collaboratively building interactive tutors.","fork":false,"url":"https://api.github.com/repos/oppia/oppia","forks_url":"https://api.github.com/repos/oppia/oppia/forks","keys_url":"https://api.github.com/repos/oppia/oppia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oppia/oppia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oppia/oppia/teams","hooks_url":"https://api.github.com/repos/oppia/oppia/hooks","issue_events_url":"https://api.github.com/repos/oppia/oppia/issues/events{/number}","events_url":"https://api.github.com/repos/oppia/oppia/events","assignees_url":"https://api.github.com/repos/oppia/oppia/assignees{/user}","branches_url":"https://api.github.com/repos/oppia/oppia/branches{/branch}","tags_url":"https://api.github.com/repos/oppia/oppia/tags","blobs_url":"https://api.github.com/repos/oppia/oppia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oppia/oppia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oppia/oppia/git/refs{/sha}","trees_url":"https://api.github.com/repos/oppia/oppia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oppia/oppia/statuses/{sha}","languages_url":"https://api.github.com/repos/oppia/oppia/languages","stargazers_url":"https://api.github.com/repos/oppia/oppia/stargazers","contributors_url":"https://api.github.com/repos/oppia/oppia/contributors","subscribers_url":"https://api.github.com/repos/oppia/oppia/subscribers","subscription_url":"https://api.github.com/repos/oppia/oppia/subscription","commits_url":"https://api.github.com/repos/oppia/oppia/commits{/sha}","git_commits_url":"https://api.github.com/repos/oppia/oppia/git/commits{/sha}","comments_url":"https://api.github.com/repos/oppia/oppia/comments{/number}","issue_comment_url":"https://api.github.com/repos/oppia/oppia/issues/comments{/number}","contents_url":"https://api.github.com/repos/oppia/oppia/contents/{+path}","compare_url":"https://api.github.com/repos/oppia/oppia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oppia/oppia/merges","archive_url":"https://api.github.com/repos/oppia/oppia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oppia/oppia/downloads","issues_url":"https://api.github.com/repos/oppia/oppia/issues{/number}","pulls_url":"https://api.github.com/repos/oppia/oppia/pulls{/number}","milestones_url":"https://api.github.com/repos/oppia/oppia/milestones{/number}","notifications_url":"https://api.github.com/repos/oppia/oppia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oppia/oppia/labels{/name}","releases_url":"https://api.github.com/repos/oppia/oppia/releases{/id}","created_at":"2015-08-14T00:16:14Z","updated_at":"2015-11-09T11:03:31Z","pushed_at":"2015-11-10T05:33:38Z","git_url":"git://github.com/oppia/oppia.git","ssh_url":"git@github.com:oppia/oppia.git","clone_url":"https://github.com/oppia/oppia.git","svn_url":"https://github.com/oppia/oppia","homepage":"https://www.oppia.org","size":44676,"stargazers_count":52,"watchers_count":52,"language":"Python","has_issues":true,"has_downloads":false,"has_wiki":true,"has_pages":false,"forks_count":66,"mirror_url":null,"open_issues_count":208,"forks":66,"open_issues":208,"watchers":52,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/oppia/oppia/pulls/1056"},"html":{"href":"https://github.com/oppia/oppia/pull/1056"},"issue":{"href":"https://api.github.com/repos/oppia/oppia/issues/1056"},"comments":{"href":"https://api.github.com/repos/oppia/oppia/issues/1056/comments"},"review_comments":{"href":"https://api.github.com/repos/oppia/oppia/pulls/1056/comments"},"review_comment":{"href":"https://api.github.com/repos/oppia/oppia/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/oppia/oppia/pulls/1056/commits"},"statuses":{"href":"https://api.github.com/repos/oppia/oppia/statuses/49bcf8ce4b3049df90a808d15bbf032a8f7a3257"}}}}