Jump to content

Empfohlene Beiträge

Geschrieben

Hallo zusammen,

 

in einem Schattenbahnhof fahren die Züge je nach Typ in unterschiedliche Richtungen. Die richtige Strecke wird aus einer Liste ausgelesen.

Es kann aber immer mal passieren, dass eine Strecke aktiviert wird, obwohl dort gerade kein Zug steht.

Wenn ich die nicht belegten Gleise aus der Liste streiche bzw. neu belegte wieder eintrage, könnte ich die Liste dynamisch halten.

Dazu müsste ich aber wissen, wieviele Strecken gerade in der Liste vorhanden sind.

Frage: Wie kann ich die aktuelle Anzahl der Listeneinträge aus einer Liste auslesen?

 

Test_Liste.mbp

Geschrieben

Hallo Guenter,
in der grafischen EV wüsste ich keine einfache Möglichkeit, um die Anzahl der Elemente aus einer Liste zu verwenden.
(außer in einer Bedingung)

Aber in Lua kannst du dem Namen einer Liste das # Zeichen voranstellen um die Anzahl der Elemente als Zahl zu bekommen:

local t = $("Ereignisse").variables["Liste_Harfe"]
$("Ereignisse").variables["Belegte_Gleise"] = #t

Den Umweg über die lokale Variable t habe ich hier nur gewählt, damit man in der zweiten Zeile das # besser wahrnehmen kann.

Viele Grüße
Götz 

Geschrieben (bearbeitet)

Hallo,

vor 4 Stunden schrieb Goetz:

in der grafischen EV wüsste ich keine einfache Möglichkeit, um die Anzahl der Elemente aus einer Liste zu verwenden

es geht auch mit der grafischen EV:

Anzahl-Bestimmung.thumb.jpg.afe767eeb86cc26f5413a64adf9d8ef5.jpg

Anzahl-Bestimmung.mbp

In dieser Beispiel-Anlage habe ich zwar die Anzahl von Fahrzeugen in einem Zugverband bestimmt (lässt sich einfacher am Beispiel zeigen), man kann die Zähler-Variable aber auch in einer Wiederholungsschleife "Für alle Elemente in einer Liste" entsprechend hochsetzen.

Viele Grüße
BahnLand

Bearbeitet von BahnLand
Geschrieben (bearbeitet)

Erstmal vielen Dank für die schnellen Rückmeldungen.

 

Leider hilft mir beides nicht weiter. Mit Lua kenne ich mich gar nicht aus. Die zweite Lösung habe ich zwar verstanden, aber den Bogen zu meiner Liste bekomme ich dennoch nicht hin. Es gibt für mich die Lösung, ein und ausfahrende Züge zu zählen. Die Summe ist dann gleich der Anzahl belegter Gleise in der Liste, aber eigentlich ist das nicht der richtige Weg. Man sollte die Elemente der Liste direkt zählen, und nicht indirekt verfahren. Aber wenn es nicht geht ...

 

Vielen Dank

Bearbeitet von guenter.strickmann
Geschrieben (bearbeitet)
vor 24 Minuten schrieb guenter.strickmann:

aber den Bogen zu meiner Liste bekomme ich dennoch nicht hin.

Du musst doch nur die Wiederholung auf "Wiederholung für alle Elemente einer Liste" ändern.
Der Rest ist exakt das, was du benötigst.

Listenelementezhlen.jpg.c290d5e969c383f3f45822f878147234.jpg

 

deine Anlage mit Zähler nach Bahnlands Prinzip:

Test_Liste mit Wiederholung.mbp

Viele Grüße
Götz

Bearbeitet von Goetz
Ergänzungen
Geschrieben

Nochmal vielen Dank für die Geduld. Ich habe den Code jetzt am Laufen. Aber die Wiederholung funktioniert nicht so, wie sie soll. Über die Wiederholung "Elemente einer Liste" wird nicht die ganze Liste gezählt, sondern immer nur bis zu dem Gleis, auf dem die Lok ausfährt. Alle Gleise jenseits davon, werden nicht mitgezählt. Entweder, es gibt doch noch einen Kniff, wie man dieses Problem umgehen kann, oder ich mache es doch mit dem Zählen der Loks. Aber eigentlich ist die Listenlösung die elegantere und richtigere.

Test_Liste.mbp

Geschrieben

So, jetzt funktioniert es mit Lua, auch wenn ich nur eine ungefähre Vorstellung habe, was das Script macht. Lua ist nicht meine Welt.

