예제 #1
0
def get_evaluations_with_prefetched_data(evaluations):
    if isinstance(evaluations, QuerySet):
        participant_counts = evaluations.annotate(
            num_participants=Count("participants")).values_list(
                "num_participants", flat=True)
        voter_counts = evaluations.annotate(
            num_voters=Count("voters")).values_list("num_voters", flat=True)
        course_evaluations_counts = evaluations.annotate(
            num_course_evaluations=Count("course__evaluations")).values_list(
                "num_course_evaluations", flat=True)
        evaluations = (
            evaluations.select_related("course__type").prefetch_related(
                "course__degrees",
                "course__semester",
                "course__responsibles",
            ))
        for evaluation, participant_count, voter_count, course_evaluations_count in zip(
                evaluations, participant_counts, voter_counts,
                course_evaluations_counts):
            if evaluation._participant_count is None:
                evaluation.num_participants = participant_count
                evaluation.num_voters = voter_count
            evaluation.course_evaluations_count = course_evaluations_count
    for evaluation in evaluations:
        if not evaluation.is_single_result:
            evaluation.distribution = calculate_average_distribution(
                evaluation)
            evaluation.avg_grade = distribution_to_grade(
                evaluation.distribution)
        else:
            evaluation.single_result_rating_result = get_single_result_rating_result(
                evaluation)
    return evaluations
예제 #2
0
    def test_average_grade(self):
        question_grade2 = baker.make(Question, questionnaire=self.questionnaire, type=Question.GRADE)

        baker.make(RatingAnswerCounter, question=self.question_grade, contribution=self.contribution1, answer=2, count=1)
        baker.make(RatingAnswerCounter, question=self.question_grade, contribution=self.contribution2, answer=4, count=2)
        baker.make(RatingAnswerCounter, question=question_grade2, contribution=self.contribution1, answer=1, count=1)
        baker.make(RatingAnswerCounter, question=self.question_likert, contribution=self.contribution1, answer=3, count=4)
        baker.make(RatingAnswerCounter, question=self.question_likert, contribution=self.general_contribution, answer=5, count=5)
        baker.make(RatingAnswerCounter, question=self.question_likert_2, contribution=self.general_contribution, answer=3, count=3)
        baker.make(RatingAnswerCounter, question=self.question_bipolar, contribution=self.general_contribution, answer=3, count=2)
        baker.make(RatingAnswerCounter, question=self.question_bipolar_2, contribution=self.general_contribution, answer=-1, count=4)
        cache_results(self.evaluation)

        contributor_weights_sum = settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT + settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT
        contributor1_average = ((settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT * ((2 * 1) + (1 * 1)) / (1 + 1)) + (settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT * 3)) / contributor_weights_sum  # 2.4
        contributor2_average = 4
        contributors_average = ((4 * contributor1_average) + (2 * contributor2_average)) / (4 + 2)  # 2.9333333

        general_non_grade_average = ((5 * 5) + (3 * 3) + (2 * 5) + (4 * 7 / 3)) / (5 + 3 + 2 + 4)  # 3.80952380

        contributors_percentage = settings.CONTRIBUTIONS_WEIGHT / (settings.CONTRIBUTIONS_WEIGHT + settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT)  # 0.375
        general_non_grade_percentage = settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT / (settings.CONTRIBUTIONS_WEIGHT + settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT)  # 0.625

        total_grade = contributors_percentage * contributors_average + general_non_grade_percentage * general_non_grade_average  # 1.1 + 2.38095238 = 3.48095238

        average_grade = distribution_to_grade(calculate_average_distribution(self.evaluation))
        self.assertAlmostEqual(average_grade, total_grade)
        self.assertAlmostEqual(average_grade, 3.48095238)
예제 #3
0
파일: exporters.py 프로젝트: tkv29/EvaP
    def filter_evaluations(semesters, evaluation_states, degrees, course_types, contributor, include_not_enough_voters):
        course_results_exist = False
        evaluations_with_results = list()
        used_questionnaires = set()
        evaluations_filter = Q(course__semester__in=semesters, state__in=evaluation_states, course__degrees__in=degrees, course__type__in=course_types)
        if contributor:
            evaluations_filter = evaluations_filter & (Q(course__responsibles__in=[contributor]) | Q(contributions__contributor__in=[contributor]))
        evaluations = Evaluation.objects.filter(evaluations_filter).distinct()
        for evaluation in evaluations:
            if evaluation.is_single_result:
                continue
            if not evaluation.can_publish_rating_results and not include_not_enough_voters:
                continue
            results = OrderedDict()
            for contribution_result in get_results(evaluation).contribution_results:
                for questionnaire_result in contribution_result.questionnaire_results:
                    # RatingQuestion.counts is a tuple of integers or None, if this tuple is all zero, we want to exclude it
                    if all(not question_result.question.is_rating_question or question_result.counts is None or sum(question_result.counts) == 0 for question_result in questionnaire_result.question_results):
                        continue
                    if not contributor or contribution_result.contributor is None or contribution_result.contributor == contributor:
                        results.setdefault(questionnaire_result.questionnaire.id, []).extend(questionnaire_result.question_results)
                        used_questionnaires.add(questionnaire_result.questionnaire)
            evaluation.course_evaluations_count = evaluation.course.evaluations.count()
            if evaluation.course_evaluations_count > 1:
                course_results_exist = True
                evaluation.weight_percentage = int((evaluation.weight / sum(evaluation.weight for evaluation in evaluation.course.evaluations.all())) * 100)
                evaluation.course.avg_grade = distribution_to_grade(calculate_average_course_distribution(evaluation.course))
            evaluations_with_results.append((evaluation, results))

        evaluations_with_results.sort(key=lambda cr: (cr[0].course.semester.id, cr[0].course.type.order, cr[0].full_name))
        used_questionnaires = sorted(used_questionnaires)

        return evaluations_with_results, used_questionnaires, course_results_exist
예제 #4
0
    def test_average_grade(self):
        question_grade2 = mommy.make(Question, questionnaire=self.questionnaire, type="G")

        mommy.make(RatingAnswerCounter, question=self.question_grade, contribution=self.contribution1, answer=2, count=1)
        mommy.make(RatingAnswerCounter, question=self.question_grade, contribution=self.contribution2, answer=4, count=2)
        mommy.make(RatingAnswerCounter, question=question_grade2, contribution=self.contribution1, answer=1, count=1)
        mommy.make(RatingAnswerCounter, question=self.question_likert, contribution=self.contribution1, answer=3, count=4)
        mommy.make(RatingAnswerCounter, question=self.question_likert, contribution=self.general_contribution, answer=5, count=5)
        mommy.make(RatingAnswerCounter, question=self.question_likert_2, contribution=self.general_contribution, answer=3, count=3)

        contributor_weights_sum = settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT + settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT
        contributor1_average = ((settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT * ((2 * 1) + (1 * 1)) / (1 + 1)) + (settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT * 3)) / contributor_weights_sum  # 2.4
        contributor2_average = 4
        contributors_average = ((4 * contributor1_average) + (2 * contributor2_average)) / (4 + 2)  # 2.9333333

        course_non_grade_average = ((5 * 5) + (3 * 3)) / (5 + 3)  # 4.25

        contributors_percentage = settings.CONTRIBUTIONS_WEIGHT / (settings.CONTRIBUTIONS_WEIGHT + settings.COURSE_NON_GRADE_QUESTIONS_WEIGHT)  # 0.375
        course_non_grade_percentage = settings.COURSE_NON_GRADE_QUESTIONS_WEIGHT / (settings.CONTRIBUTIONS_WEIGHT + settings.COURSE_NON_GRADE_QUESTIONS_WEIGHT)  # 0.625

        total_grade = contributors_percentage * contributors_average + course_non_grade_percentage * course_non_grade_average  # 1.1 + 2.65625 = 3.75625

        average_grade = distribution_to_grade(calculate_average_distribution(self.course))
        self.assertAlmostEqual(average_grade, total_grade)
        self.assertAlmostEqual(average_grade, 3.75625)
예제 #5
0
파일: views.py 프로젝트: fsr-itse/EvaP
def get_evaluations_with_prefetched_data(evaluations):
    if isinstance(evaluations, QuerySet):
        participant_counts = evaluations.annotate(num_participants=Count("participants")).values_list("num_participants", flat=True)
        voter_counts = evaluations.annotate(num_voters=Count("voters")).values_list("num_voters", flat=True)
        course_evaluations_counts = evaluations.annotate(num_course_evaluations=Count("course__evaluations")).values_list("num_course_evaluations", flat=True)
        evaluations = (evaluations
            .select_related("course__type")
            .prefetch_related(
                "course__degrees",
                "course__semester",
                "course__responsibles",
            )
        )
        for evaluation, participant_count, voter_count, course_evaluations_count in zip(evaluations, participant_counts, voter_counts, course_evaluations_counts):
            if evaluation._participant_count is None:
                evaluation.num_participants = participant_count
                evaluation.num_voters = voter_count
            evaluation.course_evaluations_count = course_evaluations_count
    for evaluation in evaluations:
        if not evaluation.is_single_result:
            evaluation.distribution = calculate_average_distribution(evaluation)
            evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
        else:
            evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
    return evaluations
예제 #6
0
파일: views.py 프로젝트: Onderi/EvaP
def get_courses_with_prefetched_data(courses):
    if isinstance(courses, QuerySet):
        participant_counts = courses.annotate(
            num_participants=Count("participants")).values_list(
                "num_participants", flat=True)
        voter_counts = courses.annotate(
            num_voters=Count("voters")).values_list("num_voters", flat=True)
        courses = (courses.select_related("type").prefetch_related(
            "degrees", "semester",
            Prefetch("contributions",
                     queryset=Contribution.objects.filter(
                         responsible=True).select_related("contributor"),
                     to_attr="responsible_contributions")))
        for course, participant_count, voter_count in zip(
                courses, participant_counts, voter_counts):
            if course._participant_count is None:
                course.num_participants = participant_count
                course.num_voters = voter_count
            course.responsible_contributors = [
                contribution.contributor
                for contribution in course.responsible_contributions
            ]
    for course in courses:
        if not course.is_single_result:
            course.distribution = calculate_average_distribution(course)
            course.avg_grade = distribution_to_grade(course.distribution)
        else:
            course.single_result_rating_result = get_single_result_rating_result(
                course)
    return courses
예제 #7
0
파일: views.py 프로젝트: PFischbeck/EvaP
def index(request):
    user = request.user

    contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']
    own_courses = Course.objects.filter(contributions__contributor=user, state__in=contributor_visible_states)

    represented_users = user.represented_users.all()
    delegated_courses = Course.objects.exclude(id__in=own_courses).filter(contributions__can_edit=True, contributions__contributor__in=represented_users, state__in=contributor_visible_states)

    all_courses = list(own_courses) + list(delegated_courses)
    all_courses.sort(key=lambda course: list(STATES_ORDERED.keys()).index(course.state))

    for course in all_courses:
        course.distribution = calculate_average_distribution(course)
        course.avg_grade = distribution_to_grade(course.distribution)

    semesters = Semester.objects.all()
    semester_list = [dict(
        semester_name=semester.name,
        id=semester.id,
        is_active_semester=semester.is_active_semester,
        courses=[course for course in all_courses if course.semester_id == semester.id]
    ) for semester in semesters]

    template_data = dict(semester_list=semester_list, delegated_courses=delegated_courses)
    return render(request, "contributor_index.html", template_data)
예제 #8
0
파일: views.py 프로젝트: jmunden1/EvaP
def get_evaluations_of_course(course, request):
    course_evaluations = []

    if course.evaluations.count() > 1:
        course_evaluations = [
            evaluation
            for evaluation in course.evaluations.filter(state="published")
            if evaluation.can_be_seen_by(request.user)
        ]
        if request.user.is_reviewer:
            course_evaluations += course.evaluations.filter(
                state__in=['in_evaluation', 'evaluated', 'reviewed'])

        course_evaluations = get_evaluations_with_course_result_attributes(
            course_evaluations)

        for course_evaluation in course_evaluations:
            if course_evaluation.is_single_result:
                course_evaluation.single_result_rating_result = get_single_result_rating_result(
                    course_evaluation)
            else:
                course_evaluation.distribution = calculate_average_distribution(
                    course_evaluation)
                course_evaluation.avg_grade = distribution_to_grade(
                    course_evaluation.distribution)

    return course_evaluations
