예제 #1
0
def course_view_data(request,
                     slug) -> Tuple[Optional[CourseInstance], Optional[Dict]]:
    """Retrieves course and relevant data for the request.

    If course does not exist it returns two None objects.
    """
    course: CourseInstance = None
    try:
        course = CourseInstance.objects.filter(slug=slug).select_related(
            'semester', 'course_type').prefetch_related('tags',
                                                        'effects').get()
    except CourseInstance.DoesNotExist:
        return None, None

    student: Student = None
    if request.user.is_authenticated and request.user.student:
        student = request.user.student

    groups = course.groups.exclude(extra='hidden').select_related(
        'teacher',
        'teacher__user',
    ).prefetch_related('term', 'term__classrooms', 'guaranteed_spots',
                       'guaranteed_spots__role')

    # Collect the general groups statistics.
    groups_stats = Record.groups_stats(groups)
    # Collect groups information related to the student.
    student_status_groups = Record.is_recorded_in_groups(student, groups)
    student_can_enqueue = Record.can_enqueue_groups(student,
                                                    course.groups.all())
    student_can_dequeue = Record.can_dequeue_groups(student,
                                                    course.groups.all())

    for group in groups:
        group.num_enrolled = groups_stats.get(group.pk).get('num_enrolled')
        group.num_enqueued = groups_stats.get(group.pk).get('num_enqueued')
        group.is_enrolled = student_status_groups.get(group.pk).get('enrolled')
        group.is_enqueued = student_status_groups.get(group.pk).get('enqueued')
        group.priority = student_status_groups.get(group.pk).get('priority')
        group.can_enqueue = student_can_enqueue.get(group.pk)
        group.can_dequeue = student_can_dequeue.get(group.pk)

    teachers = {g.teacher for g in groups}

    course.is_enrollment_on = any(g.can_enqueue for g in groups)

    waiting_students = {}
    if request.user.employee:
        waiting_students = Record.list_waiting_students([course])[course.id]

    data = {
        'course': course,
        'teachers': teachers,
        'groups': groups,
        'waiting_students': waiting_students,
    }
    return course, data
