def student_grades(student, request, course, keep_raw_scores=False, use_offline=False):
    '''
    This is the main interface to get grades.  It has the same parameters as grades.grade, as well
    as use_offline.  If use_offline is True then this will look for an offline computed gradeset in the DB.
    '''
    if not use_offline:
        return grades.grade(student, request, course, keep_raw_scores=keep_raw_scores)

    try:
        ocg = models.OfflineComputedGrade.objects.get(user=student, course_id=course.id)
    except models.OfflineComputedGrade.DoesNotExist:
        return dict(
            raw_scores=[],
            section_breakdown=[],
            msg='Error: no offline gradeset available for {}, {}'.format(student, course.id)
        )

    gradeset = json.loads(ocg.gradeset)
    # Convert score dicts back to Score tuples:

    def score_from_dict(encoded):
        """ Given a formerly JSON-encoded Score tuple, return the Score tuple """
        if encoded['module_id']:
            encoded['module_id'] = UsageKey.from_string(encoded['module_id'])
        return Score(**encoded)

    totaled_scores = gradeset['totaled_scores']
    for section in totaled_scores:
        totaled_scores[section] = [score_from_dict(score) for score in totaled_scores[section]]
    gradeset['raw_scores'] = [score_from_dict(score) for score in gradeset['raw_scores']]
    return gradeset
def offline_grade_calculation(course_key):
    '''
    Compute grades for all students for a specified course, and save results to the DB.
    '''

    tstart = time.time()
    enrolled_students = User.objects.filter(
        courseenrollment__course_id=course_key,
        courseenrollment__is_active=1
    ).prefetch_related("groups").order_by('username')

    enc = MyEncoder()

    print "{} enrolled students".format(len(enrolled_students))
    course = get_course_by_id(course_key)

    for student in enrolled_students:
        request = DummyRequest()
        request.user = student
        request.session = {}

        gradeset = grades.grade(student, request, course, keep_raw_scores=True)
        gs = enc.encode(gradeset)
        ocg, _created = models.OfflineComputedGrade.objects.get_or_create(user=student, course_id=course_key)
        ocg.gradeset = gs
        ocg.save()
        print "%s done" % student  	# print statement used because this is run by a management command

    tend = time.time()
    dt = tend - tstart

    ocgl = models.OfflineComputedGradeLog(course_id=course_key, seconds=dt, nstudents=len(enrolled_students))
    ocgl.save()
    print ocgl
    print "All Done!"
Example #3
0
    def get(self, request, course_id):
        """
        GET /api/grades_api/v1/grades/{course_id}?username={username}
        """

        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        username = request.QUERY_PARAMS.get('username')

        try:
            user = get_user(request.user, username)
        except UserNotFound:
            return Response({
                'error': 'No such user "{}"'.format(username)
            }, status=status.HTTP_404_NOT_FOUND)
        except UserNotAllowed:
            return Response({
                'error': 'Not allowed to retrieve grades for "{}"'.format(username)
            }, status=status.HTTP_403_FORBIDDEN)

        course = get_course_with_access(user, 'load', course_key, depth=None)
        grade_summary = grades.grade(user, request, course)

        return Response({
            'username': user.username,
            'course_id': course_id,
            'percent': grade_summary.get('percent')
        })
def offline_grade_calculation(course_id):
    '''
    Compute grades for all students for a specified course, and save results to the DB.
    '''

    tstart = time.time()
    enrolled_students = User.objects.filter(
        courseenrollment__course_id=course_id,
        courseenrollment__is_active=1
    ).prefetch_related("groups").order_by('username')

    enc = MyEncoder()

    print "%d enrolled students" % len(enrolled_students)
    course = get_course_by_id(course_id)

    for student in enrolled_students:
        request = DummyRequest()
        request.user = student
        request.session = {}

        gradeset = grades.grade(student, request, course, keep_raw_scores=True)
        gs = enc.encode(gradeset)
        ocg, created = models.OfflineComputedGrade.objects.get_or_create(user=student, course_id=course_id)
        ocg.gradeset = gs
        ocg.save()
        print "%s done" % student  	# print statement used because this is run by a management command

    tend = time.time()
    dt = tend - tstart

    ocgl = models.OfflineComputedGradeLog(course_id=course_id, seconds=dt, nstudents=len(enrolled_students))
    ocgl.save()
    print ocgl
    print "All Done!"
Example #5
0
    def format_user_data(user):
        try:
            grade = grades.grade(user, request, course)['percent'] * 100
        except:
            grade = 0.0

        student_dict = dict(
            (ft, getattr(user, ft))
            for ft in [sf for sf in STUDENT_FEATURES if sf in USER_FEATURES])

        student_profile = user.profile
        if student_profile:
            student_dict.update(
                dict(
                    (tf, getattr(student_profile, tf)) for tf in
                    [pf for pf in STUDENT_FEATURES if pf in PROFILE_FEATURES]))

        if student_dict['gender']:
            st_g = student_dict['gender']
            student_dict['gender'] = filter(lambda x: x[0] == st_g,
                                            GENDER_CONTRAST)[0][1]

        if student_dict['level_of_education']:
            st_level = student_dict['level_of_education']
            student_dict['level_of_education'] = filter(
                lambda x: x[0] == st_level, EDU_LEVEL_CONTRAST)[0][1]

        student_dict.update(
            {'complete_degree': "{grade}%".format(grade=grade)})

        return student_dict
Example #6
0
    def get(self, request, course_id):
        """
        GET /api/grades_api/v1/grades/{course_id}?username={username}
        """

        course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
        username = request.QUERY_PARAMS.get('username')

        try:
            user = get_user(request.user, username)
        except UserNotFound:
            return Response({'error': 'No such user "{}"'.format(username)},
                            status=status.HTTP_404_NOT_FOUND)
        except UserNotAllowed:
            return Response(
                {
                    'error':
                    'Not allowed to retrieve grades for "{}"'.format(username)
                },
                status=status.HTTP_403_FORBIDDEN)

        course = get_course_with_access(user, 'load', course_key, depth=None)
        grade_summary = grades.grade(user, request, course)

        return Response({
            'username': user.username,
            'course_id': course_id,
            'percent': grade_summary.get('percent')
        })
Example #7
0
def get_student_course_stats_base(request,course, type="grades"):
    """
    Called by get_student_course_stats and get_student_problem_stats
    Gets a list of users in a course, and then computes grades for them
    request - a mock request (using RequestDict)
    course - a string course id
    type - whether to get student weighted grades or unweighted grades.  If "grades" will get weighted
    """
    fs, db = common.get_db_and_fs_cron(common.student_course_stats_stub)
    course_obj = get_course_with_access(request.user, course, 'load', depth=None)
    users_in_course = StudentModule.objects.filter(course_id=course).values('student').distinct()
    users_in_course_ids = [u['student'] for u in users_in_course]
    log.debug("Users in course count: {0}".format(len(users_in_course_ids)))
    courseware_summaries = []
    for i in xrange(0,len(users_in_course_ids)):
        try:
            user = users_in_course_ids[i]
            current_task.update_state(state='PROGRESS', meta={'current': i, 'total': len(users_in_course_ids)})
            student = User.objects.using('remote').prefetch_related("groups").get(id=int(user))

            model_data_cache = None

            if type=="grades":
                grade_summary = grades.grade(student, request, course_obj, model_data_cache)
            else:
                grade_summary = grades.progress_summary(student, request, course_obj, model_data_cache)
            courseware_summaries.append(grade_summary)
        except:
            log.exception("Could not generate data for {0}".format(users_in_course_ids[i]))
    return courseware_summaries, users_in_course_ids