예제 #9
0
파일: test_tools.py 프로젝트: fsr-itse/EvaP
    def test_average_grade(self):
        question_grade2 = mommy.make(Question, questionnaire=self.questionnaire, type=Question.GRADE)

        mommy.make(RatingAnswerCounter, question=self.question_grade, contribution=self.contribution1, answer=2, count=1)
        mommy.make(RatingAnswerCounter, question=self.question_grade, contribution=self.contribution2, answer=4, count=2)
        mommy.make(RatingAnswerCounter, question=question_grade2, contribution=self.contribution1, answer=1, count=1)
        mommy.make(RatingAnswerCounter, question=self.question_likert, contribution=self.contribution1, answer=3, count=4)
        mommy.make(RatingAnswerCounter, question=self.question_likert, contribution=self.general_contribution, answer=5, count=5)
        mommy.make(RatingAnswerCounter, question=self.question_likert_2, contribution=self.general_contribution, answer=3, count=3)
        mommy.make(RatingAnswerCounter, question=self.question_bipolar, contribution=self.general_contribution, answer=3, count=2)
        mommy.make(RatingAnswerCounter, question=self.question_bipolar_2, contribution=self.general_contribution, answer=-1, count=4)

        contributor_weights_sum = settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT + settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT
        contributor1_average = ((settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT * ((2 * 1) + (1 * 1)) / (1 + 1)) + (settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT * 3)) / contributor_weights_sum  # 2.4
        contributor2_average = 4
        contributors_average = ((4 * contributor1_average) + (2 * contributor2_average)) / (4 + 2)  # 2.9333333

        general_non_grade_average = ((5 * 5) + (3 * 3) + (2 * 5) + (4 * 7 / 3)) / (5 + 3 + 2 + 4)  # 3.80952380

        contributors_percentage = settings.CONTRIBUTIONS_WEIGHT / (settings.CONTRIBUTIONS_WEIGHT + settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT)  # 0.375
        general_non_grade_percentage = settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT / (settings.CONTRIBUTIONS_WEIGHT + settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT)  # 0.625

        total_grade = contributors_percentage * contributors_average + general_non_grade_percentage * general_non_grade_average  # 1.1 + 2.38095238 = 3.48095238

        average_grade = distribution_to_grade(calculate_average_distribution(self.evaluation))
        self.assertAlmostEqual(average_grade, total_grade)
        self.assertAlmostEqual(average_grade, 3.48095238)
예제 #10
0
파일: views.py 프로젝트: fsr-itse/EvaP
def index(request):
    # retrieve all courses which have evaluations that are not in state "new" and in which the user participates
    courses = Course.objects.filter(
        evaluations__participants=request.user,
        evaluations__state__in=['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']
    ).distinct()
    # retrieve all evaluations which the user can see that are not new
    evaluations = [evaluation for course in courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(request.user)]
    for evaluation in evaluations:
        if evaluation.state == "published":
            if not evaluation.is_single_result:
                evaluation.distribution = calculate_average_distribution(evaluation)
                evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
            else:
                evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
        evaluation.participates_in = request.user in evaluation.participants.all()
        evaluation.voted_for = request.user in evaluation.voters.all()
    evaluations = get_evaluations_with_course_result_attributes(evaluations)
    evaluations.sort(key=lambda evaluation: evaluation.full_name)  # evaluations must be sorted for regrouping them in the template

    semesters = Semester.objects.all()
    semester_list = [dict(
        semester_name=semester.name,
        id=semester.id,
        is_active_semester=semester.is_active_semester,
        results_are_archived=semester.results_are_archived,
        grade_documents_are_deleted=semester.grade_documents_are_deleted,
        evaluations=[evaluation for evaluation in evaluations if evaluation.course.semester_id == semester.id]
    ) for semester in semesters]

    template_data = dict(
        semester_list=semester_list,
        can_download_grades=request.user.can_download_grades,
    )
    return render(request, "student_index.html", template_data)
예제 #11
0
def index(request):
    user = request.user
    show_delegated = get_parameter_from_url_or_session(request, "show_delegated", True)

    contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']
    own_courses = Course.objects.filter(
        Q(evaluations__state__in=contributor_visible_states) & (
            Q(responsibles=user) |
            Q(evaluations__contributions__contributor=user)
        )
    )
    own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]
    for evaluation in own_evaluations:
        evaluation.contributes_to = evaluation.contributions.filter(contributor=user).exists()

    displayed_evaluations = set(own_evaluations)
    if show_delegated:
        represented_users = user.represented_users.all()
        delegated_courses = Course.objects.filter(
            Q(evaluations__state__in=contributor_visible_states) & (
                Q(responsibles__in=represented_users) |
                Q(
                    evaluations__contributions__role=Contribution.Role.EDITOR,
                    evaluations__contributions__contributor__in=represented_users,
                )
            )
        )
        delegated_evaluations = set(evaluation for course in delegated_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user))
        for evaluation in delegated_evaluations:
            evaluation.delegated_evaluation = True
        displayed_evaluations |= delegated_evaluations - displayed_evaluations
    displayed_evaluations = list(displayed_evaluations)
    displayed_evaluations.sort(key=lambda evaluation: (evaluation.course.name, evaluation.name))  # evaluations must be sorted for regrouping them in the template

    for evaluation in displayed_evaluations:
        if evaluation.state == "published":
            if not evaluation.is_single_result:
                evaluation.distribution = calculate_average_distribution(evaluation)
            else:
                evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
                evaluation.distribution = normalized_distribution(evaluation.single_result_rating_result.counts)
            evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
    displayed_evaluations = get_evaluations_with_course_result_attributes(displayed_evaluations)

    semesters = Semester.objects.all()
    semester_list = [dict(
        semester_name=semester.name,
        id=semester.id,
        is_active=semester.is_active,
        evaluations=[evaluation for evaluation in displayed_evaluations if evaluation.course.semester_id == semester.id]
    ) for semester in semesters]

    template_data = dict(
        semester_list=semester_list,
        show_delegated=show_delegated,
        delegate_selection_form=DelegateSelectionForm(),
    )
    return render(request, "contributor_index.html", template_data)
예제 #12
0
파일: test_tools.py 프로젝트: janno42/EvaP
    def test_average_grade(self):
        question_grade2 = baker.make(Question,
                                     questionnaire=self.questionnaire,
                                     type=Question.GRADE)

        make_rating_answer_counters(self.question_grade, self.contribution1,
                                    [0, 1, 0, 0, 0])
        make_rating_answer_counters(self.question_grade, self.contribution2,
                                    [0, 0, 0, 2, 0])
        make_rating_answer_counters(question_grade2, self.contribution1,
                                    [1, 0, 0, 0, 0])
        make_rating_answer_counters(self.question_likert, self.contribution1,
                                    [0, 0, 4, 0, 0])
        make_rating_answer_counters(self.question_likert,
                                    self.general_contribution, [0, 0, 0, 0, 5])
        make_rating_answer_counters(self.question_likert_2,
                                    self.general_contribution, [0, 0, 3, 0, 0])
        make_rating_answer_counters(self.question_bipolar,
                                    self.general_contribution,
                                    [0, 0, 0, 0, 0, 0, 2])
        make_rating_answer_counters(self.question_bipolar_2,
                                    self.general_contribution,
                                    [0, 0, 4, 0, 0, 0, 0])

        cache_results(self.evaluation)

        contributor_weights_sum = (
            settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT +
            settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT)
        contributor1_average = (
            (settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT *
             ((2 * 1) + (1 * 1)) / (1 + 1)) +
            (settings.CONTRIBUTOR_NON_GRADE_RATING_QUESTIONS_WEIGHT *
             3)) / contributor_weights_sum  # 2.4
        contributor2_average = 4
        contributors_average = (
            (4 * contributor1_average) +
            (2 * contributor2_average)) / (4 + 2)  # 2.9333333

        general_non_grade_average = (
            (5 * 5) + (3 * 3) + (2 * 5) +
            (4 * 7 / 3)) / (5 + 3 + 2 + 4)  # 3.80952380

        contributors_percentage = settings.CONTRIBUTIONS_WEIGHT / (
            settings.CONTRIBUTIONS_WEIGHT +
            settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT)  # 0.375
        general_non_grade_percentage = settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT / (
            settings.CONTRIBUTIONS_WEIGHT +
            settings.GENERAL_NON_GRADE_QUESTIONS_WEIGHT)  # 0.625

        total_grade = (contributors_percentage * contributors_average +
                       general_non_grade_percentage * general_non_grade_average
                       )  # 1.1 + 2.38095238 = 3.48095238

        average_grade = distribution_to_grade(
            calculate_average_distribution(self.evaluation))
        self.assertAlmostEqual(average_grade, total_grade)
        self.assertAlmostEqual(average_grade, 3.48095238)
예제 #13
0
def index(request):
    # retrieve all courses which have evaluations that are not in state "new" and in which the user participates
    courses = Course.objects.filter(
        evaluations__participants=request.user,
        evaluations__state__in=[
            'prepared', 'editor_approved', 'approved', 'in_evaluation',
            'evaluated', 'reviewed', 'published'
        ]).distinct().prefetch_related('semester', 'grade_documents', 'type',
                                       'evaluations',
                                       'evaluations__participants',
                                       'evaluations__voters')
    # retrieve all evaluations which the user can see that are not new
    evaluations = [
        evaluation for course in courses
        for evaluation in course.evaluations.all()
        if evaluation.can_be_seen_by(request.user)
    ]
    for evaluation in evaluations:
        if evaluation.state == "published":
            if not evaluation.is_single_result:
                evaluation.distribution = calculate_average_distribution(
                    evaluation)
            else:
                evaluation.single_result_rating_result = get_single_result_rating_result(
                    evaluation)
                evaluation.distribution = normalized_distribution(
                    evaluation.single_result_rating_result.counts)
            evaluation.avg_grade = distribution_to_grade(
                evaluation.distribution)
        evaluation.participates_in = request.user in evaluation.participants.all(
        )
        evaluation.voted_for = request.user in evaluation.voters.all()
    evaluations = get_evaluations_with_course_result_attributes(evaluations)
    evaluations.sort(
        key=lambda evaluation: (evaluation.course.name, evaluation.name)
    )  # evaluations must be sorted for regrouping them in the template

    semesters = Semester.objects.all()
    semester_list = [
        dict(semester_name=semester.name,
             id=semester.id,
             is_active=semester.is_active,
             results_are_archived=semester.results_are_archived,
             grade_documents_are_deleted=semester.grade_documents_are_deleted,
             evaluations=[
                 evaluation for evaluation in evaluations
                 if evaluation.course.semester_id == semester.id
             ]) for semester in semesters
    ]

    template_data = dict(
        semester_list=semester_list,
        can_download_grades=request.user.can_download_grades,
    )

    return render(request, "student_index.html", template_data)
