def add_comparisons_for_user(self, assignment, student, with_comments=False, with_self_eval=False): answers = set() for i in range(assignment.total_comparisons_required): comparison = Comparison.create_new_comparison( assignment.id, student.id, False) comparison.completed = True comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2 for comparison_criterion in comparison.comparison_criteria: comparison_criterion.winner = comparison.winner db.session.add(comparison) db.session.commit() self.comparisons.append(comparison) if with_comments: for answer in answers: answer_comment = AnswerCommentFactory( user=student, answer=answer, comment_type=AnswerCommentType.evaluation) self.answer_comments.append(answer_comment) db.session.commit() if with_self_eval: student_answer = next(answer for answer in self.answers if answer.user_id == student.id and answer.assignment_id == assignment.id) if student_answer: self_evaluation = AnswerCommentFactory( user=student, answer=student_answer, comment_type=AnswerCommentType.self_evaluation) self.self_evaluations.append(self_evaluation) db.session.commit() return self
def add_comparisons_for_user(self, assignment, student, with_comments=False, with_self_eval=False): answers = set() for i in range(assignment.total_comparisons_required): comparison = Comparison.create_new_comparison(assignment.id, student.id, False) comparison.completed = True comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2 for comparison_criterion in comparison.comparison_criteria: comparison_criterion.winner = comparison.winner db.session.add(comparison) db.session.commit() self.comparisons.append(comparison) if with_comments: for answer in answers: answer_comment = AnswerCommentFactory( user=student, answer=answer, comment_type=AnswerCommentType.evaluation ) self.answer_comments.append(answer_comment) db.session.commit() if with_self_eval: student_answer = next( answer for answer in self.answers if answer.user_id == student.id and answer.assignment_id == assignment.id ) if student_answer: self_evaluation = AnswerCommentFactory( user=student, answer=student_answer, comment_type=AnswerCommentType.self_evaluation ) self.self_evaluations.append(self_evaluation) db.session.commit() return self
def get(self, course_uuid, assignment_uuid): """ Get (or create if needed) a comparison set for assignment. """ course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) require(READ, assignment, title="Comparisons Unavailable", message="Assignments and their comparisons can only be seen here by those enrolled in the course. Please double-check your enrollment in this course.") require(CREATE, Comparison, title="Comparisons Unavailable", message="Comparisons can only be seen here by those enrolled in the course. Please double-check your enrollment in this course.") restrict_user = not allow(MANAGE, assignment) comparison_count = assignment.completed_comparison_count_for_user(current_user.id) if not assignment.compare_grace: abort(403, title="Comparisons Unavailable", message="Sorry, the comparison deadline has passed. No comparisons can be done after the deadline.") elif not restrict_user and not assignment.educators_can_compare: abort(403, title="Comparisons Unavailable", message="Only students can currently compare answers for this assignment. To change these settings to include instructors and teaching assistants, edit the assignment.") elif restrict_user and comparison_count >= assignment.total_comparisons_required: abort(400, title="Comparisons Completed", message="More comparisons aren't available, since you've finished your comparisons for this assignment. Good job!") # check if user has a comparison they have not completed yet comparison = Comparison.query \ .options(joinedload('comparison_criteria')) \ .filter_by( assignment_id=assignment.id, user_id=current_user.id, completed=False ) \ .first() if comparison: on_comparison_get.send( self, event_name=on_comparison_get.name, user=current_user, course_id=course.id, data=marshal(comparison, dataformat.get_comparison(restrict_user))) else: # if there isn't an incomplete comparison, assign a new one try: comparison = Comparison.create_new_comparison(assignment.id, current_user.id, skip_comparison_examples=allow(MANAGE, assignment)) on_comparison_create.send( self, event_name=on_comparison_create.name, user=current_user, course_id=course.id, data=marshal(comparison, dataformat.get_comparison(restrict_user))) except InsufficientObjectsForPairException: abort(400, title="Comparisons Unavailable", message="Not enough answers are available for you to do comparisons right now. Please check back later for more answers.") except UserComparedAllObjectsException: abort(400, title="Comparisons Unavailable", message="You have compared all the currently available answer pairs. Please check back later for more answers.") except UnknownPairGeneratorException: abort(500, title="Comparisons Unavailable", message="Generating scored pairs failed, this really shouldn't happen.") # get evaluation comments for answers by current user answer_comments = AnswerComment.query \ .join("answer") \ .filter(and_( # both draft and completed comments are allowed AnswerComment.active == True, AnswerComment.comment_type == AnswerCommentType.evaluation, Answer.id.in_([comparison.answer1_id, comparison.answer2_id]), AnswerComment.user_id == current_user.id )) \ .order_by(AnswerComment.draft, AnswerComment.created) \ .all() comparison.answer1_feedback = [c for c in answer_comments if c.answer_id == comparison.answer1_id] comparison.answer2_feedback = [c for c in answer_comments if c.answer_id == comparison.answer2_id] return { 'comparison': marshal(comparison, dataformat.get_comparison(restrict_user, include_answer_author=False, include_score=False, with_feedback=True)), 'current': comparison_count+1 }
def get(self, course_uuid, assignment_uuid): """ Get (or create if needed) a comparison set for assignment. """ course = Course.get_active_by_uuid_or_404(course_uuid) assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid) require( READ, assignment, title="Comparisons Unavailable", message= "Assignments and their comparisons can only be seen here by those enrolled in the course. Please double-check your enrollment in this course." ) require( CREATE, Comparison, title="Comparisons Unavailable", message= "Comparisons can only be seen here by those enrolled in the course. Please double-check your enrollment in this course." ) restrict_user = not allow(MANAGE, assignment) comparison_count = assignment.completed_comparison_count_for_user( current_user.id) if not assignment.compare_grace: abort( 403, title="Comparisons Unavailable", message= "Sorry, the comparison deadline has passed. No comparisons can be done after the deadline." ) elif not restrict_user and not assignment.educators_can_compare: abort( 403, title="Comparisons Unavailable", message= "Only students can currently compare answers for this assignment. To change these settings to include instructors and teaching assistants, edit the assignment." ) elif restrict_user and comparison_count >= assignment.total_comparisons_required: abort( 400, title="Comparisons Completed", message= "More comparisons aren't available, since you've finished your comparisons for this assignment. Good job!" ) # check if user has a comparison they have not completed yet new_pair = False comparison = Comparison.query \ .options(joinedload('comparison_criteria')) \ .filter_by( assignment_id=assignment.id, user_id=current_user.id, completed=False ) \ .first() if comparison: on_comparison_get.send( self, event_name=on_comparison_get.name, user=current_user, course_id=course.id, data=marshal(comparison, dataformat.get_comparison(restrict_user))) else: # if there isn't an incomplete comparison, assign a new one try: comparison = Comparison.create_new_comparison( assignment.id, current_user.id, skip_comparison_examples=allow(MANAGE, assignment)) new_pair = True on_comparison_create.send( self, event_name=on_comparison_create.name, user=current_user, course_id=course.id, data=marshal(comparison, dataformat.get_comparison(restrict_user))) except InsufficientObjectsForPairException: abort( 400, title="Comparisons Unavailable", message= "Not enough answers are available for you to do comparisons right now. Please check back later for more answers." ) except UserComparedAllObjectsException: abort( 400, title="Comparisons Unavailable", message= "You have compared all the currently available answer pairs. Please check back later for more answers." ) except UnknownPairGeneratorException: abort( 500, title="Comparisons Unavailable", message= "Generating scored pairs failed, this really shouldn't happen." ) # get evaluation comments for answers by current user answer_comments = AnswerComment.query \ .join("answer") \ .filter(and_( # both draft and completed comments are allowed AnswerComment.active == True, AnswerComment.comment_type == AnswerCommentType.evaluation, Answer.id.in_([comparison.answer1_id, comparison.answer2_id]), AnswerComment.user_id == current_user.id )) \ .order_by(AnswerComment.draft, AnswerComment.created) \ .all() comparison.answer1_feedback = [ c for c in answer_comments if c.answer_id == comparison.answer1_id ] comparison.answer2_feedback = [ c for c in answer_comments if c.answer_id == comparison.answer2_id ] return { 'comparison': marshal( comparison, dataformat.get_comparison(restrict_user, include_answer_author=False, include_score=False, with_feedback=True)), 'new_pair': new_pair, 'current': comparison_count + 1 }
def _submit_all_possible_comparisons_for_user(self, user_id): example_winner_ids = [] example_loser_ids = [] for comparison_example in self.data.comparisons_examples: if comparison_example.assignment_id == self.assignment.id: comparison = Comparison.create_new_comparison( self.assignment.id, user_id, False) self.assertEqual(comparison.answer1_id, comparison_example.answer1_id) self.assertEqual(comparison.answer2_id, comparison_example.answer2_id) min_id = min([comparison.answer1_id, comparison.answer2_id]) max_id = max([comparison.answer1_id, comparison.answer2_id]) example_winner_ids.append(min_id) example_loser_ids.append(max_id) comparison.completed = True comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2 for comparison_criterion in comparison.comparison_criteria: comparison_criterion.winner = comparison.winner db.session.add(comparison) db.session.commit() # self.login(username) # calculate number of comparisons to do before user has compared all the pairs it can num_eligible_answers = 0 # need to minus one to exclude the logged in user's own answer for answer in self.data.get_student_answers(): if answer.assignment_id == self.assignment.id and answer.user_id != user_id: num_eligible_answers += 1 # n(n-1)/2 possible pairs before all answers have been compared num_possible_comparisons = int(num_eligible_answers * (num_eligible_answers - 1) / 2) winner_ids = [] loser_ids = [] for i in range(num_possible_comparisons): comparison = Comparison.create_new_comparison( self.assignment.id, user_id, False) min_id = min([comparison.answer1_id, comparison.answer2_id]) max_id = max([comparison.answer1_id, comparison.answer2_id]) winner_ids.append(min_id) loser_ids.append(max_id) comparison.completed = True comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2 for comparison_criterion in comparison.comparison_criteria: comparison_criterion.winner = comparison.winner db.session.add(comparison) db.session.commit() Comparison.calculate_scores(self.assignment.id) return { 'comparisons': { 'winners': winner_ids, 'losers': loser_ids }, 'comparison_examples': { 'winners': example_winner_ids, 'losers': example_loser_ids } }