From d45921d950eb3020ac052dca0f236df875b806ab Mon Sep 17 00:00:00 2001 From: Kyle Madsen Date: Wed, 30 Sep 2020 08:39:51 -0700 Subject: [PATCH] Add command line interface --- Makefile | 3 + build.gradle | 1 + gradle/dependencies.gradle | 6 ++ services-cli/README.md | 19 ++++++ services-cli/build.gradle | 63 +++++++++++++++++++ .../com.mapbox.services.cli/MapboxJavaCli.kt | 58 +++++++++++++++++ .../validator/DirectionsResponseValidator.kt | 51 +++++++++++++++ .../services/cli/validator/ValidatorResult.kt | 11 ++++ .../DirectionsResponseValidatorTest.kt | 51 +++++++++++++++ .../cli/validator/MapboxJavaCliTest.kt | 42 +++++++++++++ .../services/cli/validator/SystemOutRule.kt | 29 +++++++++ .../src/test/resources/directions_v5.json | 1 + .../src/test/resources/geojson_feature.json | 13 ++++ settings.gradle | 1 + 14 files changed, 349 insertions(+) create mode 100644 services-cli/README.md create mode 100644 services-cli/build.gradle create mode 100644 services-cli/src/main/kotlin/com.mapbox.services.cli/MapboxJavaCli.kt create mode 100644 services-cli/src/main/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidator.kt create mode 100644 services-cli/src/main/kotlin/com/mapbox/services/cli/validator/ValidatorResult.kt create mode 100644 services-cli/src/test/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidatorTest.kt create mode 100644 services-cli/src/test/kotlin/com/mapbox/services/cli/validator/MapboxJavaCliTest.kt create mode 100644 services-cli/src/test/kotlin/com/mapbox/services/cli/validator/SystemOutRule.kt create mode 100644 services-cli/src/test/resources/directions_v5.json create mode 100644 services-cli/src/test/resources/geojson_feature.json diff --git a/Makefile b/Makefile index 3b201d2b9..1b3c17aa0 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ test: build-release: ./gradlew assemble +build-cli: + ./gradlew shadowJar + javadoc: mkdir documentation mkdir documentation/core/ diff --git a/build.gradle b/build.gradle index def776027..55438c74f 100644 --- a/build.gradle +++ b/build.gradle @@ -66,6 +66,7 @@ subprojects { testCompile dependenciesList.junit testCompile dependenciesList.hamcrestJunit testCompile dependenciesList.mockito + testCompile dependenciesList.googleTruth } } diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index e7e5bbf9a..8c37963c7 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -10,6 +10,7 @@ ext { okhttp3 : '3.12.7', mockito : '2.28.2', hamcrestJunit : '2.0.0.0', + googleTruth : '1.0.1', errorprone : '2.3.1', ] @@ -23,6 +24,8 @@ ext { bintray : '1.8.4', maven : '3.6.2', artifactory: '4.9.3', + kotlin : '1.3.72', + shadowJar : '4.0.4', ] dependenciesList = [ @@ -37,6 +40,7 @@ ext { okhttp3Logging : "com.squareup.okhttp3:logging-interceptor:${version.okhttp3}", okhttp3Mockwebserver: "com.squareup.okhttp3:mockwebserver:${version.okhttp3}", mockito : "org.mockito:mockito-core:${version.mockito}", + googleTruth : "com.google.truth:truth:${version.googleTruth}", hamcrestJunit : "org.hamcrest:hamcrest-junit:${version.hamcrestJunit}", errorprone : "com.google.errorprone:error_prone_core:${version.errorprone}" ] @@ -51,5 +55,7 @@ ext { bintray : "com.jfrog.bintray.gradle:gradle-bintray-plugin:${pluginVersion.bintray}", maven : "digital.wup:android-maven-publish:${pluginVersion.maven}", artifactory: "org.jfrog.buildinfo:build-info-extractor-gradle:${pluginVersion.artifactory}", + kotlin : "org.jetbrains.kotlin:kotlin-gradle-plugin:${pluginVersion.kotlin}", + shadowJar : "com.github.jengelman.gradle.plugins:shadow:${pluginVersion.shadowJar}", ] } \ No newline at end of file diff --git a/services-cli/README.md b/services-cli/README.md new file mode 100644 index 000000000..eecd37ed7 --- /dev/null +++ b/services-cli/README.md @@ -0,0 +1,19 @@ +# Mapbox Java CLI + +This is a wrapper on top of our mapbox-java services. This was made to be a fast +debugging and testing tool, that can be used to verify new and old json contracts. + +If you'd like to add a feature, add an issue to the mapbox-java repository +and we can help. Also, pull requests are always welcome! + +### Developing + +From the command line +1. cd mapbox-java +1. Build with ./gradlew shadowJar, or make build-cli +1. Run with java -jar services-cli/build/libs/services-cli-all.jar + +From Android Studio +1. Open mapbox-java with Android Studio +1. Set MapboxJavaCli as the main configuration +1. Open the runtime configuration and add your "Program arguments" diff --git a/services-cli/build.gradle b/services-cli/build.gradle new file mode 100644 index 000000000..2730660c8 --- /dev/null +++ b/services-cli/build.gradle @@ -0,0 +1,63 @@ +apply plugin: 'de.fuerstenau.buildconfig' +apply plugin: 'application' +apply plugin: 'kotlin' +apply plugin: "com.vanniktech.android.junit.jacoco" +apply plugin: 'com.github.johnrengelman.shadow' + +buildscript { + apply from: "../gradle/dependencies.gradle" + + repositories { + maven { url 'https://plugins.gradle.org/m2' } + // To use snapshots + //maven { url 'https://oss.jfrog.org/artifactory/oss-snapshot-local/' } + jcenter() + } + + dependencies { + classpath pluginDependencies.buildConfig + classpath pluginDependencies.kotlin + classpath pluginDependencies.shadowJar + } +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +dependencies { + // To use snapshots + //implementation "com.mapbox.mapboxsdk:mapbox-sdk-services:$VERSION_NAME" + + // Make sure to use ./gradlew shadowJar for this to work + implementation project(":services-core") + implementation project(":services-directions-models") + implementation project(":services-directions-refresh-models") + implementation project(":services-geojson") + implementation project(":services-directions") + implementation project(":services-directions-refresh") + + // The Apache Software License, Version 2.0 + // http://www.apache.org/licenses/LICENSE-2.0.txt + implementation("commons-cli:commons-cli:1.4") + + // Kotlin + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + + // Testing + testImplementation("org.jetbrains.kotlin:kotlin-test-junit") +} + +buildConfig { + packageName = 'com.mapbox.services.cli' + buildConfigField 'String', 'MAPBOX_ACCESS_TOKEN', System.getenv("MAPBOX_ACCESS_TOKEN") +} + +application { + mainClassName = 'com.mapbox.services.cli.MapboxJavaCli' +} + +jar { + manifest { + attributes('Main-Class': application.mainClassName) + } +} diff --git a/services-cli/src/main/kotlin/com.mapbox.services.cli/MapboxJavaCli.kt b/services-cli/src/main/kotlin/com.mapbox.services.cli/MapboxJavaCli.kt new file mode 100644 index 000000000..43691e468 --- /dev/null +++ b/services-cli/src/main/kotlin/com.mapbox.services.cli/MapboxJavaCli.kt @@ -0,0 +1,58 @@ +package com.mapbox.services.cli + +import com.google.gson.Gson +import com.mapbox.services.cli.validator.DirectionsResponseValidator +import org.apache.commons.cli.CommandLine +import org.apache.commons.cli.DefaultParser +import org.apache.commons.cli.HelpFormatter +import org.apache.commons.cli.Option +import org.apache.commons.cli.Options +import org.apache.commons.cli.ParseException + +/** + * Entry point for the command line interface. + */ +object MapboxJavaCli { + + private const val COMMAND_FILE_INPUT = "f" + private const val COMMAND_HELP = "h" + + @JvmStatic + fun main(args: Array) { + val options = Options() + .addOption(Option.builder(COMMAND_HELP) + .longOpt("help") + .desc("Shows this help message") + .build()) + .addOption(Option.builder(COMMAND_FILE_INPUT) + .longOpt("file") + .hasArg(true) + .desc("Path to a json file or directory") + .required() + .build()) + + try { + val commandLine = DefaultParser().parse(options, args) + parseCommands(commandLine, options) + } catch (pe: ParseException) { + println(pe.message) + printHelp(options) + } + } + + private fun parseCommands(commandLine: CommandLine, options: Options) { + if (commandLine.hasOption(COMMAND_HELP)) { + printHelp(options) + } + + val fileInput = commandLine.getOptionValue(COMMAND_FILE_INPUT) + val directionsResponseValidator = DirectionsResponseValidator() + val results = directionsResponseValidator.parse(fileInput) + print(Gson().toJson(results)) + } + + private fun printHelp(options: Options) { + val syntax = "java -jar services-cli/build/libs/services-cli-all.jar" + HelpFormatter().printHelp(syntax, options) + } +} diff --git a/services-cli/src/main/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidator.kt b/services-cli/src/main/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidator.kt new file mode 100644 index 000000000..d282dcd5c --- /dev/null +++ b/services-cli/src/main/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidator.kt @@ -0,0 +1,51 @@ +package com.mapbox.services.cli.validator + +import com.mapbox.api.directions.v5.models.DirectionsResponse +import java.io.File +import kotlin.text.Charsets.UTF_8 + +/** + * Validate DirectionsResponse json strings. + */ +class DirectionsResponseValidator { + + /** + * @param filePath path to the json file or directory + * @return results for all the files + */ + fun parse(filePath: String): List { + val inputFile = File(filePath) + + val results = mutableListOf() + inputFile.forEachFile { file -> + val result = validateJson(file) + results.add(result) + } + return results + } + + private fun File.forEachFile(function: (File) -> Unit) = walk() + .filter { !it.isDirectory } + .forEach(function) + + private fun validateJson(file: File): ValidatorResult { + val json = file.readText(UTF_8) + return try { + val directionsResponse = DirectionsResponse.fromJson(json) + val toJson = directionsResponse.toJson() + val convertsBack = json == toJson + ValidatorResult( + filename = file.name, + success = true, + convertsBack = convertsBack + ) + } catch (throwable: Throwable) { + ValidatorResult( + filename = file.name, + success = false, + convertsBack = false, + throwable = throwable + ) + } + } +} diff --git a/services-cli/src/main/kotlin/com/mapbox/services/cli/validator/ValidatorResult.kt b/services-cli/src/main/kotlin/com/mapbox/services/cli/validator/ValidatorResult.kt new file mode 100644 index 000000000..8ada31976 --- /dev/null +++ b/services-cli/src/main/kotlin/com/mapbox/services/cli/validator/ValidatorResult.kt @@ -0,0 +1,11 @@ +package com.mapbox.services.cli.validator + +import com.google.gson.annotations.SerializedName + +data class ValidatorResult( + val filename: String, + val success: Boolean, + @SerializedName("converts_back") + val convertsBack: Boolean, + val throwable: Throwable? = null +) diff --git a/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidatorTest.kt b/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidatorTest.kt new file mode 100644 index 000000000..226216cb4 --- /dev/null +++ b/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/DirectionsResponseValidatorTest.kt @@ -0,0 +1,51 @@ +package com.mapbox.services.cli.validator + +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import kotlin.test.assertTrue + +class DirectionsResponseValidatorTest { + + private val directionsResponseValidator = DirectionsResponseValidator() + + @Test + fun `should successfully read file with DirectionsResponse json`() { + val testFile = "./src/test/resources/directions_v5.json" + + val results = directionsResponseValidator.parse(testFile) + + assertTrue(results[0].success) + assertThat(results[0].filename).isEqualTo("directions_v5.json") + assertThat(results[0].throwable).isNull() + } + + @Test + fun `should detect if file is not DirectionsResponse json`() { + val testFile = "./src/test/resources/geojson_feature.json" + + val results = directionsResponseValidator.parse(testFile) + + assertThat(results[0].success).isFalse() + assertThat(results[0].filename).isEqualTo("geojson_feature.json") + assertThat(results[0].throwable).isNotNull() + assertThat(results[0].convertsBack).isFalse() + } + + @Test(expected = Exception::class) + fun `should crash when json does not exist`() { + val testFile = "not a real file path" + + val results = directionsResponseValidator.parse(testFile) + + assertTrue(results[0].success) + } + + @Test + fun `should parse every file in the directory`() { + val testFile = "./src/test/resources" + + val results = directionsResponseValidator.parse(testFile) + + assertThat(results.size).isGreaterThan(1) + } +} diff --git a/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/MapboxJavaCliTest.kt b/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/MapboxJavaCliTest.kt new file mode 100644 index 000000000..62689d674 --- /dev/null +++ b/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/MapboxJavaCliTest.kt @@ -0,0 +1,42 @@ +package com.mapbox.services.cli.validator + +import com.google.common.truth.Truth.assertThat +import com.mapbox.services.cli.MapboxJavaCli +import org.junit.Rule +import org.junit.Test + + +class MapboxJavaCliTest { + + @Rule + @JvmField + val systemOutRule = SystemOutRule() + + @Test + fun `should display successful results as json`() { + val testFile = "./src/test/resources/directions_v5.json" + + MapboxJavaCli.main(arrayOf("-f", testFile)) + + val expected = """[{"filename":"directions_v5.json","success":true,"converts_back":false}]""" + assertThat(systemOutRule.results()).isEqualTo(expected) + } + + @Test + fun `should not crash with missing arguments`() { + MapboxJavaCli.main(arrayOf()) + + val consoleOutput = systemOutRule.results() + assertThat(consoleOutput).contains("Missing required option") + } + + @Test + fun `should display help with other arguments`() { + val testFile = "./src/test/resources/directions_v5.json" + MapboxJavaCli.main(arrayOf("-h", "-f", testFile)) + + val consoleOutput = systemOutRule.results() + + assertThat(consoleOutput).contains("Shows this help message") + } +} diff --git a/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/SystemOutRule.kt b/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/SystemOutRule.kt new file mode 100644 index 000000000..c63ecbb2a --- /dev/null +++ b/services-cli/src/test/kotlin/com/mapbox/services/cli/validator/SystemOutRule.kt @@ -0,0 +1,29 @@ +package com.mapbox.services.cli.validator + +import org.junit.rules.TestWatcher +import org.junit.runner.Description +import java.io.ByteArrayOutputStream +import java.io.PrintStream + +/** + * Use this rule to test what has been printed to the console. + */ +class SystemOutRule : TestWatcher() { + + private val systemOutStream = ByteArrayOutputStream() + private lateinit var stdout: PrintStream + + /** + * In the test, assert that these results are expected. + */ + fun results(): String = systemOutStream.toString() + + override fun starting(description: Description) { + stdout = System.out + System.setOut(PrintStream(systemOutStream)) + } + + override fun finished(description: Description) { + System.setOut(stdout) + } +} diff --git a/services-cli/src/test/resources/directions_v5.json b/services-cli/src/test/resources/directions_v5.json new file mode 100644 index 000000000..ab8e45367 --- /dev/null +++ b/services-cli/src/test/resources/directions_v5.json @@ -0,0 +1 @@ +{"routes":[{"geometry":"mqreFhodjVjBjYjuAoK~HurAv}AuNnwAv^jqJoyBbyClsB~cGsfAxvCkjFpPcnDjaPg_QnbBwtJ~yDa~HlmDuyD|~AebDd{E_wZzqDwbD~gAqM","legs":[{"summary":"Bayshore Freeway, Bayshore Freeway","weight":4008.7,"duration":3722.6,"steps":[{"intersections":[{"out":0,"entry":[true],"bearings":[261],"location":[-122.416686,37.783425]},{"out":2,"in":0,"entry":[false,false,true,true],"bearings":[75,165,255,345],"location":[-122.417548,37.783315]},{"out":2,"in":0,"entry":[false,true,true,true],"bearings":[75,165,255,345],"location":[-122.419192,37.783106]}],"driving_side":"right","geometry":"mqreFhodjVTjDFn@`@vGN~BHfABXHvA","mode":"driving","maneuver":{"bearing_after":261,"bearing_before":0,"location":[-122.416686,37.783425],"modifier":"left","type":"depart","instruction":"Head west on Eddy Street"},"weight":236,"duration":211.60000000000002,"name":"Eddy Street","distance":362.7},{"intersections":[{"out":2,"in":0,"entry":[false,false,true,true],"bearings":[75,165,255,345],"location":[-122.42076,37.782907]},{"out":1,"in":0,"entry":[false,true,true,false],"bearings":[75,165,255,345],"location":[-122.42091,37.782888]},{"out":1,"in":3,"entry":[false,true,true,false],"bearings":[75,165,255,345],"location":[-122.420722,37.781954]},{"out":1,"in":3,"entry":[false,true,false,false],"bearings":[75,165,255,345],"location":[-122.420534,37.781023]},{"out":1,"in":3,"entry":[false,true,true,false],"bearings":[90,165,255,345],"location":[-122.420342,37.780077]},{"out":1,"in":3,"entry":[false,true,true,false],"bearings":[75,165,255,345],"location":[-122.419972,37.778242]},{"out":1,"in":3,"entry":[false,true,true,false],"bearings":[75,165,255,345],"location":[-122.419782,37.777295]},{"out":1,"in":3,"entry":[false,true,true,false],"bearings":[75,165,255,345],"location":[-122.419594,37.776367]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[165,255,345],"location":[-122.419398,37.775431]},{"out":1,"in":3,"entry":[false,true,true,false],"bearings":[45,165,225,345],"location":[-122.41935,37.775193]},{"out":1,"in":3,"entry":[false,true,false,false],"bearings":[45,165,225,345],"location":[-122.419314,37.775061]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[165,210,345],"location":[-122.418875,37.773667]},{"out":1,"in":4,"entry":[false,true,true,false,false],"bearings":[45,165,225,315,345],"location":[-122.418702,37.773081]},{"out":1,"in":3,"entry":[false,true,false,false],"bearings":[30,165,210,345],"location":[-122.418631,37.772842]},{"out":0,"in":2,"entry":[true,false,false],"bearings":[165,270,345],"location":[-122.418498,37.772399]},{"out":1,"in":2,"entry":[true,true,false],"bearings":[75,165,345],"location":[-122.41845,37.772238]},{"out":1,"in":2,"entry":[false,true,false],"bearings":[120,165,345],"location":[-122.418146,37.771238]},{"out":1,"in":2,"entry":[true,true,false],"bearings":[135,165,345],"location":[-122.418096,37.771089]},{"out":0,"in":2,"entry":[true,true,false],"bearings":[165,270,345],"location":[-122.418033,37.770901]},{"out":1,"in":0,"entry":[false,true,true,false],"bearings":[0,195,210,270],"location":[-122.417742,37.770207]},{"out":2,"in":0,"entry":[false,false,true,false],"bearings":[15,105,195,285],"location":[-122.417803,37.769889]},{"out":2,"in":0,"entry":[false,true,true,false],"bearings":[15,105,180,285],"location":[-122.417834,37.769712]}],"driving_side":"right","geometry":"enreFvhejVB\\RChAMlAONCLAzAS|@KPCLA`BSx@KPC^EvC]zAQz@M^EPChDa@pBUp@ITE|AQxASB?^ENCJCFADATAZIVEjEcAtBc@n@MvAY^IfE{@\\IRGPEf@ORMPOLIHCJ?P@D?~@Jb@D^Bt@H","mode":"driving","maneuver":{"bearing_after":260,"bearing_before":260,"location":[-122.42076,37.782907],"modifier":"left","type":"turn","instruction":"Turn left onto Van Ness Avenue (US 101 South)"},"ref":"US 101 South","weight":480.9,"duration":308.29999999999995,"name":"Van Ness Avenue (US 101 South)","distance":1559.1},{"distance":379.8,"name":"US 101 South","ref":"US 101 South","maneuver":{"bearing_after":201,"bearing_before":187,"location":[-122.417903,37.769281],"modifier":"straight","type":"off ramp","instruction":"Take the ramp towards US 101 South: Oakland"},"destinations":"US 101 South, I-80 East: Oakland, San Jose","weight":49,"mode":"driving","geometry":"_yoeFzvdjVXLLJLJHNFPDT?TARCRGPILKLMHMBMBM?KCMEKGIIIKGOEQCQ?Q?U@SFu@Dc@B]Fw@Bo@Bk@Io@","intersections":[{"classes":["motorway"],"out":2,"in":0,"entry":[false,true,true,false],"bearings":[0,180,195,345],"location":[-122.417903,37.769281]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false],"bearings":[15,180],"location":[-122.419,37.769346]}],"duration":42.2,"driving_side":"right"},{"intersections":[{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[90,255,285],"location":[-122.416662,37.769596]},{"classes":["motorway"],"out":1,"in":2,"entry":[true,true,false],"bearings":[102,108,282],"location":[-122.40981,37.769161]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[174,353,358],"location":[-122.405473,37.767261]},{"classes":["motorway"],"out":1,"in":2,"entry":[false,true,false],"bearings":[0,180,345],"location":[-122.405244,37.766048]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,true],"bearings":[0,180,195],"location":[-122.402999,37.752554]},{"classes":["motorway"],"out":2,"in":1,"entry":[false,false,true],"bearings":[0,15,195],"location":[-122.404558,37.746941]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,true],"bearings":[7,180,187],"location":[-122.408143,37.739469]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[155,332,335],"location":[-122.406401,37.734438]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[150,180,330],"location":[-122.405674,37.733191]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[165,330,345],"location":[-122.403995,37.730114]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[163,341,346],"location":[-122.402483,37.726603]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[163,168,343],"location":[-122.401701,37.724557]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[165,180,345],"location":[-122.400278,37.720955]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,315,330],"location":[-122.397974,37.714805]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[165,180,345],"location":[-122.39554,37.710237]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false],"bearings":[165,345],"location":[-122.395121,37.708328]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[170,347,350],"location":[-122.393825,37.702429]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[165,180,345],"location":[-122.391826,37.693636]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[170,345,350],"location":[-122.3906,37.688244]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,true],"bearings":[30,210,225],"location":[-122.392891,37.669787]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,true],"bearings":[30,210,225],"location":[-122.395051,37.667539]},{"classes":["motorway"],"out":2,"in":1,"entry":[false,false,true],"bearings":[46,50,231],"location":[-122.39982,37.663398]},{"classes":["motorway"],"out":2,"in":1,"entry":[false,false,true],"bearings":[30,45,210],"location":[-122.403926,37.660623]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,true],"bearings":[15,195,210],"location":[-122.405731,37.65805]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[176,181,356],"location":[-122.406979,37.651445]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,false],"bearings":[0,180,345],"location":[-122.406419,37.64457]},{"classes":["motorway"],"out":1,"in":0,"entry":[false,true,true],"bearings":[0,165,195],"location":[-122.406082,37.641332]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[150,165,345],"location":[-122.405024,37.63824]},{"classes":["motorway"],"out":1,"in":2,"entry":[false,true,false],"bearings":[0,180,345],"location":[-122.402719,37.630324]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[166,341,345],"location":[-122.401464,37.62492]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[162,342,345],"location":[-122.398689,37.616736]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[135,300,315],"location":[-122.394473,37.611514]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[128,308,309],"location":[-122.391675,37.609715]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[129,134,309],"location":[-122.384799,37.605291]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[135,300,315],"location":[-122.378646,37.601292]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[135,300,315],"location":[-122.376557,37.599922]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[130,136,309],"location":[-122.364079,37.591793]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,285,300],"location":[-122.357438,37.587965]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.325833,37.581641]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[139,314,319],"location":[-122.322934,37.578971]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.316743,37.573261]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[139,316,319],"location":[-122.310821,37.567812]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.302578,37.560185]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,315,330],"location":[-122.293655,37.550567]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[150,315,330],"location":[-122.293005,37.549875]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[150,315,330],"location":[-122.292169,37.548986]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[144,149,324],"location":[-122.291949,37.548743]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,315,330],"location":[-122.286169,37.542512]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,315,330],"location":[-122.283856,37.53998]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.273979,37.529546]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[138,313,318],"location":[-122.262626,37.51954]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[138,141,318],"location":[-122.260906,37.518025]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[138,314,318],"location":[-122.247718,37.506343]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[138,315,318],"location":[-122.242977,37.502159]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[137,142,317],"location":[-122.239937,37.499488]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[110,284,290],"location":[-122.231907,37.495907]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[110,283,290],"location":[-122.228972,37.495072]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[120,135,300],"location":[-122.218915,37.491223]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-122.205884,37.487457]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[107,110,285],"location":[-122.185632,37.484733]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[120,285,300],"location":[-122.179679,37.482856]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[126,302,307],"location":[-122.177095,37.481497]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[120,135,300],"location":[-122.155045,37.468654]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[126,305,307],"location":[-122.152581,37.467179]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[120,135,300],"location":[-122.144516,37.462442]},{"classes":["motorway"],"out":0,"in":1,"entry":[true,false,false],"bearings":[126,304,306],"location":[-122.136462,37.457738]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[131,141,308],"location":[-122.12693,37.452112]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[140,317,320],"location":[-122.118132,37.444081]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.103307,37.429953]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.101751,37.428459]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[135,300,315],"location":[-122.092643,37.42097]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,315],"location":[-122.09244,37.420823]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[133,309,312],"location":[-122.089184,37.418478]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[120,285,300],"location":[-122.081848,37.413404]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[120,135,300],"location":[-122.081263,37.413111]},{"classes":["motorway"],"lanes":[{"valid":false,"indications":["left"]},{"valid":true,"indications":["straight"]},{"valid":true,"indications":["straight"]},{"valid":true,"indications":["straight"]},{"valid":true,"indications":["straight"]},{"valid":true,"indications":["right"]}],"out":1,"in":2,"entry":[true,true,false],"bearings":[105,120,300],"location":[-122.078361,37.411892]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[118,124,297],"location":[-122.076323,37.411054]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-122.067607,37.407809]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,110,286],"location":[-122.067189,37.407713]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-122.063708,37.406961]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-122.056615,37.405407]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-122.047017,37.403049]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-122.036066,37.400658]},{"classes":["motorway"],"out":0,"in":3,"entry":[true,true,false,false],"bearings":[105,120,270,285],"location":[-122.03242,37.39989]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,279,286],"location":[-122.027075,37.398693]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,280,285],"location":[-122.024811,37.398202]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,111,285],"location":[-122.017288,37.396552]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-122.012976,37.395607]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-122.012709,37.395542]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[107,280,285],"location":[-122.008838,37.394702]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-122.000135,37.392318]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[111,284,291],"location":[-121.994151,37.390522]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[110,282,290],"location":[-121.991164,37.389654]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-121.983628,37.387548]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[110,287,290],"location":[-121.974838,37.385032]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-121.972437,37.384341]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-121.969543,37.383509]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[110,284,290],"location":[-121.957291,37.380021]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-121.945834,37.377446]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-121.941787,37.376663]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-121.941403,37.376591]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[105,270,285],"location":[-121.939052,37.376128]}],"driving_side":"right","geometry":"_{oeFbodjVBm@Bm@@oABqANaR@a@?c@@a@@a@@_@Bc@B]Ba@Dc@De@XaDb@oCHg@Fg@Fk@Bc@Be@Bi@Bk@Fi@Fi@Hg@La@J]JYL]HQHOHQHMLSLQPSPQTOVMNGNE\\GJAtBOj@GnAUhGWd@C^?f@@d@@f@Dd@Fb@Ff@J`@Ld@P`@Pb@R`@T~Az@\\P^P^L^J^H^D^D^@`@@`@C`@Cb@Gb@Ib@O^O`@S^U`@Y^_@\\]Zc@Zc@Xc@p@eAV_@Xa@V[V[XUXWZSZQ`@S`@M^Kb@Ib@Gf@Ed@Cd@CbLg@r@Ct@Ap@An@@r@Dp@Ft@Hj@Jj@JzFnA`IdB~FnAtH`Bp@Nt@Rn@Vl@Xn@\\j@^l@b@nElDVRVPn@b@p@^n@Zp@Xt@Vn@Px@Nr@Lv@Jv@FfAFr@Br@At@Ar@Ct@El@Ir@Kr@Mt@Qp@Ql@Sj@Sn@Wt@]b@SlAm@tDiBtAq@bD_BtC}Az@c@|@a@jAg@x@]dAa@bBo@f@QrAg@jAa@lA]nEyA^K~EaBjFyAjDaArBm@rAa@dHyBdBe@zBk@v@Sx@Q|Du@lCc@f@KvGmAl@Mp@Op@Sn@UfAc@r@]n@]n@c@p@g@fAw@~CgCVQTOj@]j@[j@[l@Yh@Up@Ul@Sp@Op@On@KfAObBWnC_@nBWfBUTEdEi@`IcArSsC|u@oKv`@uFze@{GhC_@pDk@pASnAQfAMjAIx@C~@?z@?`AB`AF`AL~@Nv@L|@TdAZ`A\\v@X|@Zx@\\|@\\x@\\LFvBbA`Af@l@\\n@\\j@\\l@^j@^l@`@j@`@j@b@h@`@l@d@h@b@h@d@h@d@p@l@`MnLdD~ChBdBf@f@f@d@f@h@f@h@j@n@b@h@d@l@d@n@`@j@b@n@`@n@`@p@b@r@^p@`@t@hJrP^r@d@t@d@n@d@p@n@t@h@j@l@j@r@j@j@b@l@`@j@Zn@\\n@Xp@X|An@vF~Bp@Vr@Vr@Rr@Pt@Nv@Nn@Hr@Fn@Fr@Dp@@p@@v@?r@At@CtESnAEfGW~@CrDO`AE`X}@bNk@bDWf@EpAQ~AYtAY~@WhA]rAe@zAk@~GyClAc@`A[bA]z@Ux@U~@S`AS~@ObAM`AMbAI`BKzDUzGg@nG]pAKvAQzASfASjAWtEeAnCs@f@EvAYjQkEfGyAzOuDbCi@VIfAYpAc@vAk@pAm@vAw@jAu@rAcAjAcAbA{@hAkA~@gAbAoAzB}CdJmPdHuMzAcC|CgFtI}OxJiQdLcSpGaLvCgF`FuInDkGvTk`@zCwFlAwBlCyEnKcRz@_Bx@{Ax@cBt@gBl@gBl@kBh@oBbAeF^oCXiCNeBLsBH_CB}B@{BHmJXg]NcTPsTRmUDeDH{BJqATiBZeBb@gBh@eBp@_Br@qAv@kAx@aAlCyChNuOtOcQ|OiQvQkSzEmFdZq\\`SuTnScUhBsBxA_B\\a@fAgAhAcApAkA~GwFbByAvCmChD_DdB{AlBkBjDgDvAqA|AwAbLeKhCaCpDgDp@k@hP_OlEcEbCyB`JeIhBcBn@k@p@m@xDeDrBiBfLiKzUcT|@y@`KcJdA_AbAaAlAkAdAgA~@cAbAiA~@gApCeDbQsStPaS`IkJHKX]~IkKnB}B|DyEfGgHpA_BtBcCjHsIlByBdIqJvIeK|DqEzQiTnFoGvFyGzIiKfGgHvCmDtBiCv@aAv@aAr@eAr@kAl@iAl@oAN[JUTi@j@_Bb@qA`@qA^{AZwAZwAzCiPfDkQv@gEZcB\\gBXqAXoAXmAd@iB\\sAb@{A`@wAb@wAd@sAd@yAfI}U|CcJd@wAd@wAb@wA`@yARu@Lc@Nm@Nk@^{AXqAZwA\\cBRcAX_BV{AV_BT_BT}ARaBP_BP_BNaBLaBh@gIzJ__BLaBJgBLaBLaBNaBN_BP_BRaBR}ATaBRwAV}AV}AX_BX{AZ{AZ}A\\{A^{A^yA^wAb@yAb@wAf@uAf@uAh@sAj@sAl@oAl@oALOjTgd@~CuGdK}SdXwi@hCgFfK}SpGyMRShSya@hHqNpIiQ|NcZzA}C|]us@Xm@v@yAt@sA~@}Af@u@t@gAv@eAx@aAz@aAdSgTbIqInH_IzDeEfRgS`@a@rQoR`]q^X[rKeL|BeCjDqDdKyKnAsAnAuAjAsAfAsAnA_BhA}AxAwBxA}BpM}R\\g@tGcK|DgGtKkP~HyLd@s@^m@^s@p@kAn@oAl@qAj@oAf@sAPa@|@mCnCyId@{AfDwK`CyHtHwVV_AXcAVaATaATaATgAN{@PaANaAPiARsAh@kEjBkNtDaY~BgQ^gC`@kCd@iCrB{Kl@qD^aC\\eCZ}BrBmOtJot@n@}Ev@_GxCyUnE}[^mC`BeMhI_n@zD}YLu@fDeWdAaH|C{PvFmZhBqJ`BwHzCcO^mB~@wElAoGn@gDbAoFxA_ItEiW|Iie@xCsOhC_NdDcQl@}CN_ApFkYrF{YtCkOjB{JfA{GpBqOpBmPhB{O|CgXLmAzAuMjCaUh@eEX_CZyBj@uD\\_C","mode":"driving","maneuver":{"bearing_after":94,"bearing_before":73,"location":[-122.416662,37.769596],"modifier":"slight left","type":"merge","instruction":"Merge left onto US 101 South"},"ref":"US 101 South","weight":2830.2000000000003,"duration":2819.2000000000007,"name":"Central Freeway (US 101 South)","distance":70046.4},{"distance":4798.2,"name":"","maneuver":{"bearing_after":112,"bearing_before":106,"location":[-121.931731,37.374579],"modifier":"slight right","type":"off ramp","instruction":"Take exit 390 towards CA 87 South: Guadalupe Parkway"},"destinations":"CA 87 South: Guadalupe Parkway","exits":"390","intersections":[{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[105,120,285],"location":[-121.931731,37.374579]},{"classes":["motorway"],"lanes":[{"valid":true,"indications":["straight"]},{"valid":true,"indications":["straight"]}],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,300,330],"location":[-121.926597,37.37012]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[128,138,308],"location":[-121.923722,37.367884]},{"classes":["motorway"],"out":1,"in":3,"entry":[false,true,true,false],"bearings":[0,150,180,330],"location":[-121.918933,37.364245]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,315,330],"location":[-121.915678,37.359877]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,true,false],"bearings":[135,150,330],"location":[-121.908322,37.349121]},{"classes":["motorway"],"out":0,"in":2,"entry":[true,false,false],"bearings":[150,330,345],"location":[-121.901664,37.343143]}],"duration":192.39999999999998,"driving_side":"right","weight":206.7,"mode":"driving","geometry":"cvbcFhxegV~@{DTkA~@mEh@eBZq@Zi@~@kAj@k@j@_@VMVK^M\\IzCw@pA_@p@U`Aa@ZOp@c@d@_@Z[f@g@`@i@j@y@NYf@{@jAyBpAcCpFmKr@qAv@mA|@oA~@mAhAoAbAcAtAkATQFEz@o@nAy@tUyOlM{IvE_DpGkE|ByA~CkBxBeAzCuAhIqDl@Yl@]t@e@r@g@jB}AlB_Cd@s@b@s@d@{@b@_A`@eA`AeCbA_Cv@uAx@kAp@}@p@y@r@q@r@o@f@_@f@]`@Uf@[|@c@dBq@dCaA~As@`Ag@`@UdGsD"},{"distance":508.9,"name":"","maneuver":{"bearing_after":171,"bearing_before":150,"location":[-121.900192,37.340845],"modifier":"slight right","type":"off ramp","instruction":"Take exit 6B towards Julian Street"},"destinations":"Julian Street, Saint James Street","exits":"6B","intersections":[{"classes":["motorway"],"out":1,"in":2,"entry":[true,true,false],"bearings":[150,165,330],"location":[-121.900192,37.340845]}],"duration":44.8,"driving_side":"right","weight":57,"mode":"driving","geometry":"ic|bFds_gV^C|CmBl@[bDyAVKZI^Gh@?`@Br@NPBf@HXBT?^EXId@QVKTI"},{"intersections":[{"lanes":[{"valid":true,"indications":["left"]},{"valid":true,"indications":["straight","left"]},{"valid":false,"indications":["right"]}],"out":1,"in":3,"entry":[false,true,true,false],"bearings":[60,150,240,345],"location":[-121.898785,37.336552]},{"lanes":[{"valid":false,"indications":["left"]},{"valid":true,"indications":["straight","left"]},{"valid":false,"indications":["right"]}],"out":1,"in":3,"entry":[true,true,false,false],"bearings":[60,165,240,330],"location":[-121.898691,37.336402]}],"driving_side":"right","geometry":"mh{bFlj_gV\\SRIdAw@bBoARU","mode":"driving","maneuver":{"bearing_after":153,"bearing_before":158,"location":[-121.898785,37.336552],"modifier":"straight","type":"new name","instruction":"Continue onto North Almaden Boulevard"},"weight":75.1,"pronunciation":"ˈnoɹθ ˈɔlmədən ˈbʊləvɑɹd","duration":43.5,"name":"North Almaden Boulevard","distance":157.5},{"intersections":[{"out":1,"in":2,"entry":[true,true,false],"bearings":[105,240,315],"location":[-121.897852,37.335352]}],"driving_side":"right","geometry":"}`{bFpd_gVLVx@tBPd@Vr@DLb@lALb@`AdCJV","mode":"driving","maneuver":{"bearing_after":236,"bearing_before":136,"location":[-121.897852,37.335352],"modifier":"right","type":"turn","instruction":"Turn right onto West Saint John Street"},"weight":58.6,"duration":45.4,"name":"West Saint John Street","distance":267.1},{"intersections":[{"out":1,"in":0,"entry":[false,true,true,true],"bearings":[60,165,240,315],"location":[-121.900438,37.334113]}],"driving_side":"right","geometry":"eyzbFvt_gVVCVGlBG","mode":"driving","maneuver":{"bearing_after":171,"bearing_before":237,"location":[-121.900438,37.334113],"modifier":"left","type":"turn","instruction":"Turn left onto North Autumn Street"},"weight":15.2,"duration":15.2,"name":"North Autumn Street","distance":89.1},{"intersections":[{"in":0,"entry":[true],"bearings":[357],"location":[-121.90034,37.333317]}],"driving_side":"right","geometry":"gtzbFbt_gV","mode":"driving","maneuver":{"bearing_after":0,"bearing_before":177,"location":[-121.90034,37.333317],"modifier":"left","type":"arrive","instruction":"You have arrived at your destination, on the left"},"weight":0,"duration":0,"name":"North Autumn Street","distance":0}],"distance":78168.7}],"weight_name":"routability","weight":4008.7,"duration":3722.6,"distance":78168.7}],"waypoints":[{"name":"Eddy Street","location":[-122.416686,37.783425]},{"name":"North Autumn Street","location":[-121.90034,37.333317]}],"code":"Ok","uuid":"cjhk3ouqm1voa3vp51vsd738n"} \ No newline at end of file diff --git a/services-cli/src/test/resources/geojson_feature.json b/services-cli/src/test/resources/geojson_feature.json new file mode 100644 index 000000000..aeb1dcd2c --- /dev/null +++ b/services-cli/src/test/resources/geojson_feature.json @@ -0,0 +1,13 @@ +{ + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + 125.6, + 10.1 + ] + }, + "properties": { + "name": "Dinagat Islands" + } +} diff --git a/settings.gradle b/settings.gradle index 1542fc127..2f5a49e53 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,3 +18,4 @@ include ':services-directions-refresh' include ':services-directions-refresh-models' include ':services-isochrone' include 'samples' +include 'services-cli'