Willkommen zur Alignmentpuzzle Dokumentation

Entwicklung des Projekts

Das Projekt Alignmentpuzzle startete am 03.05.2017 und endete am 31.08.2017.

1. Woche (03.05. - 09.05.17):

Einführung in das Teamprojekt beim 1.Treffen am 03.05.: Präsentation der Betreuer:

  • Vorstellen der Idee und den grundlegenden Zielen des Projekts „Alignmentpuzzle“:
    • Erstellen einer Webseite mit einem Spiel (dem Alignmentpuzzle), wobei Themenbereiche der Bioinformatik repräsentiert und spielerich aufgegriffen werden und eine zusätzliche Dokumentation des gesamten Projekts
    • Werbung am Studieninformationstag, um Interesse am Bioinformatikstudium zu wecken oder zu vertiefen
    • Eine mögliche Darstellung eines Alignmentpuzzles ist „Phylo“, ein bereits existierendes Spiel, das als grundlegendes Vorbild betrachtet werden soll
  • Technologien:
    • JavaScript, HTML, CSS
    • Git: Versionsverwaltungstool
    • Pivotaltracker: Aufgabenverwalter
    • Slack: Kommunikationsmittel für die Gruppe
  • Einteilung in Gruppen (jeweils zwei pro Team):
    • Team Webseite: Die Aufgabe von Mario und Pepi ist, eine Webseite zu gestalten in die eine Seite mit dem Alignmentpuzzle eingebunden ist
    • Team Puzzle: Harald und Lea haben die Aufgabe, das Spielfeld, inklusive aller nötigen Bedienelemente zu gestalten
    • Team Score: Die Berechnung des besten und aktuellen Scores für eine Spielsituation ist die Aufgabe von Leonie und Julian

Ziel bis zum nächsten Treffen ist für alle, sich erste Gedanken über den Umfang seiner Aufgaben zu machen und einen groben Plan zu erstellen, was zu zun ist.

2. Woche (10.05. - 16.05.17):

Besprechung beim 2.Treffen am 10.05.

Einführung eines Teamleiters:
  • Pro Woche wird ein Gruppenmitglied zum Teamleiter ernannt
  • Aufgaben:
    • Koordination der Gruppe
    • Sorgt für eine funktionierende Kommunikation und dem Fortschreiten des Projekts, indem er oder sie Aufgaben und Ziele setzt
    • Fasst Erkenntnisse, Zielsetzungen für spätere Sitzungen und anderes am Ende des Meetings zusammen
  • Teamleiter diese Woche ist Mario

Alle drei Gruppen stellen ihre bisherigen Gedanken und Ideen bezüglich ihres Aufgabenbereichs vor.

3. Woche (17.05. - 23.05.17):

Besprechung beim 3. Treffen am 17.05. - Teamleiter diese Woche ist Harald.

Einführung in das Funktionsverwaltungssystems Git anhand des Programms Git Bash von Julian

Neue Zielsetzung:
  • Prototyp der Webseite mit funktionierendem Spiel für zwei Sequenzen bis zum 31.05. fertig stellen

4. Woche (24.05. - 30.05.17):

4. Treffen (eigentlich für den 24.05. vorgesehen) wird aufgrund einer Klausur auf den 29.05. (ohne Betreuer) verschoben. Die drei Teilbereiche Webseite, Puzzle und Score werden zu einem ersten Prototyp zusammengefügt. Das Spiel wird auf der Webseite angezeigt und zeigt außerdem korrekt den besten Score für zwei als auch den aktuellen Score für beliebig viele Sequenzen an.

5. und 6. Woche (31.05. - 13.06.17):

Besprechung beim 5. Treffen am 31.05. - Teamleiterin diese Woche ist Leonie.

Feedback von den Betreuern:
  • Webseite ist optisch nicht ansprechend (weißer Hintergrund, langweiliger Aufbau, …)
  • Vereinzelte Fehler (z.B. verdeckt der Menübalken beim Ausklappen einen Teil des Buttons)
  • Weisen nochmals darauf hin, dass die Webseite Studieninteressierte (also vor allem die jüngeren Generationen addressieren soll)
Neue Ideen/Ziele:
  • Bezüglich der Dokumentation: Eine große Zeitleiste mit Bildern (Screenshots von der Seite) soll den Fortschritt und die Unterschiede zu früheren Prototypen zeigen.
  • Modernere Aufmachung der Webseite, sowohl bezüglich Design als auch Aufbau

Da in der kommenden Woche (05. - 11.) Pfingstferien sind, finden währenddessen keine Treffen statt. Außerdem soll über diese Zeit jeder neue Ideen und Impulse für die Webseite sammeln.

7. Woche (14.06. - 20.06.17):

Besprechung beim 6. Treffen am 14.06. - Teamleiter diese Woche ist Julian.

Zusammentragen der Leistungen über die Ferien. Vorstellen von Ideen oder Anregungen zur Verbesserung des Spielerlebnisses und der optischen Aufmachung der Webseite.

8. Woche (21.06. - 27.06.17):

Besprechung beim 7. Treffen am 21.06. - Teamleiterin diese Woche ist Lea.

Neue Ziele:
  • Alle bisherigen Fortschritte, der Entwicklungsprozess, sowie der aktuelle Stand und Zukunftsaussichten sollen in einer Präsentation am 05.07. vor Professor Nieselt vorgetragen werden.
  • Ein Probevortrag vor den Betreuern ist angesetzt für den 04.07.

Die Puzzleversion ist zwischenzeitlich überarbeitet worden und wird in die Webseite eingebunden.

9.Woche (28.06.-04.07.17):

Besprechung beim 8. Treffen am 28.06. - Teamleiterin diese Woche ist Pepi.

Umfrage:
  • Jedes Teammitglied soll eine kleine Umfrage machen, um die Wirkung der Webseite und des Puzzles zu testen.
  • Resultat: Das Spiel ist unverständlich für die große Mehrheit der Befragten.
  • Idee eines Tutorials oder Hilfe-Fensters
Präsentationsvorbereitungen:
  • Erste Ideen für den Vortrag werden gesammelt und ein grober Rahmen entworfen.
  • Für die Präsentation werden im Verlauf der Woche Vortragsfolien erstellt.
Probevortrag:
  • Der Vortrag wird vor einem der beiden Betreuer gehalten, der im Nachhinein Feedback gibt.

Die Präsentation wird dem Feedback entsprechend überarbeitet und angepasst.

Aber der 10. Woche (05.07.-31.08.17):

Vortrag am 05.07. vor Professor Kay Nieselt, Privatdozentin für Bioinformatik der Universität Tübingen

Die Abgabefrist des Projekts wird um einen Monat verlängert (31.08. anstatt 31.07.). Außerdem werden die Voraussetzungen festgehalten, die bis zum Ende des Projekts erfüllt sein müssen.

To-Dos:
  • Dokumentation des Projekts
  • Texte für die Webseite
  • Tutorials und andere Einstellungen für das Puzzle

Alignmentpuzzle

Entwicklung des Spiels

1. Woche (03.05. - 09.05.17):

  1. Treffen am 03.05.17:
    Lea und Harald bilden das Team Puzzle
Vorlagespiel „Phylo“:
  • Nähere Analyse von „Phylo“, um erste Ideen für das eigene Spiel zu sammeln.
  • Fragestellungen: Welche Aspekte des Spiels sind gut, welche sollten überarbeitet oder verbessert werden?
    • Negativ kritisiert: Kein ansprechendes Design, fehlende Erklärungen zur Funktionsweise des Spiels, unverständliche Scoring-Parameter, kein Bezug zur Bioinformatik.
    • Positiv aufgefallen: Das Spiel ist einwandfrei spielbar, wenn dem Spieler die Funktion und das Ziel des Spiels klar sind.
Ideen für eigenes Puzzle:
  • Die Positionen der verschiedenen Scoringwerte sollten klar festgelegt und mit Namen gekennzeichnet werden, sodass der Spieler den aktuellen Score, den bislang besten Score und den bestmöglichen Score klar erkennen und auseinanderhalten kann.
  • Das Spiel soll zunächst nur den Vergleich von DNA-Sequenzen betrachten, wobei die einzelnen Basen durch Farbe, unterschiedliche Symbole und das DNA-Basen Alphabet (C, G, A, T) klar voneinander unterscheidbar sein sollen.
  • Es soll erkennbar sein aus welchem Organismus oder Gen die zu bearbeitenden Sequenzen stammen.
  • Scoring-Parameter sollen zum besseren Verständnis angezeigt und beschrieben werden.

2. Woche (10.05. - 16.05.17):

Besprechung am 2.Treffen (10.05.17):
  • Auflisten der Pros und Kontras bezüglich des Spiels „Phylo“
  • Vorstellen der Ideen für das eigene Puzzle
  • Besprechen dieser Ideen im gesamten Team und Sortieren nach Umsetzbarkeit und Wichtigkeit
Erste Implementationen / Ziele:
  • Erstellen von Elementen, die die DNA-Basen der alignierten Sequenzen repräsentieren, für das Spiel
  • Die DNA-Basen werden in Form von einfachen, farbigen Rechtecken dargestellt. Sie liegen in einem aus Linien aufgebauten Raster.
  • Erlernen von Event-Listenern in JavaScript und deren Anwendung. Dazu gehören Befehle wie onmousedown, onmousemouve und onmouseup, die benötigt werden, um ein Element mithilfe der Maus zu packen, zu bewegen und wieder loszulassen.

3. Woche (17.05. - 23.05.17):

Neue Zielsetzungen:
  • Ein Prototyp der Webseite muss mit einer funktionierenden Spielversion für zwei Sequenzen bis zum 31.05.17 vorzeigbar sein.
  • Lösung des Nachbar- und Randproblems finden.
    • Problem: Die Basen lassen sich übereinander verschieben und können aus dem Spielfeld bewegt werden.
Implementationen:
  • Es wird ein Mindestabstand zwischen den Basen festgelegt, der auch während des Bewegungsvorganges eingehalten werden soll, sodass das Übereinanderschieben nicht mehr möglich ist.
  • Sobald eines der äußersten Kästchen das Rasterende erreicht hat wird die Bewegung in diese Richtung abgebrochen, sodass alle Basen im Spielfeld verbleiben. Funktioniert jedoch noch nicht optimal.

4. Woche (24.05. - 30.05.17):

Das Treffen am 24.05.17 wird aufgrund einer Klausur verschoben

Neue Zielsetzungen:
  • Felder erstellen, in denen die Basen mit bestimmten Abstand zueinander einrasten können.
Implementationen:
  • Koordinaten der erstellten Felder werden den Basen übergeben, sodass diese nach dem Bewegungsvorgang in entsprechendes Feld einrasten und platziert werden können.
  • Verbesserung der Lösung des Randproblems: Der Bewegungsvorgang wird abgebrochen, wenn die Koordinaten des letzten Kästchens größer als die des letzten Feldes werden.

5. und 6. Woche (31.05. - 13.06.17):

Wichtige Meilensteine:
  • Die drei Teilbereiche Webseite, Puzzle und Score-Berechnung wurden zum Prototyp zusammengefügt und erstmals zusammen auf der Webseite angezeigt.
  • Der Prototyp lässt sich mit zwei festgelegten Sequenzen spielen.
Neue Ideen:
  • Das Spielfeld soll nicht mehr statisch, sondern dynamisch programmiert werden, wodurch das Spiel flexibler gehalten werden kann.
Neue Zielsetzungen:
  • Das Spiel soll auf mehrere Sequenzen erweitert und das Design stark optimiert werden.
  • Veränderungen der Lösungen des Rand- und Nachbarproblems, sodass diese auch dynamisch funktionieren.
  • Das Spielfeld soll sich abhängig von der Bildschirmgröße des Spielers verändern und sich relativ zu der Größenveränderung des Browserfensters mitverschieben.
Implementationen:
  • Die Basen werden mittels JavaScript nun dynamisch erzeugt. Dafür werden mehrere Strings als Eingabe verwendet, aus denen entprechend mehrere übereinanderligende Sequenzen aus Basen und zufällig eingefügten Gaps erstellt werden.
  • Veränderung der Basenform zu einer Murmel und Anbringen eines farbigen Hintergrunds auf dem ein rechteckiges Spielfeld liegt, das die Sequenzen optisch vom Hintergrund abgrenzen soll. Horizontale Linien aus Punkten stellen die Felder dar auf denen die Sequenzen angezeigt werden. Jeder Punkt kann mit einer Base besetzt werden, wobei das Freibleiben eines Punktes ein Gap symbolisiert.

7. Woche (14.06. - 20.06.17):

Implementationen:
  • Die Gruppe einigt sich auf ein einheitliches Hintergrundbild, das auf allen Seiten der Webseite als verbindendes Element angezeigt werden soll.
  • Die Form der Basen wird zu Rechtecken mit abgerundeten Ecken verändert.
  • Über dem Spielfeld werden nun die Felder „Aktueller Score“ und „Bester Score“ angezeigt, in die die berechneten Scores mit eingebunden sind.
  • Es wird ein Optionsfenster erstellt, das nach Erreichen des besten Scores angezeigt werden soll. In diesem kann entschieden werden, ob der/die Spielende ein nächstes Level spielt, das jetztige Spiel noch weiterspielen will, um mögliche andere Alignments zu finden, oder ob das Spiel verlassen möchte.

8. Woche (21.06. - 27.06.17)

Wichtige Meilensteine:
  • Das neue Spiel wird wieder in die Webseite mit eingebunden.
Neue Zielsetzungen:
  • Ein Zwischenvortrag vor Frau Prof. K. Nieselt soll für den 05.07.17 vorbereitet werden.
Implementationen:
  • Zur lebendigeren Gesataltung des Spiels werden die Score-Felder in Bewegung gebracht, sodass sie sich auf und ab bewegen. Die Basen vibrieren zudem leicht.

9. Woche (28.06. - 04.07.17)

Neue Ideen:
  • Es soll ein kleines Fenster erstellt werden, in dem neben dem Spielfeld angezeigt wird, welche Werte eine gleiche Basenpaarung, eine ungleiche Basenpaarung und eine Paarung mit einer Lücke tragen.
Zwischenpräsentation:
  • Die Themen der Zwischenpräsentation werden besprochen und eine Powerpoint-Präsentation vorbereitet.
  • Am 04.07.17 ergibt sich die Möglichkeit den Zwischenvortrag zur Probe vor einem der Betreuer zu präsentieren.

10. Woche (05.07. - 11.07.17)

Neue Ideen:
  • Es soll ein Tutorial entworfen werden, das die Spielidee und den Aufbau des Spiels genauer darstellt, da das Hilfefenster zur Erklärung der Funktionsweise des Spiels nicht ausreicht. Das Tutorial soll eine Abfolge von kurzen Videos enthalten, in denen die Funktionsweise erklärt und gezeigt wird.
Implementationen:
  • Es wird ein Feld erstellt, dass durch Anklicken die Tutorialseite aufruft.
