Methoden Methoden anpassen und fehlende Funktionen hinzufügen

@mihe7 Nachdem ich ein paar Testfälle durchgegangen bin, kann ich sagen, dass meine putTrain Methode jetzt so wie erwartet funktioniert. Nichtsdestotrotz würde ich dich gerne noch mal über meinen Code drüberschauen lassen. Könntest du mir dafür die Rechte geben, dein Profil zu sehen?
Ich gehe mal davon aus, dass du hier absichtlich nicht drauf eingegangen bist ^^ (?).

Nein. Die Kollisionsbehandlung darf nicht je Zug (EDIT: je Schritt eines Zuges natürlich) erfolgen.
OK. Sie muss also nach den angegebenen n-Schritten erfolgen, d. h. ganz zum Schluss.

Java:
    public void step(short speed) {
        ...
        for (int i = 0 i < speed; i++) {
            for (Train train : trainsOnTrack) {
                singleStep(train, getTracksByTrain(train));
            }
        }
        collissionHandling(...);
    }
Wie schaffe ich es, die Argumente dann am besten zu übergeben? Soll der Rückgabewert von singleStep() nicht mehr void sein. Falls ja, welchen Rückgabewert muss ich stattdessen verwenden? Ich brauche für die Kollisionsbehandlung im Grunde genommen ja 2 Attribute: train und rAkt, oder nicht?
 
Es geht darum, dass die Methode
nicht berücksichtigt, dass point ein Punkt sein kann, der zwei Gleise miteinander verbindet. Die Methode braucht also noch die Richtung des Zuges, um ggf. das richtige Gleis auswählen zu können - und natürlich den Code, der sich darum kümmert.

D. h. WENN point Schlüssel von edges ist, DANN muss das richtige Gleis anhand der Richtung gewählt werden, SONST muss der Punkt über die Werte von edges (also alle Tracks) gesucht werden.
Ich habe mich vertan. Ist diese dann auf Basis von findTracks() zu realisieren?
Ich gehe stark davon aus. Aber wie um Himmels Willen soll ich hier den Richtungsvektor ins Spiel bringen???
Es müsset dann ungefähr so aussehen, oder nicht?
Java:
    private Track findTrack(Point point, Point direction) {
        //Wie packe ich nun den Richtiungsvektor in die Prüfung nach
        //dem richtigen Track?
        for (Track track : tracks.values()) {
            if (track.isPassable(point)) {
                return track;
            }
        }
        return null;
    }
 
Nein, ich habe noch eine Fallunterscheidung vorgenommen.
Java:
        if (edges.containsKey(point)) {
            // Find track by direction
            ...
        } else {
            // Find point over values of edges (all tracks)
            ...
        }
        return null;

EDIT: Ups, ich glaube das versucht du gerade so zu implementieren, oder?
 
Ich gehe mal davon aus, dass du hier absichtlich nicht drauf eingegangen bist ^^ (?).


OK. Sie muss also nach den angegebenen n-Schritten erfolgen, d. h. ganz zum Schluss.

Java:
    public void step(short speed) {
        ...
        for (int i = 0 i < speed; i++) {
            for (Train train : trainsOnTrack) {
                singleStep(train, getTracksByTrain(train));
            }
        }
        collissionHandling(...);
    }
Wie schaffe ich es, die Argumente dann am besten zu übergeben? Soll der Rückgabewert von singleStep() nicht mehr void sein. Falls ja, welchen Rückgabewert muss ich stattdessen verwenden? Ich brauche für die Kollisionsbehandlung im Grunde genommen ja 2 Attribute: train und rAkt, oder nicht?
Oder sollte ich rAkt als private Attribut in der Klasse speichern?
 
Wenn ich es richtig sehe, müsst ihr mit dem aktuellen Modell:
1. Neue Positionen und Richtungen der Züge nach Modell A berechnen.
2. Für alle Ergebnisse aus 1. die requiredTracks nach Modell A ermitteln
3. Kollisionen feststellen, Züge entfernen
4. Züge tatsächlich bewegen
Ich verstehe nicht ganz, wie ich in 1. die Positionen und Richtungen berechnen soll, ohne sie direkt auf die Züge anzuwenden? Wie kann ich mir diese Informationen zwischenspeichern?
 
Ich gehe mal davon aus, dass du hier absichtlich nicht drauf eingegangen bist ^^ (?).
Richtig. Zeitmangel.

Es müsset dann ungefähr so aussehen, oder nicht?
Irgendwie wirst Du die Richtung ja übergeben müssen...

Ich gehe stark davon aus. Aber wie um Himmels Willen soll ich hier den Richtungsvektor ins Spiel bringen???
Ich weiß nicht, ob es Sinn der Sache ist, dass ich Euch für jedes Problem die Lösung in die Hand drücke.

