-
Notifications
You must be signed in to change notification settings - Fork 1
/
test_support.py
133 lines (107 loc) · 5.79 KB
/
test_support.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""
Copyright (C) 2021 Borgo Daniele
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from math import ceil
from pylatex import LongTable, NoEscape
import generator.sentences as sentences
class PointsData:
"""
This class handle the data relative to points assignment, so the evaluation table
and the total amount of the test points.
This class creates a table useful to write earned points by a student
in function of the exercise number. It can contains also some additional field,
like an extra point for the order and others field defined in the apposite
parameter in the JSON file.
After having create the table, it can be injected several times in the document,
using the apposite public method.
"""
def __init__(self, total_points, number_of_questions, is_extra_enabled, additional_params):
self.__total_points = total_points
# Create the first row of the table
questions_numbers = [sentences.OTHERS.EXTRA] if is_extra_enabled else []
questions_numbers += additional_params + list(range(1, number_of_questions + 1))
# Create the table string
table_string = ('|c|' if is_extra_enabled else '|') + 'c|' * (len(additional_params) + number_of_questions)
self.__create_table(table_string, questions_numbers)
def __create_table(self, table_string, questions_numbers):
self.__eval_table = LongTable(table_string, row_height=2.0, col_space='0.5cm')
self.__eval_table.add_hline()
self.__eval_table.add_row(questions_numbers)
self.__eval_table.add_hline()
self.__eval_table.add_empty_row()
self.__eval_table.add_hline()
def insert_eval_table(self, doc):
doc.append(self.__eval_table)
@property
def total_points(self):
return self.__total_points
class VotesData:
"""
This class generates and handles the vote table, the one used to compute
the vote, given the total earned points. It gets data from the apposite
section in the JSON.
It generates actually two tables:
- The standard one, as specified in the JSON file;
- The one for the students who have optional questions.
With the apposite public method, it injects this table in the document,
since it is able to insert it several times.
"""
def __init__(self, votes_json, optional_count):
min_vote = votes_json['min']['vote']
min_required_points = votes_json['min']['up_to']
max_vote = votes_json['max']['vote']
max_required_points = votes_json['max']['from']
# The first is the table string, the second the row containing earned points and the third the grades
string_st, points_st, votes_st = self.__create_earned_votes_array(max_vote, max_required_points,
min_vote, min_required_points)
string_wo, points_wo, votes_wo = self.__create_earned_votes_array(max_vote,
max_required_points - optional_count,
min_vote, min_required_points)
self.__standard_votes_table = self.__create_table(string_st, points_st, votes_st)
self.__votes_with_opt_table = self.__create_table(string_wo, points_wo, votes_wo)
def __create_earned_votes_array(self, max_vote, max_required_points, min_vote, min_required_points):
table_string = '|c|c|c|' + 'c|' * (max_required_points - min_required_points - 1)
points_row = [sentences.OTHERS.POINTS, NoEscape('$ \\leq ' + str(min_required_points) + ' $')]
points_row += list(range(min_required_points + 1, max_required_points))
points_row.append(NoEscape('$ ' + '\\geq ' + str(max_required_points) + ' $'))
vote_step = (max_vote - min_vote) / (max_required_points - min_required_points)
vote_acc = float(min_vote)
votes_row = [sentences.EVALUATION.GRADE, min_vote]
for i in range(min_required_points + 1, max_required_points):
vote_acc += vote_step
votes_row.append(self.VoteConverter.to_vote(vote_acc))
votes_row.append(max_vote)
return [table_string, points_row, votes_row]
@staticmethod
def __create_table(table_string, points, standard_votes):
table = LongTable(table_string, row_height=1.5, col_space='0.5cm')
table.add_hline()
table.add_row(points)
table.add_hline()
table.add_row(standard_votes)
table.add_hline()
return table
def insert_table(self, doc, has_optional_questions):
if has_optional_questions:
doc.append(self.__votes_with_opt_table)
else:
doc.append(self.__standard_votes_table)
class VoteConverter:
"""
This class is used to convert a float value in the closest upper grade.
"""
__vote_table = ('0', '0.5', '1', '1.5', '2', '2.5', '3', '3.5', '4', '4.5',
'5', '5.5', '6', '6.5', '7', '7.5', '8', '8.5', '9', '9.5', '10')
@staticmethod
def to_vote(n):
return VotesData.VoteConverter.__vote_table[ceil(n * 2)]