From 70ca9b813e6dabbef1a934be4affa06bcd4d94ce Mon Sep 17 00:00:00 2001
From: Quang Truong <truong.quang@scheidt-bachmann-st.de>
Date: Tue, 16 May 2023 16:09:17 +0200
Subject: [PATCH] Set#54: correction determination of track vacancy detection

dasb
---
 .../table/pt1/ssld/SsldTransformator.xtend    |  32 +--
 .../ppmodel/extensions/DwegExtensions.xtend   | 188 ++++++++++++++----
 2 files changed, 160 insertions(+), 60 deletions(-)

diff --git a/java/bundles/org.eclipse.set.feature.table.pt1/src/org/eclipse/set/feature/table/pt1/ssld/SsldTransformator.xtend b/java/bundles/org.eclipse.set.feature.table.pt1/src/org/eclipse/set/feature/table/pt1/ssld/SsldTransformator.xtend
index c2b40facc..ec7590a23 100644
--- a/java/bundles/org.eclipse.set.feature.table.pt1/src/org/eclipse/set/feature/table/pt1/ssld/SsldTransformator.xtend
+++ b/java/bundles/org.eclipse.set.feature.table.pt1/src/org/eclipse/set/feature/table/pt1/ssld/SsldTransformator.xtend
@@ -25,7 +25,6 @@ import org.eclipse.set.utils.table.TMFactory
 import static org.eclipse.set.feature.table.pt1.ssld.SsldColumns.*
 import static org.eclipse.set.toolboxmodel.Signale.ENUMSignalFunktion.*
 
-import static extension org.eclipse.set.ppmodel.extensions.BasisAttributExtensions.*
 import static extension org.eclipse.set.ppmodel.extensions.BereichObjektExtensions.*
 import static extension org.eclipse.set.ppmodel.extensions.DwegExtensions.*
 import static extension org.eclipse.set.ppmodel.extensions.FahrwegExtensions.*
