-
Notifications
You must be signed in to change notification settings - Fork 78
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
Programming Question Audit Trail #7595
base: master
Are you sure you want to change the base?
Changes from all commits
8f2652b
03b021a
90f4fc9
f7757d9
fbc1a33
fcc4891
a1951eb
ce47b56
eef5da2
e5d1afa
76a2afd
c5da986
9e408e8
a1b387f
dd0c028
9d2fd49
e36e247
1e43e48
063868b
9e7a7e4
ef6c7ce
230adba
3e31863
2d65d34
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,45 +2,64 @@ | |
class Course::Statistics::AnswersController < Course::Statistics::Controller | ||
helper Course::Assessment::Submission::SubmissionsHelper.name.sub(/Helper$/, '') | ||
|
||
MAX_ANSWERS_COUNT = 10 | ||
def latest_answer | ||
@answer = Course::Assessment::Answer.find(answer_params[:id]) | ||
@submission = @answer.submission | ||
@question = @answer.question | ||
@assessment = @submission.assessment | ||
|
||
submission_id = @answer.submission_id | ||
question_id = @answer.question_id | ||
|
||
def question_answer_details | ||
@question_index = question_index(question_id) | ||
|
||
@submission_question = Course::Assessment::SubmissionQuestion. | ||
where(submission_id: submission_id, question_id: question_id). | ||
includes(actable: { files: { annotations: | ||
{ discussion_topic: { posts: :codaveri_feedback } } } }, | ||
discussion_topic: { posts: :codaveri_feedback }).first | ||
end | ||
|
||
def attempts | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. similarly why is this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Attempt aligns with the vocab used in frontend, since we have never exposed the concept of "answer" to users |
||
@answer = Course::Assessment::Answer.find(answer_params[:id]) | ||
@submission = @answer.submission | ||
@question = @answer.question | ||
@assessment = @submission.assessment | ||
|
||
submission_id = @answer.submission_id | ||
question_id = @answer.question_id | ||
|
||
@question_index = question_index(question_id) | ||
|
||
@submission_question = Course::Assessment::SubmissionQuestion. | ||
where(submission_id: @answer.submission_id, question_id: @answer.question_id). | ||
where(submission_id: submission_id, question_id: question_id). | ||
includes(actable: { files: { annotations: | ||
{ discussion_topic: { posts: :codaveri_feedback } } } }, | ||
discussion_topic: { posts: :codaveri_feedback }).first | ||
|
||
fetch_all_answers(@answer.submission_id, @answer.question_id) | ||
fetch_all_answers(submission_id, question_id, answer_params[:limit].to_i) | ||
fetch_all_actable_questions(@question) | ||
end | ||
|
||
def all_answers | ||
def all_attempts | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar comment, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Attempt aligns with the vocab used in frontend, since we have never exposed the concept of "answer" to users |
||
@submission_question = Course::Assessment::SubmissionQuestion.find(submission_question_params[:id]) | ||
submission_id = @submission_question.submission_id | ||
@submission = Course::Assessment::Submission.find(submission_id) | ||
@submission = @submission_question.submission | ||
@question = @submission_question.question | ||
@assessment = @submission.assessment | ||
|
||
submission_id = @submission_question.submission_id | ||
question_id = @submission_question.question_id | ||
@question = Course::Assessment::Question.find(question_id) | ||
@assessment = @submission.assessment | ||
|
||
@submission_question = Course::Assessment::SubmissionQuestion. | ||
where(submission_id: submission_id, question_id: question_id). | ||
includes({ discussion_topic: { posts: :codaveri_feedback } }).first | ||
@question_index = question_index(question_id) | ||
@all_answers = Course::Assessment::Answer. | ||
unscope(:order). | ||
order(:created_at). | ||
where(submission_id: submission_id, question_id: question_id) | ||
|
||
fetch_all_answers(submission_id, question_id, -1) | ||
fetch_all_actable_questions(@question) | ||
end | ||
|
||
private | ||
|
||
def answer_params | ||
params.permit(:id) | ||
params.permit(:id, :limit) | ||
end | ||
|
||
def submission_question_params | ||
|
@@ -56,14 +75,36 @@ | |
question_ids.index(question_id) | ||
end | ||
|
||
def fetch_all_answers(submission_id, question_id) | ||
answers = Course::Assessment::Answer. | ||
unscope(:order). | ||
order(created_at: :desc). | ||
where(submission_id: submission_id, question_id: question_id) | ||
def fetch_all_answers(submission_id, question_id, limit) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
@all_answers = if limit == -1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok I see you've updated the query to adjust the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
Course::Assessment::Answer. | ||
unscope(:order). | ||
order(:submitted_at). | ||
where(submission_id: submission_id, question_id: question_id) | ||
else | ||
Course::Assessment::Answer. | ||
unscope(:order). | ||
order(:submitted_at). | ||
where(submission_id: submission_id, question_id: question_id). | ||
limit(limit) | ||
end | ||
end | ||
|
||
def fetch_all_actable_questions(question) | ||
unless versioned_question?(question) | ||
@all_actable_questions = [question.actable] | ||
return | ||
end | ||
|
||
question = question.actable | ||
@all_actable_questions = [question] | ||
while question.parent | ||
@all_actable_questions << question.parent | ||
question = question.parent | ||
end | ||
end | ||
|
||
current_answer = answers.find(&:current_answer?) | ||
@all_answers = answers.where(current_answer: false).limit(MAX_ANSWERS_COUNT - 1).to_a.reverse | ||
@all_answers.unshift(current_answer) | ||
def versioned_question?(question) | ||
question.actable.is_a?(Course::Assessment::Question::Programming) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# frozen_string_literal: true | ||
|
||
module Course::Statistics::AnswersHelper | ||
def get_historical_auto_gradings(programming_auto_grading) | ||
historical = [] | ||
current = programming_auto_grading | ||
|
||
while current&.parent_id | ||
parent = Course::Assessment::Answer::ProgrammingAutoGrading.find_by(id: current.parent_id) | ||
historical.unshift(parent) if parent | ||
current = parent | ||
end | ||
|
||
historical | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
# frozen_string_literal: true | ||
json.language question.language.name | ||
json.fileSubmission question.multiple_file_submission | ||
|
||
json.memoryLimit question.memory_limit if question.memory_limit | ||
json.timeLimit question.time_limit if question.time_limit | ||
json.attemptLimit question.attempt_limit if question.attempt_limit | ||
|
||
json.fileSubmission question.multiple_file_submission? | ||
|
||
json.autogradable question.auto_gradable? | ||
json.isCodaveri question.is_codaveri | ||
json.liveFeedbackEnabled question.live_feedback_enabled | ||
|
||
json.isCodaveri question.is_codaveri? | ||
json.liveFeedbackEnabled question.live_feedback_enabled? | ||
Comment on lines
+12
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason why you want to explicitly add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically within the codebase and in ruby booleans are all decorated with |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# frozen_string_literal: true | ||
|
||
json.allQuestions @all_actable_questions do |question| | ||
json.id question.id | ||
json.title @question.title | ||
json.maximumGrade @question.maximum_grade | ||
json.description format_ckeditor_rich_text(@question.description) | ||
json.type @question.question_type | ||
json.questionNumber @question_index + 1 | ||
|
||
json.partial! question, question: question, can_grade: false, answer: @all_answers.first | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# frozen_string_literal: true | ||
|
||
json.partial! 'all_questions' | ||
|
||
json.allAnswers @all_answers do |answer| | ||
json.partial! 'answer', answer: answer, question: @question | ||
end | ||
|
||
posts = @submission_question.discussion_topic.posts | ||
|
||
json.comments posts do |post| | ||
json.partial! post, post: post if post.published? | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# frozen_string_literal: true | ||
question = @question.specific | ||
|
||
# If a non current_answer is being loaded, use it instead of loading the last_attempt. | ||
is_current_answer = answer.current_answer? | ||
latest_answer = last_attempt(answer) | ||
attempt = is_current_answer ? latest_answer : answer | ||
auto_grading = attempt&.auto_grading&.specific | ||
|
||
json.fields do | ||
json.questionId answer.question_id | ||
json.id answer.acting_as.id | ||
json.files_attributes answer.files do |file| | ||
json.(file, :id, :filename) | ||
json.content file.content | ||
json.highlightedContent highlight_code_block(file.content, question.language) | ||
end | ||
end | ||
|
||
can_read_tests = can?(:read_tests, @submission) | ||
show_private = can_read_tests || (@submission.published? && @assessment.show_private?) | ||
show_evaluation = can_read_tests || (@submission.published? && @assessment.show_evaluation?) | ||
|
||
test_cases_by_type = question.test_cases_by_type | ||
test_cases_and_results = get_test_cases_and_results(test_cases_by_type, auto_grading) | ||
|
||
show_stdout_and_stderr = (can_read_tests || current_course.show_stdout_and_stderr) && | ||
auto_grading && auto_grading&.exit_code != 0 | ||
|
||
displayed_test_case_types = ['public_test'] | ||
displayed_test_case_types << 'private_test' if show_private | ||
displayed_test_case_types << 'evaluation_test' if show_evaluation | ||
|
||
historical_auto_gradings = get_historical_auto_gradings(auto_grading) | ||
|
||
json.testCases (historical_auto_gradings + [auto_grading]).each do |ag| | ||
next if ag.nil? # To account for autogradings with no test results (programming with no autograding) | ||
|
||
question = ag.test_results.first.test_case.question | ||
test_cases_by_type = question.test_cases_by_type | ||
test_cases_and_results = get_test_cases_and_results(test_cases_by_type, ag) | ||
|
||
json.questionId question.id | ||
displayed_test_case_types.each do |test_case_type| | ||
show_public = (test_case_type == 'public_test') && current_course.show_public_test_cases_output | ||
show_testcase_outputs = can_read_tests || show_public | ||
json.set! test_case_type do | ||
if test_cases_and_results[test_case_type].present? | ||
json.array! test_cases_and_results[test_case_type] do |test_case, test_result| | ||
json.identifier test_case.identifier if can_read_tests | ||
json.expression test_case.expression | ||
json.expected test_case.expected | ||
if test_result | ||
json.output get_output(test_result) if show_testcase_outputs | ||
json.passed test_result.passed? | ||
end | ||
end | ||
|
||
end | ||
end | ||
json.(ag, :stdout, :stderr) if show_stdout_and_stderr | ||
end | ||
end | ||
|
||
if answer.codaveri_feedback_job_id && question.is_codaveri | ||
codaveri_job = answer.codaveri_feedback_job | ||
json.codaveriFeedback do | ||
json.jobId answer.codaveri_feedback_job_id | ||
json.jobStatus codaveri_job.status | ||
json.jobUrl job_path(codaveri_job) if codaveri_job.status == 'submitted' | ||
json.errorMessage codaveri_job.error['message'] if codaveri_job.error | ||
end | ||
end |
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.
If you're rearranging items, please squash the commit with the respective commit?
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.
Done