Загрузка данных
import zipfile
import io
import os
import re
import xml.etree.ElementTree as ET
from PIL import Image, ImageDraw, ImageFont
# Контекстные замены для темы «Мобильное приложение спортивного фитнес-клуба»
REPLACEMENTS = [
# 1. Защита титульного листа + точечные замены ФИО и шифров
("Студент группы __________ /Евстратенко Кирилл/", "СТУДЕНТ_ГРУППЫ_ЗАЩИТА /Калинин Денис/"),
("Студент группы 9/1 РПО - 1/24 Евстратенко Кирилл", "СТУДЕНТ_ГРУППЫ_91_ЗАЩИТА Калинин Денис"),
("Евстратенко К.Ю", "К. Денис"),
("Евстратенко Кирилл", "Калинин Денис"),
("К. Евстратенко", "К. Денис"),
("Евстратенко", "Калинин"),
("Масалимов П.А.", "К. Денис"),
("Масалимов Платон", "Калинин Денис"),
("П. Масалимов", "К. Денис"),
("П.Масалимов", "К. Денис"),
("Масалимов", "Калинин"),
("К.Е.00001", "К.Д.00001"),
("А.В.00001", "К.Д.00001"),
("П.М.00001", "К.Д.00001"),
# 2. Заголовки и названия системы (Фитнес-клуб / Дневник тренировок)
("ПРИЛОЖЕНИЕ ЭЛЕКТРОННОГО ЖУРНАЛА", "ПРИЛОЖЕНИЕ СПОРТИВНОГО КЛУБА"),
("Приложение электронного журнала для студентов колледжа", "Приложение учёта тренировок и абонементов для клиентов фитнес-клуба"),
("Мобильного приложения «Электронный журнал колледжа»", "Мобильного приложения «Мой Фитнес-Клуб»"),
("мобильного приложения «Электронный журнал колледжа»", "мобильного приложения «Мой Фитнес-Клуб»"),
("«Электронный журнал колледжа (Студент)»", "«Мой Фитнес-Клуб (Клиент)»"),
("«Электронный журнал колледжа»", "«Мой Фитнес-Клуб»"),
("\"Электронный журнал колледжа\"", "\"Мой Фитнес-Клуб\""),
("“электронный журнал колледжа”", "“мой фитнес-клуб”"),
("«Электронный журнал»", "«Мой Фитнес-Клуб»"),
("“Электронный журнал”", "“Мой Фитнес-Клуб”"),
("(Студенческое приложение iOS)", "(Клиентское приложение iOS)"),
("Ведение электронного журнала", "Ведение дневника тренировок"),
("вести электронный журнал", "вести дневник тренировок"),
("Модуль журнала", "Модуль дневника тренировок"),
("журнал успеваемости", "дневник спортивных показателей"),
("ведению журналов", "ведению журналов тренировок"),
("бумажных журналов", "бумажных карт и абонементов"),
("доступ к журналу", "доступ к дневнику тренировок"),
("ведение журнала", "ведение дневника тренировок"),
("авторизация, журнал, отчёты", "авторизация, дневник тренировок, отчёты"),
("функциональные требования (журнал, оценки, отчёты)", "функциональные требования (дневник тренировок, показатели нагрузок, отчёты)"),
# 3. Предметная область и функции
("учета успеваемости и посещаемости в колледже", "учета спортивных результатов и посещения тренировок в фитнес-клубе"),
("учёта успеваемости и посещаемости студентов колледжа", "учёта спортивных результатов и посещения тренировок клиентами фитнес-клуба"),
("учёта успеваемости и посещаемости студентов", "учёта спортивных результатов и посещения тренировок клиентами"),
("успеваемости и посещаемости студентов", "спортивных показателей и посещения тренировок клиентами"),
("учёта успеваемости и посещаемости", "учёта спортивных показателей и посещения залов"),
("об успеваемости, посещаемости и расписании занятий", "о спортивных результатах, истории визитов и расписании тренировок"),
("об успеваемости и посещаемости", "о спортивных результатах и истории визитов"),
("об успеваемости и расписании", "о результатах тренировок и расписании залов"),
("об успеваемости", "о спортивном прогрессе"),
("Данные об успеваемости", "Данные о результатах тренировок"),
("Данные посещаемости", "Данные истории визитов в клуб"),
("Учёт посещаемости", "Учёт посещений клуба"),
("учёт посещаемости", "учёт посещений клуба"),
("Модуль посещаемости", "Модуль истории визитов"),
("Просмотр посещаемости", "Просмотр истории визитов"),
("просмотр оценок, посещаемости, расписания", "просмотр спортивных показателей, истории визитов, расписания тренировок"),
# 4. Оценки, предметы, расписание, пары, домашние задания -> Результаты, программы тренировок, залы, планы упражнений
("добавление, редактирование и удаление оценок, комментариев и домашних заданий по каждому предмету",
"добавление, редактирование и удаление показателей нагрузок, комментариев тренера и планов упражнений по каждой программе"),
("Модуль просмотра и загнрузки домашних заданий", "Модуль просмотра и загрузки индивидуальных планов тренировок"),
("Отображение списка предметов, групп и студентов", "Отображение списка направлений, спортивных групп и клиентов"),
("списки студентов, предметы, оценки", "списки клиентов, направления тренировок, спортивные показатели"),
("со списками студентов и оценок", "со списками клиентов и спортивных показателей"),
("об оценках и студентах", "о результатах и клиентах клуба"),
("Загрузка списка оценок", "Загрузка списка спортивных показателей"),
("Отображение актуальных оценок по предметам", "Отображение актуальных спортивных показателей по направлениям"),
("выставление оценок, расписание", "фиксация результатов тренировок, расписание занятий"),
("выставление оценок", "фиксация результатов тренировок"),
("сохранение оценок", "сохранение результатов тренировок"),
("ввод оценок", "ввод показателей тренировок"),
("изменение оценок", "изменение показателей тренировок"),
("о новых оценках, изменениях в расписании", "о новых результатах замеров, изменениях в расписании тренировок"),
("о новых оценках, изменениях расписания", "о новых результатах замеров, изменениях расписания тренировок"),
("о новой оценке", "о новом результате тренировки"),
("новых оценках и академических задолженностях", "новых замерах прогресса и истечении срока абонемента"),
("академических задолженностей и пропусков занятий", "просрочки абонементов и пропусков персональных тренировок"),
("об академической задолженности", "об окончании действия абонемента"),
("динамики среднего балла", "динамики физических показателей"),
("средних баллов и рейтингов", "индексов физической формы и рейтингов активности"),
("ведомостей, справок", "сводных отчётов, выписок об абонементе"),
("ведомостей и справок", "сводных отчётов и клубных выписок"),
("отчётов и ведомостей", "спортивных отчётов и клубных выписок"),
("печати ведомостей и справок", "печати клубных выписок и справок"),
("формирование ведомостей", "формирование отчётов по тренировкам"),
("обработку ведомостей", "обработку карт клиентов"),
("по каждому предмету", "по каждому спортивному направлению"),
("фильтрация по предмету", "фильтрация по направлению тренировок"),
("по дате, группе, предмету", "по дате, секции, направлению тренировок"),
("потерю данных оценок", "потерю данных о тренировках"),
("оценки, даты, ФИО", "показатели нагрузок, даты, ФИО"),
("быстрая загрузка оценок и расписания", "быстрая загрузка показателей и расписания тренировок"),
("Быстрая загрузка оценок и расписания", "Быстрая загрузка показателей и расписания тренировок"),
("Оценки", "Показатели нагрузок"),
("Посещаемость", "История визитов"),
("Расписание занятий", "Расписание групповых и персональных тренировок"),
("расписания занятий", "расписания групповых и персональных тренировок"),
("Просмотр расписания", "Просмотр расписания тренировок"),
("Отображение пар на день/неделю с аудиториями", "Отображение тренировок на день/неделю с номерами залов"),
("на занятиях", "на тренировках"),
("в учебном расписании", "в расписании тренировок"),
("в расписании и оценках", "в расписании тренировок и спортивных показателях"),
("в расписании", "в расписании тренировок"),
("Расписание", "Расписание тренировок"),
# 5. Организация, роли и процессы
("в учреждениях среднего профессианального образования (колледжа)", "в спортивно-оздоровительных центрах и фитнес-клубах"),
("в учебных заведениях среднего профессионального образования (колледжах, техникумах), в учебных частях",
"в спортивно-оздоровительных комплексах и фитнес-клубах, в отделах клиентского сервиса"),
("Учебные корпуса колледжа", "Спортивные залы фитнес-клуба"),
("Backend колледжа", "Backend фитнес-клуба"),
("HTTPS-эндпоинт колледжа", "HTTPS-эндпоинт фитнес-клуба"),
("к серверу колледжа", "к серверу фитнес-клуба"),
("Серверная инфраструктура колледжа", "Серверная инфраструктура фитнес-клуба"),
("сетевой инфраструктуры колледжа", "сетевой инфраструктуры фитнес-клуба"),
("шапка колледжа", "шапка фитнес-клуба"),
("в масштабах колледжа", "в масштабах фитнес-клуба"),
("серверной частью колледжа", "серверной частью фитнес-клуба"),
("учебной части колледжа", "администрации фитнес-клуба"),
("учебная часть колледжа", "администрация фитнес-клуба"),
("учебный колледж", "спортивный фитнес-клуб"),
("IT Top College (учебная часть)", "Фитнес-клуб «Атлет Про» (отдел по работе с клиентами)"),
("Учебная часть", "Отдел по работе с клиентами"),
("учебной части", "отдела по работе с клиентами"),
("учебной частью", "отделом по работе с клиентами"),
("учебный план", "план тренировочных программ"),
("учебного плана, структуры групп", "сетки тренировок, состава спортивных групп"),
("учебного процесса колледжа", "тренировочного процесса фитнес-клуба"),
("учебного процесса", "тренировочного процесса"),
("учебный процесс", "тренировочный процесс"),
("об учебном процессе", "о тренировочном процессе"),
("учебного периода", "клубного сезона"),
("Учебный период: 34 недели в год (2 семестра)", "Активный период: 52 недели в год (круглогодично)"),
("начало/конец семестра", "начало/конец клубного сезона и акций"),
("в учебное время", "в часы работы фитнес-клуба"),
("реальных учебных данных", "реальных клиентских данных"),
("учебной информации", "спортивной информации"),
("персональным учебным данным", "персональным данным абонемента и тренировок"),
("цифровизации образования (ФП «Цифровая образовательная среда»)", "цифровизации спортивной индустрии (информатизация сферы спорта и фитнеса)"),
("студентов и родителей", "клиентов и персональных тренеров"),
("выбранной группы или преподавателя", "выбранной секции или тренера"),
("студентов колледжа", "клиентов фитнес-клуба"),
("рейтингов студентов", "рейтингов активности клиентов"),
("студентов", "клиентов"),
("студентам", "клиентам"),
("студента", "клиента"),
("студентах", "клиентах"),
("студентами", "клиентами"),
("студенты", "клиенты"),
("Студенты", "Клиенты"),
("студент", "клиент"),
("Студент", "Клиент"),
("преподавателей", "тренеров"),
("преподавателям", "тренерам"),
("преподавателя", "тренера"),
("преподаватели", "тренеры"),
("Преподаватели", "Тренеры"),
("преподаватель", "тренер"),
# 6. Восстановление защищённых строк титульного листа
("СТУДЕНТ_ГРУППЫ_ЗАЩИТА", "Студент группы __________"),
("СТУДЕНТ_ГРУППЫ_91_ЗАЩИТА", "Студент группы 9/1 РПО - 1/24"),
]
def apply_replacements(text):
for old, new in REPLACEMENTS:
text = text.replace(old, new)
text = re.sub(r'\b(тренировок)(?:\s+\1)+\b', r'\1', text)
return text
def update_stamp_image(img_bytes):
im = Image.open(io.BytesIO(img_bytes)).convert("RGBA")
draw = ImageDraw.Draw(im)
bg_color = (38, 38, 38, 255)
draw.rectangle([14, 73, 196, 132], fill=bg_color)
draw.rectangle([201, 73, 382, 132], fill=bg_color)
draw.rectangle([763, 73, 944, 132], fill=bg_color)
try:
font = ImageFont.truetype("timesbd.ttf", 27)
except Exception:
try:
font = ImageFont.truetype("/usr/share/fonts/truetype/liberation/LiberationSerif-Bold.ttf", 27)
except Exception:
font = ImageFont.load_default()
draw.text((25, 76), "К.Д.00001-01", fill=(255, 255, 255, 255), font=font)
draw.text((225, 76), "Калинин", fill=(255, 255, 255, 255), font=font)
draw.text((245, 104), "17.02.26", fill=(255, 255, 255, 255), font=font)
draw.text((787, 76), "Калинин", fill=(255, 255, 255, 255), font=font)
draw.text((807, 104), "17.02.26", fill=(255, 255, 255, 255), font=font)
out = io.BytesIO()
im.save(out, format="PNG")
return out.getvalue()
def process_xml_bytes(xml_bytes):
W_NS = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
root = ET.fromstring(xml_bytes)
for p in root.iter(W_NS + "p"):
t_nodes = list(p.iter(W_NS + "t"))
if not t_nodes:
continue
full_text = "".join(t.text or "" for t in t_nodes)
new_full = apply_replacements(full_text)
if new_full != full_text:
t_nodes[0].text = new_full
for t in t_nodes[1:]:
t.text = ""
return ET.tostring(root, encoding="utf-8", xml_declaration=True)
def convert_docx(src_path, dst_path):
with zipfile.ZipFile(src_path, "r") as zin:
with zipfile.ZipFile(dst_path, "w", zipfile.ZIP_DEFLATED) as zout:
for item in zin.infolist():
data = zin.read(item.filename)
if item.filename.startswith("word/") and item.filename.endswith(".xml"):
data = process_xml_bytes(data)
elif item.filename == "word/media/image1.png":
data = update_stamp_image(data)
zout.writestr(item, data)
if __name__ == "__main__":
for f in os.listdir("."):
if not f.endswith(".docx") or "Калинин" in f or "Денис" in f or "Масалимов" in f or f.startswith("~$"):
continue
if "Тех" in f:
convert_docx(f, "Тех задание Калинин Денис-v2.docx")
elif "Методика" in f:
convert_docx(f, "Методика_испытаний_Калинин_Денис1-v2.docx")
elif "Пояснительная" in f:
convert_docx(f, "Пояснительная_записка_Калинин_Денис-v2.docx")