zpg-graphentester/algorithmen/GraphAlgo.java
2024-03-12 17:34:56 +01:00

259 lines
7 KiB
Java

package algorithmen;
import java.lang.Thread;
import java.nio.file.*;
import graph.*;
import java.util.List;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.application.Platform;
/**
*
* Abstrakte Oberklasse für alle zu simulierende Algorithmen
* Diese müssen die Methode getBezeichnung(): String und fuehreAlgorithmusAus() überschreiben.
*
* @version 6.7 (Dez. 2020)
* @author Thomas Schaller
*/
public abstract class GraphAlgo extends Thread {
// Anfang Attribute
private boolean stepping; // Einzelschrittmodus
private boolean waitforrepaint; // wird gerade gezeichnet (=> nicht nochmal zeichnen beauftragen)
private boolean waitforclick; // wird auf Klick für nächsten Step gewartet
protected boolean inArbeit;
protected GraphPlotter gp;
private Knoten startKnoten;
private int speed =100;
private Hilfe hilfe;
protected Graph g;
private List<String> aktuellerZustand;
// Ende Attribute
// Anfang Methoden
/**
* Erzeugt neues Algorithmus-Objekt
*/
public GraphAlgo() {
stepping = true;
waitforrepaint = false;
waitforclick = false;
aktuellerZustand = null;
setDaemon(true);
}
/**
* Setzt die Referenz auf die GraphAnzeige und das Hilfefenster
* @param graphPlotter
* @param hilfe
*/
public void setGUIElemente(GraphPlotter graphPlotter, Hilfe hilfe) {
gp = graphPlotter;
g = gp.getGraph();
this.hilfe = hilfe;
if (hilfe != null) hilfe.setGraphPlotter(gp);
}
/**
* Setzt Referenz auf den Graphen
* @param g Graph auf den der Algorithmus angewendet wird
*/
public void setGraph(Graph g) {
this.g = g;
gp = null;
hilfe = null;
}
/**
* Gibt Referenz auf den Graphen zurück
* @return g Graph, auf den der Algorithmus angewendet wird
*/
public Graph getGraph() {
return g;
}
/**
* Muss vom Algorithmus aufgerufen werden, um einen Haltepunkt zu setzen
*/
public void step() {
if(gp == null) return;
try{
//System.out.println("Step");
gp.updateImage();
aktuellerZustand = g.getStatus();
waitforclick = true;
if (hilfe != null) hilfe.setReviewAllowed(true);
int i = 0;
while((waitforclick && (stepping || i*10 < speed)) && !isInterrupted()){
Thread.sleep(10);
i++;
}
if (hilfe != null) hilfe.setReviewAllowed(false);
g.setStatus(aktuellerZustand);
aktuellerZustand = null;
}catch(Exception e) {
// Erneutes Stop, damit nicht stop während des Sleeps hier abgefangen wird.
stop();
}
}
/**
* Wird gerade auf einen Buttonklick für den nächsten Step gewartet?
* @return true/false
*/
public boolean getWaitforclick() {
return waitforclick;
}
/**
* Setzt, ob gewartet wird. Damit kann übermittelt werden, dass der Button gedrückt wurde
* @param wairforclickNeu Soll weiter gewartet werden?
*/
public void setWaitforclick(boolean waitforclickNeu) {
waitforclick = waitforclickNeu;
}
/**
* Setzt, ob im Einzelschrittmodus ausgeführt werden soll
* @param stepping true/false
*/
public void setStepping(boolean stepping) {
this.stepping = stepping;
}
/**
* Setzt die Wartezeit im automatischen Modus
* @param delay Wartezeit
*/
public void setSpeed(int delay) {
this.speed = delay;
}
/**
* Ausführung des Algorithmus
*/
public void run()
{
if(!inArbeit && gp != null)
{
// System.out.println("Algorithmus gestartet");
inArbeit = true;
try{
if (hilfe != null) hilfe.setReviewAllowed(false);
fuehreAlgorithmusAus();
gp.updateImage();
// System.out.println("Algorithmus beendet");
} catch( ThreadDeath e){
// System.out.println("Algorithmus vorzeitig beendet."+e);
}
if (hilfe != null) hilfe.setReviewAllowed(true);
inArbeit = false;
return;
}
else
{
return;
}
}
// Ende Methoden
/**
* Setzen des Startknotens
* @param k Startknoten
*/
public void setStartKnoten(Knoten k) {
startKnoten = k;
}
/**
* Abfragen des Startknotens für den Algorithmus
* @return gesetzter Startknoten oder Knoten Nr. 0
*/
public Knoten getStartKnoten() {
if (startKnoten != null) {
return startKnoten;
} else {
return g.getKnoten(0);
} // end of if-else
}
/**
* Methode für den eigentlichen Algorithmus
*/
public abstract void fuehreAlgorithmusAus();
/**
* Name des Algorithmus für die Dropdown-Auswahl
*/
public abstract String getBezeichnung();
/**
* Öffnet ein Anzeigefenster mit einer Meldung. Die
* Meldung wird ggf. auch im Hilfefenster angezeigt.
* Ist für die Verwendung im Algorithmus gedacht.
* @param s Meldung
*/
public void melde(String s) {
info(s);
Platform.runLater(() -> {
Alert meldung = new Alert(AlertType.INFORMATION, s, ButtonType.OK);
meldung.setTitle("Information");
meldung.setHeaderText(null);
meldung.showAndWait();
});
}
/**
* Text in das Hilfefenster einfügen
* Ist für die Verwendung im Algorithmus gedacht.
* @param s Hilfetext
*/
public void info(String s) {
if(hilfe != null) hilfe.append(s+"\n");
}
/**
* Löscht das Hilfefenster
*/
public void resetInfo() {
if(hilfe != null) hilfe.loescheAlles();
}
/**
* Rückt im Hilfefenster eine Ebene tiefer ein.
* Ist für die Verwendung im Algorithmus gedacht.
*/
public void infoIndentMore() {
if(hilfe != null) hilfe.indentMore();
}
/**
* Rückt im Hilfefenster eine Ebene aus.
* Ist für die Verwendung im Algorithmus gedacht.
*/
public void infoIndentLess() {
if(hilfe != null) hilfe.indentLess();
}
/**
* Initialisiert den Graphen
*/
public void init() {
gp.getGraphOptions().knotenKurztext = new String[]{"Wert"};
gp.getGraphOptions().knotenLangtext = new String[]{"Infotext","Wert","Markiert","Besucht"};
if(g.isGewichtet()) {
gp.getGraphOptions().kanteKurztext = new String[]{"Gewicht"};
gp.getGraphOptions().kanteLangtext = new String[]{"Gewicht","Markiert","Gelöscht"};
} else {
gp.getGraphOptions().kanteKurztext = new String[]{};
gp.getGraphOptions().kanteLangtext = new String[]{"Markiert","Gelöscht"};
}
}
}