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
-
много энамов
-
заголовки разного уровня не учитываются
-
сделать далее
-
функционал энамов, какэлементы жнама