def post(self):
        # Sort questions into a dictionary based on their unit number
        questions_by_usage_id = event_transforms.get_questions_by_usage_id(
            self.app_context)

        sorted_questions_by_unit = self._rearrange_dict_by_field(
            questions_by_usage_id, 'unit')

        # Only use Students we generated.
        students = common_utils.iter_all(models.Student.all().filter(
            'email >', 'gen_sample_student_').filter('email <',
                                                     'gen_sample_student`'))
        source = 'submit-assessment'

        for student in students:
            user = users.User(email=student.email, _user_id=student.user_id)
            assessment_data = self._generate_answers(student,
                                                     sorted_questions_by_unit)
            for data in assessment_data:
                EventEntity.record(
                    source, user,
                    transforms.dumps({
                        'values': data,
                        'location': 'AnswerHandler'
                    }))

        self.redirect(self.request.referer)
 def visit_page(self, user, pageURL):
     source = 'enter-page'
     data = {}
     data['user_agent'] = ('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit'
                           '/537.36 (KHTML, like Gecko) Chrome'
                           '/51.0.2704.106 Safari/537.36')
     data['loc'] = {'page_locale': 'en_US', 'locale': 'en_US',
                    'region':'null', 'language': 'en-US,en;q=0.8',
                    'country': 'ZZ', 'city': 'null'}
     data['location'] = pageURL
     data_str = transforms.dumps(data)
     EventEntity.record(source, user, data_str)
Example #3
0
    def post_save_settings(self):
        user = self.personalize_page_and_get_enrolled()
        if not user:
            return

        form = self.SettingsForm(self.request.POST)

        try:
            report = PartReport.get_by_id(int(form.report_id.data))
        except ValueError:
            report = None
        if not report:
            self.abort(404, "That evidence report was not found.")

        if not self.can_edit(user, report):
            self.abort(403, "You can't edit that user's report.")

        if report.assessment_scores:
            display_field_params = exam_display_choices(
                    report.assessment_scores[0])
            form.exam_display.choices = display_field_params['choices']
            form.exam_display.default = display_field_params['default']
        else:
            del form.exam_display

        if not form.validate():
            self.redirect('/')
            return

        report.units_are_public = form.units_are_public.data
        report.review_is_public = form.review_is_public.data
        if report.assessment_scores:
            report.exam_display = form.exam_display.data
        report.put()

        EventEntity.record(
                'set-evidence-settings',
                users.get_current_user(),
                transforms.dumps({
                    'part': report.part,
                    'slug': report.slug,
                    'review_is_public': report.review_is_public,
                    'public': report.units_are_public,
                    'exam_display': report.exam_display,
                    'email': user.key().name()
                    }))

        self.template_value['navbar'] = {}
        self.template_value['content'] = '''<div class="gcb-aside">OK, saved settings.<br>
        <a href="/student/home">Back to your account page...</a></div>'''
        self.render('bare.html')
Example #4
0
    def run(self):
        query = EventEntity.all()
        query.filter('source', 'unenrolled')
        query.order('-recorded_on')

        for survey in query.run():
            yield transforms.loads(survey.data)
Example #5
0
    def run(self):
        query = EventEntity.all()
        query.filter('source', 'unenrolled')
        query.order('-recorded_on')

        for survey in query.run():
            yield transforms.loads(survey.data)
 def run(self):
     """Computes submitted question answers statistics."""
     question_stats = self.MultipleChoiceQuestionAggregator(self._course)
     mapper = models_utils.QueryMapper(
         EventEntity.all(), batch_size=500, report_every=1000)
     mapper.run(question_stats.visit)
     return (question_stats.id_to_questions_dict,
             question_stats.id_to_assessments_dict)
 def visit_page(self, user, pageURL):
     source = 'enter-page'
     data = {}
     data['user_agent'] = ('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit'
                           '/537.36 (KHTML, like Gecko) Chrome'
                           '/51.0.2704.106 Safari/537.36')
     data['loc'] = {
         'page_locale': 'en_US',
         'locale': 'en_US',
         'region': 'null',
         'language': 'en-US,en;q=0.8',
         'country': 'ZZ',
         'city': 'null'
     }
     data['location'] = pageURL
     data_str = transforms.dumps(data)
     EventEntity.record(source, user, data_str)
 def run(self):
     """Computes submitted question answers statistics."""
     question_stats = self.MultipleChoiceQuestionAggregator(self._course)
     mapper = models_utils.QueryMapper(
         EventEntity.all(), batch_size=500, report_every=1000)
     mapper.run(question_stats.visit)
     return (question_stats.id_to_questions_dict,
             question_stats.id_to_assessments_dict)