Trotzdem geht es so nicht, weil ich einen gedanklichen Fehler habe. Der Name der Listeneinträge ist der Index. Aus Access VBA kenne ich das anders. Wenn ich also ein Gleis aus der Liste rausnehme, fällt mit dem Namen die Indexnummer weg. Über die Luafunktion ermittele ich die Anzahl der Indexeinträge, z. B. 6. Wenn aber der Eintrag mit der Nummer 6 fehlt, läuft die Aktivierung des Gleises trotzdem ins Leere. So bräuchte man eigentlich eine zweite Liste. Einmal mit einem dynamischen Index, der immer wieder fortlaufend von 1 bis zur Anzahl der belegten Gleise neu geschrieben wird. Auf der anderen Seite dann die Indexnummer aus der eigentlichen Liste, die dann mit den belegten Gleisen verknüpft ist.

Grunsätzlich will ich folgendes erreichen. In einem Schattenbahnhof sind nie alle Gleise belegt. Wenn ein Zug nun einfährt, soll er per Zufall veranlassen, dass ein Zug aus dem Bahnhof wieder ausfährt. Das klappt eben nur, wenn man weiß, welche Gleise belegt sind. Ansonsten könnte es passieren, dass ein nicht belegtes Gleis geöffnet wird und natürlich dann kein Zug ausfährt. Das wäre sehr misslich.

Gibt es hierfür eventuell auch einen anderen einfachen Ansatz? Eine Möglichkeit gäbe es, indem man im Vorfeld die Güter- und Personenzüge in zwei unterschiedliche Schattenbahnhöfe steuert und die dortigen Gleise dann mit Zügen "vollpackt". Dann würde es immer gehen. Aber eigentlich wollte ich das nicht.

Test_Liste.mbp

Geschrieben
vor einer Stunde schrieb guenter.strickmann:

wird nicht die ganze Liste gezählt, sondern immer nur bis zu dem Gleis, auf dem die Lok ausfährt

Das liegt dran, dass Du hier

2024-12-1320_04_48-3DTrainStudioV9.jpg.fcc05478562b251a6f26982750c8eb5f.jpg

ein Element aus der Liste herausschießt und diese danach nicht mehr lückenlos ist, z.B. fehlt hier im Beispiel Element 2:

2024-12-1320_06_51-3DTrainStudioV9.jpg.d356d853a199d86797e136c276e928b4.jpg

Wenn wir jetzt die Liste mit for und ipairs() (Graphisch: "Wiederholung") durchlaufen, bricht die Aufzählung bereits nach dem ersten Element ab. Das ist ein Verhalten von Lua, das man wissen muss.

Beste Grüße

Phrontistes

Geschrieben (bearbeitet)
vor 24 Minuten schrieb guenter.strickmann:

Gibt es hierfür eventuell auch einen anderen einfachen Ansatz?

Ob einfacher weiß ich nicht. Ich habe einen wesentlich komplexeren Schattenbahnhof konstruiert bei dem ich alle Kontakte der Ausfahrsignale durchgehe und, wenn belegt, diese in eine temporäre Liste schreibe, aus der ich dann ein Element auswürfle und dort den Zug starte. Hier das Codefragment:

local TempTrack = 0
local TempIndexNote = 0
local TempList = {}
local TempListZZ = 0

-- Da kommt vorher noch eine Auswahl durch gezielten EV-Aufruf oder durch Schalter 

