Ejemplo n.º 1
0
 def test_groups(self):
     group = StudentGroup(course_instance=self.current_course_instance)
     group.save()
     group.members.add(self.user.userprofile,self.grader.userprofile)
     self.assertEqual(StudentGroup.get_exact(self.current_course_instance,
         [self.user.userprofile,self.grader.userprofile]), group)
     self.assertEqual(StudentGroup.get_exact(self.current_course_instance,
         [self.user.userprofile,self.superuser.userprofile]), None)
Ejemplo n.º 2
0
 def get_group(self):
     if self.submission_count > 0:
         s = self.submissions[0]
         if s.submitters.count() > 0:
             return StudentGroup.get_exact(self.exercise.course_instance,
                                           s.submitters.all())
     return None
Ejemplo n.º 3
0
 def get_group(self):
     if self.submission_count > 0:
         s = self.submissions[0]
         if s.submitters.count() > 0:
             return StudentGroup.get_exact(
                 self.exercise.course_instance,
                 s.submitters.all()
             )
     return None
Ejemplo n.º 4
0
 def test_groups(self):
     group = StudentGroup(course_instance=self.current_course_instance)
     group.save()
     group.members.add(self.user.userprofile,self.grader.userprofile)
     self.assertEqual(StudentGroup.get_exact(self.current_course_instance,
         [self.user.userprofile,self.grader.userprofile]), group)
     self.assertEqual(StudentGroup.get_exact(self.current_course_instance,
         [self.user.userprofile,self.superuser.userprofile]), None)
Ejemplo n.º 5
0
    def _check_submission_allowed(self, profile, request=None):
        students = [profile]
        warnings = []

        # Let course module settings decide submissionable state.
        #if self.course_instance.ending_time < timezone.now():
        #    warnings.append(_('The course is archived. Exercises are offline.'))
        #    return False, warnings, students

        # Check enrollment requirements.
        enrollment = self.course_instance.get_enrollment_for(profile.user)
        if self.status in (
            LearningObject.STATUS.ENROLLMENT,
            LearningObject.STATUS.ENROLLMENT_EXTERNAL,
        ):
            if not self.course_instance.is_enrollment_open():
                return (self.SUBMIT_STATUS.CANNOT_ENROLL,
                        [_('The enrollment is not open.')],
                        students)
            if not self.course_instance.is_enrollable(profile.user):
                return (self.SUBMIT_STATUS.CANNOT_ENROLL,
                        [_('You cannot enroll in the course.')],
                        students)
        elif not enrollment:
            if self.course_instance.is_course_staff(profile.user):
                return (self.SUBMIT_STATUS.ALLOWED,
                        [_('Staff can submit exercises without enrolling.')],
                        students)
            return (self.SUBMIT_STATUS.NOT_ENROLLED,
                    [_('You must enroll in the course to submit exercises.')],
                    students)

        # Support group id from post or currently selected group.
        group = None
        group_id = request.POST.get("_aplus_group") if request else None
        if not group_id is None:
            try:
                gid = int(group_id)
                if gid > 0:
                    group = profile.groups.filter(
                        course_instance=self.course_instance,
                        id=gid).first()
            except ValueError:
                pass
        elif enrollment and enrollment.selected_group:
            group = enrollment.selected_group

        # Check groups cannot be changed after submitting.
        submission = self.get_submissions_for_student(profile).first()
        if submission:
            if self._detect_group_changes(profile, group, submission):
                msg = _("Group can only change between different exercises.")
                warning = _('You have previously submitted this '
                            'exercise {with_group}. {msg}')
                if submission.submitters.count() == 1:
                    warning = warning.format(with_group=_('alone'), msg=msg)
                else:
                    collaborators = StudentGroup.format_collaborator_names(
                            submission.submitters.all(), profile)
                    with_group = _('with {}').format(collaborators)
                    warning = warning.format(with_group=with_group, msg=msg)
                warnings.append(warning)
                return self.SUBMIT_STATUS.INVALID_GROUP, warnings, students

        elif self._detect_submissions(profile, group):
            warnings.append(_('{collaborators} already submitted to this exercise in a different group.').format(
                collaborators=group.collaborator_names(profile)))
            return self.SUBMIT_STATUS.INVALID_GROUP, warnings, students

        # Get submitters.
        if group:
            students = list(group.members.all())

        # Check group size.
        if not (self.min_group_size <= len(students) <= self.max_group_size):
            if self.max_group_size == self.min_group_size:
                size = "{:d}".format(self.min_group_size)
            else:
                size = "{:d}-{:d}".format(self.min_group_size, self.max_group_size)
            warnings.append(
                _("This exercise must be submitted in groups of {size} students.")
                .format(size=size))
        if self.status in (self.STATUS.ENROLLMENT, self.STATUS.ENROLLMENT_EXTERNAL):
            access_ok, access_warnings = True, []
        else:
            access_ok, access_warnings = self.one_has_access(students)
        is_staff = all(self.course_instance.is_course_staff(p.user) for p in students)
        ok = (access_ok and len(warnings) == 0) or is_staff
        all_warnings = warnings + access_warnings
        if not ok:
            if len(all_warnings) == 0:
                all_warnings.append(_(
                    'Cannot submit exercise due to unknown reason. If you '
                    'think this is an error, please contact course staff.'))
            return self.SUBMIT_STATUS.INVALID, all_warnings, students

        submit_limit_ok, submit_limit_warnings = self.one_has_submissions(students)
        if not submit_limit_ok and not is_staff:
            # access_warnings are not needed here
            return (self.SUBMIT_STATUS.AMOUNT_EXCEEDED,
                    submit_limit_warnings,
                    students)

        return self.SUBMIT_STATUS.ALLOWED, all_warnings + submit_limit_warnings, students