def student_course_progress(request, course_id, username):
    from django.contrib.auth.models import User
    from courseware.model_data import FieldDataCache
    from courseware import grades
    from django.http import Http404, HttpResponse, HttpResponseRedirect

    student=User.objects.filter(username=username)
    
    if not student.exists():
        return HttpResponse("Student '%s' not exists." % username)

    student=student[0]

    #return HttpResponse(request.session)

    try:
        course=get_course_by_id(course_id)
    except:
        return HttpResponse("Course '%s' not exists." % course_id)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, student, course, depth=None)
    grade_summary = grades.grade(student, request, course, field_data_cache)
    progress="{totalscore:.0%}".format(totalscore=grade_summary['percent'])

    return HttpResponse("course:%s<br>user:%s<br>progress:%s" % (course_id,username,progress))
Example #9
0
    def report(self):
        """Report course grade."""
        students = self._get_students()

        print "\nFetching course data for {0}".format(self.course_id)
        course = courses.get_course_by_id(self.course_id)
        request = self._create_request()
        total = {'users': 0, 'pass': 0, 'notpass': 0}

        print "Summary Report: Course Name [{0}]".format(
            course.display_name.encode('utf_8'))

        for student in students.iterator():
            request.user = student
            total['users'] += 1

            certs = GeneratedCertificate.objects.filter(
                user=student, course_id=self.course_id)

            for cert in certs.iterator():
                grade = grades.grade(cert.user, request, course)
                summary = grades.progress_summary(student, request, course)
                self._report_summary(summary)
                self._add_total(cert.user, grade, total)

        self._report_total(total)
Example #10
0
    def report(self):
        """Report course grade."""
        students = self._get_students()

        print "\nFetching course data for {0}".format(self.course_id)
        course = courses.get_course_by_id(self.course_id)
        request = self._create_request()
        total = {'users': 0, 'pass': 0, 'notpass': 0}

        print "Summary Report: Course Name [{0}]".format(
            course.display_name.encode('utf_8'))

        for student in students.iterator():
            request.user = student
            total['users'] += 1

            certs = GeneratedCertificate.objects.filter(
                user=student, course_id=self.course_id)

            for cert in certs.iterator():
                grade = grades.grade(cert.user, request, course)
                summary = grades.progress_summary(student, request, course)
                self._report_summary(summary)
                self._add_total(cert.user, grade, total)

        self._report_total(total)
Example #11
0
def student_grades(student,
                   request,
                   course,
                   keep_raw_scores=False,
                   use_offline=False):
    '''
    This is the main interface to get grades.  It has the same parameters as grades.grade, as well
    as use_offline.  If use_offline is True then this will look for an offline computed gradeset in the DB.
    '''

    if not use_offline:
        return grades.grade(student,
                            request,
                            course,
                            keep_raw_scores=keep_raw_scores)

    try:
        ocg = models.OfflineComputedGrade.objects.get(user=student,
                                                      course_id=course.id)
    except models.OfflineComputedGrade.DoesNotExist:
        return dict(raw_scores=[],
                    section_breakdown=[],
                    msg='Error: no offline gradeset available for %s, %s' %
                    (student, course.id))

    return json.loads(ocg.gradeset)
Example #12
0
def _progress(request, course_key, student_id):
    """
    Unwrapped version of "progress".

    User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user,
                                    'load',
                                    course_key,
                                    depth=None,
                                    check_if_enrolled=True)

    # check to see if there is a required survey that must be taken before
    # the user can access the course.
    if survey.utils.must_answer_survey(course, request.user):
        return redirect(reverse('course_survey', args=[unicode(course.id)]))

    staff_access = has_access(request.user, 'staff', course)

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    courseware_summary = grades.progress_summary(student, request, course)
    studio_url = get_studio_url(course, 'settings/grading')
    grade_summary = grades.grade(student, request, course)

    if courseware_summary is None:
        #This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {
        'course': course,
        'courseware_summary': courseware_summary,
        'studio_url': studio_url,
        'grade_summary': grade_summary,
        'staff_access': staff_access,
        'student': student,
        'reverifications': fetch_reverify_banner_info(request, course_key)
    }

    with grades.manual_transaction():
        response = render_to_response('courseware/progress.html', context)

    return response
    def handle(self, *args, **options):

        course_ids = options.get('course_ids')
        user_ids = options.get('user_ids')

        # Get the list of courses from the system
        courses = modulestore().get_courses()

        # If one or more courses were specified by the caller, just use those ones...
        if course_ids is not None:
            filtered_courses = []
            for course in courses:
                if unicode(course.id) in course_ids.split(','):
                    filtered_courses.append(course)
            courses = filtered_courses

        for course in courses:
            users = CourseEnrollment.objects.users_enrolled_in(course.id)
            # If one or more users were specified by the caller, just use those ones...
            if user_ids is not None:
                filtered_users = []
                for user in users:
                    if str(user.id) in user_ids.split(','):
                        filtered_users.append(user)
                users = filtered_users

            # For each user...
            for user in users:
                grade_data = grades.grade(user, course)
                grade = grade_data['percent']
                grading_policy = course.grading_policy
                proforma_grade = grades.calculate_proforma_grade(grade_data, grading_policy)
                progress_summary = grades.progress_summary(user, course)
                try:
                    gradebook_entry = StudentGradebook.objects.get(user=user, course_id=course.id)
                    if (gradebook_entry.grade != grade or
                            gradebook_entry.proforma_grade != proforma_grade or
                            gradebook_entry.progress_summary != progress_summary or
                            gradebook_entry.grade_summary != grade_data or
                            gradebook_entry.grading_policy != grading_policy):
                        gradebook_entry.grade = grade
                        gradebook_entry.proforma_grade = proforma_grade
                        gradebook_entry.progress_summary = json.dumps(progress_summary, cls=EdxJSONEncoder)
                        gradebook_entry.grade_summary = json.dumps(grade_data, cls=EdxJSONEncoder)
                        gradebook_entry.grading_policy = json.dumps(grading_policy, cls=EdxJSONEncoder)
                        gradebook_entry.save()
                except StudentGradebook.DoesNotExist:
                    StudentGradebook.objects.create(
                        user=user,
                        course_id=course.id,
                        grade=grade,
                        proforma_grade=proforma_grade,
                        progress_summary=json.dumps(progress_summary, cls=EdxJSONEncoder),
                        grade_summary=json.dumps(grade_data, cls=EdxJSONEncoder),
                        grading_policy=json.dumps(grading_policy, cls=EdxJSONEncoder)
                    )
                log_msg = 'Gradebook entry created -- Course: {}, User: {}  (grade: {}, proforma_grade: {})'.format(course.id, user.id, grade, proforma_grade)
                print log_msg
                log.info(log_msg)
Example #14
0
    def _create_cert_pdf(self, student, request, course):
        cert, created = GeneratedCertificate.objects.get_or_create(
            course_id=self.course_id, user=student)

        grade = grades.grade(cert.user, request, course)
        print "User {0}: Grade {1}% - {2}".format(
            cert.user, grade['percent'] * 100, grade['grade']),

        profile = UserProfile.objects.get(user=student)
        cert.grade = grade['percent']
        cert.mode = 'honor'
        cert.user = student
        cert.course_id = self.course_id
        cert.name = profile.name

        is_whitelisted = CertificateWhitelist.objects.filter(
            user=student, course_id=self.course_id, whitelist=True
        ).exists()

        if is_whitelisted or grade['grade']:
            if profile.allow_certificate is False:
                new_status = CertificateStatuses.restricted
                cert.status = new_status
                print ": Status {0}".format(new_status)
                if not self.noop:
                    cert.save()
            else:
                key = self._make_hashkey(self.course_id.to_deprecated_string() + student.username)
                cert.key = key

                if not self.noop:
                    response_json = create_cert_pdf(
                        student.username, self.course_id, cert.key, cert.name,
                        course.display_name, grade['percent'], self.file_prefix)
                    response = json.loads(response_json)
                    self._dprint(": Response = {}".format(response), newline=False)
                    cert.download_url = response.get(u'download_url', False)
                    msg = response.get(u'error', False)

                    if msg is False:
                        new_status = CertificateStatuses.generating
                        cert.status = new_status
                        cert.save()
                        print ": Status {0}".format(new_status)
                    else:
                        new_status = CertificateStatuses.error
                        cert.status = new_status
                        cert.save()
                        print ": Status {0}".format(new_status),
                        print ": Error {}".format(msg)
                else:
                    print ": Status {0} (Noop)".format(cert.status)
        else:
            new_status = CertificateStatuses.notpassing
            cert.status = new_status
            print ": Status {0}".format(new_status)
            if not self.noop:
                cert.save()
Example #15
0
    def get_raw(self, command="all"):
        """Get raw data of progress."""
        if not OPERATION.has_key(command):
            log.error('Invalid command: {}'.format(command))
            raise InvalidCommand("Invalid command: {}".format(command))

        if command == "summary":
            return self.courseware_summary

        self.courseware_summary["graded_students"] = 0
        student_count = 0
        for student in self.students.iterator():
            student_count += 1
            if (student_count % 100
                    == 0) or (student_count
                              == self.courseware_summary['active_students']):
                msg = "Progress %d/%d" % (
                    student_count, self.courseware_summary['active_students'])

                if self.update_state is not None:
                    self.update_state(state=msg)

                log.info(msg)

            self.request.user = student
            log.debug(" * Active user: {}".format(student))
            grade = grades.grade(student, self.request, self.course)

            if grade["grade"] is not None:
                self.courseware_summary["graded_students"] += 1

            for category in self.location_list.keys():
                if category not in ["problem"]:
                    continue

                for loc in self.location_list[category]:
                    log.debug(" * Active location: {}".format(loc))
                    module = get_module_for_student(student, loc)

                    if module is None:
                        log.debug(" * No state found: %s" % (student))
                        continue

                    self.collect_module_summary(module)

        cache.set('progress_summary',
                  self.courseware_summary["graded_students"],
                  timeout=24 * 60 * 60)

        #statistics = self._calc_statistics()
        #for key in statistics.keys():
        #    self.module_summary[key].update(statistics[key])

        if command == "modules":
            return self.module_summary

        return self.courseware_summary, self.module_summary
Example #16
0
    def get_grade_summary(self):
        '''calls grades.grade for current user and course'''
        model_data_cache = ModelDataCache.cache_for_descriptor_descendents(
            self.course.id, self.student_user, self.course)

        fake_request = self.factory.get(reverse('progress',
                                        kwargs={'course_id': self.course.id}))

        return grades.grade(self.student_user, fake_request,
                            self.course, model_data_cache)
Example #17
0
    def get_grade_summary(self):
        '''calls grades.grade for current user and course'''
        model_data_cache = ModelDataCache.cache_for_descriptor_descendents(
            self.course.id, self.student_user, self.course)

        fake_request = self.factory.get(
            reverse('progress', kwargs={'course_id': self.course.id}))

        return grades.grade(self.student_user, fake_request, self.course,
                            model_data_cache)
Example #18
0
def _progress(request, course_key, student_id):
    """
    Unwrapped version of "progress".

    User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user, 'load', course_key, depth=None, check_if_enrolled=True)

    # check to see if there is a required survey that must be taken before
    # the user can access the course.
    if survey.utils.must_answer_survey(course, request.user):
        return redirect(reverse('course_survey', args=[unicode(course.id)]))

    staff_access = has_access(request.user, 'staff', course)

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    courseware_summary = grades.progress_summary(student, request, course)
    studio_url = get_studio_url(course, 'settings/grading')
    grade_summary = grades.grade(student, request, course)

    if courseware_summary is None:
        #This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {
        'course': course,
        'courseware_summary': courseware_summary,
        'studio_url': studio_url,
        'grade_summary': grade_summary,
        'staff_access': staff_access,
        'student': student,
        'reverifications': fetch_reverify_banner_info(request, course_key)
    }

    with grades.manual_transaction():
        response = render_to_response('courseware/progress.html', context)

    return response
