diff --git a/app/main/check_packs/pack_config.py b/app/main/check_packs/pack_config.py index 91e08134..008d3c99 100644 --- a/app/main/check_packs/pack_config.py +++ b/app/main/check_packs/pack_config.py @@ -22,6 +22,7 @@ ['pres_image_capture'], ['task_tracker'], ['overview_in_tasks'], + ['abbreviations_check_pres'], ] BASE_REPORT_CRITERION = [ ["simple_check"], @@ -50,6 +51,7 @@ ["empty_task_page_check"], ["water_in_the_text_check"], ["report_task_tracker"], + ["abbreviations_check"], ] DEFAULT_TYPE = 'pres' diff --git a/app/main/checks/check_abbreviations.py b/app/main/checks/check_abbreviations.py new file mode 100644 index 00000000..f810b1b1 --- /dev/null +++ b/app/main/checks/check_abbreviations.py @@ -0,0 +1,80 @@ +import re +from pymorphy2 import MorphAnalyzer +morph = MorphAnalyzer() + + +def get_unexplained_abbrev(text): + abbreviations = find_abbreviations(text) + + if not abbreviations: + return False, None + + unexplained_abbr = [] + for abbr in abbreviations: + if not is_abbreviation_explained(abbr, text): + unexplained_abbr.append(abbr) + + return True, unexplained_abbr + + + + +def find_abbreviations(text: str): + pattern = r'\b[А-ЯA-Z]{2,5}\b' + abbreviations = re.findall(pattern, text) + + common_abbr = { + 'СССР', 'РФ', 'США', 'ВКР', 'ИТ', 'ПО', 'ООО', 'ЗАО', 'ОАО', 'HTML', 'CSS', + 'JS', 'ЛЭТИ', 'МОЕВМ', 'ЭВМ', 'ГОСТ', 'DVD' + + 'SSD', 'PC', 'HDD', + 'AX', 'BX', 'CX', 'DX', 'SI', 'DI', 'BP', 'SP', + 'AH', 'AL', 'BH', 'BL', 'CH', 'CL', 'DH', 'DL', + 'CS', 'DS', 'ES', 'SS', 'FS', 'GS', + 'IP', 'EIP', 'RIP', + 'CF', 'PF', 'AF', 'ZF', 'SF', 'TF', 'IF', 'DF', 'OF', + 'EAX', 'EBX', 'ECX', 'EDX', 'ESI', 'EDI', 'EBP', 'ESP', + 'RAX', 'RBX', 'RCX', 'RDX', 'RSI', 'RDI', 'RBP', 'RSP', + 'DOS', 'OS', 'BIOS', 'UEFI', 'MBR', 'GPT', + 'ASCII', 'UTF', 'UNICODE', 'ANSI', + 'ЭВМ', 'МОЭВМ', + 'CPU', 'GPU', 'APU', 'RAM', 'ROM', 'PROM', 'EPROM', 'EEPROM', + 'USB', 'SATA', 'PCI', 'PCIe', 'AGP', 'ISA', 'VGA', 'HDMI', 'DP', + 'LAN', 'WAN', 'WLAN', 'VPN', 'ISP', 'DNS', 'DHCP', 'TCP', 'UDP', 'IP', + 'HTTP', 'HTTPS', 'FTP', 'SSH', 'SSL', 'TLS', + 'API', 'GUI', 'CLI', 'IDE', 'SDK', 'SQL', 'NoSQL', 'XML', 'JSON', 'YAML', + 'MAC', 'IBM', 'ГОСТ' + } + filtered_abbr = [abbr for abbr in abbreviations if abbr not in common_abbr and morph.parse(abbr.lower())[0].score != 0] + + return list(set(filtered_abbr)) + + +def is_abbreviation_explained(abbr: str, text: str) -> bool: + patterns = [ + rf'{abbr}\s*\(([^)]+)\)', # АААА (расшифровка) + rf'\(([^)]+)\)\s*{abbr}', # (расшифровка) АААА + rf'{abbr}\s*[—\-]\s*([^.,;!?]+)', # АААА — расшифровка + rf'{abbr}\s*-\s*([^.,;!?]+)', # АААА - расшифровка + rf'([^.,;!?]+)\s*[—\-]\s*{abbr}', # расшифровка — АААА + rf'([^.,;!?]+)\s*-\s*{abbr}' # расшифровка - АААА + ] + + + for pattern in patterns: + match = re.search(pattern, text, re.IGNORECASE) + if match and correctly_explained(abbr, match.group(1)): + return True + + return False + +def correctly_explained(abbr, explan): + words = explan.split() + + first_letter = "" + for word in words: + first_letter += word[0].upper() + + if(first_letter == abbr[len(first_letter)]): + return True + return False diff --git a/app/main/checks/presentation_checks/__init__.py b/app/main/checks/presentation_checks/__init__.py index 52bd5f73..db54ae53 100644 --- a/app/main/checks/presentation_checks/__init__.py +++ b/app/main/checks/presentation_checks/__init__.py @@ -17,3 +17,4 @@ from .name_of_image_check import PresImageCaptureCheck from .task_tracker import TaskTracker from .overview_in_tasks import OverviewInTasks +from .abbreviations_presentation import PresAbbreviationsCheck diff --git a/app/main/checks/presentation_checks/abbreviations_presentation.py b/app/main/checks/presentation_checks/abbreviations_presentation.py new file mode 100644 index 00000000..17c4a672 --- /dev/null +++ b/app/main/checks/presentation_checks/abbreviations_presentation.py @@ -0,0 +1,59 @@ +import re +from ..base_check import BasePresCriterion, answer +from ..check_abbreviations import get_unexplained_abbrev + + +class PresAbbreviationsCheck(BasePresCriterion): + label = "Проверка расшифровки аббревиатур в презентации" + description = "Все аббревиатуры должны быть расшифрованы при первом использовании" + id = 'abbreviations_check_pres' + + def __init__(self, file_info): + super().__init__(file_info) + + def check(self): + try: + slides_text = self.file.get_text_from_slides() + + if not slides_text: + return answer(False, "Не удалось получить текст презентации") + + full_text = " ".join(slides_text) + + abbr_is_finding, unexplained_abbr = get_unexplained_abbrev(text=full_text) + + if not abbr_is_finding: + return answer(True, "Аббревиатуры не найдены в презентации") + + if not unexplained_abbr: + return answer(True, "Все аббревиатуры правильно расшифрованы") + + unexplained_abbr_with_slides = {} + + for slide_num, slide_text in enumerate(slides_text, 1): + for abbr in unexplained_abbr: + if abbr in slide_text and abbr not in unexplained_abbr_with_slides: + unexplained_abbr_with_slides[abbr] = slide_num + + result_str = "Найдены нерасшифрованные аббревиатуры при первом использовании:
" + slide_links = self.format_page_link(list(unexplained_abbr_with_slides.values())) + for index_links, abbr in enumerate(unexplained_abbr_with_slides): + result_str += f"- {abbr} на слайде {slide_links[index_links]}
" + + result_str += "
Каждая аббревиатура должна быть расшифрована при первом использовании в презентации.
" + result_str += "Расшифровка должны быть по первыми буквам, например, МВД - Министерство внутренних дел.
" + + return answer(False, result_str) + + except Exception as e: + return answer(False, f"Ошибка при проверке аббревиатур: {str(e)}") + + def _find_abbreviation_slides(self, abbr: str, slides_text: list) -> list: + found_slides = [] + + for slide_num, slide_text in enumerate(slides_text, 1): + pattern = rf'\b{re.escape(abbr)}\b' + if re.search(pattern, slide_text, re.IGNORECASE): + found_slides.append(slide_num) + + return found_slides diff --git a/app/main/checks/report_checks/__init__.py b/app/main/checks/report_checks/__init__.py index 30f22617..bf5d475c 100644 --- a/app/main/checks/report_checks/__init__.py +++ b/app/main/checks/report_checks/__init__.py @@ -32,5 +32,6 @@ from .sw_section_size import SWSectionSizeCheck from .sw_keywords_check import SWKeywordsCheck from .task_tracker import ReportTaskTracker +from .abbreviations_check import AbbreviationsCheckPres from .paragraphs_count_check import ReportParagraphsCountCheck from .template_name import ReportTemplateNameCheck diff --git a/app/main/checks/report_checks/abbreviations_check.py b/app/main/checks/report_checks/abbreviations_check.py new file mode 100644 index 00000000..20db6fac --- /dev/null +++ b/app/main/checks/report_checks/abbreviations_check.py @@ -0,0 +1,65 @@ +from ..base_check import BaseReportCriterion, answer +from ..check_abbreviations import get_unexplained_abbrev + +class AbbreviationsCheckPres(BaseReportCriterion): + label = "Проверка расшифровки аббревиатур" + description = "Все аббревиатуры должны быть расшифрованы при первом использовании" + id = 'abbreviations_check' + + def __init__(self, file_info): + super().__init__(file_info) + + + def check(self): + try: + text = self._get_document_text() + + if not text: + return answer(False, "Не удалось получить текст документа") + + abbr_is_finding, unexplained_abbr = get_unexplained_abbrev(text=text) + + if not abbr_is_finding: + return answer(True, "Аббревиатуры не найдены в документе") + + if not unexplained_abbr: + return answer(True, "Все аббревиатуры правильно расшифрованы") + + unexplained_abbr_with_page = {} + + for page_num in range(1, self.file.page_counter() + 1): + text_on_page = self.file.pdf_file.text_on_page[page_num] + + for abbr in unexplained_abbr: + if abbr in text_on_page and abbr not in unexplained_abbr_with_page: + unexplained_abbr_with_page[abbr] = page_num + + + result_str = "Найдены нерасшифрованные аббревиатуры при первом использовании:
" + page_links = self.format_page_link(list(unexplained_abbr_with_page.values())) + for index_links, abbr in enumerate(unexplained_abbr_with_page): + result_str += f"- {abbr} на странице {page_links[index_links]}
" + result_str += "Каждая аббревиатура должна быть расшифрована при первом использовании в тексте.
" + result_str += "Расшифровка должны быть по первыми буквам, например, МВД - Министерство внутренних дел.
" + + return answer(False, result_str) + + except Exception as e: + return answer(False, f"Ошибка при проверке аббревиатур: {str(e)}") + + + + def _get_document_text(self): + + if hasattr(self.file, 'pdf_file'): + page_texts = self.file.pdf_file.get_text_on_page() + return " ".join(page_texts.values()) + elif hasattr(self.file, 'paragraphs'): + text_parts = [] + for paragraph in self.file.paragraphs: + text = paragraph.to_string() + if '\n' in text: + text = text.split('\n')[1] + text_parts.append(text) + return "\n".join(text_parts) + return None