예제 #14
0
    def write_overall_results(self, evaluations_with_results,
                              course_results_exist):
        evaluations = [e for e, __ in evaluations_with_results]

        self.write_cell(_("Overall Average Grade"), "bold")
        averages = (distribution_to_grade(calculate_average_distribution(e))
                    for e in evaluations)
        self.write_row(
            averages, lambda avg: self.grade_to_style(avg)
            if avg else "border_left_right")

        self.write_cell(_("Total voters/Total participants"), "bold")
        voter_ratios = (f"{e.num_voters}/{e.num_participants}"
                        for e in evaluations)
        self.write_row(voter_ratios, style="total_voters")

        self.write_cell(_("Evaluation rate"), "bold")
        # round down like in progress bar
        participant_percentages = (
            f"{int((e.num_voters / e.num_participants) * 100) if e.num_participants > 0 else 0}%"
            for e in evaluations)
        self.write_row(participant_percentages, style="evaluation_rate")

        if course_results_exist:
            # Only query the number of evaluations once and keep track of it here.
            count_gt_1 = [e.course_evaluations_count > 1 for e in evaluations]

            # Borders only if there is a course grade below. Offset by one column
            self.write_empty_row_with_styles(["default"] + [
                "border_left_right" if gt1 else "default" for gt1 in count_gt_1
            ])

            self.write_cell(_("Evaluation weight"), "bold")
            weight_percentages = (f"{e.weight_percentage}%" if gt1 else None
                                  for e, gt1 in zip(evaluations, count_gt_1))
            self.write_row(
                weight_percentages, lambda s: "evaluation_weight"
                if s is not None else "default")

            self.write_cell(_("Course Grade"), "bold")
            for evaluation, gt1 in zip(evaluations, count_gt_1):
                if not gt1:
                    self.write_cell()
                    continue

                avg = evaluation.course.avg_grade
                style = self.grade_to_style(
                    avg) if avg is not None else "border_left_right"
                self.write_cell(avg, style)
            self.next_row()

            # Same reasoning as above.
            self.write_empty_row_with_styles(
                ["default"] +
                ["border_top" if gt1 else "default" for gt1 in count_gt_1])
예제 #15
0
파일: views.py 프로젝트: fsr-itse/EvaP
def index(request):
    user = request.user
    show_delegated = get_parameter_from_url_or_session(request, "show_delegated", True)

    contributor_visible_states = ['prepared', 'editor_approved', 'approved', 'in_evaluation', 'evaluated', 'reviewed', 'published']
    own_courses = Course.objects.filter(
        Q(evaluations__state__in=contributor_visible_states) & (
            Q(responsibles=user) |
            Q(evaluations__contributions__contributor=user)
        )
    )
    own_evaluations = [evaluation for course in own_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user)]
    for evaluation in own_evaluations:
        evaluation.contributes_to = evaluation.contributions.filter(contributor=user).exists()

    displayed_evaluations = set(own_evaluations)
    if show_delegated:
        represented_users = user.represented_users.all()
        delegated_courses = Course.objects.filter(
            Q(evaluations__state__in=contributor_visible_states) & (
                Q(responsibles__in=represented_users) |
                Q(evaluations__contributions__can_edit=True, evaluations__contributions__contributor__in=represented_users)
            )
        )
        delegated_evaluations = set(evaluation for course in delegated_courses for evaluation in course.evaluations.all() if evaluation.can_be_seen_by(user))
        for evaluation in delegated_evaluations:
            evaluation.delegated_evaluation = True
        displayed_evaluations |= delegated_evaluations - displayed_evaluations
    displayed_evaluations = list(displayed_evaluations)
    displayed_evaluations.sort(key=lambda evaluation: evaluation.full_name)  # evaluations must be sorted for regrouping them in the template

    for evaluation in displayed_evaluations:
        if evaluation.state == "published":
            if not evaluation.is_single_result:
                evaluation.distribution = calculate_average_distribution(evaluation)
                evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
            else:
                evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
    displayed_evaluations = get_evaluations_with_course_result_attributes(displayed_evaluations)

    semesters = Semester.objects.all()
    semester_list = [dict(
        semester_name=semester.name,
        id=semester.id,
        is_active_semester=semester.is_active_semester,
        evaluations=[evaluation for evaluation in displayed_evaluations if evaluation.course.semester_id == semester.id]
    ) for semester in semesters]

    template_data = dict(
        semester_list=semester_list,
        show_delegated=show_delegated,
        delegate_selection_form=DelegateSelectionForm(),
    )
    return render(request, "contributor_index.html", template_data)
예제 #16
0
def index(request):
    user = request.user
    show_delegated = get_parameter_from_url_or_session(request,
                                                       "show_delegated", True)

    contributor_visible_states = [
        'prepared', 'editor_approved', 'approved', 'in_evaluation',
        'evaluated', 'reviewed', 'published'
    ]
    own_evaluations = Evaluation.objects.filter(
        contributions__contributor=user, state__in=contributor_visible_states)

    displayed_evaluations = list(own_evaluations)
    if show_delegated:
        represented_users = user.represented_users.all()
        delegated_evaluations = Evaluation.objects.exclude(
            id__in=own_evaluations).filter(
                contributions__can_edit=True,
                contributions__contributor__in=represented_users,
                state__in=contributor_visible_states)
        for evaluation in delegated_evaluations:
            evaluation.delegated_evaluation = True
        displayed_evaluations += list(delegated_evaluations)
    displayed_evaluations.sort(key=lambda evaluation: list(STATES_ORDERED.keys(
    )).index(evaluation.state))

    delegate_selection_form = DelegateSelectionForm()

    for evaluation in displayed_evaluations:
        evaluation.distribution = calculate_average_distribution(evaluation)
        evaluation.avg_grade = distribution_to_grade(evaluation.distribution)

    semesters = Semester.objects.all()
    semester_list = [
        dict(semester_name=semester.name,
             id=semester.id,
             is_active_semester=semester.is_active_semester,
             evaluations=[
                 evaluation for evaluation in displayed_evaluations
                 if evaluation.course.semester_id == semester.id
             ]) for semester in semesters
    ]

    template_data = dict(
        semester_list=semester_list,
        show_delegated=show_delegated,
        delegate_selection_form=delegate_selection_form,
    )
    return render(request, "contributor_index.html", template_data)
예제 #17
0
def index(request):
    # retrieve all evaluations, where the user is a participant and that are not new
    evaluations = list(
        set(
            Evaluation.objects.filter(participants=request.user).exclude(
                state="new")))
    for evaluation in evaluations:
        evaluation.distribution = calculate_average_distribution(evaluation)
        evaluation.avg_grade = distribution_to_grade(evaluation.distribution)

    voted_evaluations = list(
        set(Evaluation.objects.filter(voters=request.user)))
    due_evaluations = list(
        set(
            Evaluation.objects.filter(
                participants=request.user,
                state='in_evaluation').exclude(voters=request.user)))

    # due evaluations come first, then everything else in chronological order
    # some states are handled as a group because they appear the same to students
    def sorter(evaluation):
        return (evaluation not in due_evaluations, evaluation.state
                not in ['prepared', 'editor_approved',
                        'approved'], evaluation.state != 'in_evaluation',
                evaluation.state not in ['evaluated',
                                         'reviewed'], evaluation.name)

    evaluations.sort(key=sorter)

    semesters = Semester.objects.all()
    semester_list = [
        dict(semester_name=semester.name,
             id=semester.id,
             is_active_semester=semester.is_active_semester,
             results_are_archived=semester.results_are_archived,
             grade_documents_are_deleted=semester.grade_documents_are_deleted,
             evaluations=[
                 evaluation for evaluation in evaluations
                 if evaluation.course.semester_id == semester.id
             ]) for semester in semesters
    ]

    template_data = dict(
        semester_list=semester_list,
        voted_evaluations=voted_evaluations,
        can_download_grades=request.user.can_download_grades,
    )
    return render(request, "student_index.html", template_data)
예제 #18
0
def index(request):
    # retrieve all courses, where the user is a participant and that are not new
    courses = list(
        set(
            Course.objects.filter(participants=request.user).exclude(
                state="new")))
    for course in courses:
        course.distribution = calculate_average_distribution(course)
        course.avg_grade = distribution_to_grade(course.distribution)

    voted_courses = list(set(Course.objects.filter(voters=request.user)))
    due_courses = list(
        set(
            Course.objects.filter(
                participants=request.user,
                state='in_evaluation').exclude(voters=request.user)))

    # due courses come first, then everything else in chronological order
    # some states are handled as a group because they appear the same to students
    sorter = lambda course: (course not in due_courses, course.state not in [
        'prepared', 'editor_approved', 'approved'
    ], course.state != 'in_evaluation', course.state not in
                             ['evaluated', 'reviewed'], course.name)
    courses.sort(key=sorter)

    semesters = Semester.objects.all()
    semester_list = [
        dict(semester_name=semester.name,
             id=semester.id,
             is_active_semester=semester.is_active_semester,
             results_are_archived=semester.results_are_archived,
             courses=[
                 course for course in courses
                 if course.semester_id == semester.id
             ]) for semester in semesters
    ]

    template_data = dict(
        semester_list=semester_list,
        voted_courses=voted_courses,
        can_download_grades=request.user.can_download_grades,
    )
    return render(request, "student_index.html", template_data)
예제 #19
0
파일: views.py 프로젝트: PFischbeck/EvaP
def get_courses_with_prefetched_data(courses):
    if isinstance(courses, QuerySet):
        courses = (courses
            .annotate(num_participants=Count("participants", distinct=True), num_voters=Count("voters", distinct=True))
            .select_related("type")
            .prefetch_related(
                "degrees",
                "semester",
                Prefetch("contributions", queryset=Contribution.objects.filter(responsible=True).select_related("contributor"), to_attr="responsible_contributions")
            )
        )
        for course in courses:
            course.responsible_contributors = [contribution.contributor for contribution in course.responsible_contributions]
    for course in courses:
        if not course.is_single_result:
            course.distribution = calculate_average_distribution(course)
            course.avg_grade = distribution_to_grade(course.distribution)
        else:
            course.single_result_rating_result = get_single_result_rating_result(course)
    return courses
예제 #20
0
def get_evaluations_with_prefetched_data(evaluations):
    if isinstance(evaluations, QuerySet):
        evaluations = (evaluations
            .select_related("course__type")
            .prefetch_related(
                "course__degrees",
                "course__semester",
                "course__responsibles",
            )
        )
        evaluations = Evaluation.annotate_with_participant_and_voter_counts(evaluations)

    for evaluation in evaluations:
        if not evaluation.is_single_result:
            evaluation.distribution = calculate_average_distribution(evaluation)
        else:
            evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
            evaluation.distribution = normalized_distribution(evaluation.single_result_rating_result.counts)
        evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
    return evaluations
예제 #21
0
def index(request):
    user = request.user

    contributor_visible_states = [
        'prepared', 'editor_approved', 'approved', 'in_evaluation',
        'evaluated', 'reviewed', 'published'
    ]
    own_courses = Course.objects.filter(contributions__contributor=user,
                                        state__in=contributor_visible_states)

    represented_users = user.represented_users.all()
    delegated_courses = Course.objects.exclude(id__in=own_courses).filter(
        contributions__can_edit=True,
        contributions__contributor__in=represented_users,
        state__in=contributor_visible_states)

    all_courses = list(own_courses) + list(delegated_courses)
    all_courses.sort(
        key=lambda course: list(STATES_ORDERED.keys()).index(course.state))

    for course in all_courses:
        course.distribution = calculate_average_distribution(
            course) if course.can_user_see_grades(user) else None
        course.avg_grade = distribution_to_grade(course.distribution)

    semesters = Semester.objects.all()
    semester_list = [
        dict(semester_name=semester.name,
             id=semester.id,
             is_active_semester=semester.is_active_semester,
             courses=[
                 course for course in all_courses
                 if course.semester_id == semester.id
             ]) for semester in semesters
    ]

    template_data = dict(semester_list=semester_list,
                         delegated_courses=delegated_courses)
    return render(request, "contributor_index.html", template_data)
