diff --git a/src/main/java/org/mtransit/parser/DefaultAgencyTools.java b/src/main/java/org/mtransit/parser/DefaultAgencyTools.java index cdd3677..7140e65 100644 --- a/src/main/java/org/mtransit/parser/DefaultAgencyTools.java +++ b/src/main/java/org/mtransit/parser/DefaultAgencyTools.java @@ -815,9 +815,10 @@ public void setDirectionHeadsign(@NotNull MRoute mRoute, @NotNull MDirection mDi throw new MTLog.Fatal("Trying to set direction head-sign w/o valid GTFS route (ID: %s)", gTrip.getRouteId()); } final boolean fromStopName = mDirection.getHeadsignType() == MDirection.HEADSIGN_TYPE_STOP_ID; + final boolean fromTripHeadSign = mDirection.getHeadsignType() == MDirection.HEADSIGN_TYPE_STRING; if (directionFinderEnabled(mRoute.getId(), gRoute)) { mDirection.setHeadsignString( - cleanDirectionHeadsign(gRoute, gTrip.getDirectionIdOrDefault(), fromStopName, gTrip.getTripHeadsignOrDefault()), + cleanDirectionHeadsign(gRoute, gTrip.getDirectionIdOrDefault(), fromStopName, fromTripHeadSign, gTrip.getTripHeadsignOrDefault()), gTrip.getDirectionIdOrDefault() ); return; @@ -827,7 +828,7 @@ public void setDirectionHeadsign(@NotNull MRoute mRoute, @NotNull MDirection mDi } try { mDirection.setHeadsignString( - cleanDirectionHeadsign(gRoute, gTrip.getDirectionIdOrDefault(), fromStopName, gTrip.getTripHeadsignOrDefault()), + cleanDirectionHeadsign(gRoute, gTrip.getDirectionIdOrDefault(), fromStopName, fromTripHeadSign, gTrip.getTripHeadsignOrDefault()), gTrip.getDirectionIdOrDefault() ); } catch (NumberFormatException nfe) { @@ -940,6 +941,18 @@ public boolean removeRouteDescFromDirectionHeadsign() { * @param directionId {@link org.mtransit.parser.gtfs.data.GDirectionId} (0 or 1 or missing/generated) */ @Override + public @NotNull String cleanDirectionHeadsign(@Nullable GRoute gRoute, int directionId, boolean fromStopName, boolean fromTripHeadSign, @NotNull String directionHeadSign) { + if (fromTripHeadSign) { + if (Configs.getRouteConfig().getDirectionHeadsignIgnoreTripHeadsign()) { + directionHeadSign = ""; + } + } + return cleanDirectionHeadsign(gRoute, directionId, fromStopName, directionHeadSign); + } + + @SuppressWarnings("DeprecatedIsStillUsed") + @Deprecated + @Override public @NotNull String cleanDirectionHeadsign(@Nullable GRoute gRoute, int directionId, boolean fromStopName, @NotNull String directionHeadSign) { if (gRoute != null) { if (removeRouteLongNameFromDirectionHeadsign() && directionHeadSign.equals(gRoute.getRouteLongNameOrDefault())) { @@ -1345,7 +1358,7 @@ public int getStopId(@NotNull GStop gStop) { return Math.abs(gStopId.hashCode()); } final String stopCode = cleanStopCode(gStop.getStopCode()); - @SuppressWarnings("DiscouragedApi") + //noinspection DiscouragedApi final String stopIdS = useStopCodeForStopId() ? stopCode : useStopCodeForStopIdDigitsOnly() && CharUtils.isDigitsOnly(stopCode, true) ? stopCode diff --git a/src/main/java/org/mtransit/parser/config/gtfs/data/RouteConfig.kt b/src/main/java/org/mtransit/parser/config/gtfs/data/RouteConfig.kt index 877ffff..3b5b2eb 100644 --- a/src/main/java/org/mtransit/parser/config/gtfs/data/RouteConfig.kt +++ b/src/main/java/org/mtransit/parser/config/gtfs/data/RouteConfig.kt @@ -92,6 +92,8 @@ data class RouteConfig( val directionHeadsignRemoveRouteShortName: Boolean = false, // OPT-IN feature @SerialName("direction_headsign_remove_route_desc") val directionHeadsignRemoveRouteDesc: Boolean = false, // OPT-IN feature + @SerialName("direction_headsign_ignore_trip_headsign") + val directionHeadsignIgnoreTripHeadsign: Boolean = false, // OPT-IN feature @SerialName("direction_splitter_enabled") val directionSplitterEnabled: Boolean = false, // OPT-IN feature @SerialName("direction_splitter_disabled_until") @@ -332,11 +334,13 @@ data class RouteConfig( fun cleanRouteLongName(lang: Locale, routeLongName: String) = cleanString(lang, routeLongName, this.routeLongNameCleaners) - fun cleanTripHeadsign(lang: Locale, tripHeadsign: String) = - cleanString(lang, tripHeadsign, this.tripHeadsignCleaners) + fun cleanTripHeadsign(lang: Locale, tripHeadsign: String): String { + return cleanString(lang, tripHeadsign, this.tripHeadsignCleaners) + } - fun cleanStopName(lang: Locale, stopName: String) = - cleanString(lang, stopName, this.stopNameCleaners) + fun cleanStopName(lang: Locale, stopName: String): String { + return cleanString(lang, stopName, this.stopNameCleaners) + } fun cleanStopCode(lang: Locale, stopCode: String) = cleanString(lang, stopCode, this.stopCodeCleaners) @@ -406,8 +410,9 @@ data class RouteConfig( this.tripHeadsignFromOriginalRouteIdRegex?.toRegex()?.replace(gTrip.originalRouteId, EMPTY) ?: defaultHeadsign - fun cleanDirectionHeadsign(lang: Locale, directionHeadsign: String) = - cleanString(lang, directionHeadsign, this.directionHeadsignCleaners) + fun cleanDirectionHeadsign(lang: Locale, directionHeadsign: String): String { + return cleanString(lang, directionHeadsign, this.directionHeadsignCleaners) + } fun convertStopIdFromOriginalNotSupported(originalStopId: String) = this.stopOriginalIdToStopIdConfigs diff --git a/src/main/java/org/mtransit/parser/gtfs/GAgencyTools.java b/src/main/java/org/mtransit/parser/gtfs/GAgencyTools.java index d1ebc52..12e39a8 100644 --- a/src/main/java/org/mtransit/parser/gtfs/GAgencyTools.java +++ b/src/main/java/org/mtransit/parser/gtfs/GAgencyTools.java @@ -214,6 +214,10 @@ public interface GAgencyTools { boolean removeRouteDescFromDirectionHeadsign(); + @NotNull + String cleanDirectionHeadsign(@Nullable GRoute gRoute, int directionId, boolean fromStopName, boolean fromTripHeadSign, @NotNull String directionHeadSign); + + @Deprecated @NotNull String cleanDirectionHeadsign(@Nullable GRoute gRoute, int directionId, boolean fromStopName, @NotNull String directionHeadSign); diff --git a/src/main/java/org/mtransit/parser/mt/MDirectionHeadSignFinder.kt b/src/main/java/org/mtransit/parser/mt/MDirectionHeadSignFinder.kt index eee890c..d4bfdc0 100644 --- a/src/main/java/org/mtransit/parser/mt/MDirectionHeadSignFinder.kt +++ b/src/main/java/org/mtransit/parser/mt/MDirectionHeadSignFinder.kt @@ -64,9 +64,9 @@ object MDirectionHeadSignFinder { val firstAndLastTime = directionAmPm[directionId] ?: continue val gRoute = directionRouteIdInts[directionId].takeIf { it?.size == 1 }?.getOrNull(0)?.let { routeGTFS.getRoute(it) } if (GTime.areAM(firstAndLastTime)) { - amPmDirectionHeadSigns[directionId] = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, "AM") + amPmDirectionHeadSigns[directionId] = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, false, "AM") } else if (GTime.arePM(firstAndLastTime)) { - amPmDirectionHeadSigns[directionId] = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, "PM") + amPmDirectionHeadSigns[directionId] = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, false, "PM") } } if (amPmDirectionHeadSigns.size == 2 // all AM/PM or nothing @@ -85,7 +85,7 @@ object MDirectionHeadSignFinder { ?: continue val rln = gRoute.routeLongNameOrDefault.takeIf { it.isNotBlank() } ?: continue - routeDirectionHeadSigns[directionId] = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, agencyTools.cleanRouteLongName(rln)) + routeDirectionHeadSigns[directionId] = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, false, agencyTools.cleanRouteLongName(rln)) } if (routeDirectionHeadSigns.size == directionHeadSigns.size // all route long name or nothing && agencyTools.directionHeadSignsDescriptive(routeDirectionHeadSigns) @@ -103,7 +103,7 @@ object MDirectionHeadSignFinder { val stop = routeGTFS.getStop(stopIdInt) ?: continue val gRoute = directionRouteIdInts[directionId].takeIf { it?.size == 1 }?.getOrNull(0)?.let { routeGTFS.getRoute(it) } lastStopDirectionHeadSigns[directionId] = - agencyTools.cleanDirectionHeadsign(gRoute, directionId, true, agencyTools.cleanStopName(stop.stopName)) + agencyTools.cleanDirectionHeadsign(gRoute, directionId, true, false, agencyTools.cleanStopName(stop.stopName)) MTLog.logDebug("$routeId: $directionId Stop '${stop.toStringPlus(false)}' > '${lastStopDirectionHeadSigns[directionId]}'.") } val allDirectionHeadSignsEmpty: Boolean = directionHeadSigns @@ -137,7 +137,7 @@ object MDirectionHeadSignFinder { val gRoute = directionRouteIdInts[directionId].takeIf { it?.size == 1 }?.getOrNull(0)?.let { routeGTFS.getRoute(it) } var cleanDirectionHeadsign: String? = null for (stopTimeHeadSign in stopTimeHeadSigns) { - cleanDirectionHeadsign = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, stopTimeHeadSign) // already cleaned + cleanDirectionHeadsign = agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, false, stopTimeHeadSign) // already cleaned if (cleanDirectionHeadsign.isNotBlank()) { break } @@ -188,7 +188,7 @@ object MDirectionHeadSignFinder { val routeIdInt = gTrip.routeIdInt val gRoute = routeGTFS.getRoute(routeIdInt) val headSign = gTrip.tripHeadsign - ?.let { agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, it) } ?: EMPTY + ?.let { agencyTools.cleanDirectionHeadsign(gRoute, directionId, false, true, it) } ?: EMPTY val stopTimes = routeGTFS.getStopTimes(routeId, gTrip.tripIdInt, null, null) Triple(routeIdInt, headSign, stopTimes) }.filterNot { (_, _, stopTimes) -> @@ -309,7 +309,7 @@ object MDirectionHeadSignFinder { } // starting complex merge MTLog.log("$routeId: $directionId: COMPLEX merge required for: ") - distinctTripHeadSignAndStopTimes.forEach { (routeId, headSign, stopTimes) -> + distinctTripHeadSignAndStopTimes.forEach { (_, headSign, stopTimes) -> MTLog.log( "$routeId: $directionId: '$headSign':" + (if (Constants.DEBUG) "\n" else "") + " ${stopTimes.size} stops: ${ @@ -631,7 +631,7 @@ object MDirectionHeadSignFinder { if ((stopIdIntsAfterCommonCount2 == 0 && stopIdIntsAfterCommonCount1 == 0) // #1 & #2 have same last stop || (dataLossAuthorized && (stopIdIntsAfterCommonCount2 > 0 && stopIdIntsAfterCommonCount1 > 0)) // distinct last stops (branching) ) { - if (stopTimesHeadSign1.isBlank()) { + if (stopTimesHeadSign1.isBlank() && stopTimesHeadSign2.isNotBlank()) { logMerge(!dataLossAuthorized, "$routeId: $directionId: #1 head-sign is blank, use #2 -> '$stopTimesHeadSign2'") return MergedTrip( routeIdInts1, routeIdInts2, stopTimesHeadSign2 to mergeBeforeFirstCommonStop( @@ -643,7 +643,7 @@ object MDirectionHeadSignFinder { ) ) } - if (stopTimesHeadSign2.isBlank()) { + if (stopTimesHeadSign2.isBlank() && stopTimesHeadSign1.isNotBlank()) { logMerge(!dataLossAuthorized, "$routeId: $directionId: #2 head-sign is blank, use #1 -> '$stopTimesHeadSign1'") return MergedTrip( routeIdInts1, routeIdInts2, stopTimesHeadSign1 to mergeBeforeFirstCommonStop( @@ -982,9 +982,9 @@ object MDirectionHeadSignFinder { throw MTLog.Fatal( "$routeId: $directionId: Unresolved situation! \n" + "- #1: $stopTimesHeadSign1. \n" + - " Stops: ${stopTimesList1.map { gStopTime -> "\n - ${gStopTime.toStringPlus(true)}" }} \n" + + " Stops: ${stopTimesList1.map { gStopTime -> "\n - ${gStopTime.toStringPlus(false)}" }} \n" + "- #2: $stopTimesHeadSign2. \n" + - " Stops: ${stopTimesList2.map { gStopTime -> "\n - ${gStopTime.toStringPlus(true)}" }} \n" + + " Stops: ${stopTimesList2.map { gStopTime -> "\n - ${gStopTime.toStringPlus(false)}" }} \n" + "!" ) } diff --git a/src/test/java/org/mtransit/parser/mt/MDirectionHeadSignFinderTest.kt b/src/test/java/org/mtransit/parser/mt/MDirectionHeadSignFinderTest.kt index 1b118ce..ac7ae4b 100644 --- a/src/test/java/org/mtransit/parser/mt/MDirectionHeadSignFinderTest.kt +++ b/src/test/java/org/mtransit/parser/mt/MDirectionHeadSignFinderTest.kt @@ -42,9 +42,9 @@ class MDirectionHeadSignFinderTest { @Suppress("DEPRECATION") @Before fun setUp() { - whenever(agencyTools.cleanDirectionHeadsign(anyOrNull(), anyInt(), anyBoolean(), anyString())) + whenever(agencyTools.cleanDirectionHeadsign(anyOrNull(), anyInt(), anyBoolean(), anyBoolean(), anyString())) .then { - it.arguments[3] + it.arguments[4] } whenever(agencyTools.cleanStopHeadSign(any(), any(), any(), anyString())) .then {