Zwischenpräsentation:
  • Die Zwischenpräsentation wird am 05.07.17 vor Frau Prof. K. Nieselt gehalten.

11. Woche (12.07. - 18.07.17)

Neue Zielsetzungen:
  • Es soll ein Regler-Feld erstellt werden, in dem die Scoring-Parameter verändert und angepasst werden können.
Implementationen:
  • Das Fenster mit den Reglern für die Scoring-Parameter wird erstellt. Es ist nur aufrufbar, wenn ein Spieler sich nach Erreichen des besten Scores noch weiter mit dem gefundenen Alignment beschäftigen möchte.

12. Woche (19.07. - 25.07.17)

Neue Zielsetzungen:
  • Auf den Basen soll entsprechend ihrer Art ein Buchstabe angezeigt werden, der verdeutlichen soll, dass es sich um DNA-Sequenzen handelt.
Implementationen:
  • Die Buchstaben C, G, A und T werden entsprechend für Cytosin, Guanin, Adenin und Thymin auf die Basen gesetzt.
  • Es werden Videos erstellt, die als Tutorial dienen sollen. Diese werden in das Tutorial-Fenster eingefügt und laufen dort bis zur Schließung des Fensters in Dauerschleife.

Ab der 13. Woche (26.07. - 31.08.17)

Implementationen:
  • Es wird ein Zahnrad erstellt, das beim Anklicken ein Menüfenster aufruft. Darin lassen sich die Hintergrundmusik und die Bewegungsgeräusche der Basen aus- und einschalten, sowie die Anzeige des DNA-Buchstaben Codes ausblenden.
  • Der gesamte Code wird überarbeitet und refactored.
  • Neben den Sequenzen wird der Name des Gens angezeigt, aus dem sie stammen. Fährt man mit der Maus über einen Namen, so werden weitere Informationen zum Gen sowie der Ursprungsorganismus agezeigt.

Das Alignmentpuzzle

Definition: Alignmentpuzzle

Ein Alignmentpuzzle ist ein Spiel, in dem der Spieler versucht ein bestmögliches Alignment für mindestens zwei Sequenzen zu finden. Das Ziel des Spiels ist es, die gegebenen Sequenzen durch Verschieben ihrer Elemente auf eine Weise gegeneinander auszurichten, dass ihre Ähnlichkeit so groß wie möglich wird. Dabei können die Elemente nur innerhalb ihrer Sequenz verschoben werden, ohne die Reihenfolge zu vertauschen. Die Ähnlichkeit der zu alignierenden Sequenzen wird mithilfe eines Scores gemessen, der für jede Spalte die Elemente aller Sequenzen miteinander vergleicht und in Match, Mismatch und Gap klassifiziert. Für alle Spalten wird ein Score gemäß den Scoring-Werten der verschiedenen Klassifizierungen bestimmt. Die Addition aller Spaltenscores ergibt den Gesamtscore des Alignments. Innerhalb des Spiels werden dem Spieler der bestmögliche Score und der derzeitige Spielerscore angezeigt. Erreicht dieser durch perfektes Alignieren den bestmöglichen Score, so hat er das Spielziel erreicht und kann in weiteren Levels mit neuen Sequenzen spielen.

Aufbau des Spiels

Spielfeld

Das von uns entworfene Alignmentpuzzle lässt sich innerhalb eines Spielfelds steuern, das sich zentral auf der Spielseite befindet. Es beinhaltet DNA-Sequenzen aus Basen, die als Kästchen auf horizontalen, gepunkteten Linien angeordnet sind. Dabei steht das blaue Kästchen für die Base Cytosin, das gelbe Kästchen für die Base Guanin, das rote Kästchen für die Base Adenin und das grüne Kästchen für die Base Thymin.

Die Basen der Sequenzen sind jeweils immer auf einem Punkt angeordnet und können nur einrasten, wenn sie beim Verschieben über einem Punkt losgelassen werden. Sind in den Sequenzen Gaps vorhanden, so kann dies an freien Punkten, auf denen keine Base liegt erkannt werden. Die Basen lassen sich horizontal innerhalb des Spielfelds verschieben. Schiebt der Spieler ein Element auf ein anderes, so wird dieses in dieselbe Richtung mitverschoben, sofern es noch genügend freie Punkte in dieser Richtung gibt. Sind schon alle Punkte belegt, so können die Basen nicht weiterverschoben werden, da sonst die Länge des Alignments verändert werden würde und die Base aus dem Spielfeld verschwinden würde.

Über dem Spielfeld werden dem Spieler in den Feldern „Aktueller Score“ und „Bester Score“ der momentaner Score und der bestmögliche Score des Alignments angezeigt. Der aktuelle Score wird bei jeder Aktion, die der Spielende durchführt - also wenn mindestens ein Kästchen verschoben wird -, neu berechnet und angezeigt.

Zusätzliche Elemente

Links vom Spielfeld werden auf einem Feld die Scoring-Parameter angezeigt, sodass der Spieler weiß, welche Werte für den Match Score, den Mismatch Score und der Gap Penalty bei der Score Berechnung verwendet werden. Wird das darüberliegende Hilfefenster aufgeklappt, so erhält der Spieler Informationen zur Score Berechnung, die zum Verständnis des Spiels beitragen sollen. Es wird angezeigt, wie ein Match, ein Mismatch und ein Gap aussehen und welche Scoring Parameter sie tragen. Zudem gibt es zwei Beispiele von Alignments mit drei Sequenzen der Länge von einer Base, in denen allgemein gezeigt wird, wie sich der Score berechnet.

Darunter kann ein Tutorialfenster augeklappt werden, das sich über die ganze Seite ausbreitet. Darin wird in kurzen Videos gezeigt, wie Sequnzen miteinander aligniert werden können, dass Gaps sinvoll sein können und nicht nur identische Basen miteinander aligniert werden müssen.

Klickt der Spieler auf das Zahnrad rechts oberhalb des Spielfelds, so öffnet sich ein Menüfenster. In diesem können die Hintergrundmusik des Spiels sowie die Klickgeräusche der Basenbewegung aus- und eingeschaltet werden. Zudem kann einstellt werden, ob die zugehörigen Basen-Symbole A, C, G und T auf den Kästchen angezeigt werden oder nicht. Außerdem ist es hier möglich das gerade laufende Spiel zu verlassen und ein neues Spiel zu beginnen.

Oberhalb des Alignmentpuzzles hat der Spieler die Möglichkeit auch die anderen Seiten der Webseite zu besuchen. So kann er zur Startseite wechseln, sich Themen der Bioinformatik durchlesen oder etwas über das Team erfahren.

Ablauf des Spiels

Wählt ein Spieler auf der Startseite der Webseite das Alignmentpuzzle aus, so wird er auf die Spielseite weitergeleitet und kann sich zwischen sechs Schwierigkeitsstufen des Spiels entscheiden. So sind die Level aufgeteilt in „sehr leicht“, „leicht“, „mittel“, „schwer“, „sehr schwer“ und „legendär“. Im Level „sehr leicht“ müssen zwei Sequenzen miteinander aligniert werden. Pro Level kommt eine weitere Sequenz hinzu, sodass im letzten Level („legendär“) sieben Sequenzen miteinander alignieren werden müssen. Entscheidet sich der Spieler für das einfachste Level, so wird zunächst das Tutorialfenster geöffnet, welches ihm zeigen soll, wie das Spiel funktioniert. Danach kann er sich selbst am Spiel versuchen. Bei allen anderen Leveln kann der Spieler gleich anfangen die Sequenzen zu alignieren und sich die Tutorials nur bei Bedarf anschauen.

Während des Spiels, wird nach jeder Bewegung einer Base neben dem neuen aktuellen Score angezeigt, um welchen Wert dieser von dem vorherigen abweicht. Ist der optimale Score erreicht, so öffnet sich ein Fenster, indem der Spieler zum Erreichen des optimalen Alignments gelobt wird. Darunter wird ihm die Zeit angezeigt, die er zum Lösen benögt hat. In diesem Fenster kann er nun entschieden, ob er das Spiel weiterspielen möchte, wobei er herumprobieren kann, wie sich das Verändern der Scoring-Parameter auf das optimale Alignment auswirkt. Oder er kann das aktuelle Spiel verlassen, sich ein Level aussuchen und ein neues Spiel starten. Spielt der Spieler weiter, so erscheint das Reglerfeld, in dem er die Scoring-Parameter verändern kann und ein „nächstes Level“-Feld, das ihm ermöglicht, das Spiel zu beenden und ein neues zu beginnen.

Implementation in JavaScript

Konstanten

int MAX_ELEMENTS_PER_ROW Die maximale Anzahl an Basen pro Reihe.

int MAX_AMOUNT_OF_ROWS Die maximale Anzahl an Reihen.

String A_BASE_COLOR Die Farbe der Base A (Adenin).

String T_BASE_COLOR Die Farbe der Base T (Thymin).

String G_BASE_COLOR Die Farbe der Base G (Guanin).

String C_BASE_COLOR Die Farbe der Base C (Cytosin).

String A_BASE_BORDER_COLOR Die Randfarbe der Base A (Adenin).

String T_BASE_BORDER_COLOR Die Randfarbe der Base T (Thymin).

String G_BASE_BORDER_COLOR Die Randfarbe der Base G (Guanin).

String C_BASE_BORDER_COLOR Die Randfarbe der Base C (Cytosin).

Variablen

float baseWidth Die Basenbreite.

float baseHeight Die Basenhöhe.

float distanceToNextBase Der Mindestabstand zweier Basen zueinander.

float gameLeftEdge Der linke Rand des Spielbereichs im Spielfeld.

float gameRightEdge Der rechte Rand des Spielbereichs im Spielfeld.

float gameTopEdge Der obere Rand des Spielbereichs im Spielfeld.

float gameBottomEdge Der untere Rand des Spielbereichs im Spielfeld.

float distanceToNextRow Der Abstand einer Reihe/Sequenz zur darunter und darüber liegenden.

Array lockFields Beinhaltet die Koordinaten für die Einrastfelder.

Array alignment Beinhaltet Sequenzen, die zusammen das Alignment ergeben.

element currentBase Eine Referenz auf die aktuell anvisierte Base.

String pointerType Der Zeigertyp.

float pointerCords Die X-Koordinate des Zeigers.

float pointerCordsToBaseDistance Die Differenz der X-Koordinate des Zeigers zur X-Koordinate der anivsierten Base.

int currentScoreDifferenceMovement Die Differenz zwischen dem aktuellen Punktestand und dem vorherigen.

String menuGate Gibt den Anzeigestatus des Menüfensters an.

element currentSlider Eine Referenz auf den aktuell anvisierten Regler.

float difference Die Differenz der Y-Koordinate des Zeigers zur Y-Koordinate des anivsierten Reglers.

Boolean sliderSoundAudio Ein Status, der das Reglerklickgeräusch steuert.

Array sliderLockInFields Beinhaltet die Stellen, auf denen die Regler einrasten können.

Methoden

1. Spielfeld Erzeugung (Klasse: setter_gameField):
setGameField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Erstellt das Spielfeld mit allen nötigen Komponenten.
    • Zu den Komponenten zählen:
      1. Spielfeldfläche
      2. Einrastfelder
      3. Reihen mit Sequenzen
      4. Die dazugehörigen Basen
setGameArea()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Spielfeldfläche auf die Webseite.
setBordersForBases()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Spielbereich innerhalb der Spielfeldfläche.
setLockFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Felder, in denen die Basen einrasten können.
setBaseDimensions()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Größe einer Base.
setSequenceRows()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt Markierungen in den Spielbereich, welche die Einrastfelder repräsentieren. Setzt Sequenzen bestehend aus Basen horizontal auf eine Reihe von Markierungen.
setMarksOnLine(float distanceToTop,String idName)
  • Eingabe: float, String
  • Ausgabe: keine Ausgabe
  • Funktion: Legt Markierungen auf einer horizontalen Linie, die einen Abstand von „distanceToTop“ zur oberen Kante des Spielfelds hat und weist jeder Markierung in Abhängigkeit von „idName“ eine ID zu. Diese Markierungen repräsentieren die Stellen der Einrastfelder.
setMarkAttributes(element mark,float distanceToTop,String idName)
  • Eingabe: element, float, String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Element „mark“ die Eigenschaften einer Markierung zu.
    • Eigenschaften sind:
      1. Stelle „position“ auf der Horizontalen
      2. Abstand zur oberen Spielfeldkante „distanceToTop“
      3. Größe
      4. Farbe
      5. ID „idName“
setBasesInRow(Array sequence,float distanceToTop,String idName)
  • Eingabe: Array, float, String
  • Ausgabe: keine Ausgabe
  • Funktion: Iteriert durch die Sequenz „sequence“ und platziert die darin enthaltenen Basen in der angegebenen Reihenfolge auf Markierungen, welche ebenfalls einen Abstand „distanceToTop“ zur oberen Spielfeldkante haben. Zusätzlich wird jeder Base eine ID „idName“ zugewiesen.
setBase(float distanceToTop,int position, String idName,String className)
  • Eingabe: float, int, String, String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine Base auf eine Markierung, welche den gegebenen Abstand „distanceToTop“ zur oberen Spielfeldkante hat und auf einer gegeben Stelle „position“ auf der Horizontalen liegt. Die Base bekommt eine ID „idName“ und eine Klasse „className“ zugewiesen.
setBaseAttributes(element base,String className,float distanceToTop,int position)
  • Eingabe: element, String, float, int
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Element „base“ die Eigenschaften einer Base zu.
    • Eigenschaften hier sind:
      1. Breite und Höhe
      2. Abstand „distanceToTop“ zur oberen Spielfeldkante
      3. Stelle „position“ auf der Horizontalen
setBaseEvents(element base)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Element „base“ die Funktionen einer Base zu. Diese verwalten das Greifen, Ziehen und Loslassen einer Base.
2. Interaktion mit Benutzer:
Getter für Baseninteraktion (Klasse: getter_game):
getNumberOfBasesInCurrentRow()
  • Eingabe: keine Eingabe
  • Ausgabe: int
  • Funktion: Gibt die Anzahl an Basen aus, die in der Reihe der anvisierten Base vorliegen.
getBaseNumFromLeft()
  • Eingabe: keine Eingabe
  • Ausgabe: int
  • Funktion: Gibt die Anzahl der Basen bis zur anvisierten Base von links zählend aus.
getBaseNumFromRight()
  • Eingabe: keine Eingabe
  • Ausgabe: int
  • Funktion: Gibt die Anzahl der Basen bis zur anvisierten Base von rechts zählend aus.
getBaseXcord(String baseId)
  • Eingabe: String
  • Ausgabe: float
  • Funktion: Greift über die ID „baseId“ auf die dazugehörige Base zu und gibt deren X-Koordinate aus.
getBaseClass(String baseId)
  • Eingabe: String
  • Ausgabe: String
  • Funktion: Greift über die ID „baseId“ auf die dazugehörige Base zu und gibt deren Klasse aus.