예제 #22
0
def semester_detail(request, semester_id):
    semester = get_object_or_404(Semester, id=semester_id)

    visible_states = ['published']
    if request.user.is_reviewer:
        visible_states += ['in_evaluation', 'evaluated', 'reviewed']

    courses = semester.course_set.filter(
        state__in=visible_states).prefetch_related("degrees")

    courses = [
        course for course in courses
        if course.can_user_see_course(request.user)
    ]

    for course in courses:
        course.distribution = calculate_average_distribution(
            course) if course.can_user_see_grades(request.user) else None
        course.avg_grade = distribution_to_grade(course.distribution)

    CourseTuple = namedtuple('CourseTuple', ('courses', 'single_results'))

    courses_by_degree = OrderedDict()
    for degree in Degree.objects.all():
        courses_by_degree[degree] = CourseTuple([], [])
    for course in courses:
        if course.is_single_result:
            for degree in course.degrees.all():
                section = calculate_results(course)[0]
                result = section.results[0]
                courses_by_degree[degree].single_results.append(
                    (course, result))
        else:
            for degree in course.degrees.all():
                courses_by_degree[degree].courses.append(course)

    template_data = dict(semester=semester,
                         courses_by_degree=courses_by_degree)
    return render(request, "results_semester_detail.html", template_data)
예제 #23
0
파일: views.py 프로젝트: PFischbeck/EvaP
def index(request):
    # retrieve all courses, where the user is a participant and that are not new
    courses = list(set(Course.objects.filter(participants=request.user).exclude(state="new")))
    for course in courses:
        course.distribution = calculate_average_distribution(course)
        course.avg_grade = distribution_to_grade(course.distribution)

    voted_courses = list(set(Course.objects.filter(voters=request.user)))
    due_courses = list(set(Course.objects.filter(participants=request.user, state='in_evaluation').exclude(voters=request.user)))

    # due courses come first, then everything else in chronological order
    # some states are handled as a group because they appear the same to students
    sorter = lambda course: (
        course not in due_courses,
        course.state not in ['prepared', 'editor_approved', 'approved'],
        course.state != 'in_evaluation',
        course.state not in ['evaluated', 'reviewed'],
        course.name
    )
    courses.sort(key=sorter)

    semesters = Semester.objects.all()
    semester_list = [dict(
        semester_name=semester.name,
        id=semester.id,
        is_active_semester=semester.is_active_semester,
        results_are_archived=semester.results_are_archived,
        grade_documents_are_deleted=semester.grade_documents_are_deleted,
        courses=[course for course in courses if course.semester_id == semester.id]
    ) for semester in semesters]

    template_data = dict(
        semester_list=semester_list,
        voted_courses=voted_courses,
        can_download_grades=request.user.can_download_grades,
    )
    return render(request, "student_index.html", template_data)
예제 #24
0
파일: views.py 프로젝트: jmunden1/EvaP
def get_evaluations_with_prefetched_data(evaluations):
    if isinstance(evaluations, QuerySet):
        # these annotates and the zip below could be replaced by something like this, but it was 2x slower:
        # annotate(num_participants=Coalesce('_participant_count', Count("participants", distinct=True)))
        participant_counts = evaluations.annotate(
            num_participants=Count("participants")).order_by('pk').values_list(
                "num_participants", flat=True)
        voter_counts = evaluations.annotate(
            num_voters=Count("voters")).order_by('pk').values_list(
                "num_voters", flat=True)
        course_evaluations_counts = evaluations.annotate(
            num_course_evaluations=Count("course__evaluations")).order_by(
                'pk').values_list("num_course_evaluations", flat=True)
        evaluations = (
            evaluations.select_related("course__type").prefetch_related(
                "course__degrees",
                "course__semester",
                "course__responsibles",
            ))
        for evaluation, participant_count, voter_count, course_evaluations_count in zip(
                evaluations, participant_counts, voter_counts,
                course_evaluations_counts):
            if evaluation._participant_count is None:
                evaluation.num_participants = participant_count
                evaluation.num_voters = voter_count
            evaluation.course_evaluations_count = course_evaluations_count
    for evaluation in evaluations:
        if not evaluation.is_single_result:
            evaluation.distribution = calculate_average_distribution(
                evaluation)
        else:
            evaluation.single_result_rating_result = get_single_result_rating_result(
                evaluation)
            evaluation.distribution = normalized_distribution(
                evaluation.single_result_rating_result.counts)
        evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
    return evaluations
예제 #25
0
def get_evaluations_of_course(course, request):
    course_evaluations = []

    if course.evaluations.count() > 1:
        course_evaluations = [
            evaluation
            for evaluation in course.evaluations.filter(state=Evaluation.State.PUBLISHED)
            if evaluation.can_be_seen_by(request.user)
        ]
        if request.user.is_reviewer:
            course_evaluations += course.evaluations.filter(
                state__in=[Evaluation.State.IN_EVALUATION, Evaluation.State.EVALUATED, Evaluation.State.REVIEWED]
            )

        course_evaluations = get_evaluations_with_course_result_attributes(course_evaluations)

        for course_evaluation in course_evaluations:
            if course_evaluation.is_single_result:
                course_evaluation.single_result_rating_result = get_single_result_rating_result(course_evaluation)
            else:
                course_evaluation.distribution = calculate_average_distribution(course_evaluation)
                course_evaluation.avg_grade = distribution_to_grade(course_evaluation.distribution)

    return course_evaluations
