|
@@ -0,0 +1,666 @@
|
|
|
|
|
+`<link rel="stylesheet" href="css/cssgithub-markdown.css" />`{=html}
|
|
|
|
|
+`<link rel="stylesheet" href="css/github-syntax-highlight.css" />`{=html}
|
|
|
|
|
+
|
|
|
|
|
+## Inhalt
|
|
|
|
|
+
|
|
|
|
|
+- [Einführung](#einführung)
|
|
|
|
|
+- [Übersicht der Module](#übersicht-der-module)
|
|
|
|
|
+- [Verzeichnisstruktur](#verzeichnisstruktur)
|
|
|
|
|
+- [Modul 2: Diagramme verstehen](#modul-2-diagramme-verstehen)
|
|
|
|
|
+- [Entwicklungsumgebung](#build-tool-chain)
|
|
|
|
|
+- [Javascript](#javascript)
|
|
|
|
|
+- [Sass](#sass)
|
|
|
|
|
+- [Bilddateien](#bilddateien)
|
|
|
|
|
+- [Entwicklungshistorie](#entwicklungshistorie)
|
|
|
|
|
+
|
|
|
|
|
+## Einführung
|
|
|
|
|
+
|
|
|
|
|
+Das Projekt [RisikoAtlas](https://risikoatlas.de) hat die Förderung der
|
|
|
|
|
+Risikokompetenz zum Ziel. Zu diesem Zweck wurden am Harding-Zentrum für
|
|
|
|
|
+Risikokompetenz am Max-Planck-Institut für Bildungsforschung digitale
|
|
|
|
|
+Werkzeuge entwickelt, die auf wissenschaftlichen Erkenntnissen beruhen.
|
|
|
|
|
+Neben interaktiven Visualisierungen evidenzbasierter
|
|
|
|
|
+Risikokommunikation, einer App zur Entscheidungsunterstützung und einer
|
|
|
|
|
+Browser-Erweiterung als Leseassistenz sind Lernvisualisierungen zur
|
|
|
|
|
+Verbesserung der Risikokompetenz Teil des Projektes. Das vorliegende
|
|
|
|
|
+Modul ist eines dieser sechs Lernmodule.
|
|
|
|
|
+
|
|
|
|
|
+Die Lernmodule wurden ursprünglich entwickelt von [kf
|
|
|
|
|
+interactive](https://www.kf-interactive.com).
|
|
|
|
|
+
|
|
|
|
|
+## Übersicht der Module
|
|
|
|
|
+
|
|
|
|
|
+Die folgende Liste gibt einen Überblick über die Ziele der Module:
|
|
|
|
|
+
|
|
|
|
|
+1. Module01 -- Risiken vergleichen **\***
|
|
|
|
|
+2. **Module02 -- Diagramme verstehen** **\***
|
|
|
|
|
+3. Module03 -- Trends schätzen **\***
|
|
|
|
|
+4. Module04 -- Stichproben verstehen (original: [Rock 'n
|
|
|
|
|
+ poll](http://rocknpoll.graphics/))
|
|
|
|
|
+5. Module05 -- Relative Risiken verstehen **\***
|
|
|
|
|
+6. Module06 -- Wachstumsprozesse verstehen
|
|
|
|
|
+
|
|
|
|
|
+Alle mit einem **\*** versehenen Module greifen über eine API auf eine
|
|
|
|
|
+Datenbank zu. Auf diese Weise rufen sie die benötigten Daten ab, und
|
|
|
|
|
+speichern andererseits Antworten der Benutzer, um ihnen den Vergleich zu
|
|
|
|
|
+Anderen zu ermöglichen. Für jedes dieser Module existiert auch eine
|
|
|
|
|
+offline-Version, die ausschließlich auf lokale Daten zugreift.
|
|
|
|
|
+
|
|
|
|
|
+## Verzeichnisstruktur
|
|
|
|
|
+
|
|
|
|
|
+Im Wurzelverzeichnis liegen die für den Build Prozess notwendigen
|
|
|
|
|
+Konfigurationsdateien. Das Verzeichnis `doc/` enthält detailliertere
|
|
|
|
|
+Dokumentationen zu einzelnen Aspekten des Projekts. Alle für die WebApp
|
|
|
|
|
+benötigten Dateien werden in `public/` erstellt bzw. dorthin kopiert. Im
|
|
|
|
|
+`src/` Verzeichnis befinden sich alle Quelldateien, Bilder und Fonts.
|
|
|
|
|
+Der `tasks/` Ordner enthält Javascript-Dateien, die die Teilschritte des
|
|
|
|
|
+Build-Prozesses definieren.
|
|
|
|
|
+
|
|
|
|
|
+Die grobe Struktur sieht folgendermaßen aus:
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ ├── .editorconfig // Konfiguration für Texteditoren
|
|
|
|
|
+ ├── .babelrc // Konfiguration von babel
|
|
|
|
|
+ ├── .eslintrc.yml // Konfiguration des Javascript Linters
|
|
|
|
|
+ ├── .htmlhintrc // Konfiguration des HTML Linters
|
|
|
|
|
+ ├── .sass-lint.yml // Konfiguration des Sass Linters
|
|
|
|
|
+ ├── config.js // Konfiguration des Build-Systems
|
|
|
|
|
+ ├── gulpfile.babel.js // gulp Datei, verwendet Definitionen unter `tasks/`
|
|
|
|
|
+ ├── package.json // npm Abhängigkeiten, Shortcuts für gulp tasks
|
|
|
|
|
+ ├── doc/ // Dokumentation in markdown
|
|
|
|
|
+ ├── public/ // Zielverzeichnis für den Build-Prozess
|
|
|
|
|
+ ├── src/ // Quellverzeichnis
|
|
|
|
|
+ │ ├── fonts // Font Dateien
|
|
|
|
|
+ │ ├── html // HTML 'Templates'
|
|
|
|
|
+ │ ├── img // Bilder und Sprites
|
|
|
|
|
+ │ ├── js // Javascript Quelldateien
|
|
|
|
|
+ │ └── scss // Sass stylesheets
|
|
|
|
|
+ └── tasks/ // Definitionen für den gulp Build-Prozess
|
|
|
|
|
+
|
|
|
|
|
+## Modul 2: Diagramme verstehen
|
|
|
|
|
+
|
|
|
|
|
+Dieses Modul stellt ein interaktives Werkzeug als Hilfe zur Verbesserung
|
|
|
|
|
+des Verständnisses von Diagrammen bereit.\
|
|
|
|
|
+Dazu werden den Nutzern Multiple-Choice-Fragen zu Charakteristiken des
|
|
|
|
|
+gezeigten Graphen präsentiert. Die Lösung und gegebenenfalls die falsch
|
|
|
|
|
+gewählte Antwort werden grafisch hervorgehoben. Ein zweiter Typ von Test
|
|
|
|
|
+ermöglicht es den Nutzern, Teile des Diagramms auszuwählen und zu
|
|
|
|
|
+skalieren, um einen in der Frage vorgegebenen Effekt zu erzielen. Dies
|
|
|
|
|
+soll zeigen, wie einfache Manipulationen die Interpretation von Graphen
|
|
|
|
|
+beeinflussen können. Erst wenn eine korrekte Lösung gefunden wurde, kann
|
|
|
|
|
+zur folgenden Aufgabe weitergegangen werden.
|
|
|
|
|
+
|
|
|
|
|
+### Javascript Verzeichnisstruktur
|
|
|
|
|
+
|
|
|
|
|
+Für einen besseren Überblick sind die Quell-Dateien mit kurzen
|
|
|
|
|
+Beschreibungen aufgelistet:
|
|
|
|
|
+
|
|
|
|
|
+ ├── main.jsx // Einstiegspunkt für App *mit* Verwendung der API ("online mode")
|
|
|
|
|
+ ├── main-offline.jsx // Einstiegspunkt für App *ohne* Verwendung der API ("offline mode")
|
|
|
|
|
+ ├── config.js // Globale Konfiguration der WebApp
|
|
|
|
|
+ ├── components // (p)react Komponenten
|
|
|
|
|
+ │ ├── Index.jsx // Web App Haupt-Komponente
|
|
|
|
|
+ │ └── partials
|
|
|
|
|
+ │ ├── GraphItem.jsx // Komponente für d3 Visualisierungen
|
|
|
|
|
+ │ ├── IntroItem.jsx // Komponente für die Einführung zu den Fragen
|
|
|
|
|
+ │ └── QuestionItem.jsx // Komponente für Benutzereingaben für Fragen
|
|
|
|
|
+ ├── content
|
|
|
|
|
+ │ ├── Gruppe-x_item-y.json // Definitionen der Fragen
|
|
|
|
|
+ │ ├── module.json // Definition der (meisten) Labels und Texte des User Interfaces
|
|
|
|
|
+ │ └── offline.js // Definition der Reihenfolge der Fragen
|
|
|
|
|
+ ├── d3 // d3 Module
|
|
|
|
|
+ │ ├── configuration.js // Konfiguration für d3-Module
|
|
|
|
|
+ │ ├── axes.js // Achsendefinitionen
|
|
|
|
|
+ │ ├── main.js // d3 Haupt-Modul
|
|
|
|
|
+ │ ├── defs.js // Defintionen für SVG-Element <defs> (clip-path, gradient)
|
|
|
|
|
+ │ ├── gradient.js // Darstellung der Steigung innerhalb eines Intervalls (Fragetyp 3)
|
|
|
|
|
+ │ ├── grid.js // Skalierendes Hintergrundraster
|
|
|
|
|
+ │ ├── handleConnector.js // Definition der Verbindungslinien zwischen Anfassern (Fragetyp 3)
|
|
|
|
|
+ │ ├── handleSymbols.js // Definition der Geometrie der Anfasser als SVG symbols (Fragetyp 3)
|
|
|
|
|
+ │ ├── handle.js // Konstruktor und Definition des Verhaltens der Anfasser (Fragetyp 3)
|
|
|
|
|
+ │ ├── legend.js // Legende der Graphen
|
|
|
|
|
+ │ ├── bar.js // Balkendiagramm als Feedback für Benutzer
|
|
|
|
|
+ │ ├── lineGraphs.js // Darstellung der Graphen
|
|
|
|
|
+ │ ├── points.js // Hervorhebung der Lösung / falschen Antwort (Fragetyp 1)
|
|
|
|
|
+ │ ├── scales.js // d3 Skalen für x- und y-Achsen
|
|
|
|
|
+ │ ├── range.js // Definition eines Auswahlbereichs (Fragetyp 3)
|
|
|
|
|
+ │ └── rangeController.js // Controller für Auswahlbereich; Kommunikation zwischen Visualisierungs-Modulen (untereinander) und Anwendung
|
|
|
|
|
+ └── utilities
|
|
|
|
|
+ ├── api.js // API für Lese- und Schreibzugriff auf die Datenbank
|
|
|
|
|
+ ├── enableTouch.js
|
|
|
|
|
+ ├── fonts.js
|
|
|
|
|
+ ├── formatter.js
|
|
|
|
|
+ ├── math.js
|
|
|
|
|
+ ├── randomizer.js
|
|
|
|
|
+ └── validator.js // Funktionen zur Validierung der Benutzerantworten
|
|
|
|
|
+
|
|
|
|
|
+### Wie ändere ich Bezeichner und Datenbasis?
|
|
|
|
|
+
|
|
|
|
|
+Um den Benutzern den Vergleich zu anderen zu ermöglichen, wird die
|
|
|
|
|
+Anbindung an eine Datenbank ermöglicht. Diese ist über eine API
|
|
|
|
|
+anzusprechen, die im Abschnitt "Online Version" dokumentiert ist. Es ist
|
|
|
|
|
+aber genauso möglich, auf diese Datenbankanbindung zu verzichten und
|
|
|
|
|
+stattdessen nur "lokale" Daten zu nutzen. Die dafür relevanten Dateien
|
|
|
|
|
+sind unter "Offline Version" dokumentiert.
|
|
|
|
|
+
|
|
|
|
|
+#### *Offline* Version
|
|
|
|
|
+
|
|
|
|
|
+Die "lokalen" Inhalte und Daten sind in den `json`-Dateien Dateien unter
|
|
|
|
|
+`src/js/content` definiert.
|
|
|
|
|
+
|
|
|
|
|
+#### Labels
|
|
|
|
|
+
|
|
|
|
|
+##### Umgebende Texte
|
|
|
|
|
+
|
|
|
|
|
+In `module.json` sind die umgebenden Texte und Labels definiert, die
|
|
|
|
|
+nicht direkt Teil der WebApp sind. Dies umfasst die einleitenden
|
|
|
|
|
+(`introtext`) und abschließenden Texte (`outrotext`) und die Labels der
|
|
|
|
|
+Buttons und Vergleichsansichten mit anderen Nutzern.
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ "title": "Wie werden Finanzstatistiken verzerrt?",
|
|
|
|
|
+ "introtext": "Um zu lernen, wie Statistiken verzerrt werden, …",
|
|
|
|
|
+ "outrotext": "Was haben Sie geübt? …",
|
|
|
|
|
+ "success": "Sie haben die Lösung erreicht!",
|
|
|
|
|
+ "next": "Weiter",
|
|
|
|
|
+ "start": "Start",
|
|
|
|
|
+ "restart": "Neustart",
|
|
|
|
|
+ "usersVoteHeadline": "So wählten die User",
|
|
|
|
|
+ "usersRight": "Andere Nutzer lagen richtig"
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+##### Labels der WebApp
|
|
|
|
|
+
|
|
|
|
|
+Der Titel der Aufgabe, Achsenbezeichner und Legendentext werden aus der
|
|
|
|
|
+`json`-Datei der jeweiligen Aufgabe (Namensschema
|
|
|
|
|
+`Gruppe-<x>_item-<a>.json`) gelesen und können dort geändert werden
|
|
|
|
|
+(siehe anschließenden Abschnitt zu Daten). Die Beschriftung der x-Achse
|
|
|
|
|
+wird direkt aus den Daten übernommen, die y-Achse dagegen automatisch
|
|
|
|
|
+von der Javascript-Bibliothek [d3js](https://d3js.org) generiert.
|
|
|
|
|
+
|
|
|
|
|
+```{=html}
|
|
|
|
|
+<pre>
|
|
|
|
|
+"text": "<b>Welchen Gewinn erzielte Citroniger im 4. Quartal 2016?</b>",
|
|
|
|
|
+"antworten": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "antwort": "<b>15 Millionen</b>",
|
|
|
|
|
+ …
|
|
|
|
|
+ },
|
|
|
|
|
+ …
|
|
|
|
|
+],
|
|
|
|
|
+"data": [
|
|
|
|
|
+ "id": 1,
|
|
|
|
|
+ "konkurrent": "<b>Apfelreich</b>",
|
|
|
|
|
+ "koordinaten": [
|
|
|
|
|
+ { "x": <b>"Q1/2013"</b>, "y": 21.29 },
|
|
|
|
|
+ …
|
|
|
|
|
+ ],
|
|
|
|
|
+ …
|
|
|
|
|
+],
|
|
|
|
|
+</pre>
|
|
|
|
|
+```
|
|
|
|
|
+#### Daten
|
|
|
|
|
+
|
|
|
|
|
+In der Datei `offline.js` wird die Reihenfolge der Fragen bzw. Aufgaben
|
|
|
|
|
+definiert. Die Daten der jeweiligen Aufgabe ist in der entsprechenden
|
|
|
|
|
+Datei benannt nach dem Schema `Gruppe-<x>_item-<y>.json` definiert.
|
|
|
|
|
+
|
|
|
|
|
+Zu jeder Aufgabe sind Metadaten definiert, wie die ID der Aufgabe, Titel
|
|
|
|
|
+(`text`) und `gruppe`, was den Aufgabentyp bezeichnet. Im `data` Array
|
|
|
|
|
+sind die Koordinaten und Metadaten der Graphen enthalten.
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ "id": 1,
|
|
|
|
|
+ "konkurrent": "Apfelreich",
|
|
|
|
|
+ "koordinaten": [
|
|
|
|
|
+ { "x": "Q1/2013", "y": 21.29 },
|
|
|
|
|
+ …
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+**1. Finden eines bestimmten x- oder y-Wertes eines Graphen z**
|
|
|
|
|
+
|
|
|
|
|
+Die Antworten dieses Typs bestehen aus einem Label (`"antwort"`) und
|
|
|
|
|
+Koordinaten für den entsprechenden Punkt, z.B.:
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ "antwort": "15 Millionen",
|
|
|
|
|
+ "korrekt": false,
|
|
|
|
|
+ "coordinates": {"x": "Q4/2016", "y": 15.00}
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+**2. Beurteilung und Vergleich der Entwicklung der Graphen (negative /
|
|
|
|
|
+positive / unbeständige Entwicklung, Mittelwert)**
|
|
|
|
|
+
|
|
|
|
|
+Bei diesem Aufgabentyp soll der Graph benannt werden, der die gefragte
|
|
|
|
|
+Eigenschaft besitzt:
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ "antwort": "Apfelreich",
|
|
|
|
|
+ "korrekt": true
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+**3. Manipulation des Graphen, so dass im betrachteten Teilsegment die
|
|
|
|
|
+grafische Wirkung der Steigung / des Gefälles verstärkt bzw.
|
|
|
|
|
+abgeschwächt wird.**
|
|
|
|
|
+
|
|
|
|
|
+Bei diesem Aufgabentyp sollen Graphen so manipuliert werden, dass im
|
|
|
|
|
+betrachteten Teilsegment die grafische Wirkung der Steigung / des
|
|
|
|
|
+Gefälles verstärkt bzw. abgeschwächt wird. Dies geschieht durch das
|
|
|
|
|
+Verändern der Grenzen einer Auswahl, das vertikale und horizontale
|
|
|
|
|
+Skalieren der Graphen basierend auf der gewählten Auswahl.
|
|
|
|
|
+
|
|
|
|
|
+Die Steigung wird grafisch visualisiert, sobald sich beide Punkte
|
|
|
|
|
+gleichzeitig innerhalb des Auswahlbereichs und des sichtbaren Bereichs
|
|
|
|
|
+befinden. Wurde der Graph so transformiert, dass die betrachtete
|
|
|
|
|
+Steigung innerhalb der Grenzwerte liegt, dann wird die Steigungsstrecke
|
|
|
|
|
+grün gefärbt und der Button zum fortfahren zur nächsten Aufgabe
|
|
|
|
|
+eingeblendet. Die Grenzwerte sind mit der Aufgabe definiert in der
|
|
|
|
|
+`json`-Datei als `anstiegUntereGrenze` und `anstiegObereGrenze`. Die
|
|
|
|
|
+Grenzen des betrachteten Intervalls werden mit `untereGrenze` und
|
|
|
|
|
+`obereGrenze` festgelegt.
|
|
|
|
|
+
|
|
|
|
|
+#### *Online* Version
|
|
|
|
|
+
|
|
|
|
|
+Die Konfiguration für den Zugriff auf die API ist in `src/js/config.js`
|
|
|
|
|
+definiert. Ein Request wird zusammengesetzt aus der URL der API, einem
|
|
|
|
|
+Endpunkt und optionalen Informationen, die je nach HTTP Methode als
|
|
|
|
|
+Parameter der URL angehängt werden, oder im *Message Body* des Requests
|
|
|
|
|
+verschickt werden.
|
|
|
|
|
+
|
|
|
|
|
+##### Anwendungsdaten
|
|
|
|
|
+
|
|
|
|
|
+1. Abfrage aller Aufgaben in einer Liste. Die Ordnung (Id) entspricht
|
|
|
|
|
+ der Ordnung der in der Excel-Datei abgelegten Liste. Aufgaben sind
|
|
|
|
|
+ zusätzlich qualifiziert durch "Gruppe" (int) und "Item" (string),
|
|
|
|
|
+ aus denen der Name konstruiert wird (Gruppe=2, Item="c" =\>
|
|
|
|
|
+ Name="Frage 2c")
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_Aufgaben/Liste`
|
|
|
|
|
+
|
|
|
|
|
+2. Abfrage einer spezifischen Aufgabe
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_Aufgaben/ById/{id}`
|
|
|
|
|
+
|
|
|
|
|
+3. Abfrage einer Liste von Aufgaben, die zu einer bestimmten Gruppe
|
|
|
|
|
+ gehören
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_Aufgaben/Gruppe?gruppe={gruppe}`
|
|
|
|
|
+
|
|
|
|
|
+Abfrage einer durch eine Gruppe und Item qualifizierte Aufgabe????
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_Aufgaben/Auswahl?gruppe={gruppe}&item={item}`
|
|
|
|
|
+
|
|
|
|
|
+##### Benutzerdaten
|
|
|
|
|
+
|
|
|
|
|
+1. Abfrage aller Benutzer-Daten
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/Liste`
|
|
|
|
|
+
|
|
|
|
|
+2. Abfrage eines spezifischen Benutzer-Datensatzes
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/ById/{id}`
|
|
|
|
|
+
|
|
|
|
|
+3. Abfrage aller Daten für einen bestimmten Benutzer
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/ByUserId?userId={userId}`
|
|
|
|
|
+
|
|
|
|
|
+4. Gibt die UserData für eine durch eine Gruppe und Item qualifizierte
|
|
|
|
|
+ Aufgabe zurück
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/ByAufgabe?gruppe={gruppe}&item={item}`
|
|
|
|
|
+
|
|
|
|
|
+5. Gibt die UserData für eine durch die AufgabeId qualifizierte Aufgabe
|
|
|
|
|
+ zurück
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/ByAufgabeId?aufgabeId={aufgabeId}`
|
|
|
|
|
+
|
|
|
|
|
+6. Gibt für alle Fragen die Anteile korrekter und falscher Antworten
|
|
|
|
|
+ zurück
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/Proportions`
|
|
|
|
|
+
|
|
|
|
|
+7. Gibt für eine bestimmte Frage die Anteile korrekter und falscher
|
|
|
|
|
+ Antworten zurück
|
|
|
|
|
+
|
|
|
|
|
+`GET api/M2_AufgabenUserData/ProportionsByAufgabeId?aufgabeId={aufgabeId}`
|
|
|
|
|
+
|
|
|
|
|
+8. Erzeugt einen neuen Datenrecord in der M2_AufgabeUserData-Tabelle.
|
|
|
|
|
+ Dabei sind die Angaben der AufgabeId und der UserId erforderlich, um
|
|
|
|
|
+ die Antworten einer Aufgabe/einem User zuordnen zu können. Die Id
|
|
|
|
|
+ wird nicht spezifiziert, da diese von der Datenbank automatisch
|
|
|
|
|
+ zugewiesen wird
|
|
|
|
|
+
|
|
|
|
|
+`POST api/M2_AufgabenUserData/Create`
|
|
|
|
|
+
|
|
|
|
|
+## Build Tool Chain
|
|
|
|
|
+
|
|
|
|
|
+In diesem Abschnitt werden die technischen Voraussetzungen für die
|
|
|
|
|
+Erstellung von im Browser lauffähigem Code und und die Installation und
|
|
|
|
|
+Verwendung der Entwicklungsumgebung erläutert.
|
|
|
|
|
+
|
|
|
|
|
+### Voraussetzungen
|
|
|
|
|
+
|
|
|
|
|
+Dieses Projekt wurde entwickelt auf Basis von
|
|
|
|
|
+[nodejs](https://nodejs.org) unter Verwendung von
|
|
|
|
|
+[npm](https://www.npmjs.com/) als Paket-Manager. Mit den folgenden
|
|
|
|
|
+Versionen wurde zuletzt getestet:
|
|
|
|
|
+
|
|
|
|
|
+ nodejs: v14.4.0
|
|
|
|
|
+ npm: 6.14.4
|
|
|
|
|
+
|
|
|
|
|
+Alle Abhängigkeiten sind definiert in der `npm` Konfigurations-Datei
|
|
|
|
|
+`package.json`. Wie üblich werden diese installiert mit dem Befehl
|
|
|
|
|
+`npm install`. Als Task-Manager dieses Projekts wird
|
|
|
|
|
+[gulp](https://gulpjs.com/) dabei global installiert.
|
|
|
|
|
+
|
|
|
|
|
+Für das Erstellen der Dokumentation aus den einzelnen
|
|
|
|
|
+*Markdown*-Dateien, die im Verzeichnis `doc/` liegen, wird
|
|
|
|
|
+[pandoc](https://pandoc.org) verwendet. Dieses ist für viele
|
|
|
|
|
+Betriebssysteme und Distributionen verfügbar, muss aber gesondert
|
|
|
|
|
+installiert werden.
|
|
|
|
|
+
|
|
|
|
|
+### Konfiguration
|
|
|
|
|
+
|
|
|
|
|
+Die Build Konfiguration ist in `config.js` im Wurzelverzeichnis
|
|
|
|
|
+definiert. Außerdem sind in der Datei `package.json` die zu
|
|
|
|
|
+unterstützenden Browser-Versionen für `autoprefixer` angegeben.
|
|
|
|
|
+
|
|
|
|
|
+Konfigurationen für Babel, Editoren und *Linter* sind ebenfalls im
|
|
|
|
|
+Wurzelverzeichnis zu finden:
|
|
|
|
|
+
|
|
|
|
|
+ babel: .babelrc
|
|
|
|
|
+ editorconfig: .editorconfig
|
|
|
|
|
+ html: .htmlhintrc
|
|
|
|
|
+ javascript: .eslintrc.yml
|
|
|
|
|
+ sass: .sass-lint.yml
|
|
|
|
|
+
|
|
|
|
|
+### Erstellen von Builds
|
|
|
|
|
+
|
|
|
|
|
+Alle Schritte zum Erstellen von Builds sind in den Javascript-Dateien
|
|
|
|
|
+unter `tasks/` definiert und werden von der `gulp` Konfigurationsdatei
|
|
|
|
|
+`gulpfile.babel.js` importiert. Dort sind die Teilschritte in *Tasks*
|
|
|
|
|
+zusammengefasst, die man am häufigsten benötigt.
|
|
|
|
|
+
|
|
|
|
|
+ $ gulp # Default task, Kurzform für 'gulp watch'
|
|
|
|
|
+ $ gulp build # Erstellt einen Development Build
|
|
|
|
|
+ $ gulp watch # Erstellt einen Development Build und startet den Entwicklungsserver
|
|
|
|
|
+
|
|
|
|
|
+#### Build Target
|
|
|
|
|
+
|
|
|
|
|
+Die Unterscheidung zwischen Development und Production Build wird anhand
|
|
|
|
|
+der `nodejs` Umgebungsvariable `NODE_ENV` vorgenommen. Ohne diese Angabe
|
|
|
|
|
+wird immer ein Development Build erstellt (siehe `config.js`). Für das
|
|
|
|
|
+Development Target werden Javascript und CSS zusätzlich mit *Sourcemaps*
|
|
|
|
|
+versehen, für die Produktiv-Version dagegen werden die Dateien von
|
|
|
|
|
+unnötigem Ballast befreit (`terser` für Javascript, `cssnano` für CSS).
|
|
|
|
|
+
|
|
|
|
|
+ # Erstellen eines Production Build
|
|
|
|
|
+ $ NODE_ENV=production gulp build
|
|
|
|
|
+
|
|
|
|
|
+#### Build Mode
|
|
|
|
|
+
|
|
|
|
|
+Zusätzlich gibt es für dieses Projekt die Unterscheidung zwischen
|
|
|
|
|
+'online' und 'offline' Versionen. Im Fall der 'online' Version wird auf
|
|
|
|
|
+eine API zugegriffen, um die benötigten Inhalte zu laden, und um die
|
|
|
|
|
+Antworten der Benutzer zu speichern, um ihnen einen Vergleich mit
|
|
|
|
|
+Anderen zu ermöglichen. Diese Unterscheidung kann beim Aufruf von gulp
|
|
|
|
|
+auf der Kommandozeile mit einem Parameter getroffen werden. Soweit
|
|
|
|
|
+verfügbar, wird standardmäßig der 'online' Modus verwendet, (siehe
|
|
|
|
|
+`config.js`).
|
|
|
|
|
+
|
|
|
|
|
+ # Erstellen eines Development Build für den 'offline' Modus
|
|
|
|
|
+ $ gulp --api-mode=offline
|
|
|
|
|
+
|
|
|
|
|
+#### npm Shortcuts
|
|
|
|
|
+
|
|
|
|
|
+Da die Handhabung mit dem Setzen der Umgebungsvariable und das Übergeben
|
|
|
|
|
+des Parameters etwas umständlich ist, sind in `package.json` `npm` ein
|
|
|
|
|
+paar Shortcuts definiert, z.B.:
|
|
|
|
|
+
|
|
|
|
|
+ # Erstellen eines Production Build für den 'offline' Modus per gulp Script
|
|
|
|
|
+ $ NODE_ENV=production gulp build --api-mode=offline
|
|
|
|
|
+
|
|
|
|
|
+ # Erstellen eines Production Build für den 'offline' Modus per npm Script
|
|
|
|
|
+ $ npm run build:prod:offline
|
|
|
|
|
+
|
|
|
|
|
+### Erstellen der Dokumentation
|
|
|
|
|
+
|
|
|
|
|
+Die Dokumentation in einzelne *Markdown*-Dateien aufgeteilt, die im
|
|
|
|
|
+Verzeichnis `doc/` liegen. Zum Erstellen einer zusammenhängender
|
|
|
|
|
+Dokumentation sind folgende `npm` Scripts definiert, die auf `pandoc`
|
|
|
|
|
+basieren:
|
|
|
|
|
+
|
|
|
|
|
+ npm build:doc // Kurzform für das Erstellen der Dokumentation im bevorzugten Ausgabeformat (Standard: Markdown)
|
|
|
|
|
+ npm build:doc:html // Erstellt eine HTML Dokumentation als `index.html` in `doc/html`
|
|
|
|
|
+ npm build:doc:md // Erstellt eine zusammenhängende Dokumentation als `readme.md` im Wurzelverzeichnis
|
|
|
|
|
+
|
|
|
|
|
+### Konventionen
|
|
|
|
|
+
|
|
|
|
|
+Der Javascript Code ist in ES6 (bzw. ES2015) verfasst. Als
|
|
|
|
|
+CSS-Preprocessor wird Sass mit der `scss` Syntax verwendet. Die Code
|
|
|
|
|
+Style Konventionen wurden von den ursprünglichen Entwicklern übernommen
|
|
|
|
|
+und nur an wenigen Stellen leicht angepasst.
|
|
|
|
|
+
|
|
|
|
|
+Das Projekt verwendet [editorconfig](http://editorconfig.org) für die
|
|
|
|
|
+Integration dieser Konventionen in Editoren, die entsprechende Datei
|
|
|
|
|
+heißt `.editorconfig`.
|
|
|
|
|
+
|
|
|
|
|
+Für die statische Überprüfung des Quellcodes werden folgende *Linter*
|
|
|
|
|
+verwendet:
|
|
|
|
|
+
|
|
|
|
|
+- Javascript: [eslint](https://eslint.org)
|
|
|
|
|
+- Sass: [sass-lint](https://github.com/sasstools/sass-lint)
|
|
|
|
|
+- HTML: [HTMLHint](https://github.com/htmlhint/HTMLHint)
|
|
|
|
|
+
|
|
|
|
|
+Die zugehörigen Konfigurationsdateien befinden sich im Root-Verzeichnis,
|
|
|
|
|
+wie oben in der Auflistung angegeben.
|
|
|
|
|
+
|
|
|
|
|
+## Javascript
|
|
|
|
|
+
|
|
|
|
|
+### Verwendete Bibliotheken
|
|
|
|
|
+
|
|
|
|
|
+Die grundlegende Architektur der WebApp wurde implementiert auf Basis
|
|
|
|
|
+von [preact](https://preactjs.com/), von den Entwicklern beworben mit
|
|
|
|
|
+
|
|
|
|
|
+> Fast 3kB alternative to React with the same modern API.
|
|
|
|
|
+
|
|
|
|
|
+Es ist allerdings keine exakte Reimplementierung, weswegen ein eigener
|
|
|
|
|
+Teil der Dokumentation der [Erläuterung der Unterschiede zu
|
|
|
|
|
+React](https://preactjs.com/guide/v10/differences-to-react) gewidmet
|
|
|
|
|
+ist.
|
|
|
|
|
+
|
|
|
|
|
+Für Visualisierungen wird die großartige und weit verbreitete Bibliothek
|
|
|
|
|
+[D3.js](https://d3js.org/) verwendet.
|
|
|
|
|
+
|
|
|
|
|
+### Verzeichnisstruktur
|
|
|
|
|
+
|
|
|
|
|
+Die folgende Auflistung gibt einen groben Überblick über die
|
|
|
|
|
+Verzeichnisstruktur der Javascript Quelldateien in `src/js/`. Als
|
|
|
|
|
+Einstieg dient `main.jsx` bzw. `main-offline.jsx` für den "offline"
|
|
|
|
|
+Modus. `config.js` ist die zentrale Konfigurationsdatei der WebApp. In
|
|
|
|
|
+`components` liegen die Komponenten der *preact*-WebApp. Der Quellcode
|
|
|
|
|
+für die D3-Visualisierungen befindet sich unter `d3`.
|
|
|
|
|
+
|
|
|
|
|
+ ├── main.jsx // Einstiegspunkt für App in "online" Modus
|
|
|
|
|
+ ├── main-offline.jsx // Einstiegspunkt für App in "offline" Modus
|
|
|
|
|
+ ├── config.js // Konfiguration der WebApp
|
|
|
|
|
+ ├── components/ // Verzeichnis für (p)react Komponenten
|
|
|
|
|
+ │ ├── Index.jsx // Web App Haupt-Komponente
|
|
|
|
|
+ │ └── partials/ // Vezeichnis für Teilkomponenten
|
|
|
|
|
+ ├── content/ // Verzeichnis für "offline" Inhalte
|
|
|
|
|
+ ├── d3/ // d3 Module
|
|
|
|
|
+ └── utilities/ // Verzeichnis für Hilfs-Bibliotheken und Werkzeuge
|
|
|
|
|
+
|
|
|
|
|
+## Sass
|
|
|
|
|
+
|
|
|
|
|
+Zum Kompilieren von Sass zu CSS wird `gulp-sass` verwendet, das
|
|
|
|
|
+`node-sass` benutzt, welches wiederum auf `libsass` basiert. `node-sass`
|
|
|
|
|
+hat sich beim wiederholten gedankenlosen Aktualisieren von `nodejs` und
|
|
|
|
|
+/ oder `npm` als notorischer Nerventöter herausgestellt, daher an dieser
|
|
|
|
|
+Stelle der [Verweis zur *Troubleshooting*
|
|
|
|
|
+Dokumentation](https://github.com/sass/node-sass/blob/master/TROUBLESHOOTING.md)
|
|
|
|
|
+von `node-sass`. Meist reichte im Falle eines Problems aber ein
|
|
|
|
|
+`npm rebuild node-sass`.
|
|
|
|
|
+
|
|
|
|
|
+### Struktur
|
|
|
|
|
+
|
|
|
|
|
+In der Datei `main.scss` werden alle Stile eingebunden, die in den
|
|
|
|
|
+*Partials* definiert werden, woraus die endgültige CSS-Datei generiert
|
|
|
|
|
+wird. Die Struktur des `src/scss` Verzeichnisses sieht folgendermaßen
|
|
|
|
|
+aus:
|
|
|
|
|
+
|
|
|
|
|
+ ├── base // Stile für HTML Elemente
|
|
|
|
|
+ ├── config // Globale Variable
|
|
|
|
|
+ ├── modules // Stile für Module
|
|
|
|
|
+ └── tools // Definierte *mixins* und Funktionen
|
|
|
|
|
+
|
|
|
|
|
+### Konventionen, Techniken und Tools
|
|
|
|
|
+
|
|
|
|
|
+Generell wird eine "mobile first" Strategie verfolgt. Als
|
|
|
|
|
+Standard-Einheit wird `rem` verwendet, auf deren Grundlage die
|
|
|
|
|
+Basis-Einheit definiert ist. Da sich alle Größen auf diese Einheit
|
|
|
|
|
+beziehen sollten, wird so das Skalieren des Layouts erleichtert.
|
|
|
|
|
+
|
|
|
|
|
+Sass wird in diesem Projekt mit der scss-Syntax verwendet. Stilistisch
|
|
|
|
|
+ist es in "oldschool BEM-Style" gehalten, Zitat der ursprünglichen
|
|
|
|
|
+Entwickler. Sie beziehen sich zudem auf bestimmte Guidelines:
|
|
|
|
|
+
|
|
|
|
|
+> Hugo Giraudel wrote an awesome piece on everything you need to know
|
|
|
|
|
+> about Sass, it's called [Sass Guidelines](http://sass-guidelin.es/)
|
|
|
|
|
+> and you should really have a look at it. I agree with this guideline
|
|
|
|
|
+> in almost all points, but I try to keep something more simple, and
|
|
|
|
|
+> some things more strict, the linter will let you know :)
|
|
|
|
|
+
|
|
|
|
|
+ʕ̡̢̡ॢ•̫͡ॢ•ʔ̢̡̢
|
|
|
|
|
+
|
|
|
|
|
+Regeln mit Browser-spezifischen Präfixen (*vendor prefixes*) werden dem
|
|
|
|
|
+CSS automatisch durch
|
|
|
|
|
+[autoprefixer](https://github.com/postcss/autoprefixer) hinzugefügt. Die
|
|
|
|
|
+Liste der zu unterstützenden Browser ist in `package.json` unter
|
|
|
|
|
+`browserslist` zu finden.
|
|
|
|
|
+
|
|
|
|
|
+## Bilddateien
|
|
|
|
|
+
|
|
|
|
|
+Alle in diesem Projekt verwendeten Bilddateien befinden sich unter
|
|
|
|
|
+`src/img/`.
|
|
|
|
|
+
|
|
|
|
|
+Icons in Form von SVG-Dateien befinden sich im Unterordner
|
|
|
|
|
+`src/img/sprites` und werden im Build-Prozess mittels `gulp-svg-sprite`
|
|
|
|
|
+zu einem Sprite zusammengefasst. Sie wie folgt in HTML referenziert
|
|
|
|
|
+werden:
|
|
|
|
|
+
|
|
|
|
|
+ <svg class="icon icon--arrow-left">
|
|
|
|
|
+ <use xlink:href="assets/img/sprites.svg#icon--arrow-left"/>
|
|
|
|
|
+ </svg>
|
|
|
|
|
+
|
|
|
|
|
+Stil-Definitionen für Icons sind unter `src/scss/modules/_icons.scss` zu
|
|
|
|
|
+finden. Für die Unterstützung von Fragmentbezeichnern (*fragment
|
|
|
|
|
+identifier*) in Internet Explorer wird
|
|
|
|
|
+[svgxuse](https://github.com/Keyamoon/svgxuse) verwendet.
|
|
|
|
|
+
|
|
|
|
|
+## Entwicklungshistorie
|
|
|
|
|
+
|
|
|
|
|
+Ursprünglich wurde dieses Modul als Auftragsarbeit von einer externen
|
|
|
|
|
+Firma entwickelt. Unglücklicherweise wurden während der
|
|
|
|
|
+Entwicklungsphase keine Code-Audits durchgeführt und die Qualität des
|
|
|
|
|
+gelieferten Codes ließ zu wünschen übrig. Teile des Codes mussten
|
|
|
|
|
+komplett neu entwickelt werden, da eine Fehlerbehebung nicht anders
|
|
|
|
|
+möglich erschien. Dies führte zu einer heterogenen Software-Architektur,
|
|
|
|
|
+da bei der Neuentwicklung in erster Linie auf Wartbarkeit und
|
|
|
|
|
+Verständlichkeit Wert gelegt wurde und einer angemessenen
|
|
|
|
|
+Dokumentierung.
|
|
|
|
|
+
|
|
|
|
|
+### Gründe für eine teilweise Neu-Implementierung des Moduls
|
|
|
|
|
+
|
|
|
|
|
+Teile des Codes mussten neu entwickelt werden, da insbesondere die
|
|
|
|
|
+originale Implementierung der Visualisierungs-Komponente größtenteils
|
|
|
|
|
+unwartbar war. Einfache Fehler zu beheben war nur schwer möglich, da der
|
|
|
|
|
+Code mit einer unerkennbaren Logik in Module aufgeteilt war und gängige
|
|
|
|
|
+Techniken und von d3 ignoriert wurden.
|
|
|
|
|
+
|
|
|
|
|
+1. Ein "Modul" mit dem Namen "redraw" war nur dazu gedacht,
|
|
|
|
|
+ SVG-Elemente, die in anderen Code-Fragmenten erstellt wurden, zu
|
|
|
|
|
+ aktualisieren. ﴾͡๏̯͡๏﴿\
|
|
|
|
|
+ Um Wartbarkeit als Feature zu integrieren, wurde stattdessen die
|
|
|
|
|
+ damals übliche Vorgehensweise implementiert ([General update
|
|
|
|
|
+ pattern](https://observablehq.com/@d3/general-update-pattern?collection=@d3/d3-selection)).
|
|
|
|
|
+ Inzwischen wird diese schon wieder als veraltet bezeichnet, und die
|
|
|
|
|
+ Verwendung von
|
|
|
|
|
+ [selection.join](https://observablehq.com/@d3/selection-join)
|
|
|
|
|
+ empfohlen.
|
|
|
|
|
+
|
|
|
|
|
+2. Multiple-Choice-Fragen wurden ursprünglich gegen die Labels der
|
|
|
|
|
+ Antworten validiert. Dabei wurde die Javascript Funktion `parseInt`
|
|
|
|
|
+ auf alphanumerische Strings angewendet, bzw. unflexible Reguläre
|
|
|
|
|
+ Ausdrücke verwendet, die scheitern würden, sobald sich die Struktur
|
|
|
|
|
+ der Labels oder die natürliche Sprache änderte. ( ・\_・)ノ⌒●\~\*\
|
|
|
|
|
+ Um dieses Problem zu beheben, wurde dem *offline*-Datensatz die
|
|
|
|
|
+ notwendigen Daten hinzugefügt, um mathematische Validierung über
|
|
|
|
|
+ Funktionen zu ermöglichen. Für jede Frage wird nun eine Referenz zu
|
|
|
|
|
+ einer *Validator*-Funktion angegeben, die die Daten, die mit der
|
|
|
|
|
+ gegebenen Antwort verknüpft sind, mit dem errechneten Ergebnis
|
|
|
|
|
+ vergleicht. Aktuell ist die *online*-Version des Moduls nicht
|
|
|
|
|
+ funktionsfähig, da die API noch nicht aktualisiert wurde (Stand Juni
|
|
|
|
|
+ 2020).
|
|
|
|
|
+
|
|
|
|
|
+3. Die aktuelle Implementierung ist nach wie vor sehr unflexibel
|
|
|
|
|
+ bezogen auf die Anordnung der verschiedenen Fragetypen. Die Fragen
|
|
|
|
|
+ sind in einem zweidimensionalen Array angeordnet, wobei der erste
|
|
|
|
|
+ Index den Fragetyp und der zweite die Reihenfolge innerhalb der
|
|
|
|
|
+ Gruppe definiert. Verschiedene Fragetypen können daher momentan
|
|
|
|
|
+ nicht willkürlich abgewechselt werden. Immerhin wurde der größte
|
|
|
|
|
+ Fehler behoben, der beim einfachen Umordnen von Fragen innerhalb
|
|
|
|
|
+ einer Gruppe zum "abstürzen" der Web App führte. ٩(̾●̮̮̃̾•̃̾)۶
|
|
|
|
|
+
|
|
|
|
|
+4. Die Implementierung des Aufgabentyps zum Manipulieren von Graphen
|
|
|
|
|
+ war fehlerhaft. Das Ergebnis wurde nur dann richtigerweise als
|
|
|
|
|
+ korrekt erkannt, wenn exakt das Intervall wie in der
|
|
|
|
|
+ Aufgabenstellung ausgewählt wurde. Mehrere "falsche Lösungen"
|
|
|
|
|
+ konnten gefunden werden. Dadurch konnte der Nutzer mit der folgenden
|
|
|
|
|
+ Aufgabe fortführen, auch wenn die Steigung des betrachteten
|
|
|
|
|
+ Intervalls außerhalb der Toleranzgrenzen lag. Auch waren
|
|
|
|
|
+ Konstellationen möglich, bei denen der betrachtete Teil des Graphen
|
|
|
|
|
+ außerhalb des sichtbaren Bereichs lag. Transformationen des
|
|
|
|
|
+ Auswahlbereichs wurden durch das *Parsen* von Werten aus dem SVG DOM
|
|
|
|
|
+ mit Hilfe von wackeligen Regulären Ausdrücken durchgeführt. Fügte
|
|
|
|
|
+ man der Transformation eine Rotation hinzu, funktionierte nichts
|
|
|
|
|
+ mehr. Das weckt die Vermutung, dass die Geometrie der Anfasser aus
|
|
|
|
|
+ diesem Grund zweimal definiert wurde, siehe 5.\
|
|
|
|
|
+ Dieser Teil wurde nahezu komplett neu implementiert, da der
|
|
|
|
|
+ ursprüngliche Code zusätzlich zu den beschriebenen Fehlern
|
|
|
|
|
+ unverständlich, verworren und dadurch unwartbar war. Es wurden
|
|
|
|
|
+ "Techniken" verwendet, bei denen ein Modul in den SVG-DOM
|
|
|
|
|
+ hineinschrieb und ein anderes Modul diesen Wert wieder auslas.
|
|
|
|
|
+ ⊂(©෴©)つ\
|
|
|
|
|
+ Zur Verbesserung der Verständlichkeit wurde eine
|
|
|
|
|
+ Controller-zentrische Architektur in Verbindung mit spezifischem
|
|
|
|
|
+ Event-Dispatching gewählt. Zur Validierung der Nutzer-gewählten
|
|
|
|
|
+ Auswahl werden drei Auswahlbereiche definiert: die `reference range`
|
|
|
|
|
+ bezeichnet den ursprünglich ausgewählten Bereich, auf den der
|
|
|
|
|
+ benutzerdefinierte Bereich (`selected range`) initialisiert wird.
|
|
|
|
|
+ Der Graph wird anhand letzterer transformiert. Die `solution range`
|
|
|
|
|
+ definiert die exakte Lösung und wird für die Validierung der
|
|
|
|
|
+ Nutzerauswahl verwendet. Sobald der betrachtete Teil des Graphen
|
|
|
|
|
+ sichtbar ist und das Validierungskriterium der Frage erfüllt ist,
|
|
|
|
|
+ wird die benutzerdefinierte Auswahl als Lösung anerkannt und das
|
|
|
|
|
+ Fortfahren zur folgenden Frage wird ermöglicht.
|
|
|
|
|
+
|
|
|
|
|
+5. Die Geometrie der Anfasser zum Skalieren der Graphen wurde zweimal
|
|
|
|
|
+ definiert, einmal für die horizontale und einmal für die vertikale
|
|
|
|
|
+ Version, auch wenn sie sich nur durch eine 90 Grad Rotation
|
|
|
|
|
+ unterscheiden (ganz der Wahrheit entsprechend ist das nicht, die
|
|
|
|
|
+ inneren Linien waren in einem Fall falsch ausgerichtet). Auch dieser
|
|
|
|
|
+ Code war so verworren und verständlich wie ein Stück Hirn in Aspik.
|
|
|
|
|
+ In einem Aufruf der Funktion bezog sich die Variable "width"
|
|
|
|
|
+ tatsächlich auf die Breite, im anderen Fall auf die Höhe (und
|
|
|
|
|
+ umgekehrt bei "height"). Dieser Fakt wurde, vermutlich aus Scham,
|
|
|
|
|
+ mit keinem Kommentar erwähnt. ℃ↂ_ↂ\
|
|
|
|
|
+ Die Geometrie ist nun nur einmal definiert und wird als SVG Symbol
|
|
|
|
|
+ jeweils referenziert und durch Matrizen transformiert. Nebenbei
|
|
|
|
|
+ wurde ein zeichnerisches Problem behoben.
|
|
|
|
|
+
|
|
|
|
|
+Dies sind nur Beispiele für die Probleme, die der ursprüngliche Code
|
|
|
|
|
+mitgebracht hat. Die Liste ist sicherlich nicht vollständig und es
|
|
|
|
|
+befinden sich höchstwahrscheinlich nach wie vor Eigenheiten und Fehler
|
|
|
|
|
+im Code, die man hinterfragen kann bzw. sollte.
|