aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidpkj <davidpenkow1@gmail.com>2024-04-13 12:28:41 +0200
committerdavidpkj <davidpenkow1@gmail.com>2024-04-13 12:28:41 +0200
commit59b700299f860f0854c37906eaa5a5850cc45f59 (patch)
treebaf0e3010bf38da42382e49bbc480c8dc6e65b51
parentb291ddc44b9df8754c68f865383d206d9092c5a4 (diff)
univis stuff & docs
-rw-r--r--.vscode/settings.json1
-rw-r--r--README.adoc58
-rw-r--r--future_format.yaml16
-rw-r--r--package-lock.json22
-rw-r--r--package.json6
-rw-r--r--public/config.yaml55
-rw-r--r--public/style.css66
-rw-r--r--src/files.js20
-rw-r--r--src/main.js49
-rw-r--r--src/univis.js41
-rw-r--r--src/variables.js143
11 files changed, 289 insertions, 188 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1 @@
+{} \ No newline at end of file
diff --git a/README.adoc b/README.adoc
index 58a57a2..86ff908 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,6 +1,6 @@
= Stundenplan
-A small JavaScript project to generate beautiful PDF schedules. Takes information from `src/variables.js`. Planning to use direct UnivIS-XML export.
+A small JavaScript project to generate beautiful PDF schedules. Takes information from `src/variables.js`.
== Usage
@@ -10,3 +10,59 @@ Requires the `npm` tool.
npm i # installes packages
npm run main # runs the software
```
+
+=== Optional: Parse UnivIS XML
+
+You have the option to parse a full `public/data.xml` UnivIS export to get 80% of the way to a working configuration. You still have to manually clean up and refactor the information to yaml. But you dont have to write all those characters out.
+
+If you use vim, it then should be only a matter of seconds until you have your `.pdf`.
+
+```bash
+npm run parse
+```
+
+== Configuration Structure
+
+Generally, you may edit anything in the `public` directory. The default are how I like it.
+
+To configure the actual displayed information you shoudl edit the `.yaml` file. It should look something like the following, where things like `<THIS>` should be replaced by your text.
+
+Comments (things that are ignored by the software) is everything after a `#` sign. More information on the file format and syntax can be found https://yaml.org/[here].
+
+```yaml
+# General Information
+student: <YOUR NAME>
+semester: <THE SEMESTER>
+filename: <THE RESULT FILENAME> # i.e. Stundenplan_SS24.pdf
+
+# Each of these lines will be listed at the bottom of the PDF
+hinweise:
+ - <YOUR INFO> # i.e. "Mensabetrieb: 11:15 - 14:15 Uhr + 00:15 min"
+
+# Time definitions
+eintraege:
+ - <MODULE NAME>:
+ <LECTURE TYPE>:
+ - [<GERMAN ABBREVIATION FOR THE WEEKDAY>, <START TIME>, <END TIME>, <ROOM>]
+```
+
+Please note that times should be given in the format `HHhMM` so to say 9:19 AM, you would actually write 09h19. Also the Module and Lecture `BLOCKED` is reserved for a cross hatched block.
+
+So writing
+```yaml
+...
+ - BLOCKED:
+ BLOCKED:
+...
+```
+
+would put a blocked area in the pdf, instead of putting an actual block with the text "BLOCKED / BLOCKED".
+
+== Known issues
+
+- Doesnt work if not all days are set (null checks in general)
+- Have to use the exact yaml structure
+- Margin on the left not easily configurable
+- Mensa times are not actually displayed
+- All config.yaml items are required
+- Code is german spaghetti \ No newline at end of file
diff --git a/future_format.yaml b/future_format.yaml
deleted file mode 100644
index bbb9590..0000000
--- a/future_format.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-student: David Penkowoj
-semester: Sommersemester 2024
-hinweise:
- - "Mensabetrieb: 11:15 - 14:15 Uhr + 00:15 min"
- - "GET 2 / V am 23.05. & 04.07. im V1"
- - "GET 2 / Ü am 24.05. im T S2"
- - "FuQ / V am 24.05. im T S1"
-
-eintraege:
- - GET 2:
- U:
- - [Mo, 12h00, 13h00, AM S4]
- - [Fr, 11h30, 13h00, AM S4]
- V:
- - [Di, 08h30, 10h00, H 1]
- - [Do, 08h30, 10h00, Z 1/2]
diff --git a/package-lock.json b/package-lock.json
index fc58f20..d3e4a15 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,9 +12,9 @@
"html-pdf-node": "^1.0.8",
"js-yaml": "^4.1.0",
"jsdom": "^24.0.0",
- "jspdf": "^2.5.1"
- },
- "devDependencies": {}
+ "jspdf": "^2.5.1",
+ "xml-js": "^1.6.11"
+ }
},
"node_modules/@babel/runtime": {
"version": "7.24.4",
@@ -1309,6 +1309,11 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "node_modules/sax": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz",
+ "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA=="
+ },
"node_modules/saxes": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
@@ -1588,6 +1593,17 @@
}
}
},
+ "node_modules/xml-js": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
+ "dependencies": {
+ "sax": "^1.2.4"
+ },
+ "bin": {
+ "xml-js": "bin/cli.js"
+ }
+ },
"node_modules/xml-name-validator": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
diff --git a/package.json b/package.json
index 7eca5a1..7bbb1a8 100644
--- a/package.json
+++ b/package.json
@@ -7,10 +7,12 @@
"html-pdf-node": "^1.0.8",
"js-yaml": "^4.1.0",
"jsdom": "^24.0.0",
- "jspdf": "^2.5.1"
+ "jspdf": "^2.5.1",
+ "xml-js": "^1.6.11"
},
"scripts": {
- "main": "node src/main.js"
+ "main": "node src/main.js",
+ "parse": "node src/univis.js"
},
"author": "David Penkowoj",
"license": "GPL-3.0-or-later",
diff --git a/public/config.yaml b/public/config.yaml
new file mode 100644
index 0000000..c9bece2
--- /dev/null
+++ b/public/config.yaml
@@ -0,0 +1,55 @@
+# Allgemeine Informationen
+student: David Penkowoj
+semester: Sommersemester 2024
+filename: Stundenplan_SS24.pdf
+
+# Jeder hinweis wird unter dem Stundenplan aufgelistet
+hinweise:
+ - "Mensabetrieb: 11:15 - 14:15 Uhr + 00:15 min"
+ - "GET 2 / V am 23.05. & 04.07. im V1"
+ - "GET 2 / Ü am 24.05. im T S2"
+ - "FuQ / V am 24.05. im T S1"
+
+# Modul- und Veranstaltungsdefinitionen
+eintraege:
+ - GET 2:
+ U:
+ - [Mo, 12h00, 13h00, AM S4]
+ - [Fr, 11h30, 13h00, AM S4]
+ V:
+ - [Di, 08h30, 10h00, H 1]
+ - [Do, 08h30, 10h00, Z 1/2]
+ - TGI 1:
+ V:
+ - [Mi, 08h15, 09h45, AM 1]
+ U:
+ - [Do, 15h00, 16h00, AM 1]
+ Prak. Gr. 2:
+ - [Di, 14h30, 16h30, ITI 131]
+ - Pho:
+ V:
+ - [Fr, 08h30, 10h00, T 1]
+ U:
+ - [Mi, 12h00, 13h00, AM 1]
+ - Ana 2:
+ V:
+ - [Di, 12h30, 14h00, AM 1]
+ U:
+ - [Do, 16h15, 17h15, H 1]
+ Helpdesk:
+ - [Di, 18h00, 19h00, O-Sync]
+ - [Mi, 18h00, 19h00, O-Sync]
+ - EiBMO:
+ V:
+ - [Mi, 14h00, 16h00, H 1]
+ U:
+ - [Mi, 16h00, 17h00, H 1]
+ - FuQ:
+ V:
+ - [Fr, 10h00, 11h30, AM 4]
+ U:
+ - [Di, 11h00, 12h00, SI 4 (Minsky)]
+ - BLOCKED:
+ BLOCKED:
+ - [Mo, 13h00, 19h00, BLOCKED]
+ - [Do, 10h00, 15h00, BLOCKED] \ No newline at end of file
diff --git a/public/style.css b/public/style.css
new file mode 100644
index 0000000..acc57b4
--- /dev/null
+++ b/public/style.css
@@ -0,0 +1,66 @@
+* {
+ font-weight: 300;
+ font-family: "Abel", sans-serif;
+
+ print-color-adjust: exact;
+ -webkit-print-color-adjust: exact;
+
+ --entries-b: #ccc;
+ --entries-f: #111;
+ --headers-b: #333;
+ --headers-f: #fff;
+
+ --block: #ccc;
+}
+
+em {
+ font-style: normal;
+ text-decoration: underline;
+}
+
+table {
+ width: 100%;
+}
+
+table td,
+table tr {
+ background: var(--headers-f);
+ height: 4px;
+}
+
+table th,
+table td:not(:empty) {
+ background-color: var(--entries-b);
+ color: var(--entries-f);
+ padding: 0.5em 1em;
+ position: relative
+}
+
+table th {
+ background-color: var(--headers-b);
+ color: var(--headers-f);
+}
+
+table th.tag {
+ width: 20%;
+}
+
+table td {
+ font-size: 12px;
+}
+
+table td.block {
+ background-image: repeating-linear-gradient(314deg, var(--block), var(--block) 10px, transparent 10px, transparent 20px);
+ background-size: 99.9999999% 99.9999999%; /* because 100% gives wrong scaling for some reason */
+ border: 2px solid var(--block);
+}
+
+div {
+ position: absolute;
+ display: flex;
+
+ top: 0.4em;
+ left: 0.4em;
+ width: calc(100% - 0.8em);
+ justify-content: space-between;
+} \ No newline at end of file
diff --git a/src/files.js b/src/files.js
new file mode 100644
index 0000000..970d28d
--- /dev/null
+++ b/src/files.js
@@ -0,0 +1,20 @@
+import * as yml from "js-yaml"
+import * as fs from "fs"
+
+const dir = "./public";
+
+function readConfig() {
+ return yml.load(fs.readFileSync(`${dir}/config.yaml`, 'utf8'));
+}
+
+function readStyle() {
+ return fs.readFileSync(`${dir}/style.css`, 'utf8');
+}
+
+export function readXML() {
+ return fs.readFileSync(`${dir}/data.xml`, 'utf8');
+}
+
+export const c = readConfig();
+
+c.style = `<style>${readStyle()}</style>`; \ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 5b326d7..c3cbec9 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,10 +1,10 @@
import * as fs from "fs"
import * as html_to_pdf from "html-pdf-node"
-import * as v from './variables.js'
+import { c } from './files.js'
let hinweise = "<ul>";
-for (let hinweis of v.hinweise) {
+for (let hinweis of c.hinweise) {
hinweise += `<li>${hinweis}</li>`;
}
hinweise += `</ul>`;
@@ -133,14 +133,19 @@ function main() {
let tage = structuredClone(ctage);
let tage_runtimes = structuredClone(ctage);
- for (let eintrag of v.eintraege) {
- for (let termin of eintrag.termine) {
- tage[termin.wochentag].push({
- "name": eintrag.name,
- "raum": termin.raum,
- "von": termin.von,
- "bis": termin.bis,
- })
+ for (let eintrag of c.eintraege) {
+ let eintragName = Object.keys(eintrag)[0];
+ eintrag = eintrag[eintragName]
+
+ for (let veranstaltung in eintrag) {
+ for (let termin of eintrag[veranstaltung]) {
+ tage[termin[0]].push({
+ "name": `${eintragName.toString()} / ${veranstaltung.toString()}`,
+ "raum": termin[3],
+ "von": termin[1].replace("h", ":"),
+ "bis": termin[2].replace("h", ":"),
+ })
+ }
}
}
@@ -167,7 +172,7 @@ function main() {
let el = tage_runtimes[day][0];
- if (el.name == "BLOCKED" && el.raum == "BLOCKED") {
+ if (el.name.includes("BLOCKED") && el.raum == "BLOCKED") {
res += `<td rowspan="${el.runtime}" class="block"></td>`;
} else {
let name = el.name == "BUFFER" ? "" : `<div><span>${el.name}</span>`;
@@ -183,31 +188,29 @@ function main() {
res += "</tr>"
}
- // console.log(res)
-
return res
}
let html = `
-${v.style}
-<p>Persönlicher Stundenplan von ${v.student} für das ${v.semester}. Stand: ${date}.</p>
+${c.style}
+<p>Persönlicher Stundenplan von ${c.student} für das ${c.semester}. Stand: ${date}.</p>
<table>
<tr>
- <th> Uhrzeit </th>
- <th class="tag"> Montag </th>
- <th class="tag"> Dienstag </th>
- <th class="tag"> Mittwoch </th>
- <th class="tag"> Donnerstag </th>
- <th class="tag"> Freitag </th>
+ <th>Uhrzeit</th>
+ <th class="tag">Montag</th>
+ <th class="tag">Dienstag</th>
+ <th class="tag">Mittwoch</th>
+ <th class="tag">Donnerstag</th>
+ <th class="tag">Freitag</th>
</tr>
${main()}
</table>
<br>
-<u> Hinweise: </u>
+<em>Hinweise:</em>
${hinweise}
`;
html_to_pdf.generatePdf({content: html}, options).then(pdfBuffer => {
// fs.writeFileSync("test.html", html)
- fs.writeFileSync(v.filename, pdfBuffer);
+ fs.writeFileSync(c.filename, pdfBuffer);
});
diff --git a/src/univis.js b/src/univis.js
new file mode 100644
index 0000000..f770bd7
--- /dev/null
+++ b/src/univis.js
@@ -0,0 +1,41 @@
+import * as xml from "xml-js"
+
+import { readXML } from "./files.js"
+
+function getRoomName(key) {
+ for (let room of res.Room) {
+ if (room._attributes.key == key) {
+ return room.short._text;
+ }
+ }
+
+ return "?";
+}
+
+function serializeLecture(lecture) {
+ let name = lecture.short?._text ?? lecture.name._text
+
+ for (let term in lecture.terms) {
+ let t = lecture.terms[term];
+
+ if (!t.starttime) continue;
+
+ let von = t.starttime._text.replace(":", "h");
+ let bis = t.endtime._text.replace(":", "h");
+
+ let raum = getRoomName(t.room.UnivISRef._attributes.key);
+
+ console.log(`${name}, ${von}, ${bis}, ${raum}`);
+ }
+}
+
+let data = readXML();
+let res = (xml.xml2js(data, {compact: true})).UnivIS;
+
+let semester = res._attributes.semester;
+
+console.log("semester: " + semester)
+
+for (let lecture of res.Lecture) {
+ serializeLecture(lecture)
+} \ No newline at end of file
diff --git a/src/variables.js b/src/variables.js
deleted file mode 100644
index bf98ca1..0000000
--- a/src/variables.js
+++ /dev/null
@@ -1,143 +0,0 @@
-// Dont touch this
-class Eintrag {
- constructor(name, termine) {
- this.name = name;
- this.termine = termine;
- }
-}
-
-class Termin {
- constructor(wochentag, raum, von, bis) {
- this.wochentag = wochentag;
- this.raum = raum;
- this.von = von;
- this.bis = bis;
- }
-}
-
-// You may touch this
-export const student = "David Penkowoj";
-export const semester = "Sommersemester 2024";
-export const filename = `Stundenplan-${semester.replace(" ", "-")}.pdf`;
-
-export const hinweise = [
- "Mensabetrieb: 11:15 - 14:15 Uhr + 00:15 min",
- "GET 2 / V am 23.05. & 04.07. im V1",
- "GET 2 / Ü am 24.05. im T S2",
- "FuQ / V am 24.05. im T S1",
-];
-
-export const eintraege = [
- new Eintrag("GET 2 / Ü", [
- new Termin("Mo", "AM S4", "12:00", "13:00"),
- new Termin("Fr", "AM S4", "11:30", "13:00")
- ]),
- new Eintrag("GET 2 / V", [
- new Termin("Di", "H1", "08:30", "10:00"),
- new Termin("Do", "Z 1/2", "08:30", "10:00")
- ]),
- new Eintrag("TGI 1 / V", [
- new Termin("Mi", "AM 1", "08:15", "09:45"),
- ]),
- new Eintrag("TGI 1 / Ü", [
- new Termin("Do", "AM 1", "15:00", "16:00"),
- ]),
- new Eintrag("TGI 1 / Prak. Gr. 2", [
- new Termin("Di", "ITI 131", "14:30", "17:30"),
- ]),
- new Eintrag("Pho / V", [
- new Termin("Fr", "T 1", "08:30", "10:00"),
- ]),
- new Eintrag("Pho / Ü", [
- new Termin("Mi", "AM 1", "12:00", "13:00"),
- ]),
- new Eintrag("Ana 2 / V", [
- new Termin("Di", "AM 1", "12:30", "14:00"),
- ]),
- new Eintrag("Ana 2 / Ü", [
- new Termin("Do", "H 1", "16:15", "17:15"),
- ]),
- new Eintrag("Ana 2 / Helpdesk", [
- new Termin("Di", "O-Sync", "18:00", "19:00"),
- new Termin("Mi", "O-Sync", "18:00", "19:00")
- ]),
- new Eintrag("EiBMO / V", [
- new Termin("Mi", "H 1", "14:00", "16:00"),
- ]),
- new Eintrag("EiBMO / Ü", [
- new Termin("Mi", "H 1", "16:00", "17:00"),
- ]),
- new Eintrag("FuQ / V", [
- new Termin("Fr", "AM 4", "10:00", "11:30"),
- ]),
- new Eintrag("FuQ / Ü", [
- new Termin("Di", "SI 4 (Minsky)", "11:00", "12:00"),
- ]),
- new Eintrag("BLOCKED", [
- new Termin("Mo", "BLOCKED", "13:00", "19:00"),
- new Termin("Do", "BLOCKED", "10:00", "15:00")
- ])
-];
-
-// You may touch this, if you know what you are doing
-export const style = `
-<style>
- * {
- font-weight: 300;
- font-family: "Abel", sans-serif;
- -webkit-print-color-adjust: exact;
-
- --entries-b: #ccc;
- --entries-f: #111;
- --headers-b: #333;
- --headers-f: #fff;
-
- --block: #ccc;
- }
-
- table {
- width: 100%;
- }
-
- table td, table tr {
- background: var(--headers-f);
- height: 4px;
- }
-
- table th, table td:not(:empty) {
- background-color: var(--entries-b);
- color: var(--entries-f);
- padding: 0.5em 1em;
- position: relative
- }
-
- table th {
- background-color: var(--headers-b);
- color: var(--headers-f);
- }
-
- table th.tag {
- width: 20%;
- }
-
- table td {
- font-size: 12px;
- }
-
- table td.block {
- background-image: repeating-linear-gradient(314deg, var(--block), var(--block) 10px, transparent 10px, transparent 20px);
- background-size: 99.9999999% 99.9999999%;
- border: 2px solid var(--block);
- }
-
- div {
- position: absolute;
- display: flex;
-
- top: 0.4em;
- left: 0.4em;
- width: calc(100% - 0.8em);
- justify-content: space-between;
- }
-</style>
-`;