From ecee0d7eff38c78f82f2bb0d1dd0c133bb254000 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Mon, 8 Dec 2025 11:53:45 +0300 Subject: [PATCH 01/11] update main_character_check --- app/main/checks/report_checks/main_character_check.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/app/main/checks/report_checks/main_character_check.py b/app/main/checks/report_checks/main_character_check.py index c596e999..47914a6f 100644 --- a/app/main/checks/report_checks/main_character_check.py +++ b/app/main/checks/report_checks/main_character_check.py @@ -82,12 +82,6 @@ def extract_table_contents(self, table): contents.append("|".join(row_text)) return contents - def calculate_find_value(self, table, index): - count = int((len(table) - index - 2) / 2) - if count >= 0: - return count - return 0 - def check_table(self, check_list, table, table_num): for item in check_list: for i, line in enumerate(table): @@ -105,10 +99,7 @@ def check_table(self, check_list, table, table_num): continue elif item["key"] in ["Зав. кафедрой", "Консультант"] and item["found_key"] > 0: - if item["key"] == "Консультант": - if item["found_key"] == 1: - item["find"] += self.calculate_find_value(table, i) for value in item["value"]: - if re.search(value, line): + if "Руководитель" not in line and re.search(value, line): # исключаем из поиска строки с рукодителем item["found_value"] += 1 item["logs"] += f"'{item['key']}': значение компоненты '{value}' найдено в строке '{line}' в таблице №{table_num}
" From 266f9198fdf61fb46d6bac733c5f46c5382f898e Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Mon, 8 Dec 2025 11:54:16 +0300 Subject: [PATCH 02/11] add recheck test --- tests/test_recheck.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/test_recheck.py diff --git a/tests/test_recheck.py b/tests/test_recheck.py new file mode 100644 index 00000000..4fc8135c --- /dev/null +++ b/tests/test_recheck.py @@ -0,0 +1,36 @@ +import time +from basic_selenium_test import BasicSeleniumTest +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + + +class RecheckTestSelenium(BasicSeleniumTest): + + def test_recheck_file(self): + check_id = self.open_statistic() + if check_id: + URL = self.get_url(f"/recheck/{check_id}") + self.get_driver().get(URL) + obj = WebDriverWait(self.driver, 10).until( + EC.presence_of_element_located((By.ID, "results_title")) + ) + if "Производится проверка файла" in obj.text: + start_time = time.time() + max_time = 240 + while (time.time() - start_time) < max_time: + time.sleep(10) + try: + obj = WebDriverWait(self.driver, 10).until( + EC.presence_of_element_located((By.ID, "results_table")) + ) + if obj is not None: + self.assertNotEquals(obj, None) + return + except: + continue + self.fail("Result of check is not found") + else: + self.fail("No checking status after /recheck") + else: + self.skipTest("No check in system for testing recheck") From 5d82440f5d0806b2ef7f2149481aed72ef24e4c9 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Wed, 10 Dec 2025 15:05:19 +0300 Subject: [PATCH 03/11] Update style_check_settings.py --- app/main/checks/report_checks/style_check_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main/checks/report_checks/style_check_settings.py b/app/main/checks/report_checks/style_check_settings.py index 7c3a61b5..36912a9f 100644 --- a/app/main/checks/report_checks/style_check_settings.py +++ b/app/main/checks/report_checks/style_check_settings.py @@ -12,7 +12,7 @@ class StyleCheckSettings: HEADER_2_REGEX = "^()([\\w\\s]+)\\.$" STD_BANNED_WORDS = ['мы', 'моя', 'мои', 'моё', 'наш', 'наши', 'аттач', 'билдить', 'бинарник', 'валидный', 'дебаг', 'деплоить', 'десктопное', 'железо', - 'исходники', 'картинка', 'консольное', 'конфиг', 'кусок', 'либа', 'лог', 'мануал', 'машина', + 'исходники', 'картинка', 'консольное', 'конфиг', 'кусок', 'либа', 'лог', 'мануал', 'отнаследованный', 'парсинг', 'пост', 'распаковать', 'сбоит', 'скачать', 'склонировать', 'скрипт', 'тестить', 'тул', 'тула', 'тулза', 'фиксить', 'флажок', 'флаг', 'юзкейс', 'продакт', 'продакшн', 'прод', 'фидбек', 'дедлайн', 'дэдлайн', 'оптимально', 'оптимальный', 'надежный', 'интуитивный', From fe9f6493d8adc5ab58b19c65b6856cd067b45f25 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Wed, 17 Dec 2025 08:32:21 +0300 Subject: [PATCH 04/11] add warned_words for banned_words_check --- .../report_checks/banned_words_check.py | 45 +++++++++++-------- .../report_checks/style_check_settings.py | 23 +++++++--- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/app/main/checks/report_checks/banned_words_check.py b/app/main/checks/report_checks/banned_words_check.py index 351b403e..58c67cd3 100644 --- a/app/main/checks/report_checks/banned_words_check.py +++ b/app/main/checks/report_checks/banned_words_check.py @@ -5,12 +5,13 @@ class ReportBannedWordsCheck(BaseReportCriterion): label = "Проверка наличия запретных слов в тексте отчёта" - description = 'Запрещено упоминание слова "мы"' + description = 'Запрещено упоминание определенных "опасных" слов' id = 'banned_words_check' def __init__(self, file_info, headers_map=None): super().__init__(file_info) self.words = [] + self.warned_words = [] self.min_count = 0 self.max_count = 0 if headers_map: @@ -21,12 +22,14 @@ def __init__(self, file_info, headers_map=None): def late_init(self): self.headers_main = self.file.get_main_headers(self.file_type['report_type']) if self.headers_main in StyleCheckSettings.CONFIGS.get(self.config): - self.words = [morph.normal_forms(word)[0] for word in StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['banned_words']] + self.words = {morph.normal_forms(word)[0] for word in StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['banned_words']} + self.warned_words = {morph.normal_forms(word)[0] for word in StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['warned_words']} self.min_count = StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['min_count_for_banned_words_check'] self.max_count = StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['max_count_for_banned_words_check'] else: if 'any_header' in StyleCheckSettings.CONFIGS.get(self.config): - self.words = [morph.normal_forms(word)[0] for word in StyleCheckSettings.CONFIGS.get(self.config)['any_header']['banned_words']] + self.words = {morph.normal_forms(word)[0] for word in StyleCheckSettings.CONFIGS.get(self.config)['any_header']['banned_words']} + self.warned_words = {morph.normal_forms(word)[0] for word in StyleCheckSettings.CONFIGS.get(self.config)['any_header']['warned_words']} self.min_count = StyleCheckSettings.CONFIGS.get(self.config)['any_header']['min_count_for_banned_words_check'] self.max_count = StyleCheckSettings.CONFIGS.get(self.config)['any_header']['max_count_for_banned_words_check'] @@ -34,29 +37,35 @@ def check(self): if self.file.page_counter() < 4: return answer(False, "В отчете недостаточно страниц. Нечего проверять.") self.late_init() - detected_lines = {} result_str = f'Запрещенные слова: {"; ".join(self.words)}
' - count = 0 + banned_counter = {'words': self.words, 'detected_lines': {}, 'count': 0} + warned_counter = {'words': self.warned_words,'detected_lines': {}, 'count': 0} for k, v in self.file.pdf_file.get_text_on_page().items(): lines_on_page = re.split(r'\n', v) for index, line in enumerate(lines_on_page): - words_on_line = re.split(r'[^\w-]+', line) - words_on_line = [morph.normal_forms(word)[0] for word in words_on_line] - count_banned_words = set(words_on_line).intersection(self.words) - if count_banned_words: - count += len(count_banned_words) - if k not in detected_lines.keys(): - detected_lines[k] = [] - detected_lines[k].append(f'Строка {index + 1}: {line} [{"; ".join(count_banned_words)}]') - if len(detected_lines): + words_on_line = {morph.normal_forms(word)[0] for word in re.split(r'[^\w-]+', line)} + for counter in (banned_counter, warned_counter): + count_banned_words = words_on_line.intersection(counter['words']) + if count_banned_words: + counter['count'] += len(count_banned_words) + if k not in counter['detected_lines'].keys(): + counter['detected_lines'][k] = [] + counter['detected_lines'][k].append(f'Строка {index + 1}: {line} [{"; ".join(count_banned_words)}]') + if len(banned_counter['detected_lines']): result_str += 'Обнаружены запретные слова!

