Options
All
  • Public
  • Public/Protected
  • All
Menu

MathCoach IDE API Version 4.0.0

In diesem Paket (Das Gitblit Repository findet sich hier) ist die öffentliche Schnittstelle zur MathCoach Entwicklungsumgebung (IDE) definiert. Mithilfe dieser Schnittstelle können externe Werkzeuge (z.B. Editoren) erstellt werden. Ziel ist, dass diese Werkzeuge für den Anwender komfortable - in die IDE integriert -zur Verfügung gestellt werden können. Darüber hinaus werden als Ergänzung einige Hilfsfunktionen zum Bau von Werkzeugen angeboten.

Demo

Beispielhafte Anwendung: Eine Datei (file.demo.json - auch "Kontext-Datei" genannt) wird angelegt. Diese kann direkt durch das Werkzeug (Demo-Editor) geladen werden. Das Werkzeug kann die Kontext-Datei beschreiben (um zu demonstrieren, dass es ein internes Datenmodell persistent speichern kann). Weiterhin kann das Werkzeug eine Groovy-Aufgabe generieren und die Aufgaben-Vorschau anzeigen lassen.

Idee

Grundlegende Idee ist, dass ein externes Werkzeug nahtlos in die MathCoach IDE integriert werden kann. Bestimmte Dateien werden anhand ihrer Dateiendung mit dem Werkzeug verknüpft, sodass der Benutzer das passende Werkzeug durch einen einfache Klick im Datei-Explorer starten kann. Diese Datei wird im folgenden Kontext-Datei genannt und soll dazu dienen, das interene Datenmodell (also alle Informationen, die der Benutzer im Werkzeug angibt) zu speichern. Das Werkzeug soll das gespeicherte Datenmodell zu einem späteren Zeitpunkt wieder laden können.

Ein Werkzeug kann beispielsweise MathCoach-Aufgaben (Groovy-Datei) generieren. Weitere Funktionalitäten der IDE - beispielsweise das Starten der generierten Aufgabe in der Aufgaben-Vorschau der IDE - sind ebenfalls für den Werkzeugentwickler verfügbar.

Das Realisieren von Werkzeugen auf diese Art und Weise hat zahlreiche Vorteile:

  • Werkzeuge werden einheitliche und benutzerfreundlich zur Verfügung gestellt
  • Grundlegende Funktionalitäten (Anlegen von Dateien, Navigieren im Dateisystem) werden bereits durch die IDE bereitgestellt. So können Werkzeug-Entwickler ihren Fokus auf das Werkzeug legen.
  • Die IDE kann gefährliche Situationen (z.B. das Überschreiben von Dateien) abfangen und den Benutzer entscheiden lassen, wie fortgefahren werden soll.

Entwicklung externer Werkzeuge

Externe Werkzeuge laufen ausschließlich im Webbrowser des Benutzers - es muss also auf HTML, JavaScript und CSS gesetzt werden. Außerdem muss das Werkzeug unter der Domain des jeweiligen MathCoach-Servers erreichbar sein. Zur Entwicklungszeit legt man das Werkzeug dazu im www-Verzeichnis ab. Die von der IDE bereitgestellte ide-lib.js Bibliothek muss eingebunden werden.

<script src="/mathcoach/ui/ide/ide-lib.js"/> 

Dabei darf der MathCoach-Server nicht fest in die URL eincodiert werden. Andernfalls kann es zu Problemen kommen, wenn das Werkzeug auf unterschiedlichen Server bereitgestellt wird oder ohne IDE lauffähig sein soll. Bei korrekter Verwendung steht die IDE API nun durch die globale Varialbe MC zur Verfügung - Dokumentation der IDE API.

Hinweis: Es steht ausschließlich die API, welche über die globale Variable MC definiert ist, zur Verfügung! Hilfsfunktionen wie Helpers.enableOfflineUsageIfNecessary() sind grundsätzlich nicht verfügbar und müssen vom Werkzeugentwickler eingebunden werden - siehe "Hilfunktionen für Werkzeug-Entwickler" weiter unten.