Example #9
0
    def post(self):
        """Handles POST requests."""
        student = self.personalize_page_and_get_enrolled()
        if not student:
            return

        if not self.assert_xsrf_token_or_fail(self.request, 'student-unenroll'):
            return

        form = self.SurveyForm(self.request.POST)
        if not form.validate():
            self.render_form(student, form)
            return

        info = {
                'email': student.key().name(),
                'wikis_posted': student.wikis_posted,
                }
        info.update(form.data)

        # form is good
        EventEntity.record(
                'unenrolled',
                users.get_current_user(),
                transforms.dumps(info))

        mail.send_mail('*****@*****.**', '*****@*****.**',
                'User %s unenrolled' % info['email'],
                'Their data:\n%s' % transforms.dumps(info, indent=2))

        Student.set_enrollment_status_for_current(False)
        mailchimp.unsubscribe('pre-reg', student.key().name())
        mailchimp.unsubscribe('confirmed', student.key().name())
        mailchimp.unsubscribe('for-credit', student.key().name())
        mailchimp.subscribe('unenrolled', student.key().name(), student.name)

        self.template_value['navbar'] = {'registration': True}
        self.render('unenroll_confirmation.html')
    def post(self):
        # Sort questions into a dictionary based on their unit number
        questions_by_usage_id = event_transforms.get_questions_by_usage_id(
            self.app_context)

        sorted_questions_by_unit = self._rearrange_dict_by_field(
            questions_by_usage_id, 'unit')

        # Only use Students we generated.
        students = common_utils.iter_all(models.Student.all().filter(
            'email >', 'gen_sample_student_').filter(
                'email <', 'gen_sample_student`'))
        source = 'submit-assessment'

        for student in students:
            user = users.User(email=student.email, _user_id=student.user_id)
            assessment_data = self._generate_answers(student,
                                                    sorted_questions_by_unit)
            for data in assessment_data:
                EventEntity.record(source, user, transforms.dumps({
                    'values': data, 'location': 'AnswerHandler'}))

        self.redirect(self.request.referer)
Example #11
0
    def run(self):
        # find the student's user_id..
        student = Student.get_enrolled_student_by_email(self.student_email)
        if not student:
            raise ValueError('That student was not found!')
        user_id = student.user_id
        query = EventEntity.all()
        query.filter('user_id', str(user_id))
        query.filter('source', 'edit-wiki-page')
        query.order('-recorded_on')
        edits = query.run(limit=2000)

        for edit in edits:
            fields = transforms.loads(edit.data)
            fields['recorded_on'] = edit.recorded_on
            yield fields
Example #12
0
    def run(self):
        # find the student's user_id..
        student = Student.get_enrolled_student_by_email(self.student_email)
        if not student:
            raise ValueError('That student was not found!')
        user_id = student.user_id
        query = EventEntity.all()
        query.filter('user_id', str(user_id))
        query.filter('source', 'edit-wiki-page')
        query.order('-recorded_on')
        edits = query.run(limit=2000)

        for edit in edits:
            fields = transforms.loads(edit.data)
            fields['recorded_on'] = edit.recorded_on
            yield fields