예제 #2
0
    def test_student_autoremoved_from_group(self):
        """Bolek switches seminar group for "Mycie Naczyń".

        In the meantime, Lolek tries to join the first group. He waits in queue,
        but is pulled in when Bolek leaves a vacancy.
        """
        # Bolek joins group 1.
        with patch(RECORDS_DATETIME, mock_datetime(2011, 12, 5, 12)):
            self.assertTrue(
                Record.enqueue_student(self.bolek, self.washing_up_seminar_1))
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.washing_up_seminar_1,
                                  status=RecordStatus.ENROLLED).exists())

        # Lolek tries to join group 1 and is enqueued.
        with patch(RECORDS_DATETIME, mock_datetime(2011, 12, 5, 12)):
            self.assertTrue(
                Record.enqueue_student(self.lolek, self.washing_up_seminar_1))
        self.assertFalse(
            Record.objects.filter(student=self.lolek,
                                  group=self.washing_up_seminar_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.lolek,
                                  group=self.washing_up_seminar_1,
                                  status=RecordStatus.QUEUED).exists())

        # Bolek switches the group.
        with patch(RECORDS_DATETIME, mock_datetime(2011, 12, 5, 12, 5)):
            self.assertTrue(
                Record.enqueue_student(self.bolek, self.washing_up_seminar_2))
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.washing_up_seminar_2,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertFalse(
            Record.objects.filter(student=self.bolek,
                                  group=self.washing_up_seminar_1,
                                  status=RecordStatus.ENROLLED).exists())

        # Lolek should be pulled in.
        self.assertTrue(
            Record.objects.filter(student=self.lolek,
                                  group=self.washing_up_seminar_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertFalse(
            Record.objects.filter(student=self.lolek,
                                  group=self.washing_up_seminar_1,
                                  status=RecordStatus.QUEUED).exists())
예제 #3
0
def prototype_get_course(request, course_id):
    """Retrieves the annotated groups of a single course."""
    student = request.user.student
    course = CourseInstance.objects.get(pk=course_id)
    groups = course.groups.exclude(extra='hidden').select_related(
        'course', 'teacher', 'course__semester', 'teacher__user'
    ).prefetch_related('term', 'term__classrooms', 'guaranteed_spots', 'guaranteed_spots__role')
    can_enqueue_dict = Record.can_enqueue_groups(student, groups)
    can_dequeue_dict = Record.can_dequeue_groups(student, groups)
    for group in groups:
        group.can_enqueue = can_enqueue_dict.get(group.pk)
        group.can_dequeue = can_dequeue_dict.get(group.pk)
    group_dicts = build_group_list(groups)
    return JsonResponse(group_dicts, safe=False)
예제 #4
0
def get_grouped_waiting_students(course: CourseInstance, user) -> List:
    """Return numbers of waiting students grouped by course group type.

    The user argument is used to decide if the list should be generated at all.
    """
    if not user.is_superuser:
        return []

    group_types: List = [{
        'id': '2',
        'name': 'cwiczenia'
    }, {
        'id': '3',
        'name': 'pracownie'
    }, {
        'id': '5',
        'name': 'ćwiczenio-pracownie'
    }]

    return [{
        'students_amount':
        Record.get_number_of_waiting_students(course, group_type['id']),
        'type_name':
        group_type['name']
    } for group_type in group_types]
예제 #5
0
def prototype_action(request, group_id):
    """Performs actions requested by timetable prototype.

    HTTP response 204 (successful with no content to send back) will be returned
    if the pin operation is performed with no obstacles. If the student is not
    allowed to perform an operation, 403 (forbidden) status shall be returned.
    """
    student = request.user.student
    group: Group
    try:
        group = Group.objects.get(pk=group_id)
    except Group.DoesNotExist:
        raise Http404
    # Axios sends POST data in json rather than _Form-Encoded_.
    data = json.loads(request.body.decode('utf-8'))
    action = data.get('action')
    if action == 'pin':
        Pin.objects.get_or_create(student_id=student.pk, group_id=group_id)
        return HttpResponse(status=204)
    if action == 'unpin':
        Pin.objects.filter(student_id=student.pk, group_id=group_id).delete()
        return HttpResponse(status=204)
    if action == 'enqueue':
        group_ids = Record.enqueue_student(student, group)
        if group_ids:
            # When the student joins the queue of a class, the accompanying
            # lecture group might need to be displayed (if he is automatically
            # enqueued in that). We hence send him the information about these
            # groups.
            groups = Group.objects.filter(pk__in=group_ids).select_related(
                'teacher', 'teacher__user', 'course', 'course__semester').prefetch_related(
                    'term', 'term__classrooms', 'guaranteed_spots', 'guaranteed_spots__role')
            for group in groups:
                group.is_enqueued = True
            groups_dicts = build_group_list(groups)
            return JsonResponse(groups_dicts, safe=False)
        else:
            return HttpResponse(status=403)
    if action == 'dequeue':
        group_ids = Record.remove_from_group(student, group)
        if group_ids:
            return JsonResponse(group_ids, safe=False)
        else:
            return HttpResponse(status=403)
    # If the request action is not among the above, we return Bad Request
    # response.
    return HttpResponse(status=400, content=action)
예제 #6
0
def my_prototype(request):
    """Renders the prototype with enrolled, enqueued, and pinned groups."""
    student = request.user.student
    semester = Semester.objects.get_next()

    # This costs an additional join, but works if there is no current semester.
    records = Record.objects.filter(
        student=student,
        group__course__semester=semester).exclude(status=RecordStatus.REMOVED).select_related(
            'group__teacher', 'group__teacher__user',
            'group__course', 'group__course__semester').prefetch_related(
                'group__term', 'group__term__classrooms', 'group__guaranteed_spots',
                'group__guaranteed_spots__role')
    pinned = Pin.student_pins_in_semester(student, semester)
    pinned = list(pinned)
    all_groups_by_id = {r.group_id: r.group for r in records}
    all_groups_by_id.update({p.pk: p for p in pinned})
    all_groups = list(all_groups_by_id.values())
    can_enqueue_dict = Record.can_enqueue_groups(student, all_groups)
    can_dequeue_dict = Record.can_dequeue_groups(student, all_groups)

    for record in records:
        group = all_groups_by_id.get(record.group_id)
        group.is_enrolled = record.status == RecordStatus.ENROLLED
        group.is_enqueued = record.status == RecordStatus.QUEUED

    for pin in pinned:
        group = all_groups_by_id.get(pin.pk)
        group.is_pinned = True

    all_groups = all_groups_by_id.values()
    for group in all_groups:
        group.can_enqueue = can_enqueue_dict.get(group.pk)
        group.can_dequeue = can_dequeue_dict.get(group.pk)

    group_dicts = build_group_list(all_groups)
    filters_dict = CourseInstance.prepare_filter_data(
        CourseInstance.objects.filter(semester=semester))
    courses_json = list_courses_in_semester(semester)
    data = {
        'groups_json': json.dumps(group_dicts, cls=DjangoJSONEncoder),
        'filters_json': json.dumps(filters_dict, cls=DjangoJSONEncoder),
        'courses_json': courses_json,
    }
    return render(request, 'timetable/prototype.html', data)
예제 #7
0
    def test_bolek_comes_before_lolek(self):
        """Bolek will be first to enroll into the groups. Lolek will remain in
        the queue of the exercise group, yet he will fit in the lecture
        group."""
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertCountEqual(
                Record.enqueue_student(self.bolek,
                                       self.cooking_exercise_group_1), [
                                           self.cooking_exercise_group_1.pk,
                                           self.cooking_lecture_group.pk
                                       ])
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12, 1)):
            self.assertCountEqual(
                Record.enqueue_student(self.lolek,
                                       self.cooking_exercise_group_1), [
                                           self.cooking_exercise_group_1.pk,
                                           self.cooking_lecture_group.pk
                                       ])

        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_exercise_group_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertFalse(
            Record.objects.filter(student=self.lolek,
                                  group=self.cooking_exercise_group_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.lolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.lolek,
                                  group=self.cooking_exercise_group_1,
                                  status=RecordStatus.QUEUED).exists())
        self.assertFalse(
            Record.objects.filter(student=self.lolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.QUEUED).exists())