Setter für Baseninteraktion (Klasse: setter_game):
setCurrentBase(element base)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist das Element „base“ der globalen Variable „currentBase“ zu.
setPointerType(event e)
  • Eingabe: event
  • Ausgabe: keine Ausgabe
  • Funktion: Anhand von „event“ wird der vorliegende Event-Typ der globalen Variable „pointerType“ zugewiesen
setPointerCords(event e)
  • Eingabe: event
  • Ausgabe: keine Ausgabe
  • Funktion: Anhand von „event“ wird die X-Koordinate des vorliegenden Events der globalen Variable „pointerCords“ zugewiesen.
setPointerCordsToBaseDistance()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Differenz der X-Koordinate des Events „pointerCords“ zur X-Koordinate der anvisierten Base „currentBase“ in die globale Variable „pointerCordsToBaseDistance“.
setNewAlignment()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt nach Ausführung einer Basenbewegung das Alignment in der globalen Variable „alignment“ entsprechend neu.
Basen Interaktion (Klasse: interaction_game):
startDrag(event e,element obj)
  • Eingabe: event, element
  • Ausgabe: keine Ausgabe
  • Funktion: Verwaltet den Start der Interaktion zwischen Benutzer und Base.
doBaseDrag(event e)
  • Eingabe: event
  • Ausgabe: keine Ausgabe
  • Funktion: Verwaltet die Ausführung der Interaktion zwischen Benutzer und Base. Dazu gehört das Aktualisieren der Event-Koordinaten in jedem Bewegungsschritt und das Neusetzen der Base(n).
stopBaseDrag()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Verwaltet das Ende der Interaktion zwischen Benutzer und Base. Dazu gehört die Aufnahme des neuen Spielstands und die Berechnung des aktuellen Scores.
moveBase()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Führt die Basenbewegung aus.
isBaseOutOfItsRange()
  • Eingabe: keine Eingabe
  • Ausgabe: boolean
  • Funktion: Gibt aus, ob die aktuell anvisierte Base noch in ihrem Bewegungsbereich ist.
currentBaseArea()
  • Eingabe: keine Eingabe
  • Ausgabe: String
  • Funktion: Gibt aus, in welchem Bereich sich die aktuell anvisierte Base befindet.
    • Bereiche sind:
      1. das am weitesten links liegende Feld
      2. das am weitesten rechts liegende Feld
      3. die Felder zwischen den beiden äußersten Feldern
isPointerHigher()
  • Eingabe: keine Eingabe
  • Ausgabe: boolean
  • Funktion: Gibt aus, ob der nächste Bewegungsschritt über die rechte Grenze des Bewegungsbereichs der anvisierten Base führt.
isPointerLower()
  • Eingabe: keine Eingabe
  • Ausgabe: boolean
  • Funktion: Gibt aus, ob der nächste Bewegungsschritt über die linke Grenze des Bewegungsbereichs der anvisierten Base führt.
makeMoveIfPossible(String area)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Anhand des aktuell vorliegenden Bereichs „area“, in der sich die anvisierte Base befindet, wird darüber entschieden, ob eine Basenbewegung möglich ist. Falls ja, wird diese durchgeführt.
keepDistanceToNextBases()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Es wird bei jedem Bewegungsschritt geprüft, ob ein festgelegter Distanzwert „distanceToNextBase“ von einer Base zu ihren Nachbarn vorliegt.
keepDistanceToLeftBases()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Prüft ausgehend von der aktuell anvisierten Base, ob der Mindestabstand „distanceToNextBase“ zum nächsten linken Nachbar eingehalten wird und setzt gegebenfalls den linken Nachbar passend neu, sodass der Mindestabstand wieder vorhanden ist.
keepDistanceToRightBases()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Prüft ausgehend von der aktuell anvisierten Base, ob der Mindestabstand „distanceToNextBase“ zum nächsten rechten Nachbar eingehalten wird und setzt gegebenfalls den rechten Nachbar passend neu, sodass der Mindestabstand wieder vorhanden ist.
lockInFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Sucht zu jeder Base das am nächsten liegende Einrastfeld und platziert die Base darauf.
recorretLockIn()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Prüft, ob Basen im Randbereich auf dasselbe Einrastfeld gesetzt werden und setzt daraufhin die Basen passend neu.
recorrectLockInOfRightBases(int amountOfBasesInCurrentRow,String beginId)
  • Eingabe: int, String
  • Ausgabe: keine Ausgabe
  • Funktion: Es wird von links nach rechts über die Basen in der Reihe der anvisierten Base iteriert. Besetzen mehrere Basen ein Einrastfeld, so werden diese neu gesetzt.
recorrectLockInOfLeftBases(int amountOfBasesInCurrentRow,String endId)
  • Eingabe: int, String
  • Ausgabe: keine Ausgabe
  • Funktion: Es wird von rechts nach links über die Basen in der Reihe der anvisierten Base iteriert. Besetzen mehrere Basen ein Einrastfeld, so werden diese neu gesetzt.
Setter für weitere Felder (Klasse: setter_otherFields):
setOtherFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die weiteren Felder.
    • Zu den weiteren Feldern gehören:
      1. Die Felder mit jeweiliger Punktzahl
      2. Die Informationsfelder
      3. Die Tutorialfelder
      4. Das Feld mit Genen
      5. Das Feld, welches zum nächsten Level führt
      6. Das Optionsfeld, das nach Absolvieren des Levels erscheint
setOptionField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Optionsfeld mit dazugehörigen Komponenten.
    • Zu den Komponenten gehören:
      1. Ein Feld, das die Option bietet in das nächste Level zu steigen
      2. Ein Feld, das die Option bietet im bisherigen Level zu verbleiben
      3. Das Optionsfenster, in dem die oben benannten Felder liegen.
setOptionWindowField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Optionsfenster.
setPlayNextLevelField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das nächste Level in das Optionsfenster.
setPlayAroundField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das Verbleiben in dem bisherigen Level in das Optionsfenster.
setMiniBasesForOptionField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt kleine Basen zur Dekoration in das Optionsfenster
setBaseForOptionField(left,top,id,background,borderColor)
  • Eingabe: String,String,String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Eine Base wird in das Feld an der horizontalen Stelle „left“ und an der vertikalen „top“ mit der ID „id“ gelegt und erhält die entsprechende Farbe „background“ mit Randfarbe „borderColor“
setScoreFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Felder mit jeweiliger Punktzahl.
    • Zu den Feldern gehören:
      1. Das Feld mit dem aktuellen Punktestand
      2. Das Feld mit dem bestmöglichen Punktestand
setCurrentScoreField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, das die aktuelle Punktzahl anzeigt.
setBestScoreField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, das die bestmögliche Punktzahl anzeigt.
setInfoFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Informationsfelder.
    • Zu den Informationsfeldern gehören:
      1. Das Feld mit zusammengefassten Informationen
      2. Das Feld mit ausführlichen Informationen
      3. Das Feld, das von dem Zusammengefassten zu dem Ausführlichen wechselt
      4. Das Feld, das von dem Ausführlichen zu dem Zusammengefassten wechselt
setInfoInShortField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, das die zusammengefassten Informationen beinhaltet.
setSwitcherShortToPrecisely()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, dessen Funktion von dem zusammengefassten Informationsfeld zu dem ausführlichen Informationsfeld wechselt.
setInfoPreciselyField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, das die ausführlichen Informationen beinhaltet.
setInfoPreciselyContent()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Inhalt in das Feld für die ausführlichen Informationen.
setDividingLines()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt Linien in das Feld mit ausführlichen Informationen für die Einteilung von Problemen.
setRow(distToTop)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine Linie in das Feld, welches die ausführlichen Informationen beinhaltet.
setScoreExamples()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt auftretende Vorkommnisse eines Alignments als Beispiele in das Feld mit ausführlichen Informationen.
setScoreExamples()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt auftretende Vorkommnisse eines Alignments als Beispiele in das Feld mit ausführlichen Informationen.
    • Dazu gehören:
      1. Ein Beispiel für die Gleichheit übereinander liegender Basen („match“)
      2. Ein Beispiel für die Ungleichheit übereinander liegender Basen („mismatch“)
      3. Ein Beispiel für die Alignierung einer Base mit nichts („gap“)
setMatchExample()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Beispiel für die Gleichheit übereinander liegender Basen in das Feld mit ausführlichen Informationen.
setMisMatchExample()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Beispiel für die Ungleichheit übereinander liegender Basen in das Feld mit ausführlichen Informationen.
setGapExample()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Beispiel für die Übereinanderlagerung einer Base mit nichts in das Feld mit ausführlichen Informationen.
setBiggerExamples()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt zwei größere Beispiele in das Feld mit ausführlichen Informationen.
setFirstBiggerExample()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein größeres Beispiel in das Feld mit ausführlichen Informationen.
setSecondBiggerExample()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein größeres Beispiel in das Feld mit ausführlichen Informationen.
setSmallBase(left,top,color,borderColor)
  • Eingabe: String,String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine kleine Base auf die horizontale Stelle „left“ und vertikale „top“ mit der Farbe „color“ und Randfarbe „borderColor“ in das Feld mit ausführlichen Informationen.
setBigBase(left,top,color,borderColor)
  • Eingabe: String,String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine große Base auf die horizontale Stelle „left“ und vertikale „top“ mit der Farbe „color“ und Randfarbe „borderColor“ in das Feld mit ausführlichen Informationen.
setGap(left,top)
  • Eingabe: String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine Lücke auf die horizontale Stelle „left“ und vertikale „top“ in das Feld mit ausführlichen Informationen.
setSwitcherPreciselyToShort()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, dessen Funktion von dem ausführlichen Informationsfeld zum zusammengefassten Informationsfeld wechselt.
setTutorialFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Tutorialfelder.
    • Dazu gehören:
      1. Das Tutorialfenster, das Videomaterial beinhaltet
      2. Das Feld, welches das Tutorialfenster einblendet
setTutorialWindowField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Tutorialfenster, in dem Videomaterial dargestellt wird.
setVideos()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt Videos in das Tutorialfenster.
setVideo(id,path,opacity)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Video mit der ID „id“ aus dem Verzeichnis „path“ mit einer Deckkraft „opacity“ in das Tutorialfenster.
setSignposts()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt Wegweiser in das Tutorialfenster.
    • Dazu gehören:
      1. Der Wegweiser, der zu dem nächsten Video wechselt
      2. Der Wegweiser, der zu dem vorherigen Video wechselt
      3. Der Wegweiser, der das Tutorialfenster ausblendet
setSignPostNext()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Wegweiser in das Tutorialfenster, der zum nächsten Video wechselt.
setSignPostPrev()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Wegweiser in das Tutorialfenster, der zum vorherigen Video wechselt.
setSignPostHide()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Wegweiser in das Tutorialfenster, der das Tutorialfenster ausblendet.
setTutoCallerField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, welches das Tutorialfenster einblendet.
setNextLevelField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, welches dafür zuständig ist, in das nächste Level zu wechseln.
setModeField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld, das für die Levelauswahl zuständig ist.
    • Dazu gehören:
      1. Der Levelbereich, in dem die unterschiedlichen Level angezeigt werden
      2. Ein Anzeigefeld, das die Levelauswahl kenntlich macht
      3. Das Feld für das sehr leichte Level
      4. Das Feld für das leichte Level
      5. Das Feld für das mittel schwere Level
      6. Das Feld für das schwere Level
      7. Das Feld für das sehr schwere Level
      8. Das Feld für das legendäre Level
setModeArea()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Levelbereich, in dem die unterschiedlichen Level angezeigt werden.
setRequestField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Anzeigefeld in den Levelbereich, das die Levelauswahl kenntlich macht.
setNoobField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das sehr leichte Level.
setBasicField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das leichte Level.
setModerateField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das mittel schwere Level.
setHardField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das schwere Level.
setVeryHardField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das sehr schwere Level.
setUltimateField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld für das legendäre Level.
setLevelField(left,top,id)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Levelfeld auf die horizontale Stelle „left“ und auf die vertikale „top“ mit einer ID „id“.
setGeneField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Feld mit den zu den Sequenzen gehörenden Genen.
setMenuFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt Felder für das Menü.
    • Dazu gehören:
      1. Ein Zahnrad, welches das Menüfeld aufruft
      2. Das Menüfeld, das die Einstellungen verwaltet
setMenuField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Menüfeld, das die Einstellungen verwaltet.
    • Zu den Einstellungen gehören:
      1. Musik an/aus
      2. Klickgeräusch an/aus
      3. Buchstaben (Nukleotidabkürzungen) an/aus
      4. Neues Spiel starten
setToggles()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Kippschalter in das Menüfeld.
    • Dazu gehören:
      1. Der Kippschalter für die Musikregelung
      2. Der Kippschalter für die Klickgeräuschregelung
      3. Der Kippschalter für die Buchstabenregelung der Basen
setMusicSwitchToggle()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Kippschalter für die Musikregelung.
setClickSoundSwitchToggle()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Kippschalter für die Klickgeräuschregelung.
setLetterSwitchToggle()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Kippschalter für die Buchstabenregelung der Basen.
setToggleField(top,id)
  • Eingabe: String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Feld auf der Vertikalen „top“ in das Menüfeld, das den Bewegungsbereich eines Kippschalters repräsentiert.
setCommonToggleAttributes(toggle)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Kippschalter „toggle“ die allgemeinen Kippschaltereigenschaften zu.
setNewGameField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Feld in das Menüfeld, das für einen Neustart zuständig ist.
setMenuHiderField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Feld in das Menüfeld, das für das Ausblenden des Menüfelds zuständig ist.
setMenuCallerField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Feld, das für das Einblenden des Menüfelds zuständig ist.
setMenuCallerPic()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Zahnrad in das Feld, welches das Menü einblendet.
setCurrentScoreText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, das die aktuelle Punktzahl angibt.
setBestScoreText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, das die bestmögliche Punktzahl angibt.
setNextLevelText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, das für den Wechsel in das nächste Level zuständig ist.
setInfoInShortText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld mit den zusammengefassten Informationen.
setInfoSwitcherShortToPreciselyText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, das von dem zusammengefassten Informationsfeld zu dem ausführlichen Informationsfeld wechselt.
setInfoSwitcherPreciselyToShortText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, das von dem ausführlichen Informationsfeld zu dem zusammengefassten Informationsfeld wechselt.
setOptionWindowText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Optionsfenster.
setMiniBasesOptionText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für die Basen im Optionsfenster.
setPlayNextLevelText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld im Optionsfenster, welches in das nächste Level führt.
setPlayAroundText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld im Optionsfenster, welches für das Verbleiben im aktuellen Level zuständig ist.
setTutoCallerText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, welches das Tutorialfenster einblendet.
setSignpostsText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für die Wegweiser im Tutorialfenster.
setExampleTexts()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für die Beispiele im ausführlichen Informationsfeld.
setMatchScoreText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Beispiel, das die Gleichheit übereinanderliegender Basen repräsentiert.
setMatchScoreText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Beispiel, das die Ungleichheit übereinanderliegender Basen repräsentiert.
setGapPenaltyText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Beispiel, das die Alignierung einer Base mit nichts repräsentiert.
setRequestText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, das die Levelauswahl im Levelbereich kenntlich macht.
setLevelFieldTexts()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für die Levelfelder im Levelbereich.
setMenuHiderText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld, welches das Menüfeld verbirgt.
setMenuFieldText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Menüfeld.
setToggleTexts()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für die Kippschalterbeschreibung im Menüfeld.
setNewGameText()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Textinhalt für das Feld im Menüfeld, welches ein neues Spiel startet.
Interaktion mit den weiteren Feldern (Klasse: interaction_otherFields):
setFunctionTutoCallerField(field)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“, welches das Tutorialfenster einblenden soll, eben diese Funktion zu.
setFunctionGoPrevPic()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Wegweiser im Tutorialfenster, welches auf das vorige Video wechseln soll, eben diese Funktion zu.
setFunctionGoNextPic()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Wegweiser im Tutorialfenster, das auf das nächste Video wechseln soll, eben diese Funktion zu.
setFunctionHideTuto()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Wegweiser im Tutorialfenster, welches das Menüfeld ausblenden soll, eben diese Funktion zu.
switchVid(direction)
  • Eingabe: int
  • Ausgabe: keine Ausgabe
  • Funktion: Wechselt auf das nächste oder vorherige Video, je nachdem wie die Richtung „direction“ gegeben ist. Bei 1 wird zu dem nächsten Video gewechselt, bei -1 auf das vorherige.