@@ -60,31 +59,16 @@ class SsldTransformator extends AbstractPlanPro2TableModelTransformator {
 	}
 
 	def static String getFreigemeldetLaenge(TopGraph topGraph, Fstr_DWeg dweg) {
-		if (dweg.IDFMAAnlageFreimeldung === null) {
+		val fmas = dweg?.FMAs
+		if (fmas.empty) {
 			return ""
 		}
-
-		val fmaAnlagen = dweg?.fmaAnlageFreimeldung
-		if (fmaAnlagen.empty) {
-			return ""
-		}
-		if (fmaAnlagen.contains(null)) {
-			throw new IllegalArgumentException('''«dweg?.bezeichnung?.bezeichnungFstrDWeg?.wert» contains non-FMA-Anlagen within ID_FMA_Anlage''')
-		}
-		
-		val fstrFahrwegsZumSignal = dweg.container.fstrFahrweg.filter [
-			dweg.fstrFahrweg.start === start
-		]
-		val topDWeg = fstrFahrwegsZumSignal.map[bereichObjektTeilbereich].flatten.map[IDTOPKante].toList
-		val punktObjects = fmaAnlagen?.map[fmaGrenzen]?.flatten?.filter [
-			// Only consider FMA borders which are located on the DWeg
-			punktObjektTOPKante.map[IDTOPKante].exists[topDWeg.contains(it)]
-		]
-		val distance = punktObjects?.fold(Double.valueOf(0.0), [ Double current, Punkt_Objekt grenze |
-			Math.max(current,
-				getShortestPathLength(topGraph, dweg?.fstrFahrweg?.start,
-					grenze))
-		])
+		val distance = fmas?.fold(
+			Double.valueOf(0.0), [ Double current, Punkt_Objekt grenze |
+				Math.max(current,
+					getShortestPathLength(topGraph, dweg?.fstrFahrweg?.start,
+						grenze))
+			])
 		val roundedDistance = AgateRounding.roundDown(distance)
 		if (roundedDistance == 0.0)
 			throw new IllegalArgumentException("no path found")
diff --git a/java/bundles/org.eclipse.set.ppmodel.extensions/src/org/eclipse/set/ppmodel/extensions/DwegExtensions.xtend b/java/bundles/org.eclipse.set.ppmodel.extensions/src/org/eclipse/set/ppmodel/extensions/DwegExtensions.xtend
index 7b8dede97..10922ed26 100644
--- a/java/bundles/org.eclipse.set.ppmodel.extensions/src/org/eclipse/set/ppmodel/extensions/DwegExtensions.xtend
+++ b/java/bundles/org.eclipse.set.ppmodel.extensions/src/org/eclipse/set/ppmodel/extensions/DwegExtensions.xtend
@@ -8,50 +8,33 @@
  */
 package org.eclipse.set.ppmodel.extensions
 
+import java.util.LinkedList
+import java.util.List
+import java.util.Set
+import org.eclipse.set.toolboxmodel.Basisobjekte.Basis_Objekt
+import org.eclipse.set.toolboxmodel.Basisobjekte.Punkt_Objekt
 import org.eclipse.set.toolboxmodel.Fahrstrasse.Fstr_DWeg
 import org.eclipse.set.toolboxmodel.Fahrstrasse.Fstr_DWeg_W_Kr
 import org.eclipse.set.toolboxmodel.Fahrstrasse.Fstr_Fahrweg
 import org.eclipse.set.toolboxmodel.Fahrstrasse.Fstr_Zug_Rangier
 import org.eclipse.set.toolboxmodel.Fahrstrasse.Markanter_Punkt
+import org.eclipse.set.toolboxmodel.Geodaten.TOP_Kante
+import org.eclipse.set.toolboxmodel.Gleis.Gleis_Abschnitt
 import org.eclipse.set.toolboxmodel.Ortung.FMA_Anlage
-import java.util.LinkedList
-import java.util.List
+import org.eclipse.set.toolboxmodel.Weichen_und_Gleissperren.W_Kr_Gsp_Element
 
+import static extension org.eclipse.set.ppmodel.extensions.BereichObjektExtensions.*
 import static extension org.eclipse.set.ppmodel.extensions.FahrwegExtensions.*
-import java.util.Set
+import static extension org.eclipse.set.ppmodel.extensions.FmaAnlageExtensions.*
+import static extension org.eclipse.set.ppmodel.extensions.FstrDWegWKrExtensions.*
+import static extension org.eclipse.set.ppmodel.extensions.PunktObjektExtensions.*
+import static extension org.eclipse.set.ppmodel.extensions.WKrGspElementExtensions.*
 
 /**
  * Extensions for {@link Fstr_DWeg}.
  */
 class DwegExtensions extends BasisObjektExtensions {
 
-	/**
-	 * @param dweg this Durchrutschweg
-	 * 
-	 * @returns the Fahrweg
-	 */
-	def static Fstr_Fahrweg getFstrFahrweg(
-		Fstr_DWeg dweg
-	) {
-		return dweg.IDFstrFahrweg
-	}
-
-	/**
-	 * @param dweg this Durchrutschweg
-	 * 
-	 * @returns the Weichen/Kreuzungen-Zuordnungen
-	 */
-	def static List<Fstr_DWeg_W_Kr> zuordnungen(Fstr_DWeg dweg) {
-		val result = new LinkedList<Fstr_DWeg_W_Kr>
-		val zuordnungen = dweg.container.fstrDWegWKr
-		for (zuordnung : zuordnungen) {
-			if (zuordnung.IDFstrDWeg.identitaet?.wert == dweg.identitaet.wert) {
-				result.add(zuordnung)
-			}
-		}
-		return result
-	}
-
 	/**
 	 * @param dweg this Durchrutschweg
 	 * 
@@ -74,19 +57,21 @@ class DwegExtensions extends BasisObjektExtensions {
 	/**
 	 * @param dweg this Durchrutschweg
 	 * 
-	 * @returns the FMA Anlage Freimeldung set of this Durchrutschweg
+	 * @returns the Fahrweg
 	 */
-	def static Set<FMA_Anlage> getFmaAnlageFreimeldung(Fstr_DWeg dweg) {
-		return dweg.IDFMAAnlageFreimeldung.toSet
+	def static Fstr_Fahrweg getFstrFahrweg(
+		Fstr_DWeg dweg
+	) {
+		return dweg.IDFstrFahrweg
 	}
 
 	/**
 	 * @param dweg this Durchrutschweg
 	 * 
-	 * @returns the PZB Gefahrpunkt
+	 * @returns the FMA Anlage Freimeldung set of this Durchrutschweg
 	 */
-	def static Markanter_Punkt getPZBGefahrpunkt(Fstr_DWeg dweg) {
-		return dweg.IDPZBGefahrpunkt
+	def static Set<FMA_Anlage> getFmaAnlageFreimeldung(Fstr_DWeg dweg) {
+		return dweg?.IDFMAAnlageFreimeldung?.toSet
 	}
 
 	/**
@@ -100,4 +85,135 @@ class DwegExtensions extends BasisObjektExtensions {
 		val nameDweg = dweg.bezeichnung.bezeichnungFstrDWeg.wert
 		return '''«nameStartsignal» «nameDweg»'''
 	}
+
+	/**
+	 * @param dweg this Durchrutschweg
+	 * 
+	 * @returns the PZB Gefahrpunkt
+	 */
+	def static Markanter_Punkt getPZBGefahrpunkt(Fstr_DWeg dweg) {
+		return dweg.IDPZBGefahrpunkt
+	}
+
+	/**
+	 * @param dweg this Durchrutschweg
+	 * 
+	 * @returns the Weichen/Kreuzungen-Zuordnungen
+	 */
+	def static List<Fstr_DWeg_W_Kr> zuordnungen(Fstr_DWeg dweg) {
+		val result = new LinkedList<Fstr_DWeg_W_Kr>
+		val zuordnungen = dweg.container.fstrDWegWKr
+		for (zuordnung : zuordnungen) {
+			if (zuordnung.IDFstrDWeg.identitaet?.wert == dweg.identitaet.wert) {
+				result.add(zuordnung)
+			}
+		}
+		return result
+	}
+
+   /**
+    * Find FMA of this durchrutschweg
+    * @param dweg this Durchrutschweg
+    * @return the fma on this durchrutschweg, without fma on start signal
+    */
+	def static Set<Punkt_Objekt> getFMAs(Fstr_DWeg dweg) {
+		val fahrweg = dweg?.fstrFahrweg
+		val fmaAnlagen = dweg?.fmaAnlageFreimeldung
+		if (fmaAnlagen.empty || fmaAnlagen === null) {
+			return emptySet
+		}
+
+		if (fmaAnlagen.contains(null)) {
+			throw new IllegalArgumentException('''«dweg?.bezeichnung?.bezeichnungFstrDWeg?.wert» contains non-FMA-Anlagen within ID_FMA_Anlage''')
+		}
+
+		val fmaGrenzens = fmaAnlagen.map[fmaGrenzen].flatten.toSet
+		val topFahrWeg = fahrweg?.topKanten
+		val startSignal = fahrweg?.start
+
+		// 1. Fall: start signal and end fma stay on same TOP_Kante
+		val fmaOnFahrweg = fmaGrenzens?.filter [
+			topKanten.exists[topFahrWeg.contains(it)]
+		].filter [ fma |
+			// Filter fma at start signal
+			fma.singlePoints.exists [
+				!startSignal.singlePoints.map[abstand.wert].contains(
+					abstand.wert)
+			]
+		].toSet
+
+		if (!fmaOnFahrweg.empty) {
+			return fmaOnFahrweg
+		}
+		// 2. Fall: start signal and end fma stay on two different TOP_Kante
+		return dweg.fmaOnAnotherTOPKante(fmaGrenzens)
+	}
+
+	def private static Set<Punkt_Objekt> fmaOnAnotherTOPKante(Fstr_DWeg dweg,
+		Set<Punkt_Objekt> fmaGrenzens) {
+		val fahrweg = dweg?.fstrFahrweg
+		val topFahrWeg = fahrweg?.topKanten
+		val startSignal = fahrweg?.start
+		val topEndFahrweg = fahrweg?.zielPunktObjekt?.topKanten
+		
+		// When slip way run over a track switch
+		val dwegGspElement = dweg?.zuordnungen?.map[WKrGspElement]
+		if (!dwegGspElement.empty) {
+			// 1. Fall: start from leg of track switch
+			if (startSignal.topKanten.exists [
+				dwegGspElement.map[#[topKanteL, topKanteR]].flatten.contains(it)
+			]) {
+				return fmaGrenzens.filter [
+					topKanten.exists [
+						topEndFahrweg.contains(it)
+					]
+				].filterNull.toSet
+			}
+
+			// 2. Fall: start from top of track switch and this switch is a combined switch
+			val connectionGsp = dwegGspElement.map [
+				val gzL = weicheElement?.GZFreimeldungL?.element
+				val gzR = weicheElement?.GZFreimeldungR?.element
+				if (gzL !== null && topFahrWeg.contains(topKanteL)) {
+					return gzL
+				} else if (gzR !== null && topFahrWeg.contains(topKanteR)) {
+					return gzR
+				}
+				return null
+			].filterNull.toSet
+			if (!connectionGsp.empty) {
+				return fmaGrenzens.filter [
+					topKanten.exists [ topGrenze |
+						connectionGsp.exists [
+							gzFreimeldungTOPKante.contains(topGrenze)
+						]
+					]
+				].toSet
+			}
+		}
+
+		val fmaAnlageOnZiel = fahrweg?.container?.FMAAnlage?.filter [
+			IDGleisAbschnitt?.topKanten.exists [
+				topEndFahrweg.contains(it)
+			] && !dweg.fmaAnlageFreimeldung.contains(it)
+		].toSet
+		return fmaAnlageOnZiel.map[fmaGrenzen].flatten.filter [
+			fmaGrenzens.contains(it)
+		].toSet
+	}
+
+	private static def dispatch Set<TOP_Kante> gzFreimeldungTOPKante(
+		Basis_Objekt basicObject) {
+		throw new IllegalArgumentException(basicObject.class.simpleName)
+	}
+
+	private static def dispatch Set<TOP_Kante> gzFreimeldungTOPKante(
+		W_Kr_Gsp_Element gspElement) {
+		return #[gspElement.topKanteL, gspElement.topKanteR].toSet
+	}
+
+	private static def dispatch Set<TOP_Kante> gzFreimeldungTOPKante(
+		Gleis_Abschnitt gleisAbschnitt) {
+		return gleisAbschnitt.topKanten
+	}
 }
-- 
GitLab