예제 #8
0
    def test_simple_enrollment(self):
        """Bolek will just enqueue into the group."""
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertListEqual(
                Record.enqueue_student(self.bolek,
                                       self.knitting_lecture_group),
                [self.knitting_lecture_group.pk])

        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.knitting_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
예제 #9
0
    def test_exercise_group_also_removed(self):
        """Like above bolek will enqueue into exercise group. Then he'll leave.

        He first should be automatically pulled into the lecture group. Then he
        will unenroll from the lecture group and he should be removed from the
        exercise group as well.
        """
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertCountEqual(
                Record.enqueue_student(self.bolek,
                                       self.cooking_exercise_group_1), [
                                           self.cooking_exercise_group_1.pk,
                                           self.cooking_lecture_group.pk
                                       ])

        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_exercise_group_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 2, 12)):
            self.assertCountEqual(
                Record.remove_from_group(self.bolek,
                                         self.cooking_lecture_group), [
                                             self.cooking_exercise_group_1.pk,
                                             self.cooking_lecture_group.pk
                                         ])

        self.assertFalse(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_exercise_group_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertFalse(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
예제 #10
0
def prototype_update_groups(request):
    """Retrieves the updated group annotations.

    The list of groups ids to update will be sent in JSON body of the request.
    """
    student = request.user.student
    semester = Semester.objects.get_next()
    # Axios sends POST data in json rather than _Form-Encoded_.
    ids: List[int] = json.loads(request.body.decode('utf-8'))
    num_enrolled = Count('record', filter=Q(record__status=RecordStatus.ENROLLED))
    is_enrolled = Count(
        'record',
        filter=(Q(record__status=RecordStatus.ENROLLED, record__student_id=student.pk)))
    is_enqueued = Count(
        'record',
        filter=(Q(record__status=RecordStatus.QUEUED, record__student_id=student.pk)))

    groups_from_ids = Group.objects.filter(pk__in=ids)
    groups_enrolled_or_enqueued = Group.objects.filter(
        course__semester=semester,
        record__status__in=[RecordStatus.QUEUED, RecordStatus.ENROLLED],
        record__student=student)
    groups_all = groups_from_ids | groups_enrolled_or_enqueued
    groups = groups_all.annotate(num_enrolled=num_enrolled).annotate(
        is_enrolled=is_enrolled).annotate(is_enqueued=is_enqueued).select_related(
            'course', 'teacher', 'course__semester', 'teacher__user').prefetch_related(
                'term', 'term__classrooms', 'guaranteed_spots', 'guaranteed_spots__role')

    can_enqueue_dict = Record.can_enqueue_groups(student, groups)
    can_dequeue_dict = Record.can_dequeue_groups(student, groups)
    for group in groups:
        group.can_enqueue = can_enqueue_dict.get(group.pk)
        group.can_dequeue = can_dequeue_dict.get(group.pk)
        group.is_enqueued = bool(group.is_enqueued)
        group.is_enrolled = bool(group.is_enrolled)
    group_dicts = build_group_list(groups)
    return JsonResponse(group_dicts, safe=False)
예제 #11
0
    def test_student_exceeds_the_35_limit(self):
        """Bolek will try to sign up to "Gotowanie" and "Szydełkowanie" before
        35 points limit abolition. He should be successful with "Gotowanie",
        which costs exactly 35 ECTS, but not with the second enrollment.
        """
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertTrue(
                Record.enqueue_student(self.bolek, self.cooking_lecture_group))
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertEqual(
            Record.student_points_in_semester(self.bolek, self.semester), 35)

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12, 5)):
            # He should be able to join the queue.
            self.assertTrue(
                Record.enqueue_student(self.bolek,
                                       self.knitting_lecture_group))
        # His enrollment with "Gotowanie" should still exist.
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
        # His record with "Szydełkowanie" should be removed.
        self.assertFalse(
            Record.objects.filter(student=self.bolek,
                                  group=self.knitting_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.knitting_lecture_group,
                                  status=RecordStatus.REMOVED).exists())
        self.assertEqual(
            Record.student_points_in_semester(self.bolek, self.semester), 35)
