def post(self): from model import StudentActivity from updates import send_update_query self.load_search_party_context(user_type="student") if self.is_student and self.person.is_logged_in: student = self.person lesson = student.lesson teacher = lesson.teacher task_idx = int(self.request.get("task_idx", 0)) query = self.request.get("query") url = self.request.get("url", default_value=None) ext = int(self.request.get("ext", 0)) activity = StudentActivity( student=student, lesson=lesson, task_idx=task_idx, activity_type="search", search=query, link=url ) activity.put() notifyStudent = ext == 1 send_update_query( student=student, teacher=teacher, task_idx=task_idx, query=query, notifyStudent=notifyStudent ) response_data = {"status": 1} else: response_data = {"status": 0, "msg": "Student not logged in"} import json self.response.headers.add_header("Content-Type", "application/json", charset="utf-8") self.response.out.write(json.dumps(response_data))
def clear_lesson(self, lesson, write_response=True): from model import Student, StudentActivity from google.appengine.ext import db db.delete(StudentActivity.fetch_all("lesson =", lesson)) db.delete(Student.fetch_all("lesson =", lesson)) self.log_out_all_students(lesson, False); if write_response: self.write_response_plain_text("OK")
def get_student_activities(self, student, lesson, task_idx): from model import StudentActivity, EXPECTED_UPPER_BOUND query = StudentActivity.all() query = query.filter('student =', student).filter('lesson =', lesson).filter('task_idx =', task_idx) query.order('timestamp') activities = [] for activity in query.fetch(EXPECTED_UPPER_BOUND): activities.append(activity.toDict()) return activities
def post(self): from helpers import log from updates import send_update_answer from model import StudentActivity self.load_search_party_context(user_type="student") if self.is_student and self.person.is_logged_in: student = self.person lesson = student.lesson teacher = lesson.teacher task_idx = int(self.request.get("task_idx", 0)) answer_text = self.request.get("answer_text") answer_explanation = self.request.get("answer_explanation") ext = int(self.request.get("ext", 0)) activity = StudentActivity( student=student, lesson=lesson, task_idx=task_idx, activity_type=StudentActivity.ACTIVITY_TYPE_ANSWER, answer_text=answer_text, answer_explanation=answer_explanation ) activity.put() log( "AnswerHandler: task_idx=%r, answer=%r, explanation=%r"%(task_idx, answer_text, answer_explanation) ) notifyStudent = ext==1 send_update_answer(student=student, teacher=teacher, task_idx=task_idx, answer_text=answer_text, answer_explanation=answer_explanation, notifyStudent=notifyStudent) response_data = activity.toDict(); response_data['status'] = 1; else: response_data = { "status":0, "msg":"Student not logged in" } import json self.response.headers.add_header('Content-Type', 'application/json', charset='utf-8') self.response.out.write(json.dumps(response_data))
def post(self): from model import StudentActivity, Student from updates import send_update_link_followed self.load_search_party_context(user_type="student") if self.is_student and self.person.is_logged_in: student = self.person teacher = student.teacher task_idx = int(self.request.get("task_idx", 0)) query = self.request.get("query") url = self.request.get("url") lesson_key = Student.lesson.get_value_for_datastore(student) title = self.request.get("title") ext = int(self.request.get("ext", 0)) link = StudentActivity( student = student, lesson = lesson_key, task_idx = task_idx, activity_type = StudentActivity.ACTIVITY_TYPE_LINK, search = query, link = url, link_title = title ) link.put() notifyStudent = ext==1 send_update_link_followed(student=student, teacher=teacher, task_idx=task_idx, query=query, url=url, title=title, notifyStudent=notifyStudent) response_data = link.toDict(); response_data['status'] = 1; else: response_data = { "status":0, "msg":"Student not logged in" } import json self.response.headers.add_header('Content-Type', 'application/json', charset='utf-8') self.response.out.write(json.dumps(response_data))
def post(self): from model import StudentActivity, Student from updates import send_update_link_rated self.load_search_party_context(user_type="student") if self.is_student and self.person.is_logged_in: student = self.person teacher = student.teacher task_idx = int(self.request.get("task_idx", 0)) url = self.request.get('url') title = self.request.get('title', None) lesson_key = Student.lesson.get_value_for_datastore(student) is_helpful = {"1":True, "0":False, None:None}[self.request.get("is_helpful")] ext = int(self.request.get("ext", 0)) link = StudentActivity( student = student, lesson = lesson_key, task_idx = task_idx, activity_type = StudentActivity.ACTIVITY_TYPE_LINK_RATING, link = url, link_title = title, is_helpful = is_helpful ) link.put() notifyStudent = ext==1 send_update_link_rated(student=student, teacher=teacher, task_idx=task_idx, url=url, is_helpful=is_helpful, notifyStudent=notifyStudent) response_data = link.toDict(); response_data['status'] = 1; else: response_data = { "status":0, "msg":"Student not logged in" } import json self.response.headers.add_header('Content-Type', 'application/json', charset='utf-8') self.response.out.write(json.dumps(response_data))
def make_student_structure(self, lesson, student=None): # If student is None, then this will return info for all students who # worked on this lesson. from model import Student, StudentActivity if student is not None: students = (student,) filter_key = "student =" filter_value = student else: students = tuple( Student.all().filter("lesson =", lesson) ) # PERFORMANCE: Generator might be inefficient filter_key = "lesson =" filter_value = lesson student_structure = {} if len(students) > 0: num_tasks = len(lesson.tasks) for student in students: tasks_info = [{"searches":[], "answer":{"text":"", "explanation":""}, "history":[]} for _ in range(num_tasks)] student_structure[student.nickname] = { "task_idx" : student.task_idx, "logged_in" : student.is_logged_in, "tasks" : tasks_info } # Policy: Don't report same (query,student,task_idx) more than once. # This dictionary enforces that. searches_dict = {} # (student_nickname,task_idx,link_url) -> ([link_info,...], is_helpful) link_infos_and_ratings = {} activities = StudentActivity.fetch_all(filter_key, filter_value) for activity in activities: student_nickname = activity.student.nickname task_idx = activity.task_idx activity_type = activity.activity_type if activity_type in (StudentActivity.ACTIVITY_TYPE_LINK, StudentActivity.ACTIVITY_TYPE_LINK_RATING, StudentActivity.ACTIVITY_TYPE_SEARCH): link_url = activity.link key = (student_nickname,task_idx,link_url) link_infos_and_rating = link_infos_and_ratings.setdefault(key, [[],None]) if activity_type in (StudentActivity.ACTIVITY_TYPE_LINK, StudentActivity.ACTIVITY_TYPE_SEARCH): query = activity.search search_key = (student_nickname, task_idx, query) try: search_info = searches_dict[search_key] except KeyError: search_info = {"query":query, "links_followed":[]} student_structure[student_nickname]["tasks"][task_idx]["searches"].append(search_info) searches_dict[search_key] = search_info if activity_type==StudentActivity.ACTIVITY_TYPE_LINK: link_title = activity.link_title link_info = {"url":link_url, "title":link_title, "is_helpful":None} search_info["links_followed"].append(link_info) link_infos_and_rating[0].append(link_info) elif activity_type==StudentActivity.ACTIVITY_TYPE_LINK_RATING: link_infos_and_rating[1] = activity.is_helpful elif activity_type==StudentActivity.ACTIVITY_TYPE_ANSWER: # This will end up with the most recent answer because it is in ascending time order, so # later answers will overwrite the older ones. answer_info = student_structure[student_nickname]["tasks"][task_idx]["answer"] answer_info["text"] = activity.answer_text answer_info["explanation"] = activity.answer_explanation student_structure[student_nickname]["tasks"][task_idx]["history"].append(activity) for k,v in link_infos_and_ratings.items(): (student_nickname,task_idx,link_url) = k link_infos, is_helpful = v for link_info in link_infos: link_info["is_helpful"] = is_helpful return student_structure
def _send_tab_delimited_report(self, lesson_code, utc_offset): import StringIO from model import Student, StudentActivity, Lesson import helpers encoding = "UTF-8" lesson = Lesson.get_by_key_name(lesson_code) assert lesson is not None if lesson is None or lesson.teacher_key != self.teacher_key: self.write_response_plain_text("ERROR: Lesson code appears to be incorrect.") else: students = Student.fetch_all("lesson =", lesson) task_titles = tuple(task_info[0] for task_info in lesson.tasks) student_key_to_nickname = dict((s.key().name(), s.nickname) for s in students) activities = StudentActivity.fetch_all("lesson =", lesson) report_buffer = StringIO.StringIO() excel_writer = UnicodeWriter(report_buffer, "excel-tab", "utf8") headers = ( # "Lesson_Code", "Timestamp", "Student", "Task_Number", "Task_Name", "Activity_Type", "Query", "Link_URL", "Link_Title", "Is_Helpful", "Answer_Text", "Answer_Explanation" ) excel_writer.writerow(headers) for activity in activities: student_key = activity.student_key.name() student_nickname = student_key_to_nickname[student_key] timestamp = (activity.timestamp - utc_offset).strftime("%m/%d/%Y %H:%M:%S") task_idx = activity.task_idx task_title = task_titles[task_idx] task_num = task_idx + 1 line_parts = ( # lesson_code, timestamp, student_nickname, task_num, task_title, activity.activity_type, activity.search, activity.link, activity.link_title, activity.is_helpful, activity.answer_text, activity.answer_explanation ) # line_parts = tuple(unicode(p).encode("utf8") for p in line_parts) excel_writer.writerow(line_parts) report_text = report_buffer.getvalue() report_buffer.close() content_type = "text/tab-separated-values" filename = "search_party_lesson_%s_activity_as_of_%s.txt"%(lesson_code, helpers.timestamp()) self.write_response_as_file(encoded_content=report_text, content_type=content_type, filename=filename, encoding=encoding)