Example #19
0
def _grade_with_errors(student, request, course, keep_raw_scores=False):
    """This fake grade method will throw exceptions for student3 and
    student4, but allow any other students to go through normal grading.

    It's meant to simulate when something goes really wrong while trying to
    grade a particular student, so we can test that we won't kill the entire
    course grading run.
    """
    if student.username in ['student3', 'student4']:
        raise Exception("I don't like {}".format(student.username))

    return grade(student, request, course, keep_raw_scores=keep_raw_scores)
Example #20
0
def _grade_with_errors(student, request, course, keep_raw_scores=False):
    """This fake grade method will throw exceptions for student3 and
    student4, but allow any other students to go through normal grading.

    It's meant to simulate when something goes really wrong while trying to
    grade a particular student, so we can test that we won't kill the entire
    course grading run.
    """
    if student.username in ['student3', 'student4']:
        raise Exception("I don't like {}".format(student.username))

    return grade(student, request, course, keep_raw_scores=keep_raw_scores)
Example #21
0
def is_student_pass(user, request, course_id):
    course_key = locator.CourseLocator.from_string(course_id)
    course = modulestore().get_course(course_key)

    if not settings.FEATURES.get('ENABLE_ISSUE_CERTIFICATE'):
        return False

    # If user is course staff don't grade the user
    if has_access(user, 'staff', course):
        return True

    return bool(grade(user, request, course)['grade'])
Example #22
0
def is_student_pass(user, request, course_id):
    course_key = locator.CourseLocator.from_string(course_id)
    course = modulestore().get_course(course_key)

    if not settings.FEATURES.get('ENABLE_ISSUE_CERTIFICATE'):
        return False

    # If user is course staff don't grade the user
    if has_access(user, 'staff', course):
        return True

    return bool(grade(user, request, course)['grade'])
Example #23
0
    def yield_students_progress(self):
        """Yield progress of students as CSV row."""
        header_flag = False
        student_count = 0
        for student in self.students.iterator():
            student_count += 1
            if (student_count % 100
                    == 0) or (student_count
                              == self.courseware_summary['active_students']):
                msg = "Progress %d/%d" % (
                    student_count, self.courseware_summary['active_students'])

                if self.update_state is not None:
                    self.update_state(state=msg)

                log.info(msg)

            self.request.user = student
            grade = grades.grade(student, self.request, self.course)

            for category in self.location_list.keys():
                if category not in ["problem"]:
                    continue

                for loc in self.location_list[category]:
                    module = get_module_for_student(student, loc)

                    if module is None:
                        log.debug(" * No state found: %s" % (student))
                        continue

                    module_data = self._get_module_data(module)
                    csvrow = [
                        student.username, module.location,
                        student.last_login.strftime("%Y/%m/%d %H:%M:%S %Z"),
                        grade["grade"], grade["percent"]
                    ]

                    if header_flag is False:
                        header = [
                            "username", "location", "last_login", "grade",
                            "percent"
                        ]
                        for key in module_data.keys():
                            header.append(key)
                        header_flag = True
                        yield header

                    for key in module_data.keys():
                        csvrow.append(module_data[key])

                    yield csvrow
