Skip to content

Commit 206b36d

Browse files
committed
Add optimization endpoint
1 parent 0fdf62f commit 206b36d

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.nitri.ors
2+
3+
import android.content.Context
4+
import androidx.test.core.app.ApplicationProvider
5+
import androidx.test.ext.junit.runners.AndroidJUnit4
6+
import kotlinx.coroutines.runBlocking
7+
import org.junit.Assert.assertNotNull
8+
import org.junit.Assert.assertTrue
9+
import org.junit.Test
10+
import org.junit.runner.RunWith
11+
import org.nitri.ors.client.OpenRouteServiceClient
12+
import org.nitri.ors.model.optimization.Job
13+
import org.nitri.ors.model.optimization.Vehicle
14+
import org.nitri.ors.repository.OptimizationRepository
15+
16+
@RunWith(AndroidJUnit4::class)
17+
class OptimizationInstrumentedTest {
18+
19+
private fun createRepository(context: Context): OptimizationRepository {
20+
val apiKey = context.getString(R.string.ors_api_key)
21+
val api = OpenRouteServiceClient.create(apiKey, context)
22+
return OptimizationRepository(api)
23+
}
24+
25+
@Test
26+
fun testOptimization_successful() = runBlocking {
27+
val context = ApplicationProvider.getApplicationContext<Context>()
28+
val repository = createRepository(context)
29+
30+
// Simple scenario in/near Heidelberg, Germany
31+
val vehicle = Vehicle(
32+
id = 1,
33+
profile = "driving-car",
34+
// Start and end at/near Heidelberg castle parking
35+
start = listOf(8.6910, 49.4100),
36+
end = listOf(8.6910, 49.4100)
37+
)
38+
39+
val jobs = listOf(
40+
Job(
41+
id = 101,
42+
location = listOf(8.681495, 49.41461) // Heidelberg center
43+
),
44+
Job(
45+
id = 102,
46+
location = listOf(8.687872, 49.420318) // Nearby point
47+
)
48+
)
49+
50+
val response = repository.getOptimization(
51+
vehicles = listOf(vehicle),
52+
jobs = jobs
53+
)
54+
55+
// Basic assertions
56+
assertNotNull("Optimization response should not be null", response)
57+
assertNotNull("Summary should be present", response.summary)
58+
assertTrue("Routes list should be present", response.routes != null)
59+
assertTrue("Routes should not be empty for solvable small case", response.routes.isNotEmpty())
60+
61+
val firstRoute = response.routes.first()
62+
assertTrue("Route steps should not be empty", firstRoute.steps.isNotEmpty())
63+
// Code is typically 0 for success in VROOM-like APIs; ensure non-negative as a safe check
64+
assertTrue("Response code should be non-negative", response.code >= 0)
65+
66+
// Optional additional sanity checks
67+
assertTrue("Total duration should be >= 0", response.summary.duration >= 0)
68+
assertTrue("Total service should be >= 0", response.summary.service >= 0)
69+
}
70+
}

ors-client/src/main/java/org/nitri/ors/api/OpenRouteServiceApi.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import org.nitri.ors.model.isochrones.IsochronesRequest
88
import org.nitri.ors.model.isochrones.IsochronesResponse
99
import org.nitri.ors.model.matrix.MatrixRequest
1010
import org.nitri.ors.model.matrix.MatrixResponse
11+
import org.nitri.ors.model.optimization.OptimizationRequest
12+
import org.nitri.ors.model.optimization.OptimizationResponse
1113
import org.nitri.ors.model.pois.PoisGeoJsonResponse
1214
import org.nitri.ors.model.pois.PoisRequest
1315
import org.nitri.ors.model.route.GeoJsonRouteResponse
@@ -117,4 +119,12 @@ interface OpenRouteServiceApi {
117119
suspend fun getPois(
118120
@Body request: PoisRequest
119121
): PoisGeoJsonResponse
122+
123+
// Optimization
124+
125+
@POST("optimization")
126+
suspend fun getOptimization(
127+
@Body request: OptimizationRequest
128+
): OptimizationResponse
129+
120130
}

ors-client/src/main/java/org/nitri/ors/client/OpenRouteServiceClient.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ object OpenRouteServiceClient {
4545
val retrofit = Retrofit.Builder()
4646
.baseUrl("https://api.openrouteservice.org/")
4747
.client(client)
48-
// Support both application/json and application/geo+json content types
49-
.addConverterFactory(json.asConverterFactory("application/geo+json".toMediaType()))
48+
// Prefer application/json for requests; also support application/geo+json responses
5049
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
50+
.addConverterFactory(json.asConverterFactory("application/geo+json".toMediaType()))
5151
.build()
5252

5353
return retrofit.create()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.nitri.ors.repository
2+
3+
import kotlinx.serialization.json.JsonElement
4+
import org.nitri.ors.api.OpenRouteServiceApi
5+
import org.nitri.ors.model.optimization.CustomMatrix
6+
import org.nitri.ors.model.optimization.Job
7+
import org.nitri.ors.model.optimization.OptimizationRequest
8+
import org.nitri.ors.model.optimization.OptimizationResponse
9+
import org.nitri.ors.model.optimization.Shipment
10+
import org.nitri.ors.model.optimization.Vehicle
11+
12+
/**
13+
* Repository for the OpenRouteService Optimization endpoint.
14+
*
15+
* This is a thin wrapper around the Retrofit API, similar to other repositories
16+
* in this package. The repository builds the OptimizationRequest from the
17+
* provided arguments.
18+
*/
19+
class OptimizationRepository(private val api: OpenRouteServiceApi) {
20+
21+
/**
22+
* Calls the ORS Optimization endpoint with provided arguments and builds the request.
23+
*
24+
* @param vehicles Required list of vehicles.
25+
* @param jobs Optional list of jobs.
26+
* @param shipments Optional list of shipments.
27+
* @param matrices Optional custom matrices keyed by profile.
28+
* @param options Optional free-form options.
29+
*/
30+
suspend fun getOptimization(
31+
vehicles: List<Vehicle>,
32+
jobs: List<Job>? = null,
33+
shipments: List<Shipment>? = null,
34+
matrices: Map<String, CustomMatrix>? = null,
35+
options: Map<String, JsonElement>? = null
36+
): OptimizationResponse {
37+
val request = OptimizationRequest(
38+
jobs = jobs,
39+
shipments = shipments,
40+
vehicles = vehicles,
41+
matrices = matrices,
42+
options = options
43+
)
44+
return api.getOptimization(request)
45+
}
46+
}

0 commit comments

Comments
 (0)