feat: package definiton with library and template

This commit is contained in:
orangerot 2025-09-09 13:18:10 +02:00
parent c6e566775d
commit 2ed73f8bf4
14 changed files with 185 additions and 76 deletions

View file

@ -17,20 +17,20 @@ Die Vorlage enthält zwei Optionen den Fragebogen zu erstellen. Empfohlen ist da
Erstellen mit Template. Dafür müssen lediglich die Argumente in der Datei Erstellen mit Template. Dafür müssen lediglich die Argumente in der Datei
`main.typ` ausgefüllt werden. `main.typ` ausgefüllt werden.
```typst ```typst
#import "lib.typ": oral-post-exam #import "lib.typ": exam-report, event
#show: oral-post-exam.with( #show: exam-report.with(
lecture: "", // Fach lecture: "", // Fach
date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum
examiner: "", // PrüferIn (Prof) examiner: "", // PrüferIn (Prof)
assistant: "", // BeisitzerIn assistant: "", // BeisitzerIn
did_pass: none, // Bestanden? true || false did_pass: none, // Bestanden? true || false
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
attendance: (: attendance: (
/* Veranstaltung, Jahr, regelmäßig besucht? */ /* Veranstaltung, Jahr, regelmäßig besucht? */
"Vorlesung": (year: "", did_attend: ""), event(name: "Vorlesung", year: "", did_attend: ""),
"Übung": (year: "", did_attend: ""), event(name: "Übung", year: "", did_attend: ""),
"Tutorium": (year: "", did_attend: ""), event(name: "Tutorium", year: "", did_attend: ""),
), ),
preparation_time: [ preparation_time: [
// Wie lange und wie hast alleine bzw. mit anderen vorbereitet? // Wie lange und wie hast alleine bzw. mit anderen vorbereitet?

View file

@ -2,18 +2,22 @@
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#let oral-post-exam( #let event(name: "", year: "", did_attend: "") = (
box(height: 1.2em)[*#name*], [#year], [#did_attend]
)
#let exam-report(
lecture: "", // Fach lecture: "", // Fach
date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum
examiner: "", // PrüferIn (Prof) examiner: "", // PrüferIn (Prof)
assistant: "", // BeisitzerIn assistant: "", // BeisitzerIn
did_pass: none, // Bestanden? true || false did_pass: none, // Bestanden? true || false
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
attendance: (: attendance: (
/* Veranstaltung, Jahr, regelmäßig besucht? */ /* Veranstaltung, Jahr, regelmäßig besucht? */
"Vorlesung": (year: "", did_attend: ""), event(name: "Vorlesung", year: "", did_attend: ""),
"Übung": (year: "", did_attend: ""), event(name: "Übung", year: "", did_attend: ""),
"Tutorium": (year: "", did_attend: ""), event(name: "Tutorium", year: "", did_attend: ""),
), ),
preparation_time: [ preparation_time: [
// Wie lange und wie hast alleine bzw. mit anderen vorbereitet? // Wie lange und wie hast alleine bzw. mit anderen vorbereitet?
@ -34,13 +38,6 @@
) = [ ) = [
#let checkbox(checked: false) = if (checked) {$times.square$} else {$square$} #let checkbox(checked: false) = if (checked) {$times.square$} else {$square$}
#let events = (
"Vorlesung": (year: "", did_attend: ""),
"Übung": (year: "", did_attend: ""),
"Tutorium": (year: "", did_attend: ""),
..attendance
)
#show <date>: if date.year() > 0 {date.display("[day].[month].[year]")} #show <date>: if date.year() > 0 {date.display("[day].[month].[year]")}
#show <examiner>: examiner #show <examiner>: examiner
#show <assistant>: assistant #show <assistant>: assistant
@ -64,8 +61,7 @@
let _ = g.remove("label") let _ = g.remove("label")
table(..g, table(..g,
..it.fields().children.at(0).children, ..it.fields().children.at(0).children,
..events.pairs().map(((location, (year, did_attend))) => ..(attendance + 3*(event(),)).slice(0,3).flatten()
(box(height: 1.2em)[*#location*], [#year], [#did_attend])).flatten()
) )
} }

View file

@ -1,17 +1,17 @@
#import "lib.typ": oral-post-exam #import "lib.typ": exam-report, event
#show: oral-post-exam.with( #show: exam-report.with(
lecture: "", // Fach lecture: "", // Fach
date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum
examiner: "", // PrüferIn (Prof) examiner: "", // PrüferIn (Prof)
assistant: "", // BeisitzerIn assistant: "", // BeisitzerIn
did_pass: none, // Bestanden? true || false did_pass: none, // Bestanden? true || false
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
attendance: (: attendance: (
/* Veranstaltung, Jahr, regelmäßig besucht? */ /* Veranstaltung, Jahr, regelmäßig besucht? */
"Vorlesung": (year: "", did_attend: ""), event(name: "Vorlesung", year: "", did_attend: ""),
"Übung": (year: "", did_attend: ""), event(name: "Übung", year: "", did_attend: ""),
"Tutorium": (year: "", did_attend: ""), event(name: "Tutorium", year: "", did_attend: ""),
), ),
preparation_time: [ preparation_time: [
// Wie lange und wie hast alleine bzw. mit anderen vorbereitet? // Wie lange und wie hast alleine bzw. mit anderen vorbereitet?

View file

@ -16,9 +16,9 @@ Zum Erstellen des Dokumentes müssen lediglich die Argumente in der Datei
`main.typ` ausgefüllt werden. `main.typ` ausgefüllt werden.
```typst ```typst
#import "lib.typ": oral-exam, KIND #import "lib.typ": exam-report, event, KIND
#show: oral-exam.with( #show: exam-report.with(
study: "", // Studiengang study: "", // Studiengang
lecture: "", // Fach lecture: "", // Fach
kind: KIND.NONE, // Prüfungsart KIND.{DIPLOM, STAATSEXAM, STUDIENBEGLEITEND, BACHELOR, MASTER} kind: KIND.NONE, // Prüfungsart KIND.{DIPLOM, STAATSEXAM, STUDIENBEGLEITEND, BACHELOR, MASTER}
@ -29,12 +29,12 @@ Zum Erstellen des Dokumentes müssen lediglich die Argumente in der Datei
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft? checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft?
attendance: ( attendance: (
// Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP /* Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP */
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
), ),
attendance_worth: [ attendance_worth: [
// Wie regelmäßig hast du die Lehrveranstaltungen besucht? Hat sich der // Wie regelmäßig hast du die Lehrveranstaltungen besucht? Hat sich der

View file

@ -7,7 +7,11 @@
"NONE": "" "NONE": ""
) )
#let oral-exam( #let event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: "") = (
name, lecturer, year, sws, ects, lp
)
#let exam-report(
study: "", // Studiengang study: "", // Studiengang
lecture: "", // Fach lecture: "", // Fach
kind: KIND.NONE, // Prüfungsart KIND.{DIPLOM, STAATSEXAM, STUDIENBEGLEITEND, BACHELOR, MASTER} kind: KIND.NONE, // Prüfungsart KIND.{DIPLOM, STAATSEXAM, STUDIENBEGLEITEND, BACHELOR, MASTER}
@ -18,12 +22,12 @@
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft? checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft?
attendance: ( attendance: (
// Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP /* Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP */
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
), ),
attendance_worth: [ attendance_worth: [
// Wie regelmäßig hast du die Lehrveranstaltungen besucht? Hat sich der // Wie regelmäßig hast du die Lehrveranstaltungen besucht? Hat sich der
@ -92,7 +96,7 @@
) )
#show <attendance>: it => table(..grid_arguments(it), #show <attendance>: it => table(..grid_arguments(it),
..it.fields().children.at(0).children, ..it.fields().children.at(0).children,
..(attendance.map(lecture => lecture.values()).flatten() + 5*6*([],)).slice(0,count: 5*6) ..(attendance + 5*(event(),)).slice(0,5).flatten()
) )
#show <checked_knowledge_gaps>: [ #show <checked_knowledge_gaps>: [
#h(1fr) #h(1fr)
@ -106,5 +110,3 @@
#doc #doc
] ]
#oral-exam()[]

View file

@ -1,6 +1,6 @@
#import "lib.typ": oral-exam, KIND #import "lib.typ": exam-report, event, KIND
#show: oral-exam.with( #show: exam-report.with(
study: "", // Studiengang study: "", // Studiengang
lecture: "", // Fach lecture: "", // Fach
kind: KIND.NONE, // Prüfungsart KIND.{DIPLOM, STAATSEXAM, STUDIENBEGLEITEND, BACHELOR, MASTER} kind: KIND.NONE, // Prüfungsart KIND.{DIPLOM, STAATSEXAM, STUDIENBEGLEITEND, BACHELOR, MASTER}
@ -11,12 +11,12 @@
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft? checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft?
attendance: ( attendance: (
// Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP /* Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP */
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
(lecture: "", lecturer: "", year: "", sws: "", ects: "", lp: ""), event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
), ),
attendance_worth: [ attendance_worth: [
// Wie regelmäßig hast du die Lehrveranstaltungen besucht? Hat sich der // Wie regelmäßig hast du die Lehrveranstaltungen besucht? Hat sich der

View file

@ -16,9 +16,9 @@ Zum Erstellen des Dokumentes müssen lediglich die Argumente in der Datei
`main.typ` ausgefüllt werden. `main.typ` ausgefüllt werden.
```typst ```typst
#import "lib.typ": oral-exam, KIND #import "lib.typ": exam-report, event, KIND
#show: oral-exam.with( #show: exam-report.with(
study: "", // Studiengang study: "", // Studiengang
lecture: "", // Fach lecture: "", // Fach
kind: KIND.NONE, // Prüfungsart KIND.{WAHLPFLICHT, VERTIEFUNGSFACH, ERGUENZUNGSFACH} kind: KIND.NONE, // Prüfungsart KIND.{WAHLPFLICHT, VERTIEFUNGSFACH, ERGUENZUNGSFACH}
@ -30,10 +30,10 @@ Zum Erstellen des Dokumentes müssen lediglich die Argumente in der Datei
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
attendance: ( attendance: (
/* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */ /* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
), ),
attendance_worth: [ attendance_worth: [
// Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt? // Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt?

View file

@ -9,7 +9,11 @@
"NONE": "" "NONE": ""
) )
#let oral-exam( #let event(name: "", lecturer: "", year: "", did_attend: "") = (
name, lecturer, year, did_attend
)
#let exam-report(
study: "", // Studiengang study: "", // Studiengang
lecture: "", // Fach lecture: "", // Fach
kind: KIND.NONE, // Prüfungsart KIND.{WAHLPFLICHT, VERTIEFUNGSFACH, ERGUENZUNGSFACH} kind: KIND.NONE, // Prüfungsart KIND.{WAHLPFLICHT, VERTIEFUNGSFACH, ERGUENZUNGSFACH}
@ -21,10 +25,10 @@
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
attendance: ( attendance: (
/* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */ /* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
), ),
attendance_worth: [ attendance_worth: [
// Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt? // Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt?
@ -81,13 +85,10 @@
let g = it.fields() let g = it.fields()
let _ = g.remove("children") let _ = g.remove("children")
let _ = g.remove("label") let _ = g.remove("label")
let events = attendance.map(((lecture, lecturer, year, did_attend)) =>
(lecture, lecturer, year, did_attend)
).flatten()
table(..g, table(..g,
..it.fields().children.at(0).children, ..it.fields().children.at(0).children,
..(events + 4*4*([],)).slice(0,4*4) ..(attendance + 4*(event(),)).slice(0,4).flatten()
) )
} }

View file

@ -1,6 +1,6 @@
#import "lib.typ": oral-exam, KIND #import "lib.typ": exam-report, event, KIND
#show: oral-exam.with( #show: exam-report.with(
study: "", // Studiengang study: "", // Studiengang
lecture: "", // Fach lecture: "", // Fach
kind: KIND.NONE, // Prüfungsart KIND.{WAHLPFLICHT, VERTIEFUNGSFACH, ERGUENZUNGSFACH} kind: KIND.NONE, // Prüfungsart KIND.{WAHLPFLICHT, VERTIEFUNGSFACH, ERGUENZUNGSFACH}
@ -12,10 +12,10 @@
exam_duration: duration(minutes: 0), // Prüfungsdauer exam_duration: duration(minutes: 0), // Prüfungsdauer
attendance: ( attendance: (
/* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */ /* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
(lecture: "", lecturer: "", year: "", did_attend: ""), event(name: "", lecturer: "", year: "", did_attend: ""),
), ),
attendance_worth: [ attendance_worth: [
// Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt? // Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt?

3
src/computer-science.typ Normal file
View file

@ -0,0 +1,3 @@
#import "../muendliche-nachpruefung/lib.typ" as oral-post-exam
#import "../muendliche-pruefung/lib.typ" as oral-exam

3
src/lib.typ Normal file
View file

@ -0,0 +1,3 @@
#import "computer-science.typ"
#import "mathmatics.typ"

2
src/mathmatics.typ Normal file
View file

@ -0,0 +1,2 @@
#import "../muendliche-pruefung-mathematik/lib.typ" as oral-exam

79
template/main.typ Normal file
View file

@ -0,0 +1,79 @@
#import "@local/fsmi-exam-report:0.1.0": computer-science, mathmatics
/* Choose accordingly: */
// #import mathmatics.oral-exam: exam-report, event, KIND
// #import computer-science.oral-exam: exam-report, event, KIND
#import computer-science.oral-post-exam: exam-report, event
#show: exam-report.with(
lecture: "", // Fach
date: datetime(year: 0, month: 1, day: 1), // Prüfungsdatum
exam_duration: duration(minutes: 0), // Prüfungsdauer
examiner: "", // PrüferIn (Prof)
..if exam-report in (computer-science.oral-exam.exam-report, computer-science.oral-post-exam.exam-report) {(
assistant: "", // BeisitzerIn
)},
..if computer-science.oral-post-exam.exam-report == exam-report {(
did_pass: none, // Bestanden? true || false
)},
attendance:
if computer-science.oral-post-exam.exam-report == exam-report {(
/* Veranstaltung, Jahr, regelmäßig besucht? */
event(name: "Vorlesung", year: "", did_attend: ""),
event(name: "Übung", year: "", did_attend: ""),
event(name: "Tutorium", year: "", did_attend: ""),
)} else
if computer-science.oral-exam.exam-report == exam-report {(
/* Veranstaltung, Dozent(in), Jahr, regelmäßig besucht? */
event(name: "", lecturer: "", year: "", did_attend: ""),
event(name: "", lecturer: "", year: "", did_attend: ""),
event(name: "", lecturer: "", year: "", did_attend: ""),
event(name: "", lecturer: "", year: "", did_attend: ""),
)} else
if mathmatics.oral-exam.exam-report == exam-report {(
/* Titel der Vorlesung, Dozent, Wann gehört, SWS, ECTS, LP */
event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
event(name: "", lecturer: "", year: "", sws: "", ects: "", lp: ""),
)},
preparation_time: [
// Wie lange und wie hast alleine bzw. mit anderen vorbereitet?
// Hier ist Platz für deinen Kommentar
],
agreements: [
// Fanden vor der Prüfung Absprachen zu Form oder Inhalt statt? Wurden sie eingehalten?
// Hier ist Platz für deinen Kommentar
],
preparations: [
// Welche Tips zur Vorbereitung kannst Du geben?
// Hier ist Platz für deinen Kommentar
],
examiner_behavior: [
// Wie war der Prüfungsstil des Prüfers / der Prüferin?
// Hier ist Platz für deinen Kommentar
],
examinee_behavior: [
// Kannst Du Ratschläge Verhalten in der Prüfung geben?
// Hier ist Platz für deinen Kommentar
],
..if exam-report in (computer-science.oral-exam.exam-report, mathmatics.oral-exam.exam-report) {(
study: "", // Studiengang
attendance_worth: [
// Hat sich der Besuch / Nichtbesuch der Veranstaltung für dich gelohnt?
],
examiner_recommendation: (none, [ // true, false
// Kannst du ihn / sie weiterempfehlen? Warum?
]),
)},
..if mathmatics.oral-exam.exam-report == exam-report {(
checked_knowledge_gaps: none, // Wurde Unwissen abgeprüft?
literature: [
// Welche Literatur hast du benutzt (Bücher, Skripten, Vorlesungsmitschriften)?
],
)},
)
// Schreibe bitte möglichst viele Fragen und Antworten auf.
// Hier ist Platz für deinen Kommentar

23
typst.toml Normal file
View file

@ -0,0 +1,23 @@
# for a description of available keys, see https://github.com/typst/packages/?tab=readme-ov-file#package-format
[package]
name = "fsmi-exam-report"
version = "0.1.0"
entrypoint = "src/lib.typ"
authors = [
"Gero Beckmann <orangerot@orangerot.dev>"
]
license = "MIT"
description = "Exam Reports for Fachschaft Mathematik/Informatik at the Karlsruhe Institute of Technology"
homepage = ""
repository = ""
keywords = []
categories = []
disciplines = []
# compiler = ""
[template]
path = "template"
entrypoint = "main.typ"
# thumbnail = "thumbnail.png"