예제 #12
0
def student_profile(request: HttpRequest, user_id: int) -> HttpResponse:
    """student profile"""
    try:
        student: Student = Student.objects.select_related(
            'user', 'consent').get(user_id=user_id)
    except Student.DoesNotExist:
        raise Http404

    # We will not show the student profile if he decides to hide it.
    if not BaseUser.is_employee(
            request.user) and not student.consent_granted():
        return HttpResponseRedirect(reverse('students-list'))

    semester = Semester.objects.get_next()

    records = Record.objects.filter(
        student=student,
        group__course__semester=semester,
        status=RecordStatus.ENROLLED).select_related(
            'group__teacher', 'group__teacher__user',
            'group__course').prefetch_related('group__term',
                                              'group__term__classrooms')
    groups = [r.group for r in records]

    # Highlight groups shared with the viewer in green.
    viewer_groups = Record.common_groups(request.user, groups)
    for g in groups:
        g.is_enrolled = g.pk in viewer_groups

    group_dicts = build_group_list(groups)
    data = {
        'student': student,
        'groups_json': json.dumps(group_dicts, cls=DjangoJSONEncoder),
    }

    if request.is_ajax():
        return render(request, 'users/student_profile_contents.html', data)

    active_students = Student.get_list(
        begin='All',
        restrict_list_consent=not BaseUser.is_employee(request.user))
    data.update({
        'students': active_students,
        'char': "All",
    })
    return render(request, 'users/student_profile.html', data)
