mirror of
https://github.com/kristoferssolo/LU-DF-Typst-Template.git
synced 2025-10-21 18:50:33 +00:00
feat: add qualification thesis example
This commit is contained in:
parent
e26f01c1d5
commit
0986808ab3
26
examples/qualification-thesis/bibliography.yml
Normal file
26
examples/qualification-thesis/bibliography.yml
Normal file
@ -0,0 +1,26 @@
|
||||
typst:
|
||||
type: Web
|
||||
title: Typst
|
||||
author:
|
||||
- Mädje
|
||||
- Laurenz
|
||||
- Haug
|
||||
- Martin
|
||||
- Typst Projekta Izstrādātāji
|
||||
url: {value: "https://typst.app/", date: 2025-01-01}
|
||||
lvs_68:
|
||||
type: Book
|
||||
title: Programmatūras prasību specifikācijas ceļvedis
|
||||
author: Institūcija SIA "Latvijas standarts"
|
||||
issue: 68
|
||||
date: 1996-03-27
|
||||
organization: Latvijas Nacionālais standartizācijas un metroloģijas centrs
|
||||
page-total: 22
|
||||
lvs_72:
|
||||
type: Book
|
||||
title: Ieteicamā prakse programmatūras projektējuma aprakstīšanai
|
||||
author: Institūcija SIA "Latvijas standarts"
|
||||
issue: 72
|
||||
date: 1996-03-27
|
||||
organization: Latvijas Nacionālais standartizācijas un metroloģijas centrs
|
||||
page-total: 13
|
||||
286
examples/qualification-thesis/main.typ
Normal file
286
examples/qualification-thesis/main.typ
Normal file
@ -0,0 +1,286 @@
|
||||
#import "@preview/fletcher:0.5.8" as fletcher: diagram, edge, node
|
||||
#import fletcher.shapes: cylinder, ellipse
|
||||
#import "@preview/solo-lu-df:0.0.1": ludf
|
||||
#import "utils/tables.typ": function-table
|
||||
#import "utils/diagrams.typ": data-store, dpd-database, dpd-edge, process
|
||||
|
||||
#show: ludf.with(
|
||||
title: "Darba Nosaukums",
|
||||
thesis-type: "Kvalifikācijas Darbs",
|
||||
authors: (
|
||||
(
|
||||
name: "Jānis Bērziņš",
|
||||
code: "jb12345",
|
||||
location: [Riga, Latvia],
|
||||
email: "jb12345@edu.lu.lv",
|
||||
),
|
||||
(
|
||||
name: "Zane Kalniņa",
|
||||
code: "zk67890",
|
||||
location: [Riga, Latvia],
|
||||
email: "zk67890@edu.lu.lv",
|
||||
),
|
||||
),
|
||||
date: (
|
||||
year: 2025,
|
||||
),
|
||||
place: "Rīga",
|
||||
bibliography: bibliography("bibliography.yml"),
|
||||
abstract: (
|
||||
primary: (
|
||||
text: [
|
||||
#lorem(50)
|
||||
|
||||
#lorem(30)
|
||||
|
||||
#lorem(20)
|
||||
],
|
||||
keywords: (
|
||||
"Foo",
|
||||
"Bar",
|
||||
"Baz",
|
||||
),
|
||||
),
|
||||
secondary: (
|
||||
text: [
|
||||
#lorem(20)
|
||||
|
||||
#lorem(30)
|
||||
|
||||
#lorem(50)
|
||||
],
|
||||
keywords: (
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
#set heading(numbering: none)
|
||||
= Apzīmējumu saraksts
|
||||
/ Docs: Typst dokumentācija.#footnote[https://typst.com/docs/]
|
||||
/ Universe: Typst kopienas paketes un šabloni.#footnote[https://typst.app/universe/]
|
||||
|
||||
= Ievads
|
||||
== Nolūks
|
||||
#lorem(100)
|
||||
|
||||
== Darbības sfēra
|
||||
|
||||
== Saistība ar citiem dokumentiem
|
||||
PPS ir izstrādāta, ievērojot LVS 68:1996 "Programmatūras prasību specifikācijas
|
||||
ceļvedis" @lvs_68 un LVS 72:1996 "Ieteicamā prakse programmatūras projektējuma
|
||||
aprakstīšanai" standarta prasības @lvs_72.
|
||||
|
||||
== Pārskats
|
||||
|
||||
#set heading(numbering: "1.1.")
|
||||
|
||||
= Vispārējais apraksts
|
||||
== Esošā stāvokļa apraksts
|
||||
== Pasūtītājs
|
||||
== Produkta perspektīva
|
||||
== Darījumprasības
|
||||
== Sistēmas lietotāji
|
||||
|
||||
Skatīt @dpd-0
|
||||
|
||||
#figure(
|
||||
caption: [\0. līmeņa DPD],
|
||||
diagram(
|
||||
data-store((0, 0), [Lietotājs]),
|
||||
dpd-edge("rr,ddd,ll", align(center)[Ievades ierīces\ dati]),
|
||||
process((0, 3), [Sistēma], inset: 20pt),
|
||||
dpd-edge(
|
||||
"lll,uuu,rrr",
|
||||
align(center)[Vizuālās\ izvades dati],
|
||||
),
|
||||
dpd-edge(
|
||||
"l,uuu,r",
|
||||
align(center)[Audio\ izvades dati],
|
||||
),
|
||||
),
|
||||
) <dpd-0>
|
||||
|
||||
/// Or use an image
|
||||
//
|
||||
// #figure(
|
||||
// caption: "0. līmeņa DPD",
|
||||
// image("path/to/image"),
|
||||
// ) <dpd-0>
|
||||
|
||||
== Vispārējie ierobežojumi
|
||||
|
||||
= Programmatūras prasību specifikācija
|
||||
== Konceptuālais datu bāzes apraksts
|
||||
== Funkcionālās prasības
|
||||
|
||||
#figure(
|
||||
caption: [\1. līmeņa DPD],
|
||||
diagram({
|
||||
dpd-database((0, 0), [Datubāze], snap: -1)
|
||||
dpd-edge("ldd", align(center)[Neapstrādāti\ ārējie dati])
|
||||
dpd-edge("rrr,d", align(center)[Neapstrādāti\ dati])
|
||||
|
||||
process(
|
||||
(-1, 2),
|
||||
[Ārējs apstrādātājs],
|
||||
inset: 20pt,
|
||||
stroke: (thickness: 1pt, dash: "dashed"),
|
||||
)
|
||||
dpd-edge("r,uu", align(center)[Apstrādāti\ ārējie dati])
|
||||
|
||||
data-store((0, -2), [Lietotājs])
|
||||
dpd-edge("dd", align(center)[Neapstrādāti\ lietotāja dati])
|
||||
|
||||
process((3, 1), [A modulis], inset: 20pt)
|
||||
dpd-edge("lllu", align(center)[Apstrādāti dati], shift: 20pt)
|
||||
}),
|
||||
) <dpd-1>
|
||||
|
||||
=== Funkciju sadalījums moduļos
|
||||
Funkciju sadalījums moduļos ir aprakstīts tabulā (@function-modules[tab]).
|
||||
|
||||
#figure(
|
||||
caption: "Funkciju sadalījums pa moduļiem",
|
||||
table(
|
||||
columns: (auto, 1fr, auto),
|
||||
align: left,
|
||||
table.header([Modulis], [Funkcija], [Identifikators]),
|
||||
|
||||
table.cell(rowspan: 1)[A modulis],
|
||||
[A saskarne], [#link(<AF01>)[AF01]],
|
||||
|
||||
table.cell(rowspan: 2)[B modulis],
|
||||
[B saskarne], [#link(<BF01>)[BF01]],
|
||||
[B apstrāde], [#link(<BF02>)[BF02]],
|
||||
),
|
||||
) <function-modules>
|
||||
|
||||
=== A Modulis
|
||||
#function-table(
|
||||
"A Saskarne",
|
||||
"AF01",
|
||||
[#lorem(15)],
|
||||
[
|
||||
+ #lorem(4)
|
||||
+ #lorem(5)
|
||||
+ #lorem(6)
|
||||
],
|
||||
[
|
||||
+ #lorem(4)
|
||||
+ #lorem(5)
|
||||
+ #lorem(6)
|
||||
+ #lorem(7)
|
||||
+ #lorem(8)
|
||||
- #lorem(2)
|
||||
- #lorem(1)
|
||||
- #lorem(3)
|
||||
- #lorem(1)
|
||||
],
|
||||
[
|
||||
+ #lorem(10)
|
||||
+ #lorem(10)
|
||||
],
|
||||
) <AF01>
|
||||
|
||||
=== B Modulis
|
||||
|
||||
#function-table(
|
||||
"B Saskarne",
|
||||
"BF01",
|
||||
[#lorem(15)],
|
||||
[
|
||||
+ #lorem(4)
|
||||
+ #lorem(5)
|
||||
+ #lorem(6)
|
||||
],
|
||||
[
|
||||
+ #lorem(4)
|
||||
+ #lorem(5)
|
||||
+ #lorem(6)
|
||||
+ #lorem(7)
|
||||
+ #lorem(8)
|
||||
- #lorem(2)
|
||||
- #lorem(1)
|
||||
- #lorem(3)
|
||||
- #lorem(1)
|
||||
],
|
||||
[
|
||||
+ #lorem(10)
|
||||
+ #lorem(10)
|
||||
],
|
||||
[
|
||||
+ #lorem(10)
|
||||
+ #lorem(10)
|
||||
],
|
||||
) <BF01>
|
||||
|
||||
|
||||
#function-table(
|
||||
"B Apstrāde",
|
||||
"BF02",
|
||||
[#lorem(15)],
|
||||
[
|
||||
+ #lorem(4)
|
||||
+ #lorem(5)
|
||||
+ #lorem(6)
|
||||
],
|
||||
[
|
||||
+ #lorem(4)
|
||||
+ #lorem(5)
|
||||
+ #lorem(6)
|
||||
+ #lorem(7)
|
||||
+ #lorem(8)
|
||||
- #lorem(2)
|
||||
- #lorem(1)
|
||||
- #lorem(3)
|
||||
- #lorem(1)
|
||||
],
|
||||
[
|
||||
+ #lorem(10)
|
||||
+ #lorem(10)
|
||||
],
|
||||
) <BF02>
|
||||
|
||||
== Nefunkcionālās prasības
|
||||
=== Veiktspējas prasības
|
||||
|
||||
= Programmatūras projektējuma apraksts
|
||||
== Datu bāzes projektējums
|
||||
=== Datu bāzes loģiskais ER modelis
|
||||
Skatīt @logical-erd
|
||||
|
||||
#figure(
|
||||
caption: "Datu bāzes loģiskais ER modelis",
|
||||
[\<image>],
|
||||
// image("path/to/image")
|
||||
) <logical-erd>
|
||||
|
||||
=== Datu bāzes fiziskais ER modelis
|
||||
Skatīt @physical-erd[attēlu].
|
||||
|
||||
#figure(
|
||||
caption: "Datu bāzes loģiskais ER modelis",
|
||||
[\<image>],
|
||||
// image("path/to/image")
|
||||
) <physical-erd>
|
||||
|
||||
=== Datu bāzes tabulu apraksts
|
||||
|
||||
== Daļējs funkciju projektējums
|
||||
|
||||
== Daļējs lietotāju saskarņu projektējums
|
||||
=== Navigācija
|
||||
sk. @view-flow-diagram
|
||||
|
||||
#figure(
|
||||
caption: "Ekrānskatu plūsmas diagramma",
|
||||
[\<image>],
|
||||
// image("path/to/image")
|
||||
) <view-flow-diagram>
|
||||
|
||||
=== Ekrānskati
|
||||
48
examples/qualification-thesis/utils/diagrams.typ
Normal file
48
examples/qualification-thesis/utils/diagrams.typ
Normal file
@ -0,0 +1,48 @@
|
||||
#import "@preview/fletcher:0.5.8" as fletcher: diagram, edge, node
|
||||
#import fletcher.shapes: cylinder, diamond, ellipse
|
||||
|
||||
#let default-node-stroke = 1pt
|
||||
#let default-edge-stroke = 1pt
|
||||
|
||||
/// Read https://github.com/typst/packages/raw/main/packages/preview/fletcher/0.5.8/docs/manual.pdf for more information
|
||||
|
||||
#let data-store(pos, text) = {
|
||||
node(
|
||||
pos,
|
||||
text,
|
||||
inset: 20pt,
|
||||
stroke: default-node-stroke,
|
||||
)
|
||||
}
|
||||
|
||||
#let process(..args) = {
|
||||
node(
|
||||
inset: 10pt,
|
||||
shape: ellipse,
|
||||
stroke: default-node-stroke,
|
||||
..args,
|
||||
)
|
||||
}
|
||||
|
||||
#let dpd-edge(..args) = {
|
||||
edge(
|
||||
label-pos: 0.5,
|
||||
stroke: default-edge-stroke,
|
||||
label-anchor: "center",
|
||||
label-fill: white,
|
||||
corner-radius: 4pt,
|
||||
label-size: 10pt,
|
||||
..args,
|
||||
"-|>",
|
||||
)
|
||||
}
|
||||
|
||||
#let dpd-database(..args) = {
|
||||
node(
|
||||
shape: cylinder,
|
||||
height: 6em,
|
||||
width: 10em,
|
||||
stroke: default-node-stroke,
|
||||
..args,
|
||||
)
|
||||
}
|
||||
56
examples/qualification-thesis/utils/tables.typ
Normal file
56
examples/qualification-thesis/utils/tables.typ
Normal file
@ -0,0 +1,56 @@
|
||||
/// Creates a two-column "function" table with a caption.
|
||||
///
|
||||
/// Intended for "Funkciju sadalījums moduļos" section
|
||||
///
|
||||
/// Parameters:
|
||||
/// - caption: optional caption; defaults to the first positional item.
|
||||
/// - title: tuple of column/section titles (defaults provided).
|
||||
/// - items: positional cells; first two items populate the top row,
|
||||
/// remaining items are paired with the titles ["Apraksts", "Ievade", ...]
|
||||
///
|
||||
/// Behavior:
|
||||
/// - Renders the first two titles as table headers and the first two
|
||||
/// positional items beneath them.
|
||||
/// - For titles from index 2 onward, each title is rendered as a full-width
|
||||
/// (colspan 2) bold row followed by a full-width row containing the
|
||||
/// corresponding positional item. Missing items become empty strings.
|
||||
/// - Safe for fewer/more items: missing values are coerced to "", extra
|
||||
/// items beyond the paired section are ignored.
|
||||
///
|
||||
/// Default caption to the first positional item if none provided.
|
||||
#let function-table(
|
||||
caption: "",
|
||||
titles: (
|
||||
"Funkcijas nosaukums",
|
||||
"Funkcijas identifikators",
|
||||
"Apraksts",
|
||||
"Ievade",
|
||||
"Apstrāde",
|
||||
"Izvade",
|
||||
"Paziņojumi",
|
||||
),
|
||||
..items,
|
||||
) = {
|
||||
if caption == "" {
|
||||
caption = items.pos().first()
|
||||
}
|
||||
|
||||
let cells = titles
|
||||
.slice(2) // start from "Apraksts"
|
||||
.zip(items.pos().slice(2))
|
||||
.map(pair => (
|
||||
table.cell(colspan: 2, strong(pair.at(0))),
|
||||
table.cell(colspan: 2, pair.at(1)),
|
||||
))
|
||||
.flatten()
|
||||
|
||||
figure(
|
||||
caption: caption,
|
||||
table(
|
||||
columns: (1fr, 1fr),
|
||||
strong(titles.at(0)), strong(titles.at(1)),
|
||||
items.pos().at(0), items.pos().at(1),
|
||||
..cells,
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
#import "@preview/headcount:0.1.0": *
|
||||
#import "utils.typ": render-abstract
|
||||
#import "utils.typ": make-abstract, make-documentary-page, make-title
|
||||
|
||||
#let indent = 1cm
|
||||
|
||||
@ -217,44 +217,17 @@
|
||||
)
|
||||
|
||||
|
||||
// Display the paper's title and authors at the top of the page,
|
||||
// spanning all columns (hence floating at the scope of the
|
||||
// columns' parent, which is the page).
|
||||
// The page can contain a logo if you pass one with `logo: "logo.png"`.
|
||||
align(center, upper(text(size: 16pt, [
|
||||
#university\
|
||||
#faculty
|
||||
])))
|
||||
|
||||
v(1fr)
|
||||
|
||||
align(center, upper(text(20pt, weight: "bold", title)))
|
||||
|
||||
v(0.2fr)
|
||||
|
||||
align(center, upper(text(size: 16pt, thesis-type)))
|
||||
|
||||
v(1fr)
|
||||
|
||||
// Author information
|
||||
context [
|
||||
#set par(first-line-indent: 0pt)
|
||||
#if authors.len() > 1 { "Autori:" } else { "Autors:" }
|
||||
#authors.map(author => strong(author.name)).join(", ")
|
||||
|
||||
#if authors.len() > 1 { "Studentu" } else { "Studenta" }
|
||||
apliecības Nr.: #authors.map(author => author.code).join(", ")
|
||||
|
||||
#if advisors.len() > 0 [
|
||||
Darba #if advisors.len() > 1 { "vadītāji:" } else { "vadītājs:" }
|
||||
#advisors.map(advisor => [#advisor.title #advisor.name]).join("\n")
|
||||
]
|
||||
]
|
||||
|
||||
v(0.5fr)
|
||||
|
||||
align(center, upper([#place #date.year]))
|
||||
|
||||
make-title(
|
||||
title,
|
||||
authors,
|
||||
advisors,
|
||||
university,
|
||||
faculty,
|
||||
thesis-type,
|
||||
date,
|
||||
place,
|
||||
logo,
|
||||
)
|
||||
|
||||
// Start page numbering
|
||||
set page(numbering: "1", number-align: center)
|
||||
@ -262,8 +235,8 @@
|
||||
|
||||
// Display abstract and keywords.
|
||||
if abstract != none {
|
||||
render-abstract("primary", abstract.primary)
|
||||
render-abstract("secondary", abstract.secondary)
|
||||
make-abstract("primary", abstract.primary)
|
||||
make-abstract("secondary", abstract.secondary)
|
||||
}
|
||||
|
||||
// Table of contents.
|
||||
@ -279,4 +252,6 @@
|
||||
|
||||
// Display bibliography.
|
||||
bibliography
|
||||
|
||||
make-documentary-page()
|
||||
}
|
||||
98
src/utils.typ
Normal file
98
src/utils.typ
Normal file
@ -0,0 +1,98 @@
|
||||
#let merge(a, b) = {
|
||||
let result = a
|
||||
for (k, v) in b { result.at(k) = v }
|
||||
result
|
||||
}
|
||||
|
||||
#let make-abstract(role, abstract) = {
|
||||
// Define role-based defaults
|
||||
let defaults = if role == "primary" {
|
||||
(
|
||||
lang: "lv",
|
||||
title: "Anotācija",
|
||||
keyword-title: "Atslēgvārdi",
|
||||
text: [],
|
||||
keywords: [],
|
||||
)
|
||||
} else {
|
||||
(
|
||||
lang: "en",
|
||||
title: "Abstract",
|
||||
keyword-title: "Keywords",
|
||||
text: [],
|
||||
keywords: [],
|
||||
)
|
||||
}
|
||||
|
||||
// Merge defaults with overrides
|
||||
let abs = merge(defaults, abstract)
|
||||
|
||||
context [
|
||||
#set text(lang: abs.lang)
|
||||
#heading(
|
||||
level: 1,
|
||||
outlined: false,
|
||||
numbering: none,
|
||||
abs.title,
|
||||
)
|
||||
|
||||
// Abstract body text
|
||||
#abs.text
|
||||
|
||||
// Keywords
|
||||
#par(first-line-indent: 0cm)[ *#abs.keyword-title*: ]
|
||||
#abs.keywords.join(", ").
|
||||
]
|
||||
}
|
||||
|
||||
// Display the paper's title and authors at the top of the page,
|
||||
// spanning all columns (hence floating at the scope of the
|
||||
// columns' parent, which is the page).
|
||||
// The page can contain a logo if you pass one with `logo: "logo.png"`.
|
||||
#let make-title(
|
||||
title,
|
||||
authors,
|
||||
advisors,
|
||||
university,
|
||||
faculty,
|
||||
thesis-type,
|
||||
date,
|
||||
place,
|
||||
logo,
|
||||
) = {
|
||||
align(center, upper(text(size: 16pt, [
|
||||
#university\
|
||||
#faculty
|
||||
])))
|
||||
|
||||
v(1fr)
|
||||
|
||||
align(center, upper(text(20pt, weight: "bold", title)))
|
||||
|
||||
v(0.2fr)
|
||||
|
||||
align(center, upper(text(size: 16pt, thesis-type)))
|
||||
|
||||
v(1fr)
|
||||
|
||||
// Author information
|
||||
context [
|
||||
#set par(first-line-indent: 0pt)
|
||||
#if authors.len() > 1 { "Autori:" } else { "Autors:" }
|
||||
#authors.map(author => strong(author.name)).join(", ")
|
||||
|
||||
#if authors.len() > 1 { "Studentu" } else { "Studenta" }
|
||||
apliecības Nr.: #authors.map(author => author.code).join(", ")
|
||||
|
||||
#if advisors.len() > 0 [
|
||||
Darba #if advisors.len() > 1 { "vadītāji:" } else { "vadītājs:" }
|
||||
#advisors.map(advisor => [#advisor.title #advisor.name]).join("\n")
|
||||
]
|
||||
]
|
||||
|
||||
v(0.5fr)
|
||||
|
||||
align(center, upper([#place #date.year]))
|
||||
}
|
||||
|
||||
#let make-documentary-page() = {}
|
||||
@ -2,7 +2,7 @@
|
||||
name = "solo-lu-df"
|
||||
version = "0.0.1"
|
||||
compiler = "0.13.0"
|
||||
entrypoint = "lib.typ"
|
||||
entrypoint = "src/lib.typ"
|
||||
repository = "https://github.com/kristoferssolo/LU-DF-Typst-Template"
|
||||
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
||||
license = "MIT"
|
||||
|
||||
46
utils.typ
46
utils.typ
@ -1,46 +0,0 @@
|
||||
#let merge(a, b) = {
|
||||
let result = a
|
||||
for (k, v) in b { result.at(k) = v }
|
||||
result
|
||||
}
|
||||
|
||||
#let render-abstract(role, abstract) = {
|
||||
// Define role-based defaults
|
||||
let defaults = if role == "primary" {
|
||||
(
|
||||
lang: "lv",
|
||||
title: "Anotācija",
|
||||
keyword-title: "Atslēgvārdi",
|
||||
text: [],
|
||||
keywords: [],
|
||||
)
|
||||
} else {
|
||||
(
|
||||
lang: "en",
|
||||
title: "Abstract",
|
||||
keyword-title: "Keywords",
|
||||
text: [],
|
||||
keywords: [],
|
||||
)
|
||||
}
|
||||
|
||||
// Merge defaults with overrides
|
||||
let abs = merge(defaults, abstract)
|
||||
|
||||
context [
|
||||
#set text(lang: abs.lang)
|
||||
#heading(
|
||||
level: 1,
|
||||
outlined: false,
|
||||
numbering: none,
|
||||
abs.title,
|
||||
)
|
||||
|
||||
// Abstract body text
|
||||
#abs.text
|
||||
|
||||
// Keywords
|
||||
#par(first-line-indent: 0cm)[ *#abs.keyword-title*: ]
|
||||
#abs.keywords.join(", ").
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user