Komarov's term project - application DocAnalyzer.
end_punctuation_marks[]= символ переноса строки, точка, точка с запятой, двоеточиеrussian_alphabet[]= русский алфавит в обоих регистров + цифры 0-9.lower_alphabet[]= русский алфавит в нижнем регистреupper_alphabet[]= русский алфавит в верхнем регистре
Наследуется от класса Enum и представляет собой тип перечисления видов регистра:
NOT_INITIALIZED- не проинициализированный;UPPER- верхний;LOWER- нижний.
В своем коде я гарантирую, что после чтения файла я имею массив строк, конечный символ каждой их которых либо символ переноса строки, либо точка, либо точка с запятой, либо двоеточие, символ переноса строки я хранить не буду, поэтому имеем:
EMPTY= "" - пустой символ;POINT= "." - точка;SEMICOLON= ";" - точка с запятой;COLON= ":" - двоеточие.
Это тип строки, который отражает, какую часть какого абзаца составляет строка. При считывании текста построчно из файла, обращаем внимание на последний символ строк, если это точка - то эта строка представляет собой часть обычного текста, если двоеточие - это строчка начинает какое-то перечисление, если точка с запятой - это перечисляемый элемент, ну а если в конце вообще ничего не стоит - это заголовок.
PLAIN= "plain_" - обычный текст;TITLE= "title_" - заголовок;ENUM_HEAD= "enum_head_" - начало перечисления;ENUM_PART= "enum_part_" - часть перечисления;ENUM_LAST= "enum_last_" - последний элемент перечисления.
Представляет собой тип абзаца: перечисление, заголовок или простой текст.
PLAIN= "plain_" - обычный текст;TITLE= "title_" - заголовок;ENUM= "enum_" - перечисление;
content = содержание строки.
types = массив типов перечисления LineType, отражает всю структурную
нагрузку строки.
case = регистр строки типа CaseType, показывает, с символа какого регистра
начинается строка.
level = "уровень" строки типа int, показывает как сильно "выступает" строка,
хранит количество знаков табуляции.
Представляет собой класс абзаца в классическом понимании, состоит из предложений.
(!небезопасно) content = содержание абзаца, его основная часть, массив типа Line или
наследников Paragraph.
type = поле типа ParagraphType, к какому виду параграфа объект находится.
key_sentence = предложение, открывающее перечисление.
Переопределен __str__().
Переопределен __str__().
Переопределен __str__().
Представляет собой класс логического блока текста, состоит из заголовка
и содержания. Хранит все, что относится к его заголовку/подзаголовку.
title = поле, хранящее заголовок текста.
content = содержание блока, массив типа наследников Paragraph.
Переопределен __str__().
Получаем содержимое файла при помощи модуля python-docx.
- Ввод: путь к файлу;
- Вывод: массив строк.
Получаем последний необходимый символ строки. Считываем строку с конца до тех пор,
пока не встретим или символ из end_punctuation_marks или из russian_alphabet.
- Ввод: строка;
- Вывод: последний символ строки, удовлетворяющий условиям.
Получаем ложный индекс массива который стоит после последнего истинного в массиве. Гарантировано после этого индекса есть только индексы, по которым хранятся только ложные значения.
- Ввод: булев массив;
- Вывод: ложный индекс элемента, стоящий после последнего истинного.
Преобразовываем строки обычного питоновского типа в наш класс Line.
parsed_lines= пустой список, где будут объекты класса Paragraph из скачанных строк.enum_started_lst= массив размером с количество строк, для каждого уровня храним: началось ли на этом уровне перечисление или нет. (для enum_head_ это i уровень, а для enum_part_ или enum_last_ это i - 1 уровень, то есть при начале перечисления, на новый уровень сдвигаются все строки до конца включительно, но не само начало)case_lst= массив размером с количество строк, для каждого уровня хранит регистр перво1 строки каждого уровня.curr_par_lvl= динамическая переменная, хранит уровень строки, на которой работаем. \
Цикл for по строкам:
- инициализируем
curr_par_lvlиндексом после последнего истинного вcase_lst, то есть уровнем элементов последнего начатого перечисления. - инициализируем
par_types- список типов будущей строки, пустым списком. - инициализируем
last_chпоследним символом строки при помощиget_last_char(). - инициализируем
curr_caseрегистром текущей обрабатываемой строки. - если мы не на нулевом уровне и на предыдущем уровне есть незавершенное
перечисление:
- если регистр данного уровня не установлен(т. е. это первая встретившаяся
на этом уровне строка):
- устанавливаем регистр для этого уровня аналогичный регистру этой строки;
- иначе если последний символ не точка с запятой и регистры не совпадают:
- уменьшаем
curr_par_lvlна один(спускаемся на один уровень).
- уменьшаем
- если последний символ - точка:
- добавляем в типы данной строки тип конца перечисления;
- помечаем, что на уровне на один больше перечисление завершено;
- обнуляем значение регистра для этого уровня.
- если регистр данного уровня не установлен(т. е. это первая встретившаяся
на этом уровне строка):
- если последний символ - двоеточие:
- добавляем в типы данной строки тип начала перечисления;
- помечаем, что на данном уровне на один больше началось перечисление.
- если тип строки до сих пор не был установлен и последний символ - точка:
- добавляем в типы данной строки тип простого текста;
- если тип строки и сейчас до сих пор не был установлен:
- добавляем в типы данной строки тип заголовка;
- Создаем объект типа
Line, передавая содержимое, регистр, уровень и список типов. - Добавляем этот объект в список
parsed_lines.
- Ввод: массив строк питоновского типа;
- Вывод: массив типа
Line.
Собирает строки типа Line в объект типа EnumParagraph.
- Ввод:
lines- анализируемый массив;start_index- индекс начала перечисления.
- Инициализируем
start_levelуровнем начала перечисления. - Инициализируем
parts(будущий список элементов перечисления) пустым списком. - Увеличиваем индекс на 1.
- Цикл
whileпока мы не прошли весь список и пока мы не встретили строку-конец перечисления и пока мы не спустились на уровень, на котором начинали:- Если встречаем начало перечисления:
- вызываем
collect_enum()для него. - добавляем новое перечисление в список частей
parts.
- вызываем
- Иначе:
- добавляем строку в
parts.
- добавляем строку в
- увеличиваем счетчик.
- Если встречаем начало перечисления:
- Если мы не прошли весь список и все еще на уровне элементов перечисления,
добавляем элемент по текущему индексу в
partsи увеличиваем счетчик.
- Возврат:
- объект
EnumParagraphтипаParagraphType.ENUMиз строки-начала по индексуstart_indexи частейparts; - индекс
iпоследнего элемента, вошедшего в возвращаемое перечисление.
- объект
Собирает строки типа Line в объект типа PlainParagraph.
- Ввод:
lines- анализируемый массив;start_index- индекс начала простого текста.
- Инициализируем
content(будущий список строк абзаца) начальной строкой. - Увеличиваем индекс на 1.
- Если мы уже прошли весь список, возвращаем абзац из одной строки и ее индекс.
- Цикл
whileпока мы не прошли весь список и пока текущий перебираемый элемент является строкой типа простого текста:- добавляем строку в
content. - увеличиваем счетчик.
- добавляем строку в
- Возврат:
- объект
PlainParagraphтипаParagraphType.PLAINиз строк изcontent; - индекс
iпоследнего элемента, вошедшего в возвращаемый абзацы.
- объект
Собирает строки типа Line в объект типа TitleParagraph.
- Ввод:
lines- анализируемый массив;start_index- индекс начала простого текста.
- Инициализируем
content(будущий список строк абзаца) начальной строкой. - Увеличиваем индекс на 1.
- Если мы уже прошли весь список, возвращаем абзац из одной строки и ее индекс.
- Цикл
whileпока мы не прошли весь список и пока текущий перебираемый элемент является строкой типа заголовка:- добавляем строку в
content. - увеличиваем счетчик.
- добавляем строку в
- Возврат:
- объект
TitleParagraphтипаParagraphType.TITLEиз строк изcontent; - индекс
iпоследнего элемента, вошедшего в возвращаемый абзацы.
- объект
Объединяем строки в абзацы`.
- Ввод:
lines- массив строк;
- Инициализируем
pars(будущий список абзацев) пустым списком. - Инициализируем
iнулем. - Цикл
whileпока мы не прошли весь список:- Если встречаем строку простого текста - вызываем
collect_plain(). - Если встречаем строку-заголовок - вызываем
collect_title(). - Иначе вызываем
collect_enum(). - добавляем собранный объект в
pars. - увеличиваем счетчик.
- Если встречаем строку простого текста - вызываем
- Возврат:
- массив объектов
Paragraphили его наследников.
- массив объектов
Объединяем абзацы в логические блоки`.
- Ввод:
pars- массив абзацев;
- Инициализируем
blocks(будущий список логических блоков) пустым списком. - Инициализируем
iнулем. - Цикл
whileпока мы не прошли весь список:- Инициализируем переменную
titleтекущим перебираемым абзацем. - Если это последний абзац, создаем блок из него одного, считая его заголовком, а содержание блока пустым.
- Инициализируем переменную
curr_parsпустым списком. - увеличиваем счетчик.
- Цикл
whileпока мы не прошли весь список или пока не встретили следующий заголовок:- добавляем абзац в
curr_pars. - увеличиваем счетчик.
- добавляем абзац в
- добавляем блок из заголовка и считанных частей в
blocks.
- Инициализируем переменную
- Возврат:
- массив объектов
TextBlock.
- массив объектов
Problems:
-
небезопасный контент в параграфе(разные типы могу встречаться)
-
список энамов как поле в Line
-
много энамов
-
заголовки разного уровня не учитываются
-
сделать далее
-
функционал энамов, какэлементы жнама