예제 #13
0
def build_group_list(groups: List[Group]):
    """Builds a serializable object containing relevant information about groups

    The information must be sufficient to display information in the timetable
    and perform actions (enqueuing/dequeuing).
    """
    stats = Record.groups_stats(groups)
    group_dicts = []
    group: Group
    for group in groups:
        group_dict = model_to_dict(group, fields=['id', 'limit', 'extra'])
        term_dicts = []
        for term in group.term.all():
            term_dict = model_to_dict(term, fields=['dayOfWeek', 'start_time', 'end_time'])
            term_dict['classrooms'] = term.numbers()
            term_dicts.append(term_dict)
        guaranteed_spots = [{
            'role': gs.role.name,
            'limit': gs.limit,
        } for gs in group.guaranteed_spots.all()]
        group_dict.update({
            'course': {
                'url': reverse('course-page', args=(group.course.slug, )),
                'name': group.course.name,
                'shortName': group.course.short_name,
            },
            'type': decode_class_type_singular(group.type),
            'url': reverse('group-view', args=(group.pk, )),
            'teacher': {
                'id': group.teacher_id,
                'url': reverse('employee-profile', args=(group.teacher.user_id, )),
                'name': group.teacher.user.get_full_name(),
            },
            'num_enrolled': stats.get(group.pk).get('num_enrolled'),
            'term': term_dicts,
            'guaranteed_spots': guaranteed_spots,
            'is_enrolled': getattr(group, 'is_enrolled', None),
            'is_enqueued': getattr(group, 'is_enqueued', None),
            'is_pinned': getattr(group, 'is_pinned', None),
            'can_enqueue': getattr(group, 'can_enqueue', None),
            'can_dequeue': getattr(group, 'can_dequeue', None),
            'action_url': reverse('prototype-action', args=(group.pk, )),
        })
        group_dicts.append(group_dict)
    return group_dicts
예제 #14
0
def employee_profile(request: HttpRequest, user_id: int) -> HttpResponse:
    """employee profile"""
    try:
        employee = Employee.objects.select_related('user').get(user_id=user_id)
    except Employee.DoesNotExist:
        raise Http404

    semester = Semester.objects.get_next()
    groups = Group.objects.filter(course__semester_id=semester.pk,
                                  teacher=employee).select_related(
                                      'teacher', 'teacher__user',
                                      'course').prefetch_related(
                                          'term', 'term__classrooms')
    groups = list(groups)

    # Highlight groups shared with the viewer in green.
    viewer_groups = Record.common_groups(request.user, groups)
    for g in groups:
        g.is_enrolled = g.pk in viewer_groups

    group_dicts = build_group_list(groups)

    data = {
        'employee': employee,
        'groups_json': json.dumps(group_dicts, cls=DjangoJSONEncoder),
    }

    if request.is_ajax():
        return render(request, 'users/employee_profile_contents.html', data)

    current_groups = Group.objects.filter(
        course__semester_id=semester.pk).select_related(
            'teacher', 'teacher__user').distinct('teacher')
    active_teachers = map(lambda g: g.teacher, current_groups)
    for e in active_teachers:
        e.short_new = (e.user.first_name[:1] + e.user.last_name[:2]
                       ) if e.user.first_name and e.user.last_name else None
        e.short_old = (e.user.first_name[:2] + e.user.last_name[:2]
                       ) if e.user.first_name and e.user.last_name else None

    data.update({
        'employees': active_teachers,
        'char': "All",
    })
    return render(request, 'users/employee_profile.html', data)
예제 #15
0
    def test_lecture_group_also_enrolled(self):
        """Bolek will just enqueue into the exercises group. He should also be
        enrolled into the lecture."""

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertCountEqual(
                Record.enqueue_student(self.bolek,
                                       self.cooking_exercise_group_1), [
                                           self.cooking_exercise_group_1.pk,
                                           self.cooking_lecture_group.pk
                                       ])

        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_exercise_group_1,
                                  status=RecordStatus.ENROLLED).exists())
        self.assertTrue(
            Record.objects.filter(student=self.bolek,
                                  group=self.cooking_lecture_group,
                                  status=RecordStatus.ENROLLED).exists())