' - for k, v in detected_lines.items(): - result_str += f'Страница №{k}:
{"
".join(detected_lines[k])}

' + for k, v in banned_counter['detected_lines'].items(): + result_str += f'Страница №{k}:
{"
".join(banned_counter['detected_lines'][k])}

' else: result_str = 'Пройдена!' + + if len(warned_counter['detected_lines']): + result_str += f'

Обнаружены потенциально опасные слова (не влияют на результат проверки)!
Обратите внимание, что их использование возможно только в подтвержденных случаях: {"; ".join(self.warned_words)}

' + for k, v in warned_counter['detected_lines'].items(): + result_str += f'Страница №{k}:
{"
".join(warned_counter['detected_lines'][k])}

' + result_score = 1 - if count > self.min_count: - if count <= self.max_count: + if banned_counter['count'] > self.min_count: + if banned_counter['count'] <= self.max_count: result_score = 0.5 else: result_score = 0 diff --git a/app/main/checks/report_checks/style_check_settings.py b/app/main/checks/report_checks/style_check_settings.py index 36912a9f..40a7cd21 100644 --- a/app/main/checks/report_checks/style_check_settings.py +++ b/app/main/checks/report_checks/style_check_settings.py @@ -10,14 +10,15 @@ class StyleCheckSettings: HEADER_REGEX = "^\\D+.+$" HEADER_1_REGEX = "^()([\\w\\s]+)$" HEADER_2_REGEX = "^()([\\w\\s]+)\\.$" - STD_BANNED_WORDS = ['мы', 'моя', 'мои', 'моё', 'наш', 'наши', + STD_BANNED_WORDS = ('мы', 'моя', 'мои', 'моё', 'наш', 'наши', 'аттач', 'билдить', 'бинарник', 'валидный', 'дебаг', 'деплоить', 'десктопное', 'железо', 'исходники', 'картинка', 'консольное', 'конфиг', 'кусок', 'либа', 'лог', 'мануал', 'отнаследованный', 'парсинг', 'пост', 'распаковать', 'сбоит', 'скачать', 'склонировать', 'скрипт', 'тестить', 'тул', 'тула', 'тулза', 'фиксить', 'флажок', 'флаг', 'юзкейс', 'продакт', 'продакшн', - 'прод', 'фидбек', 'дедлайн', 'дэдлайн', 'оптимально', 'оптимальный', 'надежный', 'интуитивный', + 'прод', 'фидбек', 'дедлайн', 'дэдлайн', 'оптимально', 'надежный', 'интуитивный', 'хороший', 'плохой', 'идеальный', 'быстро', 'медленно', 'какой-нибудь', 'некоторый', 'почти' - ] # TODO: list of "warning" words + ) + STD_WARNED_WORDS = ('машина', 'оптимальный') # TODO: list of "warning" words STD_MIN_LIT_REF = 1 STD_MAX_LIT_REF = 1000 #just in case for future edit HEADER_1_STYLE = { @@ -101,6 +102,7 @@ class StyleCheckSettings: "unify_regex": APPENDIX_UNIFY_REGEX, "regex": APPENDIX_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_count_for_banned_words_check': 3, 'max_count_for_banned_words_check': 6, 'min_ref_for_literature_references_check': STD_MIN_LIT_REF, @@ -125,6 +127,7 @@ class StyleCheckSettings: "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_count_for_banned_words_check': 3, 'max_count_for_banned_words_check': 6, 'min_ref_for_literature_references_check': STD_MIN_LIT_REF, @@ -149,7 +152,8 @@ class StyleCheckSettings: "ПЛАН РАБОТЫ НА ВЕСЕННИЙ СЕМЕСТР", "ОТЗЫВ РУКОВОДИТЕЛЯ", "СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"], "unify_regex": None, "regex": HEADER_REGEX, - "banned_words": STD_BANNED_WORDS + ['доработать', 'доработка', 'переписать', 'рефакторинг', 'исправление'] + "banned_words": STD_BANNED_WORDS + ('доработать', 'доработка', 'переписать', 'рефакторинг', 'исправление'), + "warned_words": STD_WARNED_WORDS }, } @@ -162,7 +166,8 @@ class StyleCheckSettings: "ПЛАН РАБОТЫ НА ОСЕННИЙ СЕМЕСТР", "СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"], "unify_regex": None, "regex": HEADER_REGEX, - "banned_words": STD_BANNED_WORDS + ['доработать', 'доработка', 'переписать', 'рефакторинг', 'исправление'] + "banned_words": STD_BANNED_WORDS + ('доработать', 'доработка', 'переписать', 'рефакторинг', 'исправление'), + "warned_words": STD_WARNED_WORDS }, } @@ -175,7 +180,8 @@ class StyleCheckSettings: "ПЛАН РАБОТЫ НА ВЕСЕННИЙ СЕМЕСТР", "ОТЗЫВ РУКОВОДИТЕЛЯ", "СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"], "unify_regex": None, "regex": HEADER_REGEX, - "banned_words": STD_BANNED_WORDS + ['доработать', 'доработка', 'переписать', 'рефакторинг', 'исправление'] + "banned_words": STD_BANNED_WORDS + ('доработать', 'доработка', 'переписать', 'рефакторинг', 'исправление'), + "warned_words": STD_WARNED_WORDS }, } @@ -193,6 +199,7 @@ class StyleCheckSettings: "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_count_for_banned_words_check': 3, 'max_count_for_banned_words_check': 6, }, @@ -208,6 +215,7 @@ class StyleCheckSettings: "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_count_for_banned_words_check': 3, 'max_count_for_banned_words_check': 6, } @@ -230,6 +238,7 @@ class StyleCheckSettings: "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_ref_for_literature_references_check': 1, 'mах_ref_for_literature_references_check': 1000, #just for future possible edit 'min_count_for_banned_words_check': 2, @@ -249,6 +258,7 @@ class StyleCheckSettings: "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_ref_for_literature_references_check': 3, 'mах_ref_for_literature_references_check': 1000, #just for future possible edit 'min_count_for_banned_words_check': 2, @@ -268,6 +278,7 @@ class StyleCheckSettings: "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, + "warned_words": STD_WARNED_WORDS, 'min_ref_for_literature_references_check': 5, 'mах_ref_for_literature_references_check': 1000, #just for future possible edit 'min_count_for_banned_words_check': 2, From d7121dddde13bda3fde6dd5098f393a4ef69da06 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Fri, 26 Dec 2025 12:08:34 +0300 Subject: [PATCH 05/11] add login_required and author check for result page --- app/routes/results.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/routes/results.py b/app/routes/results.py index 91cc5b7f..95f4f508 100644 --- a/app/routes/results.py +++ b/app/routes/results.py @@ -3,6 +3,7 @@ from time import time from flask import Blueprint, Response, render_template +from flask_login import current_user, login_required from wsgiref.handlers import format_date_time as format_date from app.db import db_methods @@ -16,6 +17,7 @@ @results_bp.route("/", methods=["GET"]) +@login_required def results_main(_id): try: oid = ObjectId(_id) @@ -24,11 +26,15 @@ def results_main(_id): return render_template("./404.html") check = db_methods.get_check(oid) if check is not None: - # show processing time for user - avg_process_time = None if check.is_ended else db_methods.get_average_processing_time() - return render_template("./results.html", navi_upload=True, results=check, - columns=TABLE_COLUMNS, avg_process_time=avg_process_time, - stats=format_check(check.pack())) + # show check only for author or admin + if current_user.is_admin or current_user.username == check.user: + # show processing time for user + avg_process_time = None if check.is_ended else db_methods.get_average_processing_time() + return render_template("./results.html", navi_upload=True, results=check, + columns=TABLE_COLUMNS, avg_process_time=avg_process_time, + stats=format_check(check.pack())) + else: + return "У вас нет прав на просмотр результатов чужих проверок", 403 else: logger.info("Запрошенная проверка не найдена: " + _id) return render_template("./404.html") From 125ea65bf22dd12c9ac557e7156902e7dfaff323 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Fri, 26 Dec 2025 12:11:51 +0300 Subject: [PATCH 06/11] little update for 404 page --- app/templates/404.html | 2 +- assets/styles/404.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/404.html b/app/templates/404.html index bf8140dd..ad648890 100644 --- a/app/templates/404.html +++ b/app/templates/404.html @@ -4,7 +4,7 @@ {% block main %}
- Страница не найдена! +

Запрашиваемый ресурс не найден

diff --git a/assets/styles/404.css b/assets/styles/404.css index c833cc62..384902ba 100644 --- a/assets/styles/404.css +++ b/assets/styles/404.css @@ -1,3 +1,3 @@ #middle-container { - background-color: black; + background-color: rgb(255, 255, 255); } From e522e11a4d6929be71343695c8bc06f5ee1c381a Mon Sep 17 00:00:00 2001 From: Marina Date: Sun, 2 Jun 2024 16:47:17 +0300 Subject: [PATCH 07/11] first try of count_lit_ref # Conflicts: # app/main/check_packs/pack_config.py # app/main/checks/report_checks/__init__.py # app/main/checks/report_checks/style_check_settings.py --- app/main/check_packs/pack_config.py | 1 + app/main/checks/report_checks/__init__.py | 2 + .../report_checks/lit_ref_in_spec_chapter.py | 65 +++++++++++++++++++ .../report_checks/style_check_settings.py | 7 +- 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 app/main/checks/report_checks/lit_ref_in_spec_chapter.py diff --git a/app/main/check_packs/pack_config.py b/app/main/check_packs/pack_config.py index 91e08134..471949ae 100644 --- a/app/main/check_packs/pack_config.py +++ b/app/main/check_packs/pack_config.py @@ -50,6 +50,7 @@ ["empty_task_page_check"], ["water_in_the_text_check"], ["report_task_tracker"], + ["references_in_chapter_check"], ] DEFAULT_TYPE = 'pres' diff --git a/app/main/checks/report_checks/__init__.py b/app/main/checks/report_checks/__init__.py index 30f22617..b3e15c17 100644 --- a/app/main/checks/report_checks/__init__.py +++ b/app/main/checks/report_checks/__init__.py @@ -34,3 +34,5 @@ from .task_tracker import ReportTaskTracker from .paragraphs_count_check import ReportParagraphsCountCheck from .template_name import ReportTemplateNameCheck + +from .lit_ref_in_spec_chapter import LitRefInChapter diff --git a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py new file mode 100644 index 00000000..a1c7b541 --- /dev/null +++ b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py @@ -0,0 +1,65 @@ +import re +from .style_check_settings import StyleCheckSettings +from ..base_check import BaseReportCriterion, answer + + +class LitRefInChapter(BaseReportCriterion): + label = "Проверка количества ссылок на источники в определенном разделе" + description = '' + id = 'references_in_chapter_check' + + def __init__(self, file_info, chapters_for_lit_ref = { + # 'введение', "определения, обозначения и сокращения", "заключение" + }, min_ref = 1, headers_map = None): + super().__init__(file_info) + self.lit_ref_count = {} + self.min_ref = min_ref + if headers_map: + self.chapters_for_lit_ref = StyleCheckSettings.CONFIGS.get(headers_map)[0]["headers_for_lit_count"] + else: + self.chapters_for_lit_ref = chapters_for_lit_ref + + def late_init(self): + self.chapters = self.file.make_chapters(self.file_type['report_type']) + + def check(self): + if self.file.page_counter() < 4: + return answer(False, "В отчете недостаточно страниц. Нечего проверять.") + result = [] + result_str = f'Пройдена!' + self.late_init() + currant_head = '' + for chapter in self.chapters: + if chapter['style'] == "heading 2": + header = chapter["text"].lower() + if currant_head: + self.lit_ref_count[currant_head].append(chapter['number']) + if currant_head in self.chapters_for_lit_ref: + ref_count = len(self.search_references(self.lit_ref_count[currant_head][0], self.lit_ref_count[currant_head][1])) + if ref_count > self.min_ref: + result.append(f'"{currant_head[0].upper() + currant_head[1:]}" : {ref_count}') + self.lit_ref_count[header] = [chapter['number'],] + currant_head = header + if result: + result_str = f'Количество ссылок на источники превышает допустимое ({self.min_ref}) в следующих разделах:
{", ".join(res for res in result)}' + return answer(False, result_str) + else: + return answer(True, result_str) + + def search_references(self, start_par, end_par): + array_of_references = [] + for i in range(start_par, end_par): + if isinstance(self.file.paragraphs[i], str): + detected_references = re.findall(r'\[[\d \-,]+\]', self.file.paragraphs[i]) + else: + detected_references = re.findall(r'\[[\d \-,]+\]', self.file.paragraphs[i].paragraph_text) + if detected_references: + for reference in detected_references: + for one_part in re.split(r'[\[\],]', reference): + if re.match(r'\d+[ \-]+\d+', one_part): + start, end = re.split(r'[ -]+', one_part) + for k in range(int(start), int(end) + 1): + array_of_references.append((k)) + elif one_part != '': + array_of_references.append(int(one_part)) + return array_of_references diff --git a/app/main/checks/report_checks/style_check_settings.py b/app/main/checks/report_checks/style_check_settings.py index 40a7cd21..ff57310e 100644 --- a/app/main/checks/report_checks/style_check_settings.py +++ b/app/main/checks/report_checks/style_check_settings.py @@ -99,6 +99,7 @@ class StyleCheckSettings: "style": HEADER_1_STYLE, "docx_style": ["heading 1"], "headers": ["Исходный код программы"], + "headers_for_lit_count": [], "unify_regex": APPENDIX_UNIFY_REGEX, "regex": APPENDIX_REGEX, "banned_words": STD_BANNED_WORDS, @@ -113,6 +114,7 @@ class StyleCheckSettings: "style": HEADER_2_STYLE, "docx_style": ["heading 2"], "headers": ["Цель работы", "Выполнение работы", "Выводы"], + "headers_for_lit_count": [], "unify_regex": None, "regex": HEADER_1_REGEX, } @@ -124,6 +126,7 @@ class StyleCheckSettings: "style": HEADER_1_STYLE, "docx_style": ["heading 2"], "headers": ["ВВЕДЕНИЕ", "ЗАКЛЮЧЕНИЕ", "СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"], + "headers_for_lit_count": [], "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, @@ -170,7 +173,7 @@ class StyleCheckSettings: "warned_words": STD_WARNED_WORDS }, } - + NIR3_CONFIG = { 'any_header': { @@ -196,6 +199,7 @@ class StyleCheckSettings: "Статья", ], "header_for_report_section_component": "Поставленная цель и задачи", + "headers_for_lit_count": [], "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, @@ -212,6 +216,7 @@ class StyleCheckSettings: "Статья", ], "header_for_report_section_component": "", + "headers_for_lit_count": [], "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, From e8203b7033414223b76592b22efada2fcb781864 Mon Sep 17 00:00:00 2001 From: Marina Date: Tue, 24 Sep 2024 21:04:55 +0300 Subject: [PATCH 08/11] structure of check is changed (need to improve results string) --- .../report_checks/lit_ref_in_spec_chapter.py | 24 ++++++++++++------- .../report_checks/style_check_settings.py | 11 +++++---- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py index a1c7b541..49e4add7 100644 --- a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py +++ b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py @@ -8,26 +8,32 @@ class LitRefInChapter(BaseReportCriterion): description = '' id = 'references_in_chapter_check' - def __init__(self, file_info, chapters_for_lit_ref = { - # 'введение', "определения, обозначения и сокращения", "заключение" - }, min_ref = 1, headers_map = None): + def __init__(self, file_info, headers_map = None): super().__init__(file_info) + self.chapters_for_lit_ref = {} self.lit_ref_count = {} - self.min_ref = min_ref if headers_map: - self.chapters_for_lit_ref = StyleCheckSettings.CONFIGS.get(headers_map)[0]["headers_for_lit_count"] + self.config = headers_map else: - self.chapters_for_lit_ref = chapters_for_lit_ref + self.config = 'VKR_HEADERS' if (self.file_type['report_type'] == 'VKR') else 'LR_HEADERS' def late_init(self): self.chapters = self.file.make_chapters(self.file_type['report_type']) + self.headers_main = self.file.get_main_headers(self.file_type['report_type']) + if self.headers_main in StyleCheckSettings.CONFIGS.get(self.config): + self.chapters_for_lit_ref = StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['chapters_for_lit_ref'] + else: + if 'any_header' in StyleCheckSettings.CONFIGS.get(self.config): + self.chapters_for_lit_ref= StyleCheckSettings.CONFIGS.get(self.config)['any_header']['chapters_for_lit_ref'] def check(self): if self.file.page_counter() < 4: return answer(False, "В отчете недостаточно страниц. Нечего проверять.") + self.late_init() + if not self.chapters_for_lit_ref: + return answer(True, 'Для загруженной работы данная проверка не предусмотрена') result = [] result_str = f'Пройдена!' - self.late_init() currant_head = '' for chapter in self.chapters: if chapter['style'] == "heading 2": @@ -36,12 +42,12 @@ def check(self): self.lit_ref_count[currant_head].append(chapter['number']) if currant_head in self.chapters_for_lit_ref: ref_count = len(self.search_references(self.lit_ref_count[currant_head][0], self.lit_ref_count[currant_head][1])) - if ref_count > self.min_ref: + if ref_count > self.chapters_for_lit_ref[currant_head][1] or ref_count < self.chapters_for_lit_ref[currant_head][0]: result.append(f'"{currant_head[0].upper() + currant_head[1:]}" : {ref_count}') self.lit_ref_count[header] = [chapter['number'],] currant_head = header if result: - result_str = f'Количество ссылок на источники превышает допустимое ({self.min_ref}) в следующих разделах:
{", ".join(res for res in result)}' + result_str = f'Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{", ".join(res for res in result)}' return answer(False, result_str) else: return answer(True, result_str) diff --git a/app/main/checks/report_checks/style_check_settings.py b/app/main/checks/report_checks/style_check_settings.py index ff57310e..da8629d8 100644 --- a/app/main/checks/report_checks/style_check_settings.py +++ b/app/main/checks/report_checks/style_check_settings.py @@ -99,7 +99,7 @@ class StyleCheckSettings: "style": HEADER_1_STYLE, "docx_style": ["heading 1"], "headers": ["Исходный код программы"], - "headers_for_lit_count": [], + "chapters_for_lit_ref": {}, "unify_regex": APPENDIX_UNIFY_REGEX, "regex": APPENDIX_REGEX, "banned_words": STD_BANNED_WORDS, @@ -114,7 +114,7 @@ class StyleCheckSettings: "style": HEADER_2_STYLE, "docx_style": ["heading 2"], "headers": ["Цель работы", "Выполнение работы", "Выводы"], - "headers_for_lit_count": [], + "chapters_for_lit_ref": {}, "unify_regex": None, "regex": HEADER_1_REGEX, } @@ -126,7 +126,7 @@ class StyleCheckSettings: "style": HEADER_1_STYLE, "docx_style": ["heading 2"], "headers": ["ВВЕДЕНИЕ", "ЗАКЛЮЧЕНИЕ", "СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"], - "headers_for_lit_count": [], + "chapters_for_lit_ref": { 'введение': [0, 1], 'определения, обозначения и сокращения': [2, 5], 'заключение': [1, 5] }, "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, @@ -198,6 +198,7 @@ class StyleCheckSettings: "Методы обоснования", "Статья", ], + "chapters_for_lit_ref": {}, "header_for_report_section_component": "Поставленная цель и задачи", "headers_for_lit_count": [], "unify_regex": None, @@ -215,6 +216,7 @@ class StyleCheckSettings: "Характеристика выводов", "Статья", ], + "chapters_for_lit_ref": {}, "header_for_report_section_component": "", "headers_for_lit_count": [], "unify_regex": None, @@ -255,11 +257,11 @@ class StyleCheckSettings: "docx_style": ["heading 2"], "headers": ["Принцип отбора аналогов", "Критерии сравнения аналогов", - "Таблица сравнения аналогов", "Выводы по итогам сравнения", "Выбор метода решения", "Список использованных источников" ], + "chapters_for_lit_ref": {}, "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, @@ -280,6 +282,7 @@ class StyleCheckSettings: "Заключение", "Список использованных источников" ], + "chapters_for_lit_ref": {}, "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, From a92fd08b7e945fe498ad43bcb9de332b4216d749 Mon Sep 17 00:00:00 2001 From: Marina Date: Wed, 25 Sep 2024 12:37:46 +0300 Subject: [PATCH 09/11] limits are added, structure is ready --- .../report_checks/lit_ref_in_spec_chapter.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py index 49e4add7..abd0fa37 100644 --- a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py +++ b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py @@ -8,10 +8,12 @@ class LitRefInChapter(BaseReportCriterion): description = '' id = 'references_in_chapter_check' - def __init__(self, file_info, headers_map = None): + def __init__(self, file_info, min_ref_value=0.5, max_ref_value=0.8, headers_map = None): super().__init__(file_info) self.chapters_for_lit_ref = {} self.lit_ref_count = {} + self.min_ref_value = min_ref_value + self.max_ref_value = max_ref_value if headers_map: self.config = headers_map else: @@ -35,22 +37,32 @@ def check(self): result = [] result_str = f'Пройдена!' currant_head = '' + chapter_for_check = 0 for chapter in self.chapters: if chapter['style'] == "heading 2": header = chapter["text"].lower() if currant_head: self.lit_ref_count[currant_head].append(chapter['number']) if currant_head in self.chapters_for_lit_ref: + chapter_for_check += 1 ref_count = len(self.search_references(self.lit_ref_count[currant_head][0], self.lit_ref_count[currant_head][1])) if ref_count > self.chapters_for_lit_ref[currant_head][1] or ref_count < self.chapters_for_lit_ref[currant_head][0]: result.append(f'"{currant_head[0].upper() + currant_head[1:]}" : {ref_count}') self.lit_ref_count[header] = [chapter['number'],] currant_head = header if result: - result_str = f'Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{", ".join(res for res in result)}' - return answer(False, result_str) + ref_value = round((chapter_for_check-len(result))/chapter_for_check, 2) + result_str = (f'Доля соответствия количества ссылок необходимому в требуемых разделах равна {ref_value}' + f'
Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{", ".join(res for res in result)}' + f'
Допустимые пороги количества ссылок:
{self.chapters_for_lit_ref}') + if ref_value > self.max_ref_value: + return answer(1, f'Пройдена! {result_str}') + elif ref_value > self.min_ref_value: + return answer(ref_value, f'Частично пройдена! {result_str}') + else: + return answer(0, f'Не пройдена! {result_str}') else: - return answer(True, result_str) + return answer(1, result_str) def search_references(self, start_par, end_par): array_of_references = [] From ad7002feb6ef766980d9926a5960001f3d8e06d4 Mon Sep 17 00:00:00 2001 From: Marina Date: Wed, 25 Sep 2024 13:54:56 +0300 Subject: [PATCH 10/11] improving of html view --- .../report_checks/lit_ref_in_spec_chapter.py | 17 +++++++++-------- .../report_checks/style_check_settings.py | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py index abd0fa37..2176e25c 100644 --- a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py +++ b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py @@ -8,7 +8,7 @@ class LitRefInChapter(BaseReportCriterion): description = '' id = 'references_in_chapter_check' - def __init__(self, file_info, min_ref_value=0.5, max_ref_value=0.8, headers_map = None): + def __init__(self, file_info, min_ref_value=0, max_ref_value=0, headers_map = None): super().__init__(file_info) self.chapters_for_lit_ref = {} self.lit_ref_count = {} @@ -33,7 +33,7 @@ def check(self): return answer(False, "В отчете недостаточно страниц. Нечего проверять.") self.late_init() if not self.chapters_for_lit_ref: - return answer(True, 'Для загруженной работы данная проверка не предусмотрена') + return answer(True, 'Для загруженной работы данная проверка не предусмотрена.') result = [] result_str = f'Пройдена!' currant_head = '' @@ -47,17 +47,18 @@ def check(self): chapter_for_check += 1 ref_count = len(self.search_references(self.lit_ref_count[currant_head][0], self.lit_ref_count[currant_head][1])) if ref_count > self.chapters_for_lit_ref[currant_head][1] or ref_count < self.chapters_for_lit_ref[currant_head][0]: - result.append(f'"{currant_head[0].upper() + currant_head[1:]}" : {ref_count}') + result.append(f'«{currant_head[0].upper() + currant_head[1:]}» : {ref_count}') self.lit_ref_count[header] = [chapter['number'],] currant_head = header if result: ref_value = round((chapter_for_check-len(result))/chapter_for_check, 2) result_str = (f'Доля соответствия количества ссылок необходимому в требуемых разделах равна {ref_value}' - f'
Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{", ".join(res for res in result)}' - f'
Допустимые пороги количества ссылок:
{self.chapters_for_lit_ref}') - if ref_value > self.max_ref_value: - return answer(1, f'Пройдена! {result_str}') - elif ref_value > self.min_ref_value: + f'
Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{"
".join(res for res in result)}' + f'
Допустимые пороги количества ссылок:
' + f'{"
".join(f"«{chapter.capitalize()}»: от {limit[0]} до {limit[1]}" for chapter, limit in self.chapters_for_lit_ref.items())}') + if ref_value >= self.max_ref_value: + return answer(1, f'Пройдена!') + elif ref_value >= self.min_ref_value: return answer(ref_value, f'Частично пройдена! {result_str}') else: return answer(0, f'Не пройдена! {result_str}') diff --git a/app/main/checks/report_checks/style_check_settings.py b/app/main/checks/report_checks/style_check_settings.py index da8629d8..791e8c2e 100644 --- a/app/main/checks/report_checks/style_check_settings.py +++ b/app/main/checks/report_checks/style_check_settings.py @@ -126,7 +126,8 @@ class StyleCheckSettings: "style": HEADER_1_STYLE, "docx_style": ["heading 2"], "headers": ["ВВЕДЕНИЕ", "ЗАКЛЮЧЕНИЕ", "СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"], - "chapters_for_lit_ref": { 'введение': [0, 1], 'определения, обозначения и сокращения': [2, 5], 'заключение': [1, 5] }, + "chapters_for_lit_ref":{}, + # { 'введение': [0, 1], 'определения, обозначения и сокращения': [2, 5], 'заключение': [1, 5] }, "unify_regex": None, "regex": HEADER_REGEX, "banned_words": STD_BANNED_WORDS, From db387f389f33416d40c7e3bd956e3c1cb1803616 Mon Sep 17 00:00:00 2001 From: vovanbravin Date: Tue, 27 Jan 2026 18:32:01 +0300 Subject: [PATCH 11/11] add annotation and fix --- app/main/checks/report_checks/__init__.py | 1 - .../report_checks/lit_ref_in_spec_chapter.py | 54 +++++++++++-------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/app/main/checks/report_checks/__init__.py b/app/main/checks/report_checks/__init__.py index b3e15c17..faa3275e 100644 --- a/app/main/checks/report_checks/__init__.py +++ b/app/main/checks/report_checks/__init__.py @@ -34,5 +34,4 @@ from .task_tracker import ReportTaskTracker from .paragraphs_count_check import ReportParagraphsCountCheck from .template_name import ReportTemplateNameCheck - from .lit_ref_in_spec_chapter import LitRefInChapter diff --git a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py index 2176e25c..d31aa4e6 100644 --- a/app/main/checks/report_checks/lit_ref_in_spec_chapter.py +++ b/app/main/checks/report_checks/lit_ref_in_spec_chapter.py @@ -8,7 +8,7 @@ class LitRefInChapter(BaseReportCriterion): description = '' id = 'references_in_chapter_check' - def __init__(self, file_info, min_ref_value=0, max_ref_value=0, headers_map = None): + def __init__(self, file_info, min_ref_value=0.5, max_ref_value=1, headers_map=None): super().__init__(file_info) self.chapters_for_lit_ref = {} self.lit_ref_count = {} @@ -23,10 +23,12 @@ def late_init(self): self.chapters = self.file.make_chapters(self.file_type['report_type']) self.headers_main = self.file.get_main_headers(self.file_type['report_type']) if self.headers_main in StyleCheckSettings.CONFIGS.get(self.config): - self.chapters_for_lit_ref = StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main]['chapters_for_lit_ref'] + self.chapters_for_lit_ref = StyleCheckSettings.CONFIGS.get(self.config)[self.headers_main][ + 'chapters_for_lit_ref'] else: if 'any_header' in StyleCheckSettings.CONFIGS.get(self.config): - self.chapters_for_lit_ref= StyleCheckSettings.CONFIGS.get(self.config)['any_header']['chapters_for_lit_ref'] + self.chapters_for_lit_ref = StyleCheckSettings.CONFIGS.get(self.config)['any_header'][ + 'chapters_for_lit_ref'] def check(self): if self.file.page_counter() < 4: @@ -38,33 +40,43 @@ def check(self): result_str = f'Пройдена!' currant_head = '' chapter_for_check = 0 + ref_in_annotation = False for chapter in self.chapters: - if chapter['style'] == "heading 2": - header = chapter["text"].lower() - if currant_head: - self.lit_ref_count[currant_head].append(chapter['number']) - if currant_head in self.chapters_for_lit_ref: - chapter_for_check += 1 - ref_count = len(self.search_references(self.lit_ref_count[currant_head][0], self.lit_ref_count[currant_head][1])) - if ref_count > self.chapters_for_lit_ref[currant_head][1] or ref_count < self.chapters_for_lit_ref[currant_head][0]: - result.append(f'«{currant_head[0].upper() + currant_head[1:]}» : {ref_count}') - self.lit_ref_count[header] = [chapter['number'],] - currant_head = header + header = chapter["text"].lower() + if currant_head: + self.lit_ref_count[currant_head].append(chapter['number']) + if currant_head in self.chapters_for_lit_ref: + chapter_for_check += 1 + ref_count = len(self.search_references(self.lit_ref_count[currant_head][0], + self.lit_ref_count[currant_head][1])) + if ref_count > self.chapters_for_lit_ref[currant_head][1] or ref_count < \ + self.chapters_for_lit_ref[currant_head][0]: + result.append(f'«{currant_head[0].upper() + currant_head[1:]}» : {ref_count}') + if currant_head == 'аннотация' or currant_head == 'annotation': + ref_in_annotation = True + self.lit_ref_count[header] = [chapter['number'], ] + currant_head = header if result: - ref_value = round((chapter_for_check-len(result))/chapter_for_check, 2) + if chapter_for_check > 0: + ref_value = round((chapter_for_check - len(result)) / chapter_for_check, 2) + else: + ref_value = 1.0 result_str = (f'Доля соответствия количества ссылок необходимому в требуемых разделах равна {ref_value}' - f'
Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{"
".join(res for res in result)}' - f'
Допустимые пороги количества ссылок:
' - f'{"
".join(f"«{chapter.capitalize()}»: от {limit[0]} до {limit[1]}" for chapter, limit in self.chapters_for_lit_ref.items())}') - if ref_value >= self.max_ref_value: + f'
Количество ссылок на источники не удовлетворяет допустимому в следующих разделах:
{"
".join(res for res in result)}' + f'
Допустимые пороги количества ссылок:
' + f'{"
".join(f"«{chapter.capitalize()}»: от {limit[0]} до {limit[1]}" for chapter, limit in self.chapters_for_lit_ref.items())}') + result_str += 'В аннотации не должно быть ссылок на литературу.' if ref_in_annotation else '' + if ref_value >= self.max_ref_value and not ref_in_annotation: return answer(1, f'Пройдена!') - elif ref_value >= self.min_ref_value: + elif ref_value >= self.min_ref_value and not ref_in_annotation: return answer(ref_value, f'Частично пройдена! {result_str}') else: return answer(0, f'Не пройдена! {result_str}') + elif ref_in_annotation: + return answer(0, 'В аннотации не должно быть ссылок на литературу.') else: return answer(1, result_str) - + def search_references(self, start_par, end_par): array_of_references = [] for i in range(start_par, end_par):