#let acronyms = yaml("acronyms.yml"); #let acroStates = state("acronymStates", ()); #let english_pack = ( degree_1: "for the", degree_2: "from the Course of Studies Computer Science", by: "by", time_period: "Time Period", student_id_course: "Student ID, Course", company: "Company", supervisor: "Supervisor in the Company", decleration: (type, title) => [ = 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. ], abstract: "Abstract", contents: "Contents", list_of_figures: "List of Figures", acronyms: "Acronyms", bibliography: "Bibliography", appendix: "Appendix", chapter: "Chapter", section: "Section", 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. ] ) // TODO: Check alignment to LaTeX template #let german_pack = ( degree_1: "für den", degree_2: "im Studiengang Informatik an der Dualen Hochschule Baden-Württemberg Stuttgart", by: "von", time_period: "Bearbeitungszeitraum", student_id_course: "Matrikelnummer, Kurs", company: "Ausbildungsfirma", supervisor: "Betreuer", decleration: (type, title) => [ == Erklärung Ich erkläre hiermit ehrenwörtlich: + dass ich meine #type mit dem Thema #title ohne fremde Hilfe angefertigt habe; + dass ich die Übernahme wörtlicher Zitate aus der Literatur sowie die Verwendung der Gedanken anderer Autoren an den entsprechenden Stellen innerhalb der Arbeit gekennzeichnet habe; + dass ich meine T1000 bei keiner anderen Prüfung vorgelegt habe; Ich bin mir bewusst, dass eine falsche Erklärung rechtliche Folgen haben wird. #title *a big & fat _TODO_!* ], abstract: "Abstract", contents: "Inhaltsverzeichnis", list_of_figures: "Abbildungsverzeichnis", acronyms: "Abkürzungsverzeichnis", bibliography: "Literaturverzeichnis", appendix: "Anhang", chapter: "Kapitel", section: "Abschnitt", confidentiality_clause: [ = Sperrvermerk 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. ] ) #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 due date of your thesis date: none, // the time period that the work described in your thesis took place in time_period: 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", // Change the language to `de` if desired language: "en", // Details on your university university: ( name: "Cooperative State University Baden-Württemberg", location: "Stuttgart", image: "assets/dhbw.svg", ), // Details on your company company: ( name: "Hewlett Packard Enterprise", image: "assets/hpe.svg", ), // Does the document require a Confidentiality Clause? confidentiality_clause: false, // Path to your bibliography file // You may use `.yml` for Hayagriva format // or `.bib` for BibLaTeX format bibliography_path: "literature.yml", // Citation style: // Customized includes ISBNs and // writes DOI in capital letters customized_ieee_citations: true, // The contents of your abstract abstract: include "./abstract.typ", // To be append after the bibliography appendix: none, // First chapter of your thesis // This is *not* required anymore // first_chapter_title: none, // Factor of page location when to pagebreak headings // to avoid a heading without content on the same page. // Can be disabled by setting it to none // WARNING: can result in "layout did not converge within 5 attempts" issue heading_pagebreak_percentage: none, // 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) // Use english by default #let selected_lang = if language == "de" {german_pack} else {english_pack} #set document( title: title, author: author, date: date, ) #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: language, 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) } // On top-level headers, do a weak pagebreak // (weak = no pagebreak on already blank pages) if it.level == 1 { pagebreak(weak: true) } else if heading_pagebreak_percentage != none { // If a heading would start at the very end of a page, // it would not look right => pagebreak context { let here_abs = here().position().y let here_rel = here_abs.abs / page.height if here_rel > heading_pagebreak_percentage { // Write but hide to assess location correctly // Hidden will not have any influence // on the output besides correct calculation hide[#here_abs.abs #page.height rel: #here_rel%] pagebreak(weak: true) } } } [ #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 { if it.level == 1 { selected_lang.chapter } else { selected_lang.section } } else { it.supplement } }) // 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, selected_lang.degree_1) #text(14pt)[*#degree*] #text(14pt)[#selected_lang.degree_2 #major] #v(32pt) #text(14pt, selected_lang.by) #text(16pt)[*#author*] #v(16pt) #text(14pt)[#date.display("[day].[month].[year]")] #set align(bottom) #grid( columns: (1fr, 0.5fr, 1fr), align(left)[ *#selected_lang.time_period* \ *#selected_lang.student_id_course* \ *#selected_lang.company* \ *#selected_lang.supervisor* ], 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 // English by default #if confidentiality_clause { selected_lang.confidentiality_clause pagebreak(weak: true) } // render the abstract aligned to the center of the page #set align(horizon) #set align(center) #heading(outlined: true, selected_lang.abstract) #block(width: 70%)[#abstract] #pagebreak() #set align(top) #set align(start) #(selected_lang.decleration)(type, title) #v(48pt) #university.location, #date.display("[day].[month].[year]") // #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() // = #selected_lang.contents #set outline( indent: n => { // Max indent is 2 if n > 2 { n = 2 } return n * 2em }, fill: repeat(" . ") ) #show outline.entry.where(level: 1): it => { if it.element.func() != heading { return it } show ".": "" v(2pt) strong(it) } #outline(target: heading, depth: 2, title: selected_lang.contents) // start adding headings to the outline after the table of contents #set heading(outlined: true) #pagebreak(weak: true) = #selected_lang.list_of_figures #show outline.entry: it => [ #v(12pt, weak: true) #it ] #outline(target: figure, title: none) #pagebreak(weak: true) = #selected_lang.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(weak: true) // 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, title: selected_lang.bibliography, style: if customized_ieee_citations {"/ieee-modified.csl"} else {"ieee"}) #if appendix != none [ #pagebreak(weak: true) #heading(numbering: none, selected_lang.appendix) #set heading( outlined: true, bookmarked: true, numbering: (..nums) => { let n = nums.pos() n.remove(0) return numbering("A.1", ..n) } ) #appendix ] ] // `pref` if to prefer the long form // may be normal, short or long #let acro(short, pref: "normal", append: "") = { let item = acronyms.at(short) locate(loc => { let entries = acroStates.at(loc).filter(e => e == short); // Already used once if entries.len() > 0 { if pref == "long" { link(label(short))[#item#append] } else { link(label(short))[#short#append] } // First usage } else { acroStates.update(e => {e.push(short); e;}); if pref == "short" { link(label(short))[#short#append (#item)] } else { link(label(short))[#item#append (#short)] } } }); } #let acroOnce(main, inside) = [#main (#inside)] #let todo(content) = par(emph([ #h(5pt) #text(weight: "bold")[To-do/WIP:] #content ]))