diff --git a/client-next/package-lock.json b/client-next/package-lock.json index 20e7e0b83c1..75fec4ca86c 100644 --- a/client-next/package-lock.json +++ b/client-next/package-lock.json @@ -26,21 +26,21 @@ "@testing-library/react": "15.0.7", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", - "@typescript-eslint/eslint-plugin": "7.10.0", - "@typescript-eslint/parser": "7.10.0", + "@typescript-eslint/eslint-plugin": "7.11.0", + "@typescript-eslint/parser": "7.11.0", "@vitejs/plugin-react": "4.3.0", "@vitest/coverage-v8": "1.6.0", "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "2.29.1", "eslint-plugin-jsx-a11y": "6.8.0", - "eslint-plugin-react": "7.34.1", + "eslint-plugin-react": "7.34.2", "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-react-refresh": "0.4.7", "jsdom": "24.1.0", - "prettier": "3.2.5", + "prettier": "3.3.0", "typescript": "5.4.5", - "vite": "5.2.11", + "vite": "5.2.12", "vitest": "1.6.0" } }, @@ -3810,17 +3810,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", - "integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz", + "integrity": "sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/type-utils": "7.10.0", - "@typescript-eslint/utils": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/type-utils": "7.11.0", + "@typescript-eslint/utils": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3844,16 +3844,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz", - "integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.11.0.tgz", + "integrity": "sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4" }, "engines": { @@ -3873,14 +3873,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz", - "integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz", + "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0" + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3891,14 +3891,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz", - "integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz", + "integrity": "sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.10.0", - "@typescript-eslint/utils": "7.10.0", + "@typescript-eslint/typescript-estree": "7.11.0", + "@typescript-eslint/utils": "7.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -3919,9 +3919,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz", - "integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", "dev": true, "license": "MIT", "engines": { @@ -3933,14 +3933,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz", - "integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz", + "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/visitor-keys": "7.10.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/visitor-keys": "7.11.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3975,16 +3975,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz", - "integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz", + "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.10.0", - "@typescript-eslint/types": "7.10.0", - "@typescript-eslint/typescript-estree": "7.10.0" + "@typescript-eslint/scope-manager": "7.11.0", + "@typescript-eslint/types": "7.11.0", + "@typescript-eslint/typescript-estree": "7.11.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3998,13 +3998,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz", - "integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz", + "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.10.0", + "@typescript-eslint/types": "7.11.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -5679,10 +5679,11 @@ } }, "node_modules/es-abstract": { - "version": "1.23.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", - "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -5723,11 +5724,11 @@ "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" }, @@ -5760,14 +5761,15 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", - "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", @@ -6135,29 +6137,30 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", - "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "version": "7.34.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz", + "integrity": "sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", "array.prototype.toreversed": "^1.1.2", "array.prototype.tosorted": "^1.1.3", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", + "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.hasown": "^1.1.4", + "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" + "string.prototype.matchall": "^4.0.11" }, "engines": { "node": ">=4" @@ -6193,6 +6196,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6203,6 +6207,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -6215,6 +6220,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6227,6 +6233,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9379,10 +9386,11 @@ } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.0.tgz", + "integrity": "sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -11135,10 +11143,11 @@ } }, "node_modules/vite": { - "version": "5.2.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", - "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", + "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.20.1", "postcss": "^8.4.38", diff --git a/client-next/package.json b/client-next/package.json index 9195702c1ad..17171945476 100644 --- a/client-next/package.json +++ b/client-next/package.json @@ -35,21 +35,21 @@ "@testing-library/react": "15.0.7", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", - "@typescript-eslint/eslint-plugin": "7.10.0", - "@typescript-eslint/parser": "7.10.0", + "@typescript-eslint/eslint-plugin": "7.11.0", + "@typescript-eslint/parser": "7.11.0", "@vitejs/plugin-react": "4.3.0", "@vitest/coverage-v8": "1.6.0", "eslint": "8.57.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-import": "2.29.1", "eslint-plugin-jsx-a11y": "6.8.0", - "eslint-plugin-react": "7.34.1", + "eslint-plugin-react": "7.34.2", "eslint-plugin-react-hooks": "4.6.2", "eslint-plugin-react-refresh": "0.4.7", "jsdom": "24.1.0", - "prettier": "3.2.5", + "prettier": "3.3.0", "typescript": "5.4.5", - "vite": "5.2.11", + "vite": "5.2.12", "vitest": "1.6.0" } } diff --git a/docs/Changelog.md b/docs/Changelog.md index 7b0982efd14..9df32c081af 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -23,6 +23,8 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle - Document and validate timeRange GraphQL parameter [#5834](https://github.com/opentripplanner/OpenTripPlanner/pull/5834) - Log the origin of a request that causes a transfer cache addition. [#5874](https://github.com/opentripplanner/OpenTripPlanner/pull/5874) - Fix handling of missing aimed departure time [#5865](https://github.com/opentripplanner/OpenTripPlanner/pull/5865) +- Add OTP request timeout GraphQL instrumentation [#5881](https://github.com/opentripplanner/OpenTripPlanner/pull/5881) +- Add feed publisher name and url to GTFS GraphQL API [#5835](https://github.com/opentripplanner/OpenTripPlanner/pull/5835) [](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE) ## 2.5.0 (2024-03-13) diff --git a/pom.xml b/pom.xml index c06bfcafeb1..5880d9dcc62 100644 --- a/pom.xml +++ b/pom.xml @@ -363,7 +363,7 @@ properly if some input files are missing a terminating newline) --> org.apache.maven.plugins maven-shade-plugin - 3.5.3 + 3.6.0 package @@ -444,7 +444,7 @@ com.google.cloud.tools jib-maven-plugin - 3.4.2 + 3.4.3 org.opentripplanner.standalone.OTPMain diff --git a/src/client/debug-client-preview/index.html b/src/client/debug-client-preview/index.html index 91f07c43b9a..717fce1baf2 100644 --- a/src/client/debug-client-preview/index.html +++ b/src/client/debug-client-preview/index.html @@ -5,8 +5,8 @@ OTP Debug Client - - + +
diff --git a/src/ext-test/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPathTest.java b/src/ext-test/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPathTest.java index 8bd3abee785..3d37de02af4 100644 --- a/src/ext-test/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPathTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPathTest.java @@ -21,7 +21,7 @@ class FlexPathTest { static List cases() { return List.of( - Arguments.of(TimePenalty.ZERO, THIRTY_MINS_IN_SECONDS), + Arguments.of(TimePenalty.NONE, THIRTY_MINS_IN_SECONDS), Arguments.of(TimePenalty.of(Duration.ofMinutes(10), 1), 2400), Arguments.of(TimePenalty.of(Duration.ofMinutes(10), 1.5f), 3300), Arguments.of(TimePenalty.of(Duration.ZERO, 3), 5400) @@ -30,8 +30,8 @@ static List cases() { @ParameterizedTest @MethodSource("cases") - void calculate(TimePenalty mod, int expectedSeconds) { - var modified = PATH.withDurationModifier(mod); + void calculate(TimePenalty penalty, int expectedSeconds) { + var modified = PATH.withTimePenalty(penalty); assertEquals(expectedSeconds, modified.durationSeconds); assertEquals(LineStrings.SIMPLE, modified.getGeometry()); } diff --git a/src/ext-test/java/org/opentripplanner/ext/flex/trip/FlexTripsMapperTest.java b/src/ext-test/java/org/opentripplanner/ext/flex/trip/FlexTripsMapperTest.java new file mode 100644 index 00000000000..0d0376bbd32 --- /dev/null +++ b/src/ext-test/java/org/opentripplanner/ext/flex/trip/FlexTripsMapperTest.java @@ -0,0 +1,37 @@ +package org.opentripplanner.ext.flex.trip; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.opentripplanner.graph_builder.issue.api.DataImportIssueStore.NOOP; + +import java.util.List; +import org.junit.jupiter.api.Test; +import org.opentripplanner.ext.flex.FlexStopTimesForTest; +import org.opentripplanner.ext.flex.FlexTripsMapper; +import org.opentripplanner.ext.flex.flexpathcalculator.DirectFlexPathCalculator; +import org.opentripplanner.model.StopTime; +import org.opentripplanner.model.impl.OtpTransitServiceBuilder; +import org.opentripplanner.transit.model._data.TransitModelForTest; +import org.opentripplanner.transit.service.StopModel; + +class FlexTripsMapperTest { + + @Test + void defaultTimePenalty() { + var builder = new OtpTransitServiceBuilder(StopModel.of().build(), NOOP); + var stopTimes = List.of(stopTime(0), stopTime(1)); + builder.getStopTimesSortedByTrip().addAll(stopTimes); + var trips = FlexTripsMapper.createFlexTrips(builder, NOOP); + assertEquals("[UnscheduledTrip{F:flex-1}]", trips.toString()); + var unscheduled = (UnscheduledTrip) trips.getFirst(); + var unchanged = unscheduled.flexPathCalculator(new DirectFlexPathCalculator()); + assertInstanceOf(DirectFlexPathCalculator.class, unchanged); + } + + private static StopTime stopTime(int seq) { + var st = FlexStopTimesForTest.area("08:00", "18:00"); + st.setTrip(TransitModelForTest.trip("flex-1").build()); + st.setStopSequence(seq); + return st; + } +} diff --git a/src/ext-test/java/org/opentripplanner/ext/geocoder/LuceneIndexTest.java b/src/ext-test/java/org/opentripplanner/ext/geocoder/LuceneIndexTest.java index b1fb33dfdd3..cee6cf3a2d8 100644 --- a/src/ext-test/java/org/opentripplanner/ext/geocoder/LuceneIndexTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/geocoder/LuceneIndexTest.java @@ -10,7 +10,9 @@ import java.time.LocalDate; import java.util.List; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; +import javax.annotation.Nonnull; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -213,13 +215,13 @@ class StopClusters { ) void stopClustersWithTypos(String searchTerm) { var results = index.queryStopClusters(searchTerm).toList(); - var ids = results.stream().map(StopCluster::id).toList(); + var ids = results.stream().map(primaryId()).toList(); assertEquals(List.of(ALEXANDERPLATZ_STATION.getId()), ids); } @Test void fuzzyStopClusters() { - var result1 = index.queryStopClusters("arts").map(StopCluster::id).toList(); + var result1 = index.queryStopClusters("arts").map(primaryId()).toList(); assertEquals(List.of(ARTS_CENTER.getId()), result1); } @@ -227,7 +229,7 @@ void fuzzyStopClusters() { void deduplicatedStopClusters() { var result = index.queryStopClusters("lich").toList(); assertEquals(1, result.size()); - assertEquals(LICHTERFELDE_OST_1.getName().toString(), result.getFirst().name()); + assertEquals(LICHTERFELDE_OST_1.getName().toString(), result.getFirst().primary().name()); } @ParameterizedTest @@ -259,7 +261,7 @@ void deduplicatedStopClusters() { } ) void stopClustersWithSpace(String query) { - var result = index.queryStopClusters(query).map(StopCluster::id).toList(); + var result = index.queryStopClusters(query).map(primaryId()).toList(); assertEquals(List.of(FIVE_POINTS_STATION.getId()), result); } @@ -268,24 +270,28 @@ void stopClustersWithSpace(String query) { void fuzzyStopCode(String query) { var result = index.queryStopClusters(query).toList(); assertEquals(1, result.size()); - assertEquals(ARTS_CENTER.getName().toString(), result.getFirst().name()); + assertEquals(ARTS_CENTER.getName().toString(), result.getFirst().primary().name()); } @Test void modes() { var result = index.queryStopClusters("westh").toList(); assertEquals(1, result.size()); - var stop = result.getFirst(); - assertEquals(WESTHAFEN.getName().toString(), stop.name()); - assertEquals(List.of(FERRY.name(), BUS.name()), stop.modes()); + var cluster = result.getFirst(); + assertEquals(WESTHAFEN.getName().toString(), cluster.primary().name()); + assertEquals(List.of(FERRY.name(), BUS.name()), cluster.primary().modes()); } @Test void agenciesAndFeedPublisher() { - var result = index.queryStopClusters("alexanderplatz").toList().getFirst(); - assertEquals(ALEXANDERPLATZ_STATION.getName().toString(), result.name()); - assertEquals(List.of(StopClusterMapper.toAgency(BVG)), result.agencies()); - assertEquals("A Publisher", result.feedPublisher().name()); + var cluster = index.queryStopClusters("alexanderplatz").toList().getFirst(); + assertEquals(ALEXANDERPLATZ_STATION.getName().toString(), cluster.primary().name()); + assertEquals(List.of(StopClusterMapper.toAgency(BVG)), cluster.primary().agencies()); + assertEquals("A Publisher", cluster.primary().feedPublisher().name()); } } + + private static @Nonnull Function primaryId() { + return c -> c.primary().id(); + } } diff --git a/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java b/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java index edfb6855835..0f05d0d49b3 100644 --- a/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java +++ b/src/ext-test/java/org/opentripplanner/ext/siri/SiriTimetableSnapshotSourceTest.java @@ -8,6 +8,15 @@ import org.junit.jupiter.api.Test; import org.opentripplanner.model.PickDrop; import org.opentripplanner.transit.model.timetable.RealTimeState; +import org.opentripplanner.transit.model.timetable.Trip; +import org.opentripplanner.transit.model.timetable.TripOnServiceDate; +import org.opentripplanner.transit.model.timetable.TripTimes; +import org.opentripplanner.transit.model.timetable.TripTimesFactory; +import org.opentripplanner.transit.service.DefaultTransitService; +import org.opentripplanner.transit.service.StopModel; +import org.opentripplanner.transit.service.TransitModel; +import org.opentripplanner.transit.service.TransitService; +import org.opentripplanner.updater.TimetableSnapshotSourceParameters; import org.opentripplanner.updater.spi.UpdateError; import org.opentripplanner.updater.spi.UpdateResult; import org.opentripplanner.updater.trip.RealtimeTestEnvironment; @@ -47,10 +56,11 @@ void testAddJourney() { var result = env.applyEstimatedTimetable(updates); assertEquals(1, result.successful()); - var tripTimes = env.getTripTimesForTrip("newJourney"); - assertEquals(RealTimeState.ADDED, tripTimes.getRealTimeState()); - assertEquals(2 * 60, tripTimes.getDepartureTime(0)); - assertEquals(4 * 60, tripTimes.getDepartureTime(1)); + assertEquals("ADDED | C1 [R] 0:02 0:02 | D1 0:04 0:04", env.getRealtimeTimetable("newJourney")); + assertEquals( + "SCHEDULED | C1 0:01 0:01 | D1 0:03 0:03", + env.getScheduledTimetable("newJourney") + ); } @Test @@ -72,14 +82,13 @@ void testReplaceJourney() { assertEquals(1, result.successful()); - var tripTimes = env.getTripTimesForTrip("newJourney"); - var pattern = env.getPatternForTrip(env.id("newJourney")); - assertEquals(RealTimeState.ADDED, tripTimes.getRealTimeState()); - assertEquals(2 * 60, tripTimes.getDepartureTime(0)); - assertEquals(4 * 60, tripTimes.getDepartureTime(1)); - assertEquals(env.stopA1.getId(), pattern.getStop(0).getId()); - assertEquals(env.stopC1.getId(), pattern.getStop(1).getId()); + assertEquals("ADDED | A1 [R] 0:02 0:02 | C1 0:04 0:04", env.getRealtimeTimetable("newJourney")); + assertEquals( + "SCHEDULED | A1 0:01 0:01 | C1 0:03 0:03", + env.getScheduledTimetable("newJourney") + ); + // Original trip should not get canceled var originalTripTimes = env.getTripTimesForTrip(env.trip1); assertEquals(RealTimeState.SCHEDULED, originalTripTimes.getRealTimeState()); } @@ -97,6 +106,10 @@ void testUpdateJourneyWithDatedVehicleJourneyRef() { var result = env.applyEstimatedTimetable(updates); assertEquals(1, result.successful()); assertTripUpdated(env); + assertEquals( + "UPDATED | A1 0:00:15 0:00:15 | B1 0:00:25 0:00:25", + env.getRealtimeTimetable(env.trip1) + ); } /** @@ -128,7 +141,7 @@ void testUpdateJourneyWithoutJourneyRef() { var updates = updatedJourneyBuilder(env).buildEstimatedTimetableDeliveries(); var result = env.applyEstimatedTimetable(updates); assertEquals(0, result.successful()); - assertFailure(result, UpdateError.UpdateErrorType.TRIP_NOT_FOUND); + assertFailure(UpdateError.UpdateErrorType.TRIP_NOT_FOUND, result); } /** @@ -167,7 +180,7 @@ void testUpdateJourneyWithFuzzyMatchingAndMissingAimedDepartureTime() { var result = env.applyEstimatedTimetableWithFuzzyMatcher(updates); assertEquals(0, result.successful(), "Should fail gracefully"); - assertFailure(result, UpdateError.UpdateErrorType.NO_FUZZY_TRIP_MATCH); + assertFailure(UpdateError.UpdateErrorType.NO_FUZZY_TRIP_MATCH, result); } /** @@ -190,15 +203,10 @@ void testChangeQuay() { var result = env.applyEstimatedTimetable(updates); assertEquals(1, result.successful()); - - var pattern = env.getPatternForTrip(env.trip1.getId()); - var tripTimes = env.getTripTimesForTrip(env.trip1); - assertEquals(RealTimeState.MODIFIED, tripTimes.getRealTimeState()); - assertEquals(11, tripTimes.getScheduledDepartureTime(0)); - assertEquals(15, tripTimes.getDepartureTime(0)); - assertEquals(20, tripTimes.getScheduledArrivalTime(1)); - assertEquals(33, tripTimes.getArrivalTime(1)); - assertEquals(env.stopB2, pattern.getStop(1)); + assertEquals( + "MODIFIED | A1 [R] 0:00:15 0:00:15 | B2 0:00:33 0:00:33", + env.getRealtimeTimetable(env.trip1) + ); } @Test @@ -221,12 +229,10 @@ void testCancelStop() { var result = env.applyEstimatedTimetable(updates); assertEquals(1, result.successful()); - - var pattern = env.getPatternForTrip(env.trip2.getId()); - - assertEquals(PickDrop.SCHEDULED, pattern.getAlightType(0)); - assertEquals(PickDrop.CANCELLED, pattern.getAlightType(1)); - assertEquals(PickDrop.SCHEDULED, pattern.getAlightType(2)); + assertEquals( + "MODIFIED | A1 0:01:01 0:01:01 | B1 [C] 0:01:10 0:01:11 | C1 0:01:30 0:01:30", + env.getRealtimeTimetable(env.trip2) + ); } // TODO: support this @@ -254,23 +260,10 @@ void testAddStop() { var result = env.applyEstimatedTimetable(updates); assertEquals(1, result.successful()); - - var pattern = env.getPatternForTrip(env.trip1.getId()); - var tripTimes = env.getTripTimesForTrip(env.trip1); - assertEquals(RealTimeState.MODIFIED, tripTimes.getRealTimeState()); - assertEquals(11, tripTimes.getScheduledDepartureTime(0)); - assertEquals(15, tripTimes.getDepartureTime(0)); - - // Should it work to get the scheduled times from an extra call? - assertEquals(19, tripTimes.getScheduledArrivalTime(1)); - assertEquals(24, tripTimes.getScheduledDepartureTime(1)); - - assertEquals(20, tripTimes.getDepartureTime(1)); - assertEquals(25, tripTimes.getDepartureTime(1)); - - assertEquals(20, tripTimes.getScheduledArrivalTime(2)); - assertEquals(33, tripTimes.getArrivalTime(2)); - assertEquals(List.of(env.stopA1, env.stopD1, env.stopB1), pattern.getStops()); + assertEquals( + "MODIFIED | A1 0:00:15 0:00:15 | D1 [C] 0:00:20 0:00:25 | B1 0:00:33 0:00:33", + env.getRealtimeTimetable(env.trip1) + ); } ///////////////// @@ -287,7 +280,7 @@ void testNotMonitored() { var result = env.applyEstimatedTimetable(updates); - assertFailure(result, UpdateError.UpdateErrorType.NOT_MONITORED); + assertFailure(UpdateError.UpdateErrorType.NOT_MONITORED, result); } @Test @@ -312,7 +305,7 @@ void testReplaceJourneyWithoutEstimatedVehicleJourneyCode() { var result = env.applyEstimatedTimetable(updates); // TODO: this should have a more specific error type - assertFailure(result, UpdateError.UpdateErrorType.UNKNOWN); + assertFailure(UpdateError.UpdateErrorType.UNKNOWN, result); } @Test @@ -332,7 +325,7 @@ void testNegativeHopTime() { var result = env.applyEstimatedTimetable(updates); - assertFailure(result, UpdateError.UpdateErrorType.NEGATIVE_HOP_TIME); + assertFailure(UpdateError.UpdateErrorType.NEGATIVE_HOP_TIME, result); } @Test @@ -355,7 +348,7 @@ void testNegativeDwellTime() { var result = env.applyEstimatedTimetable(updates); - assertFailure(result, UpdateError.UpdateErrorType.NEGATIVE_DWELL_TIME); + assertFailure(UpdateError.UpdateErrorType.NEGATIVE_DWELL_TIME, result); } // TODO: support this @@ -381,29 +374,28 @@ void testExtraUnknownStop() { var result = env.applyEstimatedTimetable(updates); - assertFailure(result, UpdateError.UpdateErrorType.INVALID_STOP_SEQUENCE); + assertFailure(UpdateError.UpdateErrorType.INVALID_STOP_SEQUENCE, result); } - private void assertFailure(UpdateResult result, UpdateError.UpdateErrorType errorType) { - assertEquals(result.failures().keySet(), Set.of(errorType)); + private void assertFailure(UpdateError.UpdateErrorType expectedError, UpdateResult result) { + assertEquals(Set.of(expectedError), result.failures().keySet()); } private static SiriEtBuilder updatedJourneyBuilder(RealtimeTestEnvironment env) { return new SiriEtBuilder(env.getDateTimeHelper()) - .withRecordedCalls(builder -> - builder.call(env.stopA1).departAimedActual("00:00:11", "00:00:15") - ) .withEstimatedCalls(builder -> - builder.call(env.stopB1).arriveAimedExpected("00:00:20", "00:00:25") + builder + .call(env.stopA1) + .departAimedExpected("00:00:11", "00:00:15") + .call(env.stopB1) + .arriveAimedExpected("00:00:20", "00:00:25") ); } private static void assertTripUpdated(RealtimeTestEnvironment env) { - var tripTimes = env.getTripTimesForTrip(env.trip1); - assertEquals(RealTimeState.UPDATED, tripTimes.getRealTimeState()); - assertEquals(11, tripTimes.getScheduledDepartureTime(0)); - assertEquals(15, tripTimes.getDepartureTime(0)); - assertEquals(20, tripTimes.getScheduledArrivalTime(1)); - assertEquals(25, tripTimes.getArrivalTime(1)); + assertEquals( + "UPDATED | A1 0:00:15 0:00:15 | B1 0:00:25 0:00:25", + env.getRealtimeTimetable(env.trip1) + ); } } diff --git a/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPath.java b/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPath.java index 3a692dff40b..4a494286313 100644 --- a/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPath.java +++ b/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/FlexPath.java @@ -41,12 +41,8 @@ public LineString getGeometry() { /** * Returns an (immutable) copy of this path with the duration modified. */ - public FlexPath withDurationModifier(TimePenalty mod) { - if (mod.isZero()) { - return this; - } else { - int updatedDuration = (int) mod.calculate(Duration.ofSeconds(durationSeconds)).toSeconds(); - return new FlexPath(distanceMeters, updatedDuration, geometrySupplier); - } + public FlexPath withTimePenalty(TimePenalty penalty) { + int updatedDuration = (int) penalty.calculate(Duration.ofSeconds(durationSeconds)).toSeconds(); + return new FlexPath(distanceMeters, updatedDuration, geometrySupplier); } } diff --git a/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/TimePenaltyCalculator.java b/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/TimePenaltyCalculator.java index 63b661f0f9a..a2252f3fec8 100644 --- a/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/TimePenaltyCalculator.java +++ b/src/ext/java/org/opentripplanner/ext/flex/flexpathcalculator/TimePenaltyCalculator.java @@ -5,17 +5,17 @@ import org.opentripplanner.street.model.vertex.Vertex; /** - * A calculator to delegates the main computation to another instance and applies a duration - * modifier afterward. + * A calculator to delegates the main computation to another instance and applies a time penalty + * afterward. */ public class TimePenaltyCalculator implements FlexPathCalculator { private final FlexPathCalculator delegate; - private final TimePenalty factors; + private final TimePenalty penalty; public TimePenaltyCalculator(FlexPathCalculator delegate, TimePenalty penalty) { this.delegate = delegate; - this.factors = penalty; + this.penalty = penalty; } @Nullable @@ -26,7 +26,7 @@ public FlexPath calculateFlexPath(Vertex fromv, Vertex tov, int fromStopIndex, i if (path == null) { return null; } else { - return path.withDurationModifier(factors); + return path.withTimePenalty(penalty); } } } diff --git a/src/ext/java/org/opentripplanner/ext/flex/trip/UnscheduledTrip.java b/src/ext/java/org/opentripplanner/ext/flex/trip/UnscheduledTrip.java index 402d39e2aa7..a4c8d9568ca 100644 --- a/src/ext/java/org/opentripplanner/ext/flex/trip/UnscheduledTrip.java +++ b/src/ext/java/org/opentripplanner/ext/flex/trip/UnscheduledTrip.java @@ -156,7 +156,7 @@ public Stream getFlexAccessTemplates( /** * Get the correct {@link FlexPathCalculator} depending on the {@code timePenalty}. - * If the modifier doesn't actually modify, we return the regular calculator. + * If the penalty would not change the result, we return the regular calculator. */ protected FlexPathCalculator flexPathCalculator(FlexPathCalculator calculator) { if (timePenalty.modifies()) { diff --git a/src/ext/java/org/opentripplanner/ext/geocoder/LuceneIndex.java b/src/ext/java/org/opentripplanner/ext/geocoder/LuceneIndex.java index 56769db0028..e0ea8ba36b9 100644 --- a/src/ext/java/org/opentripplanner/ext/geocoder/LuceneIndex.java +++ b/src/ext/java/org/opentripplanner/ext/geocoder/LuceneIndex.java @@ -6,11 +6,11 @@ import java.io.Serializable; import java.util.Arrays; import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Stream; -import javax.annotation.Nullable; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.en.EnglishAnalyzer; import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper; @@ -40,7 +40,7 @@ import org.apache.lucene.search.suggest.document.FuzzyCompletionQuery; import org.apache.lucene.search.suggest.document.SuggestIndexSearcher; import org.apache.lucene.store.ByteBuffersDirectory; -import org.opentripplanner.ext.geocoder.StopCluster.Coordinate; +import org.opentripplanner.framework.collection.ListUtils; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.standalone.api.OtpServerRequestContext; import org.opentripplanner.transit.model.framework.FeedScopedId; @@ -52,22 +52,22 @@ public class LuceneIndex implements Serializable { private static final String TYPE = "type"; private static final String ID = "id"; + private static final String SECONDARY_IDS = "secondary_ids"; private static final String SUGGEST = "suggest"; private static final String NAME = "name"; private static final String NAME_NGRAM = "name_ngram"; private static final String CODE = "code"; private static final String LAT = "latitude"; private static final String LON = "longitude"; - private static final String MODE = "mode"; - private static final String AGENCY_IDS = "agency_ids"; private final TransitService transitService; private final Analyzer analyzer; private final SuggestIndexSearcher searcher; + private final StopClusterMapper stopClusterMapper; public LuceneIndex(TransitService transitService) { this.transitService = transitService; - StopClusterMapper stopClusterMapper = new StopClusterMapper(transitService); + this.stopClusterMapper = new StopClusterMapper(transitService); this.analyzer = new PerFieldAnalyzerWrapper( @@ -95,12 +95,11 @@ public LuceneIndex(TransitService transitService) { directoryWriter, StopLocation.class, stopLocation.getId().toString(), - stopLocation.getName(), - stopLocation.getCode(), + List.of(), + ListUtils.ofNullable(stopLocation.getName()), + ListUtils.ofNullable(stopLocation.getCode()), stopLocation.getCoordinate().latitude(), - stopLocation.getCoordinate().longitude(), - Set.of(), - Set.of() + stopLocation.getCoordinate().longitude() ) ); @@ -111,12 +110,11 @@ public LuceneIndex(TransitService transitService) { directoryWriter, StopLocationsGroup.class, stopLocationsGroup.getId().toString(), - stopLocationsGroup.getName(), - null, + List.of(), + ListUtils.ofNullable(stopLocationsGroup.getName()), + List.of(), stopLocationsGroup.getCoordinate().latitude(), - stopLocationsGroup.getCoordinate().longitude(), - Set.of(), - Set.of() + stopLocationsGroup.getCoordinate().longitude() ) ); @@ -129,13 +127,12 @@ public LuceneIndex(TransitService transitService) { addToIndex( directoryWriter, StopCluster.class, - stopCluster.id().toString(), - I18NString.of(stopCluster.name()), - stopCluster.code(), + stopCluster.primaryId(), + stopCluster.secondaryIds(), + stopCluster.names(), + stopCluster.codes(), stopCluster.coordinate().lat(), - stopCluster.coordinate().lon(), - stopCluster.modes(), - stopCluster.agencyIds() + stopCluster.coordinate().lon() ) ); } @@ -183,30 +180,16 @@ public Stream queryStopClusters(String query) { } private StopCluster toStopCluster(Document document) { - var clusterId = FeedScopedId.parse(document.get(ID)); - var name = document.get(NAME); - var code = document.get(CODE); - var lat = document.getField(LAT).numericValue().doubleValue(); - var lon = document.getField(LON).numericValue().doubleValue(); - var modes = Arrays.asList(document.getValues(MODE)); - var agencies = Arrays - .stream(document.getValues(AGENCY_IDS)) - .map(id -> transitService.getAgencyForId(FeedScopedId.parse(id))) - .filter(Objects::nonNull) - .map(StopClusterMapper::toAgency) + var primaryId = FeedScopedId.parse(document.get(ID)); + var primary = stopClusterMapper.toLocation(primaryId); + + var secondaryIds = Arrays + .stream(document.getValues(SECONDARY_IDS)) + .map(FeedScopedId::parse) + .map(stopClusterMapper::toLocation) .toList(); - var feedPublisher = StopClusterMapper.toFeedPublisher( - transitService.getFeedInfo(clusterId.getFeedId()) - ); - return new StopCluster( - clusterId, - code, - name, - new Coordinate(lat, lon), - modes, - agencies, - feedPublisher - ); + + return new StopCluster(primary, secondaryIds); } static IndexWriterConfig iwcWithSuggestField(Analyzer analyzer, final Set suggestFields) { @@ -230,36 +213,33 @@ private static void addToIndex( IndexWriter writer, Class type, String id, - I18NString name, - @Nullable String code, + Collection secondaryIds, + Collection names, + Collection codes, double latitude, - double longitude, - Collection modes, - Collection agencyIds + double longitude ) { String typeName = type.getSimpleName(); Document document = new Document(); document.add(new StoredField(ID, id)); + for (var secondaryId : secondaryIds) { + document.add(new StoredField(SECONDARY_IDS, secondaryId)); + } document.add(new TextField(TYPE, typeName, Store.YES)); - document.add(new TextField(NAME, Objects.toString(name), Store.YES)); - document.add(new TextField(NAME_NGRAM, Objects.toString(name), Store.YES)); - document.add(new ContextSuggestField(SUGGEST, Objects.toString(name), 1, typeName)); + for (var name : names) { + document.add(new TextField(NAME, Objects.toString(name), Store.YES)); + document.add(new TextField(NAME_NGRAM, Objects.toString(name), Store.YES)); + document.add(new ContextSuggestField(SUGGEST, Objects.toString(name), 1, typeName)); + } document.add(new StoredField(LAT, latitude)); document.add(new StoredField(LON, longitude)); - if (code != null) { + for (var code : codes) { document.add(new TextField(CODE, code, Store.YES)); document.add(new ContextSuggestField(SUGGEST, code, 1, typeName)); } - for (var mode : modes) { - document.add(new TextField(MODE, mode, Store.YES)); - } - for (var ids : agencyIds) { - document.add(new TextField(AGENCY_IDS, ids, Store.YES)); - } - try { writer.addDocument(document); } catch (IOException ex) { diff --git a/src/ext/java/org/opentripplanner/ext/geocoder/LuceneStopCluster.java b/src/ext/java/org/opentripplanner/ext/geocoder/LuceneStopCluster.java index f58d7aa9af9..b4ee0f0919b 100644 --- a/src/ext/java/org/opentripplanner/ext/geocoder/LuceneStopCluster.java +++ b/src/ext/java/org/opentripplanner/ext/geocoder/LuceneStopCluster.java @@ -1,17 +1,15 @@ package org.opentripplanner.ext.geocoder; import java.util.Collection; -import javax.annotation.Nullable; -import org.opentripplanner.transit.model.framework.FeedScopedId; +import org.opentripplanner.framework.i18n.I18NString; /** * A package-private helper type for transporting data before serializing. */ record LuceneStopCluster( - FeedScopedId id, - @Nullable String code, - String name, - StopCluster.Coordinate coordinate, - Collection modes, - Collection agencyIds + String primaryId, + Collection secondaryIds, + Collection names, + Collection codes, + StopCluster.Coordinate coordinate ) {} diff --git a/src/ext/java/org/opentripplanner/ext/geocoder/StopCluster.java b/src/ext/java/org/opentripplanner/ext/geocoder/StopCluster.java index 8ffd44511fd..30647cc7b20 100644 --- a/src/ext/java/org/opentripplanner/ext/geocoder/StopCluster.java +++ b/src/ext/java/org/opentripplanner/ext/geocoder/StopCluster.java @@ -2,6 +2,7 @@ import java.util.Collection; import java.util.List; +import java.util.Objects; import javax.annotation.Nullable; import org.opentripplanner.transit.model.framework.FeedScopedId; @@ -14,15 +15,7 @@ * - if a stop has a parent station only the parent is returned * - if stops are closer than 10 meters to each and have an identical name, only one is returned */ -record StopCluster( - FeedScopedId id, - @Nullable String code, - String name, - Coordinate coordinate, - Collection modes, - List agencies, - @Nullable FeedPublisher feedPublisher -) { +record StopCluster(Location primary, Collection secondaries) { /** * Easily serializable version of a coordinate */ @@ -37,4 +30,29 @@ public record Agency(FeedScopedId id, String name) {} * Easily serializable version of a feed publisher */ public record FeedPublisher(String name) {} + + public enum LocationType { + STATION, + STOP, + } + + public record Location( + FeedScopedId id, + @Nullable String code, + LocationType type, + String name, + Coordinate coordinate, + Collection modes, + List agencies, + @Nullable FeedPublisher feedPublisher + ) { + public Location { + Objects.requireNonNull(id); + Objects.requireNonNull(name); + Objects.requireNonNull(type); + Objects.requireNonNull(coordinate); + Objects.requireNonNull(modes); + Objects.requireNonNull(agencies); + } + } } diff --git a/src/ext/java/org/opentripplanner/ext/geocoder/StopClusterMapper.java b/src/ext/java/org/opentripplanner/ext/geocoder/StopClusterMapper.java index 6f16d4a0cce..d9f388ea0e8 100644 --- a/src/ext/java/org/opentripplanner/ext/geocoder/StopClusterMapper.java +++ b/src/ext/java/org/opentripplanner/ext/geocoder/StopClusterMapper.java @@ -1,15 +1,23 @@ package org.opentripplanner.ext.geocoder; +import static org.opentripplanner.ext.geocoder.StopCluster.LocationType.STATION; +import static org.opentripplanner.ext.geocoder.StopCluster.LocationType.STOP; + import com.google.common.collect.Iterables; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; +import javax.annotation.Nullable; import org.opentripplanner.framework.collection.ListUtils; import org.opentripplanner.framework.geometry.WgsCoordinate; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.model.FeedInfo; +import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.network.Route; import org.opentripplanner.transit.model.organization.Agency; +import org.opentripplanner.transit.model.site.Station; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.site.StopLocationsGroup; import org.opentripplanner.transit.service.TransitService; @@ -37,7 +45,7 @@ Iterable generateStopClusters( Collection stopLocations, Collection stopLocationsGroups ) { - var stops = stopLocations + List stops = stopLocations .stream() // remove stop locations without a parent station .filter(sl -> sl.getParentStation() == null) @@ -46,50 +54,63 @@ Iterable generateStopClusters( .toList(); // if they are very close to each other and have the same name, only one is chosen (at random) - var deduplicatedStops = ListUtils - .distinctByKey( - stops, - sl -> new DeduplicationKey(sl.getName(), sl.getCoordinate().roundToApproximate100m()) + var deduplicatedStops = stops + .stream() + .collect( + Collectors.groupingBy(sl -> + new DeduplicationKey(sl.getName(), sl.getCoordinate().roundToApproximate100m()) + ) ) + .values() .stream() - .flatMap(s -> this.map(s).stream()) + .map(group -> map(group).orElse(null)) + .filter(Objects::nonNull) .toList(); - var stations = stopLocationsGroups.stream().map(this::map).toList(); + var stations = stopLocationsGroups.stream().map(StopClusterMapper::map).toList(); return Iterables.concat(deduplicatedStops, stations); } - LuceneStopCluster map(StopLocationsGroup g) { - var modes = transitService.getModesOfStopLocationsGroup(g).stream().map(Enum::name).toList(); - var agencies = agenciesForStopLocationsGroup(g) - .stream() - .map(s -> s.getId().toString()) - .toList(); + private static LuceneStopCluster map(StopLocationsGroup g) { + var childStops = g.getChildStops(); + var ids = childStops.stream().map(s -> s.getId().toString()).toList(); + var childNames = getNames(childStops); + var codes = getCodes(childStops); + return new LuceneStopCluster( - g.getId(), - null, - g.getName().toString(), - toCoordinate(g.getCoordinate()), - modes, - agencies + g.getId().toString(), + ids, + ListUtils.combine(List.of(g.getName()), childNames), + codes, + toCoordinate(g.getCoordinate()) ); } - Optional map(StopLocation sl) { - var agencies = agenciesForStopLocation(sl).stream().map(a -> a.getId().toString()).toList(); + private static List getCodes(Collection childStops) { + return childStops.stream().map(StopLocation::getCode).filter(Objects::nonNull).toList(); + } + + private static List getNames(Collection childStops) { + return childStops.stream().map(StopLocation::getName).filter(Objects::nonNull).toList(); + } + + private static Optional map(List stopLocations) { + var primary = stopLocations.getFirst(); + var secondaryIds = stopLocations.stream().skip(1).map(sl -> sl.getId().toString()).toList(); + var names = getNames(stopLocations); + var codes = getCodes(stopLocations); + return Optional - .ofNullable(sl.getName()) - .map(name -> { - var modes = transitService.getModesOfStopLocation(sl).stream().map(Enum::name).toList(); - return new LuceneStopCluster( - sl.getId(), - sl.getCode(), - name.toString(), - toCoordinate(sl.getCoordinate()), - modes, - agencies - ); - }); + .ofNullable(primary.getName()) + .map(name -> + new LuceneStopCluster( + primary.getId().toString(), + secondaryIds, + names, + codes, + toCoordinate(primary.getCoordinate()) + ) + ); } private List agenciesForStopLocation(StopLocation stop) { @@ -105,6 +126,59 @@ private List agenciesForStopLocationsGroup(StopLocationsGroup group) { .toList(); } + StopCluster.Location toLocation(FeedScopedId id) { + var loc = transitService.getStopLocation(id); + if (loc != null) { + var feedPublisher = toFeedPublisher(transitService.getFeedInfo(id.getFeedId())); + var modes = transitService.getModesOfStopLocation(loc).stream().map(Enum::name).toList(); + var agencies = agenciesForStopLocation(loc) + .stream() + .map(StopClusterMapper::toAgency) + .toList(); + return new StopCluster.Location( + loc.getId(), + loc.getCode(), + STOP, + loc.getName().toString(), + new StopCluster.Coordinate(loc.getLat(), loc.getLon()), + modes, + agencies, + feedPublisher + ); + } else { + var group = transitService.getStopLocationsGroup(id); + var feedPublisher = toFeedPublisher(transitService.getFeedInfo(id.getFeedId())); + var modes = transitService + .getModesOfStopLocationsGroup(group) + .stream() + .map(Enum::name) + .toList(); + var agencies = agenciesForStopLocationsGroup(group) + .stream() + .map(StopClusterMapper::toAgency) + .toList(); + return new StopCluster.Location( + group.getId(), + extractCode(group), + STATION, + group.getName().toString(), + new StopCluster.Coordinate(group.getLat(), group.getLon()), + modes, + agencies, + feedPublisher + ); + } + } + + @Nullable + private static String extractCode(StopLocationsGroup group) { + if (group instanceof Station station) { + return station.getCode(); + } else { + return null; + } + } + private static StopCluster.Coordinate toCoordinate(WgsCoordinate c) { return new StopCluster.Coordinate(c.latitude(), c.longitude()); } @@ -113,7 +187,7 @@ static StopCluster.Agency toAgency(Agency a) { return new StopCluster.Agency(a.getId(), a.getName()); } - static StopCluster.FeedPublisher toFeedPublisher(FeedInfo fi) { + private static StopCluster.FeedPublisher toFeedPublisher(FeedInfo fi) { if (fi == null) { return null; } else { diff --git a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java index 1fd78765a07..53d53b9bc4b 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/GtfsGraphQLIndex.java @@ -129,7 +129,6 @@ protected static GraphQLSchema buildSchema() { .type(typeWiring.build(DepartureRowImpl.class)) .type(typeWiring.build(elevationProfileComponentImpl.class)) .type(typeWiring.build(FeedImpl.class)) - .type(typeWiring.build(FeedImpl.class)) .type(typeWiring.build(GeometryImpl.class)) .type(typeWiring.build(ItineraryImpl.class)) .type(typeWiring.build(LegImpl.class)) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FeedImpl.java b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FeedImpl.java index 7d7c62136b6..d6488d3f375 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FeedImpl.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/FeedImpl.java @@ -9,6 +9,7 @@ import org.opentripplanner.apis.gtfs.GraphQLRequestContext; import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes; +import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.routing.alertpatch.EntitySelector; import org.opentripplanner.routing.alertpatch.TransitAlert; import org.opentripplanner.routing.services.TransitAlertService; @@ -64,6 +65,17 @@ public DataFetcher feedId() { return this::getSource; } + @Override + public DataFetcher publisher() { + return environment -> { + String id = getSource(environment); + return new FeedPublisher( + getTransitService(environment).getFeedInfo(id).getPublisherName(), + getTransitService(environment).getFeedInfo(id).getPublisherUrl() + ); + }; + } + private List getAgencies(DataFetchingEnvironment environment) { String id = getSource(environment); return getTransitService(environment) diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java index 559acac920d..fbfc4965c62 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/GraphQLDataFetchers.java @@ -20,6 +20,7 @@ import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRelativeDirection; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLRoutingErrorCode; import org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLTransitMode; +import org.opentripplanner.apis.gtfs.model.FeedPublisher; import org.opentripplanner.apis.gtfs.model.RideHailingProvider; import org.opentripplanner.apis.gtfs.model.StopPosition; import org.opentripplanner.apis.gtfs.model.TripOccupancy; @@ -380,6 +381,15 @@ public interface GraphQLFeed { public DataFetcher> alerts(); public DataFetcher feedId(); + + public DataFetcher publisher(); + } + + /** Feed publisher information */ + public interface GraphQLFeedPublisher { + public DataFetcher name(); + + public DataFetcher url(); } public interface GraphQLGeometry { diff --git a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml index 55f76863cc6..29c2bff0257 100644 --- a/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml +++ b/src/main/java/org/opentripplanner/apis/gtfs/generated/graphql-codegen.yml @@ -56,6 +56,7 @@ config: elevationProfileComponent: org.opentripplanner.model.plan.ElevationProfile.Step Emissions: org.opentripplanner.model.plan.Emissions#Emissions Feed: String + FeedPublisher: org.opentripplanner.apis.gtfs.model.FeedPublisher#FeedPublisher Geometry: org.locationtech.jts.geom.Geometry#Geometry InputField: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLInputField#GraphQLInputField Itinerary: org.opentripplanner.model.plan.Itinerary#Itinerary diff --git a/src/main/java/org/opentripplanner/apis/gtfs/model/FeedPublisher.java b/src/main/java/org/opentripplanner/apis/gtfs/model/FeedPublisher.java new file mode 100644 index 00000000000..ba524b537f0 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/gtfs/model/FeedPublisher.java @@ -0,0 +1,10 @@ +package org.opentripplanner.apis.gtfs.model; + +import java.util.Objects; + +public record FeedPublisher(String name, String url) { + public FeedPublisher { + Objects.requireNonNull(name); + Objects.requireNonNull(url); + } +} diff --git a/src/main/java/org/opentripplanner/apis/transmodel/OTPRequestTimeoutInstrumentation.java b/src/main/java/org/opentripplanner/apis/transmodel/OTPRequestTimeoutInstrumentation.java new file mode 100644 index 00000000000..acb27eb4e87 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/transmodel/OTPRequestTimeoutInstrumentation.java @@ -0,0 +1,36 @@ +package org.opentripplanner.apis.transmodel; + +import static graphql.execution.instrumentation.SimpleInstrumentationContext.noOp; + +import graphql.execution.instrumentation.Instrumentation; +import graphql.execution.instrumentation.InstrumentationContext; +import graphql.execution.instrumentation.InstrumentationState; +import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters; +import java.util.concurrent.atomic.AtomicLong; +import org.opentripplanner.framework.application.OTPRequestTimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A GraphQL instrumentation that periodically checks the OTP request interruption status while the + * query is being processed. + */ +public class OTPRequestTimeoutInstrumentation implements Instrumentation { + + private static final Logger LOG = LoggerFactory.getLogger(OTPRequestTimeoutInstrumentation.class); + + private final AtomicLong fieldFetchCounter = new AtomicLong(); + + @Override + public InstrumentationContext beginFieldFetch( + InstrumentationFieldFetchParameters parameters, + InstrumentationState state + ) { + long fetched = fieldFetchCounter.incrementAndGet(); + if (fetched % 100000 == 0) { + LOG.debug("Fetched {} fields", fetched); + OTPRequestTimeoutException.checkForTimeout(); + } + return noOp(); + } +} diff --git a/src/main/java/org/opentripplanner/apis/transmodel/TransmodelGraph.java b/src/main/java/org/opentripplanner/apis/transmodel/TransmodelGraph.java index 051e369dde0..2cd405212c2 100644 --- a/src/main/java/org/opentripplanner/apis/transmodel/TransmodelGraph.java +++ b/src/main/java/org/opentripplanner/apis/transmodel/TransmodelGraph.java @@ -79,7 +79,10 @@ Response executeGraphQL( } private static Instrumentation createInstrumentation(int maxResolves, Iterable tracingTags) { - Instrumentation instrumentation = new MaxQueryComplexityInstrumentation(maxResolves); + Instrumentation instrumentation = new ChainedInstrumentation( + new MaxQueryComplexityInstrumentation(maxResolves), + new OTPRequestTimeoutInstrumentation() + ); if (OTPFeature.ActuatorAPI.isOn()) { instrumentation = diff --git a/src/main/java/org/opentripplanner/framework/collection/ListUtils.java b/src/main/java/org/opentripplanner/framework/collection/ListUtils.java index 513c0bcc0d3..5964a1674e3 100644 --- a/src/main/java/org/opentripplanner/framework/collection/ListUtils.java +++ b/src/main/java/org/opentripplanner/framework/collection/ListUtils.java @@ -57,4 +57,16 @@ public static List distinctByKey( return ret; } + + /** + * Take a single nullable variable and return an empty list if it is null. Otherwise + * return a list with one element. + */ + public static List ofNullable(T input) { + if (input == null) { + return List.of(); + } else { + return List.of(input); + } + } } diff --git a/src/main/java/org/opentripplanner/gtfs/mapping/GTFSToOtpTransitServiceMapper.java b/src/main/java/org/opentripplanner/gtfs/mapping/GTFSToOtpTransitServiceMapper.java index ce65d6b0820..354c1f16177 100644 --- a/src/main/java/org/opentripplanner/gtfs/mapping/GTFSToOtpTransitServiceMapper.java +++ b/src/main/java/org/opentripplanner/gtfs/mapping/GTFSToOtpTransitServiceMapper.java @@ -171,7 +171,7 @@ public void mapStopTripAndRouteDataIntoBuilder() { builder.getPathways().addAll(pathwayMapper.map(data.getAllPathways())); builder.getStopTimesSortedByTrip().addAll(stopTimeMapper.map(data.getAllStopTimes())); - builder.getFlexTimePenalty().putAll(tripMapper.flexSafeDurationModifiers()); + builder.getFlexTimePenalty().putAll(tripMapper.flexSafeTimePenalties()); builder.getTripsById().addAll(tripMapper.map(data.getAllTrips())); fareRulesBuilder.fareAttributes().addAll(fareAttributeMapper.map(data.getAllFareAttributes())); diff --git a/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java b/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java index ca221c1c6ca..3a62ba2b269 100644 --- a/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java +++ b/src/main/java/org/opentripplanner/gtfs/mapping/TripMapper.java @@ -18,7 +18,7 @@ class TripMapper { private final TranslationHelper translationHelper; private final Map mappedTrips = new HashMap<>(); - private final Map flexSafeDurationModifiers = new HashMap<>(); + private final Map flexSafeTimePenalties = new HashMap<>(); TripMapper( RouteMapper routeMapper, @@ -45,8 +45,8 @@ Collection getMappedTrips() { /** * The map of flex duration factors per flex trip. */ - Map flexSafeDurationModifiers() { - return flexSafeDurationModifiers; + Map flexSafeTimePenalties() { + return flexSafeTimePenalties; } private Trip doMap(org.onebusaway.gtfs.model.Trip rhs) { @@ -73,11 +73,11 @@ private Trip doMap(org.onebusaway.gtfs.model.Trip rhs) { lhs.withBikesAllowed(BikeAccessMapper.mapForTrip(rhs)); var trip = lhs.build(); - mapSafeDurationModifier(rhs).ifPresent(f -> flexSafeDurationModifiers.put(trip, f)); + mapSafeTimePenalty(rhs).ifPresent(f -> flexSafeTimePenalties.put(trip, f)); return trip; } - private Optional mapSafeDurationModifier(org.onebusaway.gtfs.model.Trip rhs) { + private Optional mapSafeTimePenalty(org.onebusaway.gtfs.model.Trip rhs) { if (rhs.getSafeDurationFactor() == null && rhs.getSafeDurationOffset() == null) { return Optional.empty(); } else { diff --git a/src/main/java/org/opentripplanner/model/impl/OtpTransitServiceBuilder.java b/src/main/java/org/opentripplanner/model/impl/OtpTransitServiceBuilder.java index 544ca29599d..43c18cec59d 100644 --- a/src/main/java/org/opentripplanner/model/impl/OtpTransitServiceBuilder.java +++ b/src/main/java/org/opentripplanner/model/impl/OtpTransitServiceBuilder.java @@ -94,7 +94,7 @@ public class OtpTransitServiceBuilder { private final TripStopTimes stopTimesByTrip = new TripStopTimes(); - private final Map flexDurationFactors = new HashMap<>(); + private final Map flexTimePenalties = new HashMap<>(); private final EntityById fareZonesById = new DefaultEntityById<>(); @@ -214,7 +214,7 @@ public TripStopTimes getStopTimesSortedByTrip() { } public Map getFlexTimePenalty() { - return flexDurationFactors; + return flexTimePenalties; } public EntityById getFareZonesById() { diff --git a/src/main/java/org/opentripplanner/routing/api/request/framework/TimePenalty.java b/src/main/java/org/opentripplanner/routing/api/request/framework/TimePenalty.java index 0c6fdd96436..3ee07034135 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/framework/TimePenalty.java +++ b/src/main/java/org/opentripplanner/routing/api/request/framework/TimePenalty.java @@ -7,6 +7,9 @@ public final class TimePenalty extends AbstractLinearFunction { public static final TimePenalty ZERO = new TimePenalty(Duration.ZERO, 0.0); + /** + * An instance that doesn't actually apply a penalty and returns the duration unchanged. + */ public static final TimePenalty NONE = new TimePenalty(Duration.ZERO, 1.0); private TimePenalty(Duration constant, double coefficient) { diff --git a/src/main/java/org/opentripplanner/transit/model/timetable/TripTimesStringBuilder.java b/src/main/java/org/opentripplanner/transit/model/timetable/TripTimesStringBuilder.java new file mode 100644 index 00000000000..a5e77037dea --- /dev/null +++ b/src/main/java/org/opentripplanner/transit/model/timetable/TripTimesStringBuilder.java @@ -0,0 +1,64 @@ +package org.opentripplanner.transit.model.timetable; + +import java.util.ArrayList; +import org.opentripplanner.framework.time.TimeUtils; +import org.opentripplanner.transit.model.network.TripPattern; + +public class TripTimesStringBuilder { + + /** + * This encodes the trip times and information about stops in a readable way in order to simplify + * testing/debugging. The format of the outputput string is: + * + *
+   * REALTIME_STATE | stop1 [FLAGS] arrivalTime departureTime | stop2 ...
+   *
+   * Where flags are:
+   * C: Canceled
+   * R: Recorded
+   * PI: Prediction Inaccurate
+   * ND: No Data
+   * 
+ * + * @throws IllegalStateException if TripTimes does not match the TripPattern + */ + public static String encodeTripTimes(TripTimes tripTimes, TripPattern pattern) { + var stops = pattern.getStops(); + + if (tripTimes.getNumStops() != stops.size()) { + throw new IllegalArgumentException( + "TripTimes and TripPattern have different number of stops" + ); + } + + StringBuilder s = new StringBuilder(tripTimes.getRealTimeState().toString()); + for (int i = 0; i < tripTimes.getNumStops(); i++) { + var depart = tripTimes.getDepartureTime(i); + var arrive = tripTimes.getArrivalTime(i); + var flags = new ArrayList(); + if (tripTimes.isCancelledStop(i)) { + flags.add("C"); + } + if (tripTimes.isRecordedStop(i)) { + flags.add("R"); + } + if (tripTimes.isPredictionInaccurate(i)) { + flags.add("PI"); + } + if (tripTimes.isNoDataStop(i)) { + flags.add("ND"); + } + + s.append(" | ").append(stops.get(i).getName()); + if (!flags.isEmpty()) { + s.append(" [").append(String.join(",", flags)).append("]"); + } + s + .append(" ") + .append(TimeUtils.timeToStrCompact(arrive)) + .append(" ") + .append(TimeUtils.timeToStrCompact(depart)); + } + return s.toString(); + } +} diff --git a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls index 0f863393d87..393d5f014db 100644 --- a/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls +++ b/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls @@ -974,6 +974,18 @@ type fareComponent { routes: [Route] @deprecated } + +""" +Feed publisher information +""" +type FeedPublisher { + """Name of feed publisher""" + name: String! + + """Web address of feed publisher""" + url: String! +} + """ A feed provides routing data (stops, routes, timetables, etc.) from one or more public transport agencies. """ @@ -984,6 +996,9 @@ type Feed { """List of agencies which provide data to this feed""" agencies: [Agency] + "The publisher of the input transit data." + publisher: FeedPublisher + """ Alerts relevant for the feed. """ diff --git a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java index fcc59af845f..614c8778c6b 100644 --- a/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java +++ b/src/test/java/org/opentripplanner/apis/gtfs/GraphQLIntegrationTest.java @@ -43,6 +43,7 @@ import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.framework.model.Grams; +import org.opentripplanner.model.FeedInfo; import org.opentripplanner.model.fare.FareMedium; import org.opentripplanner.model.fare.FareProduct; import org.opentripplanner.model.fare.ItineraryFares; @@ -84,6 +85,7 @@ import org.opentripplanner.transit.model.framework.FeedScopedId; import org.opentripplanner.transit.model.network.BikeAccess; import org.opentripplanner.transit.model.network.TripPattern; +import org.opentripplanner.transit.model.organization.Agency; import org.opentripplanner.transit.model.site.RegularStop; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.model.timetable.RealTimeTripTimes; @@ -151,6 +153,18 @@ static void setup() { transitModel.addTripPattern(id("pattern-1"), pattern); + var feedId = "testfeed"; + var feedInfo = FeedInfo.dummyForTest(feedId); + transitModel.addFeedInfo(feedInfo); + + var agency = Agency + .of(new FeedScopedId(feedId, "agency-xx")) + .withName("speedtransit") + .withUrl("www.otp-foo.bar") + .withTimezone("Europe/Berlin") + .build(); + transitModel.addAgency(agency); + transitModel.initTimeZone(ZoneIds.BERLIN); transitModel.index(); var routes = Arrays diff --git a/src/test/java/org/opentripplanner/framework/collection/ListUtilsTest.java b/src/test/java/org/opentripplanner/framework/collection/ListUtilsTest.java index 6e72d5626c5..33dce1f5574 100644 --- a/src/test/java/org/opentripplanner/framework/collection/ListUtilsTest.java +++ b/src/test/java/org/opentripplanner/framework/collection/ListUtilsTest.java @@ -56,5 +56,11 @@ void distinctByKey() { assertEquals(List.of(first, third), deduplicated); } + @Test + void ofNullable() { + assertEquals(List.of(), ListUtils.ofNullable(null)); + assertEquals(List.of("A"), ListUtils.ofNullable("A")); + } + private record Wrapper(int i, String string) {} } diff --git a/src/test/java/org/opentripplanner/gtfs/mapping/TripMapperTest.java b/src/test/java/org/opentripplanner/gtfs/mapping/TripMapperTest.java index f24e405515d..964c3d8155e 100644 --- a/src/test/java/org/opentripplanner/gtfs/mapping/TripMapperTest.java +++ b/src/test/java/org/opentripplanner/gtfs/mapping/TripMapperTest.java @@ -111,14 +111,14 @@ void testMapCache() throws Exception { } @Test - void noFlexDurationModifier() { + void noFlexTimePenalty() { var mapper = defaultTripMapper(); mapper.map(TRIP); - assertTrue(mapper.flexSafeDurationModifiers().isEmpty()); + assertTrue(mapper.flexSafeTimePenalties().isEmpty()); } @Test - void flexDurationModifier() { + void flexTimePenalty() { var flexTrip = new Trip(); flexTrip.setId(new AgencyAndId("1", "1")); flexTrip.setSafeDurationFactor(1.5); @@ -126,8 +126,8 @@ void flexDurationModifier() { flexTrip.setRoute(new GtfsTestData().route); var mapper = defaultTripMapper(); var mapped = mapper.map(flexTrip); - var mod = mapper.flexSafeDurationModifiers().get(mapped); - assertEquals(1.5f, mod.coefficient()); - assertEquals(600, mod.constant().toSeconds()); + var penalty = mapper.flexSafeTimePenalties().get(mapped); + assertEquals(1.5f, penalty.coefficient()); + assertEquals(600, penalty.constant().toSeconds()); } } diff --git a/src/test/java/org/opentripplanner/mmri/AllModesAndAgenciesTest.java b/src/test/java/org/opentripplanner/mmri/AllModesAndAgenciesTest.java deleted file mode 100644 index f4e0a42fe83..00000000000 --- a/src/test/java/org/opentripplanner/mmri/AllModesAndAgenciesTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.opentripplanner.mmri; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.opentripplanner.GtfsTest; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; - -@Disabled("Requires stop-to-stop transfers without street network") -public class AllModesAndAgenciesTest extends GtfsTest { - - @Override - public final String getFeedName() { - return "mmri/1a"; - } - - @Test - public void test1a1() { - Itinerary itinerary = plan(+1388530800L, "1a1", "1a6", null, false, false, null, "", "", 5); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[5]); - - validateLeg(legs[0], 1388530860000L, 1388530920000L, "1a2", "1a1", null); - validateLeg(legs[2], 1388530980000L, 1388531040000L, "1a4", "1a3", null); - validateLeg(legs[4], 1388531100000L, 1388531160000L, "1a6", "1a5", null); - - assertEquals("", itinerary.toStr()); - } -} diff --git a/src/test/java/org/opentripplanner/mmri/ExcludedStopsTest.java b/src/test/java/org/opentripplanner/mmri/ExcludedStopsTest.java deleted file mode 100644 index 4fe48f2c123..00000000000 --- a/src/test/java/org/opentripplanner/mmri/ExcludedStopsTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.opentripplanner.mmri; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.opentripplanner.GtfsTest; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; - -@Disabled("Requires stop banning") -public class ExcludedStopsTest extends GtfsTest { - - @Override - public final String getFeedName() { - return "mmri/3f"; - } - - @Test - public void test3f1() { - Itinerary itinerary = plan(+1388530860L, "3f1", "3f3", null, false, false, null, "", "3f2", 1); - - Leg leg = itinerary.getLegs().toArray(new Leg[1])[0]; - - validateLeg(leg, 1388530860000L, 1388531040000L, "3f3", "3f1", null); - - assertEquals("", itinerary.toStr()); - } -} diff --git a/src/test/java/org/opentripplanner/mmri/OnTripTest.java b/src/test/java/org/opentripplanner/mmri/OnTripTest.java deleted file mode 100644 index 2b0e574f352..00000000000 --- a/src/test/java/org/opentripplanner/mmri/OnTripTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.opentripplanner.mmri; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.opentripplanner.GtfsTest; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; - -@Disabled("Requires departing onboard trip") -public class OnTripTest extends GtfsTest { - - @Override - public final String getFeedName() { - return "mmri/2f"; - } - - @Test - public void test2f1() { - Itinerary itinerary = plan( - +1388530920L, - null, - "2f2", - "2f|intercity", - false, - false, - null, - "", - "", - 2 - ); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[2]); - - validateLeg(legs[0], 1388530920000L, 1388531040000L, "2f3", null, null); - validateLeg(legs[1], 1388531160000L, 1388531340000L, "2f2", "2f3", null); - - assertEquals("", itinerary.toStr()); - } -} diff --git a/src/test/java/org/opentripplanner/mmri/PlannerstackScenarioTest.java b/src/test/java/org/opentripplanner/mmri/PlannerstackScenarioTest.java deleted file mode 100644 index 1e0ac9b96f2..00000000000 --- a/src/test/java/org/opentripplanner/mmri/PlannerstackScenarioTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.opentripplanner.mmri; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.opentripplanner.GtfsTest; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; - -@Disabled("Requires departing onboard a trip") -public class PlannerstackScenarioTest extends GtfsTest { - - @Override - public final String getFeedName() { - return "mmri/plannerstack_scenario"; - } - - @Test - public void testPlannerstackScenario() { - Itinerary itinerary = plan( - +1388531220L, - null, - "plannerstack_scenario2", - "plannerstack_scenario|intercity", - false, - false, - null, - "", - "", - 2 - ); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[2]); - - validateLeg(legs[0], 1388531220000L, 1388531340000L, "plannerstack_scenario3", null, null); - validateLeg( - legs[1], - 1388531400000L, - 1388531640000L, - "plannerstack_scenario2", - "plannerstack_scenario3", - null - ); - - assertEquals("", itinerary.toStr()); - } -} diff --git a/src/test/java/org/opentripplanner/mmri/PreferencesTest.java b/src/test/java/org/opentripplanner/mmri/PreferencesTest.java index d3c55097511..c33f67345fc 100644 --- a/src/test/java/org/opentripplanner/mmri/PreferencesTest.java +++ b/src/test/java/org/opentripplanner/mmri/PreferencesTest.java @@ -1,9 +1,7 @@ package org.opentripplanner.mmri; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.opentripplanner.transit.model.basic.TransitMode.BUS; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.opentripplanner.GtfsTest; import org.opentripplanner.model.plan.Itinerary; @@ -30,28 +28,4 @@ public void test2c1() { itinerary.toStr() ); } - - @Test - @Disabled - public void test2c2() { - Itinerary itinerary = plan(+1388530860L, "2c1", "2c3", null, false, false, BUS, "", "", 3); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[3]); - - validateLeg(legs[1], 1388530920000L, 1388531160000L, "2c5", "2c4", null); - - assertEquals("", itinerary.toStr()); - } - - @Test - @Disabled - public void test2c3() { - Itinerary itinerary = plan(+1388530860L, "2c1", "2c3", null, false, true, null, "", "", 3); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[3]); - - validateLeg(legs[1], 1388530920000L, 1388531160000L, "2c5", "2c4", null); - - assertEquals("", itinerary.toStr()); - } } diff --git a/src/test/java/org/opentripplanner/mmri/ServiceAlertTest.java b/src/test/java/org/opentripplanner/mmri/ServiceAlertTest.java deleted file mode 100644 index 2d35f0a246d..00000000000 --- a/src/test/java/org/opentripplanner/mmri/ServiceAlertTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.opentripplanner.mmri; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.opentripplanner.GtfsTest; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; - -@Disabled("Service alerts not mapped correctly") -public class ServiceAlertTest extends GtfsTest { - - @Override - public final String getFeedName() { - return "mmri/3i"; - } - - @Test - public void test3i1() { - Itinerary itinerary = plan(+1388530860L, "3i1", "3i2", null, false, false, null, "", "", 1); - - Leg leg = itinerary.getLegs().toArray(new Leg[1])[0]; - - validateLeg(leg, 1388530860000L, 1388530920000L, "3i2", "3i1", "Unknown effect"); - - assertEquals("", itinerary.toStr()); - } -} diff --git a/src/test/java/org/opentripplanner/mmri/TimeTest.java b/src/test/java/org/opentripplanner/mmri/TimeTest.java index 77123d3e656..90be00a56bb 100644 --- a/src/test/java/org/opentripplanner/mmri/TimeTest.java +++ b/src/test/java/org/opentripplanner/mmri/TimeTest.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.opentripplanner.GtfsTest; import org.opentripplanner.model.plan.Itinerary; @@ -37,30 +36,6 @@ public void test1g2() { assertEquals("Stop 1g1 ~ BUS bus 0:01 0:02 ~ Stop 1g2 [C₁90]", itinerary.toStr()); } - @Test - @Disabled - public void test1g3() { - Itinerary itinerary = plan(+1388617380L, "1g1", "1g2", null, false, false, null, "", "", 1); - - Leg leg = itinerary.getLegs().toArray(new Leg[1])[0]; - - validateLeg(leg, 1388703660000L, 1388703720000L, "1g2", "1g1", null); - - assertEquals("", itinerary.toStr()); - } - - @Test - @Disabled - public void test1g4() { - Itinerary itinerary = plan(-1388617440L, "1g1", "1g2", null, false, false, null, "", "", 1); - - Leg leg = itinerary.getLegs().toArray(new Leg[1])[0]; - - validateLeg(leg, 1388531100000L, 1388531160000L, "1g2", "1g1", null); - - assertEquals("", itinerary.toStr()); - } - @Test public void test1g5() { Itinerary itinerary = plan(+1388703780L, "1g1", "1g2", null, false, false, null, "", "", 1); diff --git a/src/test/java/org/opentripplanner/mmri/TransferTimeTest.java b/src/test/java/org/opentripplanner/mmri/TransferTimeTest.java deleted file mode 100644 index 9b0fc12cf37..00000000000 --- a/src/test/java/org/opentripplanner/mmri/TransferTimeTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.opentripplanner.mmri; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.opentripplanner.GtfsTest; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; - -@Disabled -public class TransferTimeTest extends GtfsTest { - - @Override - public final String getFeedName() { - return "mmri/2a2"; - } - - @Test - public void test2a3() { - Itinerary itinerary = plan(+1388530860L, "2a3", "2a6", null, false, false, null, "", "", 3); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[3]); - - validateLeg(legs[0], 1388530860000L, 1388530920000L, "2a4", "2a3", null); - validateLeg(legs[2], 1388531280000L, 1388531340000L, "2a6", "2a5", null); - - assertEquals("", itinerary.toStr()); - } - - @Test - public void test2a4() { - Itinerary itinerary = plan(+1388530920L, "2a3", "2a6", null, false, false, null, "", "", 3); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[3]); - - validateLeg(legs[0], 1388531040000L, 1388531100000L, "2a4", "2a3", null); - validateLeg(legs[2], 1388531400000L, 1388531460000L, "2a6", "2a5", null); - - assertEquals("", itinerary.toStr()); - } - - @Test - public void test2a5() { - Itinerary itinerary = plan(-1388531460L, "2a3", "2a6", null, false, false, null, "", "", 3); - - Leg[] legs = itinerary.getLegs().toArray(new Leg[3]); - - validateLeg(legs[0], 1388531040000L, 1388531100000L, "2a4", "2a3", null); - validateLeg(legs[2], 1388531400000L, 1388531460000L, "2a6", "2a5", null); - - assertEquals("", itinerary.toStr()); - } -} diff --git a/src/test/resources/mmri/1a/agency.txt b/src/test/resources/mmri/1a/agency.txt deleted file mode 100644 index d6f92d6af7f..00000000000 --- a/src/test/resources/mmri/1a/agency.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,agency_name,agency_url,agency_timezone,agency_lang -MMRI,Multimodale Reisinformatie,http://mmri.nl/,Europe/Amsterdam,nl diff --git a/src/test/resources/mmri/1a/calendar_dates.txt b/src/test/resources/mmri/1a/calendar_dates.txt deleted file mode 100644 index bc0abe90518..00000000000 --- a/src/test/resources/mmri/1a/calendar_dates.txt +++ /dev/null @@ -1,4 +0,0 @@ -date,service_id,exception_type -20140101,1a|bus|1,1 -20140101,1a|ferry|1,1 -20140101,1a|train|1,1 diff --git a/src/test/resources/mmri/1a/routes.txt b/src/test/resources/mmri/1a/routes.txt deleted file mode 100644 index 130126398bf..00000000000 --- a/src/test/resources/mmri/1a/routes.txt +++ /dev/null @@ -1,4 +0,0 @@ -agency_id,route_id,route_short_name,route_long_name,route_type -MMRI,1a|bus,bus,,3 -MMRI,1a|ferry,ferry,,4 -MMRI,1a|train,train,,2 diff --git a/src/test/resources/mmri/1a/stop_times.txt b/src/test/resources/mmri/1a/stop_times.txt deleted file mode 100644 index 280a530103d..00000000000 --- a/src/test/resources/mmri/1a/stop_times.txt +++ /dev/null @@ -1,7 +0,0 @@ -trip_id,arrival_time,departure_time,stop_id,stop_sequence -1a|bus|1,00:01:00,00:01:00,1a1,1 -1a|bus|1,00:02:00,00:02:00,1a2,2 -1a|ferry|1,00:03:00,00:03:00,1a3,3 -1a|ferry|1,00:04:00,00:04:00,1a4,4 -1a|train|1,00:05:00,00:05:00,1a5,5 -1a|train|1,00:06:00,00:06:00,1a6,6 diff --git a/src/test/resources/mmri/1a/stops.txt b/src/test/resources/mmri/1a/stops.txt deleted file mode 100644 index 11b92589dd2..00000000000 --- a/src/test/resources/mmri/1a/stops.txt +++ /dev/null @@ -1,7 +0,0 @@ -stop_id,stop_name,stop_lat,stop_lon -1a1,Stop 1a1,1.101,1.1 -1a2,Stop 1a2,1.102,1.1 -1a3,Stop 1a3,1.103,1.1 -1a4,Stop 1a4,1.104,1.1 -1a5,Stop 1a5,1.105,1.1 -1a6,Stop 1a6,1.106,1.1 diff --git a/src/test/resources/mmri/1a/transfers.txt b/src/test/resources/mmri/1a/transfers.txt deleted file mode 100644 index 9bdfd232de9..00000000000 --- a/src/test/resources/mmri/1a/transfers.txt +++ /dev/null @@ -1,3 +0,0 @@ -from_stop_id,to_stop_id,transfer_type,min_transfer_time -1a2,1a3,2,0 -1a4,1a5,2,0 diff --git a/src/test/resources/mmri/1a/trips.txt b/src/test/resources/mmri/1a/trips.txt deleted file mode 100644 index 4573658c9a5..00000000000 --- a/src/test/resources/mmri/1a/trips.txt +++ /dev/null @@ -1,4 +0,0 @@ -route_id,service_id,trip_id -1a|bus,1a|bus|1,1a|bus|1 -1a|ferry,1a|ferry|1,1a|ferry|1 -1a|train,1a|train|1,1a|train|1 diff --git a/src/test/resources/mmri/2a2/agency.txt b/src/test/resources/mmri/2a2/agency.txt deleted file mode 100644 index d6f92d6af7f..00000000000 --- a/src/test/resources/mmri/2a2/agency.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,agency_name,agency_url,agency_timezone,agency_lang -MMRI,Multimodale Reisinformatie,http://mmri.nl/,Europe/Amsterdam,nl diff --git a/src/test/resources/mmri/2a2/calendar_dates.txt b/src/test/resources/mmri/2a2/calendar_dates.txt deleted file mode 100644 index 2461c7fe35f..00000000000 --- a/src/test/resources/mmri/2a2/calendar_dates.txt +++ /dev/null @@ -1,2 +0,0 @@ -date,service_id,exception_type -20140101,ignore,1 diff --git a/src/test/resources/mmri/2a2/routes.txt b/src/test/resources/mmri/2a2/routes.txt deleted file mode 100644 index f8da6695081..00000000000 --- a/src/test/resources/mmri/2a2/routes.txt +++ /dev/null @@ -1,3 +0,0 @@ -agency_id,route_id,route_short_name,route_long_name,route_type -MMRI,2a2|bus|1,bus 1,,3 -MMRI,2a2|bus|2,bus 2,,3 diff --git a/src/test/resources/mmri/2a2/stop_times.txt b/src/test/resources/mmri/2a2/stop_times.txt deleted file mode 100644 index a3bb8933370..00000000000 --- a/src/test/resources/mmri/2a2/stop_times.txt +++ /dev/null @@ -1,15 +0,0 @@ -trip_id,arrival_time,departure_time,stop_id,stop_sequence -2a2|bus|1|1,00:01:00,00:01:00,2a3,1 -2a2|bus|1|1,00:02:00,00:02:00,2a4,2 -2a2|bus|1|2,00:04:00,00:04:00,2a3,1 -2a2|bus|1|2,00:05:00,00:05:00,2a4,2 -2a2|bus|1|3,00:07:00,00:07:00,2a3,1 -2a2|bus|1|3,00:08:00,00:08:00,2a4,2 -2a2|bus|2|1,00:02:00,00:02:00,2a5,1 -2a2|bus|2|1,00:03:00,00:03:00,2a6,2 -2a2|bus|2|2,00:05:00,00:05:00,2a5,1 -2a2|bus|2|2,00:06:00,00:06:00,2a6,2 -2a2|bus|2|3,00:08:00,00:08:00,2a5,1 -2a2|bus|2|3,00:09:00,00:09:00,2a6,2 -2a2|bus|2|4,00:10:00,00:10:00,2a5,1 -2a2|bus|2|4,00:11:00,00:11:00,2a6,2 \ No newline at end of file diff --git a/src/test/resources/mmri/2a2/stops.txt b/src/test/resources/mmri/2a2/stops.txt deleted file mode 100644 index c3c457bc753..00000000000 --- a/src/test/resources/mmri/2a2/stops.txt +++ /dev/null @@ -1,5 +0,0 @@ -stop_id,stop_name,stop_lat,stop_lon -2a3,Stop 2a3,2.103,2.102 -2a4,Stop 2a4,2.104,2.102 -2a5,Stop 2a5,2.105,2.102 -2a6,Stop 2a6,2.106,2.102 diff --git a/src/test/resources/mmri/2a2/transfers.txt b/src/test/resources/mmri/2a2/transfers.txt deleted file mode 100644 index 4ec2f4adf41..00000000000 --- a/src/test/resources/mmri/2a2/transfers.txt +++ /dev/null @@ -1,2 +0,0 @@ -from_stop_id,to_stop_id,transfer_type,min_transfer_time -2a4,2a5,2,300 diff --git a/src/test/resources/mmri/2a2/trips.txt b/src/test/resources/mmri/2a2/trips.txt deleted file mode 100644 index 1a8f2a56fdc..00000000000 --- a/src/test/resources/mmri/2a2/trips.txt +++ /dev/null @@ -1,8 +0,0 @@ -route_id,service_id,trip_id -2a2|bus|1,ignore,2a2|bus|1|1 -2a2|bus|1,ignore,2a2|bus|1|2 -2a2|bus|1,ignore,2a2|bus|1|3 -2a2|bus|2,ignore,2a2|bus|2|1 -2a2|bus|2,ignore,2a2|bus|2|2 -2a2|bus|2,ignore,2a2|bus|2|3 -2a2|bus|2,ignore,2a2|bus|2|4 \ No newline at end of file diff --git a/src/test/resources/mmri/2f/agency.txt b/src/test/resources/mmri/2f/agency.txt deleted file mode 100644 index d6f92d6af7f..00000000000 --- a/src/test/resources/mmri/2f/agency.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,agency_name,agency_url,agency_timezone,agency_lang -MMRI,Multimodale Reisinformatie,http://mmri.nl/,Europe/Amsterdam,nl diff --git a/src/test/resources/mmri/2f/calendar_dates.txt b/src/test/resources/mmri/2f/calendar_dates.txt deleted file mode 100644 index 2461c7fe35f..00000000000 --- a/src/test/resources/mmri/2f/calendar_dates.txt +++ /dev/null @@ -1,2 +0,0 @@ -date,service_id,exception_type -20140101,ignore,1 diff --git a/src/test/resources/mmri/2f/routes.txt b/src/test/resources/mmri/2f/routes.txt deleted file mode 100644 index 5875e0081d4..00000000000 --- a/src/test/resources/mmri/2f/routes.txt +++ /dev/null @@ -1,4 +0,0 @@ -agency_id,route_id,route_short_name,route_long_name,route_type -MMRI,2f|intercity,,Intercity,2 -MMRI,2f|slt|1,,Local train 1,2 -MMRI,2f|slt|2,,Local train 2,2 diff --git a/src/test/resources/mmri/2f/stop_times.txt b/src/test/resources/mmri/2f/stop_times.txt deleted file mode 100644 index 559d84d992f..00000000000 --- a/src/test/resources/mmri/2f/stop_times.txt +++ /dev/null @@ -1,9 +0,0 @@ -trip_id,arrival_time,departure_time,stop_id,stop_sequence -2f|intercity,00:01:00,00:01:00,2f1,1 -2f|intercity,00:04:00,00:04:00,2f3,2 -2f|slt|1,00:01:00,00:01:00,2f1,1 -2f|slt|1,00:03:00,00:03:00,2f2,2 -2f|slt|1,00:05:00,00:05:00,2f3,3 -2f|slt|2,00:06:00,00:06:00,2f3,1 -2f|slt|2,00:09:00,00:09:00,2f2,2 -2f|slt|2,00:11:00,00:11:00,2f1,3 diff --git a/src/test/resources/mmri/2f/stops.txt b/src/test/resources/mmri/2f/stops.txt deleted file mode 100644 index 538a3240e55..00000000000 --- a/src/test/resources/mmri/2f/stops.txt +++ /dev/null @@ -1,4 +0,0 @@ -stop_id,stop_name,stop_lat,stop_lon -2f1,Stop 2f1,2.701,2.700 -2f2,Stop 2f2,2.702,2.700 -2f3,Stop 2f3,2.703,2.700 diff --git a/src/test/resources/mmri/2f/trips.txt b/src/test/resources/mmri/2f/trips.txt deleted file mode 100644 index f9dba48f134..00000000000 --- a/src/test/resources/mmri/2f/trips.txt +++ /dev/null @@ -1,4 +0,0 @@ -route_id,service_id,trip_id -2f|intercity,ignore,2f|intercity -2f|slt|1,ignore,2f|slt|1 -2f|slt|2,ignore,2f|slt|2 diff --git a/src/test/resources/mmri/3f/agency.txt b/src/test/resources/mmri/3f/agency.txt deleted file mode 100644 index d6f92d6af7f..00000000000 --- a/src/test/resources/mmri/3f/agency.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,agency_name,agency_url,agency_timezone,agency_lang -MMRI,Multimodale Reisinformatie,http://mmri.nl/,Europe/Amsterdam,nl diff --git a/src/test/resources/mmri/3f/calendar_dates.txt b/src/test/resources/mmri/3f/calendar_dates.txt deleted file mode 100644 index 2461c7fe35f..00000000000 --- a/src/test/resources/mmri/3f/calendar_dates.txt +++ /dev/null @@ -1,2 +0,0 @@ -date,service_id,exception_type -20140101,ignore,1 diff --git a/src/test/resources/mmri/3f/routes.txt b/src/test/resources/mmri/3f/routes.txt deleted file mode 100644 index 33917fc7217..00000000000 --- a/src/test/resources/mmri/3f/routes.txt +++ /dev/null @@ -1,3 +0,0 @@ -agency_id,route_id,route_short_name,route_long_name,route_type -MMRI,3f|1,,Intercity 1,2 -MMRI,3f|2,,Intercity 2,2 diff --git a/src/test/resources/mmri/3f/stop_times.txt b/src/test/resources/mmri/3f/stop_times.txt deleted file mode 100644 index 563936db238..00000000000 --- a/src/test/resources/mmri/3f/stop_times.txt +++ /dev/null @@ -1,7 +0,0 @@ -trip_id,arrival_time,departure_time,stop_id,stop_sequence -3f|1,00:01:00,00:01:00,3f1,1 -3f|1,00:02:00,00:02:00,3f2,2 -3f|1,00:03:00,00:03:00,3f3,3 -3f|2,00:01:00,00:01:00,3f1,1 -3f|2,00:02:00,00:02:00,3f4,2 -3f|2,00:04:00,00:04:00,3f3,3 diff --git a/src/test/resources/mmri/3f/stops.txt b/src/test/resources/mmri/3f/stops.txt deleted file mode 100644 index 7ccbea9059f..00000000000 --- a/src/test/resources/mmri/3f/stops.txt +++ /dev/null @@ -1,5 +0,0 @@ -stop_id,stop_name,stop_lat,stop_lon -3f1,Stop 3f1,3.601,3.602 -3f2,Stop 3f2,3.602,3.601 -3f3,Stop 3f3,3.603,3.602 -3f4,Stop 3f4,3.602,3.603 diff --git a/src/test/resources/mmri/3f/trips.txt b/src/test/resources/mmri/3f/trips.txt deleted file mode 100644 index c16ec0732bb..00000000000 --- a/src/test/resources/mmri/3f/trips.txt +++ /dev/null @@ -1,3 +0,0 @@ -route_id,service_id,trip_id -3f|1,ignore,3f|1 -3f|2,ignore,3f|2 diff --git a/src/test/resources/mmri/3i.pb b/src/test/resources/mmri/3i.pb deleted file mode 100644 index f03fd3dc6bf..00000000000 Binary files a/src/test/resources/mmri/3i.pb and /dev/null differ diff --git a/src/test/resources/mmri/3i/agency.txt b/src/test/resources/mmri/3i/agency.txt deleted file mode 100644 index d6f92d6af7f..00000000000 --- a/src/test/resources/mmri/3i/agency.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,agency_name,agency_url,agency_timezone,agency_lang -MMRI,Multimodale Reisinformatie,http://mmri.nl/,Europe/Amsterdam,nl diff --git a/src/test/resources/mmri/3i/calendar_dates.txt b/src/test/resources/mmri/3i/calendar_dates.txt deleted file mode 100644 index 2461c7fe35f..00000000000 --- a/src/test/resources/mmri/3i/calendar_dates.txt +++ /dev/null @@ -1,2 +0,0 @@ -date,service_id,exception_type -20140101,ignore,1 diff --git a/src/test/resources/mmri/3i/routes.txt b/src/test/resources/mmri/3i/routes.txt deleted file mode 100644 index a70c8bf0979..00000000000 --- a/src/test/resources/mmri/3i/routes.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,route_id,route_short_name,route_long_name,route_type -MMRI,3i|1,bus 1,,3 \ No newline at end of file diff --git a/src/test/resources/mmri/3i/stop_times.txt b/src/test/resources/mmri/3i/stop_times.txt deleted file mode 100644 index 6954a3066aa..00000000000 --- a/src/test/resources/mmri/3i/stop_times.txt +++ /dev/null @@ -1,3 +0,0 @@ -trip_id,arrival_time,departure_time,stop_id,stop_sequence -3i|1,00:01:00,00:01:00,3i1,1 -3i|1,00:02:00,00:02:00,3i2,2 \ No newline at end of file diff --git a/src/test/resources/mmri/3i/stops.txt b/src/test/resources/mmri/3i/stops.txt deleted file mode 100644 index 62645f565ee..00000000000 --- a/src/test/resources/mmri/3i/stops.txt +++ /dev/null @@ -1,3 +0,0 @@ -stop_id,stop_name,stop_lat,stop_lon -3i1,Stop 3i1,3.801,3.8 -3i2,Stop 3i2,3.802,3.8 diff --git a/src/test/resources/mmri/3i/trips.txt b/src/test/resources/mmri/3i/trips.txt deleted file mode 100644 index 1269810469d..00000000000 --- a/src/test/resources/mmri/3i/trips.txt +++ /dev/null @@ -1,2 +0,0 @@ -route_id,service_id,trip_id -3i|1,ignore,3i|1 \ No newline at end of file diff --git a/src/test/resources/mmri/plannerstack_scenario.pb b/src/test/resources/mmri/plannerstack_scenario.pb deleted file mode 100644 index 810f9b3e6f1..00000000000 Binary files a/src/test/resources/mmri/plannerstack_scenario.pb and /dev/null differ diff --git a/src/test/resources/mmri/plannerstack_scenario/agency.txt b/src/test/resources/mmri/plannerstack_scenario/agency.txt deleted file mode 100644 index d6f92d6af7f..00000000000 --- a/src/test/resources/mmri/plannerstack_scenario/agency.txt +++ /dev/null @@ -1,2 +0,0 @@ -agency_id,agency_name,agency_url,agency_timezone,agency_lang -MMRI,Multimodale Reisinformatie,http://mmri.nl/,Europe/Amsterdam,nl diff --git a/src/test/resources/mmri/plannerstack_scenario/calendar_dates.txt b/src/test/resources/mmri/plannerstack_scenario/calendar_dates.txt deleted file mode 100644 index 2461c7fe35f..00000000000 --- a/src/test/resources/mmri/plannerstack_scenario/calendar_dates.txt +++ /dev/null @@ -1,2 +0,0 @@ -date,service_id,exception_type -20140101,ignore,1 diff --git a/src/test/resources/mmri/plannerstack_scenario/routes.txt b/src/test/resources/mmri/plannerstack_scenario/routes.txt deleted file mode 100644 index ea764d3d770..00000000000 --- a/src/test/resources/mmri/plannerstack_scenario/routes.txt +++ /dev/null @@ -1,4 +0,0 @@ -agency_id,route_id,route_short_name,route_long_name,route_type -MMRI,plannerstack_scenario|intercity,,Intercity,2 -MMRI,plannerstack_scenario|slt|1,,Local train 1,2 -MMRI,plannerstack_scenario|slt|2,,Local train 2,2 diff --git a/src/test/resources/mmri/plannerstack_scenario/stop_times.txt b/src/test/resources/mmri/plannerstack_scenario/stop_times.txt deleted file mode 100644 index 7c67a1ef04c..00000000000 --- a/src/test/resources/mmri/plannerstack_scenario/stop_times.txt +++ /dev/null @@ -1,12 +0,0 @@ -trip_id,arrival_time,departure_time,stop_id,stop_sequence -plannerstack_scenario|intercity,00:01:00,00:01:00,plannerstack_scenario1,1 -plannerstack_scenario|intercity,00:04:00,00:04:00,plannerstack_scenario3,2 -plannerstack_scenario|slt|1,00:01:00,00:01:00,plannerstack_scenario1,1 -plannerstack_scenario|slt|1,00:03:00,00:03:00,plannerstack_scenario2,2 -plannerstack_scenario|slt|1,00:05:00,00:05:00,plannerstack_scenario3,3 -plannerstack_scenario|slt|2,00:06:00,00:06:00,plannerstack_scenario3,1 -plannerstack_scenario|slt|2,00:09:00,00:09:00,plannerstack_scenario2,2 -plannerstack_scenario|slt|2,00:11:00,00:11:00,plannerstack_scenario1,3 -plannerstack_scenario|slt|3,00:10:00,00:10:00,plannerstack_scenario3,1 -plannerstack_scenario|slt|3,00:14:00,00:14:00,plannerstack_scenario2,2 -plannerstack_scenario|slt|3,00:16:00,00:16:00,plannerstack_scenario1,3 \ No newline at end of file diff --git a/src/test/resources/mmri/plannerstack_scenario/stops.txt b/src/test/resources/mmri/plannerstack_scenario/stops.txt deleted file mode 100644 index 4dac741a416..00000000000 --- a/src/test/resources/mmri/plannerstack_scenario/stops.txt +++ /dev/null @@ -1,4 +0,0 @@ -stop_id,stop_name,stop_lat,stop_lon -plannerstack_scenario1,Stop plannerstack_scenario1,2.701,2.700 -plannerstack_scenario2,Stop plannerstack_scenario2,2.702,2.700 -plannerstack_scenario3,Stop plannerstack_scenario3,2.703,2.700 diff --git a/src/test/resources/mmri/plannerstack_scenario/trips.txt b/src/test/resources/mmri/plannerstack_scenario/trips.txt deleted file mode 100644 index ce1cd4690a2..00000000000 --- a/src/test/resources/mmri/plannerstack_scenario/trips.txt +++ /dev/null @@ -1,5 +0,0 @@ -route_id,service_id,trip_id -plannerstack_scenario|intercity,ignore,plannerstack_scenario|intercity -plannerstack_scenario|slt|1,ignore,plannerstack_scenario|slt|1 -plannerstack_scenario|slt|2,ignore,plannerstack_scenario|slt|2 -plannerstack_scenario|slt|2,ignore,plannerstack_scenario|slt|3 diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/expectations/feedinfo.json b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/feedinfo.json new file mode 100644 index 00000000000..3cf3bd06d66 --- /dev/null +++ b/src/test/resources/org/opentripplanner/apis/gtfs/expectations/feedinfo.json @@ -0,0 +1,18 @@ +{ + "data" : { + "feeds" : [ + { + "agencies" : [ + { + "name" : "speedtransit", + "url" : "www.otp-foo.bar" + } + ], + "publisher" : { + "name" : "publisher", + "url" : "www.z.org" + } + } + ] + } +} \ No newline at end of file diff --git a/src/test/resources/org/opentripplanner/apis/gtfs/queries/feedinfo.graphql b/src/test/resources/org/opentripplanner/apis/gtfs/queries/feedinfo.graphql new file mode 100644 index 00000000000..68516d26237 --- /dev/null +++ b/src/test/resources/org/opentripplanner/apis/gtfs/queries/feedinfo.graphql @@ -0,0 +1,12 @@ +{ + feeds { + agencies { + name + url + } + publisher { + name + url + } + } +} \ No newline at end of file