Merge pull request #1 from ilyaoc/add-coursework-v2-template
feat: add coursework v2 template
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
## General Info
|
## General Info
|
||||||
|
|
||||||
This project contains two template functions and some utilities for writing NURE works. All functions include documentation comments inside them, so you can explore all possibilities using LSP.
|
This project contains template functions and some utilities for writing NURE works. All functions include documentation comments inside them, so you can explore all possibilities using LSP.
|
||||||
|
|
||||||
### Templates
|
### Templates
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@ This template:
|
|||||||
- Typesets the bibliography according to ДСТУ 3008:2015 using custom CSL style;
|
- Typesets the bibliography according to ДСТУ 3008:2015 using custom CSL style;
|
||||||
- Typesets the outline and appendices according to standard requirements.
|
- Typesets the outline and appendices according to standard requirements.
|
||||||
|
|
||||||
|
#### `coursework-v2` - New Coursework Variant
|
||||||
|
This template keeps the legacy coursework template intact while offering the newer title/task-page layout. See `template/default/coursework-v2.typ` for an example entrypoint.
|
||||||
|
|
||||||
### Utilities
|
### Utilities
|
||||||
- `nheading` - For unnumbered headings, such as "Introduction" and "Conclusion".
|
- `nheading` - For unnumbered headings, such as "Introduction" and "Conclusion".
|
||||||
|
|||||||
+79
-1
@@ -5,6 +5,9 @@
|
|||||||
#import "./style.typ"
|
#import "./style.typ"
|
||||||
#import "./utils.typ"
|
#import "./utils.typ"
|
||||||
|
|
||||||
|
#let dstu-table = style.dstu-table
|
||||||
|
#let hfill = utils.hfill
|
||||||
|
|
||||||
/// Coursework template for NURE
|
/// Coursework template for NURE
|
||||||
/// - university (str): University code, default "ХНУРЕ"
|
/// - university (str): University code, default "ХНУРЕ"
|
||||||
/// - subject (str): Subject short name
|
/// - subject (str): Subject short name
|
||||||
@@ -29,7 +32,8 @@
|
|||||||
bib-path: none,
|
bib-path: none,
|
||||||
appendices: (),
|
appendices: (),
|
||||||
) = {
|
) = {
|
||||||
set document(title: title, author: authors.map(c => c.name))
|
let doc-title = if type(title) == array { title.join(" ") } else { title }
|
||||||
|
set document(title: doc-title, author: authors.map(c => c.name))
|
||||||
|
|
||||||
show: style.dstu.with(skip: 1)
|
show: style.dstu.with(skip: 1)
|
||||||
|
|
||||||
@@ -56,6 +60,80 @@
|
|||||||
style.appendices(appendices)
|
style.appendices(appendices)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Alternative coursework template for NURE.
|
||||||
|
/// - university (str): University code, default "ХНУРЕ"
|
||||||
|
/// - title (str): Work title
|
||||||
|
/// - authors (array): List of author dictionaries
|
||||||
|
/// - mentors (array): List of mentor dictionaries
|
||||||
|
/// - task-list (dict): Task metadata
|
||||||
|
/// - calendar-plan (dict): Calendar plan table
|
||||||
|
/// - abstract (dict): Keywords and abstract text
|
||||||
|
/// - abstract-en (dict): Optional English keywords and abstract text
|
||||||
|
/// - bib-path (str): Path to bibliography file
|
||||||
|
/// - appendices (content): Appendix content
|
||||||
|
#let coursework-v2(
|
||||||
|
doc,
|
||||||
|
university: "ХНУРЕ",
|
||||||
|
title: none,
|
||||||
|
authors: (),
|
||||||
|
mentors: (),
|
||||||
|
task-list: (),
|
||||||
|
calendar-plan: (),
|
||||||
|
abstract: (),
|
||||||
|
abstract-en: none,
|
||||||
|
bib-path: none,
|
||||||
|
appendices: (),
|
||||||
|
faculty: "комп’ютерних наук",
|
||||||
|
education-level: "перший (бакалаврський)",
|
||||||
|
program-type: "освітньо-професійна",
|
||||||
|
program-name: none,
|
||||||
|
) = {
|
||||||
|
assert(authors.len() > 0, message: "At least one author required")
|
||||||
|
assert(mentors.len() > 0, message: "At least one mentor required")
|
||||||
|
|
||||||
|
let doc-title = if type(title) == array { title.join(" ") } else { title }
|
||||||
|
set document(title: doc-title, author: authors.map(c => c.name))
|
||||||
|
|
||||||
|
show: style.dstu.with(skip: 1)
|
||||||
|
|
||||||
|
let bib-count = state("citation-counter", ())
|
||||||
|
show cite: it => {
|
||||||
|
it
|
||||||
|
bib-count.update(((..c)) => (..c, it.key))
|
||||||
|
}
|
||||||
|
|
||||||
|
let abstract = if abstract-en != none {
|
||||||
|
abstract + (en: abstract-en)
|
||||||
|
} else {
|
||||||
|
abstract
|
||||||
|
}
|
||||||
|
|
||||||
|
tp.cw-v2.nure(
|
||||||
|
university,
|
||||||
|
title,
|
||||||
|
authors,
|
||||||
|
mentors,
|
||||||
|
task-list,
|
||||||
|
calendar-plan,
|
||||||
|
abstract,
|
||||||
|
bib-count,
|
||||||
|
faculty: faculty,
|
||||||
|
education-level: education-level,
|
||||||
|
program-type: program-type,
|
||||||
|
program-name: program-name,
|
||||||
|
)
|
||||||
|
|
||||||
|
doc
|
||||||
|
|
||||||
|
{
|
||||||
|
show regex("^\\d+\\."): it => [#it#h(0.5cm)]
|
||||||
|
show block: it => [#it.body#parbreak()]
|
||||||
|
bibliography(bib-path, title: [Перелік джерел посилання], style: "csl/dstu-3008-2015.csl", full: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
style.appendices(appendices)
|
||||||
|
}
|
||||||
|
|
||||||
/// Practice and Laboratory works template
|
/// Practice and Laboratory works template
|
||||||
/// - layout (str): "default", "minimal", or "complex"
|
/// - layout (str): "default", "minimal", or "complex"
|
||||||
/// - university (str): University code
|
/// - university (str): University code
|
||||||
|
|||||||
+123
@@ -8,6 +8,10 @@
|
|||||||
/// Ukrainian alphabet for DSTU 3008:2015 numbering
|
/// Ukrainian alphabet for DSTU 3008:2015 numbering
|
||||||
#let ukr-enum = "абвгдежиклмнпрстуфхцшщюя".clusters()
|
#let ukr-enum = "абвгдежиклмнпрстуфхцшщюя".clusters()
|
||||||
|
|
||||||
|
#let dstu-table-counter = counter("dstu-table")
|
||||||
|
#let dstu-table-appendix = state("dstu-table-appendix", none)
|
||||||
|
#let dstu-table-caption-gap = 0.65em
|
||||||
|
|
||||||
/// Helper for level 2/3 heading blocks
|
/// Helper for level 2/3 heading blocks
|
||||||
#let heading-block(it, num: auto) = {
|
#let heading-block(it, num: auto) = {
|
||||||
v(double-spacing, weak: true)
|
v(double-spacing, weak: true)
|
||||||
@@ -19,6 +23,123 @@
|
|||||||
v(double-spacing, weak: true)
|
v(double-spacing, weak: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#let _col-count(columns) = {
|
||||||
|
if type(columns) == int {
|
||||||
|
columns
|
||||||
|
} else if type(columns) == array {
|
||||||
|
columns.len()
|
||||||
|
} else {
|
||||||
|
panic("dstu-table: columns must be an int or array, e.g. 2 or (1fr, 3fr)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let _required(name, value) = {
|
||||||
|
if value == none {
|
||||||
|
panic("dstu-table: " + name + " is required")
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
#let dstu-table-label(it) = {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
align(left)[#it]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let dstu-table(
|
||||||
|
caption: none,
|
||||||
|
columns: none,
|
||||||
|
header: none,
|
||||||
|
..args,
|
||||||
|
) = {
|
||||||
|
let caption = _required("caption", caption)
|
||||||
|
let columns = _required("columns", columns)
|
||||||
|
let header = _required("header", header)
|
||||||
|
|
||||||
|
if type(header) != array {
|
||||||
|
panic("dstu-table: header must be an array, e.g. ([A], [B])")
|
||||||
|
}
|
||||||
|
|
||||||
|
dstu-table-counter.step()
|
||||||
|
|
||||||
|
let named = args.named()
|
||||||
|
let body = args.pos()
|
||||||
|
|
||||||
|
context {
|
||||||
|
let h = counter(heading).get()
|
||||||
|
let section = if h.len() > 0 { h.at(0) } else { 0 }
|
||||||
|
let n = dstu-table-counter.get().first()
|
||||||
|
let appendix = dstu-table-appendix.get()
|
||||||
|
let num = if appendix == none {
|
||||||
|
numbering("1.1", section, n)
|
||||||
|
} else {
|
||||||
|
upper(ukr-enum.at(appendix - 1)) + "." + str(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = "dstu-table-" + str(section) + "-" + str(n)
|
||||||
|
let start-marker = "start-" + id
|
||||||
|
let end-marker = "end-" + id
|
||||||
|
let cols = _col-count(columns)
|
||||||
|
|
||||||
|
v(double-spacing, weak: true)
|
||||||
|
|
||||||
|
{
|
||||||
|
set block(spacing: dstu-table-caption-gap)
|
||||||
|
|
||||||
|
block(sticky: true)[
|
||||||
|
#dstu-table-label[Таблиця #num -- #caption]
|
||||||
|
]
|
||||||
|
|
||||||
|
table(
|
||||||
|
columns: columns,
|
||||||
|
..named,
|
||||||
|
|
||||||
|
table.header(
|
||||||
|
repeat: true,
|
||||||
|
|
||||||
|
table.cell(
|
||||||
|
colspan: cols,
|
||||||
|
stroke: none,
|
||||||
|
inset: 0pt,
|
||||||
|
)[
|
||||||
|
#metadata(start-marker)
|
||||||
|
|
||||||
|
#context {
|
||||||
|
let starts = query(metadata.where(value: start-marker))
|
||||||
|
let ends = query(metadata.where(value: end-marker))
|
||||||
|
|
||||||
|
if starts.len() > 0 and ends.len() > 0 {
|
||||||
|
let start-page = starts.first().location().page()
|
||||||
|
let end-page = ends.first().location().page()
|
||||||
|
let current-page = here().page()
|
||||||
|
|
||||||
|
if current-page != start-page {
|
||||||
|
let label = if current-page == end-page {
|
||||||
|
[Кінець таблиці #num]
|
||||||
|
} else {
|
||||||
|
[Продовження таблиці #num]
|
||||||
|
}
|
||||||
|
|
||||||
|
pad(top: dstu-table-caption-gap, bottom: dstu-table-caption-gap)[
|
||||||
|
#dstu-table-label[#label]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
..header,
|
||||||
|
),
|
||||||
|
|
||||||
|
..body,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata(end-marker)
|
||||||
|
|
||||||
|
v(double-spacing, weak: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// DSTU 3008:2015 Style
|
/// DSTU 3008:2015 Style
|
||||||
#let dstu(
|
#let dstu(
|
||||||
it,
|
it,
|
||||||
@@ -118,6 +239,8 @@
|
|||||||
counter(figure.where(kind: raw)).update(0)
|
counter(figure.where(kind: raw)).update(0)
|
||||||
counter(figure.where(kind: image)).update(0)
|
counter(figure.where(kind: image)).update(0)
|
||||||
counter(figure.where(kind: table)).update(0)
|
counter(figure.where(kind: table)).update(0)
|
||||||
|
dstu-table-counter.update(0)
|
||||||
|
dstu-table-appendix.update(counter(heading).get().at(0))
|
||||||
|
|
||||||
set align(center)
|
set align(center)
|
||||||
set text(weight: "regular")
|
set text(weight: "regular")
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#import "nure.typ": *
|
||||||
@@ -0,0 +1,358 @@
|
|||||||
|
#import "../../shared.typ": universities
|
||||||
|
#import "../../helpers.typ": *
|
||||||
|
#import "../../style.typ": spacing
|
||||||
|
#import "../../utils.typ": bold, uline, filled-lines
|
||||||
|
|
||||||
|
#let note(content) = block(width: 100%, above: 5pt, below: 0pt)[
|
||||||
|
#set text(size: 10pt)
|
||||||
|
#set par(first-line-indent: 0pt, spacing: 0pt)
|
||||||
|
#align(center)[#content]
|
||||||
|
]
|
||||||
|
|
||||||
|
#let form-field(alignment: center, content) = box(
|
||||||
|
width: 100%,
|
||||||
|
stroke: (bottom: 0.5pt),
|
||||||
|
inset: (bottom: 1.5pt),
|
||||||
|
)[
|
||||||
|
#align(alignment)[#content]
|
||||||
|
]
|
||||||
|
|
||||||
|
#let label-line(label, value, caption: none, label-width: auto) = {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
if label-width == auto {
|
||||||
|
[#label #form-field(alignment: center, value)]
|
||||||
|
} else {
|
||||||
|
grid(
|
||||||
|
columns: (label-width, 1fr),
|
||||||
|
gutter: 0pt,
|
||||||
|
align: horizon,
|
||||||
|
label, form-field(alignment: center, value),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if caption != none {
|
||||||
|
note(caption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let inline-field(value) = form-field(alignment: center, value)
|
||||||
|
|
||||||
|
#let inline-label-line(label, value) = {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
block(width: 100%, below: 0pt)[
|
||||||
|
#label #uline(align: center, value)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let task-head-fields(fields) = {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
let cells = ()
|
||||||
|
for (label, value) in fields {
|
||||||
|
if type(value) == array {
|
||||||
|
for (i, line) in value.enumerate() {
|
||||||
|
cells.push(if i == 0 { label } else { [] })
|
||||||
|
cells.push(inline-field(line))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cells.push(label)
|
||||||
|
cells.push(inline-field(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid(
|
||||||
|
columns: (auto, 1fr),
|
||||||
|
gutter: 0pt,
|
||||||
|
row-gutter: 0.65em,
|
||||||
|
align: top,
|
||||||
|
..cells,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let task-num(n) = box(str(n) + ".")
|
||||||
|
|
||||||
|
#let title-field(value) = {
|
||||||
|
uline(align: center, filled-lines(value))
|
||||||
|
uline(align: center, [])
|
||||||
|
note[(тема)]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let nure(
|
||||||
|
university,
|
||||||
|
title,
|
||||||
|
authors,
|
||||||
|
mentors,
|
||||||
|
task-list,
|
||||||
|
calendar-plan,
|
||||||
|
abstract,
|
||||||
|
bib-count,
|
||||||
|
faculty: "комп’ютерних наук",
|
||||||
|
education-level: "перший (бакалаврський)",
|
||||||
|
program-type: "освітньо-професійна",
|
||||||
|
program-name: none,
|
||||||
|
) = {
|
||||||
|
let author = authors.first()
|
||||||
|
let head-mentor = mentors.first()
|
||||||
|
|
||||||
|
let uni = universities.at(university)
|
||||||
|
let edu-prog = uni.edu-programs.at(author.edu-program)
|
||||||
|
let program-name = if program-name == none {
|
||||||
|
edu-prog.at("program-name", default: edu-prog.name-long)
|
||||||
|
} else {
|
||||||
|
program-name
|
||||||
|
}
|
||||||
|
let group-name = if str(author.group).starts-with(author.edu-program) {
|
||||||
|
str(author.group)
|
||||||
|
} else {
|
||||||
|
author.edu-program + "-" + str(author.group)
|
||||||
|
}
|
||||||
|
let executor-label = if author.gender == "f" or author.gender == "female" or author.gender == "ж" {
|
||||||
|
"Виконала:"
|
||||||
|
} else {
|
||||||
|
"Виконав:"
|
||||||
|
}
|
||||||
|
let author-display-name = author.at("display-name", default: author.name)
|
||||||
|
let author-full-name-dat = author.at("full-name-dat", default: author.full-name-gen)
|
||||||
|
let mentor-display-name = head-mentor.at("display-name", default: head-mentor.name)
|
||||||
|
let mentor-degree = head-mentor.at("degree", default: "")
|
||||||
|
|
||||||
|
[
|
||||||
|
#set par(first-line-indent: 0pt, justify: false, leading: 0.45em)
|
||||||
|
|
||||||
|
#set text(size: 14pt)
|
||||||
|
#set align(center)
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ\
|
||||||
|
#uni.name
|
||||||
|
|
||||||
|
#v(0.7em)
|
||||||
|
|
||||||
|
#set align(left)
|
||||||
|
#inline-label-line(
|
||||||
|
[Факультет],
|
||||||
|
faculty,
|
||||||
|
)
|
||||||
|
#note([(повна назва)])
|
||||||
|
|
||||||
|
#v(0.8em)
|
||||||
|
#inline-label-line([Кафедра], edu-prog.department-gen)
|
||||||
|
#note([(повна назва)])
|
||||||
|
|
||||||
|
#v(1.8em)
|
||||||
|
|
||||||
|
#set align(center)
|
||||||
|
#text(size: 20pt, weight: "bold")[КОМПЛЕКСНИЙ КУРСОВИЙ ПРОЄКТ]\
|
||||||
|
#text(size: 20pt, weight: "bold")[Пояснювальна записка]
|
||||||
|
|
||||||
|
#v(0.9em)
|
||||||
|
|
||||||
|
#set align(left)
|
||||||
|
#label-line([рівень вищої освіти], education-level, label-width: 120pt)
|
||||||
|
|
||||||
|
#v(1.0em)
|
||||||
|
#title-field(title)
|
||||||
|
|
||||||
|
#v(3em)
|
||||||
|
|
||||||
|
#grid(
|
||||||
|
columns: (0.36fr, 0.64fr),
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
#executor-label\
|
||||||
|
здобувач #underline([#author.course]) курсу, групи #underline(group-name)\
|
||||||
|
#uline(align: center, author-display-name)
|
||||||
|
#note[(Власне ім’я, ПРІЗВИЩЕ)]
|
||||||
|
|
||||||
|
#v(0.2em)
|
||||||
|
#inline-label-line([Спеціальність], [#edu-prog.code -- #edu-prog.name-long])
|
||||||
|
#note[(код і повна назва спеціальності)]
|
||||||
|
#inline-label-line([Тип програми], program-type)
|
||||||
|
#inline-label-line([Освітня програма], program-name)
|
||||||
|
#note[(повна назва освітньої програми)]
|
||||||
|
|
||||||
|
#v(0.3em)
|
||||||
|
#inline-label-line([Керівник], [#mentor-degree #mentor-display-name])
|
||||||
|
#note[(посада, Власне ім’я, ПРІЗВИЩЕ)]
|
||||||
|
|
||||||
|
#v(0.3em)
|
||||||
|
#pad(left: 75pt)[
|
||||||
|
#set par(first-line-indent: 0pt)
|
||||||
|
Члени комісії (#text(size: 10pt)[Власне ім’я, ПРІЗВИЩЕ, підпис])
|
||||||
|
#v(0.55em)
|
||||||
|
#line(length: 100%, stroke: 0.5pt)
|
||||||
|
#v(0.55em)
|
||||||
|
#line(length: 100%, stroke: 0.5pt)
|
||||||
|
#v(0.55em)
|
||||||
|
#line(length: 100%, stroke: 0.5pt)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
#set align(center)
|
||||||
|
#task-list.done-date.display("[year]") р.
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
]
|
||||||
|
|
||||||
|
[
|
||||||
|
#set par(first-line-indent: 0pt, justify: false)
|
||||||
|
#align(center)[#uni.name]
|
||||||
|
|
||||||
|
#v(1.1em)
|
||||||
|
#task-head-fields((
|
||||||
|
(
|
||||||
|
[Факультет],
|
||||||
|
(
|
||||||
|
faculty,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
([Кафедра], edu-prog.department-gen),
|
||||||
|
([Рівень вищої освіти], education-level),
|
||||||
|
([Спеціальність], [#edu-prog.code -- #edu-prog.name-long]),
|
||||||
|
([Тип програми], program-type),
|
||||||
|
([Освітня програма], program-name),
|
||||||
|
))
|
||||||
|
#note[(шифр і назва)]
|
||||||
|
|
||||||
|
#v(1.7em)
|
||||||
|
#grid(
|
||||||
|
columns: (1.1fr, 1.1fr, 1.1fr, 1.7fr, 1.3fr, 1.1fr),
|
||||||
|
gutter: 0pt,
|
||||||
|
align: center + horizon,
|
||||||
|
[Курс], uline(author.course), [Група], uline(group-name), [Семестр], uline(author.semester),
|
||||||
|
)
|
||||||
|
|
||||||
|
#v(2.6em)
|
||||||
|
|
||||||
|
#align(center)[
|
||||||
|
#bold[ЗАВДАННЯ]\
|
||||||
|
#text(style: "italic", weight: "bold")[на курсовий проєкт (роботу) студента]
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1.0em)
|
||||||
|
|
||||||
|
#label-line([здобувачеві], author-full-name-dat, caption: [(прізвище, ім’я, по батькові)], label-width: 95pt)
|
||||||
|
|
||||||
|
#v(1.0em)
|
||||||
|
|
||||||
|
#task-num(1) Тема роботи #uline(align: left, filled-lines(title))
|
||||||
|
|
||||||
|
#v(0.4em)
|
||||||
|
#task-num(2) Термін здачі студентом закінченої роботи
|
||||||
|
“#underline(task-list.done-date.display("[day]"))” #underline(month-gen(task-list.done-date.month())) #task-list.done-date.display("[year]")р.
|
||||||
|
|
||||||
|
#v(0.4em)
|
||||||
|
#task-num(3) Вихідні дані до проєкту #uline(align: left, filled-lines(task-list.at("source", default: [])))
|
||||||
|
#v(0.4em)
|
||||||
|
#uline(align: left, [])
|
||||||
|
|
||||||
|
#v(0.4em)
|
||||||
|
#task-num(4) Перелік питань, що потрібно опрацювати в роботі\
|
||||||
|
#uline(align: left, filled-lines(task-list.at("content", default: [])))
|
||||||
|
#v(0.4em)
|
||||||
|
#uline(align: left, [])
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
]
|
||||||
|
|
||||||
|
[
|
||||||
|
#align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
||||||
|
#set par(first-line-indent: 0pt)
|
||||||
|
|
||||||
|
#v(1.4em)
|
||||||
|
|
||||||
|
#calendar-plan.plan-table
|
||||||
|
|
||||||
|
#v(5.0em)
|
||||||
|
|
||||||
|
Дата видачі завдання “#underline(task-list.initial-date.display("[day]"))” #underline(month-gen(task-list.initial-date.month())) #task-list.initial-date.display("[year]")р.
|
||||||
|
|
||||||
|
#v(1.4em)
|
||||||
|
|
||||||
|
Здобувач #uline(align: center, [])
|
||||||
|
#note[(підпис)]
|
||||||
|
|
||||||
|
#v(1.4em)
|
||||||
|
|
||||||
|
Керівник роботи #uline(align: center, []) #h(1cm) #underline[#mentor-degree #mentor-display-name]
|
||||||
|
#note[(підпис) #h(4.5cm) (посада, Власне ім’я, ПРІЗВИЩЕ)]
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
]
|
||||||
|
|
||||||
|
[
|
||||||
|
#let header = if abstract.at("en", default: none) != none {
|
||||||
|
bold[РЕФЕРАТ / ABSTRACT]
|
||||||
|
} else {
|
||||||
|
bold[РЕФЕРАТ]
|
||||||
|
}
|
||||||
|
#align(center, header) \
|
||||||
|
|
||||||
|
#context [
|
||||||
|
#let pages = counter(page).final().at(0)
|
||||||
|
#let images = query(figure.where(kind: image)).len()
|
||||||
|
#let tables = query(figure.where(kind: table)).len()
|
||||||
|
#let bibs = bib-count.final().dedup().len()
|
||||||
|
|
||||||
|
#let counters = ()
|
||||||
|
#if pages != 0 { counters.push[#pages с.] }
|
||||||
|
#if tables != 0 { counters.push[#tables табл.] }
|
||||||
|
#if images != 0 { counters.push[#images рис.] }
|
||||||
|
#if bibs != 0 { counters.push[#bibs джерел] }
|
||||||
|
|
||||||
|
Пояснювальна записка містить: #counters.join(", ").
|
||||||
|
]
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#(
|
||||||
|
abstract
|
||||||
|
.keywords
|
||||||
|
.map(upper)
|
||||||
|
.sorted(by: (a, b) => {
|
||||||
|
if is-cyr(a) != is-cyr(b) { is-cyr(a) } else { a < b }
|
||||||
|
})
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#abstract.text
|
||||||
|
|
||||||
|
#if abstract.at("en", default: none) != none [
|
||||||
|
\
|
||||||
|
#(abstract.en.keywords.map(upper).join(", "))
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#abstract.en.text
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
{
|
||||||
|
show outline.entry: it => {
|
||||||
|
let el = it.element
|
||||||
|
|
||||||
|
if el.func() == heading and el.supplement == [Додаток] {
|
||||||
|
if el.level > 1 {
|
||||||
|
none
|
||||||
|
} else {
|
||||||
|
block(width: 100%)[
|
||||||
|
#link(el.location())[
|
||||||
|
ДОДАТОК #it.prefix()#h(0.5em)#it.inner()
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outline(
|
||||||
|
title: [
|
||||||
|
ЗМІСТ
|
||||||
|
#v(spacing * 2, weak: true)
|
||||||
|
],
|
||||||
|
depth: 2,
|
||||||
|
indent: auto,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
#import "pz-lb/main.typ" as pz-lb
|
#import "pz-lb/main.typ" as pz-lb
|
||||||
#import "coursework/main.typ" as cw
|
#import "coursework/main.typ" as cw
|
||||||
|
#import "coursework-v2/main.typ" as cw-v2
|
||||||
|
|||||||
@@ -7,6 +7,13 @@
|
|||||||
/// fill horizontal space with a filled box
|
/// fill horizontal space with a filled box
|
||||||
#let hfill(width) = box(width: width, repeat(" ")) // HAIR SPACE (U+200A)
|
#let hfill(width) = box(width: width, repeat(" ")) // HAIR SPACE (U+200A)
|
||||||
|
|
||||||
|
/// convert an array of lines into filled lines for underlined task fields
|
||||||
|
#let filled-lines(content) = if type(content) == array {
|
||||||
|
content.map(line => [#line #hfill(1fr)]).join(linebreak())
|
||||||
|
} else {
|
||||||
|
content
|
||||||
|
}
|
||||||
|
|
||||||
/// underlined cell with centered content by default
|
/// underlined cell with centered content by default
|
||||||
#let uline(align: center, content) = underline[
|
#let uline(align: center, content) = underline[
|
||||||
#if align != left { hfill(1fr) }
|
#if align != left { hfill(1fr) }
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#import "@local/nure:0.1.1": *
|
||||||
|
#import style: spacing
|
||||||
|
|
||||||
|
#let authors = (
|
||||||
|
(
|
||||||
|
name: "Сокорчук І. П.",
|
||||||
|
display-name: "Ігор СОКОРЧУК",
|
||||||
|
full-name-gen: "Сокорчука Ігоря Петровича",
|
||||||
|
full-name-dat: "Сокорчуку Ігорю Петровичу",
|
||||||
|
edu-program: "ПЗПІ",
|
||||||
|
group: "23-3",
|
||||||
|
gender: "m",
|
||||||
|
course: 3,
|
||||||
|
semester: 6,
|
||||||
|
variant: 13,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let mentors = (
|
||||||
|
(name: "Сокорчук І. П.", display-name: "Ігор СОКОРЧУК", degree: "ст.викл. кафедри ПІ"),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let task-list = (
|
||||||
|
done-date: datetime(year: 2026, month: 12, day: 27),
|
||||||
|
initial-date: datetime(year: 2026, month: 9, day: 15),
|
||||||
|
source: (
|
||||||
|
[Узагальнити модель предметної області,],
|
||||||
|
[визначити основні сутності та зв'язки між ними.],
|
||||||
|
[Підготувати демонстраційний набір технологій для шаблону.],
|
||||||
|
),
|
||||||
|
content: (
|
||||||
|
[Опис предметної галузі, формування вимог,],
|
||||||
|
[архітектурне проєктування, тестування та],
|
||||||
|
[перевірка верстки пояснювальної записки.],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let calendar-plan = (
|
||||||
|
plan-table: table(
|
||||||
|
columns: (0.7fr, 5.8fr, 2.5fr, 1.6fr),
|
||||||
|
align: (center, left, center, center),
|
||||||
|
[№], [Назва етапів роботи], [Термін виконання етапів роботи], [Примітка],
|
||||||
|
[1], [Аналіз предметної галузі], [], [виконано],
|
||||||
|
[2], [Розробка постановки задачі], [], [виконано],
|
||||||
|
[3], [Проєктування ПЗ], [], [виконано],
|
||||||
|
[4], [Програмна реалізація], [], [виконано],
|
||||||
|
[5], [Аналіз результатів], [], [виконано],
|
||||||
|
[6], [Підготовка пояснювальної записки.], [], [виконано],
|
||||||
|
[7], [Перевірка на наявність ознак академічного плагіату], [], [виконано],
|
||||||
|
[8], [Захист роботи], [], [виконано],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let abstract = (
|
||||||
|
keywords: (
|
||||||
|
"веб-застосунок",
|
||||||
|
"інформаційна система",
|
||||||
|
"курсова робота",
|
||||||
|
"програмна інженерія",
|
||||||
|
"тестовий приклад",
|
||||||
|
),
|
||||||
|
text: [
|
||||||
|
Мета даної роботи -- продемонструвати оформлення пояснювальної записки
|
||||||
|
для комплексного курсового проєкту з використанням нового варіанта шаблону.
|
||||||
|
Приклад містить узагальнену тему, типові сторінки завдання, календарного плану,
|
||||||
|
реферату, змісту, переліку джерел посилання та додатків.
|
||||||
|
|
||||||
|
У роботі наведено умовну структуру програмної системи, що може бути
|
||||||
|
адаптована під конкретну предметну область. Основний акцент зроблено на
|
||||||
|
перевірці полів титульної сторінки, сторінки завдання, службових підписів,
|
||||||
|
нумерації розділів і коректної роботи додатків.
|
||||||
|
|
||||||
|
Результатом є демонстраційний документ, який показує очікуване використання
|
||||||
|
шаблону без прив'язки до реального студента, викладача або завершеної роботи.
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
#let abstract_en = (
|
||||||
|
keywords: (
|
||||||
|
"WEB APPLICATION",
|
||||||
|
"INFORMATION SYSTEM",
|
||||||
|
"COURSEWORK",
|
||||||
|
"SOFTWARE ENGINEERING",
|
||||||
|
"DEMO SAMPLE",
|
||||||
|
),
|
||||||
|
text: [
|
||||||
|
The purpose of this work is to demonstrate the formatting of a coursework
|
||||||
|
explanatory note using the new template variant.
|
||||||
|
|
||||||
|
The sample contains a generalized topic, typical pages for the assignment,
|
||||||
|
calendar plan, abstract, contents, bibliography, and appendices.
|
||||||
|
|
||||||
|
The work presents an illustrative structure of a software system that can be
|
||||||
|
adapted to a specific subject area. The main focus is on checking title-page
|
||||||
|
fields, assignment-page fields, signature blocks, section numbering, and
|
||||||
|
appendix handling.
|
||||||
|
|
||||||
|
The result is a demonstration document that shows the expected template usage
|
||||||
|
without being tied to a real student, supervisor, or completed project.
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
#let appendices = [
|
||||||
|
= Приклад звіту 1
|
||||||
|
#v(-spacing)
|
||||||
|
== Частина 1
|
||||||
|
#lorem(100)
|
||||||
|
== Частина 2
|
||||||
|
#lorem(200)
|
||||||
|
|
||||||
|
= Приклад звіту 2
|
||||||
|
#lorem(200)
|
||||||
|
|
||||||
|
= Приклад звіту 3
|
||||||
|
#lorem(200)
|
||||||
|
]
|
||||||
|
|
||||||
|
#show: coursework-v2.with(
|
||||||
|
title: (
|
||||||
|
"Демонстраційна інформаційна система для комплексного ",
|
||||||
|
"курсового проєкту",
|
||||||
|
),
|
||||||
|
authors: authors,
|
||||||
|
mentors: mentors,
|
||||||
|
task-list: task-list,
|
||||||
|
calendar-plan: calendar-plan,
|
||||||
|
abstract: abstract,
|
||||||
|
abstract-en: abstract_en,
|
||||||
|
bib-path: bytes(read("bibl.yml")),
|
||||||
|
appendices: appendices,
|
||||||
|
)
|
||||||
|
|
||||||
|
= Моделювання
|
||||||
|
#lorem(250)
|
||||||
|
|
||||||
|
= Імплементація
|
||||||
|
#v(-spacing)
|
||||||
|
== Підготовка
|
||||||
|
#lorem(200)
|
||||||
|
== Процес
|
||||||
|
#lorem(500)
|
||||||
|
|
||||||
|
= Тестування
|
||||||
|
#lorem(300)
|
||||||
Reference in New Issue
Block a user