Example #13
0
    def get_activity_scores(cls, student_user_ids, course, force_refresh=True):
        """Retrieve activity data for student using EventEntity.

           For each student, launch a Query of EventEntities to retrieve student
           scores.  The Query is launched as a map-reduce background process that
           will return up to 500 results, reporting back every second.  It reports
           back by calling the map_fn callback, which in turn calls parse_activity
           scores.

           As soon as the Query is launched (in the background) the foreground
           process calls build_missing_scores() to construct a student_answer.dict
           that will be updated as score data for that student is received.

           Events properties include a userid (a number) and a source (e.g.,
           tag-assessement), a  recorded-on date (timestamp) and data (a dictionary).
           Here's a typeical data dict:

           {"loc": {"city": "mililani", "language": "en-US,en;q=0.8", "locale": "en_US",
           "country": "US", "region": "hi", "long": -158.01528099999999, "lat": 21.451331,
           "page_locale": "en_US"}, "instanceid": "yOkVTqWogdaF", "quid": "5733935958982656",
           "score": 1, "location": "https://mobilecsp-201608.appspot.com/mobilecsp/unit?unit=1&lesson=45",
           "answer": [0, 1, 2, 4], "type": "McQuestion", "user_agent":
            "Mozilla/5.0 ..."}

           Note that it includes the unit_id and lesson_id as part of the Url
        """

        # Instantiate parser object
        cached_date = datetime.datetime.now()
        activityParser = ActivityScoreParser()

        if force_refresh:
            activityParser.params = activityParser.build_additional_mapper_params(
                course.app_context)

            #  Launch a background Query for each student's activity data.  This is expensive.
            for user_id in student_user_ids:
                #                if GLOBAL_DEBUG:
                logging.debug('***RAM*** launching a query for student ' +
                              str(user_id))
                mapper = models_utils.QueryMapper(
                    EventEntity.all().filter('user_id in', [user_id])       \
                                     .filter('recorded_on  >= ', cls.CUTOFF_DATE), \
                                        batch_size=1000, report_every=1000)

                # Callback function -- e.g., 45-50 callbacks per query
                def map_fn(activity_attempt):
                    #                    if GLOBAL_DEBUG:
                    #                     logging.debug('***RAM*** map_fn ' + str(activity_attempt))
                    activityParser.parse_activity_scores(activity_attempt)

                mapper.run(map_fn)

            #  In the foreground create the student_answer_dict, which is stored at:
            #   activity_scores[student][unit][lesson][sequence]  where sequence is
            #   the question's sequential position within the lesson.
            #  So each question in the lesson will have a question_answer_dict.
            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

                student = Student.get_by_user_id(user_id)

                cached_student_data[
                    'scores'] = activityParser.activity_scores.get(
                        student.email, {})
                cached_student_data[
                    'attempts'] = activityParser.num_attempts_dict.get(
                        student.email, {})
                MemcacheManager.set(
                    cls._memcache_key_for_student(student.email),
                    cached_student_data)
        else:
            uncached_students = []
            for student_id in student_user_ids:
                if student_id != '':
                    student = Student.get_by_user_id(student_id)
                    temp_email = student.email
                    temp_mem = cls._memcache_key_for_student(temp_email)
                    scores_for_student = MemcacheManager.get(temp_mem)
                    if scores_for_student:
                        cached_date = scores_for_student['date']
                        activityParser.activity_scores[
                            student_id] = scores_for_student['scores']
                        activityParser.num_attempts_dict[
                            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])       \
                                     .filter('recorded_on  >= ', cls.CUTOFF_DATE), \
                                        batch_size=1000, 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

                    student = Student.get_by_user_id(user_id)

                    cached_student_data[
                        'scores'] = activityParser.activity_scores.get(
                            student.email, {})
                    MemcacheManager.set(
                        cls._memcache_key_for_student(student.email),
                        cached_student_data)

        score_data = {}
        score_data['date'] = cached_date
        score_data['scores'] = activityParser.activity_scores
        score_data['attempts'] = activityParser.num_attempts_dict
        if GLOBAL_DEBUG:
            logging.debug('***RAM*** get_activity_scores returning scores: ' +
                          str(score_data['scores']))

        return score_data
    def get_activity_scores(cls, student_user_ids, course, force_refresh = True):
        """Retrieve activity data for student using EventEntity.

           For each student, launch a Query of EventEntities to retrieve student
           scores.  The Query is launched as a map-reduce background process that
           will return up to 500 results, reporting back every second.  It reports
           back by calling the map_fn callback, which in turn calls parse_activity
           scores.

           As soon as the Query is launched (in the background) the foreground
           process calls build_missing_scores() to construct a student_answer.dict
           that will be updated as score data for that student is received.

           Events properties include a userid (a number) and a source (e.g.,
           tag-assessement), a  recorded-on date (timestamp) and data (a dictionary).
           Here's a typeical data dict:

           {"loc": {"city": "mililani", "language": "en-US,en;q=0.8", "locale": "en_US",
           "country": "US", "region": "hi", "long": -158.01528099999999, "lat": 21.451331,
           "page_locale": "en_US"}, "instanceid": "yOkVTqWogdaF", "quid": "5733935958982656",
           "score": 1, "location": "https://mobilecsp-201608.appspot.com/mobilecsp/unit?unit=1&lesson=45",
           "answer": [0, 1, 2, 4], "type": "McQuestion", "user_agent":
            "Mozilla/5.0 ..."}

           Note that it includes the unit_id and lesson_id as part of the Url
        """

        # Instantiate parser object
        cached_date = datetime.datetime.now()
        activityParser = ActivityScoreParser()

        if force_refresh:
            activityParser.params = activityParser.build_additional_mapper_params(course.app_context)

            #  Launch a background Query for each student's activity data.  This is expensive.
            for user_id in student_user_ids:
#                if GLOBAL_DEBUG:
#                     logging.debug('***RAM*** launching a query for student ' + str(user_id))
                mapper = models_utils.QueryMapper(
                    EventEntity.all().filter('user_id in', [user_id])       \
                                     .filter('recorded_on  >= ', cls.CUTOFF_DATE), \
                                        batch_size=1000, report_every=1000)

                # Callback function -- e.g., 45-50 callbacks per query
                def map_fn(activity_attempt):
#                    if GLOBAL_DEBUG:
#                     logging.debug('***RAM*** map_fn ' + str(activity_attempt))
                    activityParser.parse_activity_scores(activity_attempt)

                mapper.run(map_fn)

            #  In the foreground create the student_answer_dict, which is stored at:
            #   activity_scores[student][unit][lesson][sequence]  where sequence is
            #   the question's sequential position within the lesson.
            #  So each question in the lesson will have a question_answer_dict.
            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

                student = Student.get_by_user_id(user_id)
                
                cached_student_data['scores'] = activityParser.activity_scores.get(student.email, {})
                cached_student_data['attempts'] = activityParser.num_attempts_dict.get(student.email, {})
                MemcacheManager.set(cls._memcache_key_for_student(student.email),cached_student_data)
        else:
            uncached_students = []
            for student_id in student_user_ids:
                if student_id != '':
                    student = Student.get_by_user_id(student_id)
                    temp_email = student.email
                    temp_mem = cls._memcache_key_for_student(temp_email)
                    scores_for_student = MemcacheManager.get(temp_mem)
                    if scores_for_student:
                        cached_date = scores_for_student['date']
                        activityParser.activity_scores[student_id] = scores_for_student['scores']
                        activityParser.num_attempts_dict[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])       \
                                     .filter('recorded_on  >= ', cls.CUTOFF_DATE), \
                                        batch_size=1000, 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

                    student = Student.get_by_user_id(user_id)

                    cached_student_data['scores'] = activityParser.activity_scores.get(student.email, {})
                    MemcacheManager.set(cls._memcache_key_for_student(student.email),cached_student_data)

        score_data = {}
        score_data['date'] = cached_date
        score_data['scores'] = activityParser.activity_scores
        score_data['attempts'] = activityParser.num_attempts_dict
        if GLOBAL_DEBUG:
            logging.debug('***RAM*** get_activity_scores returning scores: ' + str(score_data['scores']))

        return score_data
    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