def submit_response(self, stuid, responses): from queries import get_peer_tasks_for_grader, get_self_tasks_for_student self.set_metadata() if pdt_now() <= self.homework.due_date: # helper function that validates and then updates a task def check_and_update_task(task): if task.grader != stuid: raise Exception("You are not authorized to grade this response.") try: assert(0 <= float(responses[2*i]) <= task.question.points) except: raise Exception("Please enter a score between %f and %f." % (0, task.question.points)) if not responses[2*i+1].strip(): raise Exception("Please enter comments for all responses.") task.time = pdt_now() task.score = responses[2*i] task.comments = responses[2*i+1] return task i = 0 score = 0. # peer tasks should be first while i < len(self.peer_pts): tasks = get_peer_tasks_for_grader(self.question_id, stuid) task = check_and_update_task(tasks[i]) if task.comments is not None: score += self.peer_pts[i] i += 1 # then we have self tasks if self.self_pts is not None: tasks = get_self_tasks_for_student(self.question_id, stuid) if tasks: task = check_and_update_task(tasks[0]) if task.comments is not None: score += self.self_pts comments = "Watch this space for your peers' judgment of your feedback. " if self.rate_pts: comments += "Your peers' judgment is worth %f points, so you cannot earn all %s points yet." % (self.rate_pts, self.points) session.commit() return { 'locked': (pdt_now() > self.homework.due_date), 'submission': QuestionResponse( time=pdt_now(), score=score, comments=comments ) } else: raise Exception("The deadline for submitting this homework has passed.")
def get_last_due_homework(): """Returns the last homework that was due""" now = pdt_now() hws = reversed(session.query(Homework).order_by(Homework.due_date).all()) for hw in hws: if hw.due_date < now: return hw
def load_response(self, user): from queries import get_last_question_response last_submission = get_last_question_response(self.id, user.stuid) out = { 'submission': self.delay_feedback(last_submission), 'locked': self.check_if_locked(last_submission), } if user.type == "admin" or (user.type == "student" and pdt_now() > self.homework.due_date): out['solution'] = [item.solution for item in self.items] return out
def delay_feedback(self, submission): if submission is None or submission.score is None: return submission due_date = submission.question.homework.due_date submission.item_responses # instantiate item responses before we detach object from session make_transient(submission) # detaches SQLAlchemy object from session now = pdt_now() time_available = min(submission.time + timedelta(minutes=30), due_date) if now < time_available: submission.score = None submission.comments = '''Feedback on your submission will be available in %s minutes, at %s. Please refresh the page at that time to view it.''' % (1 + (time_available - now).seconds // 60, time_available.strftime("%H:%M")) return submission
def load_response(self, user): from queries import get_peer_tasks_for_grader, get_self_tasks_for_student self.set_metadata() item_responses = [] score = 0. time = None comment = "" # get peer tasks if len(self.peer_pts): tasks = get_peer_tasks_for_grader(self.question_id, user.stuid) ratings = [] for i, task in enumerate(tasks): # each review is a score + response; we represent each review as two items item_responses.extend([ItemResponse(response=task.score), ItemResponse(response=task.comments)]) if task.rating is not None: ratings.append(task.rating) if task.comments is not None: score += self.peer_pts[i] time = task.time if len(ratings) > 1: median = sorted(ratings)[len(ratings) // 2] - 1. score += self.rate_pts * median / 3. comment = "%d peers have responded to your feedback. " % len(ratings) if median == 3: comment += "They were satisfied overall with the quality of your feedback." elif median == 2: comment += "Your feedback was good, but some felt that it could have been better." elif median <= 1: comment += "Your peers found your feedback unsatisfactory. Please see a member of the course staff to discuss strategies to improve." elif score: comment = "Watch this space for your peers' rating of your feedback. " if self.rate_pts: comment += "Your peers' ratings count for %s points, so you cannot earn all %s points yet." % (self.rate_pts, self.points) # get self tasks if self.self_pts is not None: # there should really only be one task, but.... tasks = get_self_tasks_for_student(self.question_id, user.stuid) if tasks: item_responses.extend([ItemResponse(response=tasks[0].score), ItemResponse(response=tasks[0].comments)]) if tasks[0].comments is not None: score += self.self_pts time = tasks[0].time return { "locked": (pdt_now() > self.homework.due_date), "submission": QuestionResponse( item_responses=item_responses, score=score, comments=comment, time=time ) }
def hw_list(): user = validate_user() homeworks = get_homework() categories = session.query(Category).all() to_do = update_hw_grades(user, homeworks) session.commit() return render_template("list.html", homeworks=homeworks, categories=categories, user=user, options=options, current_time=pdt_now(), to_do=to_do)
def auto_assign(): """Assignment for STATS 60, spring quarter""" # Determine the due date, which the next Tuesday at 5 PM. this_time = pdt_now() while this_time.weekday() != 1: # 0 == Monday, 1 == Tuesday... this_time += timedelta(days=1) due_date = datetime(this_time.year, this_time.month, this_time.day, 17, 0) # Determine the homeworks to assign, which are the two last things due hw_a, hw_b = get_last_two_due_homeworks() print assign_tasks(hw_a.id, due_date, send_emails=False) print assign_tasks(hw_b.id, due_date, send_emails=True)
def check_and_update_task(task): if task.grader != stuid: raise Exception("You are not authorized to grade this response.") try: assert(0 <= float(responses[2*i]) <= task.question.points) except: raise Exception("Please enter a score between %f and %f." % (0, task.question.points)) if not responses[2*i+1].strip(): raise Exception("Please enter comments for all responses.") task.time = pdt_now() task.score = responses[2*i] task.comments = responses[2*i+1] return task
def hw(): user = validate_user() hw_id = request.args.get("id") hw = get_homework(hw_id) question_list = get_all_regular_questions() if user.type == "admin" else None if user.type == "admin": return render_template("hw.html", hw_list=get_homework(), homework=hw, user=user, question_list=question_list, options=options) else: if hw.start_date and hw.start_date > pdt_now(): raise Exception("This homework has not yet been released.") return render_template("hw.html", homework=hw, user=user, question_list=question_list, options=options)
def hw(): user = validate_user() hw_id = request.args.get("id") hw = get_homework(hw_id) question_list = get_all_regular_questions( ) if user.type == "admin" else None if user.type == "admin": return render_template("hw.html", hw_list=get_homework(), homework=hw, user=user, question_list=question_list, options=options) else: if hw.start_date and hw.start_date > pdt_now(): raise Exception("This homework has not yet been released.") return render_template("hw.html", homework=hw, user=user, question_list=question_list, options=options)
def submit_response(self, stuid, responses): from queries import get_last_question_response last_submission = get_last_question_response(self.id, stuid) if not self.check_if_locked(last_submission): item_responses = [ItemResponse(item_id=item.id, response=response) \ for item, response in zip(self.items, responses)] score, comments = self.check(responses) question_response = QuestionResponse( stuid=stuid, time=pdt_now(), question_id=self.id, item_responses=item_responses, score=score, comments=comments ) session.add(question_response) session.commit() return { 'submission': self.delay_feedback(question_response), 'locked': self.check_if_locked(question_response), } else: raise Exception("The deadline for submitting this homework has passed.")
def get_homeworks_before(due_date=pdt_now()): return session.query(Homework).filter(Homework.due_date <= due_date).all()
def update_hw_grades(user, homeworks): """ helper function that computes user's grades on homeworks, returns a list of uncompleted peer reviews """ # keep track of to-do list for peer reviews to_do = defaultdict(int) # keep track of the peer review corresponding to each question prq_map = {} for prq in get_peer_review_questions(): prq.set_metadata() prq_map[prq.question_id] = prq for hw in homeworks: # skip if homework not due yet if hw.due_date > pdt_now(): continue # iterate over questions for q in hw.questions: # check if q is a question that is peer-reviewed if q.id in prq_map: # if grading tasks haven't been assigned if not get_all_peer_tasks(q.id): # get corresponding Peer Review object, instantiate with data from XML prq = prq_map[q.id] # get list of all students who responded, then shuffle responders = [r.stuid for r in get_all_responses_to_question(q.id)] import random random.seed(q.id) random.shuffle(responders) # import engine from base import engine # assign peer grading tasks, if applicable # (self grading tasks are assigned individually, on the fly) tasks = [] m, n = len(prq.peer_pts), len(responders) for i, stuid in enumerate(responders): for offset in [k*(k+1)/2 for k in range(1, m+1)]: j = (i + offset) % n tasks.append({"grader": stuid, "student": responders[j], "question_id": q.id}) engine.execute(GradingTask.__table__.insert(), tasks) # if question itself is a peer review question elif isinstance(q, PeerReview): # compute updated score for student response = get_last_question_response(q.question_id, user.stuid) if response: tasks = get_peer_tasks_for_student(q.question_id, user.stuid) scores = [t.score for t in tasks if t.score is not None] new_score = sorted(scores)[len(scores) // 2] if scores else None if response.score is None: response.score = new_score response.comments = "Click <a href='rate?id=%d' target='_blank'>here</a> to view comments." % q.question_id # check that student has rated all the peer reviews for task in tasks: if task.score is not None and task.rating is None: to_do[response.question.homework] += 1 # update student's grade on the homework calculate_grade(user, hw) return to_do
def update_hw_grades(user, homeworks): """ helper function that computes user's grades on homeworks, returns a list of uncompleted peer reviews """ # keep track of to-do list for peer reviews to_do = defaultdict(int) # keep track of the peer review corresponding to each question prq_map = {} for prq in get_peer_review_questions(): prq.set_metadata() prq_map[prq.question_id] = prq for hw in homeworks: # skip if homework not due yet if hw.due_date > pdt_now(): continue # iterate over questions for q in hw.questions: # check if q is a question that is peer-reviewed if q.id in prq_map: # if grading tasks haven't been assigned if not get_all_peer_tasks(q.id): # get corresponding Peer Review object, instantiate with data from XML prq = prq_map[q.id] # get list of all students who responded, then shuffle responders = [ r.stuid for r in get_all_responses_to_question(q.id) ] import random random.seed(q.id) random.shuffle(responders) # import engine from base import engine # assign peer grading tasks, if applicable # (self grading tasks are assigned individually, on the fly) tasks = [] m, n = len(prq.peer_pts), len(responders) for i, stuid in enumerate(responders): for offset in [ k * (k + 1) / 2 for k in range(1, m + 1) ]: j = (i + offset) % n tasks.append({ "grader": stuid, "student": responders[j], "question_id": q.id }) engine.execute(GradingTask.__table__.insert(), tasks) # if question itself is a peer review question elif isinstance(q, PeerReview): # compute updated score for student response = get_last_question_response(q.question_id, user.stuid) if response: tasks = get_peer_tasks_for_student(q.question_id, user.stuid) scores = [t.score for t in tasks if t.score is not None] new_score = sorted(scores)[len(scores) // 2] if scores else None if response.score is None: response.score = new_score response.comments = "Click <a href='rate?id=%d' target='_blank'>here</a> to view comments." % q.question_id # check that student has rated all the peer reviews for task in tasks: if task.score is not None and task.rating is None: to_do[response.question.homework] += 1 # update student's grade on the homework calculate_grade(user, hw) return to_do
def get_last_two_due_homeworks(): now = pdt_now() hws = session.query(Homework).order_by(Homework.due_date).all() due_hws = [hw for hw in hws if hw.due_date < now] return due_hws[-2:]
def check_if_locked(self, last_submission): due_date = self.homework.due_date return due_date and due_date < pdt_now()