Ejemplo n.º 6
0
    def _check_submission_allowed(self, profile, request=None):
        students = [profile]
        warnings = []

        # Let course module settings decide submissionable state.
        #if self.course_instance.ending_time < timezone.now():
        #    warnings.append(_('The course is archived. Exercises are offline.'))
        #    return False, warnings, students

        # Check enrollment requirements.
        enrollment = self.course_instance.get_enrollment_for(profile.user)
        if self.status in (
            LearningObject.STATUS.ENROLLMENT,
            LearningObject.STATUS.ENROLLMENT_EXTERNAL,
        ):
            if not self.course_instance.is_enrollable(profile.user):
                return (self.SUBMIT_STATUS.CANNOT_ENROLL,
                        [_('You cannot enroll in the course.')],
                        students)
        elif not enrollment:
            # TODO Provide button to enroll, should there be option to auto-enroll
            if self.course_instance.is_course_staff(profile.user):
                return (self.SUBMIT_STATUS.ALLOWED,
                        [_('Staff can submit exercises without enrolling.')],
                        students)
            return (self.SUBMIT_STATUS.NOT_ENROLLED,
                    [_('You must enroll at course home to submit exercises.')],
                    students)

        # Support group id from post or currently selected group.
        group = None
        group_id = request.POST.get("_aplus_group") if request else None
        if not group_id is None:
            try:
                gid = int(group_id)
                if gid > 0:
                    group = profile.groups.filter(
                        course_instance=self.course_instance,
                        id=gid).first()
            except ValueError:
                pass
        elif enrollment and enrollment.selected_group:
            group = enrollment.selected_group

        # Check groups cannot be changed after submitting.
        submissions = list(self.get_submissions_for_student(profile))
        if len(submissions) > 0:
            s = submissions[0]
            if self._detect_group_changes(profile, group, s):
                msg = _("Group can only change between different exercises.")
                warning = _('You have previously submitted this '
                            'exercise {with_group}. {msg}')
                if s.submitters.count() == 1:
                    warning = warning.format(with_group=_('alone'), msg=msg)
                else:
                    collaborators = StudentGroup.format_collaborator_names(
                            s.submitters.all(), profile)
                    with_group = _('with {}').format(collaborators)
                    warning = warning.format(with_group=with_group, msg=msg)
                warnings.append(warning)
                return self.SUBMIT_STATUS.INVALID_GROUP, warnings, students

        elif self._detect_submissions(profile, group):
            warnings.append(_('{collaborators} already submitted to this exercise in a different group.').format(
                collaborators=group.collaborator_names(profile)))
            return self.SUBMIT_STATUS.INVALID_GROUP, warnings, students

        # Get submitters.
        if group:
            students = list(group.members.all())

        # Check group size.
        if not (self.min_group_size <= len(students) <= self.max_group_size):
            if self.max_group_size == self.min_group_size:
                size = "{:d}".format(self.min_group_size)
            else:
                size = "{:d}-{:d}".format(self.min_group_size, self.max_group_size)
            warnings.append(
                _("This exercise must be submitted in groups of {size} students.")
                .format(size=size))

        access_ok,access_warnings = self.one_has_access(students)

        if not self.one_has_submissions(students):
            if self.course_module.late_submissions_allowed:
                access_warnings.append(_('You have used the allowed amount of submissions for this exercise. You may still submit unofficially to receive feedback.'))
                return (self.SUBMIT_STATUS.ALLOWED,
                        warnings + access_warnings,
                        students)
            warnings.append(_('You have used the allowed amount of submissions for this exercise.'))
            return (self.SUBMIT_STATUS.AMOUNT_EXCEEDED,
                    warnings + access_warnings,
                    students)

        ok = (
            (access_ok and len(warnings) == 0) or
            all(self.course_instance.is_course_staff(p.user) for p in students)
        )
        all_warnings = warnings + access_warnings
        if not ok:
            if len(all_warnings) == 0:
                all_warnings.append(_(
                    'Cannot submit exercise due to unknown reason. If you '
                    'think this is an error, please contact course staff.'))
            return self.SUBMIT_STATUS.INVALID, all_warnings, students
        return self.SUBMIT_STATUS.ALLOWED, all_warnings, students