Example #24
0
    def handle(self, *args, **options):
        if os.path.exists(options['output']):
            raise CommandError("File {0} already exists".format(
                options['output']))

        STATUS_INTERVAL = 100
        course_id = options['course']
        print "Fetching enrolled students for {0}".format(course_id)
        enrolled_students = User.objects.filter(
            courseenrollment__course_id=course_id)
        factory = RequestMock()
        request = factory.get('/')

        total = enrolled_students.count()
        print "Total enrolled: {0}".format(total)
        course = courses.get_course_by_id(course_id)
        total = enrolled_students.count()
        start = datetime.datetime.now()
        rows = []
        header = None
        print "Fetching certificate data"
        cert_grades = {cert.user.username: cert.grade
                       for cert in list(GeneratedCertificate.objects.filter(
                       course_id=course_id).prefetch_related('user'))}
        print "Grading students"
        for count, student in enumerate(enrolled_students):
            count += 1
            if count % STATUS_INTERVAL == 0:
                # Print a status update with an approximation of
                # how much time is left based on how long the last
                # interval took
                diff = datetime.datetime.now() - start
                timeleft = diff * (total - count) / STATUS_INTERVAL
                hours, remainder = divmod(timeleft.seconds, 3600)
                minutes, seconds = divmod(remainder, 60)
                print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format(
                    count, total, hours, minutes)
                start = datetime.datetime.now()
            request.user = student
            grade = grades.grade(student, request, course)
            if not header:
                header = [section['label'] for section in grade[u'section_breakdown']]
                rows.append(["email", "username", "certificate-grade", "grade"] + header)
            percents = {section['label']: section['percent'] for section in grade[u'section_breakdown']}
            row_percents = [percents[label] for label in header]
            if student.username in cert_grades:
                rows.append([student.email, student.username, cert_grades[student.username], grade['percent']] + row_percents)
            else:
                rows.append([student.email, student.username, "N/A", grade['percent']] + row_percents)
        with open(options['output'], 'wb') as f:
            writer = csv.writer(f)
            writer.writerows(rows)
    def get_grade_summary(self):
        """
        calls grades.grade for current user and course.

        the keywords for the returned object are
        - grade : A final letter grade.
        - percent : The final percent for the class (rounded up).
        - section_breakdown : A breakdown of each section that makes
            up the grade. (For display)
        - grade_breakdown : A breakdown of the major components that
            make up the final grade. (For display)
        """
        return grades.grade(self.student_user, self.course)
Example #26
0
def _progress(request, course_id, student_id):
    """
    Unwrapped version of "progress".

    User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user,
                                    course_id,
                                    'load',
                                    depth=None)
    staff_access = has_access(request.user, course, 'staff')

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    courseware_summary = grades.progress_summary(student, request, course)

    grade_summary = grades.grade(student, request, course)

    if courseware_summary is None:
        #This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {
        'course': course,
        'courseware_summary': courseware_summary,
        'grade_summary': grade_summary,
        'staff_access': staff_access,
        'student': student,
    }

    with grades.manual_transaction():
        response = render_to_response('courseware/progress.html', context)

    return response
Example #27
0
    def handle(self, *args, **options):
        if os.path.exists(options['output']):
            raise CommandError("File {0} already exists".format(
                options['output']))

        STATUS_INTERVAL = 100
        course_id = options['course']
        print "Fetching enrolled students for {0}".format(course_id)
        enrolled_students = User.objects.filter(
            courseenrollment__course_id=course_id).prefetch_related(
                "groups").order_by('username')
        factory = RequestMock()
        request = factory.get('/')

        total = enrolled_students.count()
        print "Total enrolled: {0}".format(total)
        course = courses.get_course_by_id(course_id)
        total = enrolled_students.count()
        start = datetime.datetime.now()
        rows = []
        header = None
        for count, student in enumerate(enrolled_students):
            count += 1
            if count % STATUS_INTERVAL == 0:
                # Print a status update with an approximation of
                # how much time is left based on how long the last
                # interval took
                diff = datetime.datetime.now() - start
                timeleft = diff * (total - count) / STATUS_INTERVAL
                hours, remainder = divmod(timeleft.seconds, 3600)
                minutes, seconds = divmod(remainder, 60)
                print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format(
                    count, total, hours, minutes)
                start = datetime.datetime.now()
            request.user = student
            grade = grades.grade(student, request, course)
            if not header:
                header = [
                    section['label'] for section in grade[u'section_breakdown']
                ]
                rows.append(["email", "username"] + header)
            percents = {
                section['label']: section['percent']
                for section in grade[u'section_breakdown']
            }
            row_percents = [percents[label] for label in header]
            rows.append([student.email, student.username] + row_percents)
        with open(options['output'], 'wb') as f:
            writer = csv.writer(f)
            writer.writerows(rows)
Example #28
0
def _progress(request, course_id, student_id):
    """
    Unwrapped version of "progress".

    User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user, course_id, "load", depth=None)
    staff_access = has_access(request.user, course, "staff")

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    courseware_summary = grades.progress_summary(student, request, course)
    studio_url = get_studio_url(course_id, "settings/grading")
    grade_summary = grades.grade(student, request, course)

    if courseware_summary is None:
        # This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {
        "course": course,
        "courseware_summary": courseware_summary,
        "studio_url": studio_url,
        "grade_summary": grade_summary,
        "staff_access": staff_access,
        "student": student,
        "reverifications": fetch_reverify_banner_info(request, course_id),
    }

    with grades.manual_transaction():
        response = render_to_response("courseware/progress.html", context)

    return response
Example #29
0
def get_api(request, course_id):
    """
    **Use Cases**

        Retrieve final grade of the user.

    **Example Requests**:

        GET: /final_grades/course_id

        GET: /final_grades/course-v1:test+test111+2014_T3

    **Returns**:

        Course_id: id of the course

        User: current user

        Grade: Final Grade of the user

        Error: If any error persists

    """
    if request.user.is_authenticated():
        user = request.user

        try:
            course_key = SlashSeparatedCourseKey.from_deprecated_string(
                course_id)
            course = get_course_with_access(user,
                                            'load',
                                            course_key,
                                            depth=None)
        except Exception as e:
            return Response(data={"Error": e.message})

        try:
            grade_summary = grades.grade(user, request, course)
            return Response(
                data={
                    "User": request.user.username,
                    "Course ID": course_id,
                    "Grade": grade_summary.get('percent')
                })
        except Exception as e:
            return Response(data={"Error": e.message})
    else:
        return Response(
            data={"Error": "Authentication credentials were not provided."})
def generate_fun_certificate(student,
                             course_id,
                             course_display_name, course,
                             teachers,
                             organization_display_name, organization_logo,
                             certificate_base_filename, ignore_grades, new_grade, fail_flag):
    """Generates a certificate for one student and one course."""

    profile = UserProfile.objects.get(user=student)
    student_name = unicode(profile.name).encode('utf-8')
    # grade the student
    cert, _created = GeneratedCertificate.objects.get_or_create(
        user=student, course_id=course_id
    )
    request.user = student
    grade = grades.grade(student, request, course)
    cert.grade = grade['percent']
    cert.user = student
    cert.course_id = course_id
    cert.name = profile.name
    fail = False

    if ignore_grades:
        cert.grade = 1
    elif new_grade:
        fail = fail_flag
        cert.grade = new_grade
    elif grade['grade'] is None:
        ## edx grading
        fail = True

    if fail:
        cert.status = status.notpassing
    else:
        key = make_hashkey(random.random())
        cert.key = key
        certificate_filename = certificate_base_filename + key + ".pdf"
        certificate_language = Course.get_course_language(unicode(course_id))
        info = CertificateInfo(
            student_name, course_display_name,
            organization_display_name, organization_logo,
            certificate_filename, teachers, language=certificate_language
        )
        info.generate()

        cert.status = status.downloadable
        cert.download_url = settings.CERTIFICATE_BASE_URL + certificate_filename
    cert.save()
    return cert.status