예제 #26
0
파일: exporters.py 프로젝트: fsr-itse/EvaP
    def export(self, response, course_types_list, include_not_enough_voters=False, include_unpublished=False):
        self.workbook = xlwt.Workbook()
        self.init_styles(self.workbook)
        counter = 1
        course_results_exist = False

        for course_types in course_types_list:
            self.sheet = self.workbook.add_sheet("Sheet " + str(counter))
            counter += 1
            self.row = 0
            self.col = 0

            evaluations_with_results = list()
            evaluation_states = ['published']
            if include_unpublished:
                evaluation_states.extend(['evaluated', 'reviewed'])

            used_questionnaires = set()
            for evaluation in self.semester.evaluations.filter(state__in=evaluation_states, course__type__in=course_types).all():
                if evaluation.is_single_result:
                    continue
                if not evaluation.can_publish_rating_results and not include_not_enough_voters:
                    continue
                results = OrderedDict()
                for questionnaire_result in collect_results(evaluation).questionnaire_results:
                    if all(not question_result.question.is_rating_question or question_result.counts is None for question_result in questionnaire_result.question_results):
                        continue
                    results.setdefault(questionnaire_result.questionnaire.id, []).extend(questionnaire_result.question_results)
                    used_questionnaires.add(questionnaire_result.questionnaire)
                evaluation.course_evaluations_count = evaluation.course.evaluations.count()
                if evaluation.course_evaluations_count > 1:
                    course_results_exist = True
                    evaluation.weight_percentage = int((evaluation.weight / sum(evaluation.weight for evaluation in evaluation.course.evaluations.all())) * 100)
                    evaluation.course.avg_grade = distribution_to_grade(calculate_average_course_distribution(evaluation.course))
                evaluations_with_results.append((evaluation, results))

            evaluations_with_results.sort(key=lambda cr: (cr[0].course.type.order, cr[0].full_name))
            used_questionnaires = sorted(used_questionnaires)

            course_type_names = [ct.name for ct in CourseType.objects.filter(pk__in=course_types)]
            writec(self, _("Evaluation {0}\n\n{1}").format(self.semester.name, ", ".join(course_type_names)), "headline")

            for evaluation, results in evaluations_with_results:
                writec(self, evaluation.full_name, "evaluation")

            writen(self, _("Course Degrees"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(self, "\n".join([d.name for d in evaluation.course.degrees.all()]), "degree")

            writen(self, _("Course Type"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(self, evaluation.course.type.name, "border_left_right")

            writen(self)
            for evaluation, results in evaluations_with_results:
                self.write_empty_cell_with_borders()

            for questionnaire in used_questionnaires:
                writen(self, questionnaire.name, "bold")
                for evaluation, results in evaluations_with_results:
                    self.write_empty_cell_with_borders()

                filtered_questions = self.filter_text_and_heading_questions(questionnaire.questions.all())

                for question in filtered_questions:
                    if question.is_heading_question:
                        writen(self, question.text, "italic")
                    else:
                        writen(self, question.text)

                    for evaluation, results in evaluations_with_results:
                        if questionnaire.id not in results or question.is_heading_question:
                            self.write_empty_cell_with_borders()
                            continue
                        qn_results = results[questionnaire.id]
                        values = []
                        count_sum = 0
                        approval_count = 0

                        for grade_result in qn_results:
                            if grade_result.question.id == question.id:
                                if grade_result.has_answers:
                                    values.append(grade_result.average * grade_result.count_sum)
                                    count_sum += grade_result.count_sum
                                    if grade_result.question.is_yes_no_question:
                                        approval_count += grade_result.approval_count
                        if values:
                            avg = sum(values) / count_sum

                            if question.is_yes_no_question:
                                percent_approval = approval_count / count_sum if count_sum > 0 else 0
                                writec(self, "{:.0%}".format(percent_approval), self.grade_to_style(avg))
                            else:
                                writec(self, avg, self.grade_to_style(avg))
                        else:
                            self.write_empty_cell_with_borders()
                writen(self)
                for evaluation, results in evaluations_with_results:
                    self.write_empty_cell_with_borders()

            writen(self, _("Overall Average Grade"), "bold")
            for evaluation, results in evaluations_with_results:
                avg = distribution_to_grade(calculate_average_distribution(evaluation))
                if avg:
                    writec(self, avg, self.grade_to_style(avg))
                else:
                    self.write_empty_cell_with_borders()

            writen(self, _("Total voters/Total participants"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(self, "{}/{}".format(evaluation.num_voters, evaluation.num_participants), "total_voters")

            writen(self, _("Evaluation rate"), "bold")
            for evaluation, results in evaluations_with_results:
                # round down like in progress bar
                percentage_participants = int((evaluation.num_voters / evaluation.num_participants) * 100) if evaluation.num_participants > 0 else 0
                writec(self, "{}%".format(percentage_participants), "evaluation_rate")

            if course_results_exist:
                writen(self)
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        self.write_empty_cell_with_borders()
                    else:
                        self.write_empty_cell()

                writen(self, _("Evaluation weight"), "bold")
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        writec(self, "{}%".format(evaluation.weight_percentage), "evaluation_weight")
                    else:
                        self.write_empty_cell()

                writen(self, _("Course Grade"), "bold")
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        if evaluation.course.avg_grade:
                            writec(self, evaluation.course.avg_grade, self.grade_to_style(evaluation.course.avg_grade))
                        else:
                            self.write_empty_cell_with_borders()
                    else:
                        self.write_empty_cell()

                writen(self)
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        writec(self, None, "border_top")
                    else:
                        self.write_empty_cell()

        self.workbook.save(response)
예제 #27
0
파일: views.py 프로젝트: bissssss1/EvapP
def index(request):
    query = (Evaluation.objects
        .annotate(participates_in=Exists(Evaluation.objects.filter(id=OuterRef('id'), participants=request.user)))
        .annotate(voted_for=Exists(Evaluation.objects.filter(id=OuterRef('id'), voters=request.user)))

        .filter(~Q(state="new"), course__evaluations__participants=request.user)
        .exclude(state="new")
        .prefetch_related(
            'course', 'course__semester', 'course__grade_documents', 'course__type',
            'course__evaluations', 'course__responsibles', 'course__degrees',
        )
        .distinct()
    )
    query = Evaluation.annotate_with_participant_and_voter_counts(query)
    evaluations = [evaluation for evaluation in query if evaluation.can_be_seen_by(request.user)]

    inner_evaluation_ids = [inner_evaluation.id for evaluation in evaluations for inner_evaluation in evaluation.course.evaluations.all()]
    inner_evaluation_query = Evaluation.objects.filter(pk__in=inner_evaluation_ids)
    inner_evaluation_query = Evaluation.annotate_with_participant_and_voter_counts(inner_evaluation_query)

    evaluations_by_id = {evaluation['id']: evaluation for evaluation in inner_evaluation_query.values()}

    for evaluation in evaluations:
        for inner_evaluation in evaluation.course.evaluations.all():
            inner_evaluation.num_voters = evaluations_by_id[inner_evaluation.id]['num_voters']
            inner_evaluation.num_participants = evaluations_by_id[inner_evaluation.id]['num_participants']

    for evaluation in evaluations:
        if evaluation.state == "published":
            if not evaluation.is_single_result:
                evaluation.distribution = calculate_average_distribution(evaluation)
            else:
                evaluation.single_result_rating_result = get_single_result_rating_result(evaluation)
                evaluation.distribution = normalized_distribution(evaluation.single_result_rating_result.counts)
            evaluation.avg_grade = distribution_to_grade(evaluation.distribution)
    evaluations = get_evaluations_with_course_result_attributes(evaluations)

    # evaluations must be sorted for regrouping them in the template
    evaluations.sort(key=lambda evaluation: (evaluation.course.name, evaluation.name))

    semesters = Semester.objects.all()
    semester_list = [dict(
        semester_name=semester.name,
        id=semester.id,
        results_are_archived=semester.results_are_archived,
        grade_documents_are_deleted=semester.grade_documents_are_deleted,
        evaluations=[evaluation for evaluation in evaluations if evaluation.course.semester_id == semester.id]
    ) for semester in semesters]

    unfinished_evaluations_query = (
        Evaluation.objects
        .filter(participants=request.user, state__in=['prepared', 'editor_approved', 'approved', 'in_evaluation'])
        .exclude(voters=request.user)
        .prefetch_related('course__responsibles', 'course__type', 'course__semester')
    )

    unfinished_evaluations_query = Evaluation.annotate_with_participant_and_voter_counts(unfinished_evaluations_query)
    unfinished_evaluations = list(unfinished_evaluations_query)

    # available evaluations come first, ordered by time left for evaluation and the name
    # evaluations in other (visible) states follow by name
    def sorter(evaluation):
        return (
            evaluation.state != 'in_evaluation',
            evaluation.vote_end_date if evaluation.state == 'in_evaluation' else None,
            evaluation.full_name
        )
    unfinished_evaluations.sort(key=sorter)

    template_data = dict(
        semester_list=semester_list,
        can_download_grades=request.user.can_download_grades,
        unfinished_evaluations=unfinished_evaluations,
        evaluation_end_warning_period=settings.EVALUATION_END_WARNING_PERIOD,
    )

    return render(request, "student_index.html", template_data)
예제 #28
0
    def export(self,
               response,
               selection_list,
               include_not_enough_voters=False,
               include_unpublished=False):
        self.workbook = xlwt.Workbook()
        self.init_styles(self.workbook)
        counter = 1
        course_results_exist = False

        for degrees, course_types in selection_list:
            self.sheet = self.workbook.add_sheet("Sheet " + str(counter))
            counter += 1
            self.row = 0
            self.col = 0

            evaluations_with_results = list()
            evaluation_states = ['published']
            if include_unpublished:
                evaluation_states.extend(['evaluated', 'reviewed'])

            used_questionnaires = set()
            for evaluation in self.semester.evaluations.filter(
                    state__in=evaluation_states,
                    course__degrees__in=degrees,
                    course__type__in=course_types).distinct():
                if evaluation.is_single_result:
                    continue
                if not evaluation.can_publish_rating_results and not include_not_enough_voters:
                    continue
                results = OrderedDict()
                for questionnaire_result in collect_results(
                        evaluation).questionnaire_results:
                    if all(not question_result.question.is_rating_question
                           or question_result.counts is None
                           for question_result in
                           questionnaire_result.question_results):
                        continue
                    results.setdefault(
                        questionnaire_result.questionnaire.id,
                        []).extend(questionnaire_result.question_results)
                    used_questionnaires.add(questionnaire_result.questionnaire)
                evaluation.course_evaluations_count = evaluation.course.evaluations.count(
                )
                if evaluation.course_evaluations_count > 1:
                    course_results_exist = True
                    evaluation.weight_percentage = int(
                        (evaluation.weight / sum(evaluation.weight
                                                 for evaluation in evaluation.
                                                 course.evaluations.all())) *
                        100)
                    evaluation.course.avg_grade = distribution_to_grade(
                        calculate_average_course_distribution(
                            evaluation.course))
                evaluations_with_results.append((evaluation, results))

            evaluations_with_results.sort(
                key=lambda cr: (cr[0].course.type.order, cr[0].full_name))
            used_questionnaires = sorted(used_questionnaires)

            degree_names = [
                degree.name for degree in Degree.objects.filter(pk__in=degrees)
            ]
            course_type_names = [
                course_type.name for course_type in CourseType.objects.filter(
                    pk__in=course_types)
            ]
            writec(
                self,
                _("Evaluation {}\n\n{}\n\n{}").format(
                    self.semester.name, ", ".join(degree_names),
                    ", ".join(course_type_names)), "headline")

            for evaluation, results in evaluations_with_results:
                writec(self, evaluation.full_name, "evaluation")

            writen(self, _("Degrees"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(
                    self, "\n".join(
                        [d.name for d in evaluation.course.degrees.all()]),
                    "degree")

            writen(self, _("Course Type"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(self, evaluation.course.type.name, "border_left_right")

            writen(self)
            for evaluation, results in evaluations_with_results:
                self.write_empty_cell_with_borders()

            for questionnaire in used_questionnaires:
                writen(self, questionnaire.name, "bold")
                for evaluation, results in evaluations_with_results:
                    self.write_empty_cell_with_borders()

                filtered_questions = self.filter_text_and_heading_questions(
                    questionnaire.questions.all())

                for question in filtered_questions:
                    if question.is_heading_question:
                        writen(self, question.text, "italic")
                    else:
                        writen(self, question.text)

                    for evaluation, results in evaluations_with_results:
                        if questionnaire.id not in results or question.is_heading_question:
                            self.write_empty_cell_with_borders()
                            continue
                        qn_results = results[questionnaire.id]
                        values = []
                        count_sum = 0
                        approval_count = 0

                        for grade_result in qn_results:
                            if grade_result.question.id == question.id:
                                if grade_result.has_answers:
                                    values.append(grade_result.average *
                                                  grade_result.count_sum)
                                    count_sum += grade_result.count_sum
                                    if grade_result.question.is_yes_no_question:
                                        approval_count += grade_result.approval_count
                        if values:
                            avg = sum(values) / count_sum

                            if question.is_yes_no_question:
                                percent_approval = approval_count / count_sum if count_sum > 0 else 0
                                writec(self, "{:.0%}".format(percent_approval),
                                       self.grade_to_style(avg))
                            else:
                                writec(self, avg, self.grade_to_style(avg))
                        else:
                            self.write_empty_cell_with_borders()
                writen(self)
                for evaluation, results in evaluations_with_results:
                    self.write_empty_cell_with_borders()

            writen(self, _("Overall Average Grade"), "bold")
            for evaluation, results in evaluations_with_results:
                avg = distribution_to_grade(
                    calculate_average_distribution(evaluation))
                if avg:
                    writec(self, avg, self.grade_to_style(avg))
                else:
                    self.write_empty_cell_with_borders()

            writen(self, _("Total voters/Total participants"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(
                    self, "{}/{}".format(evaluation.num_voters,
                                         evaluation.num_participants),
                    "total_voters")

            writen(self, _("Evaluation rate"), "bold")
            for evaluation, results in evaluations_with_results:
                # round down like in progress bar
                percentage_participants = int(
                    (evaluation.num_voters / evaluation.num_participants) *
                    100) if evaluation.num_participants > 0 else 0
                writec(self, "{}%".format(percentage_participants),
                       "evaluation_rate")

            if course_results_exist:
                writen(self)
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        self.write_empty_cell_with_borders()
                    else:
                        self.write_empty_cell()

                writen(self, _("Evaluation weight"), "bold")
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        writec(self,
                               "{}%".format(evaluation.weight_percentage),
                               "evaluation_weight")
                    else:
                        self.write_empty_cell()

                writen(self, _("Course Grade"), "bold")
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        if evaluation.course.avg_grade:
                            writec(
                                self, evaluation.course.avg_grade,
                                self.grade_to_style(
                                    evaluation.course.avg_grade))
                        else:
                            self.write_empty_cell_with_borders()
                    else:
                        self.write_empty_cell()

                writen(self)
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        writec(self, None, "border_top")
                    else:
                        self.write_empty_cell()

        self.workbook.save(response)
예제 #29
0
파일: views.py 프로젝트: PFischbeck/EvaP
def course_detail(request, semester_id, course_id):
    semester = get_object_or_404(Semester, id=semester_id)
    course = get_object_or_404(semester.course_set, id=course_id, semester=semester)

    if not course.can_user_see_results_page(request.user):
        raise PermissionDenied

    course_result = collect_results(course)

    if request.user.is_reviewer:
        public_view = request.GET.get('public_view') != 'false'  # if parameter is not given, show public view.
    else:
        public_view = request.GET.get('public_view') == 'true'  # if parameter is not given, show own view.

    # redirect to non-public view if there is none because the results have not been published
    if not course.can_publish_rating_results:
        public_view = False

    represented_users = list(request.user.represented_users.all()) + [request.user]

    # remove text answers if the user may not see them
    for questionnaire_result in course_result.questionnaire_results:
        for question_result in questionnaire_result.question_results:
            if isinstance(question_result, TextResult):
                question_result.answers = [answer for answer in question_result.answers if user_can_see_text_answer(request.user, represented_users, answer, public_view)]
        # remove empty TextResults
        questionnaire_result.question_results = [result for result in questionnaire_result.question_results if not isinstance(result, TextResult) or len(result.answers) > 0]

    # filter empty headings
    for questionnaire_result in course_result.questionnaire_results:
        filtered_question_results = []
        for index, question_result in enumerate(questionnaire_result.question_results):
            # filter out if there are no more questions or the next question is also a heading question
            if isinstance(question_result, HeadingResult):
                if index == len(questionnaire_result.question_results) - 1 or isinstance(questionnaire_result.question_results[index + 1], HeadingResult):
                    continue
            filtered_question_results.append(question_result)
        questionnaire_result.question_results = filtered_question_results

    # remove empty questionnaire_results and contribution_results
    for contribution_result in course_result.contribution_results:
        contribution_result.questionnaire_results = [questionnaire_result for questionnaire_result in contribution_result.questionnaire_results if questionnaire_result.question_results]
    course_result.contribution_results = [contribution_result for contribution_result in course_result.contribution_results if contribution_result.questionnaire_results]

    add_warnings(course, course_result)

    # split course_result into different lists
    course_questionnaire_results_top = []
    course_questionnaire_results_bottom = []
    contributor_contribution_results = []
    for contribution_result in course_result.contribution_results:
        if contribution_result.contributor is None:
            for questionnaire_result in contribution_result.questionnaire_results:
                if questionnaire_result.questionnaire.is_below_contributors:
                    course_questionnaire_results_bottom.append(questionnaire_result)
                else:
                    course_questionnaire_results_top.append(questionnaire_result)
        else:
            contributor_contribution_results.append(contribution_result)

    if not contributor_contribution_results:
        course_questionnaire_results_top += course_questionnaire_results_bottom
        course_questionnaire_results_bottom = []

    course.distribution = calculate_average_distribution(course)
    course.avg_grade = distribution_to_grade(course.distribution)

    template_data = dict(
            course=course,
            course_questionnaire_results_top=course_questionnaire_results_top,
            course_questionnaire_results_bottom=course_questionnaire_results_bottom,
            contributor_contribution_results=contributor_contribution_results,
            reviewer=request.user.is_reviewer,
            contributor=course.is_user_contributor_or_delegate(request.user),
            can_download_grades=request.user.can_download_grades,
            public_view=public_view)
    return render(request, "results_course_detail.html", template_data)
예제 #30
0
    def export(self,
               response,
               semesters,
               selection_list,
               include_not_enough_voters=False,
               include_unpublished=False,
               contributor=None):
        # the excel file we're creating here is rather complex. However, from the nature of a single
        # file, it doesn't make much sense to split up the code into different methods as they will
        # always be tightly coupled based on the layout of the sheet. We thus think that one big method
        # containing the business logic is okay here
        # pylint: disable=too-many-locals, too-many-nested-blocks, too-many-branches, too-many-statements
        workbook = xlwt.Workbook()
        self.init_styles(workbook)
        counter = 1
        course_results_exist = False

        for degrees, course_types in selection_list:
            self.sheet = workbook.add_sheet("Sheet " + str(counter))
            counter += 1
            self.row = 0
            self.col = 0

            evaluations_with_results = list()
            evaluation_states = ['published']
            if include_unpublished:
                evaluation_states.extend(['evaluated', 'reviewed'])

            used_questionnaires = set()
            evaluations_filter = Q(course__semester__in=semesters,
                                   state__in=evaluation_states,
                                   course__degrees__in=degrees,
                                   course__type__in=course_types)
            if contributor:
                evaluations_filter = evaluations_filter & (
                    Q(course__responsibles__in=[contributor])
                    | Q(contributions__contributor__in=[contributor]))
            evaluations = Evaluation.objects.filter(
                evaluations_filter).distinct()
            for evaluation in evaluations:
                if evaluation.is_single_result:
                    continue
                if not evaluation.can_publish_rating_results and not include_not_enough_voters:
                    continue
                results = OrderedDict()
                for contribution_result in collect_results(
                        evaluation).contribution_results:
                    for questionnaire_result in contribution_result.questionnaire_results:
                        if all(not question_result.question.is_rating_question
                               or question_result.counts is None
                               for question_result in
                               questionnaire_result.question_results):
                            continue
                        if not contributor or contribution_result.contributor is None or contribution_result.contributor == contributor:
                            results.setdefault(
                                questionnaire_result.questionnaire.id,
                                []).extend(
                                    questionnaire_result.question_results)
                            used_questionnaires.add(
                                questionnaire_result.questionnaire)
                evaluation.course_evaluations_count = evaluation.course.evaluations.count(
                )
                if evaluation.course_evaluations_count > 1:
                    course_results_exist = True
                    evaluation.weight_percentage = int(
                        (evaluation.weight / sum(evaluation.weight
                                                 for evaluation in evaluation.
                                                 course.evaluations.all())) *
                        100)
                    evaluation.course.avg_grade = distribution_to_grade(
                        calculate_average_course_distribution(
                            evaluation.course))
                evaluations_with_results.append((evaluation, results))

            evaluations_with_results.sort(
                key=lambda cr: (cr[0].course.semester.id, cr[0].course.type.
                                order, cr[0].full_name))
            used_questionnaires = sorted(used_questionnaires)

            export_name = "Evaluation"
            if contributor:
                export_name += "\n{}".format(contributor.full_name)
            elif len(semesters) == 1:
                export_name += "\n{}".format(semesters[0].name)
            degree_names = [
                degree.name for degree in Degree.objects.filter(pk__in=degrees)
            ]
            course_type_names = [
                course_type.name for course_type in CourseType.objects.filter(
                    pk__in=course_types)
            ]
            writec(
                self,
                _("{}\n\n{}\n\n{}").format(export_name,
                                           ", ".join(degree_names),
                                           ", ".join(course_type_names)),
                "headline")

            for evaluation, results in evaluations_with_results:
                title = evaluation.full_name
                if len(semesters) > 1:
                    title += "\n{}".format(evaluation.course.semester.name)
                responsible_names = [
                    responsible.full_name
                    for responsible in evaluation.course.responsibles.all()
                ]
                title += "\n{}".format(", ".join(responsible_names))
                writec(self, title, "evaluation")

            writen(self, _("Degrees"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(
                    self, "\n".join(
                        [d.name for d in evaluation.course.degrees.all()]),
                    "degree")

            writen(self, _("Course Type"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(self, evaluation.course.type.name, "border_left_right")

            writen(self)
            for evaluation, results in evaluations_with_results:
                self.write_empty_cell_with_borders()

            for questionnaire in used_questionnaires:
                if contributor and questionnaire.type == Questionnaire.CONTRIBUTOR:
                    writen(
                        self, "{} ({})".format(questionnaire.name,
                                               contributor.full_name), "bold")
                else:
                    writen(self, questionnaire.name, "bold")
                for evaluation, results in evaluations_with_results:
                    self.write_empty_cell_with_borders()

                filtered_questions = self.filter_text_and_heading_questions(
                    questionnaire.questions.all())

                for question in filtered_questions:
                    if question.is_heading_question:
                        writen(self, question.text, "italic")
                    else:
                        writen(self, question.text)

                    for evaluation, results in evaluations_with_results:
                        if questionnaire.id not in results or question.is_heading_question:
                            self.write_empty_cell_with_borders()
                            continue
                        qn_results = results[questionnaire.id]
                        values = []
                        count_sum = 0
                        approval_count = 0

                        for grade_result in qn_results:
                            if grade_result.question.id == question.id:
                                if grade_result.has_answers:
                                    values.append(grade_result.average *
                                                  grade_result.count_sum)
                                    count_sum += grade_result.count_sum
                                    if grade_result.question.is_yes_no_question:
                                        approval_count += grade_result.approval_count
                        if values:
                            avg = sum(values) / count_sum

                            if question.is_yes_no_question:
                                percent_approval = approval_count / count_sum if count_sum > 0 else 0
                                writec(self, "{:.0%}".format(percent_approval),
                                       self.grade_to_style(avg))
                            else:
                                writec(self, avg, self.grade_to_style(avg))
                        else:
                            self.write_empty_cell_with_borders()
                writen(self)
                for evaluation, results in evaluations_with_results:
                    self.write_empty_cell_with_borders()

            writen(self, _("Overall Average Grade"), "bold")
            for evaluation, results in evaluations_with_results:
                avg = distribution_to_grade(
                    calculate_average_distribution(evaluation))
                if avg:
                    writec(self, avg, self.grade_to_style(avg))
                else:
                    self.write_empty_cell_with_borders()

            writen(self, _("Total voters/Total participants"), "bold")
            for evaluation, results in evaluations_with_results:
                writec(
                    self, "{}/{}".format(evaluation.num_voters,
                                         evaluation.num_participants),
                    "total_voters")

            writen(self, _("Evaluation rate"), "bold")
            for evaluation, results in evaluations_with_results:
                # round down like in progress bar
                percentage_participants = int(
                    (evaluation.num_voters / evaluation.num_participants) *
                    100) if evaluation.num_participants > 0 else 0
                writec(self, "{}%".format(percentage_participants),
                       "evaluation_rate")

            if course_results_exist:
                writen(self)
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        self.write_empty_cell_with_borders()
                    else:
                        self.write_empty_cell()

                writen(self, _("Evaluation weight"), "bold")
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        writec(self,
                               "{}%".format(evaluation.weight_percentage),
                               "evaluation_weight")
                    else:
                        self.write_empty_cell()

                writen(self, _("Course Grade"), "bold")
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        if evaluation.course.avg_grade:
                            writec(
                                self, evaluation.course.avg_grade,
                                self.grade_to_style(
                                    evaluation.course.avg_grade))
                        else:
                            self.write_empty_cell_with_borders()
                    else:
                        self.write_empty_cell()

                writen(self)
                for evaluation, results in evaluations_with_results:
                    if evaluation.course_evaluations_count > 1:
                        writec(self, None, "border_top")
                    else:
                        self.write_empty_cell()

        workbook.save(response)
예제 #31
0
def course_detail(request, semester_id, course_id):
    semester = get_object_or_404(Semester, id=semester_id)
    course = get_object_or_404(semester.course_set,
                               id=course_id,
                               semester=semester)

    if not course.can_user_see_results_page(request.user):
        raise PermissionDenied

    sections = calculate_results(course)

    if request.user.is_reviewer:
        public_view = request.GET.get(
            'public_view'
        ) != 'false'  # if parameter is not given, show public view.
    else:
        public_view = request.GET.get(
            'public_view'
        ) == 'true'  # if parameter is not given, show own view.

    # If grades are not published, there is no public view
    if not course.has_enough_voters_to_publish_grades:
        public_view = False

    represented_users = list(request.user.represented_users.all())
    represented_users.append(request.user)

    show_grades = course.can_user_see_grades(request.user)

    # remove text answers and grades if the user may not see them
    for section in sections:
        results = []
        for result in section.results:
            if isinstance(result, TextResult):
                answers = [
                    answer
                    for answer in result.answers if user_can_see_text_answer(
                        request.user, represented_users, answer, public_view)
                ]
                if answers:
                    results.append(
                        TextResult(question=result.question, answers=answers))
            elif isinstance(result, RatingResult) and not show_grades:
                results.append(
                    RatingResult(question=result.question,
                                 total_count=result.total_count,
                                 average=None,
                                 counts=None,
                                 warning=result.warning))
            elif isinstance(result, YesNoResult) and not show_grades:
                results.append(
                    YesNoResult(question=result.question,
                                total_count=result.total_count,
                                average=None,
                                counts=None,
                                warning=result.warning,
                                approval_count=None))
            else:
                results.append(result)

        section.results[:] = results

    # filter empty headings
    for section in sections:
        filtered_results = []
        for index in range(len(section.results)):
            result = section.results[index]
            # filter out if there are no more questions or the next question is also a heading question
            if isinstance(result, HeadingResult):
                if index == len(section.results) - 1 or isinstance(
                        section.results[index + 1], HeadingResult):
                    continue
            filtered_results.append(result)
        section.results[:] = filtered_results

    # remove empty sections
    sections = [section for section in sections if section.results]

    # group by contributor
    course_sections_top = []
    course_sections_bottom = []
    contributor_sections = OrderedDict()
    for section in sections:
        if section.contributor is None:
            if section.questionnaire.is_below_contributors:
                course_sections_bottom.append(section)
            else:
                course_sections_top.append(section)
        else:
            contributor_sections.setdefault(section.contributor, {
                'total_votes': 0,
                'sections': []
            })['sections'].append(section)

            for result in section.results:
                if isinstance(result, TextResult):
                    contributor_sections[
                        section.contributor]['total_votes'] += 1
                elif isinstance(result, RatingResult) or isinstance(
                        result, YesNoResult):
                    # Only count rating results if we show the grades.
                    if show_grades:
                        contributor_sections[section.contributor][
                            'total_votes'] += result.total_count

    course.distribution = calculate_average_distribution(
        course) if show_grades else None
    course.avg_grade = distribution_to_grade(course.distribution)

    template_data = dict(course=course,
                         course_sections_top=course_sections_top,
                         course_sections_bottom=course_sections_bottom,
                         contributor_sections=contributor_sections,
                         reviewer=request.user.is_reviewer,
                         contributor=course.is_user_contributor_or_delegate(
                             request.user),
                         can_download_grades=request.user.can_download_grades,
                         public_view=public_view)
    return render(request, "results_course_detail.html", template_data)
예제 #32
0
파일: views.py 프로젝트: fsr-itse/EvaP
def evaluation_detail(request, semester_id, evaluation_id):
    semester = get_object_or_404(Semester, id=semester_id)
    evaluation = get_object_or_404(semester.evaluations, id=evaluation_id, course__semester=semester)

    if not evaluation.can_results_page_be_seen_by(request.user):
        raise PermissionDenied

    evaluation_result = collect_results(evaluation)

    if request.user.is_reviewer:
        view = request.GET.get('view', 'public')  # if parameter is not given, show public view.
    else:
        view = request.GET.get('view', 'full')  # if parameter is not given, show own view.
    if view not in ['public', 'full', 'export']:
        view = 'public'

    view_as_user = request.user
    if view == 'export' and request.user.is_staff:
        view_as_user = UserProfile.objects.get(id=int(request.GET.get('contributor_id', request.user.id)))

    represented_users = [view_as_user]
    if view != 'export':
        represented_users += list(view_as_user.represented_users.all())
    # redirect to non-public view if there is none because the results have not been published
    if not evaluation.can_publish_rating_results and view == 'public':
        view = 'full'

    # remove text answers if the user may not see them
    for questionnaire_result in evaluation_result.questionnaire_results:
        for question_result in questionnaire_result.question_results:
            if isinstance(question_result, TextResult):
                question_result.answers = [answer for answer in question_result.answers if can_textanswer_be_seen_by(view_as_user, represented_users, answer, view)]
        # remove empty TextResults
        questionnaire_result.question_results = [result for result in questionnaire_result.question_results if not isinstance(result, TextResult) or len(result.answers) > 0]

    # filter empty headings
    for questionnaire_result in evaluation_result.questionnaire_results:
        filtered_question_results = []
        for index, question_result in enumerate(questionnaire_result.question_results):
            # filter out if there are no more questions or the next question is also a heading question
            if isinstance(question_result, HeadingResult):
                if index == len(questionnaire_result.question_results) - 1 or isinstance(questionnaire_result.question_results[index + 1], HeadingResult):
                    continue
            filtered_question_results.append(question_result)
        questionnaire_result.question_results = filtered_question_results

    # remove empty questionnaire_results and contribution_results
    for contribution_result in evaluation_result.contribution_results:
        contribution_result.questionnaire_results = [questionnaire_result for questionnaire_result in contribution_result.questionnaire_results if questionnaire_result.question_results]
    evaluation_result.contribution_results = [contribution_result for contribution_result in evaluation_result.contribution_results if contribution_result.questionnaire_results]

    add_warnings(evaluation, evaluation_result)

    # split evaluation_result into different lists
    general_questionnaire_results_top = []
    general_questionnaire_results_bottom = []
    contributor_contribution_results = []
    for contribution_result in evaluation_result.contribution_results:
        if contribution_result.contributor is None:
            for questionnaire_result in contribution_result.questionnaire_results:
                if questionnaire_result.questionnaire.is_below_contributors:
                    general_questionnaire_results_bottom.append(questionnaire_result)
                else:
                    general_questionnaire_results_top.append(questionnaire_result)
        elif view != 'export' or view_as_user.id == contribution_result.contributor.id:
            contributor_contribution_results.append(contribution_result)

    if not contributor_contribution_results:
        general_questionnaire_results_top += general_questionnaire_results_bottom
        general_questionnaire_results_bottom = []

    course_evaluations = []
    if evaluation.course.evaluations.count() > 1:
        course_evaluations = [evaluation for evaluation in evaluation.course.evaluations.filter(state="published") if evaluation.can_be_seen_by(request.user)]
        if request.user.is_reviewer:
            course_evaluations += evaluation.course.evaluations.filter(state__in=['in_evaluation', 'evaluated', 'reviewed'])
        course_evaluations = get_evaluations_with_course_result_attributes(course_evaluations)
        for course_evaluation in course_evaluations:
            if course_evaluation.is_single_result:
                course_evaluation.single_result_rating_result = get_single_result_rating_result(course_evaluation)
            else:
                course_evaluation.distribution = calculate_average_distribution(course_evaluation)
                course_evaluation.avg_grade = distribution_to_grade(course_evaluation.distribution)

    other_contributors = []
    if view == 'export':
        other_contributors = [contribution_result.contributor for contribution_result in evaluation_result.contribution_results if contribution_result.contributor not in [None, view_as_user]]

    # if the evaluation is not published, the rendered results are not cached, so we need to attach distribution
    # information for rendering the distribution bar
    if evaluation.state != 'published':
        evaluation = get_evaluations_with_prefetched_data([evaluation])[0]

    template_data = dict(
        evaluation=evaluation,
        course=evaluation.course,
        course_evaluations=course_evaluations,
        general_questionnaire_results_top=general_questionnaire_results_top,
        general_questionnaire_results_bottom=general_questionnaire_results_bottom,
        contributor_contribution_results=contributor_contribution_results,
        is_reviewer=view_as_user.is_reviewer,
        is_contributor=evaluation.is_user_contributor(view_as_user),
        is_responsible_or_contributor_or_delegate=evaluation.is_user_responsible_or_contributor_or_delegate(view_as_user),
        can_download_grades=view_as_user.can_download_grades,
        view=view,
        view_as_user=view_as_user,
        other_contributors=other_contributors,
    )
    return render(request, "results_evaluation_detail.html", template_data)
예제 #33
0
def course_detail(request, semester_id, course_id):
    semester = get_object_or_404(Semester, id=semester_id)
    course = get_object_or_404(semester.course_set,
                               id=course_id,
                               semester=semester)

    if not course.can_user_see_results_page(request.user):
        raise PermissionDenied

    course_result = collect_results(course)

    if request.user.is_reviewer:
        public_view = request.GET.get(
            'public_view'
        ) != 'false'  # if parameter is not given, show public view.
    else:
        public_view = request.GET.get(
            'public_view'
        ) == 'true'  # if parameter is not given, show own view.

    # redirect to non-public view if there is none because the results have not been published
    if not course.can_publish_rating_results:
        public_view = False

    represented_users = list(
        request.user.represented_users.all()) + [request.user]

    # remove text answers if the user may not see them
    for questionnaire_result in course_result.questionnaire_results:
        for question_result in questionnaire_result.question_results:
            if isinstance(question_result, TextResult):
                question_result.answers = [
                    answer for answer in question_result.answers
                    if user_can_see_text_answer(
                        request.user, represented_users, answer, public_view)
                ]
        # remove empty TextResults
        questionnaire_result.question_results = [
            result for result in questionnaire_result.question_results
            if not isinstance(result, TextResult) or len(result.answers) > 0
        ]

    # filter empty headings
    for questionnaire_result in course_result.questionnaire_results:
        filtered_question_results = []
        for index, question_result in enumerate(
                questionnaire_result.question_results):
            # filter out if there are no more questions or the next question is also a heading question
            if isinstance(question_result, HeadingResult):
                if index == len(questionnaire_result.question_results
                                ) - 1 or isinstance(
                                    questionnaire_result.question_results[index
                                                                          + 1],
                                    HeadingResult):
                    continue
            filtered_question_results.append(question_result)
        questionnaire_result.question_results = filtered_question_results

    # remove empty questionnaire_results and contribution_results
    for contribution_result in course_result.contribution_results:
        contribution_result.questionnaire_results = [
            questionnaire_result for questionnaire_result in
            contribution_result.questionnaire_results
            if questionnaire_result.question_results
        ]
    course_result.contribution_results = [
        contribution_result
        for contribution_result in course_result.contribution_results
        if contribution_result.questionnaire_results
    ]

    add_warnings(course, course_result)

    # split course_result into different lists
    course_questionnaire_results_top = []
    course_questionnaire_results_bottom = []
    contributor_contribution_results = []
    for contribution_result in course_result.contribution_results:
        if contribution_result.contributor is None:
            for questionnaire_result in contribution_result.questionnaire_results:
                if questionnaire_result.questionnaire.is_below_contributors:
                    course_questionnaire_results_bottom.append(
                        questionnaire_result)
                else:
                    course_questionnaire_results_top.append(
                        questionnaire_result)
        else:
            contributor_contribution_results.append(contribution_result)

    if not contributor_contribution_results:
        course_questionnaire_results_top += course_questionnaire_results_bottom
        course_questionnaire_results_bottom = []

    course.distribution = calculate_average_distribution(course)
    course.avg_grade = distribution_to_grade(course.distribution)

    template_data = dict(
        course=course,
        course_questionnaire_results_top=course_questionnaire_results_top,
        course_questionnaire_results_bottom=course_questionnaire_results_bottom,
        contributor_contribution_results=contributor_contribution_results,
        reviewer=request.user.is_reviewer,
        contributor=course.is_user_contributor_or_delegate(request.user),
        can_download_grades=request.user.can_download_grades,
        public_view=public_view)
    return render(request, "results_course_detail.html", template_data)
예제 #34
0
def course_detail(request, semester_id, course_id):
    semester = get_object_or_404(Semester, id=semester_id)
    course = get_object_or_404(semester.courses, id=course_id, semester=semester)

    if not course.can_user_see_results_page(request.user):
        raise PermissionDenied

    course_result = collect_results(course)

    if request.user.is_reviewer:
        view = request.GET.get('view', 'public')  # if parameter is not given, show public view.
    else:
        view = request.GET.get('view', 'full')  # if parameter is not given, show own view.

    view_as_user = request.user
    if view == 'export' and request.user.is_staff:
        view_as_user = UserProfile.objects.get(id=int(request.GET.get('contributor_id', request.user.id)))

    represented_users = [view_as_user]
    if view != 'export':
        represented_users += list(view_as_user.represented_users.all())
    # redirect to non-public view if there is none because the results have not been published
    if not course.can_publish_rating_results and view == 'public':
        view = 'full'

    # remove text answers if the user may not see them
    for questionnaire_result in course_result.questionnaire_results:
        for question_result in questionnaire_result.question_results:
            if isinstance(question_result, TextResult):
                question_result.answers = [answer for answer in question_result.answers if user_can_see_text_answer(view_as_user, represented_users, answer, view)]
        # remove empty TextResults
        questionnaire_result.question_results = [result for result in questionnaire_result.question_results if not isinstance(result, TextResult) or len(result.answers) > 0]

    # filter empty headings
    for questionnaire_result in course_result.questionnaire_results:
        filtered_question_results = []
        for index, question_result in enumerate(questionnaire_result.question_results):
            # filter out if there are no more questions or the next question is also a heading question
            if isinstance(question_result, HeadingResult):
                if index == len(questionnaire_result.question_results) - 1 or isinstance(questionnaire_result.question_results[index + 1], HeadingResult):
                    continue
            filtered_question_results.append(question_result)
        questionnaire_result.question_results = filtered_question_results

    # remove empty questionnaire_results and contribution_results
    for contribution_result in course_result.contribution_results:
        contribution_result.questionnaire_results = [questionnaire_result for questionnaire_result in contribution_result.questionnaire_results if questionnaire_result.question_results]
    course_result.contribution_results = [contribution_result for contribution_result in course_result.contribution_results if contribution_result.questionnaire_results]

    add_warnings(course, course_result)

    # split course_result into different lists
    general_questionnaire_results_top = []
    general_questionnaire_results_bottom = []
    contributor_contribution_results = []
    for contribution_result in course_result.contribution_results:
        if contribution_result.contributor is None:
            for questionnaire_result in contribution_result.questionnaire_results:
                if questionnaire_result.questionnaire.is_below_contributors:
                    general_questionnaire_results_bottom.append(questionnaire_result)
                else:
                    general_questionnaire_results_top.append(questionnaire_result)
        elif view != 'export' or view_as_user.id == contribution_result.contributor.id:
            contributor_contribution_results.append(contribution_result)

    if not contributor_contribution_results:
        general_questionnaire_results_top += general_questionnaire_results_bottom
        general_questionnaire_results_bottom = []

    course.distribution = calculate_average_distribution(course)
    course.avg_grade = distribution_to_grade(course.distribution)

    other_contributors = []
    if view == 'export':
        other_contributors = [contribution_result.contributor for contribution_result in course_result.contribution_results if contribution_result.contributor not in [None, view_as_user]]

    template_data = dict(
        course=course,
        general_questionnaire_results_top=general_questionnaire_results_top,
        general_questionnaire_results_bottom=general_questionnaire_results_bottom,
        contributor_contribution_results=contributor_contribution_results,
        is_reviewer=view_as_user.is_reviewer,
        is_contributor=course.is_user_contributor(view_as_user),
        is_contributor_or_delegate=course.is_user_contributor_or_delegate(view_as_user),
        can_download_grades=view_as_user.can_download_grades,
        view=view,
        view_as_user=view_as_user,
        other_contributors=other_contributors,
    )
    return render(request, "results_course_detail.html", template_data)
예제 #35
0
    def export(self,
               response,
               course_types_list,
               include_not_enough_voters=False,
               include_unpublished=False):
        self.workbook = xlwt.Workbook()
        self.init_styles(self.workbook)
        counter = 1

        for course_types in course_types_list:
            self.sheet = self.workbook.add_sheet("Sheet " + str(counter))
            counter += 1
            self.row = 0
            self.col = 0

            courses_with_results = list()
            course_states = ['published']
            if include_unpublished:
                course_states.extend(['evaluated', 'reviewed'])

            used_questionnaires = set()
            for course in self.semester.course_set.filter(
                    state__in=course_states, type__in=course_types).all():
                if course.is_single_result:
                    continue
                if not course.has_enough_voters_to_publish_grades and not include_not_enough_voters:
                    continue
                results = OrderedDict()
                for questionnaire, contributor, __, data, __ in calculate_results(
                        course):
                    if has_no_rating_answers(course, contributor,
                                             questionnaire):
                        continue
                    results.setdefault(questionnaire.id, []).extend(data)
                    used_questionnaires.add(questionnaire)
                courses_with_results.append((course, results))

            courses_with_results.sort(key=lambda cr: (cr[0].type, cr[0].name))
            used_questionnaires = sorted(used_questionnaires)

            course_type_names = [
                ct.name
                for ct in CourseType.objects.filter(pk__in=course_types)
            ]
            writec(
                self,
                _("Evaluation {0}\n\n{1}").format(
                    self.semester.name, ", ".join(course_type_names)),
                "headline")

            for course, results in courses_with_results:
                writec(self, course.name, "course")

            writen(self)
            for course, results in courses_with_results:
                self.write_empty_cell_with_borders()

            for questionnaire in used_questionnaires:
                writen(self, questionnaire.name, "bold")
                for course, results in courses_with_results:
                    self.write_empty_cell_with_borders()

                filtered_questions = self.filter_text_and_heading_questions(
                    questionnaire.question_set.all())

                for question in filtered_questions:
                    if question.is_heading_question:
                        writen(self, question.text, "italic")
                    else:
                        writen(self, question.text)

                    for course, results in courses_with_results:
                        if questionnaire.id not in results or question.is_heading_question:
                            self.write_empty_cell_with_borders()
                            continue
                        qn_results = results[questionnaire.id]
                        values = []
                        total_count = 0
                        approval_count = 0

                        for grade_result in qn_results:
                            if grade_result.question.id == question.id:
                                if grade_result.average is not None:
                                    values.append(grade_result.average *
                                                  grade_result.total_count)
                                    total_count += grade_result.total_count
                                    if grade_result.question.is_yes_no_question:
                                        approval_count += grade_result.approval_count
                        if values and course.has_enough_voters_to_publish_grades:
                            avg = sum(values) / total_count

                            if question.is_yes_no_question:
                                percent_approval = float(
                                    approval_count) / float(
                                        total_count) if total_count > 0 else 0
                                writec(self, "{:.0%}".format(percent_approval),
                                       self.grade_to_style(avg))
                            else:
                                writec(self, avg, self.grade_to_style(avg))
                        else:
                            self.write_empty_cell_with_borders()
                writen(self)
                for course, results in courses_with_results:
                    self.write_empty_cell_with_borders()

            writen(self, _("Overall Average Grade"), "bold")
            for course, results in courses_with_results:
                avg = distribution_to_grade(
                    calculate_average_distribution(course))
                if avg:
                    writec(self, avg, self.grade_to_style(avg))
                else:
                    self.write_empty_cell_with_borders()

            writen(self, _("Total voters/Total participants"), "bold")
            for course, results in courses_with_results:
                writec(
                    self, "{}/{}".format(course.num_voters,
                                         course.num_participants),
                    "total_voters")

            writen(self, _("Evaluation rate"), "bold")
            for course, results in courses_with_results:
                percent_participants = float(course.num_voters) / float(
                    course.num_participants
                ) if course.num_participants > 0 else 0
                writec(self, "{:.0%}".format(percent_participants),
                       "evaluation_rate")

        self.workbook.save(response)
예제 #36
0
def evaluation_detail(request, semester_id, evaluation_id):
    semester = get_object_or_404(Semester, id=semester_id)
    evaluation = get_object_or_404(semester.evaluations,
                                   id=evaluation_id,
                                   course__semester=semester)

    if not evaluation.can_user_see_results_page(request.user):
        raise PermissionDenied

    evaluation_result = collect_results(evaluation)

    if request.user.is_reviewer:
        view = request.GET.get(
            'view', 'public')  # if parameter is not given, show public view.
    else:
        view = request.GET.get(
            'view', 'full')  # if parameter is not given, show own view.
    if view not in ['public', 'full', 'export']:
        view = 'public'

    view_as_user = request.user
    if view == 'export' and request.user.is_staff:
        view_as_user = UserProfile.objects.get(
            id=int(request.GET.get('contributor_id', request.user.id)))

    represented_users = [view_as_user]
    if view != 'export':
        represented_users += list(view_as_user.represented_users.all())
    # redirect to non-public view if there is none because the results have not been published
    if not evaluation.can_publish_rating_results and view == 'public':
        view = 'full'

    # remove text answers if the user may not see them
    for questionnaire_result in evaluation_result.questionnaire_results:
        for question_result in questionnaire_result.question_results:
            if isinstance(question_result, TextResult):
                question_result.answers = [
                    answer for answer in question_result.answers
                    if user_can_see_textanswer(view_as_user, represented_users,
                                               answer, view)
                ]
        # remove empty TextResults
        questionnaire_result.question_results = [
            result for result in questionnaire_result.question_results
            if not isinstance(result, TextResult) or len(result.answers) > 0
        ]

    # filter empty headings
    for questionnaire_result in evaluation_result.questionnaire_results:
        filtered_question_results = []
        for index, question_result in enumerate(
                questionnaire_result.question_results):
            # filter out if there are no more questions or the next question is also a heading question
            if isinstance(question_result, HeadingResult):
                if index == len(questionnaire_result.question_results
                                ) - 1 or isinstance(
                                    questionnaire_result.question_results[index
                                                                          + 1],
                                    HeadingResult):
                    continue
            filtered_question_results.append(question_result)
        questionnaire_result.question_results = filtered_question_results

    # remove empty questionnaire_results and contribution_results
    for contribution_result in evaluation_result.contribution_results:
        contribution_result.questionnaire_results = [
            questionnaire_result for questionnaire_result in
            contribution_result.questionnaire_results
            if questionnaire_result.question_results
        ]
    evaluation_result.contribution_results = [
        contribution_result
        for contribution_result in evaluation_result.contribution_results
        if contribution_result.questionnaire_results
    ]

    add_warnings(evaluation, evaluation_result)

    # split evaluation_result into different lists
    general_questionnaire_results_top = []
    general_questionnaire_results_bottom = []
    contributor_contribution_results = []
    for contribution_result in evaluation_result.contribution_results:
        if contribution_result.contributor is None:
            for questionnaire_result in contribution_result.questionnaire_results:
                if questionnaire_result.questionnaire.is_below_contributors:
                    general_questionnaire_results_bottom.append(
                        questionnaire_result)
                else:
                    general_questionnaire_results_top.append(
                        questionnaire_result)
        elif view != 'export' or view_as_user.id == contribution_result.contributor.id:
            contributor_contribution_results.append(contribution_result)

    if not contributor_contribution_results:
        general_questionnaire_results_top += general_questionnaire_results_bottom
        general_questionnaire_results_bottom = []

    course_evaluations = []
    if evaluation.course.evaluations.count() > 1:
        course_evaluations = [
            evaluation for evaluation in evaluation.course.evaluations.filter(
                state="published")
            if evaluation.can_user_see_evaluation(request.user)
        ]
        if request.user.is_reviewer:
            course_evaluations += evaluation.course.evaluations.filter(
                state__in=['in_evaluation', 'evaluated', 'reviewed'])
        course_evaluations = get_evaluations_with_course_result_attributes(
            course_evaluations)
        for course_evaluation in course_evaluations:
            if course_evaluation.is_single_result:
                course_evaluation.single_result_rating_result = get_single_result_rating_result(
                    course_evaluation)
            else:
                course_evaluation.distribution = calculate_average_distribution(
                    course_evaluation)
                course_evaluation.avg_grade = distribution_to_grade(
                    course_evaluation.distribution)

    other_contributors = []
    if view == 'export':
        other_contributors = [
            contribution_result.contributor
            for contribution_result in evaluation_result.contribution_results
            if contribution_result.contributor not in [None, view_as_user]
        ]

    # if the evaluation is not published, the rendered results are not cached, so we need to attach distribution
    # information for rendering the distribution bar
    if evaluation.state != 'published':
        evaluation = get_evaluations_with_prefetched_data([evaluation])[0]

    template_data = dict(
        evaluation=evaluation,
        course=evaluation.course,
        course_evaluations=course_evaluations,
        general_questionnaire_results_top=general_questionnaire_results_top,
        general_questionnaire_results_bottom=
        general_questionnaire_results_bottom,
        contributor_contribution_results=contributor_contribution_results,
        is_reviewer=view_as_user.is_reviewer,
        is_contributor=evaluation.is_user_contributor(view_as_user),
        is_responsible_or_contributor_or_delegate=evaluation.
        is_user_responsible_or_contributor_or_delegate(view_as_user),
        can_download_grades=view_as_user.can_download_grades,
        view=view,
        view_as_user=view_as_user,
        other_contributors=other_contributors,
    )
    return render(request, "results_evaluation_detail.html", template_data)
예제 #37
0
    def test_average_grade(self):
        contributor1 = mommy.make(UserProfile)
        contributor2 = mommy.make(UserProfile)

        course = mommy.make(Course)
        questionnaire = mommy.make(Questionnaire)
        question_grade = mommy.make(Question,
                                    questionnaire=questionnaire,
                                    type="G")
        question_likert = mommy.make(Question,
                                     questionnaire=questionnaire,
                                     type="L")
        general_contribution = mommy.make(Contribution,
                                          contributor=None,
                                          course=course,
                                          questionnaires=[questionnaire])
        contribution1 = mommy.make(Contribution,
                                   contributor=contributor1,
                                   course=course,
                                   questionnaires=[questionnaire])
        contribution2 = mommy.make(Contribution,
                                   contributor=contributor2,
                                   course=course,
                                   questionnaires=[questionnaire])

        mommy.make(RatingAnswerCounter,
                   question=question_grade,
                   contribution=contribution1,
                   answer=1,
                   count=1)
        mommy.make(RatingAnswerCounter,
                   question=question_grade,
                   contribution=contribution2,
                   answer=4,
                   count=2)
        mommy.make(RatingAnswerCounter,
                   question=question_likert,
                   contribution=contribution1,
                   answer=3,
                   count=4)
        mommy.make(RatingAnswerCounter,
                   question=question_likert,
                   contribution=general_contribution,
                   answer=5,
                   count=3)

        contributor_weights_sum = settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT + settings.CONTRIBUTOR_NON_GRADE_QUESTIONS_WEIGHT
        contributor1_average = (
            settings.CONTRIBUTOR_GRADE_QUESTIONS_WEIGHT * 1 +
            (settings.CONTRIBUTOR_NON_GRADE_QUESTIONS_WEIGHT) *
            3) / contributor_weights_sum  # 2.2
        contributor2_average = 4
        contributors_average = (contributor1_average +
                                contributor2_average) / 2  # 3.1

        course_non_grade_average = 5

        contributors_percentage = settings.CONTRIBUTIONS_WEIGHT / (
            settings.CONTRIBUTIONS_WEIGHT +
            settings.COURSE_NON_GRADE_QUESTIONS_WEIGHT)  # 0.375
        course_non_grade_percentage = settings.COURSE_NON_GRADE_QUESTIONS_WEIGHT / (
            settings.CONTRIBUTIONS_WEIGHT +
            settings.COURSE_NON_GRADE_QUESTIONS_WEIGHT)  # 0.625

        total_grade = contributors_percentage * contributors_average + course_non_grade_percentage * course_non_grade_average  # 1.1625 + 3.125 = 4.2875

        average_grade = distribution_to_grade(
            calculate_average_distribution(course))
        self.assertAlmostEqual(average_grade, total_grade)
        self.assertAlmostEqual(average_grade, 4.2875)