Der Code in findTrack funktioniert doch, wenn point nicht auf einem Endpunkt liegt. Es geht also nur um ein kleine Erweiterung am Anfang der Methode. Du muss lediglich zu prüfen, ob point auf einem Endpunkt liegt und dann verschiebst point eben um einen Schritt in die entgegengesetzte Fahrtrichtung. Danach kannst Du den Code wie bisher laufen lassen.

Code:
A-----B-----C Tracks ohne Lok
+----->-----+ Tracks mit point auf Endpunkt B = Endpunkt von A-B und B-C
+---->+-----+ point entgegen Fahrtrichtung verschoben -> jetzt Eindeutig A-B

umgekehrter Fall:
+-----<-----+ Tracks mit point auf Endpunkt B = Endpunkt von A-B und B-C
+-----+<----+ point entgegen Fahrtrichtung verschoben -> jetzt Eindeutig B-C
 
Wäre super, wenn du mir den Aufbau grob erklären könntest. Den Code dazu werde ich schon selbst schreiben. Wenn ich keine Setter benutzen soll, wie mache ich es denn dann? Ich muss ja die Position und die Richtung für jeden Zug irgendwie speichern.
 
OK, das habe ich jetzt getan. Das funktioniert auch soweit. Was ist jetzt im 4. Schritt zu tun? Sollen hier dann tatsächlich die Setter von Train benutzt werden?

Nachdem alle Züge nun erfolgreich bewegt wurden, muss nun also noch geprüft werden, ob sie dasselbe Gleis belegen, wobei die Start und Endpunkte auch berücksichtigt werden müssen. Ist die folgende Methode also noch anwendbar?
Derzeit zieht meine Kollisionsbehandlung folgendermaßen aus:
Java:
    private void collisionHandling(Train train, List<Track> rAkt)  {
        List<Track> rNeu = getTracksByTrain(train);
        // Entferne Zug von jedem Track, der in rAkt vorhanden, in rNeu nicht vorhanden ist.
        if (rAkt != null) {
            for (Track track : rAkt) {
                if (rNeu != null && !rNeu.contains(track)) {
                      // TODO: Is this correct?
                      track.setCurrentTrain(null);
                }
            }
        }
        // Setze Zug auf jeden Track, der in rNeu vorhanden, in rAkt nicht vorhanden ist.
        if (rNeu != null) {
            for (Track track : rNeu) {
                if (rAkt != null && !rAkt.contains(track)) {
                    if (track.getCurrentTrain() != null) {
                        // Remove train
                        getTracksByTrain(train).forEach(x -> x.setCurrentTrain(null));
                        // Remove track.getCurrentTrain()
                        getTracksByTrain(track.getCurrentTrain()).forEach(x -> x.setCurrentTrain(null));
                    }
                    // TODO: Is this correct?
                    track.setCurrentTrain(train);
                }
            }
        }
    }

Wobei mir hier noch unklar ist, was rAkt nach aktualisiertem Modell sein soll und, was mit "die Züge tatsächlich bewegen" exakt gemeint ist. Nach aktuellem Stand sind bei mir die Positionen und Richtungen der Züge in der Map<Train, MeineKlasse> gespeichert.
 
Zuletzt bearbeitet:
Was ist jetzt im 4. Schritt zu tun? Sollen hier dann tatsächlich die Setter von Train benutzt werden?
Selbstverständlich.

Derzeit zieht meine Kollisionsbehandlung folgendermaßen aus:
Und wo tauchen hier die requiredTracks aller Züge auf? (Schritt 2)

Die Idee ist doch klar: man berechnet, welche Tracks von den Zügen belegt würden, wenn sich diese um einen Schritt bewegt hätten. Kollisionen treten zwischen Zügen auf, die die gleichen Tracks benötigen.

Hat man die kollidierenden Züge ermittelt, kann man sie aus der Map<Train,Placement> (s.u) entfernen. In der Map verbleiben dann die restlichen Züge und ihre neuen Positionen/Richtungen, die abschließend gesetzt werden müssen.

Mal nebenbei: eine Klasse der Art
Java:
public class Placement {
    public final Point position;
    public final Point direction;

    ...
}
kann man auch wunderbar für ein Refactoring verwenden...
 
Selbstverständlich.
Alles klar. D. h. bei putTrain sollen auch die Setter vom Train benutzt werden und nicht die extra Klasse. In der separaten Klasse werden die Positon und die Richtung also nur zwischengespeichert.
Java:
    private void assignTrainToTracks(Train train, Point point, Point directionVector, List<Track> requiredTracks) {
        requiredTracks.forEach(required -> required.setCurrentTrain(train));
        trainsOnTrack.put(train, new Placement(point, directionVector));
    }
Ist dies für den putTrain Befehl so korrekt? Insbesondere bei der Zeile trainsOnTrack.put(...) bin ich mir unsicher, ob hier schon in die Klasse gespeichert werden soll, oder ob sie tatsächlich lediglich nur für den Zwsichenspeicher beim step Befehl verwendet werden soll. Dann bräuchte ich ja eine Liste List<Train> und eine Map<Train, Placement> (?).

