{"action":"created","comment":{"url":"https://api.github.com/repos/openfun/fun-apps/pulls/comments/26124538","id":26124538,"diff_hunk":"@@ -0,0 +1,143 @@\n+import csv\n+import datetime\n+import json\n+import xml.etree.ElementTree as ET\n+\n+from django.contrib.auth.models import User, Group\n+from django.conf import settings\n+\n+from courseware.models import StudentModule\n+from student.models import UserProfile\n+from opaque_keys.edx.keys import UsageKey\n+from xmodule.modulestore.django import modulestore\n+\n+from course_dashboard.answers_distribution import get_problem_module, add_ancestors_names_to_problem_module\n+from fun import shared\n+\n+def cleanup_newlines(s):\n+    \"\"\"Makes sure all the newlines in s are representend by \\r only.\"\"\"\n+    return s.replace(\"\\r\\n\",\"\\r\").replace(\"\\n\",\"\\r\")\n+\n+def write_csv(header_row, data_rows, filename, course_id):\n+    \"\"\"write a CSV file from the contents of a datatable.\"\"\"\n+    shared.ensure_directory_exists(settings.ANSWERS_DISTRIBUTION_REPORTS_DIRECTORY, course_id.org, course_id.course)\n+    \n+    path = shared.get_path(settings.ANSWERS_DISTRIBUTION_REPORTS_DIRECTORY,\n+                           course_id.org,\n+                           course_id.course,\n+                           filename)\n+    \n+    path = path.encode('utf-8')\n+    \n+    with open(path, \"wb\") as ofile:\n+        writer = csv.writer(ofile, dialect='excel', quotechar='\"', quoting=csv.QUOTE_ALL)\n+        writer.writerow(header_row)\n+        for datarow in data_rows:\n+            encoded_row = [cleanup_newlines(unicode(s).encode('utf-8')) for s in datarow]\n+            writer.writerow(encoded_row)\n+            \n+def create_header_row(quizz_size):\n+     header_row = ['id', 'gender', 'year_of_birth', 'level_of_education']\n+     \n+     i = 0;\n+     while i < quizz_size:\n+         header_row.append( 'q' + str(i + 1))\n+         i += 1\n+     return header_row\n+\n+problem_types = [\"multiplechoiceresponse\", \"choiceresponse\" ,\"stringresponse\",\n+                 \"optionresponse\", \"numericalresponse\", \"customresponse\"]\n+\n+def create_list_of_question_ids(organisation, course_number, problem_module_id, problem_module_size):\n+     question_ids = []\n+\n+     i = 0;\n+\n+     while i < problem_module_size:\n+          question_ids.append( \"i4x-{}-{}-problem-{}_{}_1\".format(organisation,course_number, problem_module_id, str((i + 2))))\n+          i += 1\n+     return question_ids\n+\n+\n+\n+def get_problem_module_size(problem_module):\n+    \"\"\"\n+    Return the number of problem in the problem_module\n+    \"\"\"\n+    \n+    problem_module_as_xml = ET.fromstring((problem_module.data).encode('utf-8'))\n+    problem_module_size = 0\n+    \n+    for element in problem_module_as_xml.iter():\n+        if element.tag in problem_types:\n+            problem_module_size += 1\n+    return  problem_module_size\n+\n+def generate_answers_distribution_report(_xmodule_instance_args, _entry_id, course_id, _task_input, action_name):\n+    \"\"\"\n+    Main task to generate answer distribution as csv.\n+\n+    Csv structure will be as follow: \n+\n+    'id', 'gender', 'year_of_birth', 'level_of_education', q1,      , q2       , ....\n+     15,     f    ,    1989        ,    m                , choice 1 , choice 2\n+     .\n+     .\n+\n+    \"\"\"\n+    \n+    store = modulestore()    \n+    problem_module = get_problem_module(course_id.to_deprecated_string(), _task_input['problem_module_id'])\n+    add_ancestors_names_to_problem_module(problem_module[0], store)\n+    problem_module_size = get_problem_module_size(problem_module[0])\n+\n+    # the csv will have a header_row (name of each column) and data_rows which is (a list of data_row)\n+    # data_row contain all the answers of a quizz for one student    \n+    header_row = create_header_row(problem_module_size)\n+    data_rows = []\n+    data_row = []","path":"course_dashboard/answers_distribution_reports_manager/tasks.py","position":98,"original_position":98,"commit_id":"072f33fb071b52fc647d42d87d7d3d0b90f99de2","original_commit_id":"072f33fb071b52fc647d42d87d7d3d0b90f99de2","user":{"login":"regisb","id":44319,"avatar_url":"https://avatars.githubusercontent.com/u/44319?v=3","gravatar_id":"","url":"https://api.github.com/users/regisb","html_url":"https://github.com/regisb","followers_url":"https://api.github.com/users/regisb/followers","following_url":"https://api.github.com/users/regisb/following{/other_user}","gists_url":"https://api.github.com/users/regisb/gists{/gist_id}","starred_url":"https://api.github.com/users/regisb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/regisb/subscriptions","organizations_url":"https://api.github.com/users/regisb/orgs","repos_url":"https://api.github.com/users/regisb/repos","events_url":"https://api.github.com/users/regisb/events{/privacy}","received_events_url":"https://api.github.com/users/regisb/received_events","type":"User","site_admin":false},"body":"variable inutile.","created_at":"2015-03-10T14:13:55Z","updated_at":"2015-03-10T14:13:55Z","html_url":"https://github.com/openfun/fun-apps/pull/57#discussion_r26124538","pull_request_url":"https://api.github.com/repos/openfun/fun-apps/pulls/57","_links":{"self":{"href":"https://api.github.com/repos/openfun/fun-apps/pulls/comments/26124538"},"html":{"href":"https://github.com/openfun/fun-apps/pull/57#discussion_r26124538"},"pull_request":{"href":"https://api.github.com/repos/openfun/fun-apps/pulls/57"}}},"pull_request":{"url":"https://api.github.com/repos/openfun/fun-apps/pulls/57","id":30849000,"html_url":"https://github.com/openfun/fun-apps/pull/57","diff_url":"https://github.com/openfun/fun-apps/pull/57.diff","patch_url":"https://github.com/openfun/fun-apps/pull/57.patch","issue_url":"https://api.github.com/repos/openfun/fun-apps/issues/57","number":57,"state":"open","locked":false,"title":"issue1131 Get quizz answers as csv from course dashboard.","user":{"login":"jpaille","id":2971857,"avatar_url":"https://avatars.githubusercontent.com/u/2971857?v=3","gravatar_id":"","url":"https://api.github.com/users/jpaille","html_url":"https://github.com/jpaille","followers_url":"https://api.github.com/users/jpaille/followers","following_url":"https://api.github.com/users/jpaille/following{/other_user}","gists_url":"https://api.github.com/users/jpaille/gists{/gist_id}","starred_url":"https://api.github.com/users/jpaille/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpaille/subscriptions","organizations_url":"https://api.github.com/users/jpaille/orgs","repos_url":"https://api.github.com/users/jpaille/repos","events_url":"https://api.github.com/users/jpaille/events{/privacy}","received_events_url":"https://api.github.com/users/jpaille/received_events","type":"User","site_admin":false},"body":". Possibilité de télécharger l'ensemble des réponses d'un problème sous forme de csv (application answers_distribution_reports_manager)\r\n. Une répartition des réponses pour les questions à choix unique answers_distribution.py","created_at":"2015-03-10T13:19:36Z","updated_at":"2015-03-10T14:13:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openfun/fun-apps/pulls/57/commits","review_comments_url":"https://api.github.com/repos/openfun/fun-apps/pulls/57/comments","review_comment_url":"https://api.github.com/repos/openfun/fun-apps/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openfun/fun-apps/issues/57/comments","statuses_url":"https://api.github.com/repos/openfun/fun-apps/statuses/072f33fb071b52fc647d42d87d7d3d0b90f99de2","head":{"label":"openfun:jpaille/issue1131-get-quizz-results-as-csv","ref":"jpaille/issue1131-get-quizz-results-as-csv","sha":"072f33fb071b52fc647d42d87d7d3d0b90f99de2","user":{"login":"openfun","id":7224891,"avatar_url":"https://avatars.githubusercontent.com/u/7224891?v=3","gravatar_id":"","url":"https://api.github.com/users/openfun","html_url":"https://github.com/openfun","followers_url":"https://api.github.com/users/openfun/followers","following_url":"https://api.github.com/users/openfun/following{/other_user}","gists_url":"https://api.github.com/users/openfun/gists{/gist_id}","starred_url":"https://api.github.com/users/openfun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openfun/subscriptions","organizations_url":"https://api.github.com/users/openfun/orgs","repos_url":"https://api.github.com/users/openfun/repos","events_url":"https://api.github.com/users/openfun/events{/privacy}","received_events_url":"https://api.github.com/users/openfun/received_events","type":"Organization","site_admin":false},"repo":{"id":20556967,"name":"fun-apps","full_name":"openfun/fun-apps","owner":{"login":"openfun","id":7224891,"avatar_url":"https://avatars.githubusercontent.com/u/7224891?v=3","gravatar_id":"","url":"https://api.github.com/users/openfun","html_url":"https://github.com/openfun","followers_url":"https://api.github.com/users/openfun/followers","following_url":"https://api.github.com/users/openfun/following{/other_user}","gists_url":"https://api.github.com/users/openfun/gists{/gist_id}","starred_url":"https://api.github.com/users/openfun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openfun/subscriptions","organizations_url":"https://api.github.com/users/openfun/orgs","repos_url":"https://api.github.com/users/openfun/repos","events_url":"https://api.github.com/users/openfun/events{/privacy}","received_events_url":"https://api.github.com/users/openfun/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openfun/fun-apps","description":"","fork":false,"url":"https://api.github.com/repos/openfun/fun-apps","forks_url":"https://api.github.com/repos/openfun/fun-apps/forks","keys_url":"https://api.github.com/repos/openfun/fun-apps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openfun/fun-apps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openfun/fun-apps/teams","hooks_url":"https://api.github.com/repos/openfun/fun-apps/hooks","issue_events_url":"https://api.github.com/repos/openfun/fun-apps/issues/events{/number}","events_url":"https://api.github.com/repos/openfun/fun-apps/events","assignees_url":"https://api.github.com/repos/openfun/fun-apps/assignees{/user}","branches_url":"https://api.github.com/repos/openfun/fun-apps/branches{/branch}","tags_url":"https://api.github.com/repos/openfun/fun-apps/tags","blobs_url":"https://api.github.com/repos/openfun/fun-apps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openfun/fun-apps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openfun/fun-apps/git/refs{/sha}","trees_url":"https://api.github.com/repos/openfun/fun-apps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openfun/fun-apps/statuses/{sha}","languages_url":"https://api.github.com/repos/openfun/fun-apps/languages","stargazers_url":"https://api.github.com/repos/openfun/fun-apps/stargazers","contributors_url":"https://api.github.com/repos/openfun/fun-apps/contributors","subscribers_url":"https://api.github.com/repos/openfun/fun-apps/subscribers","subscription_url":"https://api.github.com/repos/openfun/fun-apps/subscription","commits_url":"https://api.github.com/repos/openfun/fun-apps/commits{/sha}","git_commits_url":"https://api.github.com/repos/openfun/fun-apps/git/commits{/sha}","comments_url":"https://api.github.com/repos/openfun/fun-apps/comments{/number}","issue_comment_url":"https://api.github.com/repos/openfun/fun-apps/issues/comments{/number}","contents_url":"https://api.github.com/repos/openfun/fun-apps/contents/{+path}","compare_url":"https://api.github.com/repos/openfun/fun-apps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openfun/fun-apps/merges","archive_url":"https://api.github.com/repos/openfun/fun-apps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openfun/fun-apps/downloads","issues_url":"https://api.github.com/repos/openfun/fun-apps/issues{/number}","pulls_url":"https://api.github.com/repos/openfun/fun-apps/pulls{/number}","milestones_url":"https://api.github.com/repos/openfun/fun-apps/milestones{/number}","notifications_url":"https://api.github.com/repos/openfun/fun-apps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openfun/fun-apps/labels{/name}","releases_url":"https://api.github.com/repos/openfun/fun-apps/releases{/id}","created_at":"2014-06-06T08:42:58Z","updated_at":"2015-03-10T13:08:56Z","pushed_at":"2015-03-10T13:13:19Z","git_url":"git://github.com/openfun/fun-apps.git","ssh_url":"git@github.com:openfun/fun-apps.git","clone_url":"https://github.com/openfun/fun-apps.git","svn_url":"https://github.com/openfun/fun-apps","homepage":"","size":10929,"stargazers_count":0,"watchers_count":0,"language":"Gettext Catalog","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":1,"forks":3,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"openfun:master","ref":"master","sha":"b27eeb4bf5ce1035a0162155d12a9cf812e79230","user":{"login":"openfun","id":7224891,"avatar_url":"https://avatars.githubusercontent.com/u/7224891?v=3","gravatar_id":"","url":"https://api.github.com/users/openfun","html_url":"https://github.com/openfun","followers_url":"https://api.github.com/users/openfun/followers","following_url":"https://api.github.com/users/openfun/following{/other_user}","gists_url":"https://api.github.com/users/openfun/gists{/gist_id}","starred_url":"https://api.github.com/users/openfun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openfun/subscriptions","organizations_url":"https://api.github.com/users/openfun/orgs","repos_url":"https://api.github.com/users/openfun/repos","events_url":"https://api.github.com/users/openfun/events{/privacy}","received_events_url":"https://api.github.com/users/openfun/received_events","type":"Organization","site_admin":false},"repo":{"id":20556967,"name":"fun-apps","full_name":"openfun/fun-apps","owner":{"login":"openfun","id":7224891,"avatar_url":"https://avatars.githubusercontent.com/u/7224891?v=3","gravatar_id":"","url":"https://api.github.com/users/openfun","html_url":"https://github.com/openfun","followers_url":"https://api.github.com/users/openfun/followers","following_url":"https://api.github.com/users/openfun/following{/other_user}","gists_url":"https://api.github.com/users/openfun/gists{/gist_id}","starred_url":"https://api.github.com/users/openfun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openfun/subscriptions","organizations_url":"https://api.github.com/users/openfun/orgs","repos_url":"https://api.github.com/users/openfun/repos","events_url":"https://api.github.com/users/openfun/events{/privacy}","received_events_url":"https://api.github.com/users/openfun/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openfun/fun-apps","description":"","fork":false,"url":"https://api.github.com/repos/openfun/fun-apps","forks_url":"https://api.github.com/repos/openfun/fun-apps/forks","keys_url":"https://api.github.com/repos/openfun/fun-apps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openfun/fun-apps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openfun/fun-apps/teams","hooks_url":"https://api.github.com/repos/openfun/fun-apps/hooks","issue_events_url":"https://api.github.com/repos/openfun/fun-apps/issues/events{/number}","events_url":"https://api.github.com/repos/openfun/fun-apps/events","assignees_url":"https://api.github.com/repos/openfun/fun-apps/assignees{/user}","branches_url":"https://api.github.com/repos/openfun/fun-apps/branches{/branch}","tags_url":"https://api.github.com/repos/openfun/fun-apps/tags","blobs_url":"https://api.github.com/repos/openfun/fun-apps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openfun/fun-apps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openfun/fun-apps/git/refs{/sha}","trees_url":"https://api.github.com/repos/openfun/fun-apps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openfun/fun-apps/statuses/{sha}","languages_url":"https://api.github.com/repos/openfun/fun-apps/languages","stargazers_url":"https://api.github.com/repos/openfun/fun-apps/stargazers","contributors_url":"https://api.github.com/repos/openfun/fun-apps/contributors","subscribers_url":"https://api.github.com/repos/openfun/fun-apps/subscribers","subscription_url":"https://api.github.com/repos/openfun/fun-apps/subscription","commits_url":"https://api.github.com/repos/openfun/fun-apps/commits{/sha}","git_commits_url":"https://api.github.com/repos/openfun/fun-apps/git/commits{/sha}","comments_url":"https://api.github.com/repos/openfun/fun-apps/comments{/number}","issue_comment_url":"https://api.github.com/repos/openfun/fun-apps/issues/comments{/number}","contents_url":"https://api.github.com/repos/openfun/fun-apps/contents/{+path}","compare_url":"https://api.github.com/repos/openfun/fun-apps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openfun/fun-apps/merges","archive_url":"https://api.github.com/repos/openfun/fun-apps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openfun/fun-apps/downloads","issues_url":"https://api.github.com/repos/openfun/fun-apps/issues{/number}","pulls_url":"https://api.github.com/repos/openfun/fun-apps/pulls{/number}","milestones_url":"https://api.github.com/repos/openfun/fun-apps/milestones{/number}","notifications_url":"https://api.github.com/repos/openfun/fun-apps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openfun/fun-apps/labels{/name}","releases_url":"https://api.github.com/repos/openfun/fun-apps/releases{/id}","created_at":"2014-06-06T08:42:58Z","updated_at":"2015-03-10T13:08:56Z","pushed_at":"2015-03-10T13:13:19Z","git_url":"git://github.com/openfun/fun-apps.git","ssh_url":"git@github.com:openfun/fun-apps.git","clone_url":"https://github.com/openfun/fun-apps.git","svn_url":"https://github.com/openfun/fun-apps","homepage":"","size":10929,"stargazers_count":0,"watchers_count":0,"language":"Gettext Catalog","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":1,"forks":3,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openfun/fun-apps/pulls/57"},"html":{"href":"https://github.com/openfun/fun-apps/pull/57"},"issue":{"href":"https://api.github.com/repos/openfun/fun-apps/issues/57"},"comments":{"href":"https://api.github.com/repos/openfun/fun-apps/issues/57/comments"},"review_comments":{"href":"https://api.github.com/repos/openfun/fun-apps/pulls/57/comments"},"review_comment":{"href":"https://api.github.com/repos/openfun/fun-apps/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openfun/fun-apps/pulls/57/commits"},"statuses":{"href":"https://api.github.com/repos/openfun/fun-apps/statuses/072f33fb071b52fc647d42d87d7d3d0b90f99de2"}}}}