Methoden Methoden anpassen und fehlende Funktionen hinzufügen

@mihe7 Ich habe ein Problem mit der addTrack Methode. Ab dem Punkt, wo ich den Track den Edges hinzufügen will, funktioniert es noch nicht, weil er immer wieder neue Listen erstellt und damit die alte überschreibt. Hast du eine Ahnung, wie ich das in einer Fallunterscheidung lösen kann?
Java:
                        if(edgesReadyForDriving.containsKey(originPoint)) {
                            edgesReadyForDriving.get(originPoint).add(newlyBuildTrack);
                            
                        }
                        else {
                            allTracksOnPoint = new ArrayList();
                            allTracksOnPoint.add(newlyBuildTrack); 
                            edgesReadyForDriving.put(originPoint, allTracksOnPoint);
                        }
                        if(edgesReadyForDriving.containsKey(departurePoint)){
                            edgesReadyForDriving.get(departurePoint).add(newlyBuildTrack);
                                
                        }
                        else {
                            allTracksOnPoint = new ArrayList();
                            allTracksOnPoint.add(newlyBuildTrack); 
                            edgesReadyForDriving.put(departurePoint, allTracksOnPoint);
                        }
 
Ich hoffe es. Es sieht bei mir momentan so aus:
Java:
    @Override
    public boolean equals(Object o) {
        if (o == null || o == this || !(o instanceof CartesianPoint)) {
            return o == this;
        }
        CartesianPoint p = (CartesianPoint) o;
        return xCoordinate == p.xCoordinate && yCoordinate == p.yCoordinate;
    }


    @Override
    public int hashCode() {
        return 57+7*xCoordinate+2555*yCoordinate;
    }
stimmt das so?
 
Ja, es geht nur darum, dass die Ergebnisse abhängig von den Koordinaten sind. Mit dem Code kann es dann aber auch nicht sein, dass ständig neue Listen angelegt werden.
 
Hab en Fehler!!! Es wurde vorher über
Code:
RawTrack tr = edgesReadyForDriving.get(point).get(i);
            if (!tr.equals(edgesReadyForDriving.get(point).get(i))) {//Ist das Gleiche wie tr
            ...
            }
geprüft und das ist ja Bockmist...
 
Jetzt wirft er mir im putTrain Befehl eine Exception, welche ich nachvollziehen kann, aber keine Ahnung habe, wie das nun zu lösen ist.
Java:
if (getConnection(passed, currentTrack) == null) { //WENN MAN KEIN GLEIS FINDET DAS AN DEM PUNKT ENDET
                throw new NoObjectWithCharacteristicsException("such a train can't be placed");
            }
In der letzten Iteration wirft er mir hier eine Exception, da natürlich am Track (1,-3) -> (1,1) kein Anschlussgleis existiert und deswegen mir getComnnection() null zurückgibt.
Muss ich dafür die getConnection() anpassen? Ich denke schon, oder, weil im putTrain macht das ja wenig Sinn.
Java:
  public RawTrack getConnection(CartesianPoint point, RawTrack track) {
        for(int i = 0; i < edgesReadyForDriving.get(point).size(); i++) {

            RawTrack tr = edgesReadyForDriving.get(point).get(i);
            if (!tr.equals(track)) {

                return tr;
            }
        }
       //Exception werfen, weil man kein Gleis findet was an diesem Punkt endet
        return null;
    }
 
