Skip to content

Commit d696932

Browse files
authored
Merge branch 'master' into 555_check_abbreviations
2 parents edd07ce + c402416 commit d696932

39 files changed

+490
-238
lines changed

Dockerfile_selenium

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ COPY tests/requirements.txt tests/requirements.txt
1414
RUN pip install -r tests/requirements.txt
1515
COPY tests ./tests
1616

17-
ENTRYPOINT python3 tests/main.py --login ${LOGIN} --password ${PASSWORD}
17+
ENTRYPOINT sleep 30 && python3 tests/main.py --login ${LOGIN} --password ${PASSWORD}

app/main/checks/presentation_checks/name_of_image_check.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ def __init__(self, file_info):
1212
def check(self):
1313
slides_without_capture = set()
1414
slide_with_image_only = set()
15-
result_str = 'Не пройдена! '
15+
result_str = ''
16+
result = True
1617
all_captions = []
1718
for num, slide in enumerate(self.file.slides, 1):
1819
captions = slide.get_captions()
@@ -27,14 +28,15 @@ def check(self):
2728
if caption[0] != slide.get_title():
2829
slide_with_image_only.add(num)
2930
if slides_without_capture:
31+
result = False
3032
result_str += (
3133
'Подписи к рисункам на следующих слайдах отсутствуют или не содержат слова "Рисунок": {}'.format(
3234
', '.join(self.format_page_link(sorted(slides_without_capture)))) + '<br>')
3335
if slide_with_image_only:
3436
result_str += (
3537
'Подписи к рисункам на следующих слайдах без текста необязательны: {}'.format(
3638
', '.join(self.format_page_link(sorted(slide_with_image_only)))) + '<br>')
37-
if result_str:
38-
return answer(False, name_of_image_check_results(result_str, all_captions))
39+
if result:
40+
return answer(True, f'Пройдена! {result_str}')
3941
else:
40-
return answer(True, 'Пройдена!')
42+
return answer(False, name_of_image_check_results(f"Не пройдена! {result_str}", all_captions))

app/main/checks/report_checks/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@
3333
from .sw_keywords_check import SWKeywordsCheck
3434
from .task_tracker import ReportTaskTracker
3535
from .abbreviations_check import AbbreviationsCheckPres
36+
from .paragraphs_count_check import ReportParagraphsCountCheck
37+
from .template_name import ReportTemplateNameCheck

