Initialer Commit

This commit is contained in:
2025-08-09 17:40:44 +02:00
parent 0880fe51c6
commit 07c230bc47
44 changed files with 13632 additions and 0 deletions

View File

@@ -1,2 +1,39 @@
# LehrerPDF
### Was ist LehrerPDF?
Beim vorliegenden Projekt handelt es sich um ein Python-Skript, das für beliebig viele Lerngruppen aus
- CSV-Dateien mit einer Namensliste für jede Lerngruppe und
- der Konfiguration der gewünschten Ausgabe für jede Lerngruppe
eine gemeinsame PDF-Datei generiert, die für jede Lerngruppe
- ein Deckblatt zur Planung des Halbjahres,
- eine Geburtstagsliste,
- eine Notenübersicht für die Lerngruppe,
- für jede Lernerfolgskontrolle eine Punkte- und Notentabelle,
- für jedes Quartal eine Tabelle zur Erfassung von SoMi-Notizen,
- eine Tabelle zur HA-Kontrolle und
- Checklisten-Tabellen zum Abhaken
für ein Halbjahr umfasst. Zusätzlich kann optional als Startseite der Stundenplan eingebunden werden.
Diese PDF-Datei kann anschließend mit einem Tablet und einem Eingabestift mit Inhalt gefüllt werden. Alle Bestandteile sind untereinander verlinkt, so dass zwischen der Bearbeitung der diversen Tabellen der Lerngruppe sowie zwischen den Lerngruppen schnell gewechselt werden kann.
Die PDF-Ausgabe kann aktuell wahlweise für die folgenden Geräte optimiert erzeugt werden. Verlinkt ist zur Illustration für jedes Gerät die aus den vorliegenden (fiktiven) Beispieldaten erzeugte PDF-Ausgabe.
- [reMarkable 2](./src/data/rm2.pdf)
- [reMarkable PaperPro](./src/data/paperpro.pdf)
- [DIN A4](src/data/a4.pdf) (für beliebige Geräte)
### Dokumentation der Verarbeitung
Die Verarbeitung gliedert sich in zwei Schritte:
- Schritt 1: [Konfiguration durch den Benutzer](./doc/konfiguration.md)
- Schritt 2: [Erzeugung des Zieldokuments](./doc/erzeugung.md)

35
doc/allgemein.md Normal file
View File

@@ -0,0 +1,35 @@
# Konfiguration der Ausgabe (allgemeiner Teil)
Neben der Festlegungen für jede Lerngruppe sind einige allgemeine Festlegungen zu treffen, die am einfachsten zu Beginn der Datei ``input.ini`` beschrieben werden (vgl. Markierung ``Allgemein`` im Beispiel):
```
[Allgemein]
# Bezeichnung des Schuljahrs (Startjahr angeben - Beispiel: 2025 für 2025/26)
schuljahr = 2025
# Halbjahr: 1, 2
halbjahr = 1
# Kalenderwochen des Halbjahres für die Übersichtsseite
kw_start = 35
kw_ende = 6
# Startseite: Binde den Stundenplan aus der angegebenen Datei ein (leer: kein Stundenplan)
stundenplandatei = stundenplan.md
# Trenner der Spalten in den CSV-Eingabedateien
csvtrenner = ;
# Ausgabegerät: rm2, paperpro, a4
device = rm2
```
Die Parameter sind zwar selbsterklärend, werden hier aber dennoch einmal kurz erläutert:
- Als Schuljahr ist das Jahr einzutragen, in dem das Schuljahr beginnt.
- Für das Halbjahr ist eine 1 oder 2 einzutragen.
- Für die Übersichtsseite des Habjahrs sind die Kalenderwoche des Beginns und die Kalenderwoche des Endes anzugeben. (Es liegt in der Natur der Sache, dass die beiden Zahlen nicht aufsteigend sein müssen, wenn ein Halbjahr zwei Kalenderjahre umfasst. Das Skript berücksichtigt dies automatisch.)
- Soll die Startseite des Zieldokuments einen Stundenplan enthalten, so ist dieser im Eingabeverzeichnis als Markdown Dokument anzugeben (vgl. auch nächster Abschnitt). Der Dateiname wird hier festgelegt. Fehlt der Dateiname, so wird der Stundenplan automatisch weggelassen.
- Für die CSV Dateien kann hier das Symbol zum Trennen der Spalte (voreingestellt Semikolon) bei Bedarf angepasst werden.
- Zum Schluss kommt die wichtigste Festlegung, das Zielgerät. Hier kann aktuell zwischen ``rm2`` (reMarkable 2), ``paperpro`` (reMarkable Paper Pro) und ``a4`` (DIN A4) gewählt werden.

23
doc/basiskonfiguration.md Normal file
View File

@@ -0,0 +1,23 @@
# Basiskonfiguration
Die Basiskonfiguration ist in der Datei ``lehrerpdf.ini`` zu finden, die im gleichenVerzeichnis wie das Python-Skript ``lehrerpdf.py`` liegt (vgl. Verzeichnis [src/](../src/)).
Aktuell wird in der Basiskonfiguration nur das Verzeichnis der Eingabedateien des Benutzers festgelegt. Als Standard ist das Unterverzeichnis ``data/`` eingetragen:
```
[Allgemein]
# Pfad (relativ oder absolut zu den Eingabedateien)
pfad = data/
```
Da im Unterverzeichnis ``data/`` (fiktive) Beispieldateien abgelegt sind, die als Ausgangspunkt zum Experimentieren mit dem Tool sicherlich hilfreich sind, empfiehlt es sich nicht die eigenen Dateien in diesem Verzeichnis abzulegen. Stattdessen sollten die Dateien separat abgelegt werden und das zugehörige Verzeichnis in der Basiskonfiguration angepasst werden.
Da ein Update des Tools eine Veränderung der Datei ``lehrerpdf.ini`` wieder überschreiben würde, wird folgende Vorgehensweise empfohlen: Legen Sie im gleichen Verzeichnis die Datei ``mylehrerpdf.ini`` an und passen Sie dort das Eingabeverzeichnis an. Die Datei ``mylehrerpdf.ini`` wird der Datei ``lehrerpdf.ini`` gegenüber durch das Skript bevorzugt.
Sie können wahlweise einen relativen Pfad oder einen absoluten Pfad angeben. Bitte beachten Sie, dass unter Windows die Backslashs \ zum Trennen der Verzeichnisse jeweils doppelt angegeben werden müssen:
```
/Users/username/Desktop/MeineDaten
c:\\Dokumente\\Desktop\\MeineDaten
```

21
doc/csv.md Normal file
View File

@@ -0,0 +1,21 @@
# CSV-Datei jede Lerngruppe
Für jede Lerngruppe ist eine Namensliste als CSV-Datei im Eingabeverzeichnis abzulegen. Als Spalten sind (in dieser Reihenfolge) der Nachname, der Vorname und das Geburtsdatum der Schülerin bzw. des Schülers anzugeben.
Evtl. weitere Spalten werden ignoriert. Fehlt das Geburtsdatum, so wird bei der Erzeugung der Ausgabe die Geburtstagsliste automatisch weggelassen.
Die Kopfzeile mit den Namen der Spalten wird vorausgesetzt und beim Einlesen übersprungen. Fehlt bei Ihrem Dokument die Kopfzeile, so fügen Sie sie bitte nachträglich ein.
Das folgende Listing zeigt einen Ausschnitt aus der Datei [klasse-5a.csv](../src/data/klasse-5a.csv) aus den Beispieldaten.
```csv
Name;Vorname;Geburtsdatum
Bauer;Felix;11.6.2014
Bauer;Lukas;7.2.2014
Bauer;Marie;6.11.2014
Bauer;Sophia;8.3.2015
Fischer;Sophia;17.11.2014
Hoffmann;Marie;20.4.2015
```
Der Dateiname ist für die Verarbeitung von zentraler Bedeutung. Zum einen richtet sich danach die Sortierung der Lerngruppen bei der Anordnung im Zieldokument. Zum anderen wird der Name (ohne die Endung .csv) als ID für die Konfiguration der Ausgabe für die zugehörige Lerngruppe benötigt.

41
doc/erzeugung.md Normal file
View File