def generate_fun_certificate(student, course_id, course_display_name, course, teachers, organization_display_name, organization_logo, certificate_base_filename,ignore_grades, new_grade):
    """Generates a certificate for one student and one course."""

    profile = UserProfile.objects.get(user=student)
    student_name = unicode(profile.name).encode('utf-8')
    # grade the student
    cert, created = GeneratedCertificate.objects.get_or_create(
        user=student, course_id=course_id)

    request.user = student
    grade = grades.grade(student, request, course)
    cert.grade = grade['percent']
    cert.user = student
    cert.course_id = course_id
    cert.name = profile.name

    if ignore_grades:
      grade['grade'] = 'A'
      grade['percent'] = 100.0

    if new_grade:
        grade['grade'] = 'A'
        cert.grade = new_grade
        cert.save()

    if grade['grade'] is None:
        cert.status = status.notpassing
    else:
        key = make_hashkey(random.random())
        cert.key = key
        info = CertificateInfo()
        info.full_name = student_name
        info.course_name = course_display_name
        info.teachers = teachers
        info.organization = organization_display_name
        info.organization_logo = organization_logo
        certificate_filename = certificate_base_filename + key + ".pdf";

        info.pdf_file_name = os.path.join(
            settings.CERTIFICATES_DIRECTORY, certificate_filename)
        if info.generate():
            cert.status = status.downloadable
            cert.download_url = settings.CERTIFICATE_BASE_URL + certificate_filename
        else:
            cert.status = status.error
            cert.error_reason = "Error while generating PDF file"
    cert.save()
    return cert.status
Example #32
0
def get_final_score(request, course):
    """
    To get the final score for the user in
    particular course.
    """
    grade_summary = {}
    student = request.user

    try:
        grade_summary = grades.grade(student, request, course)
    except:
        pass

    final_grade = grade_summary.get('percent', 0)

    return int(final_grade * 100)
    def handle(self, *args, **options):
        course_id = options['course']
        print "Fetching ungraded students for {0}".format(course_id)
        ungraded = GeneratedCertificate.objects.filter(
            course_id__exact=course_id).filter(grade__exact='')
        course = courses.get_course_by_id(course_id)
        factory = RequestFactory()
        request = factory.get('/')

        for cert in ungraded:
            # grade the student
            grade = grades.grade(cert.user, request, course)
            print "grading {0} - {1}".format(cert.user, grade['percent'])
            cert.grade = grade['percent']
            if not options['noop']:
                cert.save()
    def get_grade_summary(self):
        """
        calls grades.grade for current user and course.

        the keywords for the returned object are
        - grade : A final letter grade.
        - percent : The final percent for the class (rounded up).
        - section_breakdown : A breakdown of each section that makes
            up the grade. (For display)
        - grade_breakdown : A breakdown of the major components that
            make up the final grade. (For display)
        """

        fake_request = self.factory.get(reverse("progress", kwargs={"course_id": self.course.id}))

        return grades.grade(self.student_user, fake_request, self.course)
Example #35
0
    def handle(self, *args, **options):
        course_id = options['course']
        print "Fetching ungraded students for {0}".format(course_id)
        ungraded = GeneratedCertificate.objects.filter(
            course_id__exact=course_id).filter(grade__exact='')
        course = courses.get_course_by_id(course_id)
        factory = RequestFactory()
        request = factory.get('/')

        for cert in ungraded:
            # grade the student
            grade = grades.grade(cert.user, request, course)
            print "grading {0} - {1}".format(cert.user, grade['percent'])
            cert.grade = grade['percent']
            if not options['noop']:
                cert.save()
def student_grades(student, request, course, keep_raw_scores=False, use_offline=False):
    '''
    This is the main interface to get grades.  It has the same parameters as grades.grade, as well
    as use_offline.  If use_offline is True then this will look for an offline computed gradeset in the DB.
    '''

    if not use_offline:
        return grades.grade(student, request, course, keep_raw_scores=keep_raw_scores)

    try:
        ocg = models.OfflineComputedGrade.objects.get(user=student, course_id=course.id)
    except models.OfflineComputedGrade.DoesNotExist:
        return dict(raw_scores=[], section_breakdown=[],
                    msg='Error: no offline gradeset available for %s, %s' % (student, course.id))

    return json.loads(ocg.gradeset)
Example #37
0
def get_student_course_grade(request, course_key_string, username):
    """
    A server to server api view which computes and returns the student's grade for
    a course. A boolean `passed` property is computed and bound to the grade summary
    dict to know if student has passed or not the course according to the course grade
    cutoffs.

    Example of response :
    {
        "section_breakdown": [
            {
                "category": "Exams",
                "percent": 1.0,
                "detail": "Exams 1 - First section - 100% (1/1)",
                "label": "Exam 01"
            },
        ],
        "passed": true,
        "grade": "A",
        "totaled_scores": {
            "Exams": [[1.0, 1.0, true, "First section", null]],
        },
        "percent": 1.0,
        "grade_breakdown": [
            {
                "category": "Exams",
                "percent": 1.0,
                "detail": "Exams = 100.00% of a possible 100.00%"
            },
        ]
    }
    """

    try:
        student = User.objects.get(username=username)
        course_key = CourseKey.from_string(course_key_string)
        course = courses.get_course(course_key)
    except (User.DoesNotExist, ValueError) as error:
        return Response(str(error), status=404)

    grade_summary = grade(student, request, course, keep_raw_scores=False)
    grade_summary.update({
        'passed':
        _computed_passed(course.grade_cutoffs, grade_summary.get('percent'))
    })

    return Response(grade_summary, status=200)
Example #38
0
def offline_grade_calculation(course_id):
    '''
    Compute grades for all students for a specified course, and save results to the DB.
    '''

    tstart = time.time()
    enrolled_students = User.objects.filter(
        courseenrollment__course_id=course_id).prefetch_related(
            "groups").order_by('username')

    enc = MyEncoder()

    class DummyRequest(object):
        META = {}

        def __init__(self):
            return

        def get_host(self):
            return 'edx.mit.edu'

        def is_secure(self):
            return False

    request = DummyRequest()

    print "%d enrolled students" % len(enrolled_students)
    course = get_course_by_id(course_id)

    for student in enrolled_students:
        gradeset = grades.grade(student, request, course, keep_raw_scores=True)
        gs = enc.encode(gradeset)
        ocg, created = models.OfflineComputedGrade.objects.get_or_create(
            user=student, course_id=course_id)
        ocg.gradeset = gs
        ocg.save()
        print "%s done" % student  # print statement used because this is run by a management command

    tend = time.time()
    dt = tend - tstart

    ocgl = models.OfflineComputedGradeLog(course_id=course_id,
                                          seconds=dt,
                                          nstudents=len(enrolled_students))
    ocgl.save()
    print ocgl
    print "All Done!"
    def extract_student(student, features):
        """ convert student to dictionary """
        student_features = [x for x in STUDENT_FEATURES if x in features]
        profile_features = [x for x in PROFILE_FEATURES if x in features] 

        student_dict = dict((feature, getattr(student, feature))
                            for feature in student_features)
        profile = student.profile
        if profile is not None:
            profile_dict = dict((feature, getattr(profile, feature))
                                for feature in profile_features)
            student_dict.update(profile_dict)

        try:
            student_dict['district']=profile.district.name
        except:
            student_dict['district']=''

        try:
            student_dict['cohort']=profile.cohort.code
        except:
            student_dict['cohort']=''

        try:
            student_dict['school']=profile.school.name
        except:
            student_dict['school']=''

        try:
            reg=Registration.objects.get(user_id=student.id)
            student_dict['activate_key']=reg.activation_key
        except:
            student_dict['activate_key']=''

        try:
            if course_completed(request,student,course):
                student_dict['completed']='YES'
            else:
                student_dict['completed']='NO'
        except Exception as e:
            student_dict['completed']='error'

        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(course_id, student, course, depth=None)
        grade_summary = grades.grade(student, request, course, field_data_cache)
        student_dict['progress']="{totalscore:.0%}".format(totalscore=grade_summary['percent'])

        return student_dict
