diff --git a/src/main/java/org/mtransit/commons/CollectionsExt.kt b/src/main/java/org/mtransit/commons/CollectionsExt.kt index 8e018ee6..8c77e1e2 100644 --- a/src/main/java/org/mtransit/commons/CollectionsExt.kt +++ b/src/main/java/org/mtransit/commons/CollectionsExt.kt @@ -191,4 +191,45 @@ fun Iterable.matchList( thisPrefixLength > thisSuffixLength -> thisPrefixLength else -> thisSuffixLength }).toFloat().div(otherLength) + ignoredMatchPt +} + +fun Iterable.hasItemsGoingIntoSameOrder(otherIt: Iterable): Boolean { + return this.countItemsGoingIntoSameOrder(otherIt, firstItemsOnly = true) > 0 +} + +fun Iterable.countItemsGoingIntoSameOrder(otherIt: Iterable, firstItemsOnly: Boolean = false): Int { + val thisList = this as? List ?: this.toList() + val otherList = otherIt as? List ?: otherIt.toList() + var count = 0 + var thisIndex = 0 + var otherStartIndex = 0 + while (thisIndex < thisList.size) { + val otherMatchIndex = otherList.indexOf(thisList[thisIndex], otherStartIndex) + if (otherMatchIndex != -1) { + var len = 1 + while (thisIndex + len < thisList.size && + otherMatchIndex + len < otherList.size && + thisList[thisIndex + len] == otherList[otherMatchIndex + len]) { + len++ + } + if (len > 1) { + count += len + if (firstItemsOnly) return count + thisIndex += len + otherStartIndex = otherMatchIndex + len + continue + } + } + thisIndex++ + } + return count +} + +fun List.indexOf(element: T, startIndex: Int): Int { + for (i in startIndex until this.size) { + if (this[i] == element) { + return i + } + } + return -1 } \ No newline at end of file diff --git a/src/main/java/org/mtransit/parser/mt/MDirectionSplitter.kt b/src/main/java/org/mtransit/parser/mt/MDirectionSplitter.kt index 91563a6b..0d58da4d 100644 --- a/src/main/java/org/mtransit/parser/mt/MDirectionSplitter.kt +++ b/src/main/java/org/mtransit/parser/mt/MDirectionSplitter.kt @@ -1,6 +1,7 @@ package org.mtransit.parser.mt import org.mtransit.commons.containsExactList +import org.mtransit.commons.hasItemsGoingIntoSameOrder import org.mtransit.commons.intersectWithOrder import org.mtransit.commons.matchList import org.mtransit.commons.overlap @@ -86,6 +87,7 @@ object MDirectionSplitter { routeGTFS.updateTripDirectionId(GDirectionId.NEW_1, directionsCandidates[0].tripIdInts) } } + 2 -> { // TODO check if directions candidates group match existing split to keep original direction IDs val (direction0, direction1) = if (directionsCandidates[0].stopIdInts.sum() > directionsCandidates[1].stopIdInts.sum()) { @@ -96,6 +98,7 @@ object MDirectionSplitter { routeGTFS.updateTripDirectionId(direction0, directionsCandidates[0].tripIdInts) routeGTFS.updateTripDirectionId(direction1, directionsCandidates[1].tripIdInts) } + else -> { throw MTLog.Fatal("$routeId: Unexpected number (${directionsCandidates.size}) of results !") } @@ -125,6 +128,16 @@ object MDirectionSplitter { } == true) { continue } + // LOOK FOR SAME STOPS DIRECTION + if (directionsCandidates.singleOrNull { (_, rStopIdInts) -> + rStopIdInts.hasItemsGoingIntoSameOrder(gStopIdInts) + }?.let { (rTripIdInts, _) -> + MTLog.logDebug("$routeId: Same stops direction for: '${GIDs.toStringPlus(gTripIdInt)}': \n - ${GIDs.toStringPlus(gStopIdInts)}") + rTripIdInts.add(gTripIdInt) + true + } == true) { + continue + } // LOOK FOR ALMOST A MATCH if (directionsCandidates.singleOrNull { (_, rStopIdInts) -> val matchList = rStopIdInts.matchList(gStopIdInts, ignoreRepeat = true, ignoreFirstAndLast = gStopIdInts.size > 2, combineMatch = true) @@ -160,7 +173,7 @@ object MDirectionSplitter { (rStopIdInts.first() == gStopIdInts.last()) .xor(rStopIdInts.last() == gStopIdInts.first()) }?.takeIf { (_, rStopIdInts) -> - gStopIdInts.size.toFloat().div(rStopIdInts.size) < 0.50f + gStopIdInts.size.toFloat() / rStopIdInts.size < 0.50f }?.let { (rTripIdInts, rStopIdInts) -> MTLog.logDebug("$routeId: continuation: '${GIDs.toStringPlus(gTripIdInt)}': \n${GIDs.toStringPlus(gStopIdInts)}") if (rStopIdInts.first() == gStopIdInts.last()) { diff --git a/src/test/java/org/mtransit/commons/CollectionsExtTest.kt b/src/test/java/org/mtransit/commons/CollectionsExtTest.kt index 41e426c3..fd32d0ec 100644 --- a/src/test/java/org/mtransit/commons/CollectionsExtTest.kt +++ b/src/test/java/org/mtransit/commons/CollectionsExtTest.kt @@ -147,7 +147,6 @@ class CollectionsExtTest { ) // Act val matchList = mainList.matchList(otherList, ignoreRepeat = true, ignoreFirstAndLast = true) - print(matchList) val result = matchList >= 0.75f // Assert assertEquals(true, result) @@ -282,4 +281,92 @@ class CollectionsExtTest { // Assert assertEquals(true, result) } + + @Test + fun test_countItemsGoingIntoSameOrder_Yes() { + // Arrange + val mainList = listOf( + "09149", "00460", // == + "00464", "00465", "00843", "00487", "S09047", // != + "09339", "S00503", "02052", "00367", "00369", "03065", "00242", "00241", "00240", "00238", "09229", "03038", // == + "00832" // -> + ) + val otherList = listOf( + "09149", "00460", // == + "00461", "S00451", "00855", "00450", "00447", "09083", "02056", "00488", // != + "00486", "00484", "00481", "00471", "00479", "00477", "00498", "00474", "00473", // != + "09339", "S00503", "02052", "00367", "00369", "03065", "00242", "00241", "00240", "00238", "09229", "03038", // == + "00746", "S09056", // != + ) + // Act + val result = mainList.countItemsGoingIntoSameOrder(otherList) + // Assert + assertEquals(14, result) + } + + @Test + fun test_hasItemsGoingIntoSameOrder_Yes() { + // Arrange + val mainList = listOf( + "09149", "00460", // == + "00464", "00465", "00843", "00487", "S09047", // != + "09339", "S00503", "02052", "00367", "00369", "03065", "00242", "00241", "00240", "00238", "09229", "03038", // == + "00832" // -> + ) + val otherList = listOf( + "09149", "00460", // == + "00461", "S00451", "00855", "00450", "00447", "09083", "02056", "00488", // != + "00486", "00484", "00481", "00471", "00479", "00477", "00498", "00474", "00473", // != + "09339", "S00503", "02052", "00367", "00369", "03065", "00242", "00241", "00240", "00238", "09229", "03038", // == + "00746", "S09056", // != + ) + // Act + val result = mainList.hasItemsGoingIntoSameOrder(otherList) + // Assert + assertEquals(true, result) + } + + @Test + fun test_countItemsGoingIntoSameOrder_No() { + // Arrange + val mainList = listOf( + "09149", // -> + "00460", "00464", "00465", "00843", // != + "00487", // <> + "S09047", "09339", "S00503", "02052", "00367", "00369", "03065", "00242", "00241", "00240", "00238", "09229", "03038", // != + "00832" // -> + ) + val otherList = listOf( + "00832", // -> + "09242", "00237", "00239", "00860", "00861", "00863", "09155", "00762", "00368", "00366", "S00502", "09340", "00472", "00475", "02059", // != + "00476", "00478", "00480", "00482", "00483", "00485", "00487", "00489", "00445", "00448", "00449", "00454", "S00800", "00452", "09163", // != + "09149" // -> + ) + // Act + val result = mainList.countItemsGoingIntoSameOrder(otherList) + // Assert + assertEquals(0, result) + } + + @Test + fun test_hasItemsGoingIntoSameOrder_No() { + // Arrange + val mainList = listOf( + "09149", // -> + "00460", "00464", "00465", "00843", // != + "00487", // <> + "S09047", "09339", "S00503", "02052", "00367", "00369", "03065", "00242", "00241", "00240", "00238", "09229", "03038", // != + "00832" // -> + ) + val otherList = listOf( + "00832", // -> + "09242", "00237", "00239", "00860", "00861", "00863", "09155", "00762", "00368", "00366", "S00502", "09340", "00472", "00475", "02059", // != + "00476", "00478", "00480", "00482", "00483", "00485", "00487", "00489", "00445", "00448", "00449", "00454", "S00800", "00452", "09163", // != + "09149" // -> + ) + // Act + val result = mainList.hasItemsGoingIntoSameOrder(otherList) + // Assert + assertEquals(false, result) + } } \ No newline at end of file