Hinweis: Erst, wenn das Werkzeug in die IDE integriert und aus dieser heraus gestartet wurde, kann die IDE API verwendet werden! Soll das Werkzeug auch ohne die IDE nutzbar sein (z.B. zum Testen), muss dies bei der Implementierung berücksichtigt werden. Konnte die ide-lib.js nicht eingebunden werden (weil das Werkzeug ohne IDE gestartet wurde - darum darf auch kein Server fest eincodiert werden), steht die globale Variable MC nicht zur Verfügung (typeof MC === "undefined"). Hier kann das Werkezug eine Fallunterscheidung treffen und beispielsweise eine eigene Implementierung über die globale Variable MC bereitstellen. Siehe auch Helpers.enableOfflineUsageIfNecessary() weiter unten.

Empfohlenes Vorgehen

Damit externe Werkzeuge ein einheitliches Verhalten aufweisen, sollte wie folgt vorgegangen werden.

Als erstes muss sichergestellt werden, dass die MathCoach IDE API auch verfügbar ist. Dies ist beispielsweise nicht der Fall, wenn das Werkzeug ohne die IDE gestartet wurde oder die IDE (aus welchen Gründen auch immer) nicht einsatzbereit ist.

if(typeof MC === "undefined"){
    // Hinweis: Hier kann die IDE API nachgebildet werden,
    // sodass das Werkzeug auch "Offline" funktioniert. 
    // Also: MC = { isReady: async () => true, ...}
    throw new Error("IDE Lib nicht eingebunden"); // TODO: show error to user
}
const isReady = await MC.isReady();
if(!isReady){
    throw new Error("Die MathCoach-API ist nicht einsatzbereit."); // TODO: show error to user
}
...

Von nun an kann die IDE API vollständig genutzt werden. Zunächst sollte die Kontext-Datei (die Datei, mit der das Werkzeug gestartet wurde) geladen werden.

Ist der Inhalt der Kontext-Datei leer, wurde die Datei neu angelegt und zum ersten mal geöffnet. Nun soll das Werkzeug:

  • Sich initialisieren. Es ist sinnvoll, dass das Werkzeug mit einem beispielhaften Datenmodell inititalisiert wird.
  • Das interne Datenmodell in die Kontext-Datei schreiben
  • Die zugehörige Aufgabe generieren. Siehe auch contextFileToExerciseFile in der Dokumentation der Hilfsfunktionen.

Andernfalls kann das zuvor gespeichertes Datenmodell aus der Kontext-Datei in den Editor geladen werden. Anschließend sollte die generierten Aufgaben in der Vorschau gestartet werden, sodass der Benutzer besser abschätzen kann, wie sich Änderungen im Werkzeug auf die Aufgabe auswirken.

let contextFile = await MC.ide.getContextFile(); // Datei, mit der der Editor gestartet wurde
let contextFileContent = await MC.ide.fs.readFile(contextFile);
let contextFileIsEmpty = contextFileContent === "";

let exerciseFile = contextFileToExerciseFile(contextFile);

if(contextFileIsEmpty){
    // TODO: Datenmodell anlegen (Idealerweise mit beispielhaften Inhalt)
    // TODO: Datenmodell in Kontext-Datei schreiben, z.B. mit JSON.stringify(...)
    let dataModelAsString = JSON.stringify({/* TODO */});
    await MC.ide.fs.writeFile(contextFile, dataModelAsString);
    // TODO: Aufgabe generieren
    let generatedExerciseCode = "startup { print('Hallo Welt!') }"; 
    await MC.ide.fs.writeFile(exerciseFile, generatedExerciseCode);
}else{
    // TODO: Datenmodell laden, z.B. mit JSON.parse(contextFileContent)
    // TODO: (Aufgabe neu generieren)
    // TODO: init application based on your data model
}

// Aufgabe anzeigen
await MC.ide.navigator.navigateToExercise(exerciseFile);