Ejemplo n.º 7
0
def modify_default_courses():
    from course.models import Course, CourseInstance, Enrollment, StudentGroup

    # The container has already created the default database, but we
    # modify some settings of the course instance here.
    course = Course.objects.get(url="def", )

    instance = CourseInstance.objects.get(
        course=course,
        url="current",
    )

    #instance.head_urls =
    #        "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML-full&delayStartupUntil=onload"
    #instance.view_content_to = CourseInstance.VIEW_ACCESS.ENROLLED
    #instance.view_content_to = CourseInstance.VIEW_ACCESS.PUBLIC
    #if not instance.description:
    #    instance.description = '<p><b>TESTing</b> course instance description.</p><p>Hello course!</p>'
    #instance.save()

    from django.contrib.auth.models import User

    teacher = User.objects.get(username="******")

    course2, created = Course.objects.get_or_create(
        name="Test course 2",
        code='testcourse2',
        url='testcourse2',
    )
    if created:
        course2.teachers.set([teacher.userprofile])
        course2.save()
    now = timezone.now()
    try:
        instance2 = CourseInstance.objects.get(
            course=course2,
            instance_name="Test instance",
            url='test',
        )
        instance2.starting_time = now
        instance2.ending_time = now + timedelta(days=365)
        instance2.save()
    except CourseInstance.DoesNotExist:
        instance2 = CourseInstance.objects.create(
            course=course2,
            instance_name="Test instance",
            url='test',
            starting_time=now,
            ending_time=now + timedelta(days=365),
        )

    # enroll students
    for i in range(2, 100):
        user = User.objects.get(username="******" + str(i))
        Enrollment.objects.get_or_create(course_instance=instance,
                                         user_profile=user.userprofile)

    # student groups
    for i in range(2, 90, 3):
        group = StudentGroup(course_instance=instance)
        group.save()
        member1 = User.objects.get(username="******" + str(i))
        member2 = User.objects.get(username="******" + str(i + 1))
        group.members.add(member1.userprofile, member2.userprofile)

    # UserTags
    create_user_tags(instance)

    ###########################################################
    # add submissions for testing
    from course.models import CourseModule
    from exercise.exercise_models import BaseExercise, LearningObject
    from exercise.submission_models import Submission
    time.sleep(
        4
    )  # let the database initialize the course (JSON import from the mooc-grader)

    student1 = User.objects.get(username='******', )
    # module from the aplus-manual course
    course_module = CourseModule.objects.get(
        url='m01_introduction',
        course_instance=instance,
    )
    exercise = BaseExercise.objects.get(
        course_module=course_module,
        url='m01_introduction_07_questionnaires_questionnaire_demo',
        #order=1,
    )
    for i in range(300):
        new_submission = Submission.objects.create(exercise=exercise,
                                                   #submission_data={},
                                                   )
        new_submission.submitters.set([student1.userprofile])
        if random.random() > 0.3:  # randomly grade some submissions
            new_submission.set_points(random.randint(0, 50), 50)
            new_submission.set_ready()
            new_submission.save()