``{=html}
``{=html}
Inhalt
------
- [Einführung](#einführung)
- [Übersicht der Module](#übersicht-der-module)
- [Verzeichnisstruktur](#verzeichnisstruktur)
- [Modul 3: Trends schätzen](#modul-3-trends-schaetzen)
- [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 3: Trends schätzen
------------------------
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
│ ├── ChartScreen.jsx
│ ├── FinalScreen.jsx
│ ├── Index.jsx
│ ├── TitleScreen.jsx
│ └── partials
│ ├── GraphItem.jsx // Komponente für d3 Visualisierungen
│ └── HeaderLightItem.jsx
├── content
│ ├── group-a.json // Daten zur Aufgabenstellung: Graphen-Definitionen
│ ├── group-b.json // Daten zur Aufgabenstellung: Graphen-Definitionen
│ ├── module.json // Labels und Texten des User Interfaces
│ └── offline.js // Definition der Reihenfolge der Fragen
│ └── questions.json
├── d3
│ ├── axes.js // Achsendefinitionen
│ ├── draw.js // Interaktives Zeichnen von Graphen
│ ├── grid.js // Statisches Hintergrundraster
│ ├── legend.js // Legende eines Graphen
│ ├── line.js // Darstellung eines Graphen
│ ├── main.js // d3 Haupt-Modul
│ ├── message.js // Benachrichtigung, wenn der Graph nicht über das komplette Intervall gezeichnet wurde
│ ├── point.js // Hervorgehobener Orientierungspunkt in interaktiver Ansicht
│ ├── scales.js // Definition der d3 Skalen für x- und y-Achsen
│ └── userline.js // Statische Darstellung des interaktiv gezeichneten Graphen in Vergleichsansichten
└── utilities
├── api.js // API für Lese- und Schreibzugriff auf die Datenbank
├── enableTouch.js
├── math.js
└── fonts.js
### Wie ändere ich Inhalte und Daten?
Alle Inhalte und Daten der 'offline'-Version sind in den `json`-Dateien
Dateien unter `src/js/content` definiert. Die Datei `questions.json` ist
aber sowohl für die 'offline' als auch für die 'online' Version zwingend
notwendig. Dort sind hauptächlich Labels der Fragen, aber auch Metadaten
definiert. Für das Hinzufügen oder Ändern von Fragen sind sowohl die
Texte und Labels der Frage (`questions.json`) und die Definition der
Daten der Frage (`group-.json`) anzupassen. Die Definition der
Reihenfolge der Fragen (`offline.js`) ist nur für den 'offline' Modus
relevant, im 'online' Modus wird die Reihenfolge von der Datenbank / API
bestimmt.
#### 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 den Text der Fehlermeldung bei einem nur teilweise
gezeichneten Graphen.
{
"title": "Wie stark hängen der Wert von Immobilien und die Einkommensentwicklung zusammen?",
"introtext": "In der Diskussion um die Einkommensentwicklung im Kontext steigender Mieten, …",
"outrotext": "Sie haben gleich zwei historische Entwicklungen verinnerlicht. …",
"next": "Weiter",
"start": "Start",
"restart": "Neustart",
"error": "Achtung, da fehlt noch was!",
"done": "Wenn Sie fertig sind, klicken Sie bitte auf weiter!"
}
##### Labels der WebApp
Die Texte und Labels und teilweise die Daten zu den Fragen sind in
`src/js/content/questions.json` definiert:
{
"source": "Quelle: Mack, A., and E. Martínez-García. 2011. …",
"texts": [
{
"text": "Schätzen Sie zunächst bitte, …",
"instruction": "Bitte fahren Sie über …",
"hint": "Einen Punkt haben wir Ihnen …",
"answer1": "Nicht schlecht! …",
"answer2": "Sie sehen jetzt im Vergleich …"
},
{
"text": "Den Anstieg der Immobilien behalten wir. …",
"instruction": "Bitte fahren Sie wieder …",
"hint": "Einen Punkt haben wir Ihnen …",
"answer1": "Nicht schlecht! …",
"answer2": "Sie sehen jetzt …"
}
],
"fixedPoints": [
{
"jahr": 2005,
"index": 100
},
{
"jahr": 2005,
"einkommen": 100
}
],
"yKeys": [
"index",
"einkommen"
],
"yAxisUnit": [
"Immobilienindex",
"Einkommen"
],
"legendLabels": [
"Immobilienpreis",
"Einkommen",
"Durchschnitt"
],
"xKey": "jahr",
"xAxisUnit": "Jahr"
}
Eine Frage kann aus mehreren Teilen bestehen, in diesem Fall sind es
zwei Teile, die durch die Objekte im Array `texts` definiert werden. Im
Fall der 'offline' Version werden die Texte der Felder `answer2` nicht
verwendet. `yKeys` bezieht sich auf den Datensatz und welcher Key dort
für den jeweiligen Aufgbenteil verwendet werden soll. \[*Diese Idee ist
hundsmiserabel und man hätte das Ganze den Entwicklern um die Ohren
hauen müssen, die Struktur und die Namensgebung der Labels ist
fürchterlich, aber durch die entsprechende Implementierung in der
Datenbank / API zumindest zunächst betoniert.*\]
Besser ist die Tatsache, dass die Achsenbeschriftungen für die
Aufgabenteile (`yAxisUnit`, `xAxisUnit`) und die Labels der Legende
(`legendlabels`) angepasst werden können.
Das Objekt `fixedPoints` enthält die Koordinaten des Hilfspunktes, der
in der interaktiven Ansicht angezeigt wird.
#### Daten
##### offline
Die Datei `group-a.json` in `src/js/content` enthält Daten der folgenden
Struktur:
{
"einkommen": 65.21,
"id": 1,
"index": 108.58,
"jahr": 1975
}
Dieses Objekt beschreibt für einen x-Wert ("jahr": 1975) die y-Werte für
**zwei** verschiedene Graphen. Diese Behandlung der Daten schreit nach
einer Überarbeitung des Codes, da hier Daten und (Re)präsentation
unnötigerweise und auf komplizierte Art miteinander verwurschelt werden.
Wie im vorhergehenden Abschnitt beschrieben, werden in `question.json`
die *Keys* und *Labels* definiert, die für einen Frageabschnitt
verwendet werden sollen. In diesem Beispiel bezieht sich `xKey` auf
`"jahr"`, `yKeys` je nach Frageabschnitt auf `"index"` bzw.
\`"einkommen".
##### online
``{=html}
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:
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.