signpostHoverAnimationDouble(id1,id2)
  • Eingabe: String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist zweizeiligen Wegweisern im Tutorialfenster eine Animation zu, die erscheint, wenn der Spieler mit dem Zeiger über ihnen steht.
signpostHoverAnimationSingle(id)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einzeiligen Wegweisern im Tutorialfenster eine Animation zu, die erscheint, wenn der Spieler mit dem Zeiger über ihnen steht.
displayTutoField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Tutorialfenster ein.
displayTutoCaller()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld ein, welches die Funktion trägt, das Tutorialfenster einzublenden.
hideTutoCaller()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld aus, welches die Funktion trägt, das Tutorialfenster einzublenden.
hideTutoField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Tutorialfenster aus.
moveUpTutoField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Tutorialfenster nach oben.
moveDownTutoField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Tutorialfenster nach unten.
moveLeftTutoCaller()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld, welches das Tutorialfenster einblendet, nach links.
moveRightTutoCaller()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld, welches das Tutorialfenster einblendet, nach rechts.
hideCurrentScoreField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld aus, das den aktuellen Punktestand anzeigt.
moveUpCurrentScoreField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld, das den aktuellen Punktestand anzeigt, nach oben.
hideBestScoreField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld aus, das die bestmögliche Punktzahl anzeigt.
moveUpBestScoreField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld, das die bestmögliche Punktzahl anzeigt, nach oben.
setFunctionNextLevelField(field)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“, das den Spieler in das nächste Level befördert, eben diese Funktion zu.
displayNextLevelField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld ein, das den Spieler in das nächste Level befördert.
moveDownNextLevelField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld, das den Spieler in das nächste Level befördert, nach unten.
hideNextLevelField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld aus, das den Spieler in das nächste Level befördert.
moveUpNextLevelField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld, das den Spieler in das nächste Level befördert, nach oben.
setFunctionInfoSwitcher1Field(field)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“, das von dem zusammengefassten Informationsfeld zu dem ausführlichen Informationsfeld wechselt, eben diese Funktion zu.
setFunctionInfoSwitcher2Field(field)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“, das von dem ausführlichen Informationsfeld zu dem zusammengefassten Informationsfeld wechselt, eben diese Funktion zu.
hideInfoFieldHelper()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das ausführliche Informationsfeld aus und das zusammengefasste Informationsfeld ein.
moveLeftInfoFieldHelper()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das ausführliche Informationsfeld nach links.
moveRightInfoField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das zusammengefasste Informationsfeld nach rechts.
moveLeftOtherFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt die anderen Felder nach links.
    • Zu den anderen Feldern gehören:
      1. Das Spielfeld
      2. Das Feld, das den aktuellen Punktestand anzeigt
      3. Das Feld, das den bestmöglichen Punktestand anzeigt
      4. Das Feld, das den Spieler in das nächste Level befördert
      5. Das Optionsfenster
      6. Der Levelbereich
displayInfoFieldHelper()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das ausführliche Informationsfeld ein und das zusammengefasste Informationsfeld aus.
moveRightInfoFieldHelper()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das ausführliche Informationsfeld nach rechts.
moveLeftInfoField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das zusammengefasste Informationsfeld nach links.
moveRightOtherFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt die anderen Felder nach rechts.
    • Zu den anderen Felder gehören:
      1. Das Spielfeld
      2. Das Feld, das den aktuellen Punktestand anzeigt
      3. Das Feld, das den bestmöglichen Punktestand anzeigt
      4. Das Feld, das den Spieler in das nächste Level befördert
      5. Das Optionsfenster
      6. Der Levelbereich