Das kann durchaus funktionieren, zeigt aber nicht die Idee dahinter. Es geht darum, dass die Länge an der Stelle 0 sein müsste, d. h. der ganze Block ab positioned=passed nicht mehr ausgeführt werden sollte (s. #172).
Ups, den Kommentar muss ich wohl irgendwie übersehen haben...
Habe ich es richtig verstanden, dass die if-Abfrage nach position = passed; kommen muss, oder bereits davor, also das der Teil noch im Rumpf der Abfrage liegt? Es scheint jetzt alles zu funktionieren. Vielen Dank für die bisherige Unterstützung! 🙂

Jetzt mache ich mich mal an den step Befehl ran. Falls es noch mal zu Problemen kommen sollte, melde ich mich erneut (mit ziemlicher Sicherheit wird es dazu kommen...).
 
Mein Kommentar hat sich mit Deinem überschnitten. Daher habe ich ihn wieder entfernt und darauf hingewiesen.
Habe ich es richtig verstanden, dass die if-Abfrage nach position = passed; kommen muss, oder bereits davor, also das der Teil noch im Rumpf der Abfrage liegt?
Das ist für die Funktion irrelevant, aber da die Länge geprüft wird, bietet es sich an, es vor position = passed, d. h. möglichst nahe der Längenänderung zu machen.
 
OK, danke. Kurze Frage:
Java:
        // Check if train is on this track - if so then let it derail
        if (track.getSwitchedTo() != point) {
            if (track.getCurrentTrain() != null) {
                // TODO: remove train from trainsOnTrack and from all Track classes
            }
        }
Wie kann am besten einen ganzen Zug vom Gleisnetz entfernen? Die Entfernung von trainsOnTrack ist ja nicht schwierig. Jetzt müssen allerdings alle Track Instanzen auf denen der Zug draufsteht irgendwie durchgegangen werden, um dann setCurrentTrain=null zu setzen, oder? Wie stelle ich das am besten an?
 
OK, danke. Kurze Frage:
Java:
        // Check if train is on this track - if so then let it derail
        if (track.getSwitchedTo() != point) {
            if (track.getCurrentTrain() != null) {
                // TODO: remove train from trainsOnTrack and from all Track classes
            }
        }
Wie kann am besten einen ganzen Zug vom Gleisnetz entfernen? Die Entfernung von trainsOnTrack ist ja nicht schwierig. Jetzt müssen allerdings alle Track Instanzen auf denen der Zug draufsteht irgendwie durchgegangen werden, um dann setCurrentTrain=null zu setzen, oder? Wie stelle ich das am besten an?
@DagobertDuck funktioniert bei dir das Rückwartsaufsetzen des Zuges?
Als wenn ein Element des Richtungsvektors negativ ist?
 
Jetzt müssen allerdings alle Track Instanzen auf denen der Zug draufsteht irgendwie durchgegangen werden, um dann setCurrentTrain=null zu setzen, oder? Wie stelle ich das am besten an?
Ja, das ist jetzt genau so ein Fall wie zu Beginn: lösbar ist es, aber ggf. langsam, daher kann man sich überlegen, zusätzliche Listen zu verwalten, um den Zugriff zu beschleunigen. Dabei muss man abwägen, ob das den zusätzlichen Aufwand lohnt. Du könntest also z. B. bei Train eine Liste von Tracks verwalten, ob Du das machen willst, musst Du entscheiden.
 
@Mika34 wenn ich es richtig im Kopf habe, wird bei Dir in requiredTracks() die Länge noch nicht korrekt abgezogen. In der ersten Iteration muss eine zusätzliche 1 abgezogen werden (s. z. B. Bilder in #216).
 
Ja, das ist jetzt genau so ein Fall wie zu Beginn: lösbar ist es, aber ggf. langsam, daher kann man sich überlegen, zusätzliche Listen zu verwalten, um den Zugriff zu beschleunigen. Dabei muss man abwägen, ob das den zusätzlichen Aufwand lohnt. Du könntest also z. B. bei Train eine Liste von Tracks verwalten, ob Du das machen willst, musst Du entscheiden.
Ich glaube ich werde es ohne die zusätzliche Liste in der Train Klasse versuchen. Da habe ich die Befürchtung, dass es dann noch mal komplizierter mit dem step Befehl wird...
Wie würde denn eine "langsame" Lösung aussehen? Leider habe ich keine Idee, wie ich dort am besten durch alle Tracks iterieren könnte.
 
Ich verstehe es einfach nicht. Das Rückwärtsaufsetzen klappt bei mir einfach nicht... Es sieht bei mir so aus. Und er wirft beim Rückwärtsaufsetzen dann immer true zurück @DagobertDuck kannst du mir bitte weiterhelfen... So langsam verzweifle ich
Java:
        stopCall:while (length > 0) {
           
            if (currentTrack == null || requiredTracks.contains(currentTrack)) {
                //Länge zu groß für die Anzahl der Tracks
                throw new NoObjectWithCharacteristicsException("such a train can't be placed");
               //Exception, weil der Zug nicht platziert werden kann
            }
            requiredTracks.add(currentTrack); //FÜGE EN HINZU WO MAN GERADE DRAUF IST
            CartesianPoint passed = currentTrack.getPassedPoint(dir); //Verbidnugspunkt zweier Gleise, wo man vorbeigefahren ist
           


           // Terminal.printLine(passed);
            length =length - position.distanceTo(passed);//SUBTRAHIERE DIE LÄNGE VON DER MOMENTANEN POSITION

            if (currentTrack == startTrack) {
                length--;
            }
           
            position = passed;
            currentTrack = getConnection(passed, currentTrack);

            if (currentTrack != null) {
                dir = currentTrack.getDirectionTo(passed);
           
           
           
            if (getConnection(passed, currentTrack) == null) { //WENN MAN KEIN GLEIS FINDET DAS AN DEM PUNKT ENDET
                throw new NoObjectWithCharacteristicsException("such a train can't be placed");
            }
            //JETZIGER TRACK IST DANN DER TRACK, WO ANGESCHLOSSEN WIRD VON DEM NÄCHSTEN TRACK

            }
        }
 
?!? Du hast doch eine Liste der Tracks.
Da hast du natürlich recht.
Java:
        // Check if train is on this track - if so then let it derail
        if (track.getSwitchedTo() != point) {
            if (track.getCurrentTrain() != null) {
                Train train = track.getCurrentTrain();
                for (Track tr : tracks.values()) {
                    if (tr.getCurrentTrain() == train) {
                        tr.setCurrentTrain(null);
                    }
                }
                trainsOnTrack.remove(track.getCurrentTrain());
            }
        }
Passt das so? Falls ja, kann das mit der Stream API noch etwas verkürzt werden?

Screenshot 2020-02-28 at 14.44.52.png
Momentan bekomme ich hier allerdings noch eine Warnung und ich bin mir nicht sicher, wie ich an den Key, also den Richtungsvektor komme, da trainsOnTrack ja eine Map<Point, Train> ist.
 
Nein, ich meine die Abfrage zur Länge. Das hat aber dann nichts mit deinem Problem zu tun, da ich mit dieser Abfrage (if (currentTrack != null)...) auch keine Probleme hatte, einen Zug mit negativem Richtungsvektor aufzugleisen.
 
Ja, das entspricht meiner groben Skizze. Es geht einfach noch um Details wie z. B. die beiden Änderung von eben oder zusätzliche Abfragen wie z. B. evtl. noch erforderliche Längenprüfungen. So kann es z. B. noch notwendig sein,
Java:
            position = passed;
            if (!getConnection(passed, currentTrack).isPresent()) {
                //Exception, weil kein Punkt gefunden
            }
            currentTrack = getConnection(passed, currentTrack).get();
in einen if (length > 0)-Block zu stecken. Da müsst ihr ein wenig testen.
Jetzt habe ich es. Auf welche Weise wurde isPresent() und get() implementiert?
 
Gar nicht. In deinem Fall kannst du einfach if (getConnection(passed, currentTrack) == null) { schreiben und dann get() einfach weglassen. Ich hoffe, dass das bereits hilft.
 
Da hast du natürlich recht.
Java:
        // Check if train is on this track - if so then let it derail
        if (track.getSwitchedTo() != point) {
            if (track.getCurrentTrain() != null) {
                Train train = track.getCurrentTrain();
                for (Track tr : tracks.values()) {
                    if (tr.getCurrentTrain() == train) {
                        tr.setCurrentTrain(null);
                    }
                }
                trainsOnTrack.remove(track.getCurrentTrain());
            }
        }
Passt das so? Falls ja, kann das mit der Stream API noch etwas verkürzt werden?

Anhang anzeigen 13103
Momentan bekomme ich hier allerdings noch eine Warnung und ich bin mir nicht sicher, wie ich an den Key, also den Richtungsvektor komme, da trainsOnTrack ja eine Map<Point, Train> ist.
@mihe7 Damit meine Frage nicht untergeht
 
Ich verstehe es nicht. Kannst du bitte drüber schauen und mir sagen, was ich hier falsch mache. Ich sitze nun seit mehreren Stunden daran und ich verstehe nicht mehr was ich hier noch ausprobieren soll
Java:
while (length > 0) {

            if (currentTrack == null || requiredTracks.contains(currentTrack)) {
                // Länge zu groß für die Anzahl der Tracks
                throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                // Exception, weil der Zug nicht platziert werden kann
            }

            requiredTracks.add(currentTrack); // FÜGE EN HINZU WO MAN GERADE DRAUF IST
            CartesianPoint passed = currentTrack.getPassedPoint(dir); 


            length -= position.distanceTo(passed);

            if (currentTrack == startTrack) {
                length--;
            }
            position = passed;

            if (currentTrack != null) {
                dir = currentTrack.getDirectionTo(passed);
                if (getConnection(passed, currentTrack) == null) {
                    // Exception
                }

                currentTrack = getConnection(passed, currentTrack);

                if (getConnection(passed, currentTrack) == null) { 
                    throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                }

            }
        }
 
Passt das so? Falls ja, kann das mit der Stream API noch etwas verkürzt werden?
Du kannst
Java:
                for (Track tr : tracks.values()) {
                    if (tr.getCurrentTrain() == train) {
                        tr.setCurrentTrain(null);
                    }
                }
durch
Java:
tracks.values().stream.filter(tr -> tr.getCurrentTrain() == train).forEach(tr -> tr.setCurrentTrain(null));
ersetzen.
 
@mihe7 kannst du dir mein Programmstück anschauen, ich verstehe nicht wieso dieser Aufbau nicht stimmen kann. Das muss doch eigentlich funktionieren auf Basis der letzten Beiträge
 
Ich verstehe es nicht. Kannst du bitte drüber schauen und mir sagen, was ich hier falsch mache. Ich sitze nun seit mehreren Stunden daran und ich verstehe nicht mehr was ich hier noch ausprobieren soll
Java:
while (length > 0) {

            if (currentTrack == null || requiredTracks.contains(currentTrack)) {
                // Länge zu groß für die Anzahl der Tracks
                throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                // Exception, weil der Zug nicht platziert werden kann
            }

            requiredTracks.add(currentTrack); // FÜGE EN HINZU WO MAN GERADE DRAUF IST
            CartesianPoint passed = currentTrack.getPassedPoint(dir);


            length -= position.distanceTo(passed);

            if (currentTrack == startTrack) {
                length--;
            }
            position = passed;

            if (currentTrack != null) {
                dir = currentTrack.getDirectionTo(passed);
                if (getConnection(passed, currentTrack) == null) {
                    // Exception
                }

                currentTrack = getConnection(passed, currentTrack);

                if (getConnection(passed, currentTrack) == null) {
                    throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                }

            }
        }

1. dir muss nach currentTrack = getConnection(passed, currentTrack); berechnet werden
2. ersetze if (currentTrack != null) durch if (length > 0)
 
1. dir muss nach currentTrack = getConnection(passed, currentTrack); berechnet werden
2. ersetze if (currentTrack != null) durch if (length > 0)
Jetzt gibt er mir nur noch true zurück. Ich verstehe es nicht. Was stimmt daran nicht. @mihe7 hast du noch eine Idee
Java:
while (length > 0) {

            if (currentTrack == null || requiredTracks.contains(currentTrack)) {
                // Länge zu groß für die Anzahl der Tracks
                throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                // Exception, weil der Zug nicht platziert werden kann
            }

            requiredTracks.add(currentTrack); //
            CartesianPoint passed = currentTrack.getPassedPoint(dir); // Verbidnugspunkt zweier Gleise, wo man
                                                                      // vorbeigefahren ist

            length -= position.distanceTo(passed);//

            if (currentTrack == startTrack) {
                length--;
            }
            position = passed;

            if (length > 0) {
                if (getConnection(passed, currentTrack) == null) {
                    throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                }

                currentTrack = getConnection(passed, currentTrack);
                dir = currentTrack.getDirectionTo(passed);

                if (getConnection(passed, currentTrack) == null) { //
                    throw new NoObjectWithCharacteristicsException("such a train can't be placed");
                }

            }
        }
 
Ich verstehe es nicht. Was stimmt daran nicht. @mihe7 hast du noch eine Idee
Du musst wie @DagobertDuck mit dem Debugger herausfinden, wo das Problem liegt. So etwas ist sehr schnell gefunden: Breakpoint setzen, Schritt für Schritt durchgehen (Methoden erstmal mit Step-Over), Variablen mit den erwarteten Werten vergleichen. Wenn eine Methode was falsches zurückliefert, Breakpoint setzen, Spaß wiederholen, dann in die Methode per Step-In gehen usw.
 
Das war meine Frage ganz am Anfang, ob es Sinn macht, die Züge in einer Map<Point, Track> abzulegen. Hier ist deine Antwort darauf #114. Was sollte ich denn als Key nehmen. Oder reicht eine Liste bereits völlig aus?
 
Zuletzt bearbeitet:
@mihe7 Ich habe irgendwie Probleme mit folgender If-Abfrage
Java:
if (track.getSwitchedTo() != point)
Es funktioniert alles super. Wenn allerdings track.getSwitchedTo() = (5,1) und point = (5,1) liefert, wird trotzdem in den Rumpf der Anweisung gegangen... Woran liegt das?
Screenshot 2020-02-28 at 17.37.56.png
Auch der Versuch dies mit equals() zu überprüfen ist kläglich gescheitert:
Java:
if (!track.getSwitchedTo().equals(point))
Hier bekomme ich dann eine NPE, wenn getSwitchedTo() noch null ist und die Weiche eingestellt werden soll.

Der Sinn dieser Abfrage ist einfach, dass ich schauen möchte, ob die Weiche bereits auf den eingegebenen Punkt gesetzt ist.
 
Also, ich bin soweit. Die Methode klappt soweit, jedoch failed die an einem ganz komischen Punkt.
Wenn ich zwei Tracks habe
Code:
   -------

A----B-----C
dann klappt die Methode. Aber wenn der Zug auf dem Gleis, wo der Kopf vom Zug steht zu lang ist wie hier:

Code:
--------
    A-----B-----C
dann reagiert die Methode getRequiredTracks nicht und es wird gar keine Exception geworfen und es klappt alles, obwohl es nicht sein dürfte. Es wird also ein true zurückgegeben von putTrain() @mihe7 @DagobertDuck habt ihr eine Idee?
 
@mihe7 Mir ist gerade noch ein Fehler beim Entfernen einer Track aufgefallen.
Dein Code war ja wie folgt:
Java:
        edges.computeIfAbsent(track.getStartPoint(), x -> new ArrayList<>()).remove(track);
        track.getEndPoints().forEach(p -> edges.computeIfAbsent(p, x -> new ArrayList<>()).remove(track));
Dabei passiert allerdings das hier:
Screenshot 2020-02-28 at 18.39.52.png
Es werden also irgendwie nicht alle nötigen Punkte entfernt. Ich habe schon versucht über die Punkte zu iterieren, wodurch allerdings andere Fälle "zerstört" wurden. Wo liegt hier der Fehler?

PS: Bitte nicht #297 übersehen.
 

Zurück
Oben