Example #40
0
    def get_grade_summary(self):
        """
        calls grades.grade for current user and course.

        the keywords for the returned object are
        - grade : A final letter grade.
        - percent : The final percent for the class (rounded up).
        - section_breakdown : A breakdown of each section that makes
            up the grade. (For display)
        - grade_breakdown : A breakdown of the major components that
            make up the final grade. (For display)
        """

        fake_request = self.factory.get(
            reverse('progress', kwargs={'course_id': self.course.id}))

        return grades.grade(self.student_user, fake_request, self.course)
    def handle(self, *args, **options):

        course_id = options.get('course_id')
        course_ids = []

        if course_id:
            course_ids.append(course_id)
        else:
            course_ids = StudentGradebook.objects.filter(
                grade_summary='').values_list('course_id', flat=True)

        for course_id in course_ids:
            course_key = CourseKey.from_string(course_id)
            users = CourseEnrollment.objects.users_enrolled_in(course_key)
            course = modulestore().get_course(course_key, depth=None)
            if course:
                # For each user...
                for user in users:
                    request = RequestMockWithoutMiddleware().get('/')
                    request.user = user
                    grade_data = grades.grade(user, course)
                    grade = grade_data['percent']
                    grading_policy = course.grading_policy
                    proforma_grade = grades.calculate_proforma_grade(
                        grade_data, grading_policy)
                    progress_summary = grades.progress_summary(user, course)
                    try:
                        gradebook_entry = StudentGradebook.objects.get(
                            user=user, course_id=course.id)
                        if not gradebook_entry.grade_summary:
                            gradebook_entry.grade = grade
                            gradebook_entry.proforma_grade = proforma_grade
                            gradebook_entry.progress_summary = json.dumps(
                                progress_summary, cls=EdxJSONEncoder)
                            gradebook_entry.grade_summary = json.dumps(
                                grade_data, cls=EdxJSONEncoder)
                            gradebook_entry.grading_policy = json.dumps(
                                grading_policy, cls=EdxJSONEncoder)
                            gradebook_entry.save()
                    except StudentGradebook.DoesNotExist:
                        pass

                    log_msg = 'Gradebook entry created -- Course: {}, User: {}  (grade: {}, proforma_grade: {})'.format(
                        course.id, user.id, grade, proforma_grade)
                    log.info(log_msg)
Example #42
0
def get_student_certificate_grade(course_id, student):
    """Compute the student grade for the certificate exercises in a course

    Returns:
        grade (float or None): returns None if the course does not include any
        'certificate' exercise.
    """
    request = RequestFactory().get('/')
    request.session = {}
    request.user = student

    course = modulestore().get_course(course_id)
    grades = courseware_grades.grade(student, request, course)
    sections_grades = grades['section_breakdown']
    for section in sections_grades:
        if section['label'].lower() in ASSIGNMENT_VALID_SHORT_NAMES:
            return section['percent']
    return None
Example #43
0
def get_student_certificate_grade(course_id, student):
    """Compute the student grade for the certificate exercises in a course

    Returns:
        grade (float or None): returns None if the course does not include any
        'certificate' exercise.
    """
    request = RequestFactory().get('/')
    request.session = {}
    request.user = student

    course = modulestore().get_course(course_id)
    grades = courseware_grades.grade(student, request, course)
    sections_grades = grades['section_breakdown']
    for section in sections_grades:
        if section['label'].lower() in ASSIGNMENT_VALID_SHORT_NAMES:
            return section['percent']
    return None
Example #44
0
def progress(request, course_id, student_id=None):
    """ User progress. We show the grade bar and every problem score.

    Course staff are allowed to see the progress of students in their class.
    """
    course = get_course_with_access(request.user, course_id, 'load', depth=None)
    staff_access = has_access(request.user, course, 'staff')

    if student_id is None or student_id == request.user.id:
        # always allowed to see your own profile
        student = request.user
    else:
        # Requesting access to a different student's profile
        if not staff_access:
            raise Http404
        student = User.objects.get(id=int(student_id))

    # NOTE: To make sure impersonation by instructor works, use
    # student instead of request.user in the rest of the function.

    # The pre-fetching of groups is done to make auth checks not require an
    # additional DB lookup (this kills the Progress page in particular).
    student = User.objects.prefetch_related("groups").get(id=student.id)

    field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
        course_id, student, course, depth=None)

    courseware_summary = grades.progress_summary(student, request, course,
                                                 field_data_cache)
    grade_summary = grades.grade(student, request, course, field_data_cache)

    if courseware_summary is None:
        #This means the student didn't have access to the course (which the instructor requested)
        raise Http404

    context = {'course': course,
               'courseware_summary': courseware_summary,
               'grade_summary': grade_summary,
               'staff_access': staff_access,
               'student': student,
               }
    context.update()

    return render_to_response('courseware/progress.html', context)
Example #45
0
def student_grades(student,
                   request,
                   course,
                   keep_raw_scores=False,
                   use_offline=False):
    '''
    This is the main interface to get grades.  It has the same parameters as grades.grade, as well
    as use_offline.  If use_offline is True then this will look for an offline computed gradeset in the DB.
    '''
    if not use_offline:
        return grades.grade(student,
                            request,
                            course,
                            keep_raw_scores=keep_raw_scores)

    try:
        ocg = models.OfflineComputedGrade.objects.get(user=student,
                                                      course_id=course.id)
    except models.OfflineComputedGrade.DoesNotExist:
        return dict(
            raw_scores=[],
            section_breakdown=[],
            msg='Error: no offline gradeset available for {}, {}'.format(
                student, course.id))

    gradeset = json.loads(ocg.gradeset)

    # Convert score dicts back to Score tuples:

    def score_from_dict(encoded):
        """ Given a formerly JSON-encoded Score tuple, return the Score tuple """
        if encoded['module_id']:
            encoded['module_id'] = UsageKey.from_string(encoded['module_id'])
        return Score(**encoded)

    totaled_scores = gradeset['totaled_scores']
    for section in totaled_scores:
        totaled_scores[section] = [
            score_from_dict(score) for score in totaled_scores[section]
        ]
    gradeset['raw_scores'] = [
        score_from_dict(score) for score in gradeset['raw_scores']
    ]
    return gradeset
Example #46
0
def generate_fun_certificate(student, course, teachers, university):
    """Generates a certificate for one student and one course."""

    # grade the student
    cert, _created = GeneratedCertificate.objects.get_or_create(
        user=student, course_id=course.id
    )

    # TODO We need to create a request object manually. It's very ugly and we should
    # do something about it.
    request = RequestFactory().get('/')
    request.session = {}
    request.user = student

    grade = grades.grade(student, request, course)
    cert.grade = grade['percent']
    cert.name = student.profile.name

    if grade['grade'] is None:
        cert.status = CertificateStatuses.notpassing
    else:
        key = make_certificate_hash_key()
        certificate_filename = "attestation_suivi_{}_{}.pdf".format(
            (unicode(course.id).replace('/', '_')),
            key
        )
        cert.key = key
        certificate_language = Course.get_course_language(unicode(course.id))
        course_display_name = unicode(course.display_name).encode('utf-8')

        CertificateInfo(
            student.profile.name, course_display_name,
            university,
            certificate_filename, teachers, language=certificate_language
        ).generate()

        set_certificate_filename(cert, certificate_filename)
    cert.save()
    logger.info("Honor certificate status for student {}: {}".format(student.username, cert.status))

    trigger_tracking_log(cert, course, student)

    return cert.status
