@@ -113,8 +113,54 @@ class MapMatchingBulkTestResultsPublisherImpl(
113113 writeGeoJsonToFile(getFailedSegmentsAsGeoJson(failed), FILENAME_FAILED_SEGMENTS_GEOJSON )
114114 LOGGER .info { " Wrote failed stop-to-stop segments to GeoJSON file: ${geojsonFile.absolutePath} " }
115115
116- val failedSegmentsGeoPackageFile = File (outputDir, FILENAME_FAILED_SEGMENTS_GPKG )
117- failedSegmentsGeoPackageFile.delete()
116+ writeGeoPackageFilesForFailedSegments(failed, getSegmentMatchFailuresOnLowerBufferRadius(succeeded))
117+ }
118+
119+ private fun writeGeoJsonToFile (
120+ features : GeoJsonFeatureCollection <G2D , String >,
121+ filename : String
122+ ): File {
123+ val geojson: String = objectMapper.writeValueAsString(features)
124+
125+ val outputFile = File (outputDir, filename)
126+ outputFile.writeText(geojson)
127+ return outputFile
128+ }
129+
130+ private fun writeGeoPackageFilesForFailedSegments (
131+ primaryFailures : List <SegmentMatchFailure >,
132+ secondaryFailures : SortedMap <BufferRadius , List <SegmentMatchFailure >>
133+ ) {
134+ writeGeoPackageFileForFailedSegments(
135+ primaryFailures,
136+ getGeoPackageFilenameForFailedSegments(),
137+ getGeoPackageFilenameForFailedSegmentBuffers()
138+ )
139+
140+ secondaryFailures.entries.forEach { (bufferRadius, segmentMatchFailures) ->
141+
142+ if (segmentMatchFailures.isNotEmpty()) {
143+ writeGeoPackageFileForFailedSegments(
144+ segmentMatchFailures,
145+ getGeoPackageFilenameForFailedSegments(bufferRadius),
146+ getGeoPackageFilenameForFailedSegmentBuffers(bufferRadius)
147+ )
148+ }
149+ }
150+ }
151+
152+ private fun writeGeoPackageFileForFailedSegments (
153+ failed : List <SegmentMatchFailure >,
154+ segmentsFilename : String ,
155+ segmentBuffersFilename : String
156+ ) {
157+ var failedSegmentsGeoPackageFile = File (outputDir, segmentsFilename)
158+
159+ if (failedSegmentsGeoPackageFile.exists()) {
160+ failedSegmentsGeoPackageFile.renameTo(File (outputDir, " $segmentsFilename .bak" ))
161+ failedSegmentsGeoPackageFile = File (outputDir, segmentsFilename)
162+ }
163+
118164 GeoPackageUtils .createGeoPackage(failedSegmentsGeoPackageFile, failed, false )
119165
120166 LOGGER .info {
@@ -123,8 +169,12 @@ class MapMatchingBulkTestResultsPublisherImpl(
123169 } "
124170 }
125171
126- val failureBuffersGeoPackageFile = File (outputDir, FILENAME_FAILED_SEGMENT_BUFFERS_GPKG )
127- failureBuffersGeoPackageFile.delete()
172+ var failureBuffersGeoPackageFile = File (outputDir, segmentBuffersFilename)
173+ if (failureBuffersGeoPackageFile.exists()) {
174+ failureBuffersGeoPackageFile.renameTo(File (outputDir, " $segmentBuffersFilename .bak" ))
175+ failureBuffersGeoPackageFile = File (outputDir, segmentBuffersFilename)
176+ }
177+
128178 GeoPackageUtils .createGeoPackage(failureBuffersGeoPackageFile, failed, true )
129179
130180 LOGGER .info {
@@ -134,23 +184,19 @@ class MapMatchingBulkTestResultsPublisherImpl(
134184 }
135185 }
136186
137- private fun writeGeoJsonToFile (
138- features : GeoJsonFeatureCollection <G2D , String >,
139- filename : String
140- ): File {
141- val geojson: String = objectMapper.writeValueAsString(features)
142-
143- val outputFile = File (outputDir, filename)
144- outputFile.writeText(geojson)
145- return outputFile
146- }
147-
148187 companion object {
149188 private const val FILENAME_FAILED_ROUTES_GEOJSON = " failed_routes.geojson"
150189 private const val FILENAME_FAILED_SEGMENTS_GEOJSON = " failed_segments.geojson"
151190
152- private const val FILENAME_FAILED_SEGMENTS_GPKG = " failed_segments.gpkg"
153- private const val FILENAME_FAILED_SEGMENT_BUFFERS_GPKG = " failed_segment_buffers.gpkg"
191+ private fun getGeoPackageFilenameForFailedSegments (bufferRadius : BufferRadius ? = null): String =
192+ bufferRadius
193+ ?.let { " failed_segments_${it.value} .gpkg" }
194+ ? : " failed_segments.gpkg"
195+
196+ private fun getGeoPackageFilenameForFailedSegmentBuffers (bufferRadius : BufferRadius ? = null): String =
197+ bufferRadius
198+ ?.let { " failed_segment_buffers_${it.value} .gpkg" }
199+ ? : " failed_segment_buffers.gpkg"
154200
155201 private fun partitionBySuccess (
156202 results : List <MatchResult >
@@ -222,6 +268,49 @@ class MapMatchingBulkTestResultsPublisherImpl(
222268
223269 private fun roundTo2Digits (n : Double ): Double = (n * 100 ).roundToInt() / 100.0
224270
271+ private fun getSegmentMatchFailuresOnLowerBufferRadius (
272+ succeeded : List <SuccessfulSegmentMatchResult >
273+ ): SortedMap <BufferRadius , List <SegmentMatchFailure >> {
274+ val allUnsuccessfulBufferRadiuses: MutableSet <BufferRadius > = mutableSetOf ()
275+
276+ succeeded.forEach {
277+ allUnsuccessfulBufferRadiuses.addAll(it.details.unsuccessfulBufferRadiuses)
278+ }
279+
280+ val alreadyProcessedSegmentIds: MutableSet <String > = mutableSetOf ()
281+ val failedSegmentsByRadius: MutableMap <BufferRadius , MutableList <SegmentMatchFailure >> = mutableMapOf ()
282+
283+ allUnsuccessfulBufferRadiuses
284+ .sortedDescending()
285+ .forEach { bufferRadius ->
286+
287+ succeeded
288+ .filter { bufferRadius in it.details.unsuccessfulBufferRadiuses }
289+ .filter { it.routeId !in alreadyProcessedSegmentIds }
290+ .forEach { matchResult ->
291+
292+ failedSegmentsByRadius
293+ .getOrPut(bufferRadius) { mutableListOf () }
294+ .add(
295+ SegmentMatchFailure (
296+ matchResult.routeId,
297+ matchResult.sourceRouteGeometry,
298+ matchResult.sourceRouteLength,
299+ bufferRadius,
300+ matchResult.startStopId,
301+ matchResult.endStopId,
302+ matchResult.numberOfRoutePoints,
303+ matchResult.referencingRoutes
304+ )
305+ )
306+
307+ alreadyProcessedSegmentIds.add(matchResult.routeId)
308+ }
309+ }
310+
311+ return failedSegmentsByRadius.toSortedMap()
312+ }
313+
225314 private fun getRoutesNotMatchedEvenThoughAllSegmentsMatched (
226315 routeResults : List <MatchResult >,
227316 stopToStopSegmentResults : List <SegmentMatchResult >
0 commit comments