app/main/checks/report_checks/literature_references.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ def check(self):
5656
return answer(False,
5757
f'В Списке использованных источников не найдено ни одного источника.<br><br>Проверьте корректность использования нумированного списка.')
5858
references, ref_sequence = self.search_references(start_literature_par)
59-
all_numbers = set()
60-
for i in range(1, number_of_sources + 1):
61-
all_numbers.add(i)
59+
all_numbers = set(range(1, number_of_sources + 1))
6260
if len(references.symmetric_difference(all_numbers)) == 0:
6361
if not self.min_ref <= number_of_sources <= self.max_ref:
6462
return answer(False, f'Список источников оформлен верно, однако их количество ({number_of_sources}) не удовлетворяет необходимому критерию. <br> Количество источников должно быть не менее {self.min_ref}.')
@@ -81,7 +79,7 @@ def check(self):
8179
result_str += '''
8280
Если возникли проблемы, попробуйте сделать следующее:
8381
<ul>
84-
<li>Убедитесь, что для ссылки на источник используются квадратные скобки;</li>
82+
<li>Убедитесь, что для ссылки на источник используются квадратные скобки (т.е. [1], [2-4]);</li>
8583
<li>Убедитесь, что для оформления списка литературы был использован нумированный список;</li>
8684
<li>Убедитесь, что после и перед нумированным списком отсутствуют непустые абзацы.</li>
8785
<li>Убедитесь, что один источник не разбит на две строки клавишей "Enter".</li>
@@ -93,13 +91,16 @@ def search_references(self, start_par):
9391
prev_ref = 0
9492
ref_sequence = []
9593
array_of_references = set()
94+
reg_exp = r'\[[\^]{0,1}[\d \-,]+\]' # md can use [^5] format for hyperlink
9695
for i in range(0, start_par):
9796
if isinstance(self.file.paragraphs[i], str):
98-
detected_references = re.findall(r'\[[\d \-,]+\]', self.file.paragraphs[i])
97+
detected_references = re.findall(reg_exp, self.file.paragraphs[i])
9998
else:
100-
detected_references = re.findall(r'\[[\d \-,]+\]', self.file.paragraphs[i].paragraph_text)
99+
detected_references = re.findall(reg_exp, self.file.paragraphs[i].paragraph_text)
100+
101101
if detected_references:
102-
for reference in detected_references:
102+
for reference_raw in detected_references:
103+
reference = reference_raw.replace('^', '') # TODO: kostyl'...
103104
for one_part in re.split(r'[\[\],]', reference):
104105
if re.match(r'\d+[ \-]+\d+', one_part):
105106
start, end = re.split(r'[ -]+', one_part)
Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,114 @@
11
from ..base_check import BaseReportCriterion, answer
2+
from .main_page_settings import ReportMainPageSetting
3+
import re
4+
import copy
25

36

47
class ReportMainCharacterCheck(BaseReportCriterion):
5-
label = "Проверка фамилии и должности заведующего кафедрой"
6-
description = 'Зав. кафедрой: А.А. Лисс'
7-
id = 'main_character_check'
8+
label = "Проверка составляющих титульного листа, задания и календарного плана"
9+
description = ""
10+
id = "main_character_check"
811
priority = True
912

10-
def __init__(self, file_info, main_character_name_right="А.А. Лисс", main_character_name_wrong="К.В. Кринкин",
11-
main_character_job_right="Зав. кафедрой", main_character_job_wrong="И.о. зав. кафедрой"):
13+
def __init__(self, file_info, tables_count_to_verify=8):
1214
super().__init__(file_info)
1315
self.headers = []
14-
self.main_character_name_right = main_character_name_right
15-
self.main_character_name_wrong = main_character_name_wrong
16-
self.main_character_job_right = main_character_job_right
17-
self.main_character_job_wrong = main_character_job_wrong
16+
self.first_check_list = None
17+
self.second_check_list = None
18+
self.tables_count_to_verify = tables_count_to_verify
1819

1920
def late_init(self):
20-
self.headers = self.file.make_headers(self.file_type['report_type'])
21+
self.headers = self.file.make_headers(self.file_type["report_type"])
2122

2223
def check(self):
24+
self.first_check_list = copy.deepcopy(ReportMainPageSetting.FIRST_TABLE)
25+
self.second_check_list = copy.deepcopy(ReportMainPageSetting.SECOND_TABLE)
2326
if self.file.page_counter() < 4:
2427
return answer(False, "В отчете недостаточно страниц. Нечего проверять.")
28+
if self.tables_count_to_verify > len(self.file.tables):
29+
return answer(
30+
False,
31+
f"Количество таблиц на страницах титульного листа, задания и календарного плана должно быть не меньше {self.tables_count_to_verify}",
32+
)
2533
self.late_init()
26-
result_str = ''
34+
result_str = ""
35+
pages = []
2736
for header in self.headers:
2837
if header["marker"] and header["main_character"]:
29-
page = header["page"]
30-
text_on_page = self.file.pdf_file.text_on_page[page]
31-
if text_on_page.find(self.main_character_name_wrong) >= 0 and not text_on_page.find(
32-
self.main_character_name_right) >= 0:
33-
result_str += f"На странице {self.format_page_link([page])} указана неверная фамилия заведующего " \
34-
f"кафедрой. Убедитесь, что {self.main_character_job_right} {self.main_character_name_right}.<br>"
35-
elif not text_on_page.find(self.main_character_name_right) >= 0:
36-
result_str += f"На странице {self.format_page_link([page])} не указано ФИО заведующего кафедрой, в " \
37-
f"графе {self.main_character_job_right} должно быть указано {self.main_character_name_right}.<br>"
38-
if text_on_page.find(self.main_character_job_wrong) >= 0 and not text_on_page.find(
39-
self.main_character_job_right) >= 0:
40-
result_str += f'На странице {self.format_page_link([page])} указана неверная должность ' \
41-
f'заведующего кафедрой, должно быть "{self.main_character_job_right}".<br>'
42-
if not result_str:
43-
return answer(True, 'ФИО и должность исполняющего обязанности зав. кафедрой указаны верно на всех листах.')
38+
pages.append(header["page"])
39+
for i in range(self.tables_count_to_verify):
40+
table = self.file.tables[i]
41+
extract_table = self.extract_table_contents(table)
42+
self.check_table(self.first_check_list, extract_table, i+1)
43+
self.check_table(self.second_check_list, extract_table, i+1)
44+
links = self.format_page_link(pages)
45+
result_score = 1.0
46+
check_result = self.first_check_list + self.second_check_list
47+
penalty_score = 1 / len(check_result)
48+
for res in check_result:
49+
if res["found_key"] > 1 and res["key"] == "Консультант":
50+
links = self.format_page_link(pages[1:])
51+
result_str += f"Предупреждение: помните, что на страницах {links} указывается только консультант, являющийся фактическим руководителем (консультант от кафедры / по допразделу не указываются).<br>"
52+
elif res["found_key"] < res["find"] and res["key"] != "Консультант":
53+
result_score -= penalty_score * (res["find"] - res['found_value'])
54+
result_str += f"Поле '{res['key']}' не найдено на страницах {links}. Его удалось обнаружить {res['found_key']} из {res['find']} раз. Проверьте корректность всех вхождений.<br>"
55+
elif res["found_value"] < res["find"]:
56+
result_score -= penalty_score * (res["find"] - res['found_value'])
57+
links = self.format_page_link(pages)
58+
result_str += f"Содержимое поля '{res['key']}' указано корректно {res['found_value']} из {res['find']} раз. Проверьте корректность всех вхождений на страницах {links}.<br>"
59+
result_str += f"""<br>Логи проверки:<br><code>{"<br>".join(res['logs'] for res in check_result)}</code><br>"""
60+
if result_score < 0:
61+
result_score = 0 # for case with big penalty
62+
63+
if result_score == 1.0:
64+
return answer(result_score, f"Пройдена!<br>{result_str}")
4465
else:
45-
result_str += f'<br>Убедитесь, что вы использовали правильные формы бланков титульного листа, задания и календарного плана.' \
46-
f'<br>Для бакалавров: <a href="https://drive.google.com/drive/folders/1pvv9HJIUB0VZUXteGqtLcVq6zIgZ6rbZ">Формы бланков для бакалавров</a>.' \
47-
f'<br>Для магистров: <a href="https://drive.google.com/drive/folders/1KOoXzKv4Wf-XyGzOf1X8gN256sgame1D">Формы бланков для магистров</a>.'
48-
return answer(False, result_str)
66+
result_str += (
67+
f"<br>Убедитесь, что вы использовали правильные формы бланков титульного листа, задания и календарного плана."
68+
f'<br>Для бакалавров: <a href="https://drive.google.com/drive/folders/1pvv9HJIUB0VZUXteGqtLcVq6zIgZ6rbZ">Формы бланков для бакалавров</a>.'
69+
f'<br>Для магистров: <a href="https://drive.google.com/drive/folders/1KOoXzKv4Wf-XyGzOf1X8gN256sgame1D">Формы бланков для магистров</a>.'
70+
)
71+
return answer(result_score, result_str)
72+
73+
def extract_table_contents(self, table):
74+
contents = []
75+
processed_cells = set()
76+
for row in table.rows:
77+
row_text = []
78+
for cell in row.cells:
79+
if cell not in processed_cells:
80+
row_text.append(cell.text.strip())
81+
processed_cells.add(cell)
82+
contents.append("|".join(row_text))
83+
return contents
84+
85+
def calculate_find_value(self, table, index):
86+
count = int((len(table) - index - 2) / 2)
87+
if count >= 0:
88+
return count
89+
return 0
90+
91+
def check_table(self, check_list, table, table_num):
92+
for item in check_list:
93+
for i, line in enumerate(table):
94+
if item["key"] in line:
95+
item["found_key"] += 1
96+
item["logs"] += f"'{item['key']}': ключ компоненты найден в строке '{line}' в таблице №{table_num}<br>"
97+
98+
for value in item["value"]:
99+
if re.search(value, line):
100+
item["found_value"] += 1
101+
item["logs"] += f"\t'{item['key']}': значение компоненты '{value}' найдено в строке '{line}' в таблице №{table_num}<br>"
102+
break
103+
104+
if item["key"] != "Зав. кафедрой" and item["key"] != "Консультант":
105+
continue
106+
107+
elif item["key"] in ["Зав. кафедрой", "Консультант"] and item["found_key"] > 0:
108+
if item["key"] == "Консультант":
109+
if item["found_key"] == 1:
110+
item["find"] += self.calculate_find_value(table, i)
111+
for value in item["value"]:
112+
if re.search(value, line):
113+
item["found_value"] += 1
114+
item["logs"] += f"'{item['key']}': значение компоненты '{value}' найдено в строке '{line}' в таблице №{table_num}<br>"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
class ReportMainPageSetting:
2+
FIRST_TABLE = [
3+
{
4+
"key": "Направление",
5+
"found_value": 0,
6+
"found_key": 0,
7+
"find": 1,
8+
"value": [
9+
"01.03.02 Прикладная математика и информатика",
10+
"09.03.04 Программная инженерия",
11+
],
12+
"logs": ""
13+
},
14+
{
15+
"key": "Профиль",
16+
"found_value": 0,
17+
"found_key": 0,
18+
"find": 1,
19+
"value": [
20+
"Математическое обеспечение программно-информационных систем",
21+
"Разработка программно-информационных систем"
22+
],
23+
"logs": ""
24+
},
25+
{
26+
"key": "Факультет",
27+
"found_value": 0,
28+
"found_key": 0,
29+
"find": 1,
30+
"value": ["КТИ"],
31+
"logs": ""
32+
},
33+
{
34+
"key": "Кафедра",
35+
"found_value": 0,
36+
"found_key": 0,
37+
"find": 1,
38+
"value": ["МО ЭВМ"],
39+
"logs": ""
40+
},
41+
{
42+
"key": "Зав. кафедрой",
43+
"found_value": 0,
44+
"found_key": 0,
45+
"find": 3,
46+
"value": ["А.А. Лисс"],
47+
"logs": ""
48+
}
49+
]
50+
51+
SECOND_TABLE = [
52+
{
53+
"key": "Руководитель",
54+
"found_value": 0,
55+
"found_key": 0,
56+
"find": 3,
57+
"value": [r"(Руководитель).*([кд]\..+\.н\., (доцент|профессор))[|]*([А-Я]\.[А-Я]\. [А-Я][а-я]+)"], #
58+
"logs": ""
59+
},
60+
{
61+
"key": "Консультант",
62+
"found_value": 0,
63+
"found_key": 0,
64+
"find": 1,
65+
"value": [r"[кд]\..+\.н\., (доцент|профессор)"], # (Консультант).*(([кд]\..+\.н\., (доцент|профессор))|).*([А-Я]\.[А-Я]\. [А-Я][а-я]+)
66+
# (([кд]\..+\.н\., (доцент|профессор))|)[|]*([А-Я]\.[А-Я]\. [А-Я][а-я]+)
67+
"logs": ""
68+
}
69+
]

0 commit comments

Comments
 (0)