Jedes Werkzeug sollte über eine "Speichern"-Funktion verfügen, mit der der Benutzer:

  • Das interne Datenmodell in die Kontext-Datei speichert (sodass es später wieder geladen werden kann)
  • Die zugehörige Aufgabe wird generiert und die Vorschau zu dieser navigiert

Hilfsunktionen für Werkzeug-Entwickler (IDE-Tool-Utils)

Dokumentation der Hilfsfunktionen

Dieses Paket beinhaltet zusätzlich Hilfsfunktionen (auch IDE-Tool-Utils genannt) für Werkzeug-Entwickler. Diese sind aktuell in TypeScript implementiert, liegen jedoch auch als ES6-JavaScript und Standalone-Bibliothek zur direkten Verwendung vor. Keine der Hilfsfunktionen wird durch die ide-lib.js ausgeliefert!

Hinweis: Hilfunktionen ohne Build-System bereitzustellen gestaltet sich schwierig und bringt große Nachteile mit sich:

  • Als reine JavaScript-Datei - platziert auf einem Server - ist die die Offline-Fähigkeit (siehe Helpers.enableOfflineUsageIfNecessary()) von Werkzeugen nicht gewährleistet, da eine Internetverbindung zum Zugriff notwendig ist.
  • Werden Dateien oder Code-Ausschnitte von Hand kopiert, muss der Werkzeug-Entwickler sich um das Aktualisieren kümmern.

Als Kompromiss werden die Hilsfunktionen als reine JavaScript-Datei (ES5 oder ES6) bereitgestellt, sodass diese auch ohne TypeScript nutzbar sind.

Die IDE-Tool-Utils können wie folgt genutzt werden

Build-System mit TypeScript (empfohlen)

Das Paket @mathcaoch/ide-api muss als npm-Abhängikeit in der package.json des Werkzeugs angegeben werden. Fortan können die in TypeScript implementierten Hilfsfunktionen - aber auch die Schnittstellen der IDE-API - komfortabel verwendet werden. Eine bestmögliche Typsicherheit ist gegeben.

import { Helpers, MathCoach } from "@mathcoach/ide-api";
Helpers.enableOfflineUsageIfNecessary()
...
const file:MathCoach.File = await MC.ide.getContextFile()

Build-System ES6+ JavaScript

Das Paket @mathcaoch/ide-api muss als npm-Abhängikeit in der package.json des Werkzeugs angegeben werden. Fortan können die in ES6 JavaScript vorliegenden Hilfsfunktionen verwendet werden. Die Entwicklungsumgebung sollte grundlegende Hilfen (Autovervollständigung und eingebettete Dokumentation) anbieten.

import { Helpers } from "@mathcoach/ide-api/dist/es6"
Helpers.enableOfflineUsageIfNecessary();
...
const file = await MC.ide.getContextFile();

Standalone

Die Hilfsfunktionen liegen als eigenständige Bibliothek vor ( siehe ./dist/lib/mathcoach-ide-tool-utils.js). Diese muss händisch kopiert, in das Werkzeug eingebunden und mit ihm ausgeliefert werden. Über die globale Variable MC_IDE_TOOL_UTILS können die Hilfsfunktionen angesprochen werden. Die verwendete Entwicklungsumgebung kann in der Regel nur wenig Unterstütztung anbieten (siehe auch Typdefinition auch ohne Build-System nutzen).

// tool.html
<script src="/mathcoach/ui/ide/ide-lib.js"/> 
<script src="mathcoach-ide-tool-utils.js"/> 
<script src="tool.js"/> 

// tool.js
const { Helpers } = MC_IDE_TOOL_UTILS;
Helpers.enableOfflineUsageIfNecessary();
...
const file = await MC.ide.getContextFile();

Beispiele

Im Verzeichnis ./examples/ finden sich Beispiele für externe Werkzeuge.

Entwicklung kleinerer Werkzeuge

