// Academic aliases {{{1 #let universities = yaml("config/universities.yaml") #import "/src/helpers.typ": * #import "/src/style.typ": * // Coursework template {{{1 /// DSTU 3008:2015 Template for NURE /// -> content /// - doc (content): Content to apply the template to. /// - title (str): Title of the document. /// - subject (str): Subject short name. /// - authors ((name: str, full_name_gen: str, variant: int, course: int, semester: int, group: str, gender: str),): List of authors. /// - mentors ((name: str, degree: str),): List of mentors. /// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object. /// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object. /// - abstract (keywords: (str, ), text: (content | str)): Abstract object. /// - bib_path path: Path to the bibliography yaml file. /// - appendices (content): Content with appendices. #let coursework( doc, university: "ХНУРЕ", subject: none, title: none, authors: (), mentors: (), task_list: (), calendar_plan: (), abstract: (), bib_path: none, appendices: (), ) = { set document(title: title, author: authors.map(c => c.name)) show: dstu-style.with(skip: 1) let bib-count = state("citation-counter", ()) show cite: it => { it bib-count.update(((..c)) => (..c, it.key)) } show bibliography: it => { set text(size: 0pt) it } let author = authors.first() let head_mentor = mentors.first() let uni = universities.at(university) let edu_prog = uni.edu_programs.at(author.edu_program) // page 1 {{{2 [ #set align(center) МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ\ #upper(uni.name) \ Кафедра #edu_prog.department_gen \ ПОЯСНЮВАЛЬНА ЗАПИСКА\ ДО КУРСОВОЇ РОБОТИ\ з дисципліни: "#uni.subjects.at(subject, default: subject)"\ Тема роботи: "#title" \ \ \ #columns(2, gutter: 4cm)[ #set align(left) #set par(first-line-indent: 0pt) #gender-form("author", gender: gender-get(author)) ст. гр. #author.edu_program\-#author.group \ Керівник:\ #head_mentor.degree \ Робота захищена на оцінку \ Комісія:\ #for m in mentors { [#m.degree\ ] } #colbreak() #set align(left) #author.name \ \ #head_mentor.name \ #underline(" " * 35) \ \ #for m in mentors { [#m.name\ ] } ] #v(1fr) Харків -- #task_list.done_date.display("[year]") #pagebreak() ] // page 2 {{{2 { uline[#uni.name] linebreak() linebreak() grid( columns: (100pt, 1fr), bold[ Кафедра Дисципліна Спеціальність ], { uline(align: left, edu_prog.department_gen) linebreak() uline(align: left, uni.subjects.at(subject, default: subject)) linebreak() uline(align: left, [#edu_prog.code #edu_prog.name_long]) }, ) grid( columns: (1fr, 1fr, 1fr), gutter: 0.3fr, [#bold[Курс] #uline(author.course)], [#bold[Група] #uline([#author.edu_program\-#author.group])], [#bold[Семестр] #uline(author.semester)], ) linebreak() linebreak() linebreak() align(center, bold[ЗАВДАННЯ \ на курсову роботу студента]) linebreak() uline(align: left)[_#author.full_name_gen _] linebreak() linebreak() bold[\1. Тема роботи:] uline[#title.] linebreak() { bold[\2. Строк здачі закінченої роботи:] uline(task_list.done_date.display("[day].[month].[year]")) hfill(10fr) } linebreak() bold[\3. Вихідні дані для роботи:] uline(task_list.source) linebreak() bold[\4. Зміст розрахунково-пояснювальної записки:] uline(task_list.content) linebreak() bold[\5. Перелік графічного матеріалу:] uline(task_list.graphics) linebreak() { bold[\6. Дата видачі завдання:] uline(task_list.initial_date.display("[day].[month].[year]")) hfill(10fr) } pagebreak() } // page 3 {{{2 { align(center, bold[КАЛЕНДАРНИЙ ПЛАН]) set par(first-line-indent: 0pt) linebreak() calendar_plan.plan_table linebreak() grid( columns: (5fr, 5fr), grid( columns: (1fr, 2fr, 1fr), gutter: 0.2fr, [ Студент \ Керівник \ #align(center)["#underline[#calendar_plan.approval_date.day()]"] ], [ #uline(align: center, []) \ #uline(align: center, []) \ #uline(align: center, month_gen(calendar_plan.approval_date.month())) ], [ \ \ #underline[#calendar_plan.approval_date.year()] р. ], ), [ #author.name, \ #head_mentor.degree #head_mentor.name. ], ) pagebreak() } // page 4 {{{2 [ #align(center, bold[РЕФЕРАТ]) \ #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() /* TODO: why this stopped working? #let tables = counter(figure.where(kind: table)).final().at(0) #let images = counter(figure.where(kind: image)).final().at(0)*/ #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) { true } else { a < b } }) .join(", ") ) \ #abstract.text ] // page 5 {{{2 outline( title: [ ЗМІСТ #v(spacing * 2, weak: true) ], depth: 2, indent: auto, ) doc // bibliography {{{2 { heading(depth: 1, numbering: none)[Перелік джерел посилання] bibliography( bib_path, style: "ieee", full: true, title: none, ) let bib_data = yaml(bib_path) let format-entry(c) = { if (c.type == "Web") { let date_array = c.url.date.split("-") let date = datetime( year: int(date_array.at(0)), month: int(date_array.at(1)), day: int(date_array.at(2)), ) [#c.title. #c.author. URL: #c.url.value (дата звернення: #date.display("[day].[month].[year]")).] } else if ( c.type == "Book" ) [#c.author #c.title. #c.publisher, #c.date. #c.page-total c. ] else [ UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE ] } show enum.item: it => { set par(first-line-indent: 0pt) box(width: 1.25cm) box(width: 1em + 0.5cm)[#it.number.] it.body linebreak() } context { for (i, citation) in query(ref.where(element: none)) .map(r => str(r.target)) .dedup() .enumerate() { enum.item( i + 1, format-entry(bib_data.at(citation)), ) } } } appendices-style(appendices) } // #include "src/layouts.typ" // Practice and Laboratory works template {{{1 /// DSTU 3008:2015 Template for NURE /// -> content /// - doc (content): Content to apply the template to. /// - layout: ("default" | "simple"): Title page layout variant. /// - university: "ХНУРЕ": University metadata. Optional. /// - subject: str: Subject shortcode. /// - type: ("ЛБ" | "ПЗ" | "КР" | "РФ" | str): Work type. /// - number: int or none: Work number. Optional. /// - title: str or none: Work title. Optional. /// - authors ((name: str, full_name_gen: str or none, edu_program: str, group: str, gender: str, variant: int or none),): List of authors. /// - mentors ((name: str, degree: str, gender: ("m" | "f" | "p" | none)),): List of mentors. Optional. #let pz-lb( doc, layout: "simple", university: "ХНУРЕ", subject: none, type: none, number: none, title: none, authors: (), mentors: (), ) = { // TODO: add actually relevant asserts import "src/layouts/pz-lb/minimal.typ": * import "src/layouts/pz-lb/simple.typ": * let edu_program = authors.first().edu_program let uni = universities.at(university) set document(title: title, author: authors.map(c => c.name)) show: dstu-style.with(skip: 1) // page 1 {{{2 if layout == "simple" { simple(uni, edu_program, subject, type, number, title, authors, mentors) } else { minimal(uni, edu_program, subject, type, number, title, authors, mentors) } pagebreak(weak: true) // TODO(unexplrd): wrap my head around the old way if title == none { if number == none { context counter(heading).update(1) } else { context counter(heading).update(number) } } else { if number != none { context counter(heading).update(number - 1) } heading(eval(title, mode: "markup")) } doc } // vim:sts=2:sw=2:fdm=marker:cms=/*%s*/