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 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"}; } } }