setFunctionLevelField(field,difficulty)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Levelfeld „field“ die Funktion zu, ein Level der Schwierigkeit „difficulty“ zu erstellen und in dieses einzusteigen. Hierbei wird eine Stoppuhr gestartet.
startTime()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Startet die Zeit und hält diese in dem globalen Array „time“ fest.
hideModeField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet den Levelbereich aus.
moveUpModeField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt den Levelbereich nach oben.
displayModeField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet den Levelbereich ein.
moveDownModeField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt den Levelbereich nach unten.
setFunctionPlayNextLevelField(field)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“ im Optionsfenster, das den Spieler in das nächste Level führen soll, eben diese Funktion zu.
setFunctionPlayAroundField(field)
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“ im Optionsfenster, das den Spieler in dem aktuellen Level verbleiben lassen soll, eben diese Funktion zu.
hideOptionField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Optionsfenster aus.
moveUpOptionField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Optionsfenster nach oben.
displayOptionField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Optionsfenster ein.
moveDownOptionField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Optionsfenster nach unten.
setFunctionMenuHider(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“, welches das Menüfeld verbergen soll, eben diese Funktion zu.
setFunctionNewGameField(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld „field“ im Menüfeld, das ein neues Spiel starten soll, eben diese Funktion zu.
setFieldToggleFunction(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Kippschalterfeld „field“ eine Funktion zu.
setFunctionMusicToggle(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Kippschalterfeld „field“, das die Hintergrundmusik verwalten soll, eben diese Funktion zu.
muteAudio()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Schaltet die Hintergrundmusik aus.
activateAudio()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Schaltet die Hintergrundmusik ein.
setFunctionClickSoundToggle(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Kippschalterfeld „field“, welches das Klickgeräusch regeln soll, eben diese Funktion zu.
muteClickSounds()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Deaktiviert die Klickgeräusche.
activateClickSounds()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Aktiviert die Klickgeräusche.
setFunctionLetterSwitchToggle(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Kippschalterfeld „field“, das die Buchstabenanzeige in den Basen verwalten soll, eben diese Funktion zu.
clearBaseLetters()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Entfernt die Nukleotidkürzel aus den Basen.
setBaseLetters()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die passenden Nukleotidkürzel in die Basen.
setMenuCallerPicFunction(img)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Bild „img“, welches das Menüfeld einblendet, eben diese Funktion zu.
moveUpMenuField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Menüfeld nach oben.
moveDownMenuField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Menüfeld nach unten.
changeSrcHover()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Verändert den normalen Hintergrund von dem Feld, welches das Menüfeld einblendet, zu einem Animationshintergrund.
changeIdHover()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Verändert die normale ID des Hintergrunds von dem Feld, welches das Menüfeld einblendet, zur Animations ID.
changeSrcNormal()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Verändert den Animationshintergrund von dem Feld, welches das Menüfeld einblendet, zum normalen Hintergrund.
changeIdNormal()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Verändert die Animations ID des Hintergrunds von dem Feld, welches das Menüfeld einblendet, zur normalen ID.
extractGenes()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Extrahiert die Gene aus dem gegebenem Level und hält diese global fest.
setGeneNames()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Gennamen in das Feld für Gene und erstellt für jedes Gen ein Feld, das Informationen zu diesem beinhaltet.
createGeneInfoField(id,top)
  • Eingabe: String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Erstellt ein Geninformationsfeld mit der ID „id“ auf der Vertikalen „top“.
hoverGeneText(idText,idField,position)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist jedem Gen die Funktion zu das dazugehörige Geninformationsfeld einzublenden, sobald der Zeiger auf dem Gennamen steht.
driveOutGeneInfoField(idText,idField)
  • Eingabe: String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Fährt das Geninformationsfeld mit der ID „idField“ auf der Horizontalen aus.
growUpGeneInfoField(idText,idField,position)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Geninformationsfeld mit der ID „idField“ eine Höhe zu und setzt den Textinhalt, welche das Gen beschreiben soll in das entsprechende Geninformationsfeld.
growDownGeneInfoField(idText,idField)
  • Eingabe: String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Entzieht dem Geninformationsfeld mit der ID „idField“ den Textinhalt und die Höhe, wodurch es kleiner wird.
driveInGeneField(idText,idField,originalTop)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Fährt das Geninformationsfeld mit der ID „idField“ auf die ursprüngliche Position neben dem dazugehörigen Gen ein.
getOptimizedHeight(text)
  • Eingabe: String
  • Ausgabe: float
  • Funktion: Gibt eine Höhe als float aus, die in Abhängigkeit von der Textlänge aus dem gegebenem Text „text“ berechnet wird.
setNewText(idText,text,position)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Passt einen gegebenen Textabschnitt „text“ einem Format an.
displayGeneField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld mit den Genen ein.
hideGeneField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Feld mit den Genen aus.
moveDownGeneField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld mit den Genen nach unten.
moveUpGeneField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Feld mit den Genen nach oben.
hideOtherFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet weitere Felder aus.
    • Zu den weiteren Feldern gehören:
      1. Das Optionsfenster
      2. Das ausführliche Informationsfeld
      3. Das Feld, welches das Tutorialfenster einblendet
      4. Das Reglerfenster
      5. Das Feld, das den aktuellen Punktestand anzeigt
      6. Das Feld, das den bestmöglichen Punktestand anzeigt
      7. Das Feld, das in das nächste Level führt
showDifferenceCurrentScore(dif)
  • Eingabe: int
  • Ausgabe: keine Ausgabe
  • Funktion: Zeigt die Differenz „dif“ zwischen dem neuen Punktestand und dem vorherigen Punktestand nach einem Zug an.
createDifferenceCurrentScoreText(color,dif,left,top)
  • Eingabe: String,int,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Erstellt einen Text der Farbe „color“, welcher die Differenz „dif“ zwischen dem neuen Punktestand und dem alten Punktestand an der horizontalen Stelle „left“ und auf der Vertikalen „top“ darstellt.
moveDownDifferenceCurrentScore()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt den Text, welcher die Differenz zwischen dem neuen Punktestand und dem alten anzeigt, nach unten.
moveUpDifferenceCurrentScore()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt den Text, welcher die Differenz zwischen dem neuen Punktestand und dem alten anzeigt, nach oben.
clearCurrentScoreDifference()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Löscht den Text, welcher die Differenz zwischen dem neuen Punktestand und dem Alten anzeigt.
buttonAnimation(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem gegebenem Feld „field“ die Animation zu aufzuleuchten, wenn der Zeiger darüber steht.
enterButton(id)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist dem Feld mit der ID „id“ einen leuchtenden Rand zu.
leaveButton(id)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Nimmt dem Feld mit der ID „id“ den leuchtenden Rand, falls dieser vorhanden ist.
prepareNextLevel()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bereitet das nächste Level vor, in dem es alle Felder, mit Ausnahme von dem Menüfenster einblendenden Feld, ausblendet und den Levelbereich einblendet.
joinLevel(difficulty)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Baut ein neues Level in Abhängigkeit von der gegebenen Schwierigkeit „difficulty“ auf.
changeToBaseOriginalId()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Wechselt die ID der Basen zu ihrer Original ID, die über keine Animation verfügt.
changeToBaseAnimationId()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Wechselt die ID der Basen zu ihrer Animations ID, welche über eine Animation verfügt.
isGameComponentsAlreadyRemoved()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Prüft, ob die Basen im Spielfeld bereits gelöscht sind.
setParameters()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Startwerte für die Parameter Match Score, Mismatch Score und Gap Penalty.
Setter für die Regler (Klasse: setter_slider):
setPermanentSliderEvents()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Weist Mausereignisse und Touchereignisse Funktionen zu, welche die Regler verwalten.
setSliderField()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt das Reglerfeld, in welchem die Regler liegen.
setAllSlider()
  • Eingabe: keine Ausgabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt alle nötigen Regler, welche die Parameterwerte Match Score, Mismatch Score und Gap Penalty verwalten.
setSlider(left,top,sliderId)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt einen Regler auf die horizontale Stelle „left“ und auf die Vertikale „top“ und weist ihm eine ID „sliderId“ zu.
setCuttingLine(left)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine Trennline im Reglerfeld auf die horizontale Stelle „left“.
setCol(id,left,top)
  • Eingabe: String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine Spalte mit der ID „id“ auf die horizontale Stelle „left“ und Vertikale „top“ in das Reglerfeld, welche als Achse mit Skalierung repräsentiert wird.
setColText(id)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Überschrift einer Spalte bzw. Achse im Reglerfeld, welche die gegebene ID „id“ hat.
setMarksInCol(id)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Skalierung einer gegebenen Spalte/Achse mit der ID „id“.
setScaling(id,top,i)
  • Eingabe: String,int,int
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt eine Zahl in eine gegebene Achse bzw. Spalte mit der ID „id“ auf die entsprechende Höhe „top“.
Getter für die Regler (Klasse: getter_slider):
getPercentOfPx(mouseYcord)
  • Eingabe: float
  • Ausgabe: keine Ausgabe
  • Funktion: Wandelt den gegebenen Wert „mouseYcord“ in die entsprechende Prozentzahl um.
Interaktion mit den Reglern (Klasse: interaction_slider):
startSliderDrag(event,obj)
  • Eingabe: event,element
  • Ausgabe: keine Ausgabe
  • Funktion: Verwaltet den Start der Interaktion zwischen Benutzer und Regler.
doSliderDrag(event)
  • Eingabe: event
  • Ausgabe: keine Ausgabe
  • Funktion: Verwaltet die Ausführung der Interaktion zwischen Benutzer und Regler. Dazu wird dem anvisierten Regler stets eine neue Position auf der Vertikalen zugewiesen.
stopSliderDrag(event)
  • Eingabe: event
  • Ausgabe: keine Ausgabe
  • Funktion: Verwaltet das Ende der Interaktion zwischen Benutzer und Regler. Dazu werden die Parameterwerte von Match Score, Mismatch Score und Gap Penalty neu gesetzt.
lockSliderIn()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Lässt den anvisierten Regler in das nächstmögliche Feld auf der Achse einrasten.
resetScores(minDifferencePlace)
  • Eingabe: int
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den Wert von Match Score, Mismatch Score oder Gap Penalty in Abhängigkeit von der Position „minDifferencePlace“, auf der der anvisierte Regler liegt, neu.
updateScores()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt einen neuen bestmöglichen Punktestand und einen neuen aktuellen Punktestand in Abhängigkeit von den aktuellen Parameterwerten Match Score, Mismatch Score und Gap Penalty.
displaySliderField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Reglerfeld ein.
moveRightSliderField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Reglerfeld nach rechts.
hideSliderField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Blendet das Reglerfeld aus.
moveLeftSliderField()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Bewegt das Reglerfeld nach links.
makeSliderClickSound()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Lässt ein Klickgeräusch erklingen, sobald ein Regler angeklickt wird.
makeSliderDropSound()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Lässt ein Klickgeräusch erklingen, sobald ein Regler losgelassen wird.
Setter für die gemeinsame Attribute von Feldern (Klasse: setter_fieldAttributes):
setCommonFieldAttributes(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ die gemeinsamen Feldattribute zu.
    • Zu den Attributen gehören:
      1. Die Beweglichkeit eines Felds
      2. Der Hintergrund
      3. Der Rand
      4. Der Randradius
      5. Die Randart
      6. Die Randfarbe
setFieldTextShadow(field)
  • Eingabe: element
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Textschattierung zu.
setFieldId(field,id)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine ID „id“ zu.
setFieldCursor(field,cursor)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ einen Zeigertyp „cursor“ zu, der erscheint, sobald der Zeiger über dem Feld liegt.
setFieldSize(field,width,height)
  • Eingabe: element,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Breite „width“ und Höhe „height“ zu.
setFieldPosition(field,left,top)
  • Eingabe: element,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Stelle „left“ auf der Horizontalen und einen Wert „top“ auf der Vertikalen zu, wodurch die Position des Felds festgelegt wird.
setFieldTransition(field,transition)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ einen Übergang „transition“ zu.
setFieldMoveability(field,position)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Bewegungseigenschaft „position“ zu.
setFieldBackground(field,background)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ einen Hintergrund „background“ zu.
setFieldBorder(field,border)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ einen Rand „border“ zu.
setFieldBorderRadius(field,radius)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ einen Randradius „radius“ zu.
setFieldBorderStyle(field,borderStyle)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Randart „borderStyle“ zu.
setFieldBorderWidth(field,width)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Randbreite „width“ zu.
setFieldBorderColor(field,borderColor)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Randfarbe „borderColor“ zu.
setFieldColor(field,color)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Farbe „color“ für den Inhalt zu.
setFieldZindex(field,num)
  • Eingabe: element,int
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ einen Rang „num“ zu, welche das Feld in den Vordergrund oder Hintergrund verlegt.
setFieldOpacity(field,numString)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenen Feld „field“ eine Deckkraftstärke „numString“ zu.
Setter für die gemeinsamen Textattribute (Klasse: setter_textAttributes):
setText(left,top,size,id,innerText,fatherId)
  • Eingabe: String,String,String,String,String,String
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt ein Textfeld mit der ID „id“ und dem dazugehörigen Textinhalt „innerText“ in ein Feld mit der ID „fatherId“.
setTextFontSize(text,fontSize)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenem Text „text“ eine Schriftgröße „fontSize“ zu.
setTextInnerHtml(text,innerHtml)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenem Text „text“ einen Textinhalt „innerHtml“ zu.
setTextFontFamily(text,fontFamily)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenem Text „text“ eine Textfamilie „fontFamily“ zu.
setTextShadow(text,textShadow)
  • Eingabe: element,String
  • Ausgabe: keine Ausgabe
  • Funktion: Weist einem gegebenem Text „text“ eine Textschattierung „textShadow“ zu.
Interaktion für die Berechnung (Klasse: interaction_gameComputation):
getMsa()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Extrahiert das Alignment aus der Datenbank „sequences“.
getScores()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Berechnet die aktuelle Punktzahl und die bestmögliche Punktzahl zu Beginn.
setNewCurrentScore(newScore)
  • Eingabe: int
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt den aktuellen Punktestand neu.
lvlSolvedChecker()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Prüft, ob ein Level nach einem Zug bereits gelöst ist und blendet gegebenfalls das Optionsfenster ein.
stopTime()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Stoppt die Zeit.
addZero(num)
  • Eingabe: int
  • Ausgabe: int
  • Funktion: Legt eventuell eine Null vor die Eingabe „num“ und gibt das Resultat aus.
numOfFitIn(number,fitter)
  • Eingabe: int,int
  • Ausgabe: int
  • Funktion: Berechnet „fitter div number“ und gibt das Resultat aus.
displayUsedTime()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Zeigt die Zeit im Optionsfenster an, die der Spieler zum Lösen des Levels benötigt hat.
Interaktion für die Fenstergrößenanpassung (Klasse: interaction_windowResize):
adjustElements()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Leert die Seite bei Fenstergrößenveränderung und setzt alle Elemente angepasst an die neue Fenstergröße neu.
removeGameComponents()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Löscht Spielkomponenten von der Seite.
    • Zu den Spielkomponenten gehören:
      1. Der Spielfeldinhalt
      2. Das Feld, das die aktuelle Punktzahl anzeigt
      3. Das Feld, das die bestmögliche Punktzahl anzeigt
      4. Das Feld, das den Spieler in das nächste Level befördert
      5. Das Optionsfenster
      6. Das zusammengefasste Informationsfeld
      7. Das ausführliche Informationsfeld
      8. Das Feld, welches das Tutorialfenster aufruft
      9. Das Tutorialfenster
      10. Das Reglerfeld
      11. Regler für den Parameter, der für den Match Score steht
      12. Regler für den Parameter, der für den Mismatch Score steht
      13. Regler für den Parameter, der für die Gap Penalty steht
      14. Das Genfeld
      15. Die Geninformationsfelder
removeGameFieldContent()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Löscht alle Basen, die in dem Spielfeld vorliegen.
removeElement(id)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Löscht ein Element, das die gegebene ID „id“ hat.
removeOrganismInfoFields()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Löscht die Geninformationsfelder.
buildAdjustedPage()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Initialisiert das Spiel neu.
Initialisierung des Spiels (Klasse: begin_init)
startGame()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Zeigt die Levelauswahl an.
initialize(dif)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Initialisiert das Spiel und erzeugt ein Level der Schwierigkeit „dif“.
setDifficulty(dif)
  • Eingabe: String
  • Ausgabe: keine Ausgabe
  • Funktion: Speichert die Schwierigkeit „dif“ für das gewählte Level in der globale Variable „difficulty“.
setLevel()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die Levelinformationen in die globale Variable „level“.
setId()
  • Eingabe: keine Eingabe
  • Ausgabe: keine Ausgabe
  • Funktion: Setzt die ID des gewählten Levels in die globale Variable „id“.

CSS Animation

Animation der Basen (Datei: baseAnimations)

In dieser Datei wird die Animation der Basen verwaltet. Den Basen, die im Optionsfenster vorliegen, wird eine kontinuierliche Rotation zugewiesen. Die Basen, die im Spielfeld vorliegen, werden beim Übergang in das nächste Level von ihrer horizontalen Reihe losgelöst und jeweils über verschiedene Richtungsvektoren durch das Spielfeld bewegt.

Animation des Zahnrads (Datei: gearAnimation)

In dieser Datei wird die Animation des Zahnrads verwaltet. Hierbei wird dem Zahnrad eine kontinuierliche Rotation zugewiesen.

Probleme bei der Implementation

1. Problem: Das Erzeugen von Elementen

In der, für uns neuen Programmiersprache JavaScript gestaltet sich zunächst schon das Erstellen von Elementen, die die Basen darstellen sollen, als schwierig. Zudem soll nun anhand dieser Elemente und vorgegebener Sequenzen ein passendes Alignment erstellt werden, das dem Spieler dann angezeigt wird.

Für den statisch programmierten Prototyp, wurde eine feste Sequenz an aneinandergereihten Basen erstellt, die nicht veränderbar war und somit nur eine bestimmte DNA-Sequenz verkörperte. Das verbraucht sehr viel Code, wobei das Alignmentpuzzle nicht so variabel gestaltbar ist, da jede Sequenz die angezeigt werden soll, explizit im Code generiert werden muss.

Für das finale dynamische Programm, wurde eine Datensammlung zur Erzeugung der Elemente erstellt. Diese enthält, gelistet nach Level, verschiedene Alignments. Pro Alignment sind zwei Symbolsequenzen abgespeichert, sowie deren optimaler Score. Wird nun ein Spiel angefangen, so wird entsprechend dem gewählten Level aus der Liste zufällig ein Alignment bestimmt und bearbeitet. Dabei werden in die beiden Sequenzen zufällig Gaps eingebaut, wobei die Sequenzen beide auf dieselbe Länge gebracht werden, die der Spielfeldbreite entspricht. Gemäß dieser beiden Sequenzen werden dann die Basen erzeugt und auf dem Spielfeld angezeigt.

2. Problem: Das Bewegen von Basen

Zur Bewegeung einer Base, wird ihr beim Anklicken mit der Maus die Mauskoordinate zugewiesen, sodass sie sich im geklickten Mauszustand mit der Bewegung der Maus bewegt. Wird die Maus losgelassen, so behält die Base die zuletzt gespeicherten Koordinaten der Maus und verharrt an dieser Stelle, bis sie wieder von der Maus verschoben wird. Dadurch ist es möglich, dass die Basen mit der Maus überall hinbewegt werden können, ohne darauf zu Achten, dass sie eigentlich zu einer Sequenz gehören, die horizontal im Spielfeld platziert ist.

Daher wird den Basen nun nur noch die x-Koordinate der Maus übergeben, sodass der Spieler sie nur in der Horizontalen bewegen kann.

3. Problem: Das Mitverschieben der Nachbarbasen

Trifft in dem ersten Spielentwurf eine Base beim Verschieben auf ihre benachbarte Base, so ist es zunächst möglich, die beiden Basen übereinander zu schieben oder gar zu vertauschen.

Als Lösung dieses Problems wird nun, sobald eine Base bewegt wird, kontinuierlich ihr Abstand zu den Nachbarn abgefragt. Ist ein gewisser Mindestabstand zwischen benachbarten Basen erreicht, so wird die Nachbarbase in die gleiche Richtung mitverschoben, wobei der Mindestabstand zwischen allen Basen immer eingehalten wird.

4. Problem: Die Grenzenfestlegung

Bei der Lösung des 3. Problems wurde nicht bedacht, dass nicht nur die Grenzen bezüglich der Nachbarbasen sondern auch die Grenzen bezüglich des Spielfelds bei der Bewegug von Elementen beachtet werden müssen. So ist es zunächst möglich eine Base komplett aus dem Spielfeld heraus zu schieben, wodurch diese durch dortiges loslassen der Maustaste verloren geht.

Als Lösung dieses Problems wird nun während des Bewegungsvorgangs eine weitere Abfrage gestellt. Werden die Koordinaten der letzten Base größer als die des letzten Felds, beziehungsweise bei der ersten Base kleiner als das erste Feld, so wird der Bewegungsvorgang gestoppt. So können die Basen nicht über den Spielfeldrand hinausgeschoben werden. Aufgrund des geforderten Mindestabstands zwischen den einzelnen Basen, wird auch die Bewegung einer Base in der Mitte der Sequenz gestoppt, falls diese die benachbarten Basen zu weit an den Rand schiebt. Damit ist sichergestellt, dass sich alle Elemente nur im Spielfeld bewegen können.

Alignmentscore

Entwicklungstagebuch:

1. Woche (3.5. - 9.5.17):

  1. Treffen am 03.05.:
    Julian und Leonie bilden das Team Score
Ideen zur Implementation:
  • Das Puzzle ist ein globales Alignment: Der Needleman-Wunsch-Algorithmus bietet sich an, da er den optimalen Score berechnet.

2. Woche (10.05. - 16.05.17):

Besprechung beim 2.Treffen am 10.05.:
  • Implementationsideen:

    Als Scoring-Algorithmus wird der dynamische Needleman-Wunsch Programmieralgorithmus verwendet, der eine optimale Lösung des globalen Alignmentproblems bietet. Bei der Implentation muss eine übersichtliche Schnittstelle zum Benutzen der Berechnungsmethoden geschaffen werden, damit die anderen Gruppen wissen, wie sie den Programmcode verwenden können und dies möglichst sicher möglich ist.

    • Anforderungen an Team Webseite: HTML-Elemente auf Webseite bereitstellen, in denen die berechneten Scores eingetragen werden können. Möglich ist das über bestimmte HTML-Tag ids.
    • Absprache mit Team Puzzle: Es muss abgesprochen werden, was die Ein-/Ausgaben in die Methoden zur Berechnung des Scores sein werden.
  • Wichtige Entscheidung:

    Die Festlegung auf die Methoden, die bei einer bestimmten Veränderung des Spielfeldes aufgerufen werden soll.

  • Primärziele:

    Zunächst nur den besten und aktuellen Score für zwei Sequenzen berechnen können. Berechnen des MSA-Scores wird hinten angestellt.

3. Woche (17.05. - 23.05.17):

Besprechung beim 3.Treffen am 17.05:
  • Ein wichtiger Meilensteil bei der Score-Berechnung kann vorgestellt werden:
    Needleman-Wunsch ist implementiert und kann optimale Scores für zwei Sequenzen berechnen.
  • Essen der Woche: Party-Brötchen
Neue Zielsetzung:
  • Implementieren der Methode zur Berechnung des aktuellen Scores
  • MSA-Score Berechnung
  • Refractoring der Berechnungsfunktionen zur Klasse, um Bedienbarkeit und Kapselung zu verbessern
  • Prototyp der kompletten Seite mit funktionierendem Spiel für zwei Sequenzen

4. Woche (24.05. - 30.05.17):

Das Treffen am 24.05 wird verschoben aufgrund einer Klausur.

  1. Treffen am 29.05.:
    • Durch Zusammenfügen des Programmcodes aller Gruppen entsteht der erste Prototyp. Das Spiel ist in die Webseite der Gruppe von Pepi und Mario eingebunden und es kann sowohl der beste Score für zwei, als auch der aktuelle Score für beliebig viele Sequenzen berechnet werden.
Neue Zielsetzung:
  • Es soll später möglich sein, nach dem erfolgreichen Beenden eines Levels die Berechnungsparameter umstellen und anschließend weiterspielen zu können. So ergeben sich neue beste Alignments, die der/die Spielende herausfinden kann und für diese ein besseres Verständnis der Berechnung entsteht.
  • MSA-Score anzeigen können. Die Idee zum umsetzen des Problems ist, den Score für alle Spielfelder vorzuberechnen und lediglich anzuzeigen. Zum Speichern der vorberechneten Werte wird eine JSON-Datei angelegt, die für alle Spielfelder den Score beinhaltet
Implementation:
  • Idee des Speicherns von Sequenzen verworfen; es müssten zu viele Werte für ein Spielfeld gespeichert werden, um das Verändern der Parameter nach dem Spiel zu erlauben. Stattdessen wird der bisher für für zwei Sequenzen verwendete Needleman-Wunsch Algorithmus für multiple Sequenzalinierungen erweitert.

5. und 6. Woche (Ferien)(31.05. - 13.06.17):

Kein Treffen wegen der freien Tage.

Neue Ideen / Anforderungen:
  • MSA Berechnung:
    Für bis zu 10 Sequenzen der Länge 15 sollte der Score berechenbar sein. Dafür falls nötig auf Heuristiken zurückgreifen.
Implementation:
  • Heuristiken zeigen große Abweichung vom besten Score (nach Needleman-Wunsch)
  • Dynamischer Programmieralgorithmus wird implementiert
Wichtiger Meilenstein:
  • Bester Score für MSAs kann berechnet werden! Performance stellt noch ein großes Problem dar: Es kann bis zu einer halben Minute dauern für mehr als 4 Sequenzen den besten Score zu berechnen.

7. und 8. Woche (14.06. - 27.06.17):

Erfolge:
  • Optimierung der Berechnung des besten Scores führt zu einigen Sekunden Verbesserung der Performance
Zwischenpräsentation Vorbereitungen:
  • Bisheriger Fortschritt, Entwicklungsprozess und der aktuelle Stand des Score-Teams soll zusammengefasst werden und als Teil einer Präsentation vor Professor Kay Nieselt vorgetragen werden.
  • Probevortrag ist für den 04.07. angesetzt

9. Woche (28.06. - 04.07.17):

Präsentation am 05.07.

Neue Ideen:
  • MSA-Berechnen
    Es soll die Clustalo API benutzt werden um Alignments von mehr als 4 Sequenzen zu berechnen. Anhand des Alignments wird ein „Ziel“-Score (der nicht optimal ist) anhand der currentScore() Methode berechnet und als „best score“ angezeigt
Implementation:
  • Clustalo API wird erfolgreich verwendet für alle „großen“ Level von mehr als 4 Sequenzen. Akzeptabler Zwischenstand, Clustalo API Requests dauern aber immer noch mehrere Sekunden.
  • Die Berechnungszeit des Scores für 4 oder weniger Sequenzen konnte erfolgreich auf unter zwei Sekunden optimiert werden.

ab der 10. Woche (5.7. bis 31.08.17):

Neue Ideen:
  • Es sollen alle Scores optimal vorberechnet und zu diesem Zweck erneut eine JSON Datei angelegt werden. Um die Bedienbarkeit aufrecht zu erhalten wird es Skripte zum interagieren mit der JSON Datei, sowie zum Eintragen neuer Level und Sequenzen geben.
  • Es soll mit „echten“ Sequenzen gespielt werden. Zu diesem Zweck werden Gene gesucht, aus denen dann 15 Basen lange Sequenzen für das Spiel kopiert werden. BONUS-Idee: Es sollen kleine Texte erstellt werden, die die Funktion des Gens erklären. Zudem sollen die Level so gewählt werden, dass eine Sequenz entweder gegen eine verwandte Sequenz eines anderen Organismus oder eine mutierte (kranke/onkogene) Variante des Gens aligniert wird. Intention: Interesse wecken und einzelne tiefe, aber nicht überfordernde Einblick geben.

Der Alignment-Score:

Die Berechnung des Alignmentscores (oder auch nur Score) erfolgt im Hintergrund und nur das Ergebnis (im Falle des Alignmentpuzzles unserer Webseite der aktuelle und beste Score) ist für den Spieler sichtbar. Dennoch ist er essenziell und ohne ihn wäre das Spiel nicht funktionstüchtig. Im Folgenden soll der Score, dessen Berechnung und unsere Implementation näher erläutert werden.

Definition: Score

Die Güte eines Alignments wird mit dem Alignmentscore (englisch für Punktzahl) beschrieben, dem ein spezielles Bewertungsschema zugrunde liegt, das von den drei Parametern „Mismatch Score“, „Match Score“ und „Gap Penalty“ abhängt. Jede Spalte des Alignments wird nach diesen Parametern beurteilt und der entsprechende Wert ermittelt. Die Summe der Wertungen jeder Spalte ergibt schlussendlich den gesamten Score.

Bemerkung

Der Sum-of-Pairs-Score (SoP-Score) stellt eine Möglichkeit dar, ein Alignment zu evaluieren. Er repräsentiert die Summe der Bewertungen aller Spalten in einem Alignment, wobei jede Kombination von Paarungen in einer Spalte betrachtet wird. Die Bewertung einer Basenpaarung hängt dabei von den oben erwähnten Parametern Match Score, Mismatch Score und Gap Penalty ab.

Beispiel zur Sum-Of-Pairs-Score Berechnung::

Match: +2, Mismatch: -1, Gap: -2

Sequenz 1: A T G T
Sequenz 2: G G G T
Sequenz 3: G G T
Spalten-Scores: -5 0 6 6

Für die erste Spalte berechnet sich der Score wie folgt:

S(A,G)+S(A,-)+S(G,-)= -1 -2-2 =-5

Die Berechnung der anderen Spalten erfolgt analog.

Aus allen Spalten ergibt sich dann der insgesamte SoP-Score von:

SoP-Score = (-5) + 0 + 6 + 6 = 7

Das Ziel in der Berechnung besteht maßgeblich in der Suche nach dem optimalen Score - also der maximalen Punktzahl, die erreicht werden kann. Es handelt sich dann um ein optimales Alignment und nur auf dessen Basis ist das Ergebnis relevant. Für das Ermitteln des bestmöglichen Scores gibt es verschiedene Ansätze, wichtig ist dabei vor allem eine schnelle und zuverlässige Berechnung.

Berechnung des Scores nach Needleman-Wunsch

Wie oben bereits erwähnt erfolgt die Berechnung des Scores anhand den Parametern Mismatch Score, Match Score und Gap Penalty. Der Score hängt dabei hauptsächlich von den jeweiligen Werten dieser Parameter ab; auch kann ein Variieren dieser Werte ein völlig anderes optimales Alignment bedeuten. Obwohl meist das Ziel verfolgt wird, so viele gleiche Basen wie möglich anzuordnen, um einen besonders hohen Score zu erreichen, ist es in manchen Situationen von Vorteil, eine Base mit einer Gap zu alignieren, um den bestmöglichen Score zu erzielen.

Für globale (und auch lokale) Alignments gibt es mehrere Berechnungsmöglichkeiten, die in ihrer Leistung und Korrektheit variieren können. Ein Algorithmus, der die möglichen optimalen Alignments der gegebenen Sequenzen kalkuliert, ist Needleman-Wunsch. Bei diesem handelt es sich um ein dynamisches Programmierverfahren (engl.: dynamic programming algorithm), das definitiv die möglichen optimalen Alignments liefert. Dazu zerlegt der Algorithmus das Hauptproblem - also das Erreichen des bestmöglichen Scores - in kleinere Probleme - das Berechnen des bestmöglichen Scores von Teilsequenzen. Aus diesen baut die Berechnungsmethode schließlich den optimalen Score für die gesamte Sequenz auf. Needleman-Wunsch basiert für 2 Sequenzen X und Y der Länge n und m auf der Formel

Formel von Needleman-Wunsch

wobei i der Index von X und j der Index von Y ist.

Bemerkung

Die beiden Sequenzen werden in eine n x m-Matrix eingetragen - eine Sequenz horizontal, die andere vertikal.

Ein kleines Beispiel, um das Prinzip zu veranschaulichen:

Sequenz A: AGTT
Sequenz B: CGT
  A G T T
C        
G        
T        

Mithilfe der Formel wird dann die Matrix befüllt, indem auf jedes einzelne Feld der Matrix der Algorithmus angewendet wird. Aus dieser Matrix lässt sich zum Schluss dann das optimale Alignment und dessen Score ermitteln.

Die einzelnen Zeilen der Formel repräsentieren die Nachbarn des zu berechnenden Felds und eine darauf angewendete Bewertung:

F(i-1,j-1) steht dabei für das diagonal gelegene Feld, wobei für s(x_i,y_j) der SoP-Score (siehe Definition: Score für eine genaue Erklärung) auf die entsprechenden Symbole angewendet wird.

F(i-1,j) repräsentiert den Nachbarn ein Feld weiter oben, während F(i,j-1) den Nachbarn ein Feld links bezeichnet. Bei beiden wird zusätzlich auf den Wert des Feldes noch der Score für eine Gap Penalty berechnet.

Der optimale Score des gesamten Alignments ist dann im letzten Eintrag F(n,m) gespeichert.

Während dieses Bewertungsschema für zwei zu vergleichende Sequenzen noch relativ übersichtlich ist, nimmt es bei wachsender Anzahl von Sequenzen, Multiple Sequence Alignment (kurz: MSA) genannt, rasant an Komplexität zu. Die Anzahl an Feldnachbarn wächst, wodurch mehr Abfragen in der Formel benötigt werden, die sämtliche Kombinationen abdecken. Die Anzahl dieser Einträge kann mithilfe

Formel zur Berechnung der Anzahl an Nachbarn

für n Sequenzen berechnet werden; i ist die Menge an Gaps. Anhand dessen wird jedoch deutlich, dass die Menge der angrenzenden Felder schnell in den mehrstelligen Bereich aufsteigt und somit einen massiven Rechenaufwand garantiert, was sich früher oder später in der Laufzeit des Programms manifestiert.

Heuristiken

Als Heuristik bezeichnet man in der Informatik ein bestimmtes Vorgehen zum Lösen eines Problems. Im Gegensatz zu der Alternative Needleman-Wunsch arbeiten Heuristiken wesentlich schneller und verbrauchen deutlich weniger Speicherplatz. Jedoch garantieren sie nicht ein optimales Alignment zu finden, was einen Nachteil darstellt. Dennoch liefern Heuristiken in den meisten Fälle optimale oder zumindest sehr gute Ergebnisse. Für Problemstellungen der Bioinformatik kommen Heuristiken sehr häufig zum Einsatz, um Lösungen zu approximieren, die sonst nur in sehr langer Rechenzeit bestimmt werden können. Ein sehr prominentes Beispiel für den Einsatz von Heuristiken ist der BLAST Algorithmus , der den Smith-Waterman Algorithmus für lokale Alignments approximiert. Mit Hilfe von BLAST können bei jeder Suche zehntausende von Sequenzen in den Datenbanken des NCBI (meist) innerhalb von Sekunden aligniert werden.

Implementation

Das Anzeigen der Scores basiert auf der Datei Sequences.json, die alle Level des Spiels mit zugehörigen Beschreibungen und Alignmentscores enthält. Es existieren JavaScript-Funktionen zum Erstellen eines Levels, oder die Rückgabe des besten Alignmentscores für ein Level, die die direkte Interaktion mit der JSON-Datei verbergen. Zum Anzeigen des aktuellen Scores muss nicht mit der JSON-Datei interagiert, sondern der Sum-of-Pairs-Score des aktuell auf dem Spielfeld sichtbaren Alignments berechnet werden. Es bleibt der komplexeste Teil zu erwähnen: Die eigentliche Berechnung der Alignmentscores der ausgewählten Sequenzen und das Füllen der JSON-Datei, sodass die JavaScript Funktionen im Browser aus ihr lesen können. Die Berechnung findet in Python statt.

Abrufen der gespeicherten Level

Ein selbst gestelltes Ziel bei der Umsetzung des Alignmentpuzzles ist immer das Verwenden von Sequenzen aus echten Genen gewesen. Um dies zu verwirklichen muss eine Möglichkeit bestehen, die ausgewählten Sequenzen zu speichern und abrufbar zu machen. Da ein Dantenbankserver für ein reines „front-end“ Projekt nicht als Möglichkeit in Betracht kommt, ist JSON hier die Lösung. Da alle Sequenzen manuell ausgesucht werden müssen, kann festgestellt werden, wie schwer ein Level ist. Somit eröffnet sich die Möglichkeit, den Benutzer vor jedem Spiel eine Schwierigkeitsstufe auswählen zu lassen.

Bemerkung

Die JavaScript Object Notation (JSON) ist ein Dateistandard zum Austauschen von Daten in einer für Menschen lesbaren Form. JSON wird oft in Webschnittstellen verwendet, wenn Daten abgefragt werden. Eine JSON Datei besteht aus einer Auflistung von „key: value“ Paaren.

Beispiel einer JSON-Datei:

{
        "name": "John Doe",
        "age": 42,
        "interests": ["boats", "cats", "mistery novels"],
        "place of residence": "Tübingen"
}
Methoden
getLevel(String difficulty)

Gibt ein JavaScript-Objekt zurück, das einem Level der gegebenen Schwierigkeit difficulty entspricht. Die Schwierigkeit muss eine der folgenden sein: „noob“, „basic“, „moderate“, „hard“, „veryHard“, „ultimate“.

Felder eines Levels:
  • alignment – Ein Array, der die Sequenzen des Levels mit zufällig eingefügten Gaps enthält. Stellt die Ausgangssituation des Levels dar
  • names – Ein Array, der die Namen der Gene, aus denen die Sequenzen des Levels entnommen sind, enthält.
  • descriptions – Ein Array, der für jede Sequenz eine Beschreibung enthält, die als Informationstext angezeigt werden kann.
  • organisms – Ein Array, der für jede Sequenz den Organismus enthält, aus dem das Gen Stammt
  • id – Ein String, der eine eindeutige Identifikation des Levels erlaubt
  • score – der Score des optimalen Alignments der Sequenzen.
getBestScore(String id, Integer match, Integer mismatch, Integer gap)

Gibt vorberechneten Alignmentscore für die Scoring-Parameter match, mismatch und gap für den mit id referenzierten Eintrag in der JSON-Datei sequences.json.

randomGaps(Array sequences)

Gibt für einen gegebenen Array an Sequenzen einen Array zurück, der in jeder enthaltenen Sequenz zufällig Gaps einfügt, sodass die Länge aller Sequenzen genau 20 ist. Es passen genau 20 Basen pro Reihe in das Puzzle.

randomOrder(Array a)

Gibt eine zufällige Permutation des gegebenen Arrays a zurück.

Bemerkung

Damit das Spiel abwechslungsreich bleibt werden die Funktionen randomGaps und randomOrder vor jedem Level auf die Sequenzen angewendet. Die Sequenzen bekommen eine zufällige Reihenfolge und jeweils zufällig eingefügte Gaps, ohne dabei die Reihenfolge der Basen zu verändern.

Berechnen des aktuellen Alignmentscores

Neben der Anzeige des besten erreichbaren Alignmentscores für ein Level braucht es für ein Spiel auch eine Art der Rückmeldung für den Spieler, um zu sehen wie gut er, oder sie sich schlägt. In der Bioinformatik wird zu diesem Zweck gerne der Sum-of-Pairs-Score verwendet.

Methode
getCurrentScore(Array alignment, Integer match, Integer, mismatch, Integer gap)

Gibt den Sum-of-Pairs-Score für ein im Array alignment beschriebenes Alignment zurück. Zur Bewertung aller Paare von Basen werden die Scoring-Parameter match, mismatch und gap verwendet.

Vorberechnen der besten Alignmentscores in Python

Warnung

Der im folgenden beschriebene Python Programmcode ist nicht von der Webseite aus ereichbar, sonder dient lediglich dem Vorbereiten des Alignmentpuzzles. Der Programmcode ist im Gitlab Projekt im Ordner computation zu finden.

Matrizen

Dynamische Datenstrukturen sind von zentraler Bedeutung für die Implementation von dynamischen Programmieralgorithmen. Der Needleman-Wunsch Algorithmus beruht auf dem Erstellen einer Scoring-Matrix, die den Alignmentscore der Präfixe aller alignierten Sequenzen beinhaltet. Diese benötigt für jede zu alignierende Sequenz eine eigene Dimension. Für multiple Sequenzalignments von mehr als zwei oder drei Sequenzen kann es schnell zu unüberschaubar komplexen Strukturen kommen und eine stabile Implementation ist wichtig. Da die Implementation von dynamischen Programmieralgorithmen nicht primärer Zweck der Programmiersprache JavaScript ist, sind jedoch keine performanten Bibliotheken für solche Datenstrukturen aus offiziellen Quellen vorhanden. Aus diesem Grund findet die Programmiersprache Python zum Vorberechnen der Needleman-Wunsch Scores für alle Level Verwendung, da sich mit Python die sehr effiziente Matrixbibliothek Numpy verwenden lässt.

Initialisiert wird eine Matrix anhand eines Arrays dimensions mit einer Länge in jeder Dimension. Für jeden Eintrag in dimensions existiert in der Matrix eine neue Dimension mit entsprechender Länge. Es muss beachtet werden, dass zum Initialisieren einer Scoring Matrix auf jede Längenangabe eins dazu addiert werden muss, da in alle Richtungen eine Zeile mit festen Initialwerten vorhanden sein muss.

Bemerkung

Für eine zweidimensionale Scoring-Matrix A für den Gebrauch im Needleman-Wunsch Algorithmus sind die Initialwerte in der ersten Zeile und Spalte wie folgt definiert:

A[i][0] = i * gap-penalty * -1

A[0][j] = j * gap-penalty * -1

Matrix A nach der Initialisierung mit Gap-Penalty 2:

0 -2 -4 -6 -8
-2        
-4        
-6        

Zum Ausfüllen der Matrix beim Berechnen, wird über sie von der Nullkoordinate, dem Vektor aller Indizes i=0 in der Matrix, bis zur Koordinate aller maximalen Indizes in der Matrix einmal komplett durchlaufen.

Vorbereiten der Level

Die Sequenzen aus echten Genen werden in FastA-Dateien im Ordner levels_fasta gespeichert. Sie sollten mit einer Raute beginnen, gefolgt von einer gültigen Schwierigkeitsstufe. Gültige Schwierigkeitsstufen sind: „noob“, „basic“, „moderate“, „hard“, „veryHard“ und „ultimate“.

Die Beschreibungszeile jeder Sequenz enthält in dieser Reihenfolge den Genname, eine Beschreibung der Funktion des Gens und den Organismus in dem dieses Gen vorkommt. Die drei Elemente der Beschreibungszeile werden durch das Symbol „|“ getrennt.

Bemerkung

Das FastA Format ist ein Standard, nach dem Sequenzen gespeichert werden. Ein Eintrag für eine Sequenz beginnt immer mit einer Beschreibungszeile, die den Name und weitere optionale Informationen enthalten kann. Eine Beschreibungszeile muss immer mit dem Symbol „>“ beginnen. Auf die Beschreibungszeile können dann beliebig viele Zeilen mit Sequenzabschnitten folgen, bis der nächste Eintrag wieder mit „>“ eingeläutet wird.

Beispiel FastA-Datei:

> Sequenz13498 | ATP7A | Mus musculus
ATGCCGCGCCGGAGAGCGTGTGTCCGCGCGAGATATTTG
ATAGACAGGATAGAGATACCCCAGATTTGAGACCAGAAG
ATGAC ...
> Sequenz13499 | ATP7B | Mus musculus
ATAGAATTTAGGAGCGGCGCCCAGATTTGAGACCAGAAG
ATAGACAGGATAGAGATTTAGGTTTATTGCGCGCGAAAA
ATGAC ...

Aus entsprechend formatierten FastA Dateien, können mit folgenden Befehlen Level in die Datei sequence.json geschrieben werden:

python3 manage.py --add-level=<levelname.fasta> --difficulty=<Schwierigkeitsstufe>

Fügt der Datei sequences.json ein Level an für eine gegebene Schwierigkeit

python3 manage.py --create-new

Erstellt die Datei sequences.json komplett neu anhand der im Ordner levels_fasta beschriebenen Levels. Der Aufruf wird die vorhande Datei sequences.json überschreiben!

Warnung

Beim Hinzufügen von einem, oder mehreren Leveln werden nicht automatisch die Alignmentscores berechnet. Dies muss mit einem separaten Befehl geschehen.

Berechnung des Optimalen Alignmentscores

Auf Grundlage der Datei sequences.json können die optimalen Alignmentscores nach dem Needleman-Wunsch Algorithmus berechnet werden. Es wird dabei für je fünf verschiedene Bewertungsparameter match, mismatch und gap der optimale Score berechnet und in einen dreidimensionalen Array geschrieben. Die redundante Berechnung wird vorgenommen, um den Modus „herum spielen“ nach erfolgreichem Beenden eines Levels auf der Spielseite zu ermöglichen. Dabei soll der Benutzer ein Gefühl für den Ablauf der Berechnung bekommen und sehen, wieso die standardmäßig gewählten Berechnungsparameter Matchscore=2, Mismatchscore=-1 und Gappenalty=2 für Sequenzalignments sinnvoller sind, als manche anderen Parameter. Der folgenden Befehle starten die Berechnung:

python3 manage.py --compute

Berechnet für alle Leveleinträge in der Datei sequences.json für die im Feld scores ein leerer Array steht die optimalen Alignmentscores.

python3 manage.py --verbose --compute

Empfohlener Aufruf. Berechnet für alle Leveleinträge in der Datei sequences.json für die im Feld scores ein leerer Array steht die optimalen Alignmentscores. Zeigt dabei den Fortschritt der Berechnung, sowie die verstrichene Zeit seit Beginn der Berechnung an.

Clustal Omega Client

Für den Fall, dass eine Sequenz mit der gespielt wird nicht in der Datei sequences.json erscheint, muss es eine Möglichkeit geben, denoch einen besten Score anzuzeigen. Das European Bioinformatics Institute (EMBL-EBI) stellt einen Webdienst der Software Clustal Omega zur Berechnung von Alignments frei zur Verfügung. Der Webdienst lässt sich via Anfragen auf eine API starten und das Ergebnis abfragen. Zum Verbessern der Ladezeiten bei der Berechnung des besten Scores für ein Level wird ein Client verwendet, der von Clustal Omega berechnete Alignments abfrägt und anschließend den Score des Alignments mit der Methode getBestScore berechnet.

Bemerkung

Als API bezeichnet man eine Anwendungs Programmierschnittstelle (engl: Application Programming Interface). Anders als Webseiten bieten APIs keine graphische Oberfläche, mit der interagiert werden kann, sondern dienen der direkten Interaktion mit den Anwendungen, die im Hintergrund der Webseiten laufen. So können wie im Fall der ClustalO-API Programme genutzt, oder gestartet werden, die auf einem entfernten Server laufen. Andere APIs erlauben zum Beispiel den Zugriff auf Datenbanken.

Clustal Omega verwendet eine Heuristik um ein gutes Alignment in kurzer Zeit berechnen zu können.

Methoden
ClustalCall(Array Sequences)

Konstruktor der Klasse. Aufruf des Konstruktors startet eine Abfrage an die ClustalO-API.

Attribute der ClustalCall-Klasse:
  • ClustalCall.alignment ist ein Array, in dem das von ClustalO berechnete Alignment gespeichert ist, sobald dieses berechnet ist.
  • ClustalCall.SLEEP_INTERVAL ist ein Integer. Beschreibt die Wartezeit in Milisekunden zwischen Statusabfragen an die ClustalO-API.
  • ClustalCall.POST_URL ist ein String, der die Url des Webdienstes repräsentiert.
  • ClustalCall.STATUS_URL ist ein String, der die Url zur Abfrage des Status der Berechnung repräsentiert.
  • ClustalCall.RESULT_RUL ist ein String, der die Url zur Abfrage des fertig berechneten Alignments repräsentiert.
  • jobID ist ein String, der die ID des Berechnungs-Jobs repräsentiert. Anhand der ID, können Status und Resultat der Berechnung abgefragt werden
  • data ist ein JSON Objekt, das die benötigten POST-Parameter für die Anfrage an den Webdienst enthält
getResult()

Frägt das Ergebnis der Berechnung des ClustalO Webdienstes ab.

Die Funktion muss nie explizit aufgerufen werden! Alle Ergebnisse sind als Attribute der Klasse gespeichert.

toFasta(Array sequences)

Wandelt ein Array mit Sequenzen um in einen String im FastA-Format.

toSequenceArray(String fastAString)

Wandelt einen String im FastA-Format um in einen Array, der alle Sequenzen des FastA-Strings enthält.

Entwicklung der Webseite

Erstellung des Prototypen der Homepage:

1. und 2. Woche (03.05. - 16.05.17):

  1. Treffen am 03.05.17:
    Pepi und Mario bilden das Team Webseite
Zunächst werden Ideen gesammelt, wie die Homepage aussehen soll (Anordnung der verschiedenen Logos, Navigationsleiste etc.)
  • Handschriftliche Zeichnung auf Papier (siehe „Grundgedanke Webseite.pdf“)
  • Das Logo soll sich dauerhaft oben auf der Webseite befinden und als Verlinkung zur Homepage dienen. Wichtig ist dabei der Bezug zur Bioinformatik und zum Thema des Projekts – nämlich dem Alignmentpuzzle. Daher werden in dem Logo die vier typischen Farben der Basen der DNA – rot, blau, gelb und grün - als Elemente benutzt. Es soll zentriert sein.
  • Startsymbol mit Verlinkung zum Alignmentpuzzle soll fest oben links neben dem Logo der Webseite stehen, da dies den wesentlichen Bestandteil der Webseite ausmacht und dieser Bereich in der Webseite (oben links) ist, beruhend auf statistischen Untersuchungen, der erste Teil, welcher die Aufmerksamkeit des Nutzers auf sich zieht. Das Startsymbol soll die Aufmerksamkeit des Besuchers auf sich ziehen und wieder den Bezug zum Spiel haben.
  • Navigationsleiste soll sich links befinden und kann mittels Knopfdruck auftauchen oder verschwinden, sodass die Webseite dynamischer aussieht; zudem beinhaltet sie:
    • Einen Link zur Homepage
    • Einen Link zum Alignmentpuzzle zusätzlich zu dem Spielverweis auf der Homepage
    • Einen Link zu weiteren Themen der Bioinformatik (aufgeteilt in Unterpunkte) - Idee: Kurze Texte zur einigen Themen der Bioinformatik einbinden
    • Einen Link zum Impressum, in das am Ende die Namen der Teammitglieder, deren Studiengänge und ähnliches eingetragen werden sollen.
  • Eine Slideshow mit unterhaltsamen Antworten auf die Frage: „Was ist Bioinformatik?“; diese soll direkt unterhalb des Logos der Webseite befindlich sein und automatisch ablaufen.
  • Den zentralen Punkt der Homepage bildet ein Text der allgemein die Bioinformatik thematisieren soll. Verlinkungen innerhalb des Texts zu dem Thema „Topics of bioinformatics“ sollen möglich sein. Außerdem ist eine Idee Bilder mit in den Text zu integrieren (Bildrechte usw. beachten wegen möglichen Bildrechtsverletzungen!)
  • Die rechte Seite der Homepage soll durch einen dünnen schwarzen Strich von der Mitte getrennt sein. Zudem soll dort ein von Hand gezeichnetes und mit dem Computer bearbeitetes Bild der Evolution „Vom Affen zum Menschen“ zu sehen sein. Es soll bis zum Ende der Homepage reichen.
Erste Implementationen:
  • Erstellen einer HTML-Datei
  • Vorstellungen und Ideen sollen zunächst als Grundgedanke und daher nur oberflächlich dargestellt werden (Navigationsleiste vorhanden, Platzhalter für das noch nicht vorhandene Logo und den anderen Zeichnungen als Bilder in die Webseite eingefügt)
  • Erstellen weiterer HTML-Dateien für die unterschiedlichen Teile der Webseite, um dort die Ideen, das Spiel und die Dokumentation einbinden zu können

Innerhalb der zwei Wochen wird dann ein Logo kreiert. Zunächst als Zeichnung auf Papier, später mit dem Programm InkScaoe am Computer abgebildet. Ein analoger Prozess findet mit dem Bild zum Alignmentpuzzle statt sowie dem Evolutionsbild, das an der rechten Seite der Homepage integriert werden soll.

Ab der 3. Woche (17.05.17):

Erfolge / Neue Ziele:
  • Das Alignmentpuzzle wird in die dafür zugehörige HTML-Datei integriert.
  • „Deutsch“ als Standardsprache der Webseite:
    • Motivation hierfür unter anderem die geringe Anzahl an deutschen Bioinformatik-Webseiten (Stand: 17.05.17)
    • Studieninteressierten, die nur eingeschränkte Englischkenntnisse vorweisen können, sollen ebenfalls angesprochen werden
  • Überlegungen bezüglich der Schriftart: Welche der bisher verwendeten erscheint am besten geeignet für die Webseite?

Das Spiel ist ab diesem Zeitpunkt auf dem Prototyp der Webseite spielbar und kann über die Homepage sowie der Navigationsleiste erreicht werden.

Verbesserung des Prototypen

Ab der 4. Woche (24.05.17):

Prototyp überarbeiten:
  • Überlegungen bezüglich den Anforderungen der Zielgruppe (Studieninteressierte)
  • Design der Webseite:
    • Wirkt nicht modern und ansprechend
    • Der weiße Hintergrund wirkt langweilig und soll durch Farbe und/oder spannende Highlights ersetzt werden.
  • Der Protoyp wird generell in Frage gestellt und eine komplette Überholung in Betracht gezogen.

Ab der 7. Woche (14.06.17):

Neue Implementationen:
  • Grundidee bezüglich „Alignmentpuzzle“, „Themen der Bioinformatik“ und „Über uns“ ist weiterhin das zentrale und prägende Gerüst der Webseite und führt von der Homepage aus, auf drei unterschiedliche HTML Dateien. Diese werden als Logos in Kästen auf der Homepage abgebildet. Auf diese Weise werden die Themen der Webeite klar voneinander getrennt und der Nutzer kann sich leicht zum gewünschten Inhalt navigieren.
  • Diese drei Hauptsektionen sollen jederzeit und von überall aus von der Webseite erreichbar sein, indem am oberen Webseitenrand jeweils drei Kästen eingefügt sind, ähnlich wie auf der Homepage. Je nach dem bei welchem Punkt der Benutzer aktuell ist, sind jeweils die anderen drei Punkte am oberen Bildschirmrand zu sehen (Bsp.: Benutzer befindet sich bei dem Punkt „Über uns“: Am oberen Bildschirmrand sind demnach in den Kästchen folgende Punkte angezeigt: „Zurück zur Startseite“, „Themen der Bioinformatik“ und „Alignmentpuzzle“)
  • Unter dem Punkt „Themen der Bioinformatik“ sollen die Themen „Wirkstoffdesign“, „Alignment“ sowie „Sequenzierung“ in eine manuelle Slideshow mit Informationstexten und Bildern integriert werden. Außerdem soll hier zusätzlich die Bioinformatik allgemein noch vorgestellt werden.
  • Der Punkt „Alignmentpuzzle“ führt zu dem Spiel der Webseite.
  • Die Sektion „Über uns“ enthält einen Verweis zur Dokumentation des Projekts, sowie eine Vorstellungsrunde zu den einzelnen Mitgliedern des Teams
  • Die unterschiedlichen Inhalte bei „Themen der Bioinformatik“ und bei „Über uns“ sind durch eine kleine Navigationsleiste, jeweils auf der linken Seite, zugänglich. Beim Wechseln des gerade genannten Inhalts, gibt es einen visuellen Effekt; der alte Inhalt verschwindet langsam, während der neue ebenfalls langsam angezeigt wird (Fade-Effekt).
  • Der Hintergrund soll durch ein entsprechendes Hintergrundbild ansprechender und moderner wirken, das im Bezug zur Bioinformatik steht. Damit es auch zum Thema des Projekts passt, ist ein DNA-Strang das Hauptmotiv.
  • Die Farbe der Schrift soll allgemein weiß sein, damit es in einem guten Kontrast zu dem dunkelblauen Hintergrund steht.

Ab der 8. Woche (20.06.17):

Umsetzung der Ideen aus der 7. Woche. Für das Alignmentpuzzle steht ein Template zur Verfügung.

Anpassung von Feinheiten

Ab der 9. Woche (28.06.17):

Ein User-Test in Form einer Umfrage zu der Webseite sowie zu dem Spiel wird durchgeführt. Die aufgekommenen Probleme werden auf die bestmögliche Weise gelöst.

Informationstexte für Themen der Bioinformatik stehen auf der Webseite zum Lesen zur Verfügung. Die Texte sollen mithilfe von erklärenden Bildern aufgelockert werden.

Es erfolgen weitere Verfeinerungen am Hintergrund: Sowohl Farbe als auch Sättigung werden angepasst. Der Hintergrund bei der Startseite wird ganz oben durch einen Farbverlauf verdunkelt, damit die weiße Schrift lesbar ist.

Alle Schriften werden aufeinander abgestimmt, wobei die Schrift der Knöpfe auf der Startseite (sowie die Knöpfe zur Verlinkung der anderen Seiten, die sich ganz oben an jeder einzelnen Seite befinden) von Hand mit Inkscape erstellt wurden.

Ein Link zur Dokumentation wird auch auf der Hauptseite hinzugefügt.

Der HTML-/CSS-Code aller Seiten wird so angepasst, dass alles bei Vergrößerung/Verkleinerung gut lesbar bleibt.

Definition: Alignment

Der Begriff Alignment bedeutet übersetzt etwa „Anordnung“ oder „Abgleich“ und beschreibt ein zentrales Thema in der Bioinformatik. Dabei handelt es sich um ein Verfahren zur Bestimmung von Ähnlichkeiten zwischen biologischen Sequenzen. Das grundlegende Ziel dahinter besteht darin gleiche oder zumindest ähnliche Sequenzabschnitte einander zuzuordnen.

Die zugeordneten Sequenzen können DNA-, RNA- oder Protein-Sequenzen sein, die übereinander arrangiert werden, sodass jedem Element einer Sequenz ein Element einer anderen Sequenz zugeordnet - aligniert - wird.

Ein kleines Beispiel:

Sequenz A: ATGCG
Sequenz B: ATTG

Daraus kann sich zum Beispiel folgendes Alignment ergeben:

ATGCG
||||
ATTG

Die einzelnen Buchstaben sind hier die Basen von DNA-Sequenzen. Das Alphabet für ein Alignment von RNA-Sequenzen würde statt dem T (für die Base Thymin) ein U (für die Base Uracil) beinhalten, während das von Protein-Sequenzen den Einbuchstabencode der 20 Aminosäuren einschließt. Um ein sinnvolles Ergebnis zu erzielen muss ein Alignment stets auf der Basis eines gemeinsamen Alphabets stattfinden. Das heißt ein Vergleich von beispielsweise DNA-Basen mit Aminosäuren eines Proteinabschnitts kann so nicht durchgeführt werden.

Wie aus dem Beispiel hervorgeht, dürfen zwei Symbole einer Sequenz nicht nur einem Symbol einer anderen zugeordnet werden, wobei ein Symbol entweder ein Buchstabe des Alphabets oder eine Gap (dazu später mehr) ist. Eine weitere Konvention besteht darin, dass die ursprüngliche Reihenfolge der einzelnen Elemente jeder Sequenz - oder auch String genannt - erhalten bleibt. Vertauschen einzelner Basen, um mehr gleiche Abschnitte zu erhalten, ist daher nicht möglich.

Auf Grundlage dieser Definition sind viele verschiedene Alignments möglich, wobei diese nicht zwangsläufig die Ähnlichkeit der Strings widerspiegeln. Demnach braucht es ein allgemeines, objektives Bewertungsschema, das die Übereinstimmungen zwischen den Sequenzen maximiert.

Doch bevor die Frage nach solch einer Funktion beantwortet werden kann, muss zunächst geklärt werden, wie ein Alignment mit Sequenzen unterschiedlicher Länge gehandhabt werden soll. Die simple Lösung dafür liefern „Lücken“ oder der häufiger gebrauchte Begriff aus dem Englischen: Gaps. Das Alignieren mit einer Gap bedeutet das Alignieren mit Nichts - der entsprechende Platz wird einfach leer gelassen. Das Einfügen solcher Lücken erlaubt es nicht nur Sequenzen auf eine gleiche Länge zu bringen, sondern auch unterschiedliche Kombinationsmöglichkeiten der alignierten Strings.

Auf die beiden Beispielsequenzen von vorhin bezogen entsteht dann das Alignment:

Sequenz A:  ATGCG
Sequenz B: ATTG

ATGCG
|||||
ATT-G

Es wurde nun eine Gap eingefügt, sodass jede Base beider Sequenzen jeweils zu einem Symbol zugeordnet wurde.

Nun kann auch die Frage zum Bewertungsschema geklärt werden. Das Alignment wird anhand folgender Parametern beurteilt: Match steht für die Alignierung gleicher Symbole, Mismatch für die Alignierung ungleicher Symbole und Gap für die eben beschriebene Alignierung mit einer Lücke. Alle drei Parameter beschreiben jeweils eine bestimmte Punktzahl, womit jede Spalte des Alignments bewertet wird. Die Summe aller Spaltenwerte ist dann die Gesamtpunktzahl des Alignments, die im Folgenden Score genannt wird. Näheres zur genauen Berechnung des Scores findet sich im Abschnitt zum Thema Alignment-Score.

Hier soll nur kurz anhand des Beispiels von vorhin eine ungefähre Vorstellung gegeben werden, wie diese Bewertung aussieht. Dieses Mal muss aber noch für die drei Parameter die jeweilige Punktzahl ausgewählt werden, in diesem Fall Match: +2, Mismatch: -1, Gap: -2. Die Zahlen sind willkürlich gewählt und können nach Belieben verändert werden. Es ist allerdings sinnvoll positive Werte für Match und negative Werte für Mismatch und Gap zu wählen, um einen möglichst aussagekräftigen Score zu erhalten. Der Score eines Alignments wird nun folgendermaßen berechnet:

Sequenz A: ATGCG
Sequenz B: ATTG

Match: +2
Mismatch: -1
Gap: -2

A  T  G  C  G
|  |  |  |  |
A  T  T  -  G
+2 +2 -1 -2 +2 = +3

Eine andere Möglichkeit die Sequenzen zu alignieren wäre folgende:
A  T  G  C  G
|  |  |  |  |
A  T  -  T  G
+2 +2 -2 -1 +2 = +3

Jede Spalte wird unabhängig von den anderen betrachtet und bewertet je nachdem, ob zwei gleiche oder ungleiche Basen oder eine Gap mit einer Base aligniert wird. Das Ergebnis bleibt bei beiden Alignments gleich; es kann also mehrere Kombinationsmöglichkeiten geben, die zu demselben Score führen.

Die Intention besteht immer darin den maximalen Score zu erzielen; es handelt sich dann um das „optimale Alignment“ - die günstigste Anordnung der Elemente aller Sequenzen. Nur auf Basis des optimalen Alignments sind sinnvolle Aussagen über die arrangierten Sequenzen möglich. Ein hoher Score bedeutet meist, dass eine hohe Ähnlichkeit zwischen den alignierten Sequenzen besteht. Ähnlichkeit in der Sequenzabfolge kann dabei Hinweise auf analoge Strukturen liefern, was gerade bei Proteinen maßgeblich Aufschluss über deren Funktionsweise gibt. Ähnlichkeit weist in den allermeisten Fällen auch auf eine evolutionäre Verwandschaft hin, wodurch beispielsweise phylogenetische Fragen wie gemeinsame Vorfahren beantwortet werden können.

Es gibt eine Differenzierung von Alignments: Das Alignment wie bisher beschrieben entspricht dem globalen Alignment, das heißt, dass alle Symbole der Sequenzen berücksichtigt werden. Dagegen wird ein Alignment als lokal bezeichnet, wenn nur Teile der Strings aligniert werden. Letzteres bietet sich unter anderem dafür an, um in langen, womöglich sehr unterschiedlichen Sequenzen, konservierte, homologe Regionen aufzuspüren - zum Beispiel eine gleiche Aminosäureabfolge bei Proteinen. Ein globales Alignment ist vor allem dann sinnvoll, wenn die zu untersuchenden Sequenzen sich in Länge und Aufbau ähneln.

Bei so kurzen Zeichenfolgen wie im obigen Beispiel ist es natürlich ein Leichtes den besten Score in kürzester Zeit zu ermitteln. Doch bestehen die wirklichen Alignments meist aus Sequenzen mit mehreren hundert Basen als Länge oder aber es werden mehr als zwei Sequenzen aligniert, was wiederum einem anderen Bewertungsschema als dem hier vorgestellten entspricht (mehr dazu findet sich unter Alignment-Score. Die Komplexität nimmt mit der Länge an Elementen und Anzahl an Strings rapide zu und das Lösen solcher Alignments per Hand wird zur unmöglichen Aufgabe. Hier kommt die Bioinformatik ins Spiel. Diese versucht mit computergestützen Methoden und intelligenten Algorithmen derartige Probleme in adäquater Zeit und mit so wenig Ressourcen wie möglich zu lösen.

Hintergrund

Bioinformatik ist ein Studienfach, das noch nicht lange besteht und somit auch nur an vereinzelten Universitäten angeboten wird. Im Gegensatz zu Fächern wie der reinen Informatik oder Biologie, können sich die meisten Menschen nichts unter der Kombination dieser beiden Fachgebiete vorstellen. Aus diesem Grund ziehen beispielsweise viele Studieninteressierte die Möglichkeit dieses Studiums gar nicht erst in Betracht. Dabei stellt Bioinformatik einen aufkommenden Trend in der Arbeitswelt dar und immer mehr Firmen suchen nach ausgebildeten Fachkräften dieser interdisziplinären Wissenschaft.

Die Webseite entstand im Rahmen des Teamprojekts der Vorlesung Software Engineering für Studierende der Informatik oder Teilgebieten der Informatik. Das Projekt Alignmentpuzzle stellte als Vorgabe eine Webseite mit einem Spiel, das sich mit dem Alignmentproblem beschäftigt, zu erstellen. Die Umsetzung war dann dem Team, das sich aus sechs Leuten zusammensetzte, überlassen, wobei Fragen nach Design oder Aufbau selbstständig geklärt werden sollten.

Das Bestreben unserer Webseite ist zum einen ein einfaches aber dennoch ansprechendes und aufgeschlossenes Design. Gerade im Hinblick auf die Moderne, in der aufgrund der Reizüberflutung stärker nach optischer Aufmachung gefiltert wird, erscheint uns das als fundamental und unabdingbar. Die Webseite soll Eindruck hinterlassen und nicht einfach neben den zahlreichen Konkurrenzseiten untergehen.

Zum anderen wird ein zentrales Thema der Bioinformatik - das Alignmentproblem wie oben beschrieben - thematisiert. Allen voran soll (der Vorgabe des Projekts entsprechend) das Alignmentpuzzle im Vordergrund stehen; auch um die Thematik auf mehr als nur der Basis eines einfachen Texts zu illustrieren. Das Spiel soll zunächst die Aufmerksamkeit der Webseitebesucher auf sich ziehen und ein grundlegendes Verständnis und Interesse für die Materie erzeugen. Die Texte zur Bioinformatik stehen dann bei Interesse nach mehr als ergänzende Informationsquelle zur Verfügung. Als unsere Zielgruppe stehen allen voran Studieninteressierte, die am Studieninformationstag mithilfe der Webseite auf die Bioinformatik aufmerksam gemacht werden sollen. Die Intention ist daher ein selbterklärender Aufbau, wobei der User keine Probleme beim Navigieren und Orientieren haben sollte. In Bezug darauf sollte er aber dennoch einen tieferen Einblick in das Themengebiet erlangen. Da vor allem das Puzzle im Mittelpunkt steht, war das Bestreben ein übersichtliches und verständliches Arrangement mit der Möglichkeit eines Mini-Tutoriums als zusätzliche Hilfestellung.

Angesichts der Tatsache, dass es sich hier um ein Projekt von einem einzigen Semester handelt, ist die Webseite und deren Inhalte relativ klein beziehungsweise kurz gehalten. Das Augenmerk lag zunächst auf den wichtigeren Aspekten wie die Funtkionstüchtigkeit des Puzzles. Aufgrund der Gestaltung steht jedoch die Option offen, die Website noch nach Belieben zu einem späteren Zeitpunkt zu erweitern und mit weiteren Informationen auszustatten ohne großartige Veränderungen am bisherigen Code zu vollziehen.