[ADD] титульный лист по бланку отчёта об учебной практике
This commit is contained in:
@@ -96,6 +96,37 @@ PREAMBLE = r"""\documentclass[a4paper, 14pt]{extarticle}
|
||||
\end{tabular}%
|
||||
}
|
||||
|
||||
\newcommand{\ptpfieldw}[4][4.5cm]{%
|
||||
\par\noindent
|
||||
\makebox[#1][l]{#2}%
|
||||
\begin{tabular}[t]{@{}c@{}}%
|
||||
\makebox[#4][c]{#3} \\[-1.05em]%
|
||||
\rule{#4}{0.4pt}%
|
||||
\end{tabular}\par}
|
||||
|
||||
\newcommand{\ptpfield}[3][4.5cm]{%
|
||||
\ptpfieldw[#1]{#2}{#3}{\dimexpr\textwidth-#1\relax}}
|
||||
|
||||
\newcommand{\ptpfieldnote}[4][4.5cm]{%
|
||||
\ptpfield[#1]{#2}{#3}%
|
||||
\par\vspace{-0.7em}%
|
||||
\hspace*{#1}\makebox[\dimexpr\textwidth-#1\relax][c]{\footnotesize\itshape #4}\par}
|
||||
|
||||
\newcommand{\ptpfieldpar}[3][4.5cm]{%
|
||||
\par\noindent
|
||||
\makebox[#1][l]{#2}%
|
||||
\begin{tabular}[t]{@{}c@{}}%
|
||||
\parbox{\dimexpr\textwidth-#1\relax}{\centering #3} \\[-0.55em]%
|
||||
\rule{\dimexpr\textwidth-#1\relax}{0.4pt}%
|
||||
\end{tabular}\par}
|
||||
|
||||
\newcommand{\ptpsig}[3]{%
|
||||
\par\noindent
|
||||
\begin{tabularx}{\textwidth}{@{}l X c c@{}}%
|
||||
#1 & & \sigline[4.2cm]{}{\itshape подпись, дата}
|
||||
& \sigline[4.2cm]{#2}{\itshape #3} \\%
|
||||
\end{tabularx}\par}
|
||||
|
||||
\begin{document}"""
|
||||
|
||||
END_DOCUMENT = r"\end{document}" + "\n"
|
||||
|
||||
@@ -36,4 +36,10 @@ def ministry_lines(fm: dict[str, str]) -> str:
|
||||
f"({get('вуз_статус')})>>",
|
||||
f"({get('вуз_аббревиатура')})",
|
||||
]
|
||||
return "\n".join(f"\\vspace*{{-0.7ex}}\n\\centerline{{{line}}}" for line in lines)
|
||||
# Первая строка без отрицательного отступа: иначе она вылезает за верхнюю
|
||||
# границу рамки, в которую шапку заключает бланк отчёта.
|
||||
head = f"\\centerline{{{lines[0]}}}"
|
||||
rest = "\n".join(
|
||||
f"\\vspace*{{-0.7ex}}\n\\centerline{{{line}}}" for line in lines[1:]
|
||||
)
|
||||
return f"{head}\n{rest}"
|
||||
|
||||
@@ -1,5 +1,97 @@
|
||||
"""Титульный лист по бланку «ОТЧЁТ ПО УЧЕБНОЙ ПРАКТИКЕ» кафедры ИУ9."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from md2gost.latex.titlepages._common import field, ministry_lines
|
||||
|
||||
|
||||
def render(fm: dict[str, str]) -> str:
|
||||
raise NotImplementedError
|
||||
faculty = field(fm, "факультет")
|
||||
department = field(fm, "кафедра")
|
||||
student_short = field(fm, "студент")
|
||||
student_full = field(fm, "студент_полностью") or student_short
|
||||
group = field(fm, "группа")
|
||||
practice = field(fm, "тип_практики")
|
||||
company = field(fm, "предприятие")
|
||||
team = field(fm, "команда")
|
||||
repo = field(fm, "хранилище")
|
||||
advisor = field(fm, "руководитель")
|
||||
year = field(fm, "год", "2026")
|
||||
|
||||
team_line = f"{team} (хранилище {repo})" if repo else team
|
||||
|
||||
return (
|
||||
"\\begin{titlepage}\n"
|
||||
"\\thispagestyle{empty}\n"
|
||||
"\n"
|
||||
"% --- Шапка в рамке с разделителем, как в бланке ---\n"
|
||||
"\\vspace*{-45pt}\n"
|
||||
"\\noindent\\begin{tabular}"
|
||||
"{|@{\\hspace{4pt}}c@{\\hspace{4pt}}|@{\\hspace{4pt}}c@{\\hspace{4pt}}|}\n"
|
||||
"\\hline\n"
|
||||
"\\begin{minipage}{0.16\\textwidth}\\centering\\vspace{3pt}\n"
|
||||
"\\includegraphics[width=0.92\\textwidth]{emblem}\n"
|
||||
"\\vspace{3pt}\\end{minipage}\n"
|
||||
"&\n"
|
||||
"\\begin{minipage}{0.775\\textwidth}\\small\\bfseries\n"
|
||||
"\\vspace*{2pt}\n"
|
||||
f"{ministry_lines(fm)}\n"
|
||||
"\\vspace*{0.5ex}\n"
|
||||
"\\end{minipage} \\\\\n"
|
||||
"\\hline\n"
|
||||
"\\end{tabular}\n"
|
||||
"\n"
|
||||
"% --- Полосы ---\n"
|
||||
"\\vspace{6pt}\n"
|
||||
"\\noindent\\rule{\\textwidth}{2.3pt}\n"
|
||||
"\n"
|
||||
"\\vspace*{-18pt}\n"
|
||||
"\\noindent\\rule{\\textwidth}{0.4pt}\n"
|
||||
"\n"
|
||||
"% --- Факультет и кафедра ---\n"
|
||||
"\\vspace{2.5ex}\n"
|
||||
f"\\ptpfield[2.8cm]{{ФАКУЛЬТЕТ}}{{{faculty}}}\n"
|
||||
"\n"
|
||||
"\\vspace{1.5ex}\n"
|
||||
f"\\ptpfield[2.8cm]{{КАФЕДРА}}{{{department}}}\n"
|
||||
"\n"
|
||||
"% --- Заголовок ---\n"
|
||||
"\\vspace{3.5em}\n"
|
||||
"\\begin{center}\n"
|
||||
"{\\Large\\bfseries\\underline{ОТЧЁТ ПО УЧЕБНОЙ ПРАКТИКЕ}}\n"
|
||||
"\\end{center}\n"
|
||||
"\n"
|
||||
"% --- Поля ---\n"
|
||||
"\\vspace{2.5em}\n"
|
||||
f"\\ptpfieldnote[2.4cm]{{Студент}}{{{student_full}}}{{фамилия, имя, отчество}}\n"
|
||||
"\n"
|
||||
"\\vspace{1.8ex}\n"
|
||||
f"\\ptpfieldw[2.4cm]{{Группа}}{{{group}}}{{5cm}}\n"
|
||||
"\n"
|
||||
"\\vspace{1.8ex}\n"
|
||||
f"\\ptpfield[4.6cm]{{Тип практики}}{{{practice}}}\n"
|
||||
"\n"
|
||||
"\\vspace{1.8ex}\n"
|
||||
f"\\ptpfield[4.6cm]{{Название предприятия}}{{{company}}}\n"
|
||||
"\n"
|
||||
"\\vspace{1.8ex}\n"
|
||||
f"\\ptpfieldpar[2.4cm]{{Команда}}{{{team_line}}}\n"
|
||||
"\n"
|
||||
"% --- Подписи ---\n"
|
||||
"\\vfill\n"
|
||||
f"\\ptpsig{{Студент}}{{{student_short}}}{{фамилия, и.о.}}\n"
|
||||
"\n"
|
||||
"\\vspace{2em}\n"
|
||||
f"\\ptpsig{{Руководитель практики}}{{{advisor}}}{{фамилия, и.о.}}\n"
|
||||
"\n"
|
||||
"% --- Оценка ---\n"
|
||||
"\\vspace{2em}\n"
|
||||
"\\noindent Оценка \\rule{0.5\\textwidth}{0.4pt}\n"
|
||||
"\n"
|
||||
"\\vfill\n"
|
||||
"\\begin{center}\n"
|
||||
f"\\textsl{{{year} г.}}\n"
|
||||
"\\end{center}\n"
|
||||
"\n"
|
||||
"\\end{titlepage}"
|
||||
)
|
||||
|
||||
@@ -163,3 +163,71 @@ def test_titlepage_registry_lists_three_layouts() -> None:
|
||||
def test_titlepage_unknown_name_raises() -> None:
|
||||
with pytest.raises(ValueError, match="ptp-report"):
|
||||
render_fm("титульник: несуществующий\n")
|
||||
|
||||
|
||||
PTP_REPORT_FM = (
|
||||
"титульник: ptp-report\n"
|
||||
"факультет: Информатика и системы управления (ИУ)\n"
|
||||
"кафедра: Теоретическая информатика и компьютерные технологии (ИУ9)\n"
|
||||
"студент: И. И. Камалетдинов\n"
|
||||
"студент_полностью: Камалетдинов Ильяс Илнарович\n"
|
||||
"группа: ИУ9-22Б\n"
|
||||
"тип_практики: проектно-технологическая практика\n"
|
||||
"предприятие: МГТУ имени Н. Э. Баумана\n"
|
||||
"команда: Система мониторинга радиоэфира\n"
|
||||
"хранилище: https://monitor.yss.su/IU9/radio-serv\n"
|
||||
"руководитель: Д. П. Посевин\n"
|
||||
"год: 2026\n"
|
||||
)
|
||||
|
||||
|
||||
def test_ptp_report_has_blank_headings() -> None:
|
||||
tex = render_fm(PTP_REPORT_FM)
|
||||
for heading in (
|
||||
"ОТЧЁТ ПО УЧЕБНОЙ ПРАКТИКЕ",
|
||||
"Тип практики",
|
||||
"Название предприятия",
|
||||
"Команда",
|
||||
"Оценка",
|
||||
"Руководитель практики",
|
||||
):
|
||||
assert heading in tex
|
||||
|
||||
|
||||
def test_ptp_report_fills_all_fields() -> None:
|
||||
tex = render_fm(PTP_REPORT_FM)
|
||||
for value in (
|
||||
"Камалетдинов Ильяс Илнарович",
|
||||
"И. И. Камалетдинов",
|
||||
"ИУ9-22Б",
|
||||
"проектно-технологическая практика",
|
||||
"МГТУ имени Н. Э. Баумана",
|
||||
"Д. П. Посевин",
|
||||
"2026",
|
||||
):
|
||||
assert value in tex
|
||||
|
||||
|
||||
def test_ptp_report_team_line_includes_repository() -> None:
|
||||
tex = render_fm(PTP_REPORT_FM)
|
||||
assert "Система мониторинга радиоэфира (хранилище" in tex
|
||||
assert "monitor.yss.su/IU9/radio-serv" in tex
|
||||
|
||||
|
||||
def test_ptp_report_team_line_without_repository() -> None:
|
||||
fm = PTP_REPORT_FM.replace(
|
||||
"хранилище: https://monitor.yss.su/IU9/radio-serv\n", ""
|
||||
)
|
||||
tex = render_fm(fm)
|
||||
assert "хранилище" not in tex
|
||||
|
||||
|
||||
def test_ptp_report_has_no_hardcoded_names() -> None:
|
||||
"""Имена, группы и предприятия приходят только из front matter."""
|
||||
import inspect
|
||||
|
||||
from md2gost.latex.titlepages import ptp_report
|
||||
|
||||
source = inspect.getsource(ptp_report)
|
||||
for forbidden in ("Посевин", "Коновалов", "Камалетдинов", "ИУ9-2"):
|
||||
assert forbidden not in source
|
||||
|
||||
Reference in New Issue
Block a user