Und wo tauchen hier die requiredTracks aller Züge auf? (Schritt 2)
Das wäre bei mir doch die Liste rNeu, oder nicht?
 
Alles klar. D. h. bei putTrain sollen auch die Setter vom Train benutzt werden
Warum fängst Du jetzt mit putTrain an?!? Wir sind beim Bewegen der Züge.

Das wäre bei mir doch die Liste rNeu, oder nicht?
Nein. Mit der Methode machst Du nichts anderes als vorher auch.

In der separaten Klasse werden die Positon und die Richtung also nur zwischengespeichert.
Die Klasse stellt Position und Richtung dar. Ob Du Objekte der Klasse nur als Zwischenspeicher verwendest, oder z. B. auch Parameter und Variablen (z. B. in Train) auf die Klasse umstellst, bleibt Dir überlassen.
 
Oh je, also irgendwie hat mich das jetzt noch mehr verwirrt. Ist meine derzeitige Methode zur Kollisionsbehandlung soweit korrekt? Was soll rAkt und rNeu konkret sein?

Warum fängst Du jetzt mit putTrain an?!? Wir sind beim Bewegen der Züge.
Naja, weil mir unklar ist, wann jetzt genau die Setter von Train benutzt werden sollen und wann die Position/Richtung in der separaten Klasse gespeichert werden sollen. Außerdem habe ich an dieser Stell vorher mit den Settern die Richtung/Position des Zuges festgelegt. Daher dachte ich, dass ich das jetzt in die Klasse umleiten muss. Die Trennung zwischen Setter und Klasse ist mir noch nicht klar.

rNeu ist ja:
Java:
List<Track> rNeu = getTracksByTrain(train);
wobei
Java:
    private List<Track> getTracksByTrain(Train train) {
        Point position = trainsOnTrack.get(train).getPosition();
        Point direction = trainsOnTrack.get(train).getDirection();
        Track track = findTrack(position, direction);
        return getRequiredTracks(track, position, direction, train.getLength());
    }
Ich habe diese Methode also auch auf die separate Klasse angepasst. trainsOnTrack ist Map<Train, Placement>. Vorher war es eine List<Train>.

Die Aufgabe nimmt kein Ende...
 
Die Aufgabe sollte sich auch bald dem Ende neigen. Daher wäre ich dir sehr verbunden, wenn du im Laufe der nächsten Tage privat einmal über meine (scheinbar) richtig funktionierende putTrain Methode schauen könntest. Das sollte ja nicht allzu viel Zeit in Anspruch nehmen.
 
Ist meine derzeitige Methode zur Kollisionsbehandlung soweit korrekt?
Nein.

Was soll rAkt und rNeu konkret sein?
Genau das wäre die Frage an Dich. Was willst Du damit erreichen?

Naja, weil mir unklar ist, wann jetzt genau die Setter von Train benutzt werden sollen und wann die Position/Richtung in der separaten Klasse gespeichert werden sollen.
Wir sind doch jetzt beim Bewegen von Zügen, da hat doch das Aufgleisen (putTrain) nichts mehr damit zu tun.

Nochmal: Du sollst Dich ja um die Bewegung der Züge kümmern. Dazu kannst Du die vier Schritte durchführen
1. Neue Positionen und Richtungen der Züge nach Modell A berechnen.
2. Für alle Ergebnisse aus 1. die requiredTracks nach Modell A ermitteln
3. Kollisionen feststellen, Züge entfernen
4. Züge tatsächlich bewegen
ohne Änderungen am existierenden Modell vornehmen zu müssen.

Hintergrund ist, dass es das aktuelle Modell nicht zulässt, mehrere Züge auf einem Gleis zu haben. Wäre dies der Fall, könntest Du zuerst alle Züge bewegen, dann die Kollisionen ermitteln und die Züge entfernen. Vielleicht solltest Du diesen Weg gehen, der ist m. E. nämlich wesentlich einfacher.

Ansonsten muss die Reihenfolge entsprechend umgekehrt werden: zuerst Kollisionen ermitteln (nach fiktiver Bewegung) und Züge entfernen, dann alle Züge bewegen (tatsächliche Bewegung). Die vier Schritte sind einfach ein Vorschlag dazu.
 
OK. Soll es denn dann jetzt eine List<Train> und eine Map<Train, Placement> geben?? Die neue Implementierung der neuen Klasse hat mich durcheinander gebracht.
ohne Änderungen am existierenden Modell vornehmen zu müssen
Ich habe vorher an der putTrain Methode und somit am existierenden Modell ja schon einiges ändern müssen, damit es Modell 2B entspricht.
 
@mihe7 Könntest du Dich bei mir auch privat melden, denn ich verzweifle momentan mit der exakt gleichen Methode... Oder gegebenenfalls der Konversation beifügen...
 

Zurück
Oben