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)