Für kleiner Werkzeuge bietet es sich an im www-Verzeichnis zu entwickeln (z.B. myTool/tool.html und myTool/tool.js). Die MathCoach-IDE stellt Autovervollständigung beim Editieren der tool.js-Datei zur Verfügung. Da es sich um eine JavaScript-Datei handelt, ist keine Typsicherheit gegeben. Das Werkzeug muss lokal in die IDE integriert werden, siehe weiter unten.

Demo

Über einen Deklarations-Eintrag in der Datei ide-settings.json kann ein Werkzeug (lokal) in die IDE integriert werden. Der Benutzer kann über das Kontext-Menü Dateien, die mit dem Werkzeug geöffnet werden können, anlegen. Wird im WWW-Teil des Dateisystems entwickelt, bietet die IDE grundlegende Unterstütztung beim Editieren von JavaScript-Dateien

Entwicklung größerer Werkzeuge

Für größere Werkzeuge sollten etablierte Entwicklungswerkzeuge verwendet werden, beispielsweise:

  • npm um externe Bibliotheken (u.A. dieses Paket) einzubinden
  • webpack oder Parcel als Build-System um den Quellcode des Werkzeuges zu "bündeln"
  • TypeScript zum typsischeren Programmieren (und/oder Dateien zu ES6 oder ES5 konformen JavaScript umzuformen)
  • Git zur Versionierung des Quellcodes
  • Visual Studio Code als Entwicklungsumgebung
  • Unit und End-To-End Tests

Das "gebündelte" Werkzeug muss nach dem Build-Prozess in das WWW-Verzeichnis kopiert und ebenfalls lokal in die IDE integriert werden, siehe weiter unten.

MathCoach-API als npm-Package einbinden

Die MathCoach-API kann auch als npm-Package eingebunden werden, sodass eine typsichere und komfortable Entwicklung (z.B. mit Visual Studio Code) möglich ist. Außerdem wird es möglich die angebotenen Hilfsfunktionen zu einzubinden. Hierzu muss die package.json des Werkzeug-Projektes wie folgt ergänzt werden:

{
    ...
    "devDependencies": {
        "@mathcoach/ide-api": "git+https://bayes.htwsaar.de/gitblit/r/mathcoach/mathcoach-ide-api.git"
    },
    ...
}

Der Git-Repo URL kann man eine Versionsnummer anhängen (z.B. ".../mathcoach/mathcoach-ide-api.git#3.0.0" für Version 3.0.0), sodass die API, falls notwendig, versioniert (Semantic Versioning) werden kann. Verfügbare Versionen sind Git-Tags und können in der Weboberfläche des Git-Repositories oder über die Konsole (git tag --list) eingesehen werden.

Nun können Hilfsfunktionen (in TypeScript) wie folgt eingebunden werden.

import { Helpers } from "@mathcoach/ide-api";

Die Typedefinition sollte automatisch verfügbar sein, sodass der Umgang mit der IDE API (Einstiegspunkt ist die globale Variable MC) durch eine Entwicklungsumgebung wie Visual Studio Code unterstützt wird. Falls nicht, muss man die Typdefinition händisch einbinden (siehe Typdefinition auch ohne Build-System nutzen).

Typdefinition auch ohne Build-System nutzen

Beim Arbeiten mit Visual Studio Code kann man auch ohne Einsatz weiterer Entwicklungswerkzeuge und Build-Systeme von der Typdefinition der IDE API profitieren. Hierzu muss ein spezielles Kommentar (Triple-Slash Directive) an den Anfang der JavaScript-Datei platziert werden (path falls nötig anpassen):

/// <reference path="../node_modules/@mathcoach/ide-api/dist/es6/MathCoach.d.ts"/>

Dies sorgt dafür, dass Visual Studio Code Autovervollständigung samt Dokumentation der IDE API anbieten kann. Sollte es bei Verwendung von TypeScript notwendig sein, kann man eine Datei wie global.d.ts anlegen und die Triple-Slash Directive dort einmalig hinterlegen.

Zertifikat-Problem beheben

