From f7918b8ae0610234fc73c540e55fc35e758f86f4 Mon Sep 17 00:00:00 2001 From: Jonah <73760377+jonerrr@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:48:53 -0400 Subject: [PATCH] store bus route polylines as wkt --- backend/Cargo.lock | 302 ++++++++++++++---- backend/Cargo.toml | 4 +- .../20240609200453_bus_stops.up.sql | 1 + backend/src/bus/static_data.rs | 92 +++--- backend/src/main.rs | 8 - backend/src/routes/bus/routes.rs | 35 +- backend/src/static_data.rs | 18 +- 7 files changed, 324 insertions(+), 136 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 1f8e799..2ef3d2f 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -76,6 +76,15 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "arbitrary" version = "1.3.2" @@ -188,10 +197,12 @@ dependencies = [ "chrono-tz", "csv", "futures", + "geo", "http", "indicatif", - "itertools", + "itertools 0.13.0", "once_cell", + "polyline", "prost", "prost-build", "rayon", @@ -206,6 +217,7 @@ dependencies = [ "tracing", "tracing-subscriber", "uuid", + "wkt", "zip", ] @@ -280,9 +292,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "bzip2" @@ -307,9 +319,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" dependencies = [ "jobserver", "libc", @@ -404,15 +416,15 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -572,6 +584,16 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "earcutr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" +dependencies = [ + "itertools 0.11.0", + "num-traits", +] + [[package]] name = "either" version = "1.13.0" @@ -639,14 +661,20 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", ] +[[package]] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" + [[package]] name = "flume" version = "0.11.0" @@ -783,6 +811,44 @@ dependencies = [ "version_check", ] +[[package]] +name = "geo" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f811f663912a69249fa620dcd2a005db7254529da2d8a0b23942e81f47084501" +dependencies = [ + "earcutr", + "float_next_after", + "geo-types", + "geographiclib-rs", + "log", + "num-traits", + "robust", + "rstar", + "spade", +] + +[[package]] +name = "geo-types" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff16065e5720f376fbced200a5ae0f47ace85fd70b7e54269790281353b6d61" +dependencies = [ + "approx", + "num-traits", + "rstar", + "serde", +] + +[[package]] +name = "geographiclib-rs" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e5ed84f8089c70234b0a8e0aedb6dc733671612ddc0d37c6066052f9781960" +dependencies = [ + "libm", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -800,6 +866,15 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -819,6 +894,16 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -950,9 +1035,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -1003,9 +1088,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown", @@ -1048,6 +1133,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1074,9 +1168,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1205,9 +1299,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", @@ -1302,9 +1396,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -1497,6 +1591,15 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "polyline" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f19cbf429afe5a5186d4c6ca7b246b446b2d18919eefdddb521792d57c874f67" +dependencies = [ + "geo-types", +] + [[package]] name = "portable-atomic" version = "1.7.0" @@ -1511,12 +1614,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2288c0e17cc8d342c712bb43a257a80ebffce59cdb33d5000d8348f3ec02528b" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ "zerocopy", - "zerocopy-derive", ] [[package]] @@ -1556,7 +1658,7 @@ checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck", - "itertools", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -1576,7 +1678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", "syn", @@ -1593,9 +1695,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" dependencies = [ "bytes", "pin-project-lite", @@ -1603,6 +1705,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls 0.23.12", + "socket2", "thiserror", "tokio", "tracing", @@ -1610,9 +1713,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" dependencies = [ "bytes", "rand", @@ -1634,6 +1737,7 @@ dependencies = [ "libc", "once_cell", "socket2", + "tracing", "windows-sys 0.52.0", ] @@ -1783,7 +1887,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls 0.23.12", - "rustls-pemfile 2.1.2", + "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", "serde_json", @@ -1815,6 +1919,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "robust" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30" + [[package]] name = "rsa" version = "0.9.6" @@ -1835,6 +1945,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rstar" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133315eb94c7b1e8d0cb097e5a710d850263372fd028fff18969de708afc7008" +dependencies = [ + "heapless", + "num-traits", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1843,9 +1964,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustix" @@ -1896,9 +2017,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64 0.22.1", "rustls-pki-types", @@ -1906,9 +2027,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -1961,18 +2082,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" dependencies = [ "proc-macro2", "quote", @@ -1981,9 +2102,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ "itoa", "memchr", @@ -2109,6 +2230,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spade" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "766195f983f4098dc3bf37fb66bd609f6e6258c4b8db684d05252b2c694cdbcd" +dependencies = [ + "hashbrown", + "num-traits", + "robust", + "smallvec", +] + [[package]] name = "spin" version = "0.9.8" @@ -2343,6 +2476,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "stringprep" version = "0.1.5" @@ -2362,9 +2501,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -2385,14 +2524,15 @@ checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2562,15 +2702,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -2754,19 +2894,20 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -2779,9 +2920,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -2791,9 +2932,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2801,9 +2942,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -2814,15 +2955,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -2902,6 +3043,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3033,6 +3183,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wkt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "296937617013271141d1145d9c05861f5ed3b1bc4297e81c692aa3cff9270a9c" +dependencies = [ + "geo-types", + "log", + "num-traits", + "thiserror", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -3128,18 +3290,18 @@ dependencies = [ [[package]] name = "zstd-safe" -version = "7.2.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.12+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 009f0d4..9af6a0e 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -9,13 +9,14 @@ axum = "0.7.5" chrono = { version = "0.4.38", features = ["serde"] } chrono-tz = "0.9.0" csv = "1.3.0" -# geo = "0.28.0" # geo-types = "0.7.13" futures = "0.3.30" +geo = "0.28.0" http = "1.1.0" indicatif = "0.17.8" itertools = "0.13.0" once_cell = "1.19.0" +polyline = "0.11.0" prost = "0.13.1" rayon = "1.10.0" regex = "1.10.6" @@ -41,6 +42,7 @@ tower-http = { version = "0.5.2", features = [ tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } uuid = { version = "1.9.1", features = ["serde", "v5", "v7"] } +wkt = "0.11.0" zip = "2.1.6" [build-dependencies] diff --git a/backend/migrations/20240609200453_bus_stops.up.sql b/backend/migrations/20240609200453_bus_stops.up.sql index 73da080..9aad3d2 100644 --- a/backend/migrations/20240609200453_bus_stops.up.sql +++ b/backend/migrations/20240609200453_bus_stops.up.sql @@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS bus_route_stops ( -- can be 1 or 0 -- each route has two directions with separate stops direction INTEGER NOT NULL, + geom VARCHAR NOT NULL, PRIMARY KEY (route_id, stop_id, stop_sequence) ); diff --git a/backend/src/bus/static_data.rs b/backend/src/bus/static_data.rs index f63d326..58f35e1 100644 --- a/backend/src/bus/static_data.rs +++ b/backend/src/bus/static_data.rs @@ -1,22 +1,13 @@ use super::api_key; +use geo::{LineString, MultiLineString}; use indicatif::{ProgressBar, ProgressStyle}; +use polyline::decode_polyline; use rayon::prelude::*; use regex::Regex; use serde::{Deserialize, Deserializer, Serialize}; use sqlx::{PgPool, QueryBuilder}; +use wkt::ToWkt; -// pub async fn should_update(pool: &PgPool) -> bool { -// let count = sqlx::query!("SELECT COUNT(*) FROM bus_route_stops as count") -// .fetch_one(pool) -// .await -// .unwrap() -// .count -// .unwrap(); -// // this is the correct route stop count -// count != 24690 -// } - -// id, long_name, short_name, color, route_type #[derive(Serialize)] pub struct Route { pub id: String, @@ -26,11 +17,13 @@ pub struct Route { pub shuttle: bool, } -// id, name, direction, lat, lon -struct Stop(i32, String, String, f32, f32); - -// route id, stop id, sequence -// struct RouteStop(String, i32, i32, i32); +struct Stop { + id: i32, + name: String, + direction: String, + lat: f32, + lon: f32, +} struct RouteStop { route_id: String, @@ -38,6 +31,7 @@ struct RouteStop { stop_sequence: i32, headsign: String, direction: i32, + geom: String, } // could hypothetically use transactions to prevent conflicts @@ -57,7 +51,6 @@ pub async fn stops_and_routes(pool: &PgPool) { .unwrap(), ); - // TODO: dont convert to tuple and just use struct for mut route in all_routes.into_iter() { // get the stops for the route let r_stops: RouteStops = RouteStops::get(&route.id).await; @@ -92,7 +85,13 @@ pub async fn stops_and_routes(pool: &PgPool) { .references .stops .into_par_iter() - .map(|s| Stop(s.code, s.name, s.direction, s.lat, s.lon)) + .map(|s| Stop { + id: s.code, + name: s.name, + direction: s.direction, + lat: s.lat, + lon: s.lon, + }) .collect::>(); // let s_names = stops_n.iter().map(|s| s.1.clone()).collect::>(); // println!("{:?}", s_names); @@ -104,6 +103,13 @@ pub async fn stops_and_routes(pool: &PgPool) { .par_iter() .map(|rs| { let route_id = &route.id; + // Combine all the polylines into one MultiLineString + let route_geom = MultiLineString::new( + rs.polylines + .iter() + .map(|p| p.points.clone()) + .collect::>(), + ); rs.stop_ids .par_iter() @@ -114,6 +120,7 @@ pub async fn stops_and_routes(pool: &PgPool) { stop_sequence: sequence as i32, headsign: rs.name.name.clone(), direction: rs.id, + geom: route_geom.to_wkt().to_string(), }) .collect::>() }) @@ -125,13 +132,12 @@ pub async fn stops_and_routes(pool: &PgPool) { } // remove duplicates - stops.sort_by(|a, b| a.0.cmp(&b.0)); - stops.dedup_by(|a, b| a.0 == b.0); + stops.sort_by(|a, b| a.id.cmp(&b.id)); + stops.dedup_by(|a, b| a.id == b.id); pb.finish_with_message("Finished parsing bus data"); // insert routes into db - let mut query_builder = QueryBuilder::new("INSERT INTO bus_routes (id, long_name, short_name, color, shuttle)"); query_builder.push_values(routes, |mut b, route| { @@ -151,11 +157,11 @@ pub async fn stops_and_routes(pool: &PgPool) { let mut query_builder = QueryBuilder::new("INSERT INTO bus_stops (id, name, direction, lat, lon)"); query_builder.push_values(chunk, |mut b, route| { - b.push_bind(route.0) - .push_bind(route.1.clone()) - .push_bind(route.2.clone()) - .push_bind(route.3) - .push_bind(route.4); + b.push_bind(route.id) + .push_bind(&route.name) + .push_bind(&route.direction) + .push_bind(route.lat) + .push_bind(route.lon); }); query_builder.push("ON CONFLICT DO NOTHING"); let query = query_builder.build(); @@ -164,14 +170,15 @@ pub async fn stops_and_routes(pool: &PgPool) { for chunk in route_stops.chunks(chunk_size) { let mut query_builder = QueryBuilder::new( - "INSERT INTO bus_route_stops (route_id, stop_id, stop_sequence, headsign, direction)", + "INSERT INTO bus_route_stops (route_id, stop_id, stop_sequence, headsign, direction, geom)", ); query_builder.push_values(chunk, |mut b, route| { b.push_bind(&route.route_id) .push_bind(route.stop_id) .push_bind(route.stop_sequence) .push_bind(&route.headsign) - .push_bind(route.direction); + .push_bind(route.direction) + .push_bind(&route.geom); }); query_builder.push("ON CONFLICT DO NOTHING"); let query = query_builder.build(); @@ -186,7 +193,7 @@ pub async fn stops_and_routes(pool: &PgPool) { #[derive(Deserialize, Clone, Debug)] pub struct AgencyRoute { pub color: String, - pub description: String, + // pub description: String, pub id: String, #[serde(rename = "longName")] pub long_name: String, @@ -254,7 +261,6 @@ fn de_get_id<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { - //TODO: remove unwraps let ids = Vec::::deserialize(deserializer)?; Ok(ids .into_iter() @@ -267,7 +273,6 @@ where } // fix stop capitalization by capitalizing only the first letter of each word -// could probably use regex for this fn de_stop_name<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -308,6 +313,7 @@ pub struct StopGroup { name: StopName, #[serde(rename = "stopIds", deserialize_with = "de_get_id")] stop_ids: Vec, + polylines: Vec, } #[derive(Deserialize, Clone, Debug)] @@ -316,6 +322,21 @@ pub struct StopName { name: String, } +fn de_polyline<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let polyline = String::deserialize(deserializer)?; + Ok(decode_polyline(&polyline, 5).map_err(serde::de::Error::custom)?) +} + +#[derive(Deserialize, Clone, Debug)] +pub struct PolyLine { + // length: i32, + #[serde(deserialize_with = "de_polyline")] + points: LineString, +} + #[derive(Deserialize, Clone, Debug)] pub struct References { stops: Vec, @@ -349,18 +370,13 @@ impl RouteStops { "https://bustime.mta.info/api/where/stops-for-route/{}.json", route_id )) - .query(&[ - ("key", api_key()), - ("version", "2"), - ("includePolyliines", "false"), - ]) + .query(&[("key", api_key()), ("version", "2")]) .send() .await .unwrap() .json::() .await .unwrap(); - // dbg!(&route_stops["data"].as_object().unwrap()["entry"]); serde_json::from_value(route_stops["data"].to_owned()).unwrap() } diff --git a/backend/src/main.rs b/backend/src/main.rs index 4bfc6ff..24eeb4d 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -18,14 +18,6 @@ pub mod feed { const VERSION: &str = env!("CARGO_PKG_VERSION"); -// fn stop_list(pool: &PgPool) -> Vec { -// let stops = sqlx::query!("select id from stops") -// .fetch_all(pool) -// .await -// .unwrap(); -// stops.iter().map(|s| s.id.clone()).collect() -// } - #[tokio::main] async fn main() { tracing_subscriber::registry() diff --git a/backend/src/routes/bus/routes.rs b/backend/src/routes/bus/routes.rs index 9aaaf0c..62b0f45 100644 --- a/backend/src/routes/bus/routes.rs +++ b/backend/src/routes/bus/routes.rs @@ -1,10 +1,37 @@ -use crate::{bus::static_data::Route, routes::errors::ServerError}; -use axum::{extract::State, response::IntoResponse, Json}; +use crate::routes::errors::ServerError; +use axum::{ + extract::{Query, State}, + response::IntoResponse, + Json, +}; use http::HeaderMap; +use serde::{Deserialize, Serialize}; use sqlx::PgPool; -pub async fn get(State(pool): State) -> Result { - let routes = sqlx::query_as!(Route, "SELECT * FROM bus_routes") +#[derive(Serialize)] +pub struct Route { + pub id: String, + pub long_name: String, + pub short_name: String, + pub color: String, + pub shuttle: bool, + // pub geom: Option, +} + +fn no_geom() -> bool { + false +} +#[derive(Deserialize)] +pub struct Parameters { + #[serde(default = "no_geom")] + geom: bool, +} + +pub async fn get( + State(pool): State, + params: Query, +) -> Result { + let routes = sqlx::query_as!(Route, r#"SELECT * FROM bus_routes"#) .fetch_all(&pool) .await?; diff --git a/backend/src/static_data.rs b/backend/src/static_data.rs index 5a2af22..9b5b38b 100644 --- a/backend/src/static_data.rs +++ b/backend/src/static_data.rs @@ -4,18 +4,6 @@ use serde::{Deserialize, Deserializer}; use sqlx::{PgPool, QueryBuilder}; use std::io::Cursor; -// pub async fn should_update(pool: &PgPool) -> bool { -// let stop_count = sqlx::query!("SELECT COUNT(*) FROM stops as count") -// .fetch_one(pool) -// .await -// .unwrap() -// .count -// .unwrap(); - -// // the amount of stops that should be in the database -// stop_count != 496 -// } - // convert strings to numbers pub fn de_str_to_i16<'de, D>(deserializer: D) -> Result where @@ -69,8 +57,8 @@ where #[derive(Deserialize, Clone)] pub struct Station { - #[serde(deserialize_with = "de_remove_prefix", rename = "routeId")] - pub route_id: String, + // #[serde(deserialize_with = "de_remove_prefix", rename = "routeId")] + // pub route_id: String, #[serde(deserialize_with = "de_str_to_i16", rename = "stopSequence")] pub stop_sequence: i16, #[serde(deserialize_with = "de_remove_prefix", rename = "stopId")] @@ -107,7 +95,7 @@ pub struct NearbyGroup { pub struct NearbyStop { #[serde(deserialize_with = "de_remove_prefix")] pub id: String, - pub name: String, + // pub name: String, // not used currently pub lat: f32, pub lon: f32,