예제 #16
0
    def test_one_isim_student(self):
        """When one ISIM student comes, he can take the guaranteed place."""
        with freeze_time(self.opening_time + timedelta(seconds=5)):
            Record.enqueue_student(self.bolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=10)):
            Record.enqueue_student(self.lolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=15)):
            Record.enqueue_student(self.reksio, self.group)

        # At this point one guy (Reksio) is in the queue.
        self.assertTrue(Record.is_enrolled(self.bolek, self.group))
        self.assertTrue(Record.is_enrolled(self.lolek, self.group))
        self.assertFalse(Record.is_enrolled(self.reksio, self.group))
        self.assertTrue(Record.is_recorded(self.reksio, self.group))

        with freeze_time(self.opening_time + timedelta(minutes=1)):
            Record.enqueue_student(self.tola, self.group)

        # Reksio is still waiting, but Tola took the ISIM guaranteed spot.
        self.assertTrue(Record.is_enrolled(self.bolek, self.group))
        self.assertTrue(Record.is_enrolled(self.lolek, self.group))
        self.assertFalse(Record.is_enrolled(self.reksio, self.group))
        self.assertTrue(Record.is_recorded(self.reksio, self.group))
        self.assertTrue(Record.is_enrolled(self.tola, self.group))

        with freeze_time(self.opening_time + timedelta(minutes=5)):
            Record.remove_from_group(self.lolek, self.group)

        self.assertTrue(Record.is_enrolled(self.bolek, self.group))
        self.assertTrue(Record.is_enrolled(self.reksio, self.group))
        self.assertFalse(Record.is_recorded(self.lolek, self.group))
        self.assertTrue(Record.is_enrolled(self.tola, self.group))

        with freeze_time(self.opening_time + timedelta(minutes=10)):
            Record.enqueue_student(self.lolek, self.group)

        # Now Lolek sits in the queue.
        self.assertTrue(Record.is_recorded(self.lolek, self.group))
        self.assertFalse(Record.is_enrolled(self.lolek, self.group))

        with freeze_time(self.opening_time + timedelta(minutes=15)):
            Record.remove_from_group(self.tola, self.group)

        # Now that Tola has left, the ISIM spot is free, but Lolek is still in
        # the queue.
        self.assertFalse(Record.is_recorded(self.tola, self.group))
        self.assertTrue(Record.is_recorded(self.lolek, self.group))
        self.assertFalse(Record.is_enrolled(self.lolek, self.group))
예제 #17
0
    def test_waiting_students_number(self):
        """Check whether we get correct number of waiting students of given type.

        Our exercise groups have limit for 1 person.
        Bolek is in cooking_exercise_group_1 and Lolek is in cooking_exercise_group_2.
        Tola is in queues of all above groups.
        Bolek changed his mind and want to be in cooking_exercise_group_2.
        Lolek also want to join other group(cooking_exercise_group_1).
        We have 2 enrolled Records and 4 enqueued.
        Only Lola isn't enrolled in any group.
        That's why we should return 1.
        """
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 8, 12)):
            self.cooking_exercise_group_1.limit = 1
            self.cooking_exercise_group_2.limit = 1
            Record.enqueue_student(self.bolek, self.cooking_exercise_group_1)
            Record.enqueue_student(self.lolek, self.cooking_exercise_group_2)
            Record.enqueue_student(self.tola, self.cooking_exercise_group_1)
            Record.enqueue_student(self.tola, self.cooking_exercise_group_2)
            Record.enqueue_student(self.bolek, self.cooking_exercise_group_2)
            Record.enqueue_student(self.lolek, self.cooking_exercise_group_1)

            expected_waiting = {
                self.cooking_exercise_group_1.course_id: {
                    self.cooking_exercise_group_1.type: 1
                }
            }
            self.assertDictEqual(
                Record.list_waiting_students(
                    [self.cooking_exercise_group_1.course]), expected_waiting)
예제 #18
0
    def test_higher_priority_2(self):
        """The only difference between this test and the one above is the order
        in which Bolek and Lolek leave their groups.
        """
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertTrue(
                Record.enqueue_student(self.bolek,
                                       self.cooking_exercise_group_1))
            self.assertTrue(
                Record.enqueue_student(self.lolek,
                                       self.cooking_exercise_group_2))

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 13)):
            self.assertTrue(
                Record.enqueue_student(self.tola,
                                       self.cooking_exercise_group_1))
            self.assertTrue(
                Record.set_queue_priority(self.tola,
                                          self.cooking_exercise_group_1, 7))
            self.assertTrue(
                Record.enqueue_student(self.tola,
                                       self.cooking_exercise_group_2))
            self.assertTrue(
                Record.set_queue_priority(self.tola,
                                          self.cooking_exercise_group_2, 8))

        self.assertTrue(
            Record.is_recorded(self.tola, self.cooking_exercise_group_1))
        self.assertTrue(
            Record.is_recorded(self.tola, self.cooking_exercise_group_2))
        self.assertFalse(
            Record.is_enrolled(self.tola, self.cooking_exercise_group_1))
        self.assertFalse(
            Record.is_enrolled(self.tola, self.cooking_exercise_group_2))

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 8, 12)):
            self.assertCountEqual(
                Record.remove_from_group(self.lolek,
                                         self.cooking_exercise_group_2),
                [self.cooking_exercise_group_2.pk])
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 8, 13)):
            self.assertCountEqual(
                Record.remove_from_group(self.bolek,
                                         self.cooking_exercise_group_1),
                [self.cooking_exercise_group_1.pk])

        self.assertFalse(
            Record.is_recorded(self.tola, self.cooking_exercise_group_1))
        self.assertTrue(
            Record.is_enrolled(self.tola, self.cooking_exercise_group_2))