Falls es Probleme mit dem HTW Zertifikat gibt, muss das Zertifikat von Newton ggf. von Hand hinzugefügt werden. Nur so kann npm auf das Git-Repository zugreifen und den Inhalt automatisch herunterladen.

cd /usr/local/share/ca-certificates/
sudo mkdir newton.htwsaar.de

sudo cp path/to/newton.htwsaar.de.crt /usr/local/share/ca-certificates/newton.htwsaar.de/

sudo chown 755 /usr/local/share/ca-certificates/newton.htwsaar.de
sudo chown 644 /usr/local/share/ca-certificates/newton.htwsaar.de/newton.htwsaar.de.crt
sudo update-ca-certificates

Werkzeuge in die IDE integrieren

Damit die IDE das Werkzeug integrieren kann, muss eine Werkzeug-Deklaration registriert werden. Zur Entwicklungszeit kann der Werkzeug-Entwickler dies lokal vornehmen. Anschließend können verknüpfte Dateien mit dem Werkzeug geöffnet und erstellt werden (siehe Kontext-Menüs im IDE-Explorer). Eine Freischaltung des Werkzeugs für alle Autoren erfolgt durch einen Administrator.

Lokal (Nur für den Entwickler des Werkzeugs)

In der IDE muss eine Werkzeug-Deklaration angelegt werden, dazu muss die Einstellungsdatei ide-settings.json editiert werden. Damit Änderungen an der Einstellungsdatei wirksam werden, muss die MathCoach IDE neu geladen (Seite neu laden) werden.

{
    ...
    "editor.external.declarations": [
        {
            "displayName": "Dummy",
            "entry": "/mathcoach/www/YOURNAME/tool.html",
            "description": "...",
            "developer": "...",
            "extension": "fib.json"
        }
        ...
    ],
    ...
}
Schlüssel Beschreibung Beispiel
"description" Eine kurze Beschreibung "Editor zum Erstellen von Fill-In-Blank Aufgaben."
"developer" Namen der Werkzeug-Entwickler "John Doe, Jane Doe"
"displayName" Der Name des Werkzeugs "Fill-In-Blank-Editor"
"documentation" Optional. Link zur Werkzeug-Dokumentation. Diese muss sich auf dem selben Server wie die IDE befinden. "/mathcoach/www/YOURNAME/fib/docs.html"
"entry" Der Einstiegspunkt für das Werkzeugs. Dieser muss sich auf dem selben Server wie die IDE befinden. "/mathcoach/www/YOURNAME/fib/tool.html"
"extension" Dateien anhand der Datei-Erweiterung mit dem Werkzeug verknüpfen. Hier sollte etwas Eindeutiges gewählt werden. "fib.json" für Dateien wie someExercise.fib.json

Global (Für alle Autoren)

  • Das Werkzeug samt Werkzeug-Deklaration muss an einen Administrator übergeben werden
  • Der Administrator schaltet das Werkzeug nach einer kurzen Prüfung (Keine Konflikte mit anderen Dateierweiterung, usw) frei. Beim nächsten Release von MathCoach ist das Werkzeug dann für alle Autoren verfügbar.

Infos zu diesem Repository

.
├── CHANGELOG.md                // Dokumentation von Änderungen der API
├── examples                    // Beispiele
│   ├── ...
│   └── ...
├── media                       // Grafiken
│   └── ...
├── test                        // Unit Tests
│   └── ...
├── src                         // Hilfsfunktionen für Werkzeugentwickler
│   ├── index.ts                // Einstiegspunkt
│   └── ...
├── mathcoach-api.d.ts          // Typ-Definition der API
├── package.json
├── package-lock.json
├── README.md
└── tsconfig.json

Dokumentation erzeugen

npm install && npm run build

Release einer neuen Version

  • Version der API in der package.json eintragen
  • Version in der Überschrift der README.md eintragen
  • Beispiele und Changelog aktualisieren
  • IDE-Projekt prüfen: package.json, ide-lib.js, ...
  • Final: Release Tag setzen git tag -a VERSION -m '...' und pushen

Index