-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BB-726 Implement generate_report_data for PollBlock and SurveyBlock #50
Conversation
8f46400
to
a7c047e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great start! I've pointed out some issues. Maybe you already thought of some or all of them :)
self.ugettext("Answer ID"): a, | ||
self.ugettext("Answer"): answer | ||
} | ||
yield (user_state.username, report) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will end up creating multiple responses per student, which is not the way to go here. The report generator creates a dict that maps from the username to the report, if it gets multiple reports per username, they will get merged. So this will not work.
All the questions and answers here should be merged into a single report. For instance you could have the key for the question be: 'Question ({})'.format(question_id)
@bradenmacdonald How do you think this should be handled? Do you think it makes sense to enhance the current reporting code to support cases where we have multiple responses for a single user for a single block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xitij2000 Do you mean things like Capa problems that can have multiple questions in a single block? I thought we're handling that already. The capa generate_report_data
code definitely looks like it yields multiple rows per block per student when appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bradenmacdonald I think then we might have a bug because of this code here:
https://github.com/edx/edx-platform/blob/055f7323f7f0c5389aa81dd46935499310b0e258/lms/djangoapps/instructor_task/tasks_helper/grades.py#L673-L678
It's creating a dict keyed on the username, so if it gets two rows with the same username, it will only keep one. I did a quick test and this seems to be the case.
Given that, I think the code @john2x wrote is correct, but we need to fix the report generator. This will also need some additonal thought because it means we now have multiple responses with the same block key and state and I don't know how that will interfere with existing tools. Some people were affected when the state column was removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @xitij2000. You are right about the other answers overwriting the previous ones. This is actually apparent in my example output above (there should've been 6 rows). I missed that.
I can flatten the questions for the Survey report like 'Question ({})'.format(question_id)
for the meantime to fit the current expectations of the report generator. Maybe something like the following (question ids are enjoy
and learn
)?
username,...,Question (enjoy),Answer ID (enjoy),Answer (enjoy),Question (learn),Answer ID (learn),Answer (learn),...
john,...,Are you enjoying the course?,Y,Yes,Do you think you will learn a lot?,M,Maybe,...
Though for the Capa report, there doesn't seem to be question id's that can be used for the header. We could use the question label/text itself for the headers? But that might get too long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How much work will it be to open a fix PR for making the platform's report generator accept multiple entries? Then once we have that PR open we can ask edX + the community if it will break any tooling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's much work since I know exactly what to do. The only issue would be the duplicated state entries.
One option would be to add a checkbox or similar to the UI that lets people switch between raw reports or enhanced reports. If they unselect enhanced reports (default is selected) then we only output the state in old-style reports.
Is it worth posting this in slack? Or perhaps the forum? I'll make a PR first and link to that either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@john2x Yup, that is exactly what I was going for :-) No other places would be affected other than the report, so this is a "safe" change to make.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @xitij2000 :) So just to confirm, we'll keep the Survey report to yield multiple answers per username?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've prepared changes to flatten the survey report
for user_state in user_state_iterator:
if limit_responses and count >= limit_responses:
# End the iterator here
return
# user_state.state={'submissions_count': 1, 'choices': {u'enjoy': u'Y', u'recommend': u'N', u'learn': u'M'}}
choices = user_state.state['choices']
# flatten the multiple questions/answers in a survey into one report row
report = {}
for q, a in choices.items():
question = questions_dict[q]['label']
answer = answers_dict[a]
report.update({
self.ugettext('Question ({question_id})'.format(question_id=q)): question,
self.ugettext('Answer ID ({question_id})'.format(question_id=q)): a,
self.ugettext('Answer ({question_id})'.format(question_id=q)): answer,
self.ugettext('Submissions count ({question_id})'.format(question_id=q)): user_state.state['submissions_count']
})
if report:
count += 1
yield (user_state.username, report)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@john2x Yeah, this will be fixed in the generate method.
d1ab927
to
25729df
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 This is looking good and working as expected. I just have a few minor nits about the code that I'd like to see addressed before this is merged.
- I tested this: tested on devstack
- I read through the code
- [na] I checked for accessibility issues
- [na] Includes documentation
poll/poll.py
Outdated
}) | ||
""" | ||
if limit_responses == 0: | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why this is necessary. It will end with line 813 anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improved the limit_responses
check (both here and in survey report). Removed this block and changed the condition in the loop to check if limit_responses
is not None. Also added tests for limit_responses=0
.
tests/unit/test_xblock_poll.py
Outdated
# each choice of a user gets its own row | ||
# so the first three rows should be edx's choices | ||
self.assertEqual(['edx', 'edx', 'edx'], | ||
[username for username, _ in report_data[:3]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you bump this up to 4 so we get responses for 2 users?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to assert for 2 users
tests/unit/test_xblock_poll.py
Outdated
# each choice of a user gets its own row | ||
# so the first two rows should be edx's choices | ||
self.assertEqual(['edx', 'edx'], | ||
[username for username, _ in report_data[:3]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think the [:3] is a bit distracting here since it's doing nothing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed unnecessary [:3]
poll/poll.py
Outdated
}) | ||
""" | ||
if limit_responses == 0: | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be removed, same comments as above.
poll/poll.py
Outdated
for user_state in user_state_iterator: | ||
# user_state.state={'submissions_count': 1, 'choices': {u'enjoy': u'Y', u'recommend': u'N', u'learn': u'M'}} | ||
choices = user_state.state['choices'] | ||
for q, a in choices.items(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use more descriptive names than q and a, like question_id and answer_id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated variable names
@john2x A couple of general comments:
|
- Remove Question ID and Answer ID from reports - Improve limit_responses check - Increase survey test to check for 4 items instead of 3
a5a905a
to
9198f56
Compare
setup.py
Outdated
@@ -45,7 +45,7 @@ def package_data(pkg, roots): | |||
|
|||
setup( | |||
name='xblock-poll', | |||
version='1.6.3', | |||
version='1.6.4', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could you bump this to 1.7 since it's adding a new feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After bumping it you can squash the commits and merge it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @xitij2000. I've bumped to 1.7.0 and squashed and merged.
See BB-726
Example outputs:
Poll
Survey
TODO