예제 #19
0
    def test_higher_priority_1(self):
        """Both exercise groups are occupied by Bolek and Lolek. Tola will
        enqueue to both with different priorities. She will end up in the group
        of higher priority regardless of the order in which Bolek and Lolek free
        up the places.
        """
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 12)):
            self.assertTrue(
                Record.enqueue_student(self.bolek,
                                       self.cooking_exercise_group_1))
            self.assertTrue(
                Record.enqueue_student(self.lolek,
                                       self.cooking_exercise_group_2))

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 1, 13)):
            self.assertTrue(
                Record.enqueue_student(self.tola,
                                       self.cooking_exercise_group_1))
            self.assertTrue(
                Record.set_queue_priority(self.tola,
                                          self.cooking_exercise_group_1, 7))
            self.assertTrue(
                Record.enqueue_student(self.tola,
                                       self.cooking_exercise_group_2))
            self.assertTrue(
                Record.set_queue_priority(self.tola,
                                          self.cooking_exercise_group_2, 8))

        self.assertTrue(
            Record.is_recorded(self.tola, self.cooking_exercise_group_1))
        self.assertTrue(
            Record.is_recorded(self.tola, self.cooking_exercise_group_2))
        self.assertFalse(
            Record.is_enrolled(self.tola, self.cooking_exercise_group_1))
        self.assertFalse(
            Record.is_enrolled(self.tola, self.cooking_exercise_group_2))

        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 8, 12)):
            self.assertCountEqual(
                Record.remove_from_group(self.bolek,
                                         self.cooking_exercise_group_1),
                [self.cooking_exercise_group_1.pk])
        with patch(RECORDS_DATETIME, mock_datetime(2011, 10, 8, 13)):
            self.assertCountEqual(
                Record.remove_from_group(self.lolek,
                                         self.cooking_exercise_group_2),
                [self.cooking_exercise_group_2.pk])

        self.assertFalse(
            Record.is_recorded(self.tola, self.cooking_exercise_group_1))
        self.assertTrue(
            Record.is_enrolled(self.tola, self.cooking_exercise_group_2))
예제 #20
0
def my_profile(request):
    """User profile page.

    The profile page displays user settings (e-mail address, notifications). If
    he is a student, his opening times will be displayed. If the user is an
    employee, the page allows him to modify his public information (office,
    consultations).
    """
    semester = Semester.objects.get_next()

    data = {
        'semester': semester,
    }

    if BaseUser.is_employee(request.user):
        data.update({
            'consultations': request.user.employee.consultations,
            'room': request.user.employee.room,
            'homepage': request.user.employee.homepage,
            'title': request.user.employee.title,
        })

    if semester and BaseUser.is_student(request.user):
        student: Student = request.user.student
        groups_opening_times = GroupOpeningTimes.objects.filter(
            student_id=student.pk,
            group__course__semester_id=semester.pk).select_related(
                'group', 'group__course', 'group__teacher',
                'group__teacher__user').prefetch_related(
                    'group__term', 'group__term__classrooms')
        groups_times = []
        got: GroupOpeningTimes
        for got in groups_opening_times:
            group: Group = got.group
            group.opening_time = got.time
            groups_times.append(group)
        t0_time_obj = T0Times.objects.filter(student_id=student.pk,
                                             semester_id=semester.pk)
        try:
            t0_time = t0_time_obj.get().time
        except T0Times.DoesNotExist:
            t0_time = None
        grade_info = StudentGraded.objects.filter(
            student=student).select_related('semester').order_by(
                '-semester__records_opening')
        semesters_participated_in_grade = [x.semester for x in grade_info]
        current_semester_ects = Record.student_points_in_semester(
            student, semester)
        data.update({
            't0_time': t0_time,
            'groups_times': groups_times,
            'semesters_participated_in_grade': semesters_participated_in_grade,
            'current_semester_ects': current_semester_ects,
        })

    notifications_form = create_form(request)
    data.update({
        'form': notifications_form,
    })

    return render(request, 'users/my_profile.html', data)
