def create_grader_and_rubric(self, sub, scores): grader_dict = { "feedback" : "", "status" : "S", "grader_id" : "1", "grader_type" : "IN", "confidence" : 1, "score" : sum(scores), "submission_id" : sub.id, "errors" : [], 'rubric_scores_complete' : True, 'rubric_scores' : scores } create_and_handle_grader_object(grader_dict)
def create_grader_and_rubric(self, sub, scores): grader_dict = { "feedback": "", "status": "S", "grader_id": "1", "grader_type": "IN", "confidence": 1, "score": sum(scores), "submission_id": sub.id, "errors": [], 'rubric_scores_complete': True, 'rubric_scores': scores } create_and_handle_grader_object(grader_dict)
def save_grade(request): """ Supports POST requests with the following arguments: location: string grader_id: int submission_id: int score: int feedback: string submission_key : string Returns json dict with keys version: int success: bool error: string, present if not success """ if request.method != "POST": raise Http404 post_data = request.POST.dict().copy() for tag in ['location', 'grader_id', 'submission_id', 'submission_key', 'score', 'feedback', 'submission_flagged']: if not tag in post_data: return util._error_response("Cannot find needed key {0} in request.".format(tag), _INTERFACE_VERSION) location = post_data['location'] grader_id = post_data['grader_id'] submission_id = post_data['submission_id'] #Submission key currently unused, but plan to use it for validation in the future. submission_key = post_data['submission_key'] score = post_data['score'] #This is done to ensure that response is properly formatted on the lms side. feedback_dict = post_data['feedback'] rubric_scores_complete = request.POST.get('rubric_scores_complete', False) rubric_scores = request.POST.getlist('rubric_scores', []) is_submission_flagged = request.POST.get('submission_flagged', False) if isinstance(is_submission_flagged, basestring): is_submission_flagged = (is_submission_flagged.lower()=="true") status = GraderStatus.success confidence = 1.0 is_answer_unknown = request.POST.get('answer_unknown', False) if isinstance(is_answer_unknown, basestring): is_answer_unknown = (is_answer_unknown.lower()=="true") if is_answer_unknown: status = GraderStatus.failure confidence = 0.0 try: score = int(score) except ValueError: #Score may not be filled out if answer_unknown or flagged if is_answer_unknown or is_submission_flagged: score = 0 else: return util._error_response("Expected integer score. Got {0}".format(score), _INTERFACE_VERSION) try: sub=Submission.objects.get(id=submission_id) except Exception: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": "Submission id {0} is not valid.".format(submission_id)} ) #Patch to handle rubric scores in the case of "I don't know" or flagging if scores aren't filled out if is_answer_unknown or is_submission_flagged and len(rubric_scores)==0: success, targets=rubric_functions.generate_targets_from_rubric(sub.rubric) rubric_scores = [0 for l in targets] rubric_scores_complete = True success, error_message = grader_util.validate_rubric_scores(rubric_scores, rubric_scores_complete, sub) if not success: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": error_message} ) d = {'submission_id': submission_id, 'score': score, 'feedback': feedback_dict, 'grader_id': grader_id, 'grader_type': 'PE', # Humans always succeed (if they grade at all)... 'status': status, # ...and they're always confident too. 'confidence': confidence, #And they don't make any errors 'errors' : "", 'rubric_scores_complete' : rubric_scores_complete, 'rubric_scores' : rubric_scores, 'is_submission_flagged' : is_submission_flagged, } #Currently not posting back to LMS. Only saving grader object, and letting controller decide when to post back. (success, header) = grader_util.create_and_handle_grader_object(d) if not success: return util._error_response("There was a problem saving the grade. Contact support.", _INTERFACE_VERSION) #xqueue_session=util.xqueue_login() #error,msg = util.post_results_to_xqueue(xqueue_session,json.dumps(header),json.dumps(post_data)) util.log_connection_data() return util._success_response({'msg': "Posted to queue."}, _INTERFACE_VERSION)
def peer_grading(request): """ Temporary peer grading view. Can be removed once real peer grading is wired in. Handles both rendering and AJAX Posts. """ post_data = {} saved = False location = "i4x://MITx/6.002x/problem/OETest" student_id = "2" if request.method == 'POST': post_data = request.POST.dict().copy() for tag in ['score', 'submission_id', 'max_score', 'student_id', 'feedback', 'type']: if not post_data.has_key(tag): return HttpResponse("Failed to find needed key {0}".format(tag)) try: post_data['score'] = int(post_data['score']) post_data['max_score'] = int(post_data['max_score']) post_data['submission_id'] = int(post_data['submission_id']) post_data['student_id'] = post_data['student_id'] post_data['feedback'] = {'feedback' : post_data['feedback']} except Exception: return HttpResponse("Can't parse score into an int.") if post_data['type'] == "calibration": calibration_data = { 'submission_id': post_data['submission_id'], 'score': post_data['score'], 'feedback': post_data['feedback'], 'student_id': student_id, 'location': location, } try: success, data = create_and_save_calibration_record(calibration_data) except Exception: return HttpResponse("Could not create calibration record.") if not success: return HttpResponse(data) return HttpResponse("Calibration record created! Reload for next essay.") elif post_data['type'] == "submission": try: created, header = create_and_handle_grader_object({ 'score': post_data['score'], 'status': GraderStatus.success, 'grader_id': student_id, 'grader_type': "PE", 'confidence': 1, 'submission_id': post_data['submission_id'], 'feedback': post_data['feedback'], 'errors' : "", }) except Exception: return HttpResponse("Cannot create grader object.") return HttpResponse("Submission object created! Reload for next essay.") else: return HttpResponse("Invalid grader type.") if request.method == 'GET': post_data = {} success, data = check_calibration_status(location, student_id) if not success: return HttpResponse(data) calibrated = data['calibrated'] url_base = settings.GRADING_CONTROLLER_INTERFACE['url'] if not url_base.endswith("/"): url_base += "/" if calibrated: found, sub_id = get_single_peer_grading_item(location, student_id) post_data['submission_id'] = sub_id if not found: try: post_data.pop('submission_id') except Exception: return HttpResponse("Could not find submission_id in post_data") return HttpResponse("No available grading. Check back later.") try: sub_id = post_data['submission_id'] sub = Submission.objects.get(id=int(sub_id)) except Exception: try: post_data.pop('submission_id') except Exception: return HttpResponse("Could not find key submission_id in post data.") return HttpResponse("Invalid submission id in session. Cannot find it. Try reloading.") if sub.state in [SubmissionState.finished]: post_data.pop('submission_id') return HttpResponse("Invalid submission id in session. Sub is marked finished. Try reloading.") rendered = render_to_string('instructor_grading.html', { 'score_points': [i for i in xrange(0, sub.max_score + 1)], 'ajax_url': url_base, 'text': sub.student_response, 'location': sub.location, 'prompt': sub.prompt, 'rubric': sub.rubric, 'sub_id': sub.id, 'max_score': sub.max_score, 'type': 'submission', 'student_id': student_id, }) return HttpResponse(rendered) else: success, data = get_calibration_essay(location, student_id) if not success: return HttpResponse(data) rendered = render_to_string("instructor_grading.html", { 'score_points': [i for i in xrange(0, data['max_score'] + 1)], 'ajax_url': url_base, 'text': data['student_response'], 'location': location, 'prompt': data['prompt'], 'rubric': data['rubric'], 'sub_id': data['submission_id'], 'max_score': data['max_score'], 'type': 'calibration', 'student_id': student_id, }) return HttpResponse(rendered)
def save_grade(request): """ Supports POST requests with the following arguments: course_id: int grader_id: int submission_id: int score: int feedback: string Returns json dict with keys version: int success: bool error: string, present if not success """ if request.method != "POST": return util._error_response("Request needs to be GET", _INTERFACE_VERSION) course_id = request.POST.get('course_id') grader_id = request.POST.get('grader_id') submission_id = request.POST.get('submission_id') score = request.POST.get('score') feedback = request.POST.get('feedback') skipped = request.POST.get('skipped')=="True" rubric_scores_complete = request.POST.get('rubric_scores_complete', False) rubric_scores = request.POST.getlist('rubric_scores', []) is_submission_flagged = request.POST.get('submission_flagged', False) if isinstance(is_submission_flagged, basestring): is_submission_flagged = is_submission_flagged.lower() == 'true' if (# These have to be truthy not (course_id and grader_id and submission_id) or # These have to be non-None score is None or feedback is None): return util._error_response("required_parameter_missing", _INTERFACE_VERSION) if skipped: success, sub = staff_grading_util.set_instructor_grading_item_back_to_preferred_grader(submission_id) if not success: return util._error_response(sub, _INTERFACE_VERSION) return util._success_response({}, _INTERFACE_VERSION) try: score = int(score) except ValueError: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": "Expected integer score. Got {0}".format(score)}) try: sub=Submission.objects.get(id=submission_id) except Exception: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": "Submission id {0} is not valid.".format(submission_id)} ) first_sub_for_location=Submission.objects.filter(location=sub.location).order_by('date_created')[0] rubric= first_sub_for_location.rubric rubric_success, parsed_rubric = rubric_functions.parse_rubric(rubric) if rubric_success: success, error_message = grader_util.validate_rubric_scores(rubric_scores, rubric_scores_complete, sub) if not success: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": error_message} ) d = {'submission_id': submission_id, 'score': score, 'feedback': feedback, 'grader_id': grader_id, 'grader_type': 'IN', # Humans always succeed (if they grade at all)... 'status': GraderStatus.success, # ...and they're always confident too. 'confidence': 1.0, #And they don't make errors 'errors' : "", 'rubric_scores_complete' : rubric_scores_complete, 'rubric_scores' : rubric_scores, 'is_submission_flagged' : is_submission_flagged, } success, header = grader_util.create_and_handle_grader_object(d) if not success: return util._error_response("grade_save_error", _INTERFACE_VERSION, data={'msg': 'Internal error'}) util.log_connection_data() return util._success_response({}, _INTERFACE_VERSION)
def save_grade(request): """ Supports POST requests with the following arguments: course_id: int grader_id: int submission_id: int score: int feedback: string Returns json dict with keys version: int success: bool error: string, present if not success """ if request.method != "POST": return util._error_response("Request needs to be GET", _INTERFACE_VERSION) course_id = request.POST.get('course_id') grader_id = request.POST.get('grader_id') submission_id = request.POST.get('submission_id') score = request.POST.get('score') feedback = request.POST.get('feedback') skipped = request.POST.get('skipped') == "True" rubric_scores_complete = request.POST.get('rubric_scores_complete', False) rubric_scores = request.POST.getlist('rubric_scores', []) is_submission_flagged = request.POST.get('submission_flagged', False) if isinstance(is_submission_flagged, basestring): is_submission_flagged = is_submission_flagged.lower() == 'true' if ( # These have to be truthy not (course_id and grader_id and submission_id) or # These have to be non-None score is None or feedback is None): return util._error_response("required_parameter_missing", _INTERFACE_VERSION) if skipped: log.debug(submission_id) success, sub = staff_grading_util.set_instructor_grading_item_back_to_ml( submission_id) if not success: return util._error_response(sub, _INTERFACE_VERSION) return util._success_response({}, _INTERFACE_VERSION) try: score = int(score) except ValueError: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": "Expected integer score. Got {0}".format(score)}) try: sub = Submission.objects.get(id=submission_id) except: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={ "msg": "Submission id {0} is not valid.".format(submission_id) }) first_sub_for_location = Submission.objects.filter( location=sub.location).order_by('date_created')[0] rubric = first_sub_for_location.rubric rubric_success, parsed_rubric = rubric_functions.parse_rubric(rubric) if rubric_success: success, error_message = grader_util.validate_rubric_scores( rubric_scores, rubric_scores_complete, sub) if not success: return util._error_response("grade_save_error", _INTERFACE_VERSION, data={"msg": error_message}) d = { 'submission_id': submission_id, 'score': score, 'feedback': feedback, 'grader_id': grader_id, 'grader_type': 'IN', # Humans always succeed (if they grade at all)... 'status': GraderStatus.success, # ...and they're always confident too. 'confidence': 1.0, #And they don't make errors 'errors': "", 'rubric_scores_complete': rubric_scores_complete, 'rubric_scores': rubric_scores, 'is_submission_flagged': is_submission_flagged, } success, header = grader_util.create_and_handle_grader_object(d) if not success: return util._error_response("grade_save_error", _INTERFACE_VERSION, data={'msg': 'Internal error'}) util.log_connection_data() return util._success_response({}, _INTERFACE_VERSION)
def peer_grading(request): """ Temporary peer grading view. Can be removed once real peer grading is wired in. Handles both rendering and AJAX Posts. """ post_data = {} saved = False location = "i4x://MITx/6.002x/problem/OETest" student_id = "2" if request.method == 'POST': post_data = request.POST.dict().copy() for tag in [ 'score', 'submission_id', 'max_score', 'student_id', 'feedback', 'type' ]: if not post_data.has_key(tag): return HttpResponse( "Failed to find needed key {0}".format(tag)) try: post_data['score'] = int(post_data['score']) post_data['max_score'] = int(post_data['max_score']) post_data['submission_id'] = int(post_data['submission_id']) post_data['student_id'] = post_data['student_id'] post_data['feedback'] = {'feedback': post_data['feedback']} except: return HttpResponse("Can't parse score into an int.") if post_data['type'] == "calibration": calibration_data = { 'submission_id': post_data['submission_id'], 'score': post_data['score'], 'feedback': post_data['feedback'], 'student_id': student_id, 'location': location, } try: success, data = create_and_save_calibration_record( calibration_data) except: return HttpResponse("Could not create calibration record.") if not success: return HttpResponse(data) return HttpResponse( "Calibration record created! Reload for next essay.") elif post_data['type'] == "submission": try: created, header = create_and_handle_grader_object({ 'score': post_data['score'], 'status': GraderStatus.success, 'grader_id': student_id, 'grader_type': "PE", 'confidence': 1, 'submission_id': post_data['submission_id'], 'feedback': post_data['feedback'], 'errors': "", }) except: return HttpResponse("Cannot create grader object.") return HttpResponse( "Submission object created! Reload for next essay.") else: return HttpResponse("Invalid grader type.") if request.method == 'GET': post_data = {} success, data = check_calibration_status(location, student_id) if not success: return HttpResponse(data) calibrated = data['calibrated'] url_base = settings.GRADING_CONTROLLER_INTERFACE['url'] if not url_base.endswith("/"): url_base += "/" if calibrated: found, sub_id = get_single_peer_grading_item(location, student_id) post_data['submission_id'] = sub_id if not found: try: post_data.pop('submission_id') except: return HttpResponse( "Could not find submission_id in post_data") return HttpResponse("No available grading. Check back later.") try: sub_id = post_data['submission_id'] sub = Submission.objects.get(id=int(sub_id)) except: try: post_data.pop('submission_id') except: return HttpResponse( "Could not find key submission_id in post data.") return HttpResponse( "Invalid submission id in session. Cannot find it. Try reloading." ) if sub.state in [SubmissionState.finished]: post_data.pop('submission_id') return HttpResponse( "Invalid submission id in session. Sub is marked finished. Try reloading." ) rendered = render_to_string( 'instructor_grading.html', { 'score_points': [i for i in xrange(0, sub.max_score + 1)], 'ajax_url': url_base, 'text': sub.student_response, 'location': sub.location, 'prompt': sub.prompt, 'rubric': sub.rubric, 'sub_id': sub.id, 'max_score': sub.max_score, 'type': 'submission', 'student_id': student_id, }) return HttpResponse(rendered) else: success, data = get_calibration_essay(location, student_id) if not success: return HttpResponse(data) rendered = render_to_string( "instructor_grading.html", { 'score_points': [i for i in xrange(0, data['max_score'] + 1)], 'ajax_url': url_base, 'text': data['student_response'], 'location': location, 'prompt': data['prompt'], 'rubric': data['rubric'], 'sub_id': data['submission_id'], 'max_score': data['max_score'], 'type': 'calibration', 'student_id': student_id, }) return HttpResponse(rendered)
def save_grade(request): """ Supports POST requests with the following arguments: location: string grader_id: int submission_id: int score: int feedback: string submission_key : string Returns json dict with keys version: int success: bool error: string, present if not success """ if request.method != "POST": raise Http404 post_data = request.POST.dict().copy() log.debug(post_data) for tag in [ 'location', 'grader_id', 'submission_id', 'submission_key', 'score', 'feedback', 'submission_flagged' ]: if not tag in post_data: return util._error_response( "Cannot find needed key {0} in request.".format(tag), _INTERFACE_VERSION) location = post_data['location'] grader_id = post_data['grader_id'] submission_id = post_data['submission_id'] #Submission key currently unused, but plan to use it for validation in the future. submission_key = post_data['submission_key'] score = post_data['score'] #This is done to ensure that response is properly formatted on the lms side. feedback_dict = post_data['feedback'] rubric_scores_complete = request.POST.get('rubric_scores_complete', False) rubric_scores = request.POST.getlist('rubric_scores', []) is_submission_flagged = request.POST.get('submission_flagged', False) if isinstance(is_submission_flagged, basestring): is_submission_flagged = (is_submission_flagged.lower() == "true") status = GraderStatus.success confidence = 1.0 is_answer_unknown = request.POST.get('answer_unknown', False) if isinstance(is_answer_unknown, basestring): is_answer_unknown = (is_answer_unknown.lower() == "true") if is_answer_unknown: status = GraderStatus.failure confidence = 0.0 try: score = int(score) except ValueError: return util._error_response( "Expected integer score. Got {0}".format(score), _INTERFACE_VERSION) try: sub = Submission.objects.get(id=submission_id) except: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={ "msg": "Submission id {0} is not valid.".format(submission_id) }) success, error_message = grader_util.validate_rubric_scores( rubric_scores, rubric_scores_complete, sub) if not success: return util._error_response("grade_save_error", _INTERFACE_VERSION, data={"msg": error_message}) d = { 'submission_id': submission_id, 'score': score, 'feedback': feedback_dict, 'grader_id': grader_id, 'grader_type': 'PE', # Humans always succeed (if they grade at all)... 'status': status, # ...and they're always confident too. 'confidence': confidence, #And they don't make any errors 'errors': "", 'rubric_scores_complete': rubric_scores_complete, 'rubric_scores': rubric_scores, 'is_submission_flagged': is_submission_flagged, } #Currently not posting back to LMS. Only saving grader object, and letting controller decide when to post back. (success, header) = grader_util.create_and_handle_grader_object(d) if not success: return util._error_response( "There was a problem saving the grade. Contact support.", _INTERFACE_VERSION) #xqueue_session=util.xqueue_login() #error,msg = util.post_results_to_xqueue(xqueue_session,json.dumps(header),json.dumps(post_data)) util.log_connection_data() return util._success_response({'msg': "Posted to queue."}, _INTERFACE_VERSION)
def save_grade(request): """ Supports POST requests with the following arguments: location: string grader_id: int submission_id: int score: int feedback: string submission_key : string Returns json dict with keys version: int success: bool error: string, present if not success """ if request.method != "POST": raise Http404 post_data = request.POST.dict().copy() log.debug(post_data) for tag in ["location", "grader_id", "submission_id", "submission_key", "score", "feedback", "submission_flagged"]: if not tag in post_data: return util._error_response("Cannot find needed key {0} in request.".format(tag), _INTERFACE_VERSION) location = post_data["location"] grader_id = post_data["grader_id"] submission_id = post_data["submission_id"] # Submission key currently unused, but plan to use it for validation in the future. submission_key = post_data["submission_key"] score = post_data["score"] # This is done to ensure that response is properly formatted on the lms side. feedback_dict = post_data["feedback"] rubric_scores_complete = request.POST.get("rubric_scores_complete", False) rubric_scores = request.POST.getlist("rubric_scores", []) is_submission_flagged = request.POST.get("submission_flagged", False) if isinstance(is_submission_flagged, basestring): is_submission_flagged = is_submission_flagged.lower() == "true" status = GraderStatus.success confidence = 1.0 is_answer_unknown = request.POST.get("answer_unknown", False) if isinstance(is_answer_unknown, basestring): is_answer_unknown = is_answer_unknown.lower() == "true" if is_answer_unknown: status = GraderStatus.failure confidence = 0.0 try: score = int(score) except ValueError: return util._error_response("Expected integer score. Got {0}".format(score), _INTERFACE_VERSION) try: sub = Submission.objects.get(id=submission_id) except: return util._error_response( "grade_save_error", _INTERFACE_VERSION, data={"msg": "Submission id {0} is not valid.".format(submission_id)}, ) success, error_message = grader_util.validate_rubric_scores(rubric_scores, rubric_scores_complete, sub) if not success: return util._error_response("grade_save_error", _INTERFACE_VERSION, data={"msg": error_message}) d = { "submission_id": submission_id, "score": score, "feedback": feedback_dict, "grader_id": grader_id, "grader_type": "PE", # Humans always succeed (if they grade at all)... "status": status, # ...and they're always confident too. "confidence": confidence, # And they don't make any errors "errors": "", "rubric_scores_complete": rubric_scores_complete, "rubric_scores": rubric_scores, "is_submission_flagged": is_submission_flagged, } # Currently not posting back to LMS. Only saving grader object, and letting controller decide when to post back. (success, header) = grader_util.create_and_handle_grader_object(d) if not success: return util._error_response("There was a problem saving the grade. Contact support.", _INTERFACE_VERSION) # xqueue_session=util.xqueue_login() # error,msg = util.post_results_to_xqueue(xqueue_session,json.dumps(header),json.dumps(post_data)) util.log_connection_data() return util._success_response({"msg": "Posted to queue."}, _INTERFACE_VERSION)