diff --git a/template.typ b/template.typ index 982c2db..cc3a47a 100755 --- a/template.typ +++ b/template.typ @@ -3,461 +3,462 @@ #let acroStates = state("acronymStates", ()); #let thesis( - // the title of your thesis - title: none, - // your name - author: none, - // your student id / matriculation number - student_id: none, - // the name of your course, such as "TINF21A" - course: none, - signature: none, - - // the name of your supervisor - supervisor: none, + // the title of your thesis + title: none, + // your name + author: none, + // your student id / matriculation number + student_id: none, + // the name of your course, such as "TINF21A" + course: none, + signature: none, - // the due date of your thesis - date: none, - // the time period that the work described in your thesis took place in - time_period: none, + // the name of your supervisor + supervisor: none, - // the type of your thesis, such as T1000, T2000, etc. - type: none, - // your degree, such as "Bachelor of Science" - degree: "Bachelor of Science", - // your major, such as "Computer Science" - major: "Computer Science", + // the due date of your thesis + date: none, + // the time period that the work described in your thesis took place in + time_period: none, - // Details on your university - university: ( - name: "Cooperative State University Baden-Württemberg", - location: "Stuttgart", - image: "assets/dhbw.svg", - ), + // the type of your thesis, such as T1000, T2000, etc. + type: none, + // your degree, such as "Bachelor of Science" + degree: "Bachelor of Science", + // your major, such as "Computer Science" + major: "Computer Science", - // Details on your company - company: ( - name: "Hewlett Packard Enterprise", - image: "assets/hpe.svg", - ), + // Details on your university + university: ( + name: "Cooperative State University Baden-Württemberg", + location: "Stuttgart", + image: "assets/dhbw.svg", + ), - // Does the document require a Confidentiality Clause? - confidentiality_clause: false, + // Details on your company + company: ( + name: "Hewlett Packard Enterprise", + image: "assets/hpe.svg", + ), - // Path to your bibliography file - // You may use `.yml` for Hayagriva format - // or `.bib` for BibLaTeX format - bibliography_path: "literature.yml", + // Does the document require a Confidentiality Clause? + confidentiality_clause: false, - // The contents of your abstract - abstract: include "./abstract.typ", + // Path to your bibliography file + // You may use `.yml` for Hayagriva format + // or `.bib` for BibLaTeX format + bibliography_path: "literature.yaml", - // First chapter of your thesis - // This is required to generate the content section correctly - first_chapter_title: "Introduction", + // The contents of your abstract + abstract: include "./abstract.typ", - // set automatically by using the template via `#show: thesis.with(...) - body, + // First chapter of your thesis + // This is required to generate the content section correctly + first_chapter_title: "Introduction", + + // set automatically by using the template via `#show: thesis.with(...) + body, ) = [ - // Assert all parameters are set - #assert.ne(title, none) - #assert.ne(author, none) - #assert.ne(student_id, none) - #assert.ne(type, none) - #assert.ne(course, none) - #assert.ne(date, none) - #assert.ne(time_period, none) - #assert.ne(supervisor, none) - - #set document( - title: title, - author: author, - ) - - #set page( - paper: "a4", - margin: 2.5cm, - numbering: none, // don't number the first pages, i.e. titlepage and abstract - ) - - // suggested font and font size by the DHBW style guide - #set text( - font: "Linux Libertine", - size: 12pt, - hyphenate: false, - lang: "en", - ligatures: true, - ) - - #set par( - leading: 8pt, // 1.5x line spacing - justify: true, - linebreaks: "optimized", - ) - - #set figure( - numbering: "I" - ) - - // don't outline or number the first headings - #set heading( - numbering: none, - outlined: false, - ) - - // modify the spacing between various headings and the content below them - #show heading: it => { - let sizes = if it.level == 1 { - (64pt, 24pt, 24pt) - } else if it.level == 2 { - (32pt, 20pt, 18pt) - } else { - (24pt, 16pt, 14pt) - } - - [ - #set text(size: sizes.at(2)) - #v(sizes.at(0)) - #if it.numbering != none [ - #counter(heading).display(it.numbering) #h(4pt) #it.body - ] else [#it.body] - #v(sizes.at(1)) - ] - } - // Alternative formating for headdings - // #show heading: it => { - // v(1em) - // if it.numbering != none { - // grid( - // columns: (auto, auto), - // { - // numbering(it.numbering, ..counter(heading).at(it.location())) - // h(24pt / it.level) - // }, - // it.body, - // ) - // } else { - // it.body - // } - // v(0.5em) - // } - // #show heading.where(level: 1): set text(size: 24pt) - // #show heading.where(level: 2): set text(size: 20pt) - // #show heading.where(level: 3): set text(size: 16pt) - - // Style figure captions - #show figure : it => block(breakable: false)[ - #v(15pt, weak: true) - #it.body - #align(center)[ - // #v(.5em) - #block(width: 80%, text(size: .9em)[ - #it.supplement #it.counter.display(it.numbering): - #emph(it.caption) - ]) - #v(15pt) - ] - ] - - // rename level 1 headings to "Chapter", otherwise "Section" - #set ref(supplement: it => { - if it.func() == heading and it.level == 1 { - "Chapter" - } else { - "Section" - } - }) - - // beginning of the document, render the title page - - #set align(center) - - // nice - #grid( - columns: (1fr, 1fr), - align(center)[ - #image(company.image, width: 69%) - ], - align(center)[ - #image(university.image, width: 69%) - ], - ) - #v(64pt) - - #set par(justify: false) - #text(20pt)[*#title*] - #v(32pt) - #set par(justify: true) - - #text(16pt)[*#type*] - #v(16pt) - - #text(14pt)[for the] - - #text(14pt)[*#degree*] - - #text(14pt)[from the Course of Studies #major] - #v(32pt) - - #text(14pt)[by] - - #text(16pt)[*#author*] - #v(16pt) - - #text(14pt)[#date] - - #set align(bottom) - - #grid( - columns: (1fr, 0.5fr, 1fr), - align(left)[ - *Time Period* \ - *Student ID, Course* \ - *Company* \ - *Supervisor in the Company* - ], - none, - align(left)[ - #time_period \ - #student_id, #course \ - #company.name \ - #supervisor - ], - ) - - #pagebreak() - #set align(top) - #set align(left) - - // initially set the page numbering to roman - #set page(numbering: "I") - #counter(page).update(1) - - // https://www.dhbw.de/fileadmin/user_upload/Dokumente/Broschueren_Handbuch_Betriebe/Infoblatt_Vertraulichkeit.pdf - #if confidentiality_clause [ - == Confidentiality Clause - - The content of this work may not be made accessible to people outside of the - testing process and the evaluation process neither as a whole nor as excerpts, - unless an authorization stating otherwise is presented by the training facility. - - // #text(lang: "de")[ - // Der Inhalt dieser Arbeit darf weder als Ganzes noch in Auszügen Personen außerhalb des - // Prüfungs- und des Evaluationsverfahrens zugänglich gemacht werden, sofern keine anders - // lautende Genehmigung des Dualen Partners vorliegt. - // ] - - #pagebreak() - ] - - // render the abstract aligned to the center of the page - #set align(horizon) - #set align(center) - - == Abstract - - #block(width: 70%)[#abstract] - - #pagebreak() - - #set align(top) - #set align(start) - - = Author's Declaration - - Hereby I solemnly declare: - - + that this #type, titled #text(style: "italic")[#title] is entirely the product of my - own scholarly work, unless otherwise indicated in the text or references, or acknowledged below; - - + I have indicated the thoughts adopted directly or indirectly from other sources at the appropriate - places within the document; - - + this #type has not been submitted either in whole or part, for a degree at this or - any other university or institution; - - + I have not published this #type in the past; - - // - the printed version is equivalent to the submitted one. - - I am aware that a dishonest declaration will entail legal consequences. - #v(48pt) - - #university.location, #date - // #v(48pt) - - #box(width: 196pt, height: 40pt)[ - #if signature == "hide" { - box(height: 50pt) - } else if signature == none { - [ - Set your signature by setting the `signature` argument - to an image or set it to `hide`, to leave place for signing otherwise - #v(2pt) - ] - } else { - image(signature) - } - #v(0pt, weak: true) - #line(length: 100%) - #author - ] - - #pagebreak() - - = Contents - - #locate(loc => { - let headings = query(heading, loc) - let before_content = true - let after_content = false - - for elem in headings { - // kind of hacky, we track whether the main document has started by looking for a chapter by name - if elem.body == [#first_chapter_title] { - before_content = false - } - - // similarly, track the end of the main content by the position of the "Bibliography" chapter - if elem.body == [Bibliography] { - after_content = true - } - - // page numbers of the main document are arabic, the first pages are roman - let index_fmt = if before_content { - "I" - } else { - "1" - } - - let location = elem.location() - let page_index = counter(page).at(location).at(0) - - let formatted_index = numbering(index_fmt, page_index) - - // only the main content should be numbered - let formatted_name = if before_content or after_content { - elem.body - } else [ - #numbering("1.1", ..counter(heading).at(location)) - #h(4pt) - #elem.body - ] - - let is_chapter = elem.level == 1 - - // indent headings in the table of contents based on their level - let indent = if is_chapter { - 0pt - } else if elem.level == 2 { - 2em - } else { - 4em - } - - // non-chapter headings have their line filled with dots - let spacer = if is_chapter { " " } else { " . " } - - if elem.body != [Abstract] and elem.body != [Confidentiality Clause] { - link( - location, - [ - #h(indent) - // add extra spacing between chapters - #if is_chapter {v(1pt)} - // chapters are bold, sections are not - #if is_chapter [*#formatted_name*] else [#formatted_name] - #box(width: 1fr, repeat(spacer)) - #h(8pt) - #if is_chapter [*#formatted_index*] else [#formatted_index] \ - ], - ) - } - } - }) - - // #outline(target: heading.) - - // #show outline.entry.where( - // level: 1 - // ): it => { - // v(12pt, weak: true) - // strong(it) - // } - - // #outline(target: heading, depth: 3, indent: 2em, fill: repeat(" . ")) - - #pagebreak() - - // start adding headings to the outline after the table of contents - #set heading(outlined: true) - - // = List of Figures - - #show outline.entry: it => [ - #v(12pt, weak: true) #it - ] - - #outline(target: figure, title: "List of Figures", fill: repeat(" . ")) - - #pagebreak() - - = Acronyms - - #let acroArr = (); - #for (k, v) in acronyms.pairs().sorted(key: s => lower(s.at(0))) { - acroArr.push([*#k* #label(k)]); - acroArr.push([#v]); - } - - #table( - columns: (1fr, 6fr), - align: horizon, - stroke: none, - ..acroArr, - ) - - #pagebreak() - - // update heading and page numberings to begin the main part of the document - #set heading(numbering: "1.1") - #set page(numbering: "1 / 1") - #counter(page).update(1) - - // the actual chapters - #body - - // finally, include the bibliography chapter at the end of the document - #pagebreak() - // #bibliography(bibliography_path, style: "ieee") - #bibliography(bibliography_path, style: "ieee") + // Assert all parameters are set + #assert.ne(title, none) + #assert.ne(author, none) + #assert.ne(student_id, none) + #assert.ne(type, none) + #assert.ne(course, none) + #assert.ne(date, none) + #assert.ne(time_period, none) + #assert.ne(supervisor, none) + + #set document( + title: title, + author: author, + ) + + #set page( + paper: "a4", + margin: 2.5cm, + numbering: none, // don't number the first pages, i.e. titlepage and abstract + ) + + // suggested font and font size by the DHBW style guide + #set text( + font: "Linux Libertine", // Linux Biolinum O + // font: "Linux Biolinum O", + size: 12pt, + hyphenate: false, + lang: "en", + ligatures: true, + ) + + #set par( + leading: 8pt, // 1.5x line spacing + justify: true, + linebreaks: "optimized", + ) + + #set figure( + numbering: "I" + ) + + // don't outline or number the first headings + #set heading( + numbering: none, + outlined: false, + ) + + // modify the spacing between various headings and the content below them + #show heading: it => { + let sizes = if it.level == 1 { + (64pt, 24pt, 24pt) + } else if it.level == 2 { + (32pt, 20pt, 18pt) + } else { + (24pt, 16pt, 14pt) + } + + [ + #set text(size: sizes.at(2)) + #v(sizes.at(0)) + #if it.numbering != none [ + #counter(heading).display(it.numbering) #h(4pt) #it.body + ] else [#it.body] + #v(sizes.at(1)) + ] + } + // Alternative formating for headdings + // #show heading: it => { + // v(1em) + // if it.numbering != none { + // grid( + // columns: (auto, auto), + // { + // numbering(it.numbering, ..counter(heading).at(it.location())) + // h(24pt / it.level) + // }, + // it.body, + // ) + // } else { + // it.body + // } + // v(0.5em) + // } + // #show heading.where(level: 1): set text(size: 24pt) + // #show heading.where(level: 2): set text(size: 20pt) + // #show heading.where(level: 3): set text(size: 16pt) + + // Style figure captions + // TODO: consider reenabling, broken + // #show figure : it => block(breakable: false)[ + // #v(15pt, weak: true) + // #it.body + // #align(center)[ + // // #v(.5em) + // #block(width: 80%, text(size: .9em)[ + // #it.supplement #it.counter.display(it.numbering): + // #emph(it.caption.text) + // ]) + // #v(15pt) + // ] + // ] + + // rename level 1 headings to "Chapter", otherwise "Section" + #set ref(supplement: it => { + if it.func() == heading and it.level == 1 { + "Chapter" + } else { + "Section" + } + }) + + // beginning of the document, render the title page + + #set align(center) + + // nice + #grid( + columns: (1fr, 1fr), + align(center)[ + #image(company.image, width: 69%) + ], + align(center)[ + #image(university.image, width: 69%) + ], + ) + #v(64pt) + + #set par(justify: false) + #text(20pt)[*#title*] + #v(32pt) + #set par(justify: true) + + #text(16pt)[*#type*] + #v(16pt) + + #text(14pt)[for the] + + #text(14pt)[*#degree*] + + #text(14pt)[from the Course of Studies #major] + #v(32pt) + + #text(14pt)[by] + + #text(16pt)[*#author*] + #v(16pt) + + #text(14pt)[#date] + + #set align(bottom) + + #grid( + columns: (1fr, 0.5fr, 1fr), + align(left)[ + *Time Period* \ + *Student ID, Course* \ + *Company* \ + *Supervisor in the Company* + ], + none, + align(left)[ + #time_period \ + #student_id, #course \ + #company.name \ + #supervisor + ], + ) + + #pagebreak() + #set align(top) + #set align(left) + + // initially set the page numbering to roman + #set page(numbering: "I") + #counter(page).update(1) + + // https://www.dhbw.de/fileadmin/user_upload/Dokumente/Broschueren_Handbuch_Betriebe/Infoblatt_Vertraulichkeit.pdf + #if confidentiality_clause [ + == Confidentiality Clause + + The content of this work may not be made accessible to people outside of the + testing process and the evaluation process neither as a whole nor as excerpts, + unless an authorization stating otherwise is presented by the training facility. + + // #text(lang: "de")[ + // Der Inhalt dieser Arbeit darf weder als Ganzes noch in Auszügen Personen außerhalb des + // Prüfungs- und des Evaluationsverfahrens zugänglich gemacht werden, sofern keine anders + // lautende Genehmigung des Dualen Partners vorliegt. + // ] + + #pagebreak() + ] + + // render the abstract aligned to the center of the page + #set align(horizon) + #set align(center) + + == Abstract + + #block(width: 70%)[#abstract] + + #pagebreak() + + #set align(top) + #set align(start) + + = Author's Declaration + + Hereby I solemnly declare: + + + that this #type, titled #text(style: "italic")[#title] is entirely the product of my own scholarly work, unless otherwise indicated in the text or references, or acknowledged below; + + + I have indicated the thoughts adopted directly or indirectly from other sources at the appropriate places within the document; + + + this #type has not been submitted either in whole or part, for a degree at this or any other university or institution; + + + I have not published this #type in the past; + + // - the printed version is equivalent to the submitted one. + + I am aware that a dishonest declaration will entail legal consequences. + #v(48pt) + + #university.location, #date + // #v(48pt) + + #box(width: 196pt, height: 40pt)[ + #if signature == "hide" { + box(height: 50pt) + } else if signature == none { + [ + Set your signature by setting the `signature` argument + to an image or set it to `hide`, to leave place for signing otherwise + #v(2pt) + ] + } else { + image(signature) + } + #v(0pt, weak: true) + #line(length: 100%) + #author + ] + + #pagebreak() + + = Contents + + #locate(loc => { + let headings = query(heading, loc) + let before_content = true + let after_content = false + + for elem in headings { + // kind of hacky, we track whether the main document has started by looking for a chapter by name + if elem.body == [#first_chapter_title] { + before_content = false + } + + // similarly, track the end of the main content by the position of the "Bibliography" chapter + if elem.body == [Bibliography] { + after_content = true + } + + // page numbers of the main document are arabic, the first pages are roman + let index_fmt = if before_content { + "I" + } else { + "1" + } + + let location = elem.location() + let page_index = counter(page).at(location).at(0) + + let formatted_index = numbering(index_fmt, page_index) + + // only the main content should be numbered + let formatted_name = if before_content or after_content { + elem.body + } else [ + #numbering("1.1", ..counter(heading).at(location)) + #h(4pt) + #elem.body + ] + + let is_chapter = elem.level == 1 + + // indent headings in the table of contents based on their level + let indent = if is_chapter { + 0pt + } else if elem.level == 2 { + 2em + } else { + 4em + } + + // non-chapter headings have their line filled with dots + let spacer = if is_chapter { " " } else { " . " } + + if elem.body != [Abstract] and elem.body != [Confidentiality Clause] { + link( + location, + [ + #h(indent) + // add extra spacing between chapters + #if is_chapter {v(1pt)} + // chapters are bold, sections are not + #if is_chapter [*#formatted_name*] else [#formatted_name] + #box(width: 1fr, repeat(spacer)) + #h(8pt) + #if is_chapter [*#formatted_index*] else [#formatted_index] \ + ], + ) + } + } + }) + + // #outline(target: heading.) + + // #show outline.entry.where( + // level: 1 + // ): it => { + // v(12pt, weak: true) + // strong(it) + // } + + // #outline(target: heading, depth: 3, indent: 2em, fill: repeat(" . ")) + + #pagebreak() + + // start adding headings to the outline after the table of contents + #set heading(outlined: true) + + // = List of Figures + + #show outline.entry: it => [ + #v(12pt, weak: true) #it + ] + + #outline(target: figure, title: "List of Figures", fill: repeat(" . ")) + + #pagebreak() + + = Acronyms + + #let acroArr = (); + #for (k, v) in acronyms.pairs().sorted(key: s => lower(s.at(0))) { + acroArr.push([*#k* #label(k)]); + acroArr.push([#v]); + } + + #table( + columns: (1fr, 6fr), + align: horizon, + stroke: none, + ..acroArr, + ) + + #pagebreak() + + // update heading and page numberings to begin the main part of the document + #set heading(numbering: "1.1") + #set page(numbering: "1 / 1") + #counter(page).update(1) + + // the actual chapters + #body + + // finally, include the bibliography chapter at the end of the document + #pagebreak() + #bibliography(bibliography_path, style: "ieee") ] +// `pref` if to prefer the long form #let acro(short, pref: false, append: "") = { - let item = acronyms.at(short) + let item = acronyms.at(short) - locate(loc => { - let entries = acroStates.at(loc).filter(e => e == short); - - if entries.len() > 0 { - if pref { - link(label(short))[#item#append] - } else { - link(label(short))[#short#append] - } - } else { - acroStates.update(e => {e.push(short); e;}); - if pref { - link(label(short))[#item#append (#short)] - } else { - link(label(short))[#short#append (#item)] - } - } - }); + locate(loc => { + let entries = acroStates.at(loc).filter(e => e == short); + + // Already used once + if entries.len() > 0 { + if pref { + link(label(short))[#item#append] + } else { + link(label(short))[#short#append] + } + // First usage + } else { + acroStates.update(e => {e.push(short); e;}); + if pref { + link(label(short))[#item#append (#short)] + } else { + link(label(short))[#short#append (#item)] + } + } + }); } #let acroOnce(main, inside) = [#main (#inside)] #let todo(content) = par(emph([ - #h(5pt) #text(weight: "bold")[To-do/WIP:] #content + #h(5pt) #text(weight: "bold")[To-do/WIP:] #content ]))