@@ -0,0 +1,41 @@
# Erzeugung des PDF-Ausgabedokuments
Zu diesem Zeitpunkt sollte die Konfiguration abgeschlossen sein. Das PDF-Zieldokument kann nun erzeugt werden. Dazu muss das Python-Skript ``lehrerpdf.py``gestartet werden.
### Voraussetzungen
Hierzu sind einige Voraussetzungen zu erfüllen:
1. Auf dem eingesetzten Rechner muss [Python](https://www.python.org) auf der Kommandozeile installiert sein. (Das vorliegende Skript wurde unter Python 3.13 entwickelt und getestet. Es sollte aber auch mit älteren Python Versionen lauffähig sein.) Da Python plattformunabhängig ist, ist auch das vorliegende Projekt plattformunabhängig.
2. Die beiden Python-Module ``xhtml2pdf`` und ``markdown`` müssen installiert sein.
```python
pip3 install xhtml2pdf
pip3 install markdown
```
### Starten des Skripts
Nun kann das Skript gestartet werden:
```
python3 lehrerpdf.py
```
Auf der Konsole werden die Verarbeitungsschritte dokumentiert und auch evtl. Fehler bei der Verarbeitung angezeigt:
```
Verarbeite das Verzeichnis: data/
Verarbeite Datei: data/klasse-5a.csv
Verarbeite Datei: data/klasse-6b.csv
Verarbeite Datei: data/kurs-if-9.csv
Verarbeite Datei: data/kurs-if-ef.csv
Erzeuge PDF-Datei: rm2.pdf
Fertig!
```
Die Ausgabedatei, dessen Namen das Zielgerät angibt (im obigen Beispiel ``rm2.pdf``
für das Ziel Gerät reMarkable 2), wird dabei im Verzeichnis der Eingabedateien abgelegt.

24
doc/konfiguration.md Normal file
View File

@@ -0,0 +1,24 @@
# Konfiguration
Die Konfiguration gliedert sich in zwei Teile.
### 1. Basiskonfiguration
Die Eingabe des Python-Skripts besteht aus mehreren Dateien, die im nachfolgenden Abschnitt genauer beschrieben werden. Der Pfad zu diesen Eingabedateien wird in der Basiskonfiguration festgelegt.
- [Basiskonfiguration](basiskonfiguration.md) (Datei ``lehrerpdf.ini``)
### 2. Konfiguration der PDF-Ausgabe
Für die Erzeugung der PDF-Ausgabe ist pro Lerngruppe eine CSV-Datei mit den Namen der SchülerInnen erforderlich. Zusätzlich können für jede Lerngruppe diverse Parameter zur Darstellung der Ausgabe konfiguriert werden. Einige allgemeine Parameter wie das aktuelle Halbjahr gelten dabei für alle Lerngruppen. Der optionale Stundenplan wird auf der Startseite dargestellt.
- [CSV-Datei jede Lerngruppe](csv.md)
- Konfiguration der Ausgabe (Datei ``input.ini``)
- [allgemeiner Teil](allgemein.md)
- [Teil für jede Lerngruppe](lerngruppe.md)
- [Stundenplan-Datei](stundenplan.md)

46
doc/lerngruppe.md Normal file
View File

@@ -0,0 +1,46 @@
# Konfiguration der Ausgabe (für jede Lerngruppe)
In der Datei ``input.ini`` im Eingabeverzeichnis wird für neben einigen allgemeinen Festlegungen für jede Lerngruppe die gewünschte Ausgabe konfiguriert. Dabei wird die ID aus dem Dateinamen als Bereichsmarkierung (vgl. ``klasse-5a`` im Beispiel) benötigt.
```python
[klasse-5a]
# Bezeichnung der Lerngruppe
bezeichnung = Mathe 5a
# Kurzbezeichnung der Lerngruppe
kurzbezeichnung = Mathe 5a
# Anzahl Arbeiten oder Klausuren: 0, 1, 2, ... (0=keine Arbeiten/Klausuren)
schriftlich_anzahl = 3
# Bezeichnung Arbeit oder Klausur o.ä.
schriftlich_bez = Arbeit
# Anzahl der Quartale bei der SoMi-Erfassung: 1 (gemeinsames) oder 2 (getrennte)
somi_quartale = 2
# Anzahl der Zeilen pro Schüler in einem SoMi-Bogen: 1, 2, ...
somi_zeilen = 2
# Spalte für Halbjahresnote im 2. Hj. in Übersicht einblenden: ja, nein
halbjahresnote = ja
# Anzahl der Zeilen pro Schüler in einem HA-Bogen: 0, 1, 2, ... (0=kein HA-Bogen)
ha_zeilen = 1
# Anzahl der Seiten mit Checkliste: 1, 2, ...
checkliste_seiten = 2
```
Die Parameter sind zwar selbsterklärend, werden hier aber dennoch einmal kurz erläutert:
- Die Bezeichnung der Lerngruppe wird als Überschrift überall dort verwendet, wo genügend Platz zur Verfügung steht.
- Ist nur wenig Platz vorhanden (z.B. im Stundenplan oder in der Navigationsleiste), kommt die Kurzbeschreibung der Lerngruppe zum Einsatz.
- Die Anzahl der schriftlichen Lernerfolgskontrollen gibt an, wie viele Korrekturbögen erzeugt werden. Die Anzahl 0 sorgt dafür, dass diese automatisch weggelassen werden.
- Die Bezeichnung der Lernerfolgskontrolle passt sich dem Sprachgebrauch an, z.B. Arbeit oder Kursarbeit oder Klausur.
- Bei der Erfassung von Notizen zur Sonstigen Mitarbeit (SoMi) wird angegeben, ob eine durchlaufende Liste für beide Quartale oder zwei getrennte Listen für die beiden Quartale generiert werden sollen.
- Zudem können eine oder mehrere Zeilen pro SchülerIn erzeugt werden.
- In der Notenübersicht des zweiten Halbjahres kann optional eine Spalte für die Note des ersten Halbjahres angelegt werden.
- Bei der Erfassung von Hausaufgaben bzw. deren Nichterledigung können eine oder mehrere Zeilen pro SchülerIn angelegt werden. Die Anzahl 0 sorgt dafür, dass Hausaufgabenlisten ganz weggelassen werden.
- Abschließend kann die Anzahl der Checklisten für diese Lerngruppe festgelegt werden. Hier empfiehlt es sich lieber zu viele Listen zu konfigurieren, da das Einfügen zusätzlicher Seiten die Verweise (Links) im PDF Zieldokument unbrauchbar macht.

26
doc/stundenplan.md Normal file
View File

@@ -0,0 +1,26 @@
# Stundenplan
Wird ein Stundenplan auf der Startseite gewünscht, so wird die im allgemeinen Teil der Ausgabekonfiguration angegebene Markdown-Datei eingelesen und aufbereitet.
Die Beispieldatei ``stundenplan.md`` kann dabei als Ausgangspunkt verwendet werden:
```md
| St. | Montag | Dienstag | Mittwoch | Donnerstag | Freitag |
| :------: | :----------: | :----------: | :----------: | :----------: | :----------: |
| 1.<br>2. | [klasse-5a] | [klasse-6b] | | | |
| 3.<br>4. | [klasse-6b] | [kurs-if-ef] | [klasse-5a] | | |
| 5.<br>6. | [kurs-if-9] | | [kurs-if-ef] | | |
| 7. | | | | | |
| 8.<br>9. | | [kurs-if-9] | | | |
```
Dabei ist zu beachten:
- Durch ``<br>`` kann ein Zeilenumbruch in einer Zelle erzwungen werden kann.
- Die Spalten der Tabelle werden durch ``|`` voneinander abgetrennt.
- Wird die ID einer Lerngruppe in eckige Klammern gesetzt (z.B. ``[klasse-5a]``), so wird die Aufbereitung automatisch einen Verweis auf die Seite generieren, auf der die Informationen zur zugehörigen Lerngruppe beginnen.
- Die Aufteilung der sechs Spalten (Stunde, Montag, ...) sollte möglichst beibehalten werden. Bei der Aufbereitung wird die erste Spalte enger dargestellt, alle übrigen Spalten werden gleich breit formatiert.
Fehlt die Datei für den Stundenplan (bewusst oder versehentlich), so wird automatisch auf die Berücksichtigung eines Stundenplans auf der Startseite verzichtet.

3698
src/data/a4.pdf Normal file

File diff suppressed because one or more lines are too long

140
src/data/input.ini Normal file
View File

@@ -0,0 +1,140 @@
[Allgemein]
# Bezeichnung des Schuljahrs (Startjahr angeben - Beispiel: 2025 für 2025/26)
schuljahr = 2025
# Halbjahr: 1, 2
halbjahr = 1
# Kalenderwochen des Halbjahres für die Übersichtsseite
kw_start = 35
kw_ende = 6
# Startseite: Binde den Stundenplan aus der angegebenen Datei ein (leer: kein Stundenplan)
stundenplandatei = stundenplan.md
# Trenner der Spalten in den CSV-Eingabedateien
csvtrenner = ;
# Ausgabegerät: rm2, paperpro, a4
device = rm2
[klasse-5a]
# Bezeichnung der Lerngruppe
bezeichnung = Mathe 5a
# Kurzbezeichnung der Lerngruppe (für Stundenplan)
kurzbezeichnung = Mathe 5a
# Anzahl Arbeiten oder Klausuren: 0, 1, 2, ... (0=keine Arbeiten/Klausuren)
schriftlich_anzahl = 3
# Bezeichnung Arbeit oder Klausur o.ä.
schriftlich_bez = Arbeit
# Anzahl der Quartale bei der SoMi-Erfassung: 1 (gemeinsames) oder 2 (getrennte)
somi_quartale = 2
# Anzahl der Zeilen pro Schüler in einem SoMi-Bogen: 1, 2, ...
somi_zeilen = 2
# Spalte für Halbjahresnote im 2. Hj. in Übersicht einblenden: ja, nein
halbjahresnote = ja
# Anzahl der Zeilen pro Schüler in einem HA-Bogen: 0, 1, 2, ... (0=kein HA-Bogen)
ha_zeilen = 1
# Anzahl der Seiten mit Checkliste: 1, 2, ...
checkliste_seiten = 2
[klasse-6b]
# Bezeichnung der Lerngruppe
bezeichnung = Mathe 6b
# Kurzbezeichnung der Lerngruppe (für Stundenplan)
kurzbezeichnung = Mathe 6b
# Anzahl Arbeiten oder Klausuren: 0, 1, 2, ... (0=keine Arbeiten/Klausuren)
schriftlich_anzahl = 3
# Bezeichnung Arbeit oder Klausur o.ä.
schriftlich_bez = Arbeit
# Anzahl der Quartale bei der SoMi-Erfassung: 1 (gemeinsames) oder 2 (getrennte)
somi_quartale = 2
# Anzahl der Zeilen pro Schüler in einem SoMi-Bogen: 1, 2, ...
somi_zeilen = 2
# Spalte für Halbjahresnote im 2. Hj. in Übersicht einblenden: ja, nein
halbjahresnote = ja
# Anzahl der Zeilen pro Schüler in einem HA-Bogen: 0, 1, 2, ... (0=kein HA-Bogen)
ha_zeilen = 1
# Anzahl der Seiten mit Checkliste: 1, 2, ...
checkliste_seiten = 2
[kurs-if-9]
# Bezeichnung der Lerngruppe
bezeichnung = Informatik 9
# Kurzbezeichnung der Lerngruppe (für Stundenplan)
kurzbezeichnung = Info 9
# Anzahl Arbeiten oder Klausuren: 0, 1, 2, ... (0=keine Arbeiten/Klausuren)
schriftlich_anzahl = 2
# Bezeichnung Arbeit oder Klausur o.ä.
schriftlich_bez = Kursarbeit
# Anzahl der Quartale bei der SoMi-Erfassung: 1 (gemeinsames) oder 2 (getrennte)
somi_quartale = 1
# Anzahl der Zeilen pro Schüler in einem SoMi-Bogen: 1, 2, ...
somi_zeilen = 2
# Spalte für Halbjahresnote im 2. Hj. in Übersicht einblenden: ja, nein
halbjahresnote = ja
# Anzahl der Zeilen pro Schüler in einem HA-Bogen: 0, 1, 2, ... (0=kein HA-Bogen)
ha_zeilen = 0
# Anzahl der Seiten mit Checkliste: 1, 2, ...
checkliste_seiten = 2
[kurs-if-ef]
# Bezeichnung der Lerngruppe
bezeichnung = Informatik EF
# Kurzbezeichnung der Lerngruppe (für Stundenplan)
kurzbezeichnung = Info EF
# Anzahl Arbeiten oder Klausuren: 0, 1, 2, ... (0=keine Arbeiten/Klausuren)
schriftlich_anzahl = 2
# Bezeichnung Arbeit oder Klausur o.ä.
schriftlich_bez = Klausur
# Anzahl der Quartale bei der SoMi-Erfassung: 1 (gemeinsames) oder 2 (getrennte)
somi_quartale = 2
# Anzahl der Zeilen pro Schüler in einem SoMi-Bogen: 1, 2, ...
somi_zeilen = 2
# Spalte für Halbjahresnote im 2. Hj. in Übersicht einblenden: ja, nein
halbjahresnote = ja
# Anzahl der Zeilen pro Schüler in einem HA-Bogen: 0, 1, 2, ... (0=kein HA-Bogen)
ha_zeilen = 0
# Anzahl der Seiten mit Checkliste: 1, 2, ...
checkliste_seiten = 2

25
src/data/klasse-5a.csv Normal file
View File

@@ -0,0 +1,25 @@
Name;Vorname;Geburtsdatum
Bauer;Felix;11.6.2014
Bauer;Lukas;7.2.2014
Bauer;Marie;6.11.2014
Bauer;Sophia;8.3.2015
Fischer;Sophia;17.11.2014
Hoffmann;Marie;20.4.2015
Meyer;Lena;20.5.2014
Müller;Anna;19.6.2014
Müller;Felix;24.4.2014
Schmidt;Felix;21.2.2014
Schmidt;Leon;18.9.2014
Schmidt;Paul;14.10.2014
Schneider;Leon;1.1.2015
Schneider;Sophia;21.3.2015
Schneider;Sophia;7.1.2015
Schulz;Felix;18.2.2015
Schulz;Laura;11.4.2014
Schulz;Marie;16.8.2014
Schulz;Max;28.3.2014
Schulz;Paul;16.6.2015
Schulz;Paul;23.9.2014
Weber;Felix;7.3.2014
Weber;Paul;17.2.2014
Wiesner;Lukas;10.8.2014
1 Name Vorname Geburtsdatum
2 Bauer Felix 11.6.2014
3 Bauer Lukas 7.2.2014
4 Bauer Marie 6.11.2014
5 Bauer Sophia 8.3.2015
6 Fischer Sophia 17.11.2014
7 Hoffmann Marie 20.4.2015
8 Meyer Lena 20.5.2014
9 Müller Anna 19.6.2014
10 Müller Felix 24.4.2014
11 Schmidt Felix 21.2.2014
12 Schmidt Leon 18.9.2014
13 Schmidt Paul 14.10.2014
14 Schneider Leon 1.1.2015
15 Schneider Sophia 21.3.2015
16 Schneider Sophia 7.1.2015
17 Schulz Felix 18.2.2015
18 Schulz Laura 11.4.2014
19 Schulz Marie 16.8.2014
20 Schulz Max 28.3.2014
21 Schulz Paul 16.6.2015
22 Schulz Paul 23.9.2014
23 Weber Felix 7.3.2014
24 Weber Paul 17.2.2014
25 Wiesner Lukas 10.8.2014

24
src/data/klasse-6b.csv Normal file
View File

@@ -0,0 +1,24 @@
Name;Vorname;Geburtsdatum
Bauer;Lena;5.6.2014
Bauer;Marie;6.11.2014
Fischer;Laura;5.3.2013
Fischer;Lena;1.3.2013
Fischer;Leon;27.3.2013
Fischer;Lukas;21.9.2013
Fischer;Lukas;23.8.2013
Fischer;Marie;10.6.2013
Fischer;Max;24.6.2014
Hoffmann;Paul;4.4.2014
Meyer;Laura;12.10.2013
Meyer;Lena;20.5.2014
Schmidt;Laura;18.3.2013
Schmidt;Leon;26.5.2013
Schmidt;Lukas;23.9.2013
Schneider;Sophia;13.7.2013
Schulz;Max;28.3.2014
Weber;Laura;7.5.2013
Weber;Lena;13.3.2013
Wiesner;Felix;15.1.2013
Wiesner;Lena;26.12.2013
Wiesner;Leon;17.12.2013
Wiesner;Lukas;23.7.2013
1 Name Vorname Geburtsdatum
2 Bauer Lena 5.6.2014
3 Bauer Marie 6.11.2014
4 Fischer Laura 5.3.2013
5 Fischer Lena 1.3.2013
6 Fischer Leon 27.3.2013
7 Fischer Lukas 21.9.2013
8 Fischer Lukas 23.8.2013
9 Fischer Marie 10.6.2013
10 Fischer Max 24.6.2014
11 Hoffmann Paul 4.4.2014
12 Meyer Laura 12.10.2013
13 Meyer Lena 20.5.2014
14 Schmidt Laura 18.3.2013
15 Schmidt Leon 26.5.2013
16 Schmidt Lukas 23.9.2013
17 Schneider Sophia 13.7.2013
18 Schulz Max 28.3.2014
19 Weber Laura 7.5.2013
20 Weber Lena 13.3.2013
21 Wiesner Felix 15.1.2013
22 Wiesner Lena 26.12.2013
23 Wiesner Leon 17.12.2013
24 Wiesner Lukas 23.7.2013

19
src/data/kurs-if-9.csv Normal file
View File

@@ -0,0 +1,19 @@
Name;Vorname;Geburtsdatum
Bauer;Felix;15.7.2010
Bauer;Max;28.11.2010
Fischer;Lukas;3.5.2011
Hoffmann;Lena;14.2.2011
Hoffmann;Lukas;8.8.2010
Meyer;Lukas;28.9.2010
Müller;Leon;9.3.2011
Schmidt;Laura;25.12.2010
Schneider;Sophia;12.4.2010
Schulz;Sophia;15.6.2010
Weber;Felix;27.2.2011
Weber;Lukas;8.6.2011
Wiesner;Anna;10.4.2010
Wiesner;Felix;18.11.2010
Wiesner;Lena;28.2.2010
Wiesner;Max;1.11.2010
Wiesner;Paul;26.3.2010
Wiesner;Sophia;23.6.2011
1 Name Vorname Geburtsdatum
2 Bauer Felix 15.7.2010
3 Bauer Max 28.11.2010
4 Fischer Lukas 3.5.2011
5 Hoffmann Lena 14.2.2011
6 Hoffmann Lukas 8.8.2010
7 Meyer Lukas 28.9.2010
8 Müller Leon 9.3.2011
9 Schmidt Laura 25.12.2010
10 Schneider Sophia 12.4.2010
11 Schulz Sophia 15.6.2010
12 Weber Felix 27.2.2011
13 Weber Lukas 8.6.2011
14 Wiesner Anna 10.4.2010
15 Wiesner Felix 18.11.2010
16 Wiesner Lena 28.2.2010
17 Wiesner Max 1.11.2010
18 Wiesner Paul 26.3.2010
19 Wiesner Sophia 23.6.2011

31
src/data/kurs-if-ef.csv Normal file
View File

@@ -0,0 +1,31 @@
Name;Vorname;Geburtsdatum
Bauer;Leon;4.4.2008
Bauer;Lukas;4.2.2008
Bauer;Lukas;8.6.2009
Bauer;Max;19.12.2008
Bauer;Paul;15.4.2008
Fischer;Felix;16.8.2008
Fischer;Laura;22.9.2008
Fischer;Leon;13.8.2008
Fischer;Lukas;5.5.2009
Fischer;Marie;9.3.2008
Fischer;Max;13.11.2008
Hoffmann;Anna;24.11.2008
Hoffmann;Laura;18.11.2008
Hoffmann;Max;27.11.2008
Meyer;Max;5.11.2008
Müller;Anna;12.4.2009
Müller;Lena;10.1.2008
Müller;Leon;5.3.2008
Müller;Sophia;12.8.2008
Müller;Sophia;21.7.2008
Schmidt;Anna;20.1.2008
Schmidt;Anna;5.1.2008
Schmidt;Laura;23.7.2008
Schneider;Lena;1.2.2009
Schneider;Marie;1.8.2008
Schneider;Paul;22.10.2008
Schneider;Sophia;1.9.2008
Schulz;Laura;9.8.2008
Weber;Laura;28.10.2008
Weber;Lena;14.9.2008
1 Name Vorname Geburtsdatum
2 Bauer Leon 4.4.2008
3 Bauer Lukas 4.2.2008
4 Bauer Lukas 8.6.2009
5 Bauer Max 19.12.2008
6 Bauer Paul 15.4.2008
7 Fischer Felix 16.8.2008
8 Fischer Laura 22.9.2008
9 Fischer Leon 13.8.2008
10 Fischer Lukas 5.5.2009
11 Fischer Marie 9.3.2008
12 Fischer Max 13.11.2008
13 Hoffmann Anna 24.11.2008
14 Hoffmann Laura 18.11.2008
15 Hoffmann Max 27.11.2008
16 Meyer Max 5.11.2008
17 Müller Anna 12.4.2009
18 Müller Lena 10.1.2008
19 Müller Leon 5.3.2008
20 Müller Sophia 12.8.2008
21 Müller Sophia 21.7.2008
22 Schmidt Anna 20.1.2008
23 Schmidt Anna 5.1.2008
24 Schmidt Laura 23.7.2008
25 Schneider Lena 1.2.2009
26 Schneider Marie 1.8.2008
27 Schneider Paul 22.10.2008
28 Schneider Sophia 1.9.2008
29 Schulz Laura 9.8.2008
30 Weber Laura 28.10.2008
31 Weber Lena 14.9.2008

3870
src/data/paperpro.pdf Normal file

File diff suppressed because one or more lines are too long

4100
src/data/rm2.pdf Normal file

File diff suppressed because one or more lines are too long

8
src/data/stundenplan.md Normal file
View File

@@ -0,0 +1,8 @@
| St. | Montag | Dienstag | Mittwoch | Donnerstag | Freitag |
| :------: | :----------: | :----------: | :----------: | :----------: | :----------: |
| 1.<br>2. | [klasse-5a] | [klasse-6b] | | | |
| 3.<br>4. | [klasse-6b] | [kurs-if-ef] | [klasse-5a] | | |
| 5.<br>6. | [kurs-if-9] | | [kurs-if-ef] | | |
| 7. | | | | | |
| 8.<br>9. | | [kurs-if-9] | | | |

7
src/devices/a4.css Normal file
View File

@@ -0,0 +1,7 @@
@page {
size: a4 portrait;
margin-left: 0.5cm;
margin-right: 0.5cm;
margin-top: 0.25cm;
margin-bottom: 0.25cm;
}

35
src/devices/a4.ini Normal file
View File

@@ -0,0 +1,35 @@
[Navigation]
# Lerngruppenbezeichnung in der Navileiste (Zeilenumbruch vermeiden): kurz, normal
bezeichnung = normal
[Startseite]
# Schriftgröße der Kalenderwochen (Seitenumbruch vermeiden): normal, klein
schrift = normal
[Korrekturbogen]
# Anzahl der Aufgaben in der Korrekturtabelle: 1, 2, 3, ...
anzahl_aufgaben = 6
[SoMiNoten]
# Anzahl der SoMi-Noten-Spalten
anzahl_noten = 10
[Hausaufgaben]
# Anzahl der HA-Noten-Spalten
anzahl_ha = 10
# Umschalten auf kleine Schrift ab X Schülern (Seitenumbruch vermeiden): 20, 21, 22, ...
umschalten_kleinschrift = 30
[Checkliste]
# Anzahl der Check-Spalten
anzahl_checks = 10
# Umschalten auf kleine Schrift ab X Schülern (Seitenumbruch vermeiden): 20, 21, 22, ...
umschalten_kleinschrift = 30

303
src/devices/general.css Normal file
View File

@@ -0,0 +1,303 @@
/* Schrift überall */
h1, th, td, h1 {
font-family: Helvetica;
font-weight: lighter;
}
th, td {
font-size: 140%;
}
th {
font-weight: 500;
}
/* Lerngruppennavigation */
table.lerngruppen {
margin-top: 0pt;
width: 100%;
border: none;
}
table.lerngruppen a {
color: black;
text-decoration: none;
}
table.lerngruppen td {
border-left: 0.3px solid black;
border-right: 0.3px solid black;
border-top: none;
border-bottom: none;
}
td.group, td.current {
width: 12.5%;
font-size: 100%;
padding-top: 3pt;
padding-bottom: 0pt;
padding-right: 2pt;
text-align: center;
}
table.lerngruppen tr {
border: none;
}
table.lerngruppen td.home {
width: 5.5%;
font-size: 100%;
border: none;
}
td.group {
background-color: ghostwhite;
}
td.current {
background-color: lightgrey;
}
/* Überschriftszeile */
table.headline, tr.headline, td.headline {
border: none !important;
}
table.headline {
width: 100%;
margin-top: 12pt;
margin-bottom: 10pt;
}
table.headline td {
font-size: 175%;
border: none;
}
table.headline td.nr {
width: 5.5%;
}
td.left {
width: 47.5%;
padding-top: 2pt;
text-align: left;
}
td.right {
width: 48.0%;
padding-top: 0pt;
padding-right: 0pt;
text-align: right;
}
table.headline a {
color: black;
text-decoration: none;
}
img.icon {
width: 16pt;
height: 16pt;
padding-left: 1pt;
padding-right: 1pt;
}
/* Startseite inkl. Stundenplan */
h1.start {
margin-top: 60pt;
font-size: 200%;
margin-bottom: 10pt;
text-align: center;
}
table.timetable {
border: none;
width: 100%;
}
table.timetable tr {
border: none;
}
table.timetable a {
color: black;
}
th.luecke, td.luecke {
width: 5.5%;
text-align: center;
border: none;
}
th.stunde, td.stunde {
width: 7.5%;
text-align: center;
border: 0.3px solid black;
border-right: 1px solid black;
}
th.tag, td.tag {
width: 17.5%;
text-align: center;
border: 0.3px solid black;
}
table.timetable th.stunde, th.tag {
border-bottom: 1px solid black;
}
/* Alle Tabellen */
table, tr, td {
border: 0.3px solid black;
}
th, td {
padding-top: 4pt;
padding-left: 2pt;
text-align: left;
}
th.nr, td.nr {
width: 5.5%;
text-align: right;
padding-right: 2pt;
vertical-align: middle;
}
th.name, td.name {
width: 30%;
vertical-align: middle;
border-right: 1px solid black;
}
tr.header {
border-bottom: 1px solid black;
}
/* Halbjahresübersicht */
th.kw, td.kw {
width: 5.5%;
text-align: right;
padding-right: 2pt;
vertical-align: middle;
}
th.kw {
text-align: center;
}
th.kwsmall, td.kwsmall {
font-size: 8.5pt;
}
th.kw_sessions, td.kw_sessions {
width: 20%;
text-align: center;
padding-left: 0pt;
}
th.kw_content, td.kw_content {
width: 75%;
}
/* Geburtstagstabelle */
td.geb, th.geb {
width: 15%;
padding-left: 0pt;
text-align: center;
}
td.age {
width: 7.5%;
padding-left: 0pt;
text-align: center;
}
td.eightteen {
background: lightgrey;
}
td.home {
width: 42.5%;
}
/* Übersichtstabelle */
table.overview th.nr, th.name, th.endnote {
vertical-align: bottom;
}
.overview th.note, .overview td.note {
border-left: 0.3px solid black;
border-right: none;
}
.overview td.line, .overview th.line {
border-left: 1px solid black;
border-right: none;
}
th.hj, td.hj {
width: 8%;
border-left: 1px solid black;
border-right: 1px solid black;
vertical-align: bottom;
text-align: center;
padding-left: 0pt;
}
th.schr, th.somi {
width: 30%;
}
th.schr_cell, th.somi_cell {
text-align: center;
padding-left: 0pt;
}
table.overview a {
color: black;
text-decoration: underline;
}
th.endnote, td.endnote {
width: 8%;
text-align: center;
padding-left: 0pt;
border-left: 1px solid black;
}
/* Korrektur-Tabelle */
table.korrektur td {
vertical-align: middle;
}
th.korrektur, td.korrektur {
width: 10%;
text-align: center;
padding-left: 0pt;
}
th.summe, td.summe, th.aknote, td.aknote {
width: 10%;
text-align: center;
padding-left: 0pt;
}
th.summe, td.summe {
border-left: 1px solid black;
}
tr.muster {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
/* SoMi-Tabelle */
table.somi th {
vertical-align: bottom;
}
table.somi td {
vertical-align: middle;
}
th.somi, td.somi, th.schr, td.schr {
width: 8.5%;
text-align: center;
padding-left: 0pt;
}
th.sominote, td.sominote {
width: 10%;
text-align: center;
padding-left: 0pt;
}
th.sominote, td.sominote {
border-left: 1px solid black;
}
/* Check-Tabelle */
table.check th {
height: 40pt;
vertical-align: bottom;
}
table.check td {
vertical-align: middle;
}
th.check, td.check, th.checksmall, td.checksmall {
width: 8%;
}
table.checksmall td {
font-size: 8pt;
}
/* HA-Tabelle */
th.ha, td.ha, th.hasmall, td.hasmall {
width: 8%;
}
th.ha, th.hasmall {
border-left: none;
border-right: none;
}
table.hasmall td {
font-size: 8.5pt;
}

7
src/devices/paperpro.css Normal file
View File

@@ -0,0 +1,7 @@
@page {
size: 17.98cm 23.98cm;
margin-left: 0.5cm;
margin-right: 0.5cm;
margin-top: 0.25cm;
margin-bottom: 0.25cm;
}

35
src/devices/paperpro.ini Normal file
View File

@@ -0,0 +1,35 @@
[Navigation]
# Lerngruppenbezeichnung in der Navileiste (Zeilenumbruch vermeiden): kurz, normal
bezeichnung = normal
[Startseite]
# Schriftgröße der Kalenderwochen (Seitenumbruch vermeiden): normal, klein
schrift = normal
[Korrekturbogen]
# Anzahl der Aufgaben in der Korrekturtabelle: 1, 2, 3, ...
anzahl_aufgaben = 5
[SoMiNoten]
# Anzahl der SoMi-Noten-Spalten
anzahl_noten = 8
[Hausaufgaben]
# Anzahl der HA-Noten-Spalten
anzahl_ha = 9
# Umschalten auf kleine Schrift ab X Schülern (Seitenumbruch vermeiden): 20, 21, 22, ...
umschalten_kleinschrift = 24
[Checkliste]
# Anzahl der Check-Spalten
anzahl_checks = 9
# Umschalten auf kleine Schrift ab X Schülern (Seitenumbruch vermeiden): 20, 21, 22, ...
umschalten_kleinschrift = 22

7
src/devices/rm2.css Normal file
View File

@@ -0,0 +1,7 @@
@page {
size: 15.72cm 20.96cm;
margin-left: 0.5cm;
margin-right: 0.5cm;
margin-top: 0.25cm;
margin-bottom: 0.25cm;
}

35
src/devices/rm2.ini Normal file
View File

@@ -0,0 +1,35 @@
[Navigation]
# Lerngruppenbezeichnung in der Navileiste (Zeilenumbruch vermeiden): kurz, normal
bezeichnung = kurz
[Startseite]
# Schriftgröße der Kalenderwochen (Seitenumbruch vermeiden): normal, klein
schrift = klein
[Korrekturbogen]
# Anzahl der Aufgaben in der Korrekturtabelle: 1, 2, 3, ...
anzahl_aufgaben = 5
[SoMiNoten]
# Anzahl der SoMi-Noten-Spalten
anzahl_noten = 8
[Hausaufgaben]
# Anzahl der HA-Noten-Spalten
anzahl_ha = 8
# Umschalten auf kleine Schrift ab X Schülern (Seitenumbruch vermeiden): 20, 21, 22, ...
umschalten_kleinschrift = 20
[Checkliste]
# Anzahl der Check-Spalten
anzahl_checks = 8
# Umschalten auf kleine Schrift ab X Schülern (Seitenumbruch vermeiden): 20, 21, 22, ...
umschalten_kleinschrift = 20

14
src/img/LICENSE.txt Normal file
View File

@@ -0,0 +1,14 @@
Lineicons Free Basic
The Lineicons Free Basic version is open source and licensed under the MIT License. You can use, modify, and distribute it with your personal or commercial projects. However, reselling or redistributing it as an 'Icon Pack' from other sources is prohibited.
Commercial/Personal Use: Permitted.
Embedding and Redistributing with Projects: Permitted.
Attribution: Appreciated but not required.
Reselling or Redistributing Source Files as Icon Pack/Icon Font/Icons from Other Sources or
Public/Private Domain: Prohibited.
Note: If you enjoy our free pack, please consider supporting us by starring our project on GitHub: https://github.com/LineiconsHQ/Lineicons

1
src/img/bell-1.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.0016 2.00098C12.4158 2.00098 12.7516 2.33676 12.7516 2.75098V3.53801C16.5416 3.9143 19.5016 7.11197 19.5016 11.001V14.115L20.1938 15.9609C20.7454 17.4319 19.6581 19.001 18.0871 19.001H15.0628C15.0287 20.6631 13.6701 21.9995 11.9998 21.9995C10.3295 21.9995 8.97089 20.6631 8.93682 19.001H5.9161C4.34514 19.001 3.25776 17.4319 3.80936 15.9609L4.5016 14.115V11.001C4.5016 7.11197 7.46161 3.9143 11.2516 3.53801V2.75098C11.2516 2.33676 11.5874 2.00098 12.0016 2.00098ZM10.4375 19.001C10.471 19.8339 11.1573 20.4995 11.9998 20.4995C12.8423 20.4995 13.5286 19.8339 13.5622 19.001H10.4375ZM6.0016 11.001C6.0016 7.68727 8.68789 5.00098 12.0016 5.00098C15.3153 5.00098 18.0016 7.68727 18.0016 11.001V14.1168C18.0016 14.2955 18.0337 14.4727 18.0965 14.64L18.7893 16.4876C18.9732 16.9779 18.6108 17.501 18.0871 17.501H5.9161C5.39244 17.501 5.02998 16.9779 5.21385 16.4876L5.90673 14.64C5.96946 14.4727 6.0016 14.2955 6.0016 14.1168V11.001Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path d="M7.18535 12.75C7.18535 12.3082 7.54352 11.95 7.98535 11.95H7.99535C8.43718 11.95 8.79535 12.3082 8.79535 12.75C8.79535 13.1918 8.43718 13.55 7.99535 13.55H7.98535C7.54352 13.55 7.18535 13.1918 7.18535 12.75Z" fill="#000000"/><path d="M7.98535 15.95C7.54352 15.95 7.18535 16.3082 7.18535 16.75C7.18535 17.1918 7.54352 17.55 7.98535 17.55H7.99535C8.43718 17.55 8.79535 17.1918 8.79535 16.75C8.79535 16.3082 8.43718 15.95 7.99535 15.95H7.98535Z" fill="#000000"/><path d="M11.1951 12.75C11.1951 12.3082 11.5533 11.95 11.9951 11.95H12.0051C12.4469 11.95 12.8051 12.3082 12.8051 12.75C12.8051 13.1918 12.4469 13.55 12.0051 13.55H11.9951C11.5533 13.55 11.1951 13.1918 11.1951 12.75Z" fill="#000000"/><path d="M11.9951 15.95C11.5533 15.95 11.1951 16.3082 11.1951 16.75C11.1951 17.1918 11.5533 17.55 11.9951 17.55H12.0051C12.4469 17.55 12.8051 17.1918 12.8051 16.75C12.8051 16.3082 12.4469 15.95 12.0051 15.95H11.9951Z" fill="#000000"/><path d="M15.2049 12.75C15.2049 12.3082 15.5631 11.95 16.0049 11.95H16.0149C16.4567 11.95 16.8149 12.3082 16.8149 12.75C16.8149 13.1918 16.4567 13.55 16.0149 13.55H16.0049C15.5631 13.55 15.2049 13.1918 15.2049 12.75Z" fill="#000000"/><path d="M16.0049 15.95C15.5631 15.95 15.2049 16.3082 15.2049 16.75C15.2049 17.1918 15.5631 17.55 16.0049 17.55H16.0149C16.4567 17.55 16.8149 17.1918 16.8149 16.75C16.8149 16.3082 16.4567 15.95 16.0149 15.95H16.0049Z" fill="#000000"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8.75 2.75C8.75 2.33579 8.41421 2 8 2C7.58579 2 7.25 2.33579 7.25 2.75V3.75H5.5C4.25736 3.75 3.25 4.75736 3.25 6V19C3.25 20.2426 4.25736 21.25 5.5 21.25H18.5C19.7426 21.25 20.75 20.2426 20.75 19V6C20.75 4.75736 19.7426 3.75 18.5 3.75H16.75V2.75C16.75 2.33579 16.4142 2 16 2C15.5858 2 15.25 2.33579 15.25 2.75V3.75H8.75V2.75ZM19.25 8.25V6C19.25 5.58579 18.9142 5.25 18.5 5.25H5.5C5.08579 5.25 4.75 5.58579 4.75 6V8.25H19.25ZM4.75 9.75H19.25V19C19.25 19.4142 18.9142 19.75 18.5 19.75H5.5C5.08579 19.75 4.75 19.4142 4.75 19V9.75Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path d="M15.5071 10.5245C15.8 10.2316 15.8 9.75674 15.5071 9.46384C15.2142 9.17095 14.7393 9.17095 14.4464 9.46384L10.9649 12.9454L9.55359 11.5341C9.2607 11.2412 8.78582 11.2412 8.49293 11.5341C8.20004 11.827 8.20004 12.3019 8.49294 12.5947L10.4346 14.5364C10.7275 14.8293 11.2023 14.8292 11.4952 14.5364L15.5071 10.5245Z" fill="#000000"/><path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM3.5 12C3.5 7.30558 7.30558 3.5 12 3.5C16.6944 3.5 20.5 7.30558 20.5 12C20.5 16.6944 16.6944 20.5 12 20.5C7.30558 20.5 3.5 16.6944 3.5 12Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 784 B

View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path d="M20.75 18.5V8.67794L19.25 10.1779V18.5C19.25 18.9142 18.9142 19.25 18.5 19.25H5.5C5.08579 19.25 4.75 18.9142 4.75 18.5V5.5C4.75 5.08579 5.08579 4.75 5.5 4.75H18.314L19.2936 3.77034C19.3842 3.67974 19.4806 3.59848 19.5816 3.52657C19.2607 3.35027 18.8921 3.25 18.5 3.25H5.5C4.25736 3.25 3.25 4.25736 3.25 5.5V18.5C3.25 19.7426 4.25736 20.75 5.5 20.75H18.5C19.7426 20.75 20.75 19.7426 20.75 18.5Z" fill="#000000"/><path d="M20.4838 6.51868C20.7767 6.22578 20.7767 5.75091 20.4838 5.45802C20.1909 5.16512 19.7161 5.16512 19.4232 5.45802L11.9298 12.9514L8.57686 9.59849C8.28396 9.3056 7.80909 9.3056 7.5162 9.5985C7.22331 9.89139 7.22331 10.3663 7.5162 10.6592L11.3995 14.5424C11.6924 14.8353 12.1672 14.8353 12.4601 14.5424L20.4838 6.51868Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 890 B

1
src/img/comment-1.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path fill-rule="evenodd" clip-rule="evenodd" d="M2.50002 12.0957C2.50002 6.849 6.75332 2.5957 12 2.5957C17.2467 2.5957 21.5 6.849 21.5 12.0957C21.5 17.3424 17.2467 21.5957 12 21.5957H3.25002C2.94668 21.5957 2.6732 21.413 2.55711 21.1327C2.44103 20.8525 2.50519 20.5299 2.71969 20.3154L4.77303 18.262C3.35633 16.603 2.50002 14.4488 2.50002 12.0957ZM12 4.0957C7.58174 4.0957 4.00002 7.67742 4.00002 12.0957C4.00002 14.305 4.89463 16.304 6.34317 17.7526C6.48382 17.8932 6.56284 18.084 6.56284 18.2829C6.56284 18.4818 6.48382 18.6726 6.34317 18.8132L5.06068 20.0957H12C16.4183 20.0957 20 16.514 20 12.0957C20 7.67742 16.4183 4.0957 12 4.0957Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 784 B

1
src/img/home-2.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.45 4.90342C12.1833 4.70342 11.8167 4.70342 11.55 4.90342L5.05 9.77842C4.86115 9.92006 4.75 10.1423 4.75 10.3784V18.4998C4.75 18.9141 5.08579 19.2498 5.5 19.2498H9V16.9998C9 15.343 10.3431 13.9998 12 13.9998C13.6569 13.9998 15 15.343 15 16.9998V19.2498H18.5C18.9142 19.2498 19.25 18.9141 19.25 18.4998V10.3784C19.25 10.1423 19.1389 9.92006 18.95 9.77842L12.45 4.90342ZM10.65 3.70342C11.45 3.10342 12.55 3.10342 13.35 3.70342L19.85 8.57842C20.4166 9.00334 20.75 9.67021 20.75 10.3784V18.4998C20.75 19.7425 19.7426 20.7498 18.5 20.7498H14.25C13.8358 20.7498 13.5 20.4141 13.5 19.9998V16.9998C13.5 16.1714 12.8284 15.4998 12 15.4998C11.1716 15.4998 10.5 16.1714 10.5 16.9998V19.9998C10.5 20.4141 10.1642 20.7498 9.75 20.7498H5.5C4.25736 20.7498 3.25 19.7425 3.25 18.4998V10.3784C3.25 9.67021 3.58344 9.00334 4.15 8.57842L10.65 3.70342Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path fill-rule="evenodd" clip-rule="evenodd" d="M20.8749 2.51272C20.1915 1.8293 19.0835 1.8293 18.4001 2.51272L13.2418 7.67095C12.879 8.03379 12.6511 8.50974 12.5959 9.0199L12.4069 10.7668C12.3824 10.9926 12.4616 11.2173 12.6222 11.3778C12.7827 11.5384 13.0074 11.6176 13.2332 11.5931L14.9801 11.4041C15.4903 11.3489 15.9662 11.121 16.3291 10.7582L21.4873 5.59994C22.1707 4.91652 22.1707 3.80848 21.4873 3.12506L20.8749 2.51272ZM18.5981 4.43601L19.564 5.40191L15.2684 9.69751C15.1474 9.81846 14.9888 9.89443 14.8187 9.91283L13.9984 10.0016L14.0872 9.18126C14.1056 9.01121 14.1815 8.85256 14.3025 8.73161L18.5981 4.43601Z" fill="#000000"/><path d="M5.5 3.25H15.5411L14.0411 4.75H5.5C5.08579 4.75 4.75 5.08579 4.75 5.5V18.5C4.75 18.9142 5.08579 19.25 5.5 19.25H18.5C18.9142 19.25 19.25 18.9142 19.25 18.5V9.95823L20.75 8.45823V18.5C20.75 19.7426 19.7426 20.75 18.5 20.75H5.5C4.25736 20.75 3.25 19.7426 3.25 18.5V5.5C3.25 4.25736 4.25736 3.25 5.5 3.25Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg width="80" height="80" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(0 0 0)"><path d="M15.3289 11.4955C14.4941 11.4955 13.724 11.2188 13.1051 10.7522C13.3972 10.3301 13.6284 9.86262 13.786 9.36254C14.1827 9.7539 14.7276 9.99545 15.3289 9.99545C16.5422 9.99545 17.5258 9.01185 17.5258 7.79851C17.5258 6.58517 16.5422 5.60156 15.3289 5.60156C14.7276 5.60156 14.1827 5.84312 13.786 6.23449C13.6284 5.73441 13.3972 5.26698 13.1051 4.84488C13.7239 4.37824 14.4941 4.10156 15.3289 4.10156C17.3706 4.10156 19.0258 5.75674 19.0258 7.79851C19.0258 9.84027 17.3706 11.4955 15.3289 11.4955Z" fill="#000000"/><path d="M14.7723 13.1891C15.0227 13.437 15.2464 13.6945 15.4463 13.9566C16.7954 13.9826 17.7641 14.3143 18.4675 14.7651C19.2032 15.2366 19.6941 15.8677 20.0242 16.5168C20.3563 17.1698 20.5204 17.8318 20.6002 18.337C20.6398 18.5878 20.6579 18.795 20.6661 18.9365C20.6702 19.0071 20.6717 19.061 20.6724 19.0952L20.6726 19.1161L20.6727 19.1313L20.6727 19.1363L21.4197 19.1486C20.6793 19.1358 20.6728 19.136 20.6727 19.1363L20.6727 19.1376C20.6666 19.5509 20.9961 19.8914 21.4096 19.8985C21.8237 19.9057 22.1653 19.5758 22.1725 19.1617L21.4284 19.1488C22.1725 19.1617 22.1725 19.1621 22.1725 19.1617L22.1725 19.1599L22.1726 19.1575L22.1726 19.1511L22.1727 19.1319C22.1727 19.1163 22.1726 19.0951 22.1721 19.0686C22.1712 19.0158 22.1689 18.9419 22.1636 18.85C22.153 18.6665 22.1303 18.4094 22.0819 18.1029C21.9856 17.4936 21.7848 16.6697 21.3612 15.8368C20.9357 15 20.2801 14.1451 19.2768 13.5022C18.2708 12.8574 16.9604 12.4549 15.274 12.4549C14.8284 12.4549 14.4092 12.483 14.0148 12.5362C14.2852 12.7384 14.5376 12.9566 14.7723 13.1891Z" fill="#000000"/><path fill-rule="evenodd" clip-rule="evenodd" d="M5.13173 7.79855C5.13173 5.75678 6.7869 4.1016 8.82867 4.1016C10.8704 4.1016 12.5256 5.75678 12.5256 7.79855C12.5256 9.84031 10.8704 11.4955 8.82867 11.4955C6.7869 11.4955 5.13173 9.84031 5.13173 7.79855ZM8.82867 5.6016C7.61533 5.6016 6.63173 6.58521 6.63173 7.79855C6.63173 9.01189 7.61533 9.99549 8.82867 9.99549C10.042 9.99549 11.0256 9.01189 11.0256 7.79855C11.0256 6.58521 10.042 5.6016 8.82867 5.6016Z" fill="#000000"/><path d="M3.37502 19.1374C3.38126 19.5507 3.0517 19.8914 2.63812 19.8986C2.22397 19.9058 1.88241 19.5759 1.87522 19.1617L2.62511 19.1487C1.87522 19.1617 1.87523 19.1621 1.87522 19.1617L1.87519 19.1599L1.87516 19.1575L1.87509 19.1511L1.875 19.1319C1.87499 19.1163 1.87512 19.0951 1.87559 19.0687C1.87653 19.0158 1.87882 18.942 1.88413 18.85C1.89474 18.6665 1.91745 18.4094 1.96585 18.103C2.0621 17.4936 2.26292 16.6697 2.68648 15.8368C3.11206 15 3.76758 14.1452 4.77087 13.5022C5.77688 12.8575 7.08727 12.455 8.77376 12.455C10.4602 12.455 11.7706 12.8575 12.7767 13.5022C13.7799 14.1452 14.4355 15 14.861 15.8368C15.2846 16.6697 15.4854 17.4936 15.5817 18.103C15.6301 18.4094 15.6528 18.6665 15.6634 18.85C15.6687 18.942 15.671 19.0158 15.6719 19.0687C15.6724 19.0951 15.6725 19.1163 15.6725 19.1319L15.6724 19.1511L15.6724 19.1575L15.6723 19.1599C15.6723 19.1603 15.6723 19.1617 14.9282 19.1488L15.6723 19.1617C15.6651 19.5759 15.3235 19.9058 14.9094 19.8986C14.4959 19.8914 14.1664 19.5509 14.1725 19.1376L14.1725 19.1364C14.1726 19.1361 14.1791 19.1358 14.9199 19.1487L14.1725 19.1364L14.1725 19.1314L14.1724 19.1161L14.1722 19.0952C14.1716 19.061 14.17 19.0072 14.1659 18.9366C14.1577 18.7951 14.1396 18.5878 14.1 18.337C14.0202 17.8319 13.8561 17.1699 13.524 16.5168C13.1939 15.8677 12.703 15.2366 11.9673 14.7651C11.2343 14.2954 10.2132 13.955 8.77376 13.955C7.33434 13.955 6.31319 14.2954 5.58022 14.7651C4.84453 15.2366 4.35363 15.8677 4.02351 16.5168C3.6914 17.1699 3.52727 17.8319 3.44749 18.337C3.40787 18.5878 3.38981 18.7951 3.38163 18.9366C3.37756 19.0072 3.37596 19.061 3.37536 19.0952C3.37505 19.1123 3.375 19.1245 3.375 19.1314L3.37502 19.1374Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

4
src/lehrerpdf.ini Normal file
View File

@@ -0,0 +1,4 @@
[Allgemein]
# Pfad (relativ oder absolut zu den Eingabedateien)
pfad = data/

230
src/lehrerpdf.py Executable file
View File

@@ -0,0 +1,230 @@
#! python3
import os, glob, sys
import argparse, csv
from configparser import ConfigParser
from xhtml2pdf import pisa
sys.path.append(os.path.abspath("./pages"))
import start, halbjahr, birthday, uebersicht, korrektur, somi, ha, checkliste
# 1. Eingabepfad einlesen aus lehrerpdf.ini oder bevorzugt: mylehrerpdf.ini
base_file = "mylehrerpdf.ini"
if (not(os.path.exists(base_file))):
base_file = "lehrerpdf.ini"
if (not(os.path.exists(base_file))):
print(base_file+" nicht vorhanden!")
exit(0)
base = ConfigParser(allow_no_value=True)
base.read(base_file)
try:
path = base["Allgemein"]["pfad"] # Basispfad
except KeyError:
print('Der Schlüssel Allgemein oder "pfad" existiert nicht in der Config-Datei!')
exit(0)
if (not(os.path.exists(path))):
print("Basisverzeichnis "+path+" nicht vorhanden!")
exit(0)
print("Verarbeite das Verzeichnis: "+path)
# 2. Konfiguration des Benutzers einlesen
inputs_file = path+"input.ini"
if (not(os.path.exists(inputs_file))):
print(inputs_file+" nicht vorhanden!")
exit(0)
inputs = ConfigParser()
inputs.read(inputs_file)
# 3. Konfiguration des Zielgeräts einlesen
try:
device = inputs["Allgemein"]["device"]
except KeyError:
print('Der Schlüssel Allgemein oder "device" existiert nicht in der Input-Datei!')
exit(0)
# Basiskonfiguration für das Device einlesen
ini_file = 'devices/'+device+'.ini'
if (not(os.path.exists(ini_file))):
print(ini_file+" nicht vorhanden!")
exit(0)
config = ConfigParser(allow_no_value=True)
config.read(ini_file)
# CSS Formatierung für das Device einlesen
css_devicefile = 'devices/'+device+'.css'
if (not(os.path.exists(css_devicefile))):
print(css_devicefile+" nicht vorhanden!")
exit(0)
fd = open(css_devicefile)
devicestyle = fd.read()
# CSS Formatierung für alle Devices einlesen
css_file = 'devices/general.css'
if (not(os.path.exists(css_file))):
print(css_file+" nicht vorhanden!")
exit(0)
f = open(css_file)
style = f.read()
# 4. Vorbereitungen für Verarbeitung
# Lerngruppen aus Eingabedateien ermitteln
dateien = glob.glob(path+'*.csv')
dateien.sort()
lerngruppen = []
for lerngruppe in dateien:
dateiname = lerngruppe.replace(path,"")
gruppenid = dateiname.replace(".csv","")
lerngruppen.append(gruppenid)
# Wichtige Schlüssel einlesen
try:
csv_info = inputs["Allgemein"]
except KeyError:
print("Der Schlüssel Allgemein existiert nicht in der Input-Datei!")
exit(0)
try:
sj_test = csv_info["schuljahr"]
hj_test = csv_info["halbjahr"]
except KeyError:
print("Schuljahr oder Halbjahr existiert nicht im algemeinen Teil der Input-Datei!")
exit(0)
try:
csv_trenner = csv_info["csvtrenner"]
except KeyError:
print('Der Schlüssel "csvtrenner" existiert nicht im allgemeinen Bereich der Input-Datei!')
exit(0)
# 5. Baue die Ausgabe aus den einzelnen Bestandteilen zusammen
body = ''
# Startseite einbinden
body = body + start.erstelleStartseite(lerngruppen, path, config, inputs)
# Verarbeite nacheinander alle Eingabedateien = Lerngruppen
for datei in dateien:
print("Verarbeite Datei: "+datei)
if (not(os.path.exists(datei))):
print("Datei "+datei+" nicht vorhanden!")
exit(0)
# Implizite Konfiguration der aktuellen Lerngruppe aus Benutzerconfig auslesen
dateiname = datei.replace(path,"")
kursid = dateiname.replace(".csv","")
try:
kurs_inputs = inputs[kursid]
except KeyError:
print('Der Bereichsschlüssel "'+kursid+'" (zur entsprechenden Datei) existiert nicht in der Input-Datei (1)!')
exit(0)
try:
klassekurs_name = kurs_inputs["bezeichnung"]
except KeyError:
print('Der Schlüssel "bezeichnung" fehlt im Bereich "'+kursid+'" der Input-Datei!')
exit(0)
# CSV Datei mit Schülernamen einlesen und für Geburtstag aufbereiten
csvdaten = open(datei, encoding="utf8")
csvdatenReader = csv.reader(csvdaten, delimiter=csv_trenner)
linecount = 0
namen = []
gebdaten = []
gebdaten_all = True
for row in csvdatenReader:
linecount = linecount +1
if linecount>1: # Ignoriere Header
nachname = row[0]
vorname = row[1]
name = nachname + ", " +vorname
namen.append(name)
if (gebdaten_all):
try:
gebdatum = row[2]
gebdaten.append(gebdatum)
except IndexError:
print(' - Einträge für Geburtstag fehlen für Lerngruppe "'+kursid+'"!')
gebdaten = []
gebdaten_all = False
# Übersichtsseite für das Halbjahr zusammenbauen
body = body + halbjahr.erstelleHalbjahresuebersicht(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# Geburtstagsseite zusammenbauen
if (len(gebdaten)==0):
print(' - Geburtstagsliste wird weggelassen.')
else:
body = body + birthday.erstelleGeburtstagsBogen(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# Übersichtsseite Noten zusammenbauen
body = body + uebersicht.erstelleUebersicht(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# optional: Korrekturbögen zusammenbauen
try:
schr_anzahl = int(kurs_inputs["schriftlich_anzahl"])
except KeyError:
print('Der Schlüssel "schr_anzahl" fehlt im Bereich "'+kursid+'" der Input-Datei!')
exit(0)
if (schr_anzahl>0):
body = body + korrektur.erstelleKorrekturbogen(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# SoMi-Bogen zusammenbauen
body = body + somi.erstelleSoMiBogen(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# optional: HA-Bogen zusammenbauen
try:
ha_zeilen = int(kurs_inputs["ha_zeilen"])
except KeyError:
print('Der Schlüssel "ha_zeilen" fehlt im Bereich "'+kursid+'" der Input-Datei!')
exit(0)
if (ha_zeilen>0):
body = body + ha.erstelleHABogen(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# Checkliste(n) zusammenbauen
body = body + checkliste.erstelleCheckliste(klassekurs_name, lerngruppen, path, namen, gebdaten, config, inputs, kurs_inputs)
# 6. Abschluss: PDF Generierung
html_source = '<html><head>'
html_source += '<style>'+devicestyle+style+'</style></head><body>'+body+'</body></html>'
pisa.showLogging()
datei_ausgabe = path + device + '.pdf'
print("Erzeuge PDF-Datei: " + device + '.pdf')
with open(datei_ausgabe, "w+b") as result_file:
# convert HTML to PDF
pisa_status = pisa.CreatePDF(
html_source, # page data
dest=result_file, # destination file
)
# Check for errors
if pisa_status.err:
print("Fehler bei der Erzeugung der PDF aus HTML!")
print("Fertig!")

144
src/pages/birthday.py Normal file
View File

@@ -0,0 +1,144 @@
import os, re
from datetime import datetime
import header
def erstelleGeburtstagsBogen(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
# Sortierung nach Geburtsmonat für Geburtstagsliste
gebmonat = []
for geb in gebdaten:
parts = re.split("\.", geb)
day = parts[0]
if (len(day)==1):
day = '0'+day
month = parts[1]
if (len(month)==1):
month = '0'+month
year = parts[2]
gebmonat.append(month+'-'+day+'-'+year)
gebmonat, namen = (list(t) for t in zip(*sorted(zip(gebmonat, namen))))
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
zschuljahr = int(schuljahr)
halbjahr = allg["halbjahr"]
table += '<a name="'+klassekurs_name+'Birthday"></a>'
table += header.erstelleHeader('Geburtstage', klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
table += '<table class="home" repeat="1">'
table += '<tr class="header">'
table += '<th class="nr">Nr</th>'
table += '<th class="name">Name, Vorname</th>'
table += '<th class="geb">Geburtstag</th>'
table += '<th class="age">Alter</th>'
table += '<th class="home"></th>'
table += '</tr>'
count = 0
# Geburtstagsliste im 1. Hj. ab August, 2. Hj. ab Februar
startmonat = 8
if (halbjahr == '2'):
startmonat = 2
startpoint = -1
for count in range(len(namen)):
datum = gebmonat[count]
parts = re.split("-", datum)
month = parts[0]
zmonth = int(month)
if (zmonth>=startmonat):
startpoint = count
break
newcount = 0
for count in range(startpoint, len(namen)):
name = namen[count]
datum = gebmonat[count]
parts = re.split("-", datum)
month = parts[0]
zmonth = int(month)
day = parts[1]
year = parts[2]
zyear = int(year)
if (halbjahr=='1'):
if (zmonth>=8 and zmonth<=12):
current_year = zschuljahr
else:
current_year = zschuljahr+1
else:
current_year = zschuljahr+1
newcount = newcount + 1
table += '<tr>'
table += '<td class="nr">'+str(newcount)+'</td>'
table += '<td class="name">'+name+'</td>'
age = current_year - zyear
hurray = ''
if (age==18):
hurray = ' eightteen'
table += '<td class="geb">'+day+'.'+month+'.'+year+'</td>'
table += '<td class="age'+hurray+'">'+str(age)+'</td>'
table += '<td class="home">&nbsp;</td>'
table += '</tr>'
for count in range(0, startpoint):
name = namen[count]
datum = gebmonat[count]
parts = re.split("-", datum)
month = parts[0]
zmonth = int(month)
day = parts[1]
year = parts[2]
zyear = int(year)
if (halbjahr=='1'):
current_year = zschuljahr+1
else:
current_year = zschuljahr+2
newcount = newcount + 1
table += '<tr>'
table += '<td class="nr">'+str(newcount)+'</td>'
table += '<td class="name">'+name+'</td>'
age = current_year - zyear
hurray = ''
if (age==18):
hurray = ' eightteen'
table += '<td class="geb">'+day+'.'+month+'.'+year+'</td>'
table += '<td class="age'+hurray+'">'+str(age)+'</td>'
table += '<td class="home">&nbsp;</td>'
table += '</tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table

55
src/pages/checkliste.py Normal file
View File

@@ -0,0 +1,55 @@
import os
import header
def erstelleCheckliste(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
try:
check_seiten = int(kurs_inputs["checkliste_seiten"])
except KeyError:
print('Der Schlüssel "checkliste_seiten" existiert nicht für die Lerngruppe in der Input-Datei!')
exit(0)
if (check_seiten==0):
check_seiten = 1
check_anzahl = int(config["Checkliste"]["anzahl_checks"])
umschalten = int(config["Checkliste"]["umschalten_kleinschrift"])
for no in range(check_seiten):
if (no==0):
table += '<a name="'+klassekurs_name+'Check"></a>'
line = 'Checkliste'
if check_seiten > 1:
line += 'n'
table += header.erstelleHeader(line, klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
css = 'check'
if (len(namen)>umschalten): # kleine Schrift, um möglichst alles auf einer Seite zu halten
css = 'checksmall'
table += '<table class="'+css+'" repeat="1">'
table += '<tr class="header"><th class="nr">Nr</th><th class="name">Name, Vorname</th>'
for i in range(check_anzahl):
table += '<th class="'+css+'"></th>'
table += '</tr>'
count = 0
for name in namen:
count = count + 1
table += '<tr><td class="nr">'+str(count)+'</td><td class="name">'+name+'</td>'
for i in range(check_anzahl):
table += '<td class="'+css+'"></td>'
table += '</tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table

68
src/pages/ha.py Normal file
View File

@@ -0,0 +1,68 @@
import os
import header
def erstelleHABogen(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
halbjahr = allg["halbjahr"]
ha_anzahl = int(config["Hausaufgaben"]["anzahl_ha"])
umschalten = int(config["Hausaufgaben"]["umschalten_kleinschrift"])
try:
ha_zeilen = int(kurs_inputs["ha_zeilen"])
except KeyError:
print('Der Schlüssel "ha_zeilen" existiert nicht für die Lerngruppe in der Input-Datei!')
exit(0)
offset = 0
if (halbjahr=='2'):
offset = 2
css = 'ha'
if (len(namen)>umschalten): # kleine Schrift, um möglichst alles auf einer Seite zu halten
css = 'hasmall'
table += '<a name="'+klassekurs_name+'HA"></a>'
table += header.erstelleHeader('Hausaufgaben', klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
table += '<table class="'+css+'" repeat="1">'
table += '<tr class="header"><th class="nr">Nr</th><th class="name">Name, Vorname</th>'
for i in range(ha_anzahl):
table += '<th class="'+css+'"></th>'
table += '</tr>'
rowspan = ''
if ha_zeilen>1:
rowspan = ' rowspan="'+str(ha_zeilen)+'"'
count = 0
for name in namen:
count = count + 1
for zeile in range(0, ha_zeilen):
table += '<tr>'
if zeile==0:
table += '<td class="nr"'+rowspan+'>'+str(count)+'</td>'
table += '<td class="name"'+rowspan+'>'+name+'</td>'
for i in range(ha_anzahl):
table += '<td class="'+css+'">&nbsp;</td>'
table += '</tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table

62
src/pages/halbjahr.py Normal file
View File

@@ -0,0 +1,62 @@
import os
import header
def erstelleHalbjahresuebersicht(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
halbjahr = allg["halbjahr"]
allgemein = inputs["Allgemein"]
try:
kw_start = int(allgemein["kw_start"])
kw_ende = int(allgemein["kw_ende"])
except KeyError:
print('"kw_start" oder "kw_ende" fehlt im allgemeinen Teil der Input-Datei!')
exit(0)
table += '<a name="'+klassekurs_name+'"></a>'
table += '<a name="'+klassekurs_name+'Halbjahr"></a>'
table += header.erstelleHeader('Halbjahresplanung', klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
css = 'halbjahr'
table += '<table class="'+css+'" repeat="1">'
table += '<tr class="header"><th class="kw">KW</th>'
table += '<th class="kw_sessions">Sitzungen</th><th class="kw_content"></th>'
table += '</tr>'
try:
schrift = config["Startseite"]["schrift"]
except KeyError:
print('Der Schlüssel Starseite oder "schrift" existiert nicht in der Device-Datei!')
exit(0)
extrakw = ''
if (schrift=='klein'):
extrakw = ' kwsmall'
if (halbjahr=='1'):
for count in range(kw_start, 52):
table += '<tr><td class="kw'+extrakw+'">'+str(count)+'</td>'
table += '<th class="kw_sessions"></td><td class="kw_content"></td></tr>'
for count in range(1, kw_ende+1):
table += '<tr><td class="kw'+extrakw+'">'+str(count)+'</td>'
table += '<th class="kw_sessions"></td><td class="kw_content"></td></tr>'
else:
for count in range(kw_start, kw_ende+1):
table += '<tr><td class="kw'+extrakw+'">'+str(count)+'</td>'
table += '<th class="kw_sessions"></td><td class="kw_content"></td></tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table

124
src/pages/header.py Normal file
View File

@@ -0,0 +1,124 @@
import os
def erstelleNavigation(klassekurs_name, lerngruppen, path, config, inputs):
header = '<table class="lerngruppen"><tr>'
header += '<td class="home">&nbsp;</td>'
myclass = "group"
if (klassekurs_name==''):
header += '<td class="current">Startseite</td>'
else:
header += '<td class="group"><a href="#Home">Startseite</a></td>'
for kursid in lerngruppen:
try:
kurs_inputs_aktuell = inputs[kursid]
except KeyError:
print('Der Bereichsschlüssel "'+kursid+'" (zur entsprechenden Datei) existiert nicht in der Input-Datei (3).')
exit(0)
try:
device = inputs["Allgemein"]["device"]
except KeyError:
print('Der Schlüssel Allgemein oder "device" existiert nicht in der Input-Datei!')
exit(0)
try:
bezeichnung = config["Navigation"]["bezeichnung"]
except KeyError:
print('Der Schlüssel Navigation oder "kurzbezeichnung" existiert nicht in der Device-Datei!')
exit(0)
try:
klassekurs_aktuell = kurs_inputs_aktuell["bezeichnung"]
if (bezeichnung=='kurz'):
klassekurs_print = kurs_inputs_aktuell["kurzbezeichnung"]
else:
klassekurs_print = kurs_inputs_aktuell["bezeichnung"]
except KeyError:
print('Der Schlüssel "(kurz)bezeichnung" fehlt im Bereich "'+kursid+'" der Input-Datei!')
exit(0)
myclass = "group"
if (klassekurs_aktuell == klassekurs_name):
header += '<td class="current">'+klassekurs_print+'</td>'
else:
header += '<td class="group"><a href="#'+klassekurs_aktuell+'">'+klassekurs_print+'</a></td>'
header += '</tr></table>'
return header
def erstelleHeader(line, klassekurs_name, gebdaten, lerngruppen, path, config, inputs, kurs_inputs):
# Part 1: Navigation für alle Lerngruppen
header = erstelleNavigation(klassekurs_name, lerngruppen, path, config, inputs)
# Part2: Icons für die aktuelle Lerngruppe
header += '<table class="headline"><tr class="headline">'
# Icon
header += '<td class="nr">&nbsp;</td>'
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
zschuljahr = int(schuljahr)
halbjahr = allg["halbjahr"]
# Überschrift
if len(line)>0:
myline = line
else:
myline = str(zschuljahr) + '/' + str((zschuljahr-2000)+1) + ', ' + halbjahr + '. Hj.'
# Überschrift links
header+= '<td class="left headline">'+klassekurs_name+' - '+myline+'</td>'
# Iconleiste rechts
header += '<td class="right headline">'
# Halbjahresseite
header += '<a href="#'+klassekurs_name+'Halbjahr">&nbsp;<img class="icon" src="img/calendar-days.svg"/></a>'
# Geburtstagsseite
if (len(gebdaten)>0):
header += '<a href="#'+klassekurs_name+'Birthday">&nbsp;<img class="icon" src="img/bell-1.svg"/></a>'
# Notenübersicht
header += '<a href="#'+klassekurs_name+'Overview">&nbsp;<img class="icon" src="img/user-multiple-4.svg"/></a>'
# Arbeiten/Klausuren
schr_anzahl = int(kurs_inputs["schriftlich_anzahl"])
schr_bez = kurs_inputs["schriftlich_bez"]
if (schr_anzahl>0):
offset = 0
if (halbjahr=='2'):
offset = schr_anzahl
header += '<a href="#'+klassekurs_name+'Korrektur'+str(offset+1)+'">&nbsp;<img class="icon" src="img/pen-to-square.svg"/></a>'
# SoMi
somi_quartale = int(kurs_inputs["somi_quartale"])
offset = 0
if (halbjahr=='2'):
offset = 2
header += '<a href="#'+klassekurs_name+'SoMiQ'+str(offset+1)+'">&nbsp;<img class="icon" src="img/comment-1.svg"/></a>'
# HA
ha_zeilen = int(kurs_inputs["ha_zeilen"])
if (ha_zeilen>0):
header += '<a href="#'+klassekurs_name+'HA">&nbsp;<img class="icon" src="img/check-square-2.svg"/></a>'
# Checklisten
header += '<a href="#'+klassekurs_name+'Check">&nbsp;<img class="icon" src="img/check-circle-1.svg"/></a>'
header += '</td></tr></table>'
return header

63
src/pages/korrektur.py Normal file
View File

@@ -0,0 +1,63 @@
import os
import header
def erstelleKorrekturbogen(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
halbjahr = allg["halbjahr"]
try:
schr_bez = kurs_inputs["schriftlich_bez"]
schr_anzahl = int(kurs_inputs["schriftlich_anzahl"])
korrektur_seiten = int(kurs_inputs["schriftlich_anzahl"])
except KeyError:
print('Ein Parameter "schriftlich_XYZ" fehlt für die Lerngruppe in der Input-Datei!')
exit(0)
aufgaben_anzahl = int(config["Korrekturbogen"]["anzahl_aufgaben"])
offset = 0
if (halbjahr=='2'):
offset = schr_anzahl
for no in range(offset+1, offset+schr_anzahl+1):
table += '<a name="'+klassekurs_name+'Korrektur'+str(no)+'"></a>'
line = schr_bez+' Nr. '+str(no)
table += header.erstelleHeader(line, klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
table += '<table class="korrektur" repeat="1">'
table += '<tr class="header"><th class="nr">Nr</th><th class="name">Name, Vorname</th>'
for i in range(aufgaben_anzahl):
table += '<th class="korrektur">A. '+str(i+1)+'</th>'
table += '<th class="summe">Summe</th><th class="aknote">Note</th>'
table += '</tr>'
table += '<tr class="muster"><td class="nr"></td><td class="name">Musterlösung</td>'
for i in range(aufgaben_anzahl):
table += '<td class="korrektur"></td>'
table += '<td class="summe"></td><td class="aknote"></td>'
table += '</tr>'
count = 0
for name in namen:
count = count + 1
table += '<tr><td class="nr">'+str(count)+'</td><td class="name">'+name+'</td>'
for i in range(aufgaben_anzahl):
table += '<td class="korrektur"></td>'
table += '<td class="summe"></td><td class="aknote"></td>'
table += '</tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table

90
src/pages/somi.py Normal file
View File

@@ -0,0 +1,90 @@
import os
import header
def erstelleSoMiBogen(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
halbjahr = allg["halbjahr"]
try:
somi_quartale = int(kurs_inputs["somi_quartale"])
somi_zeilen = int(kurs_inputs["somi_zeilen"])
except KeyError:
print('Ein Parameter "somi_XYZ" fehlt für die Lerngruppe in der Input-Datei!')
exit(0)
noten_anzahl = int(config["SoMiNoten"]["anzahl_noten"])
offset = 0
if (halbjahr=='2'):
offset = 2
for no in range(offset+1, offset+somi_quartale+1):
table += '<a name="'+klassekurs_name+'SoMiQ'+str(no)+'"></a>'
line = ''
if somi_quartale>1:
line += 'SoMi Q'+str(no)
else:
line += 'SoMi Q'+str(no)
line += '/Q'+str(no+1)
table += header.erstelleHeader(line, klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
table += '<table class="somi" repeat="'+str(somi_zeilen)+'">'
rowspan = ''
if somi_zeilen>1:
rowspan = ' rowspan="'+str(somi_zeilen)+'"'
for zeile in range(0, somi_zeilen):
myclass = ' class="header"'
if (somi_zeilen>1 and zeile<(somi_zeilen-1)):
myclass = ''
table += '<tr'+myclass+'>'
if zeile==0:
table += '<th class="nr"'+rowspan+'>Nr</th>'
table += '<th class="name"'+rowspan+'>Name, Vorname</th>'
for i in range(noten_anzahl):
table += '<th class="somi">&nbsp;</th>'
if zeile==0:
table += '<th class="sominote"'+rowspan+'>Note</th>'
table += '</tr>'
count = 0
for name in namen:
count = count + 1
for zeile in range(0, somi_zeilen):
table += '<tr>'
if zeile==0:
table += '<td class="nr"'+rowspan+'>'+str(count)+'</td>'
table += '<td class="name"'+rowspan+'>'+name+'</td>'
for i in range(noten_anzahl):
table += '<td class="somi">&nbsp;</td>'
if zeile==0:
table += '<td class="sominote"'+rowspan+'></td>'
table += '</tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table

86
src/pages/start.py Normal file
View File

@@ -0,0 +1,86 @@
import os
import markdown
import header
def erstelleStartseite(lerngruppen, path,config, inputs):
table = ''
table += '<a name="Home"></a>'
table += header.erstelleNavigation('', lerngruppen, path, config, inputs)
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
zschuljahr = int(schuljahr)
halbjahr = allg["halbjahr"]
myline = 'Schuljahr ' + str(zschuljahr) + '/' + str((zschuljahr-2000)+1) + ', ' + halbjahr + '. Hj.'
table += '<h1 class="start">'+myline+'</h1>'
table += '<div class="tt">'
# Markdowndatei einlesen
try:
stundenplandatei = allg['stundenplandatei']
except KeyError:
print('Der Bereichsschlüssel "stundenplandatei" im allgemeinen Bereich existiert nicht in der Input-Datei!')
exit(0)
tt_file = path+stundenplandatei
if (len(stundenplandatei)==0):
print("Stundenplan in der Konfiguration ausgeschaltet, erzeuge Startseite ohne Stundenplan.")
elif (not(os.path.exists(tt_file))):
print("Angegebene Stundenplandatei nicht vorhanden, erzeuge Startseite ohne Stundenplan.")
else:
f = open(tt_file)
text = f.read()
# nach HTML konvertieren
html = markdown.markdown(text, extensions=['tables'])
# mit Markup anreichern zur CSS Formatierung
html = html.replace('<table>','<table class="timetable">')
html = html.replace('''<th style="text-align: center;">''','''<th class="tag">''')
html = html.replace('''<td style="text-align: center;">''','''<td class="tag">''')
html = html.replace('''<tr>
<th class="tag">''','''<tr><th class="luecke">&nbsp;</th><th class="stunde">''')
html = html.replace('''<tr>
<td class="tag">''','''<tr><td class="luecke">&nbsp;</td><td class="stunde">''')
# ggf. Links zu Lerngruppen einfügen
for kursid in lerngruppen:
try:
kurs_inputs_aktuell = inputs[kursid]
except KeyError:
print('Der Bereichsschlüssel "'+kursid+'" (zur entsprechenden Datei) existiert nicht in der Input-Datei (2)!')
exit(0)
try:
klassekurs_aktuell = kurs_inputs_aktuell["bezeichnung"]
klassekurs_aktuell_kurz = kurs_inputs_aktuell["kurzbezeichnung"]
except KeyError:
print('Der Schlüssel "bezeichnung" fehlt im Bereich "'+kursid+'" der Input-Datei!')
exit(0)
html = html.replace('['+kursid+']','<a href="#'+klassekurs_aktuell+'">'+klassekurs_aktuell_kurz+'</a>')
table += html
table += '</div>'
table += '<pdf:nextpage />'
return table

87
src/pages/uebersicht.py Normal file
View File

@@ -0,0 +1,87 @@
import os
import header
def erstelleUebersicht(klassekurs_name, dateien, path, namen, gebdaten, config, inputs, kurs_inputs):
table = ''
table += '<a name="'+klassekurs_name+'Overview"></a>'
allg = inputs["Allgemein"]
schuljahr = allg["schuljahr"]
halbjahr = allg["halbjahr"]
halbjahresnote = False
if ("halbjahresnote" in kurs_inputs):
if (kurs_inputs["halbjahresnote"]=='ja'):
halbjahresnote = True
table += header.erstelleHeader('Notenübersicht', klassekurs_name, gebdaten, dateien, path, config, inputs, kurs_inputs)
schr_bez = kurs_inputs["schriftlich_bez"]
schr_anzahl = int(kurs_inputs["schriftlich_anzahl"])
somi_quartale = int(kurs_inputs["somi_quartale"])
table += '<table class="overview" repeat="1">'
table += '<tr><th class="nr" rowspan="2">Nr</th><th class="name" rowspan="2">Name, Vorname</th>'
if (halbjahr=='2' and halbjahresnote):
table += '<th class="hj" rowspan="2">Hj.</th>'
if schr_anzahl>0:
table += '<th class="schr" colspan="'+str(schr_anzahl)+'">'+schr_bez+'en</th>'
table += '<th class="somi line" colspan="'+str(somi_quartale)+'">SoMi</th>'
table += '<th class="endnote" rowspan="2">Note</th></tr>'
table += '<tr class="header">'
offset = 0
if (halbjahr=='2'):
offset = schr_anzahl
for i in range(offset+1, offset+schr_anzahl+1):
table += '<th class="schr_cell"><a href="#'+klassekurs_name+'Korrektur'+str(i)+'">Nr. '+str(i)+'</a></th>'
tag = 'Nr.'+str(i)
offset = 0
if (halbjahr=='2'):
offset = 2
if somi_quartale>1:
line = ' line'
for i in range(offset+1, offset+somi_quartale+1):
table += '<th class="somi_cell'+line+'"><a href="#'+klassekurs_name+'SoMiQ'+str(i)+'">Q'+str(i)+'</a></th>'
if (len(line)>0):
line = ''
tag = 'Q'+str(i)
else:
table += '<th class="somi_cell line"><a href="#'+klassekurs_name+'SoMiQ'+str(offset+1)+'">'
tag = ''
for i in range(offset+1, offset+somi_quartale+1):
tag += 'Q'+str(i)+'+Q'+str(i+1)
table += tag + '</a></th>'
table += '</tr>'
count = 0
for name in namen:
count = count + 1
table += '<tr><td class="nr">'+str(count)+'</td><td class="name">'+name+'</td>'
if (halbjahr=='2' and halbjahresnote):
table += '<td class="hj"></td>'
for i in range(schr_anzahl):
table += '<td class="note">&nbsp;</td>'
table += '<td class="line">&nbsp;</td>'
for i in range(somi_quartale-1):
table += '<td class="note">&nbsp;</td>'
table += '<td class="line endnote">&nbsp;</td>' # Endnote
table += '</tr>'
table += '</table>'
table += '<pdf:nextpage />'
return table