From 58b756195240c74243506e68b1691a6a4ca3cbde Mon Sep 17 00:00:00 2001 From: Matt Bhagat-Conway Date: Thu, 1 Jan 2026 12:50:44 -0500 Subject: [PATCH 1/5] make network build work with r5 7.5, #540 --- .../org/ipea/r5r/Network/NetworkBuilder.java | 27 +- .../org/ipea/r5r/Network/NetworkChecker.java | 2 +- .../r5r/Network/TransitLayerWithShapes.java | 329 ------------------ 3 files changed, 24 insertions(+), 334 deletions(-) delete mode 100644 java-r5rcore/src/org/ipea/r5r/Network/TransitLayerWithShapes.java diff --git a/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java b/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java index 5d0631cd8..79e3729e4 100644 --- a/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java +++ b/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java @@ -7,7 +7,10 @@ import com.conveyal.r5.kryo.KryoNetworkSerializer; import com.conveyal.r5.streets.StreetLayer; import com.conveyal.r5.transit.TransferFinder; +import com.conveyal.r5.transit.TransitLayer; import com.conveyal.r5.transit.TransportNetwork; +import com.conveyal.r5.transit.GtfsTransferLoader; +import com.conveyal.r5.analyst.cluster.TransportNetworkConfig.TransferConfig; import org.apache.commons.io.FilenameUtils; import org.ipea.r5r.R5RCore; @@ -116,21 +119,32 @@ private static TransportNetwork createNetwork() { network.streetLayer.parentNetwork = network; network.streetLayer.indexStreets(); - network.transitLayer = new TransitLayerWithShapes(); + network.transitLayer = new TransitLayer(); + // this replaces the old r5r TransitLayerWithShapes class; saving shapes now built in to r5. + network.transitLayer.saveShapes = true; + + // Options here are OSM_ONLY (only use OSM data to find transfers, consistent with r5r versions + // up to 2.3.0), STOP_TO_PATTERN (only use OSM data to find transfers to stops served by patterns + // that do not have a stop with an explicit transfer from the source stop), STOP_TO_STOP (use OSM + // to find transfers for all stop pairs that don't have an explicit GTFS transfer), and GTFS_ONLY + // (use only transfers specified in GTFS, almost never appropriate). + GtfsTransferLoader transferLoader = new GtfsTransferLoader(network.transitLayer, TransferConfig.OSM_ONLY); gtfsFeeds.forEach(gtfsFeed -> { - network.transitLayer.loadFromGtfs(gtfsFeed); + network.transitLayer.loadFromGtfs(gtfsFeed, transferLoader); // Is there a reason we can't push this close call down into the loader method? Maybe exception handling? gtfsFeed.close(); }); + transferLoader.logErrors(); + network.transitLayer.parentNetwork = network; network.streetLayer.associateStops(network.transitLayer); network.streetLayer.buildEdgeLists(); network.rebuildTransientIndexes(); - TransferFinder transferFinder = new TransferFinder(network); + TransferFinder transferFinder = new TransferFinder(network, transferLoader); transferFinder.findTransfers(); transferFinder.findParkRideTransfer(); @@ -150,6 +164,7 @@ private static TransportNetwork createNetwork() { } } catch (DataSourceException e) { e.printStackTrace(); + throw new RuntimeException(e); } network.scenarioId = "r5r"; @@ -162,7 +177,11 @@ private static TransportNetwork createNetwork() { network.transitLayer.buildDistanceTables(null); // pre-calculate transfers between transit stops - new TransferFinder(network).findTransfers(); + // TODO mwbc: why is this happening again? It does not happen twice in the R5 + // TransportNetworkCache#buildNetworkFromConfig. I don't want to remove it though due to + // https://github.com/conveyal/r5/issues/991. Maybe we should just move the entire transfer + // finding process here? + new TransferFinder(network, transferLoader).findTransfers(); return network; } diff --git a/java-r5rcore/src/org/ipea/r5r/Network/NetworkChecker.java b/java-r5rcore/src/org/ipea/r5r/Network/NetworkChecker.java index 57672b3af..e724a5f06 100644 --- a/java-r5rcore/src/org/ipea/r5r/Network/NetworkChecker.java +++ b/java-r5rcore/src/org/ipea/r5r/Network/NetworkChecker.java @@ -25,7 +25,7 @@ public class NetworkChecker { * This string should be changed to a new value each time the network storage format changes. * I considered using an ISO date string but that could get confusing when seen in filenames. */ - public static final String NETWORK_FORMAT_VERSION = "nv3"; + public static final String NETWORK_FORMAT_VERSION = "nv4"; public static final byte[] HEADER = "R5NETWORK".getBytes(); diff --git a/java-r5rcore/src/org/ipea/r5r/Network/TransitLayerWithShapes.java b/java-r5rcore/src/org/ipea/r5r/Network/TransitLayerWithShapes.java deleted file mode 100644 index 94a5a1518..000000000 --- a/java-r5rcore/src/org/ipea/r5r/Network/TransitLayerWithShapes.java +++ /dev/null @@ -1,329 +0,0 @@ -package org.ipea.r5r.Network; - -import com.conveyal.gtfs.GTFSFeed; -import com.conveyal.gtfs.model.*; -import com.conveyal.r5.transit.*; -import com.conveyal.r5.util.LocationIndexedLineInLocalCoordinateSystem; -import com.google.common.base.Strings; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import gnu.trove.list.TIntList; -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.map.TObjectIntMap; -import gnu.trove.map.hash.TObjectIntHashMap; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.linearref.LinearLocation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.time.DateTimeException; -import java.time.ZoneId; -import java.time.zone.ZoneRulesException; -import java.util.*; -import java.util.stream.DoubleStream; -import java.util.stream.StreamSupport; - -public class TransitLayerWithShapes extends TransitLayer { - - public static final boolean SAVE_SHAPES = true; - - private static final Logger LOG = LoggerFactory.getLogger(TransitLayerWithShapes.class); - - /** - * Load data from a GTFS feed. Call multiple times to load multiple feeds. - * The supplied feed is treated as read-only, and is not closed after being loaded. - * This method requires findPatterns() to have been called on the feed before it's passed in. - */ - public void loadFromGtfs (GTFSFeed gtfs, TransitLayer.LoadLevel level) throws DuplicateFeedException { - if (feedChecksums.containsKey(gtfs.feedId)) { - throw new DuplicateFeedException(gtfs.feedId); - } - - // checksum feed and add to checksum cache - feedChecksums.put(gtfs.feedId, gtfs.checksum); - - // Load stops. - // ID is the GTFS string ID, stopIndex is the zero-based index, stopVertexIndex is the index in the street layer. - TObjectIntMap indexForUnscopedStopId = new TObjectIntHashMap<>(); - stopsWheelchair = new BitSet(gtfs.stops.size()); - for (Stop stop : gtfs.stops.values()) { - int stopIndex = stopIdForIndex.size(); - String scopedStopId = String.join(":", stop.feed_id, stop.stop_id); - // This is only used while building the TransitNetwork to look up StopTimes from the same feed. - indexForUnscopedStopId.put(stop.stop_id, stopIndex); - stopIdForIndex.add(scopedStopId); - // intern zone IDs to save memory - fareZoneForStop.add(stop.zone_id); - parentStationIdForStop.add(stop.parent_station); - stopForIndex.add(stop); - if (stop.wheelchair_boarding != null && stop.wheelchair_boarding.trim().equals("1")) { - stopsWheelchair.set(stopIndex); - } - if (level == TransitLayer.LoadLevel.FULL) { - stopNames.add(stop.stop_name); - } - } - - // Load service periods, assigning integer codes which will be referenced by trips and patterns. - TObjectIntMap serviceCodeNumber = new TObjectIntHashMap<>(20, 0.5f, -1); - gtfs.services.forEach((serviceId, service) -> { - int serviceIndex = services.size(); - services.add(service); - serviceCodeNumber.put(serviceId, serviceIndex); - LOG.debug("Service {} has ID {}", serviceIndex, serviceId); - }); - - LOG.info("Creating trip patterns and schedules."); - - // These are temporary maps used only for grouping purposes. - Map tripPatternForPatternId = new HashMap<>(); - Multimap tripsForBlock = HashMultimap.create(); - - // Keyed with unscoped route_id, which is fine as this is for a single GTFS feed - TObjectIntMap routeIndexForRoute = new TObjectIntHashMap<>(); - int nTripsAdded = 0; - int nZeroDurationHops = 0; - TRIPS: for (String tripId : gtfs.trips.keySet()) { - Trip trip = gtfs.trips.get(tripId); - Route route = gtfs.routes.get(trip.route_id); - // Construct the stop pattern and schedule for this trip. - String scopedRouteId = String.join(":", gtfs.feedId, trip.route_id); - TIntList arrivals = new TIntArrayList(TYPICAL_NUMBER_OF_STOPS_PER_TRIP); - TIntList departures = new TIntArrayList(TYPICAL_NUMBER_OF_STOPS_PER_TRIP); - TIntList stopSequences = new TIntArrayList(TYPICAL_NUMBER_OF_STOPS_PER_TRIP); - - int previousDeparture = Integer.MIN_VALUE; - - int nStops = 0; - - Iterable stopTimes; - - try { - stopTimes = gtfs.getInterpolatedStopTimesForTrip(tripId); - } catch (GTFSFeed.FirstAndLastStopsDoNotHaveTimes e) { - LOG.warn("First and last stops do not both have times specified on trip {} on route {}, skipping this as interpolation is impossible", trip.trip_id, trip.route_id); - continue TRIPS; - } - - for (StopTime st : stopTimes) { - arrivals.add(st.arrival_time); - departures.add(st.departure_time); - stopSequences.add(st.stop_sequence); - - if (previousDeparture > st.arrival_time || st.arrival_time > st.departure_time) { - LOG.warn("Negative-time travel at stop {} on trip {} on route {}, skipping this trip as it will wreak havoc with routing", st.stop_id, trip.trip_id, trip.route_id); - continue TRIPS; - } - - if (previousDeparture == st.arrival_time) { //Teleportation: arrive at downstream stop immediately after departing upstream - //often the result of a stop_times input with time values rounded to the nearest minute. - //TODO check if the distance of the hop is reasonably traveled in less than 60 seconds, which may vary by mode. - nZeroDurationHops++; - } - - previousDeparture = st.departure_time; - - nStops++; - } - - if (nStops == 0) { - LOG.warn("Trip {} on route {} {} has no stops, it will not be used", trip.trip_id, trip.route_id, route.route_short_name); - continue; - } - - String patternId = gtfs.patternForTrip.get(tripId); - - TripPattern tripPattern = tripPatternForPatternId.get(patternId); - if (tripPattern == null) { - tripPattern = new TripPattern(String.format("%s:%s", gtfs.feedId, route.route_id), stopTimes, indexForUnscopedStopId); - - // if we haven't seen the route yet _from this feed_ (as IDs are only feed-unique) - // create it. - if (level == TransitLayer.LoadLevel.FULL) { - if (!routeIndexForRoute.containsKey(trip.route_id)) { - int routeIndex = routes.size(); - RouteInfo ri = new RouteInfo(route, gtfs.agency.get(route.agency_id)); - routes.add(ri); - routeIndexForRoute.put(trip.route_id, routeIndex); - } - - tripPattern.routeIndex = routeIndexForRoute.get(trip.route_id); - - if (trip.shape_id != null && SAVE_SHAPES) { - Shape shape = gtfs.getShape(trip.shape_id); - if (shape == null) LOG.warn("Shape {} for trip {} was missing", trip.shape_id, trip.trip_id); - else { - // TODO this will not work if some trips in the pattern don't have shapes - tripPattern.shape = shape.geometry; - - // project stops onto shape - boolean stopsHaveShapeDistTraveled = StreamSupport.stream(stopTimes.spliterator(), false) - .noneMatch(st -> Double.isNaN(st.shape_dist_traveled)); - boolean shapePointsHaveDistTraveled = DoubleStream.of(shape.shape_dist_traveled) - .noneMatch(Double::isNaN); - - LinearLocation[] locations; - - if (stopsHaveShapeDistTraveled && shapePointsHaveDistTraveled) { - // create linear locations from dist traveled - locations = StreamSupport.stream(stopTimes.spliterator(), false) - .map(st -> { - double dist = st.shape_dist_traveled; - - int segment = 0; - - while (segment < shape.shape_dist_traveled.length - 2 && - dist > shape.shape_dist_traveled[segment + 1] - ) segment++; - - double endSegment = shape.shape_dist_traveled[segment + 1]; - double beginSegment = shape.shape_dist_traveled[segment]; - double proportion = (dist - beginSegment) / (endSegment - beginSegment); - - return new LinearLocation(segment, proportion); - }).toArray(LinearLocation[]::new); - } else { - // naive snapping - LocationIndexedLineInLocalCoordinateSystem line = - new LocationIndexedLineInLocalCoordinateSystem(shape.geometry.getCoordinates()); - - locations = StreamSupport.stream(stopTimes.spliterator(), false) - .map(st -> { - Stop stop = gtfs.stops.get(st.stop_id); - return line.project(new Coordinate(stop.stop_lon, stop.stop_lat)); - }) - .toArray(LinearLocation[]::new); - } - - tripPattern.stopShapeSegment = new int[locations.length]; - tripPattern.stopShapeFraction = new float[locations.length]; - - for (int i = 0; i < locations.length; i++) { - tripPattern.stopShapeSegment[i] = locations[i].getSegmentIndex(); - tripPattern.stopShapeFraction[i] = (float) locations[i].getSegmentFraction(); - } - } - } - } - - tripPatternForPatternId.put(patternId, tripPattern); - tripPattern.originalId = tripPatterns.size(); - tripPatterns.add(tripPattern); - } - tripPattern.setOrVerifyDirection(trip.direction_id); - int serviceCode = serviceCodeNumber.get(trip.service_id); - - // TODO there's no reason why we can't just filter trips like this, correct? - // TODO this means that invalid trips still have empty patterns created - Collection frequencies = gtfs.getFrequencies(trip.trip_id); - TripSchedule tripSchedule = TripSchedule.create(trip, arrivals.toArray(), departures.toArray(), frequencies, stopSequences.toArray(), serviceCode); - if (tripSchedule == null) continue; - - tripPattern.addTrip(tripSchedule); - - this.hasFrequencies = this.hasFrequencies || tripSchedule.headwaySeconds != null; - this.hasSchedules = this.hasSchedules || tripSchedule.headwaySeconds == null; - - nTripsAdded += 1; - // Record which block this trip belongs to, if any. - if ( ! Strings.isNullOrEmpty(trip.block_id)) { - tripsForBlock.put(trip.block_id, tripSchedule); - } - } - LOG.info("Done creating {} trips on {} patterns.", nTripsAdded, tripPatternForPatternId.size()); - - LOG.info("{} zero-duration hops found.", nZeroDurationHops); - - LOG.info("Chaining trips together according to blocks to model interlining..."); - // Chain together trips served by the same vehicle that allow transfers by simply staying on board. - // Elsewhere this is done by grouping by (serviceId, blockId) but this is not supported by the spec. - // Discussion started on gtfs-changes. - tripsForBlock.asMap().forEach((blockId, trips) -> { - TripSchedule[] schedules = trips.toArray(new TripSchedule[trips.size()]); - Arrays.sort(schedules); // Sorts on first departure time - for (int i = 0; i < schedules.length - 1; i++) { - schedules[i].chainTo(schedules[i + 1]); - } - }); - LOG.info("Done chaining trips together according to blocks."); - - LOG.info("Sorting trips on each pattern"); - for (TripPattern tripPattern : tripPatternForPatternId.values()) { - Collections.sort(tripPattern.tripSchedules); - } - LOG.info("done sorting"); - - LOG.info("Finding the approximate center of the transport network..."); - findCenter(gtfs.stops.values()); - - //Set transportNetwork timezone - //If there are no agencies (which is strange) it is GMT - //Otherwise it is set to first valid agency timezone and warning is shown if agencies have different timezones - if (gtfs.agency.size() == 0) { - timeZone = ZoneId.of("GMT"); - LOG.warn("graph contains no agencies; API request times will be interpreted as GMT."); - } else { - for (Agency agency : gtfs.agency.values()) { - if (agency.agency_timezone == null) { - LOG.warn("Agency {} is without timezone", agency.agency_name); - continue; - } - ZoneId tz; - try { - tz = ZoneId.of(agency.agency_timezone); - } catch (ZoneRulesException z) { - LOG.error("Agency {} in GTFS with timezone '{}' wasn't found in timezone database reason: {}", agency.agency_name, agency.agency_timezone, z.getMessage()); - //timezone will be set to GMT if it is still empty after for loop - continue; - } catch (DateTimeException dt) { - LOG.error("Agency {} in GTFS has timezone in wrong format:'{}'. Expected format: area/city ", agency.agency_name, agency.agency_timezone); - //timezone will be set to GMT if it is still empty after for loop - continue; - } - //First time setting timezone - if (timeZone == null) { - LOG.info("TransportNetwork time zone set to {} from agency '{}' and agency_timezone:{}", tz, - agency.agency_name, agency.agency_timezone); - timeZone = tz; - } else if (!timeZone.equals(tz)) { - LOG.error("agency time zone {} differs from TransportNetwork time zone: {}. This will be problematic.", tz, - timeZone); - } - } - - //This can only happen if all agencies have empty timezones - if (timeZone == null) { - timeZone = ZoneId.of("GMT"); - LOG.warn( - "No agency in graph had valid timezone; API request times will be interpreted as GMT."); - } - } - - if (level == TransitLayer.LoadLevel.FULL) { - this.fares = new HashMap<>(gtfs.fares); - } - - // Will be useful in naming patterns. -// LOG.info("Finding topology of each route/direction..."); -// Multimap, TripPattern> patternsForRouteDirection = HashMultimap.create(); -// tripPatterns.forEach(tp -> patternsForRouteDirection.put(new T2(tp.routeId, tp.directionId), tp)); -// for (T2 routeAndDirection : patternsForRouteDirection.keySet()) { -// RouteTopology topology = new RouteTopology(routeAndDirection.first, routeAndDirection.second, patternsForRouteDirection.get(routeAndDirection)); -// } - - } - - // The median of all stopTimes would be best but that involves sorting a huge list of numbers. - // So we just use the mean of all stops for now. - private void findCenter (Collection stops) { - double lonSum = 0; - double latSum = 0; - for (Stop stop : stops) { - latSum += stop.stop_lat; - lonSum += stop.stop_lon; - } - // Stops is a HashMap so size() is fast. If it ever becomes a MapDB BTree, we may want to do this differently. - centerLat = latSum / stops.size(); - centerLon = lonSum / stops.size(); - } -} From 4511c45931ba75a2317c9bd164fa7573a206272b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 17:58:51 +0000 Subject: [PATCH 2/5] Rebuild JAR for commit 58b756195240c74243506e68b1691a6a4ca3cbde --- r-package/inst/jar/r5r.jar | Bin 149916 -> 141897 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/r-package/inst/jar/r5r.jar b/r-package/inst/jar/r5r.jar index b10e505827ab4ecb5b001657ad0c6cd4c3dbabd2..f7c9aab21e5e3cbbcb4dcb54a7869a125ccc953d 100644 GIT binary patch delta 7486 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 delta 15483 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 WfQI?cGKl?qZvVxMW^h9MqyGmT@iIUF From c693e4c3cde834c30539a5e8f812e842fd95a10d Mon Sep 17 00:00:00 2001 From: Matt Bhagat-Conway Date: Wed, 30 Jul 2025 20:28:32 -0400 Subject: [PATCH 3/5] add support for config.json in network building --- .../org/ipea/r5r/Network/NetworkBuilder.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java b/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java index 79e3729e4..5f9ede1e2 100644 --- a/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java +++ b/java-r5rcore/src/org/ipea/r5r/Network/NetworkBuilder.java @@ -3,6 +3,7 @@ import com.conveyal.analysis.datasource.DataSourceException; import com.conveyal.gtfs.GTFSFeed; import com.conveyal.osmlib.OSM; +import com.conveyal.r5.analyst.cluster.TransportNetworkConfig; import com.conveyal.r5.analyst.scenario.RasterCost; import com.conveyal.r5.kryo.KryoNetworkSerializer; import com.conveyal.r5.streets.StreetLayer; @@ -24,6 +25,7 @@ import java.util.stream.Stream; public class NetworkBuilder { + public static final String JSON_CONFIG_FILE = "config.json"; public static boolean useNativeElevation = false; public static String elevationCostFunction = "NONE"; @@ -34,6 +36,8 @@ public class NetworkBuilder { private static OSM osmFile; private static Stream gtfsFeeds; private static String tiffFile = ""; + private static TransportNetworkConfig transportNetworkConfig = null; + public static TransportNetwork checkAndLoadR5Network(String dataFolder) throws Exception { File file = new File(dataFolder, "network.dat"); @@ -105,6 +109,8 @@ private static Map buildNetworkConfig() { networkConfig.put("elevation_cost_function", elevationCostFunction); networkConfig.put("tiff_file_name", tiffFile); + networkConfig.put("transportNetworkConfig", transportNetworkConfig != null ? JSON_CONFIG_FILE : null); + return networkConfig; } @@ -112,13 +118,14 @@ private static TransportNetwork createNetwork() { TransportNetwork network = new TransportNetwork(); network.scenarioId = "r5r"; - network.streetLayer = new StreetLayer(); + network.streetLayer = new StreetLayer(transportNetworkConfig); network.streetLayer.loadFromOsm(osmFile); osmFile.close(); network.streetLayer.parentNetwork = network; network.streetLayer.indexStreets(); + // currently the TransitLayer has no config, so we do not pass in networkConfig network.transitLayer = new TransitLayer(); // this replaces the old r5r TransitLayerWithShapes class; saving shapes now built in to r5. network.transitLayer.saveShapes = true; @@ -204,6 +211,15 @@ public static void loadDirectory(File directory) { } if (name.endsWith(".zip")) gtfsFiles.add(file.getAbsolutePath()); if (name.endsWith(".tif") | name.endsWith(".tiff")) tiffFile = file.getAbsolutePath(); + if (name.equals(JSON_CONFIG_FILE)) { + try { + // Use the R5 object mapper to make sure R5 config files are compatible (e.g. same case conventions) + transportNetworkConfig = com.conveyal.analysis.util.JsonUtil.objectMapper.readValue(file, TransportNetworkConfig.class); + } catch (Exception e) { + // re-throw, don't silently ignore a config file + throw new RuntimeException(e); + } + } } // Supply feeds with a stream, so they do not sit open in memory while other feeds are being processed. From e8c8e18f0d31232c0d353f211b2279605c965b9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 22:17:41 +0000 Subject: [PATCH 4/5] Rebuild JAR for commit c693e4c3cde834c30539a5e8f812e842fd95a10d --- r-package/inst/jar/r5r.jar | Bin 141897 -> 142207 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/r-package/inst/jar/r5r.jar b/r-package/inst/jar/r5r.jar index f7c9aab21e5e3cbbcb4dcb54a7869a125ccc953d..a6e8182561f8e9889c98f14c6c91ff57fa26b993 100644 GIT binary patch delta 5836 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 bUI2P51OW#?1waHs7;*rpF|tVj56Ai+ZU|kn From bf969ccdc6ed009c391e2618d136c7f47b67be21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 13:16:37 +0000 Subject: [PATCH 5/5] Rebuild JAR for commit 31229c8bbc613fd182e0fd216a5ef3d44193d49e --- r-package/inst/jar/r5r.jar | Bin 143311 -> 143625 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/r-package/inst/jar/r5r.jar b/r-package/inst/jar/r5r.jar index 82bb07727c0a0c68fced9c47735a0c534c135343..1ef7eb8a27b4f39339c5c2df038e30ad8cad6617 100644 GIT binary patch delta 7194 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 Qc#SZC5%&cH;Lm6MA3{N)(*OVf delta 6861 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 mvq*q&E^hW#me$U1{ajr%RS*#W*?Gy=GX)