diff --git a/Fahrstrassen.lua b/Fahrstrassen.lua new file mode 100644 index 0000000..f898f94 --- /dev/null +++ b/Fahrstrassen.lua @@ -0,0 +1,137 @@ +require("kskit\\Serializer") +require("kskit\\On") + +local Anmeldungen={} +local Dirty=false + +local function IstIn(Tabelle, Wert) + for _, v in ipairs(Tabelle) do + if v == Wert then return true end + end + return false +end + +function FahrstrassenMelden(...) + +end + +function FahrstrassenInit(Slot) + Anmeldungen = ladeTabelle(Slot) or {} + Main(function() + -- Anmeldungen abarbeiten + for Zugname, Anmeldung in pairs(Anmeldungen) do + -- Freigefahrene Fahrstrassen aus Belegtliste entfernen + while Anmeldung[3][1] and EEPGetSignal(Anmeldung[3][1]) == 1 do + table.remove(Anmeldung[3], 1) + Dirty=true + end + + -- Haben wir es im letzten Zyklus zu schalten versucht und ist jetzt etwas eingestellt? + if Anmeldung[2] > 0 and EEPGetSignal(Anmeldung[2]) > 1 then + local FStartIst=Anmeldung[2] + local FZielIst=EEPGetSignal(FStartIst)-1 + local FStartSoll=table.remove(Anmeldung[1], 1) + local FZielSoll=table.remove(Anmeldung[1], 1) + -- Erfolg vermelden! + FahrstrassenMelden("Fahrt ",Zugname," ueber ",serialize{FStartIst,FZielIst}) + if FStartIst ~= FStartSoll or FZielIst ~= FZielSoll then + -- Was ist hier passiert. Wir haben gerade eine Fahrstrasse geschaltet, die nicht gefordert war. + -- Das kann passieren, wenn eine wiederholte Anmeldung kurz vor uns das Fahrstrassenziel umgestellt hat + FahrstrassenMelden("Fehlschlag Schalten ",Zugname," an ",serialize(Anmeldung[1]),": alternative Fahrstrasse bereits geschaltet") + -- Die Anmeldung passt jetzt nicht mehr, weil wir fahren ja schon woanders hin + Anmeldung[1]={} + end + Anmeldung[2]=0 + -- Fahrstrassen Startsignal als belegt (durch uns) markieren + table.insert(Anmeldung[3], FStartIst) + Dirty=true + end + + -- Prüfung, das es den Zug überhaupt noch gibt + -- Das passiert nachdem wir das Fahrstrassensignal auf erfolgreiche Schaltung geprüft haben + -- War sie erfolgreich und der Zug ist jetzt weg, ist sie in der Belegtliste schon drin + local ok, Speed = EEPGetTrainSpeed(Zugname) + if not ok then + Anmeldungen[Zugname]=nil + Dirty=true + -- Durch den Zug belegte Fahrstrassen auflösen + for _, FStart in ipairs(Anmeldung[3]) do + if EEPGetSignal(FStart) > 1 then + EEPSetSignal(FStart, 1, 1) + FahrstrassenMelden("FS ",FStart," hilfsweise aufgeloest, ",Zugname," verschollen") + end + end + -- Abbrechen, wir brauchen für den Zug nix mehr zu schalten + break + end + + -- Wenn noch eine Anmeldung vorhanden und FS-Signal aufgelöst ist, dann versuchen wir zu schalten + local FSignal = 0 + if Anmeldung[1][1] and EEPGetSignal(Anmeldung[1][1]) == 1 then + FSignal=Anmeldung[1][1] + EEPSetSignal(FSignal, Anmeldung[1][2] + 1, 1) + end + -- Und uns merken, das wir einen Schaltversuch unternommen haben + -- In FSignal steht noch eine 0 drin, falls die FS noch durch anderen Zug geschaltet ist + if Anmeldung[2] ~= FSignal then Dirty = true end + Anmeldung[2]=FSignal + + -- Wenn wir alles abgearbeitet haben, können wir den Zug auch vergessen + if #Anmeldung[1]==0 and #Anmeldung[3]==0 then + Anmeldungen[Zugname]=nil + Dirty=true + end + end + + -- Hat sich was geändert? Anmeldungen wegspeichern! + if Dirty then + speicherTabelle(Slot, Anmeldungen) + Dirty=false + end + end) +end + +function FahrstrassenDebug() + r="" + for Zugname, Anmeldung in pairs(Anmeldungen) do + r=r..Zugname..":Angemeldet="..serialize(Anmeldung[1])..",InArbeit="..serialize(Anmeldung[2])..",Geschaltet="..serialize(Anmeldung[3]).."\n" + end + return r +end + +function FS(Zugname, ...) + local Route = {...} + if #Route % 2 ~= 0 then + error("FS() hat immer eine ungerade Anzahl von Argumenten") + end + if Anmeldungen[Zugname] == nil then + Anmeldungen[Zugname] = {{},0,{}} + end + local Anmeldung = Anmeldungen[Zugname] + while Route[1] do + -- Ist die Anmeldung noch nicht Teil unserer belegtliste, alles ok und weitermachen + if not IstIn(Anmeldung[3], Route[1]) then + break + end + -- Die Fahrstrasse ist bereits geschalten, mist! + -- Ist sie in der richtigen Stellung? + if Route[2] == EEPGetSignal(Route[1]) - 1 then + -- Ja! Alles gut. Dieser Teil der Anmeldung wird ignoriert + FahrstrassenMelden("Anmeldung ",Zugname," an ",serialize{Route[1],Route[2]}," wiederholt") + table.remove(Route, 1) + table.remove(Route, 1) + else + -- Wenn das Ziel auch noch falsch ist, komplette Anmeldung verwerfen, wir fahren jetzt schon woanders hin + FahrstrassenMelden("Fehlschlag ",Zugname," an ",serialize(Route),": alternative Fahrstrasse bereits geschaltet") + return + end + end + + -- Wenn von unserer Anmeldung jetzt nix mehr übrig ist, brauchen wir auch nichts zu machen + if #Route == 0 then return end + + -- Anmeldung durchführen + FahrstrassenMelden("Anmeldung ",Zugname," an ",serialize(Route)) + Anmeldung[1]=Route + Dirty = true +end