예제 #21
0
    def test_isim_not_involved(self):
        """When ISIM students are not involved, enrollment behaves normally."""
        with freeze_time(self.opening_time + timedelta(seconds=5)):
            Record.enqueue_student(self.bolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=10)):
            Record.enqueue_student(self.lolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=15)):
            Record.enqueue_student(self.reksio, self.group)

        self.assertTrue(Record.is_enrolled(self.bolek, self.group))
        self.assertTrue(Record.is_enrolled(self.lolek, self.group))
        self.assertFalse(Record.is_enrolled(self.reksio, self.group))
        self.assertTrue(Record.is_recorded(self.reksio, self.group))

        with freeze_time(self.opening_time + timedelta(minutes=5)):
            Record.remove_from_group(self.lolek, self.group)

        self.assertTrue(Record.is_enrolled(self.bolek, self.group))
        self.assertTrue(Record.is_enrolled(self.reksio, self.group))
        self.assertFalse(Record.is_recorded(self.lolek, self.group))
예제 #22
0
    def test_two_isim_students(self):
        """When there are two ISIM students, they compete for the regular spots
        and the guaranteed spot at the same time.
        """
        with freeze_time(self.opening_time + timedelta(seconds=5)):
            Record.enqueue_student(self.bolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=10)):
            Record.enqueue_student(self.lolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=15)):
            Record.enqueue_student(self.tola, self.group)
        # Bolek and Lolek are in the regular spots, Tola has taken the
        # ISIM-guaranteed extra spot.
        self.assertTrue(Record.is_enrolled(self.bolek, self.group))
        self.assertTrue(Record.is_enrolled(self.lolek, self.group))
        self.assertTrue(Record.is_enrolled(self.tola, self.group))

        with freeze_time(self.opening_time + timedelta(seconds=20)):
            Record.enqueue_student(self.reksio, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=25)):
            Record.enqueue_student(self.uszatek, self.group)
        # Now both Reksio and Uszatek are waiting.
        self.assertFalse(Record.is_enrolled(self.reksio, self.group))
        self.assertFalse(Record.is_enrolled(self.uszatek, self.group))

        with freeze_time(self.opening_time + timedelta(seconds=30)):
            Record.remove_from_group(self.tola, self.group)
        # Now Uszatek jumps into the guaranteed spot even though he is not first
        # in line.
        self.assertFalse(Record.is_enrolled(self.reksio, self.group))
        self.assertTrue(Record.is_enrolled(self.uszatek, self.group))

        with freeze_time(self.opening_time + timedelta(seconds=35)):
            Record.enqueue_student(self.tola, self.group)
            Record.remove_from_group(self.lolek, self.group)
        # Now Reksio takes up the regular spot. Tola is waiting.
        self.assertTrue(Record.is_enrolled(self.reksio, self.group))
        self.assertFalse(Record.is_enrolled(self.tola, self.group))

        with freeze_time(self.opening_time + timedelta(seconds=40)):
            Record.enqueue_student(self.lolek, self.group)
        with freeze_time(self.opening_time + timedelta(seconds=45)):
            Record.remove_from_group(self.bolek, self.group)
        # Now Tola assumes the regular spot, because she was in line before
        # Lolek.
        self.assertTrue(Record.is_enrolled(self.uszatek, self.group))
        self.assertTrue(Record.is_enrolled(self.tola, self.group))
        self.assertFalse(Record.is_enrolled(self.lolek, self.group))