if TempTrack == 0 then
  -- No train selected yet. Get random train
  TempIndexNote = 0
  local t = FYOS.variables["Sigs"] -- Liste aller Signalkontakte der Ausfahrsignale
  for i, Iter in ipairs(t) do
    if not (Iter == $("")) then
      TempIndexNote = TempIndexNote + 1
      if (#layout:getVehiclesOn(Iter) > 0) and (Iter.state == 0) then
        TempListZZ = TempListZZ + 1
        TempList[TempListZZ] = TempIndexNote
      end
    end
  end
end

if #TempList > 0 then
  TempTrack = TempList[math.random(1, #TempList)]
end

if TempTrack > 0 then
  -- Zug starten wie auch immer
end

 

vor 24 Minuten schrieb guenter.strickmann:

So bräuchte man eigentlich eine zweite Liste.

Ja, die braucht man. In meinem Beispiel heißt sie TempList.

Beste Grüße

Phrontistes

Nachtrag: Das Obige könnte man auch graphisch machen. Wenn Du Access VBA kennst, müsstest Du ja lesen können, was passiert.

Bearbeitet von Phrontistes
Nachtrag
Geschrieben

Nur noch ein kleiner Hinweis, nachdem Du mit Lua angefangen hast:

#Belegte_Gleise

gibt die Anzahl der Listenelemente zurück ohne dass Du die Wiederholung brauchst. Das ändert aber nichts daran, dass hier "1" zurückgeben wird, wenn das Element mit Index "2" nicht (mehr) existiert wie in meinem obigen Beispiel.

Geschrieben (bearbeitet)

Aus VBA heraus hatte ich das schon als m:n Verbindung gesehen und vermutet, dass es nicht so einfach wird. Wenn ich jetzt deinen Code sehe und weiß, dass das nicht so einfach ist, mache ich zwei Schattenbahnhöfe und trenne die Züge. :( Für die Programmierung müsste ich erstmal grundlegend in die Materie einsteigen.

Trotzdem vielen Dank für die Mühe. Die EV kann viel, aber kommt dann an die Grenzen.

Bearbeitet von guenter.strickmann
Geschrieben (bearbeitet)

Vielleicht als kleiner Trost: Lua ist die hässlichste und nervigste Sprache, die ich kenne und habe eine Weile gebraucht, mich daran zu gewöhnen. Aber meckern nutzt nichts. Wenn man ein paar Eigenheiten mal drauf hat, ist es nicht so schwer. Und man kann einiges mehr machen als in der graphischen EV (die ja auch "nur" ein Lua-Codegenerator ist).

Bearbeitet von Phrontistes
typo
Geschrieben (bearbeitet)
vor 3 Stunden schrieb guenter.strickmann:

Gibt es hierfür eventuell auch einen anderen einfachen Ansatz?

Ja, da hätte ich einen Vorschlag:

SbfVerwaltunggrafischnummeriert.thumb.jpg.f0a6a64a4d1d16513ae298829434154d.jpg

Anstatt die Liste zu verändern, würde ich sie neu aufbauen.
Wenn ein Zug das Harfensignal betritt ...

  1. überschreibe die alte "Liste_Harfe" mit einer neuen, leeren "Liste_Harfe"
  2. setze den "Belegte_Gleise" Zähler auf 0
  3. in einer Wiederholung für alle Harfensignale
  4. prüfe, ob ein Fahrzeug darauf steht
  5. falls ja, erhöhe den "Belegte_Gleise" Zähler um 1
  6. und speichere in der neuen "Liste_Harfe" unter dem Index "Belegte_Gleise" die Fahrstraße, welche du im Signal in der Variablen "Fahrstraße" hinterlegt hast
  7. warte (optional) einen Moment
  8. speichere in "Zufall" eine zufällige Zahl mit einem Wert zwischen 1 und "Belegte_Gleise"
  9. Aktiviere die Fahrstraße, welche in der neuen "Liste_Harfe" unter dem Index "Zufall" gespeichert ist

Die nun überflüssige Variable "Index" habe ich aus den Harfensignalen gelöscht und stattdessen in einer Variablen "Fahrstraße" die zugehörige Fahrstraße hinterlegt.

Test_Liste korrekt reduzieren.mbp

Beachte bitte auch, dass bei diesem Ansatz zwei deiner Ereignisse sowie die zweite Liste weggefallen sind.

Viele Grüße
Götz

Nachtrag: Das Prinzip ist im Kern das, was auch @Phrontistes beschrieben hat.
Und ich habe vergessen vor den Schritten 8 und 9 zu prüfen, ob die Liste mindestens 1 Eintrag enthält.
Ein leerer Sbf würde daher im Protokoll in Schritt 8 zu einer Fehlermeldung führen.

Bearbeitet von Goetz
Ergänzungen
Geschrieben (bearbeitet)
vor 13 Stunden schrieb guenter.strickmann:

Die [grafische] EV kann viel ...

aber eine Lua Lösung ist noch einfacher, weil man nur temporäre Variablen benötigt und auf Modulvariablen ganz verzichten kann:

local Liste_Harfe = {}                                           -- lege eine leere Liste an
local Sbf_Kontakte = layout:getEntitiesByKeyword("HarfenSignal") -- lege eine Liste mit allen Harfensignalen an

for i, Signal in ipairs(Sbf_Kontakte) do                         -- für alle Signale aus der Liste der Harfensignale
  if #layout:getVehiclesOn(Signal) > 0 then                      -- wenn auf dem Kontakt ein Fahrzeug steht
    table.insert(Liste_Harfe, Signal.variables["Fahrstraße"])    -- füge die Fahrstraße aus dem Signal zur Liste hinzu
  end
end

if #Liste_Harfe > 0 then                                         -- wenn die Liste nicht leer ist
  local Zufallszahl = math.random(1, #Liste_Harfe)               -- würfel eine Zahl zwischen 1 und der Anzahl Elemente
  Liste_Harfe[Zufallszahl].active = true                         -- und aktiviere die Fahrtraße von Listenplatz "Zufall"
end

 

Anlage mit obigem Skript:

Test_Liste Lua verwaltet.mbp

 

Für das Beispiel von @Phrontistes sowie auch meine beiden gilt:
Du kannst jederzeit einen Zug im Schattenbahnhof händisch aufgleisen oder entfernen.
Weil immer frisch geprüft wird, wo überall ein Zug steht, bringt das dieses System nicht aus dem Tritt.

Viele Grüße
Götz

Bearbeitet von Goetz
Schreibfehler korrigiert

Erstelle ein Benutzerkonto oder melde dich an, um zu kommentieren

Du musst ein Benutzerkonto besitzen, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen.

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde dich hier an.

Jetzt anmelden
×
×
  • Neu erstellen...