def get_problem_list(request): """ Get the list of problems that need grading in course request.GET['course_id']. Returns: list of dicts with keys 'location' 'problem_name' 'num_graded' -- number graded 'num_pending' -- number pending in the queue 'min_for_ml' -- minimum needed to make ML model """ if request.method!="GET": error_message="Request needs to be GET." log.error(error_message) return util._error_response(error_message, _INTERFACE_VERSION) course_id=request.GET.get("course_id") if not course_id: error_message="Missing needed tag course_id" log.error(error_message) return util._error_response(error_message, _INTERFACE_VERSION) locations_for_course = [x['location'] for x in list(Submission.objects.filter(course_id=course_id).values('location').distinct())] if len(locations_for_course)==0: error_message="No problems associated with course." log.error(error_message) return util._error_response(error_message, _INTERFACE_VERSION) location_info=[] for location in locations_for_course: problem_name = Submission.objects.filter(location=location)[0].problem_id submissions_pending = staff_grading_util.submissions_pending_instructor(location, state_in=[SubmissionState.waiting_to_be_graded]).count() finished_instructor_graded = staff_grading_util.finished_submissions_graded_by_instructor(location).count() min_scored_for_location=settings.MIN_TO_USE_PEER location_ml_count = Submission.objects.filter(location=location, preferred_grader_type="ML").count() if location_ml_count>0: min_scored_for_location=settings.MIN_TO_USE_ML submissions_required = max([0,min_scored_for_location-finished_instructor_graded]) problem_name_from_location=location.split("://")[1] location_dict={ 'location' : location, 'problem_name' : problem_name, 'problem_name_from_location' : problem_name_from_location, 'num_graded' : finished_instructor_graded, 'num_pending' : submissions_pending, 'num_required' : submissions_required, 'min_for_ml' : settings.MIN_TO_USE_ML, } location_info.append(location_dict) util.log_connection_data() return util._success_response({'problem_list' : location_info}, _INTERFACE_VERSION)
def get_next_submission(request): """ Supports GET request with the following arguments: course_id -- the course for which to return a submission. grader_id -- LMS user_id of the requesting user Returns json dict with the following keys: version: '1' (number) success: bool if success: 'submission_id': a unique identifier for the submission, to be passed back with the grade. 'submission': the submission, rendered as read-only html for grading 'rubric': the rubric, also rendered as html. 'prompt': the question prompt, also rendered as html. 'message': if there was no submission available, but nothing went wrong, there will be a message field. else: 'error': if success is False, will have an error message with more info. } """ if request.method != "GET": raise Http404 course_id = request.GET.get('course_id') grader_id = request.GET.get('grader_id') location = request.GET.get('location') log.debug( "Getting next submission for instructor grading for course: {0}.". format(course_id)) if not (course_id or location) or not grader_id: return util._error_response("required_parameter_missing", _INTERFACE_VERSION) if location: ( found, id ) = staff_grading_util.get_single_instructor_grading_item_for_location( location) # TODO: save the grader id and match it in save_grade to make sure things # are consistent. if not location: (found, id) = staff_grading_util.get_single_instructor_grading_item(course_id) if not found: return util._success_response( {'message': 'No more submissions to grade.'}, _INTERFACE_VERSION) try: submission = Submission.objects.get(id=int(id)) except Submission.DoesNotExist: log.error("Couldn't find submission %s for instructor grading", id) return util._error_response('failed_to_load_submission', _INTERFACE_VERSION, data={'submission_id': id}) #Get error metrics from ml grading, and get into dictionary form to pass down to staff grading view success, ml_error_info = ml_grading_util.get_ml_errors(submission.location) if success: ml_error_message = staff_grading_util.generate_ml_error_message( ml_error_info) else: ml_error_message = ml_error_info ml_error_message = "Machine learning error information: " + ml_error_message if submission.state != 'C': log.error( "Instructor grading got a submission (%s) in an invalid state: ", id, submission.state) return util._error_response('wrong_internal_state', _INTERFACE_VERSION, data={ 'submission_id': id, 'submission_state': submission.state }) num_graded, num_pending = staff_grading_util.count_submissions_graded_and_pending_instructor( submission.location) response = { 'submission_id': id, 'submission': submission.student_response, 'rubric': submission.rubric, 'prompt': submission.prompt, 'max_score': submission.max_score, 'ml_error_info': ml_error_message, 'problem_name': submission.problem_id, 'num_graded': staff_grading_util.finished_submissions_graded_by_instructor( submission.location).count(), 'num_pending': staff_grading_util.submissions_pending_instructor( submission.location, state_in=[SubmissionState.waiting_to_be_graded]).count(), 'min_for_ml': settings.MIN_TO_USE_ML, } util.log_connection_data() log.debug("Sending success response back to instructor grading!") log.debug("Sub id from get next: {0}".format(submission.id)) return util._success_response(response, _INTERFACE_VERSION)
def get_problem_list(request): """ Get the list of problems that need grading in course request.GET['course_id']. Returns: list of dicts with keys 'location' 'problem_name' 'num_graded' -- number graded 'num_pending' -- number pending in the queue 'min_for_ml' -- minimum needed to make ML model """ if request.method != "GET": error_message = "Request needs to be GET." log.error(error_message) return util._error_response(error_message, _INTERFACE_VERSION) course_id = request.GET.get("course_id") if not course_id: error_message = "Missing needed tag course_id" log.error(error_message) return util._error_response(error_message, _INTERFACE_VERSION) locations_for_course = [ x['location'] for x in list( Submission.objects.filter( course_id=course_id).values('location').distinct()) ] if len(locations_for_course) == 0: error_message = "No problems associated with course." log.error(error_message) return util._error_response(error_message, _INTERFACE_VERSION) location_info = [] for location in locations_for_course: problem_name = Submission.objects.filter( location=location)[0].problem_id submissions_pending = staff_grading_util.submissions_pending_instructor( location, state_in=[SubmissionState.waiting_to_be_graded]).count() finished_instructor_graded = staff_grading_util.finished_submissions_graded_by_instructor( location).count() min_scored_for_location = settings.MIN_TO_USE_PEER location_ml_count = Submission.objects.filter( location=location, preferred_grader_type="ML").count() if location_ml_count > 0: min_scored_for_location = settings.MIN_TO_USE_ML submissions_required = max( [0, min_scored_for_location - finished_instructor_graded]) problem_name_from_location = location.split("://")[1] location_dict = { 'location': location, 'problem_name': problem_name, 'problem_name_from_location': problem_name_from_location, 'num_graded': finished_instructor_graded, 'num_pending': submissions_pending, 'num_required': submissions_required, 'min_for_ml': settings.MIN_TO_USE_ML, } location_info.append(location_dict) util.log_connection_data() log.debug(location_info) return util._success_response({'problem_list': location_info}, _INTERFACE_VERSION)
def get_next_submission(request): """ Supports GET request with the following arguments: course_id -- the course for which to return a submission. grader_id -- LMS user_id of the requesting user Returns json dict with the following keys: version: '1' (number) success: bool if success: 'submission_id': a unique identifier for the submission, to be passed back with the grade. 'submission': the submission, rendered as read-only html for grading 'rubric': the rubric, also rendered as html. 'prompt': the question prompt, also rendered as html. 'message': if there was no submission available, but nothing went wrong, there will be a message field. else: 'error': if success is False, will have an error message with more info. } """ if request.method != "GET": raise Http404 course_id = request.GET.get('course_id') grader_id = request.GET.get('grader_id') location = request.GET.get('location') if not (course_id or location) or not grader_id: return util._error_response("required_parameter_missing", _INTERFACE_VERSION) if location: (found, id) = staff_grading_util.get_single_instructor_grading_item_for_location(location) # TODO: save the grader id and match it in save_grade to make sure things # are consistent. if not location: (found, id) = staff_grading_util.get_single_instructor_grading_item(course_id) if not found: return util._success_response({'message': 'No more submissions to grade.'}, _INTERFACE_VERSION) try: submission = Submission.objects.get(id=int(id)) except Submission.DoesNotExist: log.error("Couldn't find submission %s for instructor grading", id) return util._error_response('failed_to_load_submission', _INTERFACE_VERSION, data={'submission_id': id}) #Get error metrics from ml grading, and get into dictionary form to pass down to staff grading view success, ml_error_info=ml_grading_util.get_ml_errors(submission.location) if success: ml_error_message=staff_grading_util.generate_ml_error_message(ml_error_info) else: ml_error_message=ml_error_info ml_error_message="Machine learning error information: " + ml_error_message if submission.state != 'C': log.error("Instructor grading got a submission (%s) in an invalid state: ", id, submission.state) return util._error_response('wrong_internal_state', _INTERFACE_VERSION, data={'submission_id': id, 'submission_state': submission.state}) num_graded, num_pending = staff_grading_util.count_submissions_graded_and_pending_instructor(submission.location) response = {'submission_id': id, 'submission': submission.student_response, 'rubric': submission.rubric, 'prompt': submission.prompt, 'max_score': submission.max_score, 'ml_error_info' : ml_error_message, 'problem_name' : submission.problem_id, 'num_graded' : staff_grading_util.finished_submissions_graded_by_instructor(submission.location).count(), 'num_pending' : staff_grading_util.submissions_pending_instructor(submission.location, state_in=[SubmissionState.waiting_to_be_graded]).count(), 'min_for_ml' : settings.MIN_TO_USE_ML, } util.log_connection_data() return util._success_response(response, _INTERFACE_VERSION)