Example #47
0
def get_student_course_stats_base(request, course, type="grades"):
    """
    Called by get_student_course_stats and get_student_problem_stats
    Gets a list of users in a course, and then computes grades for them
    request - a mock request (using RequestDict)
    course - a string course id
    type - whether to get student weighted grades or unweighted grades.  If "grades" will get weighted
    """
    fs, db = common.get_db_and_fs_cron(common.student_course_stats_stub)
    course_obj = get_course_with_access(request.user,
                                        course,
                                        'load',
                                        depth=None)
    users_in_course = StudentModule.objects.filter(
        course_id=course).values('student').distinct()
    users_in_course_ids = [u['student'] for u in users_in_course]
    log.debug("Users in course count: {0}".format(len(users_in_course_ids)))
    courseware_summaries = []
    for i in xrange(0, len(users_in_course_ids)):
        try:
            user = users_in_course_ids[i]
            current_task.update_state(state='PROGRESS',
                                      meta={
                                          'current': i,
                                          'total': len(users_in_course_ids)
                                      })
            student = User.objects.using('remote').prefetch_related(
                "groups").get(id=int(user))

            model_data_cache = None

            if type == "grades":
                grade_summary = grades.grade(student, request, course_obj,
                                             model_data_cache)
            else:
                grade_summary = grades.progress_summary(
                    student, request, course_obj, model_data_cache)
            courseware_summaries.append(grade_summary)
        except:
            log.exception("Could not generate data for {0}".format(
                users_in_course_ids[i]))
    return courseware_summaries, users_in_course_ids
Example #48
0
def generate_fun_certificate(student, course, teachers, university):
    """Generates a certificate for one student and one course."""

    # grade the student
    cert, _created = GeneratedCertificate.objects.get_or_create(
        user=student, course_id=course.id)

    # TODO We need to create a request object manually. It's very ugly and we should
    # do something about it.
    request = RequestFactory().get('/')
    request.session = {}
    request.user = student

    grade = grades.grade(student, request, course)
    cert.grade = grade['percent']
    cert.name = student.profile.name

    if grade['grade'] is None:
        cert.status = CertificateStatuses.notpassing
    else:
        key = make_certificate_hash_key()
        certificate_filename = "attestation_suivi_{}_{}.pdf".format(
            (unicode(course.id).replace('/', '_')), key)
        cert.key = key
        certificate_language = Course.get_course_language(unicode(course.id))
        course_display_name = unicode(course.display_name).encode('utf-8')

        CertificateInfo(student.profile.name,
                        course_display_name,
                        university,
                        certificate_filename,
                        teachers,
                        language=certificate_language).generate()

        set_certificate_filename(cert, certificate_filename)
    cert.save()
    logger.info("Honor certificate status for student {}: {}".format(
        student.username, cert.status))

    trigger_tracking_log(cert, course, student)

    return cert.status
def is_course_passed(course, grade_summary=None, student=None, request=None):
    """
    check user's course passing status. return True if passed

    Arguments:
        course : course object
        grade_summary (dict) : contains student grade details.
        student : user object
        request (HttpRequest)

    Returns:
        returns bool value
    """
    nonzero_cutoffs = [cutoff for cutoff in course.grade_cutoffs.values() if cutoff > 0]
    success_cutoff = min(nonzero_cutoffs) if nonzero_cutoffs else None

    if grade_summary is None:
        grade_summary = grades.grade(student, request, course)

    return success_cutoff and grade_summary['percent'] >= success_cutoff
Example #50
0
def has_passed(request, course_id, section_url_name):
    """
    Returns True if the student has higher or equeal grades in
    asssignment type.
    """
    student = request.user

    # Get the course by ID
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(student, 'load', course_key, depth=None)

    # Get the grade summary
    with outer_atomic():
        field_data_cache = grades.field_data_cache_for_grading(course, student)
        scores_client = ScoresClient.from_field_data_cache(field_data_cache)

    grade_summary = grades.grade(student,
                                 request,
                                 course,
                                 field_data_cache=field_data_cache,
                                 scores_client=scores_client)

    # Get assignment type wise percent
    assignments = {}
    for section in grade_summary['section_breakdown']:
        if section.get('prominent', False):
            assignments.update({section['category']: section['percent']})

    # Get the section assignment type
    section_assignment_type = ''
    for chapter in course.get_children():
        for sequenctial in chapter.get_children():
            if sequenctial.url_name == section_url_name:
                section_assignment_type = sequenctial.format
                break

    # Get section assignment percent
    percentage = assignments.get(section_assignment_type, 0.0)

    # Return passing status
    return percentage * 100 == 100
def offline_grade_calculation(course_key):
    '''
    Compute grades for all students for a specified course, and save results to the DB.
    '''

    tstart = time.time()
    enrolled_students = User.objects.filter(
        courseenrollment__course_id=course_key,
        courseenrollment__is_active=1
    ).prefetch_related("groups").order_by('username')

    enc = MyEncoder()

    print "{} enrolled students".format(len(enrolled_students))
    course = get_course_by_id(course_key)

    for student in enrolled_students:
        request = DummyRequest()
        request.user = student
        request.session = {}

        gradeset = grades.grade(student, request, course, keep_raw_scores=True)
        # Convert Score namedtuples to dicts:
        totaled_scores = gradeset['totaled_scores']
        for section in totaled_scores:
            totaled_scores[section] = [score._asdict() for score in totaled_scores[section]]
        gradeset['raw_scores'] = [score._asdict() for score in gradeset['raw_scores']]
        # Encode as JSON and save:
        gradeset_str = enc.encode(gradeset)
        ocg, _created = models.OfflineComputedGrade.objects.get_or_create(user=student, course_id=course_key)
        ocg.gradeset = gradeset_str
        ocg.save()
        print "%s done" % student  	# print statement used because this is run by a management command

    tend = time.time()
    dt = tend - tstart

    ocgl = models.OfflineComputedGradeLog(course_id=course_key, seconds=dt, nstudents=len(enrolled_students))
    ocgl.save()
    print ocgl
    print "All Done!"
    def get_grade_summary(self):
        """
        calls grades.grade for current user and course.

        the keywords for the returned object are
        - grade : A final letter grade.
        - percent : The final percent for the class (rounded up).
        - section_breakdown : A breakdown of each section that makes
            up the grade. (For display)
        - grade_breakdown : A breakdown of the major components that
            make up the final grade. (For display)
        """

        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            self.course.id, self.student_user, self.course)

        fake_request = self.factory.get(reverse('progress',
                                        kwargs={'course_id': self.course.id}))

        return grades.grade(self.student_user, fake_request,
                            self.course, field_data_cache)
def _generate_user_gradebook(course_key, user):
    """
    Recalculates the specified user's gradebook entry
    """
    # import is local to avoid recursive import
    from courseware.courses import get_course
    course_descriptor = get_course(course_key, depth=None)
    grading_policy = course_descriptor.grading_policy
    request = RequestMockWithoutMiddleware().get('/')
    request.user = user
    request.course_descriptor = course_descriptor
    progress_summary = progress_summary_wrapped(request, course_id)
    log.info(progress_summary)
    grade_summary = grades.grade(user, course_descriptor)
    grade = grade_summary['percent']
    proforma_grade = grades.calculate_proforma_grade(grade_summary,
                                                     grading_policy)

    try:
        gradebook_entry = StudentGradebook.objects.get(user=user,
                                                       course_id=course_key)
        if gradebook_entry.grade != grade:
            gradebook_entry.grade = grade
            gradebook_entry.proforma_grade = proforma_grade
            gradebook_entry.progress_summary = json.dumps(progress_summary,
                                                          cls=EdxJSONEncoder)
            gradebook_entry.grade_summary = json.dumps(grade_summary,
                                                       cls=EdxJSONEncoder)
            gradebook_entry.grading_policy = json.dumps(grading_policy,
                                                        cls=EdxJSONEncoder)
            gradebook_entry.save()
    except StudentGradebook.DoesNotExist:
        StudentGradebook.objects.create(
            user=user,
            course_id=course_key,
            grade=grade,
            proforma_grade=proforma_grade,
            progress_summary=json.dumps(progress_summary, cls=EdxJSONEncoder),
            grade_summary=json.dumps(grade_summary, cls=EdxJSONEncoder),
            grading_policy=json.dumps(grading_policy, cls=EdxJSONEncoder))
