def parse_activity_scores(self, activity_attempt): if activity_attempt.source == 'tag-assessment': data = transforms.loads(activity_attempt.data) timestamp = int( (activity_attempt.recorded_on - datetime.datetime(1970, 1, 1)).total_seconds()) questions = self.params['questions_by_usage_id'] valid_question_ids = self.params['valid_question_ids'] assessment_weights = self.params['assessment_weights'] group_to_questions = self.params['group_to_questions'] student_answers = self.activity_scores.get(Student.get_student_by_user_id(activity_attempt.user_id).email, {}) answers = event_transforms.unpack_check_answers( data, questions, valid_question_ids, assessment_weights, group_to_questions, timestamp) #add score to right lesson question_info = questions[data['instanceid']] unit_answers = student_answers.get(question_info['unit'], {}) lesson_answers = unit_answers.get(question_info['lesson'], {}) for answer in answers: question_answer_dict = {} question_answer_dict['unit_id'] = answer.unit_id question_answer_dict['lesson_id'] = answer.lesson_id question_answer_dict['sequence'] = answer.sequence question_answer_dict['question_id'] = answer.question_id question_answer_dict['question_type'] = answer.question_type question_answer_dict['timestamp'] = answer.timestamp question_answer_dict['answers'] = answer.answers question_answer_dict['score'] = answer.score question_answer_dict['weighted_score'] = answer.weighted_score question_answer_dict['tallied'] = answer.tallied if answer.sequence in lesson_answers and lesson_answers[answer.sequence] < timestamp: lesson_answers[answer.sequence] = question_answer_dict elif answer.sequence not in lesson_answers: lesson_answers[answer.sequence] = question_answer_dict unit_answers[question_info['lesson']] = lesson_answers student_answers[question_info['unit']] = unit_answers self.activity_scores[Student.get_student_by_user_id(activity_attempt.user_id).email] = student_answers return self.activity_scores
def map(self, event): # Find out whether this event is relevant to this unit. data = transforms.loads(event.data) url = data['location'] parsed = urlparse.urlparse(url) unit = urlparse.parse_qs(parsed.query)['unit'][0] if int(unit) != int(self.unit): return student = Student.get_student_by_user_id(event.user_id) self.add_row({ 'name': student.name, 'email': student.key().name(), 'index': data['index'], 'answer': data['value'], })
def post(self): """Handles POST requests.""" user = self.personalize_page_and_get_user() if not user: self.redirect(users.create_login_url(self.request.uri), normalize=False) return if not self.assert_xsrf_token_or_fail(self.request, 'register-post'): return can_register = self.app_context.get_environ( )['reg_form']['can_register'] if not can_register: self.template_value['course_status'] = 'full' else: name = self.request.get('form01') additional_fields = transforms.dumps(self.request.POST.items()) # create new or re-enroll old student student = Student.get_by_email(user.email()) if not student: student = Student(key_name=user.email()) student.user_id = user.user_id() student_by_uid = Student.get_student_by_user_id(user.user_id()) is_valid_student = (student_by_uid is None or student_by_uid.user_id == student.user_id) assert is_valid_student, ( 'Student\'s email and user id do not match.') student.user_id = user.user_id() student.is_enrolled = True student.name = name student.age = self.request.get('form02') student.additional_fields = additional_fields student.put() # Render registration confirmation page self.template_value['navbar'] = {'registration': True} self.render('confirmation.html')
def post(self): """Handles POST requests.""" user = self.personalize_page_and_get_user() if not user: self.redirect( users.create_login_url(self.request.uri), normalize=False) return if not self.assert_xsrf_token_or_fail(self.request, 'register-post'): return can_register = self.app_context.get_environ( )['reg_form']['can_register'] if not can_register: self.template_value['course_status'] = 'full' else: name = self.request.get('form01') additional_fields = transforms.dumps(self.request.POST.items()) # create new or re-enroll old student student = Student.get_by_email(user.email()) if not student: student = Student(key_name=user.email()) student.user_id = user.user_id() student_by_uid = Student.get_student_by_user_id(user.user_id()) is_valid_student = (student_by_uid is None or student_by_uid.user_id == student.user_id) assert is_valid_student, ( 'Student\'s email and user id do not match.') student.user_id = user.user_id() student.is_enrolled = True student.name = name student.additional_fields = additional_fields student.put() # Render registration confirmation page self.template_value['navbar'] = {'registration': True} self.render('confirmation.html')
def post(self): """Handles POST requests.""" user = self.personalize_page_and_get_user() if not user: self.redirect(users.create_login_url(self.request.uri), normalize=False) return if not self.assert_xsrf_token_or_fail(self.request, "register-post"): return can_register = self.app_context.get_environ()["reg_form"]["can_register"] if not can_register: self.template_value["course_status"] = "full" else: name = self.request.get("form01") additional_fields = transforms.dumps(self.request.POST.items()) # create new or re-enroll old student student = Student.get_by_email(user.email()) if not student: student = Student(key_name=user.email()) student.user_id = user.user_id() student_by_uid = Student.get_student_by_user_id(user.user_id()) is_valid_student = student_by_uid is None or student_by_uid.user_id == student.user_id assert is_valid_student, "Student's email and user id do not match." student.user_id = user.user_id() student.is_enrolled = True student.name = name student.age = self.request.get("formAge") student.additional_fields = additional_fields student.put() # Render registration confirmation page self.template_value["navbar"] = {"registration": True} self.render("confirmation.html")
def get_activity_scores(cls, student_user_ids, course, force_refresh = False): """Retrieve activity data for student using EventEntity""" #instantiate parser object cached_date = datetime.datetime.now() activityParser = ActivityScoreParser() if force_refresh: activityParser.params = activityParser.build_additional_mapper_params(course.app_context) for user_id in student_user_ids: mapper = models_utils.QueryMapper( EventEntity.all().filter('user_id in', [user_id]), batch_size=500, report_every=1000) def map_fn(activity_attempt): activityParser.parse_activity_scores(activity_attempt) mapper.run(map_fn) activityParser.build_missing_scores() #Lets cache results for each student for user_id in student_user_ids: cached_student_data = {} cached_student_data['date'] = cached_date cached_student_data['scores'] = activityParser.activity_scores.get(Student.get_student_by_user_id( user_id).email, {}) MemcacheManager.set(cls._memcache_key_for_student(Student.get_student_by_user_id(user_id).email), cached_student_data) else: uncached_students = [] for student_id in student_user_ids: scores_for_student = MemcacheManager.get(cls._memcache_key_for_student(Student.get_student_by_user_id( student_id).email)) if scores_for_student: cached_date = scores_for_student['date'] activityParser.activity_scores[student_id] = scores_for_student['scores'] else: uncached_students.append(student_id) if len(uncached_students) > 0: if cached_date == None or datetime.datetime.now() < cached_date: cached_date = datetime.datetime.now() activityParser.params = activityParser.build_additional_mapper_params(course.app_context) for user_id in uncached_students: mapper = models_utils.QueryMapper( EventEntity.all().filter('user_id in', [user_id]), batch_size=500, report_every=1000) def map_fn(activity_attempt): activityParser.parse_activity_scores(activity_attempt) mapper.run(map_fn) activityParser.build_missing_scores() #Lets cache results for each student for user_id in uncached_students: cached_student_data = {} cached_student_data['date'] = cached_date cached_student_data['scores'] = activityParser.activity_scores.get(Student.get_student_by_user_id( user_id).email, {}) MemcacheManager.set(cls._memcache_key_for_student(Student.get_student_by_user_id(user_id).email), cached_student_data) score_data = {} score_data['date'] = cached_date score_data['scores'] = activityParser.activity_scores return score_data
def get_markup_for_basic_analytics(self, job): """Renders markup for basic enrollment and assessment analytics.""" subtemplate_values = {} errors = [] stats_calculated = False update_message = safe_dom.Text('') if not job: update_message = safe_dom.Text( 'Enrollment/assessment statistics have not been calculated ' 'yet.') else: if job.status_code == jobs.STATUS_CODE_COMPLETED: stats = transforms.loads(job.output) stats_calculated = True #event = EventEntity().all().fetch(limit=400) cr = courses.Course(self).get_units() subtemplate_values['enrolled'] = stats['enrollment'][ 'enrolled'] subtemplate_values['unenrolled'] = ( stats['enrollment']['unenrolled']) subtemplate_values['submissions'] = stats['id'] scores = [] total_records = 0 names = [] submissions = {} students = {} data = [] for key, value in stats['id'].items(): students[key] = value course = courses.Course(self) problems = course.get_assessment_list() assessments = dict((a.unit_id, a.title) for a in problems) lesson_list = [] unit_list = [] units = course.get_units() for u in units: lessons = course.get_lessons(u.unit_id) for l in lessons: single = {} single['lesson_unit'] = l.unit_id single['lesson_id'] = l.lesson_id single['lesson_title'] = l.title lesson_list.append(single) if u.type == 'U': un = {} un['index'] = u._index un['id'] = u.unit_id un['title'] = u.title unit_list.append(un) tmp_unit = {} for l in lesson_list: tmp_unit[l['lesson_unit']] = [] for l in lesson_list: tmp_unit[l['lesson_unit']].append(l) struct = [] for key, value in tmp_unit.items(): unit = {} for u in unit_list: if u['index'] == key: unit['id'] = u['id'] unit['title'] = u['title'] unit['lessons'] = value unit['lesson_count'] = len(value) struct.append(unit) for sname, sid in students.items(): st = Student.get_student_by_user_id(sid) sc = course.get_all_scores(st) data.append({'name': sname, 'scores': sc}) for key, value in stats['scores'].items(): total_records += value[0] avg = round(value[1] / value[0], 1) if value[0] else 0 scores.append({ 'key': key, 'completed': value[0], 'avg': avg }) subtemplate_values['scores'] = scores subtemplate_values['total_records'] = total_records subtemplate_values['names'] = names subtemplate_values['data'] = data subtemplate_values['struct'] = struct update_message = safe_dom.Text( """ Enrollment and assessment statistics were last updated at %s in about %s second(s).""" % (job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT), job.execution_time_sec)) elif job.status_code == jobs.STATUS_CODE_FAILED: update_message = safe_dom.NodeList().append( safe_dom.Text(""" There was an error updating enrollment/assessment statistics. Here is the message:""")).append( safe_dom.Element('br')).append( safe_dom.Element('blockquote').add_child( safe_dom.Element('pre').add_text('\n%s' % job.output))) else: update_message = safe_dom.Text( 'Enrollment and assessment statistics update started at %s' ' and is running now. Please come back shortly.' % job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT)) subtemplate_values['stats_calculated'] = stats_calculated subtemplate_values['errors'] = errors subtemplate_values['update_message'] = update_message return jinja2.utils.Markup( self.get_template('basic_analytics.html', [os.path.dirname(__file__)]).render( subtemplate_values, autoescape=True))
def post(self): """Handles POST requests.""" user = self.personalize_page_and_get_user() if not user: self.redirect( users.create_login_url(self.request.uri), normalize=False) return if not self.assert_xsrf_token_or_fail(self.request, 'register-post'): return can_register = self.app_context.get_environ( )['reg_form']['can_register'] if not can_register: self.template_value['course_status'] = 'full' else: missing = self.find_missing_fields(self.request.POST) if missing: self.template_value['navbar'] = {'registration': True} self.template_value['content'] = ''' <div class="gcb-col-11 gcb-aside"> <h2>Something is missing...</h2> <p>You didn't fill out all the required fields in the registration form. Please use your browser's BACK button, and complete the form before submitting.</p> <p>Missing: {0}</p> <p>Thanks!</p> </div> '''.format(", ".join(missing)) self.render('bare.html') return # We accept the form. Now populate the student model: # create new or re-enroll old student student = Student.get_by_email(user.email()) if not student: student = Student(key_name=user.email()) student.user_id = user.user_id() student_by_uid = Student.get_student_by_user_id(user.user_id()) is_valid_student = (student_by_uid is None or student_by_uid.user_id == student.user_id) assert is_valid_student, ( 'Student\'s email and user id do not match.') student.user_id = user.user_id() student.is_enrolled = True string_fields = ('name', 'location_city', 'location_state', 'location_country', 'education_level', 'role', 'other_role') for field in string_fields: setattr(student, field, self.request.POST.get(field, None)) string_list_fields = ('grade_levels', 'title_and_setting', 'research_area', 'faculty_area', 'student_subject') for field in string_list_fields: raw = self.request.POST.get(field, '') if len(raw) > 0: values = [s.strip() for s in raw.split(',')] setattr(student, field, values) student.put() # now that we're in full registration, don't subscribe to pre-reg any more #mailchimp.subscribe('pre-reg', user.email(), student.name) self.redirect('confirm') return # Render registration confirmation page self.template_value['navbar'] = {'registration': True} self.render('confirmation.html')
def get_markup_for_basic_analytics(self, job): """Renders markup for basic enrollment and assessment analytics.""" subtemplate_values = {} errors = [] stats_calculated = False update_message = safe_dom.Text('') if not job: update_message = safe_dom.Text( 'Enrollment/assessment statistics have not been calculated ' 'yet.') else: if job.status_code == jobs.STATUS_CODE_COMPLETED: stats = transforms.loads(job.output) stats_calculated = True #event = EventEntity().all().fetch(limit=400) cr = courses.Course(self).get_units() subtemplate_values['enrolled'] = stats['enrollment']['enrolled'] subtemplate_values['unenrolled'] = ( stats['enrollment']['unenrolled']) subtemplate_values['submissions'] = stats['id'] scores = [] total_records = 0 names = [] submissions = {} students = {} data = [] for key, value in stats['id'].items(): students[key] = value course = courses.Course(self) problems = course.get_assessment_list() assessments = dict( (a.unit_id, a.title) for a in problems) lesson_list = [] unit_list = [] units = course.get_units() for u in units: lessons = course.get_lessons(u.unit_id) for l in lessons: single = {} single['lesson_unit'] = l.unit_id single['lesson_id'] = l.lesson_id single['lesson_title'] = l.title lesson_list.append(single) if u.type == 'U': un = {} un['index'] = u._index un['id'] = u.unit_id un['title'] = u.title unit_list.append(un) tmp_unit = {} for l in lesson_list: tmp_unit[l['lesson_unit']] = [] for l in lesson_list: tmp_unit[l['lesson_unit']].append(l) struct = [] for key, value in tmp_unit.items(): unit = {} for u in unit_list: if u['index'] == key: unit['id'] = u['id'] unit['title'] = u['title'] unit['lessons'] = value unit['lesson_count'] = len(value) struct.append(unit) for sname, sid in students.items(): st = Student.get_student_by_user_id(sid) sc = course.get_all_scores(st) data.append({'name': sname, 'scores': sc}) for key, value in stats['scores'].items(): total_records += value[0] avg = round(value[1] / value[0], 1) if value[0] else 0 scores.append({'key': key, 'completed': value[0], 'avg': avg}) subtemplate_values['scores'] = scores subtemplate_values['total_records'] = total_records subtemplate_values['names'] = names subtemplate_values['data'] = data subtemplate_values['struct'] = struct update_message = safe_dom.Text(""" Enrollment and assessment statistics were last updated at %s in about %s second(s).""" % ( job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT), job.execution_time_sec)) elif job.status_code == jobs.STATUS_CODE_FAILED: update_message = safe_dom.NodeList().append( safe_dom.Text(""" There was an error updating enrollment/assessment statistics. Here is the message:""") ).append( safe_dom.Element('br') ).append( safe_dom.Element('blockquote').add_child( safe_dom.Element('pre').add_text('\n%s' % job.output))) else: update_message = safe_dom.Text( 'Enrollment and assessment statistics update started at %s' ' and is running now. Please come back shortly.' % job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT)) subtemplate_values['stats_calculated'] = stats_calculated subtemplate_values['errors'] = errors subtemplate_values['update_message'] = update_message return jinja2.utils.Markup(self.get_template( 'basic_analytics.html', [os.path.dirname(__file__)] ).render(subtemplate_values, autoescape=True))