Example #54
0
def offline_grade_calculation(course):
    '''
    Compute grades for all students for a specified course, and save results to the DB.
    '''

    tstart = time.time()
    enrolled_students = User.objects.filter(
        courseenrollment__course_id=course.id,
        courseenrollment__is_active=1).prefetch_related("groups").order_by(
            'username')

    enc = MyEncoder()
    all_studnets = len(enrolled_students)
    print "{} enrolled students in {}".format(all_studnets, course.id)
    counter = 0
    for student in enrolled_students:
        counter += 1
        if counter % 1000 == 0:
            print "{}/{} done: Course {}".format(counter, all_studnets,
                                                 course.id)
        request = DummyRequest()
        request.user = student
        request.session = {}

        gradeset = grades.grade(student, request, course, keep_raw_scores=True)
        ocg, _created = models.OfflineComputedGrade.objects.get_or_create(
            user=student, course_id=course.id)
        ocg.gradeset = gradeset['grade']
        ocg.save()

    tend = time.time()
    dt = tend - tstart

    ocgl = models.OfflineComputedGradeLog(course_id=course.id,
                                          seconds=dt,
                                          nstudents=len(enrolled_students))
    ocgl.save()
    print ocgl
    print "All Done!"
Example #55
0
def on_score_changed(sender, **kwargs):
    """
    Listens for a 'score_changed' signal and when observed
    recalculates the specified user's gradebook entry
    """
    from courseware.views import get_course
    user = kwargs['user']
    course_key = kwargs['course_key']
    course_descriptor = get_course(course_key, depth=None)
    request = RequestMockWithoutMiddleware().get('/')
    request.user = user
    progress_summary = grades.progress_summary(user, request, course_descriptor, locators_as_strings=True)
    grade_summary = grades.grade(user, request, course_descriptor)
    grading_policy = course_descriptor.grading_policy
    grade = grade_summary['percent']
    proforma_grade = grades.calculate_proforma_grade(grade_summary, grading_policy)

    try:
        gradebook_entry = StudentGradebook.objects.get(user=user, course_id=course_key)
        if gradebook_entry.grade != grade:
            gradebook_entry.grade = grade
            gradebook_entry.proforma_grade = proforma_grade
            gradebook_entry.progress_summary = json.dumps(progress_summary, cls=EdxJSONEncoder)
            gradebook_entry.grade_summary = json.dumps(grade_summary, cls=EdxJSONEncoder)
            gradebook_entry.grading_policy = json.dumps(grading_policy, cls=EdxJSONEncoder)
            gradebook_entry.save()
    except StudentGradebook.DoesNotExist:
        StudentGradebook.objects.create(
            user=user,
            course_id=course_key,
            grade=grade,
            proforma_grade=proforma_grade,
            progress_summary=json.dumps(progress_summary, cls=EdxJSONEncoder),
            grade_summary=json.dumps(grade_summary, cls=EdxJSONEncoder),
            grading_policy=json.dumps(grading_policy, cls=EdxJSONEncoder)
        )
    def format_user_data(user):
        try:
            grade = grades.grade(user, request, course)['percent'] * 100
        except:
            grade = 0.0


        student_dict = dict((ft, getattr(user, ft)) for ft in [sf for sf in STUDENT_FEATURES if sf in USER_FEATURES])

        student_profile = user.profile
        if student_profile:
            student_dict.update(dict((tf, getattr(student_profile, tf)) for tf in [pf for pf in STUDENT_FEATURES if pf in PROFILE_FEATURES]))

        if student_dict['gender']:
            st_g = student_dict['gender']
            student_dict['gender'] = filter(lambda x: x[0] == st_g, GENDER_CONTRAST)[0][1]

        if student_dict['level_of_education']:
            st_level = student_dict['level_of_education'] 
            student_dict['level_of_education'] = filter(lambda x: x[0] == st_level, EDU_LEVEL_CONTRAST)[0][1]

        student_dict.update({'complete_degree': "{grade}%".format(grade=grade)})

        return student_dict
Example #57
0
    def add_cert(self, student, course_id, course=None):
        """

        Arguments:
          student - User.object
          course_id - courseenrollment.course_id (string)

        Request a new certificate for a student.
        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'


        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status

        """

        VALID_STATUSES = [status.generating,
                          status.unavailable, status.deleted, status.error,
                          status.notpassing]

        cert_status = certificate_status_for_student(
            student, course_id)['status']

        if cert_status in VALID_STATUSES:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)

            cert, created = GeneratedCertificate.objects.get_or_create(
                user=student, course_id=course_id)

            grade = grades.grade(student, self.request, course)
            is_whitelisted = self.whitelist.filter(
                user=student, course_id=course_id, whitelist=True).exists()

            if is_whitelisted or grade['grade'] is not None:

                key = make_hashkey(random.random())

                cert.grade = grade['percent']
                cert.user = student
                cert.course_id = course_id
                cert.key = key
                cert.name = profile.name

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue
                if self.restricted.filter(user=student).exists():
                    cert.status = status.restricted
                else:
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': course_id,
                        'name': profile.name,
                    }
                    cert.status = status.generating
                    self._send_to_xqueue(contents, key)
                cert.save()
            else:
                cert_status = status.notpassing
                cert.grade = grade['percent']
                cert.status = cert_status
                cert.user = student
                cert.course_id = course_id
                cert.name = profile.name
                cert.save()

        return cert_status
Example #58
0
    def add_cert(self, student, course_id, course=None):
        """

        Arguments:
          student - User.object
          course_id - courseenrollment.course_id (string)

        Request a new certificate for a student.
        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status

        """

        VALID_STATUSES = [status.generating,
                          status.unavailable,
                          status.deleted,
                          status.error,
                          status.notpassing]

        cert_status = certificate_status_for_student(student, course_id)['status']

        new_status = cert_status

        if cert_status in VALID_STATUSES:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)

            # Needed
            self.request.user = student
            self.request.session = {}

            grade = grades.grade(student, self.request, course)
            is_whitelisted = self.whitelist.filter(
                user=student, course_id=course_id, whitelist=True).exists()
            enrollment_mode = CourseEnrollment.enrollment_mode_for_user(student, course_id)
            mode_is_verified = (enrollment_mode == GeneratedCertificate.MODES.verified)
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student)
            user_is_reverified = SoftwareSecurePhotoVerification.user_is_reverified_for_all(course_id, student)
            org = course_id.split('/')[0]
            course_num = course_id.split('/')[1]
            cert_mode = enrollment_mode
            if (mode_is_verified and user_is_verified and user_is_reverified):
                template_pdf = "certificate-template-{0}-{1}-verified.pdf".format(
                    org, course_num)
            elif (mode_is_verified and not (user_is_verified and user_is_reverified)):
                template_pdf = "certificate-template-{0}-{1}.pdf".format(
                    org, course_num)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{0}-{1}.pdf".format(
                    org, course_num)

            cert, created = GeneratedCertificate.objects.get_or_create(
                user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade['percent']
            cert.course_id = course_id
            cert.name = profile.name

            if is_whitelisted or grade['grade'] is not None:

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': course_id,
                        'name': profile.name,
                        'grade': grade['grade'],
                        'template_pdf': template_pdf,
                    }
                    new_status = status.generating
                    cert.status = new_status
                    cert.save()
                    self._send_to_xqueue(contents, key)
            else:
                new_status = status.notpassing
                cert.status = new_status
                cert.save()

        return new_status