From dc99f9d3c99b8f39b94310bd253acb7bea54cc40 Mon Sep 17 00:00:00 2001 From: dwasint <82520990+dwasint@users.noreply.github.com> Date: Sat, 11 Mar 2023 18:03:35 -0400 Subject: [PATCH] Pulls latest upstream (#10) * Updates the byond testing version to tgstation ver (#66) * runs cargo fmt (#63) * Sets the debug and test linux build to use all features (#67) Problem: PRs and all features aren't properly running created unit tests. Nor are they actually being fully compiled (only checked) on Linux. Solution: Only have the release builds that are distributed as artifacts run with the default features. This way, tests can cover all features. * Base64 encoding (#65) * Adds base64 encoding * Adds tests * Commented out import * Fixes the naming of variables * ...of course it was a typo * Update Cargo.toml Co-authored-by: William Wallace * Clippy tweaks (#62) * this `else { if .. }` block can be collapsed * question mark operator is useless here * this call to `from_str_radix` can be replaced with a call to `str::parse` * equality checks against true are unnecessary * Revert "question mark operator is useless here" This reverts commit 01272c520b056b0cc9f6439add85684205fea8f7. * Cargo update (#64) * updates cargo dependencies versions to latest * Fixes perlin noise generation to use an inclusive range * Update src/cellularnoise.rs Co-authored-by: William Wallace * Updates cargo.lock Co-authored-by: William Wallace * Basic version getter (#68) * Bump Version sto v0.4.8 * Setup cross compiling using the cross project (#70) * Make the url feature default (#71) Co-authored-by: Jared-Fogle <35135081+Jared-Fogle@users.noreply.github.com> * 0.4.9 * Runs cargo update (#72) most importantly git2, which made it error when trying to build on linux with the latest rust version * Stringify url_encode and decode input before sending it to Rust (#73) Co-authored-by: Jordan Brown * 0.4.10 * Add worley noise optional feature (#74) * worley_noise * a simple fix, forgot to ad dmsort as a necessary package * replaces .unwrap() with ? * forgot to save :cryingintoheavens: * IM SORRY I CANT USE ? IN CLOSURES * Completely reworks how the code works, massively optimizing it. Generation lost a tiny bit of it's fidelity but oh well, looks fantastic rn * one last change * tfw errors * makes the noise generate pretties noise * cargo fmt * Add TOML feature (#75) Adds rustg_read_toml_file, which takes a filepath and spits out the output after decoding (a list, probably). Uses the rust-toml lib * 0.5.0 Cargo updates * Adds TOTP generator to the hash feature (#76) * Adds TOTP generator to the hash feature * Updated TOTP based on requested changes, added a function that allow specification of a tolerance, also updated the hash.dm file to reflect the new functions * Remove debug print, convert offset output to be JSON, added a test * Added comments * Added some error handling * Improves error handling again * cargo fmt hash.rs * separate mod block for hash tests * Functions for more precise time measurement (#77) * fix linux ci by removing pkg-config requirement This isnt needed * Aho-Corasick string replacements to help clean up replaceText spam (#82) * Cleanups and additions for the Aho-Corasick replacement stuff (#83) * Fix clippy lints, Rustfmt, put both on CI, and update Cargo.lock (#85) Co-authored-by: Mothblocks <35135081+Jared-Fogle@users.noreply.github.com> * Adds Redis Pub/Sub integration (#80) dds the ability to connect to Redis, subscribe to messages and publish them as well. See here for example usage. The API, prefixed with rustg_redis_: connect(addr) - Connects to a Redis instance using the given address, for example redis://127.0.0.1/. Returns an empty string on success, returns the error otherwise. disconnect() - Closes the connection to Redis and stops the thread managing it. Call this before restarting or attempting to reconnect after an error. subscribe(channel) - Subscribes to a given channel and starts receiving messages from it. get_messages() - Returns all received messages as a JSON string, in the format of {"channel_1": ["msg1", "msg2", "msg3", ...], "channel_2": ["msg1", "msg2", "msg3", ...]}. Also includes errors, which appear on the channel "RUSTG_REDIS_ERROR_CHANNEL". publish(channel, message) - Publishes a message on the given channel. Remember to check the error channel every time you call get_messages(). If any occur, you need to call disconnect(), then connect() again, then resubscribe to desired channels. * fixes warning in redis (#88) * Fix clippy CI, format byond_fn (#89) * Adds alphabetical order tests for README.md, lib.rs and Cargo.toml (#84) Adds alphabetical order tests for README.md, lib.rs and Cargo.toml #84 Also renamed "non-default features" to "additional features" in Cargo.toml for consistency with readme updated the cargo.lock and ran rustfmt * Bump to 0.6.0 (#90) * Fixes redis dmsrc (#91) * Cleaner and saner http request parsing. (#93) * Add functions for seeking lines and getting line counts in functions (#95) dds rustg_file_get_line_count for getting the line count of a given filename, and rustg_file_seek_line for getting a specific line. These are useful as to not load the entire file into memory in DM, which is useful for very large files like dictionaries. * 0.7.0 (#96) * Adds a new type of noise: Discrete Batched Perlin-like Noise (DBP) (#99) * Updates WorleyNoise to be multi-threaded and faster (#102) Another noise algorithm updated in my streak, this time it's worleynoise, since i didn't know jack shit and i heavily abused Rc<> to acomplish my goals it was really shit. Now it is multi-threaded, blazing fast and really sexy lookin. NOTE: this update changes ABI of worley noise slightly. * Updates CellularNoise to be faster and multi-threaded (#101) Hello, I guess i'm on a streak. I reimplemented CAnoise to be multi-threaded and much faster as i removed a considerable amount of branches. No change to behaviour or ABI noted, it's just faster now. * toml2json now returns errors to byond (#98) Co-authored-by: ZeWaka * Updates cargo packages (#104) * 0.8.0 * Tiny README update * Small improvements for before 1.0 (#105) * 1.0.0 (#106) * Pallette Encoding Image Fix (#107) * Uploads rust_g.dm as an Actions Artifact (#108) * 1.0.1 * add note to README about not using the .so * Returns the TOML library to previous functionality (#112) * 1.0.2 * Clippy - unneeded returns (#114) * Add an a* pathfinder (#113) Returns the shortest path in a static node map. That is made for TGMC wich uses manually placed nodes for pathfinding. Benchmark : image That's the average number of path computed in one second, out of 30 runs with random nodes. Size of the node map is roughly 800 On average 32 times faster than tgmc a* implementation. Another possible comparison is with TG's JPS system, and according to the benchmark done here it's 7000 times faster (tgstation/tgstation#56780). Not exactly the same use cases though * Add rustg_toml_encode (#116) Add rustg_toml_encode * 1.1.0 * Fixes cellular noise not working for diff height and width values (#117) * Update README.md update readme with `pathfinder` feature and rust-analyzer note, re: #115 * Fix the `pathfinder` feature's loc in the README * Package debug symbols with rust-g (#119) * 515 Support (#121) * add a unix_timestamp extern (#122) Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> * 1.2.0 * Remove useless features from the image crate (#128) * lmao we don't need jpeg dependencies for image * update `noise` to remove the rest of the junk deps * small clippy fixes (cherry picked from commit 65cf48a0072df02fe422aeeef31c416ad8791a08) * Update rust.yml * adds all-features flag to linux and windows build * reverts actions to tg's current * Update rust.yml * Update rust.yml * Update rust.yml * Update rust.yml --------- Co-authored-by: ZeWaka Co-authored-by: William Wallace Co-authored-by: oranges Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> Co-authored-by: Jared-Fogle <35135081+Jared-Fogle@users.noreply.github.com> Co-authored-by: Mark Suckerberg <29362068+MarkSuckerberg@users.noreply.github.com> Co-authored-by: Gamer025 <33846895+Gamer025@users.noreply.github.com> Co-authored-by: Jordan Brown Co-authored-by: EdgeLordExe <42111655+EdgeLordExe@users.noreply.github.com> Co-authored-by: adamsong Co-authored-by: pali <6pali6@gmail.com> Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Co-authored-by: vuonojenmustaturska Co-authored-by: MCHSL <56649176+MCHSL@users.noreply.github.com> Co-authored-by: AnturK Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com> Co-authored-by: san7890 Co-authored-by: BraveMole Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com> --- .github/workflows/rust.yml | 4 +- .vscode/settings.json | 2 +- Cargo.lock | 2018 ++++++++++++---------- Cargo.toml | 97 +- Cross.toml | 11 + LICENSE | 2 +- README.md | 23 +- build.rs | 9 +- dmsrc/acreplace.dm | 42 + dmsrc/cellularnoise.dm | 2 +- dmsrc/dbpnoise.dm | 16 + dmsrc/dmi.dm | 7 +- dmsrc/file.dm | 10 +- dmsrc/git.dm | 5 +- dmsrc/hash.dm | 7 +- dmsrc/http.dm | 6 +- dmsrc/json.dm | 2 +- dmsrc/log.dm | 4 +- dmsrc/main.dm | 10 + dmsrc/noise.dm | 2 +- dmsrc/pathfinder.dm | 32 + dmsrc/redis-pubsub.dm | 7 + dmsrc/sql.dm | 12 +- dmsrc/time.dm | 6 + dmsrc/toml.dm | 17 + dmsrc/unzip.dm | 4 +- dmsrc/url.dm | 4 +- dmsrc/worleynoise.dm | 16 + docker/Dockerfile.i686-unknown-linux-gnu | 5 + scripts/prepare_binaries.sh | 12 +- src/acreplace.rs | 94 + src/byond.rs | 25 +- src/cellularnoise.rs | 132 +- src/dbpnoise.rs | 36 + src/dmi.rs | 66 +- src/error.rs | 29 +- src/file.rs | 41 +- src/git.rs | 8 +- src/hash.rs | 132 +- src/http.rs | 24 +- src/json.rs | 4 +- src/lib.rs | 24 +- src/log.rs | 28 +- src/noise_gen.rs | 8 +- src/pathfinder.rs | 281 +++ src/redis_pubsub.rs | 179 ++ src/sql.rs | 28 +- src/time.rs | 49 + src/toml.rs | 42 + src/unzip.rs | 25 +- src/url.rs | 8 +- src/worleynoise.rs | 255 +++ tests/abc-tests.rs | 67 + tests/dm-tests.rs | 12 + tests/dm/hash.dme | 23 + tests/dm/toml.dme | 29 + tests/rsc/ai_nodes_info.json | 1 + 57 files changed, 2846 insertions(+), 1198 deletions(-) create mode 100644 Cross.toml create mode 100644 dmsrc/acreplace.dm create mode 100644 dmsrc/dbpnoise.dm create mode 100644 dmsrc/pathfinder.dm create mode 100644 dmsrc/redis-pubsub.dm create mode 100644 dmsrc/time.dm create mode 100644 dmsrc/toml.dm create mode 100644 dmsrc/worleynoise.dm create mode 100644 docker/Dockerfile.i686-unknown-linux-gnu create mode 100644 src/acreplace.rs create mode 100644 src/dbpnoise.rs create mode 100644 src/pathfinder.rs create mode 100644 src/redis_pubsub.rs create mode 100644 src/time.rs create mode 100644 src/toml.rs create mode 100644 src/worleynoise.rs create mode 100644 tests/abc-tests.rs create mode 100644 tests/dm/hash.dme create mode 100644 tests/dm/toml.dme create mode 100644 tests/rsc/ai_nodes_info.json diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dd103d34..a5a818f1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -38,7 +38,7 @@ jobs: name: rust_g.dll path: target/i686-pc-windows-msvc/release/rust_g.dll build-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: BYOND_MAJOR: 513 BYOND_MINOR: 1521 @@ -48,7 +48,7 @@ jobs: - run: | sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install g++-multilib zlib1g-dev:i386 libssl-dev:i386 pkg-config:i386 + sudo apt-get install g++-multilib zlib1g-dev:i386 pkg-config libssl-dev:i386 libssl-dev libssl1.1:i386 ./scripts/install_byond.sh - uses: actions-rs/toolchain@v1 with: diff --git a/.vscode/settings.json b/.vscode/settings.json index 36268ab1..111ee693 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "rust-analyzer.cargo.target": "i686-pc-windows-gnu" + "rust-analyzer.cargo.target": "i686-pc-windows-msvc" } diff --git a/Cargo.lock b/Cargo.lock index 3fd65723..9fee1ee0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adler" version = "1.0.2" @@ -13,105 +15,127 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] -name = "ahash" -version = "0.3.8" +name = "aes" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ - "const-random", + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", ] [[package]] name = "ahash" -version = "0.4.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.7", + "once_cell", + "version_check", +] [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] [[package]] name = "arrayvec" -version = "0.5.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] -name = "autocfg" -version = "1.0.1" +name = "async-trait" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "base-x" -version = "0.2.8" +name = "autocfg" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] -name = "base64" -version = "0.13.0" +name = "base64ct" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" [[package]] name = "bigdecimal" -version = "0.1.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244" +checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744" dependencies = [ "num-bigint", "num-integer", - "num-traits 0.2.14", - "serde", + "num-traits", ] [[package]] -name = "bitflags" -version = "1.2.1" +name = "bindgen" +version = "0.59.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] [[package]] -name = "block-buffer" -version = "0.7.3" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "block-buffer" -version = "0.9.0" +name = "bitvec" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" dependencies = [ - "generic-array 0.14.4", + "funty", + "radium", + "tap", + "wyz", ] [[package]] -name = "block-padding" -version = "0.1.5" +name = "block-buffer" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -122,45 +146,33 @@ checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" [[package]] name = "bumpalo" -version = "3.6.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "bytemuck" -version = "1.5.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" +checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a" [[package]] name = "byteorder" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" - -[[package]] -name = "bytes" -version = "0.5.6" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" [[package]] name = "bzip2" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" dependencies = [ "bzip2-sys", "libc", @@ -168,9 +180,9 @@ dependencies = [ [[package]] name = "bzip2-sys" -version = "0.1.10+1.0.8" +version = "0.1.11+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fa3d1ac1ca21c5c4e36a97f3c3eb25084576f6fc47bf0139c1123434216c6c" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" dependencies = [ "cc", "libc", @@ -179,18 +191,21 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.67" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] [[package]] -name = "cfg-if" -version = "0.1.10" +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" @@ -206,19 +221,38 @@ checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ "libc", "num-integer", - "num-traits 0.2.14", - "serde", - "time 0.1.43", - "winapi 0.3.9", + "num-traits", + "time 0.1.44", + "winapi", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "cipher" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "bitflags", + "generic-array", +] + +[[package]] +name = "clang-sys" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +dependencies = [ + "cc", ] [[package]] @@ -227,6 +261,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "combine" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "const-random" version = "0.1.13" @@ -243,23 +287,23 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.7", "lazy_static", "proc-macro-hack", "tiny-keccak", ] [[package]] -name = "const_fn" -version = "0.4.5" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -267,68 +311,95 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] -name = "cpuid-bool" -version = "0.1.2" +name = "cpufeatures" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.3" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" dependencies = [ - "cfg-if 1.0.0", + "autocfg", + "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" -version = "0.8.3" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "lazy_static", + "cfg-if", + "once_cell", ] [[package]] @@ -337,35 +408,48 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dashmap" -version = "3.11.10" +version = "5.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5" +checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" dependencies = [ - "ahash 0.3.8", - "cfg-if 0.1.10", - "num_cpus", + "cfg-if", + "hashbrown", + "lock_api", + "parking_lot_core", ] [[package]] -name = "deflate" -version = "0.7.20" +name = "dbpnoise" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" +checksum = "b2a92e2d3660e5513454071018433d22bbdfc8a79b9bcf1b6399aa72e96b8586" dependencies = [ - "adler32", - "byteorder", + "lerp", + "rand 0.8.5", + "rand_pcg", + "rand_seeder", + "rayon", ] [[package]] name = "deflate" -version = "0.8.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" dependencies = [ "adler32", - "byteorder", ] [[package]] @@ -381,81 +465,73 @@ dependencies = [ [[package]] name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.9.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "generic-array 0.14.4", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] -name = "discard" -version = "1.0.4" +name = "dtoa" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] name = "either" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] -name = "enum_primitive" -version = "0.1.1" +name = "fastrand" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ - "num-traits 0.1.43", + "instant", ] [[package]] -name = "fake-simd" -version = "0.1.2" +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.14" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if 0.1.10", "crc32fast", - "libc", "libz-sys", - "miniz_oxide 0.3.7", + "miniz_oxide", ] [[package]] name = "flume" -version = "0.9.2" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bebadab126f8120d410b677ed95eee4ba6eb7c6dd8e34a5ec88a08050e26132" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" dependencies = [ "futures-core", "futures-sink", "nanorand", - "spinning_top", + "pin-project", + "spin 0.9.4", ] [[package]] @@ -490,104 +566,128 @@ dependencies = [ ] [[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "frunk" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +checksum = "0cd67cf7d54b7e72d0ea76f3985c3747d74aee43e0218ad993b7903ba7a5395e" dependencies = [ - "bitflags", - "fuchsia-zircon-sys", + "frunk_core", + "frunk_derives", + "frunk_proc_macros", ] [[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "frunk_core" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +checksum = "1246cf43ec80bf8b2505b5c360b8fb999c97dabd17dbb604d85558d5cbc25482" [[package]] -name = "futures-channel" -version = "0.3.13" +name = "frunk_derives" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +checksum = "3dbc4f084ec5a3f031d24ccedeb87ab2c3189a2f33b8d070889073837d5ea09e" dependencies = [ - "futures-core", + "frunk_proc_macro_helpers", + "quote", + "syn", ] [[package]] -name = "futures-core" -version = "0.3.13" +name = "frunk_proc_macro_helpers" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" +checksum = "99f11257f106c6753f5ffcb8e601fb39c390a088017aaa55b70c526bff15f63e" +dependencies = [ + "frunk_core", + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "futures-io" -version = "0.3.13" +name = "frunk_proc_macros" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" +checksum = "a078bd8459eccbb85e0b007b8f756585762a72a9efc53f359b371c3b6351dbcc" +dependencies = [ + "frunk_core", + "frunk_proc_macros_impl", + "proc-macro-hack", +] [[package]] -name = "futures-macro" -version = "0.3.13" +name = "frunk_proc_macros_impl" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" +checksum = "6ffba99f0fa4f57e42f57388fbb9a0ca863bc2b4261f3c5570fed579d5df6c32" dependencies = [ + "frunk_core", + "frunk_proc_macro_helpers", "proc-macro-hack", - "proc-macro2", "quote", "syn", ] +[[package]] +name = "funty" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + [[package]] name = "futures-sink" -version = "0.3.13" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.13" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.13" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-core", "futures-io", - "futures-macro", "futures-task", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] [[package]] name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -599,49 +699,29 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] -[[package]] -name = "gif" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e41945ba23db3bf51b24756d73d81acb4f28d85c3dccc32c6fae904438c25f" -dependencies = [ - "color_quant", - "lzw", -] - -[[package]] -name = "gif" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "git2" -version = "0.13.17" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d250f5f82326884bd39c2853577e70a121775db76818ffa452ed1e80de12986" +checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" dependencies = [ "bitflags", "libc", @@ -650,13 +730,19 @@ dependencies = [ "url", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "h2" -version = "0.2.7" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "futures-core", "futures-sink", @@ -667,23 +753,22 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "tracing-futures", ] [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.4.7", + "ahash", ] [[package]] name = "hermit-abi" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] @@ -694,46 +779,56 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" -version = "0.2.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes 1.0.1", + "bytes", "fnv", - "itoa", + "itoa 1.0.2", ] [[package]] name = "http-body" -version = "0.3.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 0.5.6", + "bytes", "http", + "pin-project-lite", ] [[package]] name = "httparse" -version = "1.3.5" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.13.10" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -742,8 +837,8 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", - "pin-project", + "itoa 1.0.2", + "pin-project-lite", "socket2", "tokio", "tower-service", @@ -753,25 +848,22 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "bytes 0.5.6", - "futures-util", + "http", "hyper", - "log", "rustls", "tokio", "tokio-rustls", - "webpki", ] [[package]] name = "idna" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ "matches", "unicode-bidi", @@ -780,64 +872,51 @@ dependencies = [ [[package]] name = "image" -version = "0.18.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545f000e8aa4e569e93f49c446987133452e0091c2494ac3efd3606aa3d309f2" +checksum = "7e30ca2ecf7666107ff827a8e481de6a132a9b687ed3bb20bb1c144a36c00964" dependencies = [ + "bytemuck", "byteorder", - "enum_primitive", - "gif 0.9.2", - "jpeg-decoder", - "num-iter", - "num-rational 0.1.42", - "num-traits 0.1.43", - "png 0.11.0", - "scoped_threadpool", + "color_quant", + "num-rational", + "num-traits", + "png", ] [[package]] -name = "image" -version = "0.23.14" +name = "indexmap" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "gif 0.11.1", - "jpeg-decoder", - "num-iter", - "num-rational 0.3.2", - "num-traits 0.2.14", - "png 0.16.8", - "scoped_threadpool", - "tiff", + "autocfg", + "hashbrown", ] [[package]] -name = "indexmap" -version = "1.6.2" +name = "instant" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "autocfg", - "hashbrown", + "cfg-if", ] [[package]] -name = "inflate" -version = "0.3.4" +name = "integer-sqrt" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f9f47468e9a76a6452271efadc88fe865a82be91fe75e6c0c57b87ccea59d4" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" dependencies = [ - "adler32", + "num-traits", ] [[package]] name = "io-enum" -version = "0.2.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94534fd32a986dd34d97ddefe5198630d5ed99efd4e9b9b9ed4359e6b23a9cf7" +checksum = "03e3306b0f260aad2872563eb0d5d1a59f2420fad270a661dce59a01e92d806b" dependencies = [ "autocfg", "derive_utils", @@ -846,103 +925,155 @@ dependencies = [ ] [[package]] -name = "iovec" -version = "0.1.4" +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + +[[package]] +name = "itertools" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ - "libc", + "either", ] [[package]] -name = "ipnet" -version = "2.3.0" +name = "itoa" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "0.4.7" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ "libc", ] [[package]] -name = "jpeg-decoder" -version = "0.1.22" +name = "js-sys" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ - "rayon", + "wasm-bindgen", ] [[package]] -name = "js-sys" -version = "0.3.48" +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lerp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b19ac50d419bff1a024a8eb8034bfbee6c1cf8fa3472502f6bd3def327b09e4c" dependencies = [ - "wasm-bindgen", + "num-traits", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "lexical" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "lexical-core", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "lexical-core" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] [[package]] -name = "lexical" -version = "5.2.1" +name = "lexical-parse-float" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a11b9b772d42a9cf7ff6742d4695054070432742b19cecea07e7c4eca8173d25" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" dependencies = [ - "cfg-if 1.0.0", - "lexical-core", + "lexical-parse-integer", + "lexical-util", + "static_assertions", ] [[package]] -name = "lexical-core" -version = "0.7.5" +name = "lexical-parse-integer" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" dependencies = [ - "arrayvec", - "bitflags", - "cfg-if 1.0.0", - "ryu", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-util" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lexical-write-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] + +[[package]] +name = "lexical-write-integer" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", "static_assertions", ] [[package]] name = "libc" -version = "0.2.88" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "libgit2-sys" -version = "0.12.18+1.1.0" +version = "0.13.4+1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da6a42da88fc37ee1ecda212ffa254c25713532980005d5f7c0b0fbe7e6e885" +checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" dependencies = [ "cc", "libc", @@ -950,11 +1081,21 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libz-sys" -version = "1.1.2" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -964,65 +1105,58 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "lru" -version = "0.6.5" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f374d42cdfc1d7dbf3d3dec28afab2eb97ffbf43a3234d795b5986dbf4b90ba" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" dependencies = [ "hashbrown", ] -[[package]] -name = "lzw" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" - [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "md-5" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +checksum = "658646b21e0b72f7866c7038ab086d3d5e1cd6271f060fd37defb241949d0582" dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug 0.3.0", + "digest", ] [[package]] name = "memchr" -version = "2.3.4" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -1034,79 +1168,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] -name = "mime_guess" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "miniz_oxide" -version = "0.3.7" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", - "autocfg", ] [[package]] name = "mio" -version = "0.6.23" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", "libc", "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", ] [[package]] name = "mysql" -version = "20.1.0" +version = "22.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a8660184af84975ac1639aa692a539c37739cec8a22a414de3db9cb573c1aa" +checksum = "b9d8136c78f78cda5c1a4eee4ce555281b71e3e6db715817bc50e186e623b36f" dependencies = [ "bufstream", + "bytes", + "crossbeam", + "flate2", "io-enum", "libc", "lru", "mysql_common", "named_pipe", "native-tls", - "nix", + "once_cell", "pem", "percent-encoding", "serde", @@ -1118,30 +1222,38 @@ dependencies = [ [[package]] name = "mysql_common" -version = "0.24.1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de63b87a5f24c5db252418a6f04abb2f62823bd838dc9b1d7fdb8ae972ef76cf" +checksum = "4140827f2d12750de1e8755442577e4292a835f26ff2f659f0a380d1d71020b0" dependencies = [ - "base64 0.12.3", + "base64", "bigdecimal", + "bindgen", "bitflags", + "bitvec", "byteorder", - "bytes 0.5.6", - "chrono", + "bytes", + "cc", + "cmake", + "crc32fast", "flate2", + "frunk", "lazy_static", "lexical", "num-bigint", - "num-traits 0.2.14", - "rand 0.7.3", + "num-traits", + "rand 0.8.5", "regex", "rust_decimal", + "saturating", "serde", "serde_json", - "sha1", - "sha2 0.8.2", - "time 0.2.25", - "twox-hash", + "sha-1", + "sha2", + "smallvec", + "subprocess", + "thiserror", + "time 0.3.11", "uuid", ] @@ -1151,23 +1263,23 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad9c443cce91fc3e12f017290db75dde490d685cdaaf508d7159d7cf41f0eb2b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] name = "nanorand" -version = "0.4.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dacfd1e4084e3220e57fbd5a7030deb248b46051d4ac2989e1d4a890e393d7c5" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ - "getrandom 0.2.2", + "getrandom 0.2.7", ] [[package]] name = "native-tls" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", @@ -1182,130 +1294,126 @@ dependencies = [ ] [[package]] -name = "net2" -version = "0.2.37" +name = "noise" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "9ba869e17168793186c10ca82c7079a4ffdeac4f1a7d9e755b9491c028180e40" dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", + "num-traits", + "rand 0.7.3", + "rand_xorshift", ] [[package]] -name = "nix" -version = "0.19.1" +name = "nom" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", + "memchr", + "minimal-lexical", ] [[package]] -name = "noise" -version = "0.6.0" +name = "num" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "337525774dd8a197b613a01ea88058ef0ed023e5ed1e4b7e93de478e1f2bf770" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" dependencies = [ - "image 0.18.0", - "rand 0.5.6", + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] name = "num-bigint" -version = "0.2.6" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits", ] [[package]] -name = "num-integer" -version = "0.1.44" +name = "num-complex" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ - "autocfg", - "num-traits 0.2.14", + "num-traits", ] [[package]] -name = "num-iter" -version = "0.1.42" +name = "num-integer" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", - "num-integer", - "num-traits 0.2.14", + "num-traits", ] [[package]] -name = "num-rational" -version = "0.1.42" +name = "num-iter" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ + "autocfg", "num-integer", - "num-traits 0.2.14", + "num-traits", ] [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", + "num-bigint", "num-integer", - "num-traits 0.2.14", -] - -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.14", + "num-traits", ] [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", ] [[package]] -name = "once_cell" -version = "1.7.2" +name = "num_threads" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] [[package]] -name = "opaque-debug" -version = "0.2.3" +name = "once_cell" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "opaque-debug" @@ -1315,29 +1423,41 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.32" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", - "lazy_static", "libc", + "once_cell", + "openssl-macros", "openssl-sys", ] +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.60" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg", "cc", @@ -1346,15 +1466,70 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "password-hash" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +dependencies = [ + "base64ct", + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "pathfinding" +version = "3.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84da3eab6c7638931f4876ebb03455be74db8eab1e344cd5a90daba8b3ad2f22" +dependencies = [ + "fixedbitset", + "indexmap", + "integer-sqrt", + "itertools", + "num-traits", + "rustc-hash", + "thiserror", +] + +[[package]] +name = "pbkdf2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pem" -version = "0.8.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "base64 0.13.0", - "once_cell", - "regex", + "base64", ] [[package]] @@ -1365,18 +1540,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.5" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63" +checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.5" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" +checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" dependencies = [ "proc-macro2", "quote", @@ -1385,15 +1560,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - -[[package]] -name = "pin-project-lite" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1403,39 +1572,27 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.19" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "png" -version = "0.11.0" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b0cabbbd20c2d7f06dbf015e06aad59b6ca3d9ed14848783e98af9aaf19925" -dependencies = [ - "bitflags", - "deflate 0.7.20", - "inflate", - "num-iter", -] - -[[package]] -name = "png" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" dependencies = [ "bitflags", "crc32fast", - "deflate 0.8.6", - "miniz_oxide 0.3.7", + "deflate", + "miniz_oxide", ] [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro-hack" @@ -1443,42 +1600,29 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.5.6" +name = "radium" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "winapi 0.3.9", -] +checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" [[package]] name = "rand" @@ -1490,19 +1634,18 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", ] [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", + "rand_chacha 0.3.1", + "rand_core 0.6.3", ] [[package]] @@ -1517,70 +1660,73 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.2", + "rand_core 0.6.3", ] [[package]] name = "rand_core" -version = "0.3.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "rand_core 0.4.2", + "getrandom 0.1.16", ] [[package]] name = "rand_core" -version = "0.4.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom 0.2.7", +] [[package]] -name = "rand_core" -version = "0.5.1" +name = "rand_hc" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "getrandom 0.1.16", + "rand_core 0.5.1", ] [[package]] -name = "rand_core" -version = "0.6.2" +name = "rand_pcg" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" dependencies = [ - "getrandom 0.2.2", + "rand_core 0.6.3", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "rand_seeder" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb" dependencies = [ - "rand_core 0.5.1", + "rand_core 0.6.3", ] [[package]] -name = "rand_hc" -version = "0.3.0" +name = "rand_xorshift" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" dependencies = [ - "rand_core 0.6.2", + "rand_core 0.5.1", ] [[package]] name = "rayon" -version = "1.5.0" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg", "crossbeam-deque", @@ -1590,43 +1736,56 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] +[[package]] +name = "redis" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80b5f38d7f5a020856a0e16e40a9cfabf88ae8f0e4c2dcd8a3114c1e470852" +dependencies = [ + "async-trait", + "combine", + "dtoa", + "itoa 0.4.8", + "percent-encoding", + "sha1 0.6.1", + "url", +] + [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "534cfe58d6a18cc17120fbf4635d53d14691c1fe4d951064df9bd326178d7d5a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.4.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.22" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remove_dir_all" @@ -1634,20 +1793,21 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] name = "reqwest" -version = "0.10.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ - "base64 0.13.0", - "bytes 0.5.6", + "base64", + "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", @@ -1657,14 +1817,16 @@ dependencies = [ "lazy_static", "log", "mime", - "mime_guess", "percent-encoding", - "pin-project-lite 0.2.6", + "pin-project-lite", "rustls", + "rustls-pemfile", "serde", + "serde_json", "serde_urlencoded", "tokio", "tokio-rustls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1682,37 +1844,46 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", - "winapi 0.3.9", + "winapi", ] [[package]] name = "rust-g" -version = "0.4.7" +version = "1.2.0" dependencies = [ + "aho-corasick", + "base64", "chrono", "const-random", "dashmap", + "dbpnoise", "flume", "git2", "hex", - "image 0.23.14", + "image", "lazy_static", "md-5", "mysql", "noise", + "num", "once_cell", + "pathfinding", "percent-encoding", - "png 0.16.8", - "rand 0.7.3", + "png", + "rand 0.8.5", + "rayon", + "redis", + "regex", "reqwest", "serde", "serde_json", "sha-1", - "sha2 0.9.3", + "sha2", "thiserror", + "toml", "twox-hash", "url", "zip", @@ -1720,59 +1891,64 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.10.3" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7f5b8840fb1f83869a3e1dfd06d93db79ea05311ac5b42b8337d3371caa4f1" +checksum = "34a3bb58e85333f1ab191bf979104b586ebd77475bc6681882825f4532dfe87c" dependencies = [ "arrayvec", - "num-traits 0.2.14", + "num-traits", "serde", ] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustls" -version = "0.18.1" +version = "0.20.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" dependencies = [ - "base64 0.12.3", "log", "ring", "sct", "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +dependencies = [ + "base64", +] + [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "saturating" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi 0.3.9", + "windows-sys", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" version = "1.1.0" @@ -1781,9 +1957,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "sct" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", "untrusted", @@ -1791,9 +1967,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.1.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -1804,43 +1980,28 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.1.1" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" -version = "1.0.124" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" +checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.124" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" +checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" dependencies = [ "proc-macro2", "quote", @@ -1849,86 +2010,104 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ - "itoa", + "itoa 1.0.2", "ryu", "serde", ] [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.2", "ryu", "serde", ] [[package]] name = "sha-1" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpuid-bool", - "digest 0.9.0", - "opaque-debug 0.3.0", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] name = "sha1" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] [[package]] -name = "sha2" -version = "0.8.2" +name = "sha1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "cfg-if", + "cpufeatures", + "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + [[package]] name = "sha2" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpuid-bool", - "digest 0.9.0", - "opaque-debug 0.3.0", + "cfg-if", + "cpufeatures", + "digest", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "slab" -version = "0.4.2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.3.19" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ - "cfg-if 1.0.0", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1938,23 +2117,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "spinning_top" -version = "0.2.2" +name = "spin" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e529d73e80d64b5f2631f9035113347c578a1c9c7774b83a2b880788459ab36" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" dependencies = [ "lock_api", ] -[[package]] -name = "standback" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2beb4d1860a61f571530b3f855a1b538d0200f7871c63331ecd6f17b1f014f8" -dependencies = [ - "version_check", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -1962,166 +2132,100 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "stdweb" -version = "0.4.20" +name = "subprocess" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" dependencies = [ - "discard", - "rustc_version", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", + "libc", + "winapi", ] [[package]] -name = "stdweb-derive" -version = "0.5.3" +name = "subtle" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] -name = "stdweb-internal-macros" -version = "0.2.9" +name = "syn" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ - "base-x", "proc-macro2", "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", + "unicode-ident", ] [[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - -[[package]] -name = "syn" -version = "1.0.62" +name = "tap" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "fastrand", "libc", - "rand 0.8.3", "redox_syscall", "remove_dir_all", - "winapi 0.3.9", + "winapi", ] [[package]] name = "thiserror" -version = "1.0.24" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.24" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tiff" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" -dependencies = [ - "jpeg-decoder", - "miniz_oxide 0.4.4", - "weezl", -] - [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "winapi 0.3.9", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", ] [[package]] name = "time" -version = "0.2.25" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1195b046942c221454c2539395f85413b33383a067449d78aab2b7b052a142f7" +checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217" dependencies = [ - "const_fn", + "itoa 1.0.2", "libc", - "standback", - "stdweb", + "num_threads", "time-macros", - "version_check", - "winapi 0.3.9", ] [[package]] name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" -version = "0.1.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn", -] +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tiny-keccak" @@ -2134,9 +2238,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.1.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -2149,29 +2253,28 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "0.2.25" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +checksum = "57aec3cfa4c296db7255446efb4928a6be304b431a806216105542a67b6ca82e" dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "iovec", - "lazy_static", + "autocfg", + "bytes", + "libc", "memchr", "mio", "num_cpus", - "pin-project-lite 0.1.12", - "slab", + "once_cell", + "pin-project-lite", + "socket2", + "winapi", ] [[package]] name = "tokio-rustls" -version = "0.14.1" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "futures-core", "rustls", "tokio", "webpki", @@ -2179,53 +2282,51 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.3.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-core", "futures-sink", - "log", - "pin-project-lite 0.1.12", + "pin-project-lite", "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", ] [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.25" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ - "cfg-if 1.0.0", - "log", - "pin-project-lite 0.2.6", + "cfg-if", + "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ - "pin-project", - "tracing", + "once_cell", ] [[package]] @@ -2236,54 +2337,42 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "twox-hash" -version = "1.6.0" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", - "rand 0.7.3", + "cfg-if", + "rand 0.8.5", "static_assertions", ] [[package]] name = "typenum" -version = "1.12.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] -name = "unicase" -version = "2.6.0" +name = "unicode-bidi" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] -name = "unicode-bidi" -version = "0.3.4" +name = "unicode-ident" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", -] +checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - [[package]] name = "untrusted" version = "0.7.1" @@ -2292,9 +2381,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", "idna", @@ -2310,15 +2399,15 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" [[package]] name = "vcpkg" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" @@ -2338,27 +2427,31 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.71" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ - "cfg-if 1.0.0", - "serde", - "serde_json", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.71" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", "lazy_static", @@ -2371,11 +2464,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.21" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -2383,9 +2476,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.71" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2393,9 +2486,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.71" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", @@ -2406,15 +2499,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.71" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "web-sys" -version = "0.3.48" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" dependencies = [ "js-sys", "wasm-bindgen", @@ -2422,9 +2515,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.4" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ "ring", "untrusted", @@ -2432,25 +2525,13 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.20.0" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" +checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf" dependencies = [ "webpki", ] -[[package]] -name = "weezl" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -2461,12 +2542,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2479,35 +2554,112 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "wyz" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "tap", ] [[package]] name = "zip" -version = "0.5.11" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8264fcea9b7a036a4a5103d7153e988dbc2ebbafb34f68a3c2d404b6b82d74b6" +checksum = "bf225bcf73bb52cbb496e70475c7bd7a3f769df699c0020f6c7bd9a96dcf0b8d" dependencies = [ + "aes", "byteorder", "bzip2", + "constant_time_eq", "crc32fast", + "crossbeam-utils", "flate2", - "thiserror", - "time 0.1.43", + "hmac", + "pbkdf2", + "sha1 0.10.1", + "time 0.3.11", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.10.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4a6bd64f22b5e3e94b4e238669ff9f10815c27a5180108b849d24174a83847" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "4.1.6+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b61c51bb270702d6167b8ce67340d2754b088d0c091b06e593aa772c3ee9bb" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "1.6.3+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" +dependencies = [ + "cc", + "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 07ecbc7f..024568e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,14 @@ [package] name = "rust-g" -edition = "2018" -version = "0.4.7" -authors = ["Bjorn Neergaard "] +edition = "2021" +version = "1.2.0" +authors = [ + "Bjorn Neergaard ", + "Tad Hardesty ", + "rust-g maintainer team", +] repository = "https://github.com/tgstation/rust-g" -license-file = "LICENSE" +license = "MIT" description = "Offloaded task library for the /tg/ Space Station 13 codebase" [lib] @@ -14,39 +18,65 @@ crate-type = ["cdylib"] opt-level = 3 codegen-units = 1 lto = true +debug = true [dependencies] thiserror = "1.0" -flume = { version = "0.9", optional = true } +flume = { version = "0.10", optional = true } chrono = { version = "0.4", optional = true } -md-5 = { version = "0.9", optional = true } -twox-hash = { version = "1.6.0", optional = true } +base64 = { version = "0.13", optional = true } +md-5 = { version = "0.10", optional = true } +twox-hash = { version = "1.6", optional = true } const-random = { version = "0.1.13", optional = true } -sha-1 = { version = "0.9", optional = true } -sha2 = { version = "0.9", optional = true } +sha-1 = { version = "0.10", optional = true } +sha2 = { version = "0.10", optional = true } hex = { version = "0.4", optional = true } percent-encoding = { version = "2.1", optional = true } url-dep = { version = "2.1", package = "url", optional = true } -png = { version = "0.16", optional = true } -image = { version = "0.23.10", optional = true } -git2 = { version = "0.13", optional = true, default-features = false } -noise = { version = "0.6", optional = true} -reqwest = { version = "0.10", optional = true, default-features = false, features = ["blocking", "rustls-tls"] } +png = { version = "0.17", optional = true } +image = { version = "0.24", optional = true, default-features = false, features = ["png"] } +git2 = { version = "0.14", optional = true, default-features = false } +noise = { version = "0.8", optional = true } +redis = { version = "0.21", optional = true } +reqwest = { version = "0.11", optional = true, default-features = false, features = [ + "blocking", + "rustls-tls", +] } serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } lazy_static = { version = "1.4", optional = true } once_cell = { version = "1.4", optional = true } -mysql = { version = "20.0", optional = true } -dashmap = { version = "3.11", optional = true } -zip = { version = "0.5.8", optional = true } -rand = {version = "0.7", optional = true} - +mysql = { version = "22.2", optional = true } +dashmap = { version = "5.3", optional = true } +zip = { version = "0.6", optional = true } +rand = { version = "0.8", optional = true } +toml-dep = { version = "0.5.8", package = "toml", optional = true } +aho-corasick = { version = "0.7.18", optional = true } +rayon = { version = "1.5", optional = true } +dbpnoise = { version = "0.1.2", optional = true } +pathfinding = { version = "3.0.13", optional = true } +num = { version = "0.4.0", optional = true } [features] -default = ["cellularnoise", "dmi", "file", "git", "http", "json", "log", "noise", "sql"] +default = [ + "acreplace", + "cellularnoise", + "dmi", + "file", + "git", + "http", + "json", + "log", + "noise", + "sql", + "time", + "toml", + "url", +] # default features -cellularnoise = ["rand"] +acreplace = ["aho-corasick"] +cellularnoise = ["rand", "rayon"] dmi = ["png", "image"] file = [] git = ["git2", "chrono"] @@ -54,11 +84,30 @@ http = ["reqwest", "serde", "serde_json", "once_cell", "jobs"] json = ["serde", "serde_json"] log = ["chrono"] sql = ["mysql", "serde", "serde_json", "once_cell", "dashmap", "jobs"] - -# non-default features -hash = ["md-5", "sha-1", "sha2", "hex", "twox-hash", "const-random"] +time = [] +toml = ["serde", "serde_json", "toml-dep"] url = ["url-dep", "percent-encoding"] + +# additional features +batchnoise = ["dbpnoise"] +hash = [ + "base64", + "const-random", + "md-5", + "hex", + "sha-1", + "sha2", + "twox-hash", + "serde", + "serde_json", +] +pathfinder = ["num", "pathfinding", "serde", "serde_json"] +redis_pubsub = ["flume", "redis", "serde", "serde_json"] unzip = ["zip", "jobs"] +worleynoise = ["rand", "rayon"] # internal feature-like things jobs = ["flume"] + +[dev-dependencies] +regex = "1" diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 00000000..31a39d64 --- /dev/null +++ b/Cross.toml @@ -0,0 +1,11 @@ +[target.i686-pc-windows-gnu] +image = "rustembedded/cross:i686-pc-windows-gnu" + +[target.i686-unknown-linux-gnu] +image = "rustg/i686-unknown-linux-gnu" + +[build.env] +passthrough = [ + "PKG_CONFIG_ALLOW_CROSS" +] + diff --git a/LICENSE b/LICENSE index ad58f722..28a1a6d0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Bjorn Neergaard, /tg/station contributors +Copyright (c) 2022 Bjorn Neergaard, rust-g contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 39ab9c41..54dcda1e 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,16 @@ System libraries: ```sh sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install zlib1g-dev:i386 libssl-dev:i386 pkg-config:i386 + sudo apt-get install zlib1g-dev:i386 libssl-dev:i386 ``` * Other Linux distributions install the appropriate **32-bit development** and **32-bit runtime** packages. +If you want to use the `pc-windows-gnu` or similar other target ABI, do the following: +1. Change the `"rust-analyzer.cargo.target"` setting in `.cargo/config` to `i686-pc-windows-gnu`. +2. Run `git update-index --assume-unchanged .cargo/config`, which will tell git to 'ignore' the changes you made. +3. If you find yourself ever wanting to change back, run `git update-index --no-assume-unchanged .cargo/config`. + ## Compiling The [Cargo] tool handles compilation, as well as automatically downloading and @@ -74,9 +79,12 @@ cargo build --release --target i686-pc-windows-msvc # output: target/i686-pc-windows-msvc/release/rust_g.dll ``` +If you aren't sharing the binary with other people, consider compiling [targeting your native cpu](https://rust-lang.github.io/packed_simd/perf-guide/target-feature/rustflags.html#target-cpu) for potential performance improvements. You can do this by setting the `RUSTFLAGS` environment variable to `-C target-cpu=native`. For example, in Powershell you would use `$Env:RUSTFLAGS="-C target-cpu=native"`. + To get additional features, pass a list to `--features`, for example `--features hash,url`. To get all features, pass `--all-features`. To disable the default features, pass `--no-default-features`. The default features are: +* acreplace: Aho-Corasick string matching and replacement. * cellularnoise: Function to generate cellular automata-based noise. * dmi: DMI manipulations which are impossible from within BYOND. Used by the asset cache subsystem to improve load times. @@ -85,13 +93,21 @@ The default features are: * http: Asynchronous HTTP(s) client supporting most standard methods. * json: Function to check JSON validity. * log: Faster log output. -* sql: Asynchronous MySQL/MariaDB client library. * noise: 2d Perlin noise. +* sql: Asynchronous MySQL/MariaDB client library. +* time: High-accuracy time measuring. +* toml: TOML parser. +* url: Faster replacements for `url_encode` and `url_decode`. Additional features are: +* batchnoise: Discrete Batched Perlin-like Noise, fast and multi-threaded - sent over once instead of having to query for every tile. * hash: Faster replacement for `md5`, support for SHA-1, SHA-256, and SHA-512. Requires OpenSSL on Linux. -* url: Faster replacements for `url_encode` and `url_decode`. +* pathfinder: An a* pathfinder used for finding the shortest path in a static node map. Not to be used for a non-static map. +* redis_pubsub: Library for sending and receiving messages through Redis. * unzip: Function to download a .zip from a URL and unzip it to a directory. +* worleynoise: Function that generates a type of nice looking cellular noise, more expensive than cellularnoise + +Regarding rust-analyzer: If you are using a feature set other than the default, you will need to adjust `rust-analyzer.cargo.features`. ## Installing @@ -164,6 +180,7 @@ open("rust_g", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = -1 ENOTD If you're still having problems, ask in the [Coderbus Discord]'s `#tooling-questions` channel. + [tgstation]: https://github.com/tgstation/tgstation [beestation]: https://github.com/beestation/beestation-hornet [Rust]: https://rust-lang.org diff --git a/build.rs b/build.rs index 99d60ebf..3039dbf0 100644 --- a/build.rs +++ b/build.rs @@ -28,9 +28,14 @@ fn main() { for (key, _value) in std::env::vars() { // CARGO_FEATURE_ — For each activated feature of the package being built, this environment variable will be present where is the name of the feature uppercased and having - translated to _. if let Some(uprfeature) = key.strip_prefix("CARGO_FEATURE_") { - let feature = uprfeature.to_lowercase().replace("_", "-"); // actual proper name of the enabled feature + let feature = uprfeature.to_lowercase().replace('_', "-"); // actual proper name of the enabled feature if feature_dm_exists!(&feature) { - writeln!(f, "{}", std::fs::read_to_string(feature_dm_file!(&feature)).unwrap()).unwrap(); + writeln!( + f, + "{}", + std::fs::read_to_string(feature_dm_file!(&feature)).unwrap() + ) + .unwrap(); } } } diff --git a/dmsrc/acreplace.dm b/dmsrc/acreplace.dm new file mode 100644 index 00000000..ada138c6 --- /dev/null +++ b/dmsrc/acreplace.dm @@ -0,0 +1,42 @@ + +/** + * Sets up the Aho-Corasick automaton with its default options. + * + * The search patterns list and the replacements must be of the same length when replace is run, but an empty replacements list is allowed if replacements are supplied with the replace call + * Arguments: + * * key - The key for the automaton, to be used with subsequent rustg_acreplace/rustg_acreplace_with_replacements calls + * * patterns - A non-associative list of strings to search for + * * replacements - Default replacements for this automaton, used with rustg_acreplace + */ +#define rustg_setup_acreplace(key, patterns, replacements) RUSTG_CALL(RUST_G, "setup_acreplace")(key, json_encode(patterns), json_encode(replacements)) + +/** + * Sets up the Aho-Corasick automaton using supplied options. + * + * The search patterns list and the replacements must be of the same length when replace is run, but an empty replacements list is allowed if replacements are supplied with the replace call + * Arguments: + * * key - The key for the automaton, to be used with subsequent rustg_acreplace/rustg_acreplace_with_replacements calls + * * options - An associative list like list("anchored" = 0, "ascii_case_insensitive" = 0, "match_kind" = "Standard"). The values shown on the example are the defaults, and default values may be omitted. See the identically named methods at https://docs.rs/aho-corasick/latest/aho_corasick/struct.AhoCorasickBuilder.html to see what the options do. + * * patterns - A non-associative list of strings to search for + * * replacements - Default replacements for this automaton, used with rustg_acreplace + */ +#define rustg_setup_acreplace_with_options(key, options, patterns, replacements) RUSTG_CALL(RUST_G, "setup_acreplace")(key, json_encode(options), json_encode(patterns), json_encode(replacements)) + +/** + * Run the specified replacement engine with the provided haystack text to replace, returning replaced text. + * + * Arguments: + * * key - The key for the automaton + * * text - Text to run replacements on + */ +#define rustg_acreplace(key, text) RUSTG_CALL(RUST_G, "acreplace")(key, text) + +/** + * Run the specified replacement engine with the provided haystack text to replace, returning replaced text. + * + * Arguments: + * * key - The key for the automaton + * * text - Text to run replacements on + * * replacements - Replacements for this call. Must be the same length as the set-up patterns + */ +#define rustg_acreplace_with_replacements(key, text, replacements) RUSTG_CALL(RUST_G, "acreplace_with_replacements")(key, text, json_encode(replacements)) diff --git a/dmsrc/cellularnoise.dm b/dmsrc/cellularnoise.dm index 2f48dd9d..2828fdc8 100644 --- a/dmsrc/cellularnoise.dm +++ b/dmsrc/cellularnoise.dm @@ -12,4 +12,4 @@ * * height: The height of the grid. */ #define rustg_cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) \ - call(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height) + RUSTG_CALL(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height) diff --git a/dmsrc/dbpnoise.dm b/dmsrc/dbpnoise.dm new file mode 100644 index 00000000..2b3914d3 --- /dev/null +++ b/dmsrc/dbpnoise.dm @@ -0,0 +1,16 @@ +/** + * This proc generates a grid of perlin-like noise + * + * Returns a single string that goes row by row, with values of 1 representing an turned on cell, and a value of 0 representing a turned off cell. + * + * Arguments: + * * seed: seed for the function + * * accuracy: how close this is to the original perlin noise, as accuracy approaches infinity, the noise becomes more and more perlin-like + * * stamp_size: Size of a singular stamp used by the algorithm, think of this as the same stuff as frequency in perlin noise + * * world_size: size of the returned grid. + * * lower_range: lower bound of values selected for. (inclusive) + * * upper_range: upper bound of values selected for. (exclusive) + */ +#define rustg_dbp_generate(seed, accuracy, stamp_size, world_size, lower_range, upper_range) \ + RUSTG_CALL(RUST_G, "dbp_generate")(seed, accuracy, stamp_size, world_size, lower_range, upper_range) + diff --git a/dmsrc/dmi.dm b/dmsrc/dmi.dm index b9baca82..4edd9fe8 100644 --- a/dmsrc/dmi.dm +++ b/dmsrc/dmi.dm @@ -1,3 +1,4 @@ -#define rustg_dmi_strip_metadata(fname) call(RUST_G, "dmi_strip_metadata")(fname) -#define rustg_dmi_create_png(path, width, height, data) call(RUST_G, "dmi_create_png")(path, width, height, data) -#define rustg_dmi_resize_png(path, width, height, resizetype) call(RUST_G, "dmi_resize_png")(path, width, height, resizetype) + +#define rustg_dmi_strip_metadata(fname) RUSTG_CALL(RUST_G, "dmi_strip_metadata")(fname) +#define rustg_dmi_create_png(path, width, height, data) RUSTG_CALL(RUST_G, "dmi_create_png")(path, width, height, data) +#define rustg_dmi_resize_png(path, width, height, resizetype) RUSTG_CALL(RUST_G, "dmi_resize_png")(path, width, height, resizetype) diff --git a/dmsrc/file.dm b/dmsrc/file.dm index e0c30336..c18d3f8a 100644 --- a/dmsrc/file.dm +++ b/dmsrc/file.dm @@ -1,7 +1,9 @@ -#define rustg_file_read(fname) call(RUST_G, "file_read")(fname) -#define rustg_file_exists(fname) call(RUST_G, "file_exists")(fname) -#define rustg_file_write(text, fname) call(RUST_G, "file_write")(text, fname) -#define rustg_file_append(text, fname) call(RUST_G, "file_append")(text, fname) +#define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname) +#define rustg_file_exists(fname) RUSTG_CALL(RUST_G, "file_exists")(fname) +#define rustg_file_write(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname) +#define rustg_file_append(text, fname) RUSTG_CALL(RUST_G, "file_append")(text, fname) +#define rustg_file_get_line_count(fname) text2num(RUSTG_CALL(RUST_G, "file_get_line_count")(fname)) +#define rustg_file_seek_line(fname, line) RUSTG_CALL(RUST_G, "file_seek_line")(fname, "[line]") #ifdef RUSTG_OVERRIDE_BUILTINS #define file2text(fname) rustg_file_read("[fname]") diff --git a/dmsrc/git.dm b/dmsrc/git.dm index b121e7f0..93a02d81 100644 --- a/dmsrc/git.dm +++ b/dmsrc/git.dm @@ -1,2 +1,3 @@ -#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev) -#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev) + +#define rustg_git_revparse(rev) RUSTG_CALL(RUST_G, "rg_git_revparse")(rev) +#define rustg_git_commit_date(rev) RUSTG_CALL(RUST_G, "rg_git_commit_date")(rev) diff --git a/dmsrc/hash.dm b/dmsrc/hash.dm index 3ecedc6f..c666d2e2 100644 --- a/dmsrc/hash.dm +++ b/dmsrc/hash.dm @@ -1,11 +1,14 @@ -#define rustg_hash_string(algorithm, text) call(RUST_G, "hash_string")(algorithm, text) -#define rustg_hash_file(algorithm, fname) call(RUST_G, "hash_file")(algorithm, fname) +#define rustg_hash_string(algorithm, text) RUSTG_CALL(RUST_G, "hash_string")(algorithm, text) +#define rustg_hash_file(algorithm, fname) RUSTG_CALL(RUST_G, "hash_file")(algorithm, fname) +#define rustg_hash_generate_totp(seed) RUSTG_CALL(RUST_G, "generate_totp")(seed) +#define rustg_hash_generate_totp_tolerance(seed, tolerance) RUSTG_CALL(RUST_G, "generate_totp_tolerance")(seed, tolerance) #define RUSTG_HASH_MD5 "md5" #define RUSTG_HASH_SHA1 "sha1" #define RUSTG_HASH_SHA256 "sha256" #define RUSTG_HASH_SHA512 "sha512" #define RUSTG_HASH_XXH64 "xxh64" +#define RUSTG_HASH_BASE64 "base64" #ifdef RUSTG_OVERRIDE_BUILTINS #define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing)) diff --git a/dmsrc/http.dm b/dmsrc/http.dm index 93d964bb..d63748d6 100644 --- a/dmsrc/http.dm +++ b/dmsrc/http.dm @@ -4,6 +4,6 @@ #define RUSTG_HTTP_METHOD_PATCH "patch" #define RUSTG_HTTP_METHOD_HEAD "head" #define RUSTG_HTTP_METHOD_POST "post" -#define rustg_http_request_blocking(method, url, body, headers, options) call(RUST_G, "http_request_blocking")(method, url, body, headers, options) -#define rustg_http_request_async(method, url, body, headers, options) call(RUST_G, "http_request_async")(method, url, body, headers, options) -#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id) +#define rustg_http_request_blocking(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_blocking")(method, url, body, headers, options) +#define rustg_http_request_async(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_async")(method, url, body, headers, options) +#define rustg_http_check_request(req_id) RUSTG_CALL(RUST_G, "http_check_request")(req_id) diff --git a/dmsrc/json.dm b/dmsrc/json.dm index 80a18539..caa637c4 100644 --- a/dmsrc/json.dm +++ b/dmsrc/json.dm @@ -1 +1 @@ -#define rustg_json_is_valid(text) (call(RUST_G, "json_is_valid")(text) == "true") +#define rustg_json_is_valid(text) (RUSTG_CALL(RUST_G, "json_is_valid")(text) == "true") diff --git a/dmsrc/log.dm b/dmsrc/log.dm index 709b484e..1faadc8e 100644 --- a/dmsrc/log.dm +++ b/dmsrc/log.dm @@ -1,2 +1,2 @@ -#define rustg_log_write(fname, text, format) call(RUST_G, "log_write")(fname, text, format) -/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")() +#define rustg_log_write(fname, text, format) RUSTG_CALL(RUST_G, "log_write")(fname, text, format) +/proc/rustg_log_close_all() return RUSTG_CALL(RUST_G, "log_close_all")() diff --git a/dmsrc/main.dm b/dmsrc/main.dm index 80099ca0..5f6b72e7 100644 --- a/dmsrc/main.dm +++ b/dmsrc/main.dm @@ -37,3 +37,13 @@ #define RUST_G (__rust_g || __detect_rust_g()) #endif + +// Handle 515 call() -> call_ext() changes +#if DM_VERSION >= 515 +#define RUSTG_CALL call_ext +#else +#define RUSTG_CALL call +#endif + +/// Gets the version of rust_g +/proc/rustg_get_version() return RUSTG_CALL(RUST_G, "get_version")() diff --git a/dmsrc/noise.dm b/dmsrc/noise.dm index 6277a462..5630600e 100644 --- a/dmsrc/noise.dm +++ b/dmsrc/noise.dm @@ -1 +1 @@ -#define rustg_noise_get_at_coordinates(seed, x, y) call(RUST_G, "noise_get_at_coordinates")(seed, x, y) +#define rustg_noise_get_at_coordinates(seed, x, y) RUSTG_CALL(RUST_G, "noise_get_at_coordinates")(seed, x, y) diff --git a/dmsrc/pathfinder.dm b/dmsrc/pathfinder.dm new file mode 100644 index 00000000..3259aa87 --- /dev/null +++ b/dmsrc/pathfinder.dm @@ -0,0 +1,32 @@ +/** + * Register a list of nodes into a rust library. This list of nodes must have been serialized in a json. + * Node {// Index of this node in the list of nodes + * unique_id: usize, + * // Position of the node in byond + * x: usize, + * y: usize, + * z: usize, + * // Indexes of nodes connected to this one + * connected_nodes_id: Vec} + * It is important that the node with the unique_id 0 is the first in the json, unique_id 1 right after that, etc. + * It is also important that all unique ids follow. {0, 1, 2, 4} is not a correct list and the registering will fail + * Nodes should not link across z levels. + * A node cannot link twice to the same node and shouldn't link itself either + */ +#define rustg_register_nodes_astar(json) RUSTG_CALL(RUST_G, "register_nodes_astar")(json) + +/** + * Add a new node to the static list of nodes. Same rule as registering_nodes applies. + * This node unique_id must be equal to the current length of the static list of nodes + */ +#define rustg_add_node_astar(json) RUSTG_CALL(RUST_G, "add_node_astar")(json) + +/**² + * Remove every link to the node with unique_id. Replace that node by null + */ +#define rustg_remove_node_astart(unique_id) RUSTG_CALL(RUST_G, "remove_node_astar")(unique_id) + +/** + * Compute the shortest path between start_node and goal_node using A*. Heuristic used is simple geometric distance + */ +#define rustg_generate_path_astar(start_node_id, goal_node_id) RUSTG_CALL(RUST_G, "generate_path_astar")(start_node_id, goal_node_id) diff --git a/dmsrc/redis-pubsub.dm b/dmsrc/redis-pubsub.dm new file mode 100644 index 00000000..842f1bf5 --- /dev/null +++ b/dmsrc/redis-pubsub.dm @@ -0,0 +1,7 @@ +#define RUSTG_REDIS_ERROR_CHANNEL "RUSTG_REDIS_ERROR_CHANNEL" + +#define rustg_redis_connect(addr) RUSTG_CALL(RUST_G, "redis_connect")(addr) +/proc/rustg_redis_disconnect() return RUSTG_CALL(RUST_G, "redis_disconnect")() +#define rustg_redis_subscribe(channel) RUSTG_CALL(RUST_G, "redis_subscribe")(channel) +/proc/rustg_redis_get_messages() return RUSTG_CALL(RUST_G, "redis_get_messages")() +#define rustg_redis_publish(channel, message) RUSTG_CALL(RUST_G, "redis_publish")(channel, message) diff --git a/dmsrc/sql.dm b/dmsrc/sql.dm index d3bfc49b..cad44b59 100644 --- a/dmsrc/sql.dm +++ b/dmsrc/sql.dm @@ -1,6 +1,6 @@ -#define rustg_sql_connect_pool(options) call(RUST_G, "sql_connect_pool")(options) -#define rustg_sql_query_async(handle, query, params) call(RUST_G, "sql_query_async")(handle, query, params) -#define rustg_sql_query_blocking(handle, query, params) call(RUST_G, "sql_query_blocking")(handle, query, params) -#define rustg_sql_connected(handle) call(RUST_G, "sql_connected")(handle) -#define rustg_sql_disconnect_pool(handle) call(RUST_G, "sql_disconnect_pool")(handle) -#define rustg_sql_check_query(job_id) call(RUST_G, "sql_check_query")("[job_id]") +#define rustg_sql_connect_pool(options) RUSTG_CALL(RUST_G, "sql_connect_pool")(options) +#define rustg_sql_query_async(handle, query, params) RUSTG_CALL(RUST_G, "sql_query_async")(handle, query, params) +#define rustg_sql_query_blocking(handle, query, params) RUSTG_CALL(RUST_G, "sql_query_blocking")(handle, query, params) +#define rustg_sql_connected(handle) RUSTG_CALL(RUST_G, "sql_connected")(handle) +#define rustg_sql_disconnect_pool(handle) RUSTG_CALL(RUST_G, "sql_disconnect_pool")(handle) +#define rustg_sql_check_query(job_id) RUSTG_CALL(RUST_G, "sql_check_query")("[job_id]") diff --git a/dmsrc/time.dm b/dmsrc/time.dm new file mode 100644 index 00000000..f4ac5e5c --- /dev/null +++ b/dmsrc/time.dm @@ -0,0 +1,6 @@ +#define rustg_time_microseconds(id) text2num(RUSTG_CALL(RUST_G, "time_microseconds")(id)) +#define rustg_time_milliseconds(id) text2num(RUSTG_CALL(RUST_G, "time_milliseconds")(id)) +#define rustg_time_reset(id) RUSTG_CALL(RUST_G, "time_reset")(id) + +/proc/rustg_unix_timestamp() + return text2num(RUSTG_CALL(RUST_G, "unix_timestamp")()) diff --git a/dmsrc/toml.dm b/dmsrc/toml.dm new file mode 100644 index 00000000..b490d959 --- /dev/null +++ b/dmsrc/toml.dm @@ -0,0 +1,17 @@ +#define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null") + +/proc/rustg_read_toml_file(path) + var/list/output = rustg_raw_read_toml_file(path) + if (output["success"]) + return json_decode(output["content"]) + else + CRASH(output["content"]) + +#define rustg_raw_toml_encode(value) json_decode(RUSTG_CALL(RUST_G, "toml_encode")(json_encode(value))) + +/proc/rustg_toml_encode(value) + var/list/output = rustg_raw_toml_encode(value) + if (output["success"]) + return output["content"] + else + CRASH(output["content"]) diff --git a/dmsrc/unzip.dm b/dmsrc/unzip.dm index ce945b1b..77e79de2 100644 --- a/dmsrc/unzip.dm +++ b/dmsrc/unzip.dm @@ -1,2 +1,2 @@ -#define rustg_unzip_download_async(url, unzip_directory) call(RUST_G, "unzip_download_async")(url, unzip_directory) -#define rustg_unzip_check(job_id) call(RUST_G, "unzip_check")("[job_id]") +#define rustg_unzip_download_async(url, unzip_directory) RUSTG_CALL(RUST_G, "unzip_download_async")(url, unzip_directory) +#define rustg_unzip_check(job_id) RUSTG_CALL(RUST_G, "unzip_check")("[job_id]") diff --git a/dmsrc/url.dm b/dmsrc/url.dm index 914b8bb9..3f53e257 100644 --- a/dmsrc/url.dm +++ b/dmsrc/url.dm @@ -1,5 +1,5 @@ -#define rustg_url_encode(text) call(RUST_G, "url_encode")(text) -#define rustg_url_decode(text) call(RUST_G, "url_decode")(text) +#define rustg_url_encode(text) RUSTG_CALL(RUST_G, "url_encode")("[text]") +#define rustg_url_decode(text) RUSTG_CALL(RUST_G, "url_decode")(text) #ifdef RUSTG_OVERRIDE_BUILTINS #define url_encode(text) rustg_url_encode(text) diff --git a/dmsrc/worleynoise.dm b/dmsrc/worleynoise.dm new file mode 100644 index 00000000..379adfca --- /dev/null +++ b/dmsrc/worleynoise.dm @@ -0,0 +1,16 @@ +/** + * This proc generates a noise grid using worley noise algorithm + * + * Returns a single string that goes row by row, with values of 1 representing an alive cell, and a value of 0 representing a dead cell. + * + * Arguments: + * * region_size: The size of regions + * * threshold: the value that determines wether a cell is dead or alive + * * node_per_region_chance: chance of a node existiing in a region + * * size: size of the returned grid + * * node_min: minimum amount of nodes in a region (after the node_per_region_chance is applied) + * * node_max: maximum amount of nodes in a region + */ +#define rustg_worley_generate(region_size, threshold, node_per_region_chance, size, node_min, node_max) \ + RUSTG_CALL(RUST_G, "worley_generate")(region_size, threshold, node_per_region_chance, size, node_min, node_max) + diff --git a/docker/Dockerfile.i686-unknown-linux-gnu b/docker/Dockerfile.i686-unknown-linux-gnu new file mode 100644 index 00000000..f37a8bfd --- /dev/null +++ b/docker/Dockerfile.i686-unknown-linux-gnu @@ -0,0 +1,5 @@ +FROM rustembedded/cross:i686-unknown-linux-gnu + +RUN dpkg --add-architecture i386 && \ + apt-get update && \ + apt-get install --assume-yes zlib1g-dev:i386 libssl-dev:i386 pkg-config:i386 diff --git a/scripts/prepare_binaries.sh b/scripts/prepare_binaries.sh index 73afd201..20a22b80 100755 --- a/scripts/prepare_binaries.sh +++ b/scripts/prepare_binaries.sh @@ -3,16 +3,18 @@ set -euo pipefail touch build.rs +echo '==== Make sure cross is installed ====' +cargo install cross + echo '==== Linux build ====' # ------------------------------------------------ rustup target add i686-unknown-linux-gnu env PKG_CONFIG_ALLOW_CROSS=1 \ - cargo build --release --target i686-unknown-linux-gnu + cargo build --release --target i686-unknown-linux-gnu mv target/rust_g.dm target/rust_g.linux.dm echo '==== Windows build ====' # ---------------------------------------------- -rustup target add i686-pc-windows-gnu -cargo build --release --target i686-pc-windows-gnu +cross build --release --target i686-pc-windows-gnu # https://github.com/rust-lang/rust/issues/12859#issuecomment-62255275 # Most distros ship 32-bit toolchains with SJLJ unwinding, but for 32-bit Rust # can only cross-compile targeting DWARF. All 64-bit toolchains use SEH, where @@ -27,6 +29,10 @@ cargo build --release --target i686-pc-windows-gnu # tar xf rust-mingw-nightly-i686-pc-windows-gnu.tar.gz # ./rust-mingw-nightly-i686-pc-windows-gnu/install.sh --prefix=$(rustc --print sysroot) +# Luckily we are taking the third workaround, which is using the cross projects i686 +# windows toolchain docker which comes with an updated version of mingw that supports +# the DWARF based unwinding, freeing us from such earthly concerns + # Make sure the `rust_g.dm` produced for each platform are the same, just in # case. cmp target/rust_g.dm target/rust_g.linux.dm diff --git a/src/acreplace.rs b/src/acreplace.rs new file mode 100644 index 00000000..681bdf0b --- /dev/null +++ b/src/acreplace.rs @@ -0,0 +1,94 @@ +use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind}; +use serde::Deserialize; +use std::{cell::RefCell, collections::hash_map::HashMap}; + +struct Replacements { + pub automaton: AhoCorasick, + pub replacements: Vec, +} + +#[derive(Deserialize)] +struct AhoCorasickOptions { + #[serde(default, deserialize_with = "deserialize_byond_bool")] + pub anchored: bool, + #[serde(default, deserialize_with = "deserialize_byond_bool")] + pub ascii_case_insensitive: bool, + #[serde(default, deserialize_with = "deserialize_matchkind")] + pub match_kind: MatchKind, +} + +impl AhoCorasickOptions { + fn auto_configure_and_build(&self, patterns: &[String]) -> AhoCorasick { + AhoCorasickBuilder::new() + .anchored(self.anchored) + .ascii_case_insensitive(self.ascii_case_insensitive) + .match_kind(self.match_kind) + .auto_configure(patterns) + .build(patterns) + } +} + +fn deserialize_byond_bool<'de, D>(deserializer: D) -> Result +where + D: serde::de::Deserializer<'de>, +{ + match u8::deserialize(deserializer)? { + 0 => Ok(false), + _ => Ok(true), + } +} + +fn deserialize_matchkind<'de, D>(deserializer: D) -> Result +where + D: serde::de::Deserializer<'de>, +{ + match String::deserialize(deserializer)?.as_ref() { + "LeftmostFirst" => Ok(MatchKind::LeftmostFirst), + "LeftmostLongest" => Ok(MatchKind::LeftmostLongest), + _ => Ok(MatchKind::Standard), + } +} + +thread_local! { + static CREPLACE_MAP: RefCell> = RefCell::new(HashMap::new()); +} + +byond_fn!(fn setup_acreplace(key, patterns_json, replacements_json) { + let patterns: Vec = serde_json::from_str(patterns_json).ok()?; + let replacements: Vec = serde_json::from_str(replacements_json).ok()?; + let ac = AhoCorasickBuilder::new().auto_configure(&patterns).build(&patterns); + CREPLACE_MAP.with(|cell| { + let mut map = cell.borrow_mut(); + map.insert(key.to_owned(), Replacements { automaton: ac, replacements }); + }); + Some("") +}); + +byond_fn!(fn setup_acreplace_with_options(key, options_json, patterns_json, replacements_json) { + let options: AhoCorasickOptions = serde_json::from_str(options_json).ok()?; + let patterns: Vec = serde_json::from_str(patterns_json).ok()?; + let replacements: Vec = serde_json::from_str(replacements_json).ok()?; + let ac = options.auto_configure_and_build(&patterns); + CREPLACE_MAP.with(|cell| { + let mut map = cell.borrow_mut(); + map.insert(key.to_owned(), Replacements { automaton: ac, replacements }); + }); + Some("") +}); + +byond_fn!(fn acreplace(key, text) { + CREPLACE_MAP.with(|cell| -> Option { + let map = cell.borrow_mut(); + let replacements = map.get(key)?; + Some(replacements.automaton.replace_all(text, &replacements.replacements)) + }) +}); + +byond_fn!(fn acreplace_with_replacements(key, text, replacements_json) { + let call_replacements: Vec = serde_json::from_str(replacements_json).ok()?; + CREPLACE_MAP.with(|cell| -> Option { + let map = cell.borrow_mut(); + let replacements = map.get(key)?; + Some(replacements.automaton.replace_all(text, &call_replacements)) + }) +}); diff --git a/src/byond.rs b/src/byond.rs index 68925ce3..385d5251 100644 --- a/src/byond.rs +++ b/src/byond.rs @@ -12,11 +12,13 @@ thread_local! { } pub unsafe fn parse_args<'a>(argc: c_int, argv: *const *const c_char) -> Vec> { - slice::from_raw_parts(argv, argc as usize) - .iter() - .map(|ptr| CStr::from_ptr(*ptr)) - .map(|cstr| cstr.to_string_lossy()) - .collect() + unsafe { + slice::from_raw_parts(argv, argc as usize) + .iter() + .map(|ptr| CStr::from_ptr(*ptr)) + .map(|cstr| cstr.to_string_lossy()) + .collect() + } } pub fn byond_return(value: Option>) -> *const c_char { @@ -42,7 +44,7 @@ pub fn byond_return(value: Option>) -> *const c_char { #[macro_export] macro_rules! byond_fn { - ($name:ident() $body:block) => { + (fn $name:ident() $body:block) => { #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn $name( @@ -53,10 +55,10 @@ macro_rules! byond_fn { } }; - ($name:ident($($arg:ident),* $(, ...$rest:ident)?) $body:block) => { + (fn $name:ident($($arg:ident),* $(, ...$rest:ident)?) $body:block) => { #[no_mangle] #[allow(clippy::missing_safety_doc)] - pub extern "C" fn $name( + pub unsafe extern "C" fn $name( _argc: ::std::os::raw::c_int, _argv: *const *const ::std::os::raw::c_char ) -> *const ::std::os::raw::c_char { let __args = unsafe { $crate::byond::parse_args(_argc, _argv) }; @@ -75,3 +77,10 @@ macro_rules! byond_fn { } }; } + +// Easy version checker. It's in this file so it is always included +byond_fn!( + fn get_version() { + Some(env!("CARGO_PKG_VERSION")) + } +); diff --git a/src/cellularnoise.rs b/src/cellularnoise.rs index 3c837e27..fcd2bcb5 100644 --- a/src/cellularnoise.rs +++ b/src/cellularnoise.rs @@ -1,10 +1,11 @@ use crate::error::Result; use rand::*; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; use std::fmt::Write; -byond_fn! { cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) { +byond_fn!(fn cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) { noise_gen(percentage, smoothing_iterations, birth_limit, death_limit, width, height).ok() -} } +}); fn noise_gen( percentage_as_str: &str, @@ -14,79 +15,76 @@ fn noise_gen( width_as_str: &str, height_as_str: &str, ) -> Result { - let percentage = percentage_as_str.parse::()?; - let smoothing_level = smoothing_level_as_str.parse::()?; - let birth_limit = birth_limit_as_str.parse::()?; - let death_limit = death_limit_as_str.parse::()?; + let percentage = percentage_as_str.parse::()?; + let smoothing_level = smoothing_level_as_str.parse::()?; + let birth_limit = birth_limit_as_str.parse::()?; + let death_limit = death_limit_as_str.parse::()?; let width = width_as_str.parse::()?; let height = height_as_str.parse::()?; - - // Noise generation - let mut zplane = vec![vec![false; width]; height]; - for row in zplane.iter_mut() { - for cell in row.iter_mut() { - *cell = rand::thread_rng().gen_range(0, 100) < percentage; - } - } - - // Smoothing part - for _timer in 0..smoothing_level { - let zplane_old = zplane.clone(); - for i in 0..height { - for j in 0..width { - let mut sum = 0; - - if i > 0 { - if j > 0 { - sum += if zplane_old[i - 1][j - 1] { 1 } else { 0 }; - } - - sum += if zplane_old[i - 1][j] { 1 } else { 0 }; - - if j + 1 < width { - sum += if zplane_old[i - 1][j + 1] { 1 } else { 0 }; - } - } - - if j > 0 { - sum += if zplane_old[i][j - 1] { 1 } else { 0 }; - } - - if j + 1 < width { - sum += if zplane_old[i][j + 1] { 1 } else { 0 }; - } - - if i + 1 < height { - if j > 0 { - sum += if zplane_old[i + 1][j - 1] { 1 } else { 0 }; + //we populate it, from 0 to height+3, 0 to height+1 is exactly height long, but we also need border guards, so we add another +2, so it is 0..height+3 + let mut filled_vec = (0..width + 3) + .into_par_iter() + .map(|x| { + let mut rng = rand::thread_rng(); + (0..height + 3) + .into_iter() + .map(|y| { + if x == 0 || y == 0 || x == width + 2 || y == height + 2 { + return false; } + rng.gen_range(0..100) < percentage + }) + .collect::>() + }) + .collect::>>(); - sum += if zplane_old[i + 1][j] { 1 } else { 0 }; + //then we smoothe it + (0..smoothing_level).into_iter().for_each(|_| { + let replace_vec = (0..width + 3) + .into_par_iter() + .map(|x| { + (0..height + 3) + .into_iter() + .map(|y| { + if x == 0 || y == 0 || x == width + 2 || y == height + 2 { + return false; + } + let sum: usize = filled_vec[x - 1][y - 1] as usize + + filled_vec[x - 1][y] as usize + + filled_vec[x - 1][y + 1] as usize + + filled_vec[x][y - 1] as usize + + filled_vec[x][y + 1] as usize + + filled_vec[x + 1][y - 1] as usize + + filled_vec[x + 1][y] as usize + + filled_vec[x + 1][y + 1] as usize; - if j + 1 < width { - sum += if zplane_old[i + 1][j + 1] { 1 } else { 0 }; - } - } + if sum < death_limit && filled_vec[x][y] { + return false; + } + if sum > birth_limit && !filled_vec[x][y] { + return true; + } + filled_vec[x][y] + }) + .collect::>() + }) + .collect::>>(); + filled_vec = replace_vec; + }); - if zplane_old[i][j] == true { - if sum < death_limit { - zplane[i][j] = false; - } else { - zplane[i][j] = true; - } - } else { - if sum > birth_limit { - zplane[i][j] = true; - } else { - zplane[i][j] = false; - } - } - } - } - } + //then we cut it + let map = (1..width + 1) + .into_par_iter() + .map(|x| { + (1..height + 1) + .into_iter() + .map(|y| filled_vec[x][y]) + .collect::>() + }) + .collect::>>(); let mut string = String::new(); - for row in zplane.iter() { + for row in map.iter() { for cell in row.iter() { if *cell { let _ = write!(string, "1"); diff --git a/src/dbpnoise.rs b/src/dbpnoise.rs new file mode 100644 index 00000000..db67e5bb --- /dev/null +++ b/src/dbpnoise.rs @@ -0,0 +1,36 @@ +use crate::error::Result; +use dbpnoise::gen_noise; + +byond_fn!(fn dbp_generate(seed, accuracy, stamp_size, world_size, lower_range, upper_range) { + gen_dbp_noise(seed, accuracy, stamp_size, world_size, lower_range, upper_range).ok() +}); + +fn gen_dbp_noise( + seed: &str, + accuracy_as_str: &str, + stamp_size_as_str: &str, + world_size_as_str: &str, + lower_range_as_str: &str, + upper_range_as_str: &str, +) -> Result { + let accuracy = accuracy_as_str.parse::()?; + let stamp_size = stamp_size_as_str.parse::()?; + let world_size = world_size_as_str.parse::()?; + let lower_range = lower_range_as_str.parse::()?; + let upper_range = upper_range_as_str.parse::()?; + let map: Vec> = gen_noise( + seed, + accuracy, + stamp_size, + world_size, + lower_range, + upper_range, + ); + let mut result = String::new(); + for row in map { + for cell in row { + result.push(if cell { '1' } else { '0' }); + } + } + Ok(result) +} diff --git a/src/dmi.rs b/src/dmi.rs index 0a4a4ecd..1737341d 100644 --- a/src/dmi.rs +++ b/src/dmi.rs @@ -1,19 +1,19 @@ use crate::error::{Error, Result}; -use png::{Decoder, Encoder, OutputInfo}; +use png::{Decoder, Encoder, OutputInfo, Reader}; use std::{ fs::{create_dir_all, File}, path::Path, }; -byond_fn! { dmi_strip_metadata(path) { +byond_fn!(fn dmi_strip_metadata(path) { strip_metadata(path).err() -} } +}); -byond_fn! { dmi_create_png(path, width, height, data) { +byond_fn!(fn dmi_create_png(path, width, height, data) { create_png(path, width, height, data).err() -} } +}); -byond_fn! { dmi_resize_png(path, width, height, resizetype) { +byond_fn!(fn dmi_resize_png(path, width, height, resizetype) { let resizetype = match resizetype { "catmull" => image::imageops::CatmullRom, "gaussian" => image::imageops::Gaussian, @@ -23,37 +23,54 @@ byond_fn! { dmi_resize_png(path, width, height, resizetype) { _ => image::imageops::Nearest, }; resize_png(path, width, height, resizetype).err() -} } +}); fn strip_metadata(path: &str) -> Result<()> { - let (info, image) = read_png(path)?; - Ok(write_png(path, info, image)?) + let (reader, frame_info, image) = read_png(path)?; + write_png(path, reader, frame_info, image, true) } -fn read_png(path: &str) -> Result<(OutputInfo, Vec)> { - let (info, mut reader) = Decoder::new(File::open(path)?).read_info()?; - let mut buf = vec![0; info.buffer_size()]; +fn read_png(path: &str) -> Result<(Reader, OutputInfo, Vec)> { + let mut reader = Decoder::new(File::open(path)?).read_info()?; + let mut buf = vec![0; reader.output_buffer_size()]; + let frame_info = reader.next_frame(&mut buf)?; - reader.next_frame(&mut buf)?; - Ok((info, buf)) + Ok((reader, frame_info, buf)) } -fn write_png(path: &str, info: OutputInfo, image: Vec) -> Result<()> { +fn write_png( + path: &str, + reader: Reader, + info: OutputInfo, + image: Vec, + strip: bool, +) -> Result<()> { let mut encoder = Encoder::new(File::create(path)?, info.width, info.height); encoder.set_color(info.color_type); encoder.set_depth(info.bit_depth); + let reader_info = reader.info(); + if let Some(palette) = reader_info.palette.to_owned() { + encoder.set_palette(palette); + } + let mut writer = encoder.write_header()?; + // Handles zTxt chunk copying from the original image if we /don't/ want to strip it + if !strip { + for chunk in &reader_info.compressed_latin1_text { + writer.write_text_chunk(chunk)?; + } + } Ok(writer.write_image_data(&image)?) } fn create_png(path: &str, width: &str, height: &str, data: &str) -> Result<()> { - let width = u32::from_str_radix(width, 10)?; - let height = u32::from_str_radix(height, 10)?; + let width = width.parse::()?; + let height = height.parse::()?; let bytes = data.as_bytes(); if bytes.len() % 7 != 0 { - return Err(Error::InvalidPngDataError); + return Err(Error::InvalidPngData); } let mut result: Vec = Vec::new(); @@ -70,15 +87,20 @@ fn create_png(path: &str, width: &str, height: &str, data: &str) -> Result<()> { } let mut encoder = Encoder::new(File::create(path)?, width, height); - encoder.set_color(png::ColorType::RGB); + encoder.set_color(png::ColorType::Rgb); encoder.set_depth(png::BitDepth::Eight); let mut writer = encoder.write_header()?; Ok(writer.write_image_data(&result)?) } -fn resize_png>(path: P, width: &str, height: &str, resizetype: image::imageops::FilterType) -> std::result::Result<(), Error> { - let width = u32::from_str_radix(width, 10)?; - let height = u32::from_str_radix(height, 10)?; +fn resize_png>( + path: P, + width: &str, + height: &str, + resizetype: image::imageops::FilterType, +) -> std::result::Result<(), Error> { + let width = width.parse::()?; + let height = height.parse::()?; let img = image::open(path.as_ref())?; diff --git a/src/error.rs b/src/error.rs index d1a7e1ff..104e80b7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,9 +7,9 @@ use std::{ use thiserror::Error; #[cfg(feature = "png")] -use png::{DecodingError, EncodingError}; +use image::error::ImageError; #[cfg(feature = "png")] -use image::error::{ImageError}; +use png::{DecodingError, EncodingError}; #[cfg(feature = "unzip")] use zip::result::ZipError; @@ -34,24 +34,33 @@ pub enum Error { #[cfg(feature = "png")] #[error(transparent)] ImageEncoding(#[from] EncodingError), + #[cfg(feature = "http")] #[error(transparent)] - ParseIntError(#[from] ParseIntError), + JsonSerialization(#[from] serde_json::Error), #[error(transparent)] - ParseFloatError(#[from] ParseFloatError), + ParseInt(#[from] ParseIntError), #[error(transparent)] - GenericImageError(#[from] ImageError), + ParseFloat(#[from] ParseFloatError), + #[error(transparent)] + GenericImage(#[from] ImageError), #[cfg(feature = "png")] #[error("Invalid png data.")] - InvalidPngDataError, + InvalidPngData, #[cfg(feature = "http")] #[error(transparent)] - RequestError(#[from] reqwest::Error), - #[cfg(feature = "http")] + Request(#[from] reqwest::Error), + #[cfg(feature = "toml")] + #[error(transparent)] + TomlDeserialization(#[from] toml_dep::de::Error), + #[cfg(feature = "toml")] #[error(transparent)] - SerializationError(#[from] serde_json::Error), + TomlSerialization(#[from] toml_dep::ser::Error), #[cfg(feature = "unzip")] #[error(transparent)] - UnzipError(#[from] ZipError) + Unzip(#[from] ZipError), + #[cfg(feature = "hash")] + #[error("Unable to decode hex value.")] + HexDecode, } impl From for Error { diff --git a/src/file.rs b/src/file.rs index 947c738d..d766e96f 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,24 +1,35 @@ use crate::error::Result; use std::{ fs::{File, OpenOptions}, - io::{BufReader, BufWriter, Read, Write}, + io::{BufRead, BufReader, BufWriter, Read, Write}, }; -byond_fn! { file_read(path) { +byond_fn!(fn file_read(path) { read(path).ok() -} } +}); -byond_fn! { file_exists(path) { +byond_fn!(fn file_exists(path) { Some(exists(path)) -} } +}); -byond_fn! { file_write(data, path) { +byond_fn!(fn file_write(data, path) { write(data, path).err() -} } +}); -byond_fn! { file_append(data, path) { +byond_fn!(fn file_append(data, path) { append(data, path).err() -} } +}); + +byond_fn!(fn file_get_line_count(path) { + Some(get_line_count(path).ok()?.to_string()) +}); + +byond_fn!(fn file_seek_line(path, line) { + seek_line(path, match line.parse::() { + Ok(line) => line, + Err(_) => return None, + }) +}); fn read(path: &str) -> Result { let file = File::open(path)?; @@ -27,7 +38,7 @@ fn read(path: &str) -> Result { let mut content = String::with_capacity(metadata.len() as usize); file.read_to_string(&mut content)?; - let content = content.replace("\r", ""); + let content = content.replace('\r', ""); Ok(content) } @@ -70,3 +81,13 @@ fn append(data: &str, path: &str) -> Result { Ok(written) } + +fn get_line_count(path: &str) -> Result { + let file = BufReader::new(File::open(path)?); + Ok(file.lines().count() as u32) +} + +fn seek_line(path: &str, line: usize) -> Option { + let file = BufReader::new(File::open(path).ok()?); + file.lines().nth(line).and_then(|line| line.ok()) +} diff --git a/src/git.rs b/src/git.rs index 641aeea3..1ce3d069 100644 --- a/src/git.rs +++ b/src/git.rs @@ -5,15 +5,15 @@ thread_local! { static REPOSITORY: Result = Repository::open("."); } -byond_fn! { rg_git_revparse(rev) { +byond_fn!(fn rg_git_revparse(rev) { REPOSITORY.with(|repo| -> Result { let repo = repo.as_ref().map_err(Error::code)?; let object = repo.revparse_single(rev).map_err(|e| e.code())?; Ok(object.id().to_string()) }).ok() -} } +}); -byond_fn! { rg_git_commit_date(rev) { +byond_fn!(fn rg_git_commit_date(rev) { REPOSITORY.with(|repo| -> Result { let repo = repo.as_ref().map_err(Error::code)?; let object = repo.revparse_single(rev).map_err(|e| e.code())?; @@ -21,4 +21,4 @@ byond_fn! { rg_git_commit_date(rev) { let datetime = Utc.timestamp(commit.time().seconds(), 0); Ok(datetime.format("%F").to_string()) }).ok() -} } +}); diff --git a/src/hash.rs b/src/hash.rs index 15914912..01c4af26 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,25 +1,43 @@ use crate::error::{Error, Result}; -use const_random::const_random ; +use const_random::const_random; const XXHASH_SEED: u64 = const_random!(u64); -use twox_hash::XxHash64; use md5::Md5; use sha1::Sha1; use sha2::{Digest, Sha256, Sha512}; use std::{ + convert::TryInto, fs::File, - io::{BufReader, Read}, hash::Hasher, + io::{BufReader, Read}, + time::{SystemTime, UNIX_EPOCH}, }; +use twox_hash::XxHash64; - - -byond_fn! { hash_string(algorithm, string) { +byond_fn!(fn hash_string(algorithm, string) { string_hash(algorithm, string).ok() -} } +}); -byond_fn! { hash_file(algorithm, string) { +byond_fn!(fn hash_file(algorithm, string) { file_hash(algorithm, string).ok() -} } +}); + +byond_fn!(fn generate_totp(hex_seed) { + match totp_generate(hex_seed, 0, None) { + Ok(value) => Some(value), + Err(error) => Some(format!("ERROR: {:?}", error)) + } +}); + +byond_fn!(fn generate_totp_tolerance(hex_seed, tolerance) { + let tolerance_value: i32 = match tolerance.parse() { + Ok(value) => value, + Err(_) => return Some(String::from("ERROR: Tolerance not a valid integer")) + }; + match totp_generate_tolerance(hex_seed, tolerance_value, None) { + Ok(value) => Some(value), + Err(error) => Some(format!("ERROR: {:?}", error)) + } +}); fn hash_algorithm>(name: &str, bytes: B) -> Result { match name { @@ -46,14 +64,15 @@ fn hash_algorithm>(name: &str, bytes: B) -> Result { "xxh64" => { let mut hasher = XxHash64::with_seed(XXHASH_SEED); hasher.write(bytes.as_ref()); - Ok(format!("{:x}",hasher.finish())) + Ok(format!("{:x}", hasher.finish())) } + "base64" => Ok(base64::encode(bytes.as_ref())), _ => Err(Error::InvalidAlgorithm), } } fn string_hash(algorithm: &str, string: &str) -> Result { - Ok(hash_algorithm(algorithm, string)?) + hash_algorithm(algorithm, string) } fn file_hash(algorithm: &str, path: &str) -> Result { @@ -61,5 +80,94 @@ fn file_hash(algorithm: &str, path: &str) -> Result { let mut file = BufReader::new(File::open(path)?); file.read_to_end(&mut bytes)?; - Ok(hash_algorithm(algorithm, &bytes)?) + hash_algorithm(algorithm, &bytes) +} + +/// Generates multiple TOTP codes from 20 character hex_seed, with time step +-tolerance +/// time_override is used as the current unix time instead of the current system time for testing +fn totp_generate_tolerance( + hex_seed: &str, + tolerance: i32, + time_override: Option, +) -> Result { + let mut results: Vec = Vec::new(); + for i in -tolerance..(tolerance + 1) { + let result = totp_generate(hex_seed, i.try_into().unwrap(), time_override)?; + results.push(result) + } + Ok(serde_json::to_string(&results)?) +} + +/// Generates a single TOTP code from 20 character hex_seed, offset by offset time steps +/// time_override is used as the current unix time instead of the current system time for testing +/// TOTP algorithm described https://blogs.unimelb.edu.au/sciencecommunication/2021/09/30/totp/ +/// HMAC algorithm described https://csrc.nist.gov/csrc/media/publications/fips/198/1/final/documents/fips-198-1_final.pdf +fn totp_generate(hex_seed: &str, offset: i64, time_override: Option) -> Result { + let mut seed: [u8; 64] = [0; 64]; + + match hex::decode_to_slice(hex_seed, &mut seed[..10] as &mut [u8]) { + Ok(value) => value, + Err(_) => return Err(Error::HexDecode), + }; + + let ipad: [u8; 64] = seed.map(|x| x ^ 0x36); // HMAC Step 4 + let opad: [u8; 64] = seed.map(|x| x ^ 0x5C); // HMAC Step 7 + + // Will panic if the date is not between Jan 1 1970 and the year ~200 billion + let curr_time: i64 = time_override.unwrap_or_else(|| { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("SystemTime is before Unix Epoc") + .as_secs() + .try_into() + .unwrap() + }) / 30; + let time: u64 = (curr_time + offset) as u64; + + let time_bytes: [u8; 8] = time.to_be_bytes(); + + // HMAC Step 5 and 6 + let mut hasher = Sha1::new(); + hasher.update(ipad); + hasher.update(time_bytes); + let ipad_time_hash = hasher.finalize(); + + // HMAC Step 8 and 9 + hasher = Sha1::new(); + hasher.update(opad); + hasher.update(ipad_time_hash); + let hmac = hasher.finalize(); + + let offset: usize = (hmac[19] & 0x0F).into(); + + let result_bytes: [u8; 4] = hmac[offset..(offset + 4)].try_into().unwrap(); + + let full_result: u32 = u32::from_be_bytes(result_bytes); + let result: u32 = (full_result & 0x7FFFFFFF) % 1000000; + + Ok(result.to_string()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn totp_generate_test() { + // The big offset is so that it always uses the same time, allowing for verification that the algorithm is correct + // Seed, time, and result for zero offset taken from https://blogs.unimelb.edu.au/sciencecommunication/2021/09/30/totp/ + let result = totp_generate("B93F9893199AEF85739C", 0, Some(54424722i64 * 30 + 29)); + assert_eq!(result.unwrap(), "417714"); + let result2 = totp_generate("B93F9893199AEF85739C", -1, Some(54424722i64 * 30 + 29)); + assert_eq!(result2.unwrap(), "358747"); + let result3 = totp_generate("B93F9893199AEF85739C", 1, Some(54424722i64 * 30 + 29)); + assert_eq!(result3.unwrap(), "539257"); + let result4 = totp_generate("B93F9893199AEF85739C", 2, Some(54424722i64 * 30 + 29)); + assert_eq!(result4.unwrap(), "679828"); + let json_result = + totp_generate_tolerance("B93F9893199AEF85739C", 1, Some(54424722i64 * 30 + 29)); + assert_eq!(json_result.unwrap(), "[\"358747\",\"417714\",\"539257\"]"); + let err_result = totp_generate_tolerance("66", 0, None); + assert!(err_result.is_err()); + } } diff --git a/src/http.rs b/src/http.rs index 28c8345e..8b72f0fe 100644 --- a/src/http.rs +++ b/src/http.rs @@ -9,7 +9,9 @@ use std::io::Write; #[derive(Deserialize)] struct RequestOptions { + #[serde(default)] output_filename: Option, + #[serde(default)] body_filename: Option, } @@ -22,8 +24,8 @@ struct Response<'a> { // If the response can be deserialized -> success. // If the response can't be deserialized -> failure. -byond_fn! { http_request_blocking(method, url, body, headers, ...rest) { - let req = match construct_request(method, url, body, headers, rest.first().map(|x| &**x)) { +byond_fn!(fn http_request_blocking(method, url, body, headers, options) { + let req = match construct_request(method, url, body, headers, options) { Ok(r) => r, Err(e) => return Some(e.to_string()) }; @@ -32,11 +34,11 @@ byond_fn! { http_request_blocking(method, url, body, headers, ...rest) { Ok(r) => Some(r), Err(e) => Some(e.to_string()) } -} } +}); // Returns new job-id. -byond_fn! { http_request_async(method, url, body, headers, ...rest) { - let req = match construct_request(method, url, body, headers, rest.first().map(|x| &**x)) { +byond_fn!(fn http_request_async(method, url, body, headers, options) { + let req = match construct_request(method, url, body, headers, options) { Ok(r) => r, Err(e) => return Some(e.to_string()) }; @@ -47,13 +49,13 @@ byond_fn! { http_request_async(method, url, body, headers, ...rest) { Err(e) => e.to_string() } })) -} } +}); // If the response can be deserialized -> success. // If the response can't be deserialized -> failure or WIP. -byond_fn! { http_check_request(id) { +byond_fn!(fn http_check_request(id) { Some(jobs::check(id)) -} } +}); // ---------------------------------------------------------------------------- // Shared HTTP client state @@ -91,7 +93,7 @@ fn construct_request( url: &str, body: &str, headers: &str, - options: Option<&str>, + options: &str, ) -> Result { let mut req = match method { "post" => HTTP_CLIENT.post(url), @@ -114,7 +116,7 @@ fn construct_request( } let mut output_filename = None; - if let Some(options) = options { + if !options.is_empty() { let options: RequestOptions = serde_json::from_str(options)?; output_filename = options.output_filename; if let Some(fname) = options.body_filename { @@ -146,7 +148,7 @@ fn submit_request(prep: RequestPrep) -> Result { } if let Some(output_filename) = prep.output_filename { - let mut writer = std::io::BufWriter::new(std::fs::File::create(&output_filename)?); + let mut writer = std::io::BufWriter::new(std::fs::File::create(output_filename)?); std::io::copy(&mut response, &mut writer)?; writer.flush()?; } else { diff --git a/src/json.rs b/src/json.rs index 2185e9d6..db75d967 100644 --- a/src/json.rs +++ b/src/json.rs @@ -3,14 +3,14 @@ use std::cmp; const VALID_JSON_MAX_RECURSION_DEPTH: usize = 8; -byond_fn! { json_is_valid(text) { +byond_fn!(fn json_is_valid(text) { let value = match serde_json::from_str::(text) { Ok(value) => value, Err(_) => return Some("false".to_owned()) }; Some(get_recursion_level(&value).is_ok().to_string()) -} } +}); /// Gets the recursion level of the given value /// If it is above VALID_JSON_MAX_RECURSION_DEPTH, returns Err(()) diff --git a/src/lib.rs b/src/lib.rs index b2c779ad..bbe40556 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + #[macro_use] mod byond; #[allow(dead_code)] @@ -6,6 +8,12 @@ mod error; #[cfg(feature = "jobs")] mod jobs; +#[cfg(feature = "acreplace")] +pub mod acreplace; +#[cfg(feature = "cellularnoise")] +pub mod cellularnoise; +#[cfg(feature = "dbpnoise")] +pub mod dbpnoise; #[cfg(feature = "dmi")] pub mod dmi; #[cfg(feature = "file")] @@ -22,14 +30,22 @@ pub mod json; pub mod log; #[cfg(feature = "noise")] pub mod noise_gen; +#[cfg(feature = "pathfinder")] +pub mod pathfinder; +#[cfg(feature = "redis_pubsub")] +pub mod redis_pubsub; #[cfg(feature = "sql")] pub mod sql; -#[cfg(feature = "url")] -pub mod url; +#[cfg(feature = "time")] +pub mod time; +#[cfg(feature = "toml")] +pub mod toml; #[cfg(feature = "unzip")] pub mod unzip; -#[cfg(feature = "cellularnoise")] -pub mod cellularnoise; +#[cfg(feature = "url")] +pub mod url; +#[cfg(feature = "worleynoise")] +pub mod worleynoise; #[cfg(not(target_pointer_width = "32"))] compile_error!("rust-g must be compiled for a 32-bit target"); diff --git a/src/log.rs b/src/log.rs index 41e86aac..de45fc0b 100644 --- a/src/log.rs +++ b/src/log.rs @@ -14,11 +14,11 @@ thread_local! { static FILE_MAP: RefCell> = RefCell::new(HashMap::new()); } -byond_fn! { log_write(path, data, ...rest) { +byond_fn!(fn log_write(path, data, ...rest) { FILE_MAP.with(|cell| -> Result<()> { // open file let mut map = cell.borrow_mut(); - let path = Path::new(&path as &str); + let path = Path::new(path as &str); let file = match map.entry(path.into()) { Entry::Occupied(elem) => elem.into_mut(), Entry::Vacant(elem) => elem.insert(open(path)?), @@ -31,26 +31,28 @@ byond_fn! { log_write(path, data, ...rest) { // write first line, timestamped let mut iter = data.split('\n'); if let Some(line) = iter.next() { - write!(file, "[{}] {}\n", Utc::now().format("%F %T%.3f"), line)?; + writeln!(file, "[{}] {}", Utc::now().format("%F %T%.3f"), line)?; } // write remaining lines for line in iter { - write!(file, " - {}\n", line)?; + writeln!(file, " - {}", line)?; } } Ok(()) }).err() -} } - -byond_fn! { log_close_all() { - FILE_MAP.with(|cell| { - let mut map = cell.borrow_mut(); - map.clear(); - }); - Some("") -} } +}); + +byond_fn!( + fn log_close_all() { + FILE_MAP.with(|cell| { + let mut map = cell.borrow_mut(); + map.clear(); + }); + Some("") + } +); fn open(path: &Path) -> Result { if let Some(parent) = path.parent() { diff --git a/src/noise_gen.rs b/src/noise_gen.rs index 0b97eb48..d97a17e9 100644 --- a/src/noise_gen.rs +++ b/src/noise_gen.rs @@ -1,4 +1,4 @@ -use noise::{NoiseFn, Perlin, Seedable}; +use noise::{NoiseFn, Perlin}; use std::{ cell::RefCell, collections::hash_map::{Entry, HashMap}, @@ -10,9 +10,9 @@ thread_local! { static GENERATORS: RefCell> = RefCell::new(HashMap::new()); } -byond_fn! { noise_get_at_coordinates(seed, x, y) { +byond_fn!(fn noise_get_at_coordinates(seed, x, y) { get_at_coordinates(seed, x, y).ok() -} } +}); //note that this will be 0 at integer x & y, scaling is left up to the caller fn get_at_coordinates(seed_as_str: &str, x_as_str: &str, y_as_str: &str) -> Result { @@ -25,7 +25,7 @@ fn get_at_coordinates(seed_as_str: &str, x_as_str: &str, y_as_str: &str) -> Resu Entry::Occupied(ref mut occ) => occ.get_mut(), Entry::Vacant(vac) => { let seed = seed_as_str.parse::()?; - let perlin = Perlin::new().set_seed(seed); + let perlin = Perlin::new(seed); vac.insert(perlin) } }; diff --git a/src/pathfinder.rs b/src/pathfinder.rs new file mode 100644 index 00000000..395c40d3 --- /dev/null +++ b/src/pathfinder.rs @@ -0,0 +1,281 @@ +use num::integer::sqrt; +use pathfinding::prelude::astar; +use serde::{Deserialize, Serialize}; +use std::cell::RefCell; +use std::hash::Hash; +use std::num::ParseIntError; +use std::rc::Rc; +use thiserror::Error; + +thread_local! { +static NODES: RefCell>>> = RefCell::new(Vec::new()); +} + +fn get_nodes_len() -> usize { + NODES.with(|nodes_ref| nodes_ref.borrow().len()) +} + +fn get_node(id: usize) -> Option>> { + NODES.with(|nodes_ref| nodes_ref.borrow().get(id).cloned()) +} + +fn push_node(node: Node) { + NODES.with(|nodes_ref| nodes_ref.borrow_mut().push(Some(Rc::new(node)))); +} + +fn null_out_node(id: usize) { + NODES.with(|nodes_ref| nodes_ref.borrow_mut()[id] = None); +} + +// Container for a node. Exist mainly to be able to implement Hash, which is not implemented for RefCell +#[derive(Serialize, Deserialize, Default, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +struct Node { + // A unique id that acts as its index in NODES + unique_id: usize, + // Position of the node in byond + x: usize, + y: usize, + z: usize, + // Indexes of nodes connected to this one + connected_nodes_id: Vec, +} + +impl Node { + // Return a vector of all connected nodes, encapsulated in a NodeContainer. + fn successors(&self) -> Vec<(Rc, usize)> { + self.connected_nodes_id + .iter() + .filter_map(|index| get_node(*index)) + .flatten() + .map(|node| (node.clone(), self.distance(node.as_ref()))) + .collect() + } + + // Return the geometric distance between this node and another one. + fn distance(&self, other: &Self) -> usize { + sqrt( + ((self.x as isize - other.x as isize).pow(2) + + (self.y as isize - other.y as isize).pow(2)) as usize, + ) + } +} + +#[derive(Error, Debug)] +enum RegisteringNodesError { + #[error(transparent)] + Serialization(#[from] serde_json::Error), + #[error("Nodes were not correctly indexed")] + NodesNotCorrectlyIndexed, +} + +byond_fn!(fn register_nodes_astar(json) { + match register_nodes(json) { Ok(s) => Some(s), + Err(e) => Some(format!("{e}")) + } +}); + +// Builds a list of nodes from a json file. +// Errors if the input list of nodes is not correctly indexed. Each node should have for unique id its position in the list, with the first unique-id being 0. +fn register_nodes(json: &str) -> Result { + let deserialized_nodes: Vec = serde_json::from_str(json)?; + if deserialized_nodes + .iter() + .enumerate() + .filter(|(i, node)| i != &node.unique_id) + .count() + != 0 + { + return Err(RegisteringNodesError::NodesNotCorrectlyIndexed); + } + + deserialized_nodes.into_iter().for_each(push_node); + + Ok("1".to_string()) +} + +byond_fn!(fn add_node_astar(json) { + match add_node(json) { + Ok(s) => Some(s), + Err(e) => Some(format!("{e}")) + } +}); + +// Add a node to the static list of node. +// If it is connected to other existing nodes, it will update their connected_nodes_id list. +fn add_node(json: &str) -> Result { + let new_node: Node = serde_json::from_str(json)?; + + // As always, a node unique id should correspond to its index in NODES + if new_node.unique_id != get_nodes_len() { + return Err(RegisteringNodesError::NodesNotCorrectlyIndexed); + } + + // Make sure every connection we have we other nodes is 2 ways + for index in new_node.connected_nodes_id.iter() { + NODES.with(|nodes_ref| { + if let Some(Some(node)) = nodes_ref.borrow_mut().get_mut(*index) { + Rc::get_mut(node) + .unwrap() + .connected_nodes_id + .push(new_node.unique_id) + } + }) + } + + push_node(new_node); + + Ok("1".to_string()) +} + +#[derive(Error, Debug)] +enum DeleteNodeError { + #[error(transparent)] + ParsingError(ParseIntError), + #[error("Node was not found")] + NodeNotFound, +} + +byond_fn!(fn remove_node_astar(unique_id) { + match remove_node(unique_id) { + Ok(s) => Some(s), + Err(e) => Some(format!("{e}")) + } +}); + +// Replace the node with unique_id by None +// Update connected nodes as well so nothing target the removed node anymore +// Errors if no node can be found with unique_id +fn remove_node(unique_id: &str) -> Result { + let unique_id = match unique_id.parse::() { + Ok(id) => id, + Err(e) => return Err(DeleteNodeError::ParsingError(e)), + }; + + let node_to_delete = match get_node(unique_id) { + Some(Some(node)) => node, + _ => return Err(DeleteNodeError::NodeNotFound), + }; + + for index in node_to_delete.connected_nodes_id.iter() { + NODES.with(|nodes_ref| { + if let Some(Some(node)) = nodes_ref.borrow_mut().get_mut(*index) { + Rc::get_mut(node) + .unwrap() + .connected_nodes_id + .retain(|index| index != &node_to_delete.unique_id); + } + }) + } + + null_out_node(unique_id); + + Ok("1".to_string()) +} + +#[derive(Error, Debug)] +enum AstarError { + #[error("Starting node not found")] + StartNodeNotFound, + #[error("Goal node not found")] + GoalNodeNotFound, + #[error("No path found")] + NoPath, +} + +byond_fn!(fn generate_path_astar(start_node_id, goal_node_id) { + if let (Ok(start_node_id), Ok(goal_node_id)) = (start_node_id.parse::(), goal_node_id.parse::()) { + match generate_path(start_node_id, goal_node_id) { + Ok(vector) => Some(match serde_json::to_string(&vector) { + Ok(s) => s, + Err(_) => "Cannot serialize path".to_string(), + }), + Err(e) => Some(format!("{e}")) + } + } + else { + Some("Invalid arguments".to_string()) + } +}); + +// Compute the shortest path between start node and goal node using A* +fn generate_path(start_node_id: usize, goal_node_id: usize) -> Result, AstarError> { + let start_node = match get_node(start_node_id) { + Some(Some(node)) => node, + _ => return Err(AstarError::StartNodeNotFound), + }; + + let goal_node = match get_node(goal_node_id) { + Some(Some(node)) => node, + _ => return Err(AstarError::GoalNodeNotFound), + }; + + if goal_node.z != start_node.z { + return Err(AstarError::NoPath); + } + + // Compute the shortest path between start node and goal node using A* + let path = astar( + &start_node, + |node| node.successors(), + |node| node.distance(&goal_node), + |node| node.distance(&goal_node) == 0, + ); + + // Extract a vector of node container from the path variable. Errors if no path was found + let path = match path { + None => return Err(AstarError::NoPath), + Some(path) => path.0, + }; + + // Map every nodecontainer to the unique id of its node, so it can be sent to byond + Ok(path + .into_iter() + .map(|node| node.unique_id) + .rev() // Reverse iterator so it is easy to pop the list in byond + .collect()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_register() { + let json = std::fs::read_to_string("tests/rsc/ai_nodes_info.json").unwrap(); + assert!(register_nodes(&json).is_ok()); + assert!(NODES.with(|nodes_ref| nodes_ref.borrow().len() != 0)) + } + + #[test] + fn test_add_node() { + let json = std::fs::read_to_string("tests/rsc/ai_nodes_info.json").unwrap(); + assert!(register_nodes(&json).is_ok()); + let mut node_to_add = NODES + .with(|nodes_ref| nodes_ref.borrow().get(18).cloned()) + .unwrap() + .unwrap() + .as_ref() + .clone(); + let initial_len = NODES.with(|nodes_ref| nodes_ref.borrow().len()); + + node_to_add.unique_id = initial_len; + assert!(add_node(&serde_json::to_string(&node_to_add).unwrap()).is_ok()); + assert!(initial_len == NODES.with(|nodes_ref| nodes_ref.borrow().len() - 1)); + } + + #[test] + fn test_remove_node() { + let json = std::fs::read_to_string("tests/rsc/ai_nodes_info.json").unwrap(); + assert!(register_nodes(&json).is_ok()); + + assert!(remove_node("11").is_ok()); + assert!(NODES.with(|nodes_ref| nodes_ref.borrow().get(11).unwrap().is_none())) + } + + #[test] + fn test_pathfinding() { + let json = std::fs::read_to_string("tests/rsc/ai_nodes_info.json").unwrap(); + assert!(register_nodes(&json).is_ok()); + assert!(generate_path(10, 25).is_ok()); + } +} diff --git a/src/redis_pubsub.rs b/src/redis_pubsub.rs new file mode 100644 index 00000000..97d3d0da --- /dev/null +++ b/src/redis_pubsub.rs @@ -0,0 +1,179 @@ +use redis::{Client, Commands, RedisError}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::thread; +use std::time::Duration; + +const ERROR_CHANNEL: &str = "RUSTG_REDIS_ERROR_CHANNEL"; + +thread_local! { + static REQUEST_SENDER: RefCell>> = RefCell::new(None); + static RESPONSE_RECEIVER: RefCell>> = RefCell::new(None); +} + +enum PubSubRequest { + Subscribe(String), + Publish(String, String), +} + +// response might not be a good name, since those are not sent in response to requests +enum PubSubResponse { + Disconnected(String), + Message(String, String), +} + +fn handle_redis_inner( + client: Client, + control: &flume::Receiver, + out: &flume::Sender, +) -> Result<(), RedisError> { + let mut conn = client.get_connection()?; + let mut pub_conn = client.get_connection()?; + let mut pubsub = conn.as_pubsub(); + pubsub.set_read_timeout(Some(Duration::from_secs(1)))?; + + loop { + loop { + match control.try_recv() { + Ok(req) => match req { + PubSubRequest::Subscribe(channel) => { + pubsub.subscribe(&[channel.as_str()])?; + } + PubSubRequest::Publish(channel, message) => { + pub_conn.publish(&channel, &message)?; + } + }, + Err(flume::TryRecvError::Empty) => break, + Err(flume::TryRecvError::Disconnected) => return Ok(()), + } + } + + if let Some(msg) = match pubsub.get_message() { + Ok(msg) => Some(msg), + Err(e) => { + if e.is_timeout() { + None + } else { + return Err(e); + } + } + } { + let chan = msg.get_channel_name().to_owned(); + let data: String = msg.get_payload().unwrap_or_default(); + if let Err(flume::TrySendError::Disconnected(_)) = + out.try_send(PubSubResponse::Message(chan, data)) + { + return Ok(()); // If no one wants to receive any more messages from us, we exit this thread + } + } + } +} + +fn handle_redis( + client: Client, + control: flume::Receiver, + out: flume::Sender, +) { + if let Err(e) = handle_redis_inner(client, &control, &out) { + let _ = out.send(PubSubResponse::Disconnected(e.to_string())); + } +} + +fn connect(addr: &str) -> Result<(), RedisError> { + let client = redis::Client::open(addr)?; + let _ = client.get_connection_with_timeout(Duration::from_secs(1))?; + let (c_sender, c_receiver) = flume::bounded(1000); + let (o_sender, o_receiver) = flume::bounded(1000); + REQUEST_SENDER.with(|cell| cell.replace(Some(c_sender))); + RESPONSE_RECEIVER.with(|cell| cell.replace(Some(o_receiver))); + thread::spawn(|| handle_redis(client, c_receiver, o_sender)); + Ok(()) +} + +fn disconnect() { + // Dropping the sender and receiver will cause the other thread to exit + REQUEST_SENDER.with(|cell| { + cell.replace(None); + }); + RESPONSE_RECEIVER.with(|cell| { + cell.replace(None); + }); +} + +// It's lame as hell to use strings as errors, but I don't feel like +// making a whole new type encompassing possible errors, since we're returning a string +// to BYOND anyway. +fn subscribe(channel: &str) -> Option { + REQUEST_SENDER.with(|cell| { + if let Some(chan) = cell.borrow_mut().as_ref() { + chan.try_send(PubSubRequest::Subscribe(channel.to_owned())) + .err() + .map(|e| e.to_string()) + } else { + Some("Not connected".to_owned()) + } + }) +} + +fn publish(channel: &str, msg: &str) -> Option { + REQUEST_SENDER.with(|cell| { + if let Some(chan) = cell.borrow_mut().as_ref() { + chan.try_send(PubSubRequest::Publish(channel.to_owned(), msg.to_owned())) + .err() + .map(|e| e.to_string()) + } else { + Some("Not connected".to_owned()) + } + }) +} + +fn get_messages() -> String { + let mut result: HashMap> = HashMap::new(); + + RESPONSE_RECEIVER.with(|cell| { + let opt = cell.borrow_mut(); + if let Some(recv) = opt.as_ref() { + for resp in recv.try_iter() { + match resp { + PubSubResponse::Message(chan, msg) => { + result.entry(chan).or_default().push(msg); + } + PubSubResponse::Disconnected(error) => { + // Pardon the in-band signaling but it's probably the best way to do this + result + .entry(ERROR_CHANNEL.to_owned()) + .or_default() + .push(error); + } + } + } + } + }); + + serde_json::to_string(&result).unwrap_or_else(|_| "{}".to_owned()) +} + +byond_fn!(fn redis_connect(addr) { + connect(addr).err().map(|e| e.to_string()) +}); + +byond_fn!( + fn redis_disconnect() { + disconnect(); + Some("") + } +); + +byond_fn!(fn redis_subscribe(channel) { + subscribe(channel) +}); + +byond_fn!( + fn redis_get_messages() { + Some(get_messages()) + } +); + +byond_fn!(fn redis_publish(channel, message) { + publish(channel, message) +}); diff --git a/src/sql.rs b/src/sql.rs index 9312540c..90b9f4ff 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -32,7 +32,7 @@ struct ConnectOptions { max_threads: Option, } -byond_fn! { sql_connect_pool(options) { +byond_fn!(fn sql_connect_pool(options) { let options = match serde_json::from_str::(options) { Ok(options) => options, Err(e) => return Some(err_to_json(e)), @@ -41,16 +41,16 @@ byond_fn! { sql_connect_pool(options) { Ok(o) => o.to_string(), Err(e) => err_to_json(e) }) -} } +}); -byond_fn! { sql_query_blocking(handle, query, params) { +byond_fn!(fn sql_query_blocking(handle, query, params) { Some(match do_query(handle, query, params) { Ok(o) => o.to_string(), Err(e) => err_to_json(e) }) -} } +}); -byond_fn! { sql_query_async(handle, query, params) { +byond_fn!(fn sql_query_async(handle, query, params) { let handle = handle.to_owned(); let query = query.to_owned(); let params = params.to_owned(); @@ -60,10 +60,10 @@ byond_fn! { sql_query_async(handle, query, params) { Err(e) => err_to_json(e) } })) -} } +}); // hopefully won't panic if queries are running -byond_fn! { sql_disconnect_pool(handle) { +byond_fn!(fn sql_disconnect_pool(handle) { let handle = match handle.parse::() { Ok(o) => o, Err(e) => return Some(err_to_json(e)), @@ -80,9 +80,9 @@ byond_fn! { sql_disconnect_pool(handle) { }).to_string() } ) -} } +}); -byond_fn! { sql_connected(handle) { +byond_fn!(fn sql_connected(handle) { let handle = match handle.parse::() { Ok(o) => o, Err(e) => return Some(err_to_json(e)), @@ -97,11 +97,11 @@ byond_fn! { sql_connected(handle) { }).to_string() } ) -} } +}); -byond_fn! { sql_check_query(id) { +byond_fn!(fn sql_check_query(id) { Some(jobs::check(id)) -} } +}); // ---------------------------------------------------------------------------- // Main connect and query implementation @@ -168,7 +168,7 @@ fn do_query(handle: &str, query: &str, params: &str) -> Result match ctype { MYSQL_TYPE_VARCHAR | MYSQL_TYPE_STRING | MYSQL_TYPE_VAR_STRING => { - serde_json::Value::String(String::from_utf8_lossy(&b).into_owned()) + serde_json::Value::String(String::from_utf8_lossy(b).into_owned()) } MYSQL_TYPE_BLOB | MYSQL_TYPE_LONG_BLOB @@ -181,7 +181,7 @@ fn do_query(handle: &str, query: &str, params: &str) -> Result serde_json::Value::Null, diff --git a/src/time.rs b/src/time.rs new file mode 100644 index 00000000..f27b9ddb --- /dev/null +++ b/src/time.rs @@ -0,0 +1,49 @@ +use std::{ + cell::RefCell, + collections::hash_map::{Entry, HashMap}, + time::Instant, +}; + +thread_local!( static INSTANTS: RefCell> = RefCell::new(HashMap::new()) ); + +byond_fn!(fn time_microseconds(instant_id) { + INSTANTS.with(|instants| { + let mut map = instants.borrow_mut(); + let instant = match map.entry(instant_id.into()) { + Entry::Occupied(elem) => elem.into_mut(), + Entry::Vacant(elem) => elem.insert(Instant::now()), + }; + Some(instant.elapsed().as_micros().to_string()) + }) +}); + +byond_fn!(fn time_milliseconds(instant_id) { + INSTANTS.with(|instants| { + let mut map = instants.borrow_mut(); + let instant = match map.entry(instant_id.into()) { + Entry::Occupied(elem) => elem.into_mut(), + Entry::Vacant(elem) => elem.insert(Instant::now()), + }; + Some(instant.elapsed().as_millis().to_string()) + }) +}); + +byond_fn!(fn time_reset(instant_id) { + INSTANTS.with(|instants| { + let mut map = instants.borrow_mut(); + map.insert(instant_id.into(), Instant::now()); + Some("") + }) +}); + +byond_fn!( + fn unix_timestamp() { + Some( + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs_f64() + .to_string(), + ) + } +); diff --git a/src/toml.rs b/src/toml.rs new file mode 100644 index 00000000..09faf25c --- /dev/null +++ b/src/toml.rs @@ -0,0 +1,42 @@ +use crate::error::Result; + +byond_fn!(fn toml_file_to_json(path) { + serde_json::to_string( + &match toml_file_to_json_impl(path) { + Ok(value) => serde_json::json!({ + "success": true, "content": value + }), + Err(error) => serde_json::json!({ + "success": false, "content": error.to_string() + }), + } + ).ok() +}); + +fn toml_file_to_json_impl(path: &str) -> Result { + Ok(serde_json::to_string(&toml_dep::from_str::< + toml_dep::Value, + >(&std::fs::read_to_string( + path, + )?)?)?) +} + +byond_fn!(fn toml_encode(value) { + serde_json::to_string( + &match toml_encode_impl(value) { + Ok(value) => serde_json::json!({ + "success": true, "content": value + }), + + Err(error) => serde_json::json!({ + "success": false, "content": error.to_string() + }), + } + ).ok() +}); + +fn toml_encode_impl(value: &str) -> Result { + Ok(toml_dep::to_string_pretty(&serde_json::from_str::< + toml_dep::Value, + >(value)?)?) +} diff --git a/src/unzip.rs b/src/unzip.rs index 48a17a76..16b5009a 100644 --- a/src/unzip.rs +++ b/src/unzip.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, jobs, http::HTTP_CLIENT}; +use crate::{error::Result, http::HTTP_CLIENT, jobs}; use reqwest::blocking::RequestBuilder; use std::fs; use std::io::Write; @@ -10,26 +10,22 @@ struct UnzipPrep { unzip_directory: String, } -fn construct_unzip( - url: &str, - unzip_directory: &str -) -> UnzipPrep { - +fn construct_unzip(url: &str, unzip_directory: &str) -> UnzipPrep { let req = HTTP_CLIENT.get(url); let dir_copy = unzip_directory.to_string(); - + UnzipPrep { req, unzip_directory: dir_copy, } } -byond_fn! { unzip_download_async(url, unzip_directory) { - let unzip = construct_unzip(&url, &unzip_directory); +byond_fn!(fn unzip_download_async(url, unzip_directory) { + let unzip = construct_unzip(url, unzip_directory); Some(jobs::start(move || do_unzip_download(unzip).unwrap_or_else(|e| e.to_string()) )) -} } +}); fn do_unzip_download(prep: UnzipPrep) -> Result { let unzip_path = Path::new(&prep.unzip_directory); @@ -40,12 +36,11 @@ fn do_unzip_download(prep: UnzipPrep) -> Result { let reader = std::io::Cursor::new(content); let mut archive = ZipArchive::new(reader)?; - for i in 0..archive.len() - { + for i in 0..archive.len() { let mut entry = archive.by_index(i)?; let file_path = unzip_path.join(entry.name()); - + if let Some(parent) = file_path.parent() { fs::create_dir_all(parent)? } @@ -63,6 +58,6 @@ fn do_unzip_download(prep: UnzipPrep) -> Result { Ok("true".to_string()) } -byond_fn! { unzip_check(id) { +byond_fn!(fn unzip_check(id) { Some(jobs::check(id)) -} } +}); diff --git a/src/url.rs b/src/url.rs index be2179e1..177cbd40 100644 --- a/src/url.rs +++ b/src/url.rs @@ -2,13 +2,13 @@ use crate::error::Result; use std::borrow::Cow; use url_dep::form_urlencoded::byte_serialize; -byond_fn! { url_encode(data) { +byond_fn!(fn url_encode(data) { Some(encode(data)) -} } +}); -byond_fn! { url_decode(data) { +byond_fn!(fn url_decode(data) { decode(data).ok() -} } +}); fn encode(string: &str) -> String { byte_serialize(string.as_bytes()).collect() diff --git a/src/worleynoise.rs b/src/worleynoise.rs new file mode 100644 index 00000000..0995ae61 --- /dev/null +++ b/src/worleynoise.rs @@ -0,0 +1,255 @@ +use crate::error::Result; +use core::panic; +use rand::prelude::*; +use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}; +use std::fmt::Write; +use std::{ + collections::HashSet, + sync::{Arc, RwLock}, +}; + +byond_fn!(fn worley_generate(region_size, threshold, node_per_region_chance, size, node_min, node_max) { + worley_noise(region_size, threshold, node_per_region_chance, size, node_min, node_max).ok() +}); + +const RANGE: usize = 4; + +// This is a quite complex algorithm basically what it does is it creates 2 maps, one filled with cells and the other with 'regions' that map onto these cells. +// Each region can spawn 1 node, the cell then determines wether it is true or false depending on the distance from it to the nearest node in the region minus the second closest node. +// If this distance is greater than the threshold then the cell is true, otherwise it is false. +fn worley_noise( + str_reg_size: &str, + str_positive_threshold: &str, + str_node_per_region_chance: &str, + str_size: &str, + str_node_min: &str, + str_node_max: &str, +) -> Result { + let region_size = str_reg_size.parse::()?; + let positive_threshold = str_positive_threshold.parse::()?; + let size = str_size.parse::()?; + let node_per_region_chance = str_node_per_region_chance.parse::()?; + let node_min = str_node_min.parse::()?; + let node_max = str_node_max.parse::()?; + + let world_size = (size as f32 / region_size as f32).ceil() as i32; + + let mut map = NoiseCellMap::new(region_size, world_size) + .node_fill(node_min, node_max, node_per_region_chance) + .worley_fill(positive_threshold)?; + + map.truncate(size); + map.par_iter_mut().for_each(|row| { + row.truncate(size); + }); + + let mut output = String::new(); + + for row in map { + for cell in row { + if cell { + let _ = write!(output, "1"); + } else { + let _ = write!(output, "0"); + } + } + } + Ok(output) +} +struct NoiseCellMap { + reg_vec: Vec>, + reg_size: i32, + reg_amt: i32, +} + +impl NoiseCellMap { + fn new(reg_size: i32, reg_amt: i32) -> Self { + let mut noise_cell_map = NoiseCellMap { + reg_vec: Vec::new(), + reg_size, + reg_amt, + }; + for x in 0..reg_amt { + noise_cell_map.reg_vec.push(Vec::new()); + for y in 0..reg_amt { + noise_cell_map.reg_vec[x as usize].push(NoiseCellRegion::new((x, y), reg_size)); + } + } + noise_cell_map + } + + fn node_fill(&mut self, mut node_min: u32, mut node_max: u32, node_chance: usize) -> &mut Self { + node_min = node_min.max(1); + node_max = node_min.max(node_max); + let node_counter: Arc> = Arc::new(RwLock::new(0)); + let reg_size = self.reg_size; + self.reg_vec.par_iter_mut().flatten().for_each(|region| { + let mut rng = ThreadRng::default(); + // basically, to make sure the algorithm works optimally or rather works at all without panicing we have to ensure we spawn at least some nodes + // this amount of nodes scales inversely to range. + { + let mut write_guard = node_counter.write().unwrap(); + if (*write_guard < RANGE) && rng.gen_range(0..100) > node_chance { + *write_guard += 1; + return; + } + *write_guard = 0; + } + + let amt = rng.gen_range(node_min..node_max); + for _ in 0..amt { + let coord = (rng.gen_range(0..reg_size), rng.gen_range(0..reg_size)); + region.insert_node(coord); + } + }); + self + } + + fn get_nodes_in_range(&self, centre: (i32, i32), range: i32) -> HashSet<(i32, i32)> { + let mut v = HashSet::new(); + for x in centre.0 - range..centre.0 + range { + if x < 0 || x >= self.reg_amt { + continue; + } + for y in centre.1 - range..centre.1 + range { + if y < 0 || y >= self.reg_amt { + continue; + } + v.extend( + self.reg_vec[x as usize][y as usize] + .get_nodes() + .iter() + .cloned(), + ) + } + } + v + } + + fn worley_fill(&mut self, threshold: f32) -> Result>> { + let new_data = self + .reg_vec + .par_iter() + .flatten() + .map(|region| { + let mut edit_region = region.clone(); + let mut nodes_in_range = + self.get_nodes_in_range(region.reg_coordinates, RANGE as i32); + { + let mut i = 1; + while nodes_in_range.len() < 2 { + i += 1; + nodes_in_range = + self.get_nodes_in_range(region.reg_coordinates, (i + RANGE) as i32); + if i > 32 { + panic!("Not enough nodes in range!"); + } + } + } + for x in 0..region.reg_size { + for y in 0..region.reg_size { + edit_region.cell_vec[x as usize][y as usize] = (get_nth_smallest_dist( + region.to_global_coordinates((x, y)), + 1, + &nodes_in_range, + ) - get_nth_smallest_dist( + region.to_global_coordinates((x, y)), + 0, + &nodes_in_range, + )) > threshold; + } + } + edit_region + }) + .collect::>(); + let mut final_vec: Vec> = Vec::new(); + for x in 0..self.reg_amt * self.reg_size { + final_vec.push(Vec::new()); + for _ in 0..self.reg_amt * self.reg_size { + final_vec[x as usize].push(false); + } + } + new_data.into_iter().for_each(|reg| { + for x in 0..reg.reg_size { + for y in 0..reg.reg_size { + let g_coords = reg.to_global_coordinates((x, y)); + final_vec[g_coords.0 as usize][g_coords.1 as usize] = + reg.cell_vec[x as usize][y as usize]; + } + } + }); + Ok(final_vec) + } +} +#[derive(Debug, Clone)] +struct NoiseCellRegion { + cell_vec: Vec>, + node_set: HashSet<(i32, i32)>, + reg_coordinates: (i32, i32), + reg_size: i32, +} + +impl NoiseCellRegion { + fn new(reg_coordinates: (i32, i32), reg_size: i32) -> Self { + let mut noise_cell_region = NoiseCellRegion { + cell_vec: Vec::new(), + node_set: HashSet::new(), + reg_coordinates, + reg_size, + }; + for x in 0..reg_size { + noise_cell_region.cell_vec.push(Vec::new()); + for _ in 0..reg_size { + noise_cell_region.cell_vec[x as usize].push(false); + } + } + noise_cell_region + } + + fn insert_node(&mut self, node: (i32, i32)) { + self.node_set.insert(node); + } + + fn to_global_coordinates(&self, coord: (i32, i32)) -> (i32, i32) { + let mut c = (0, 0); + c.0 = coord.0 + self.reg_coordinates.0 * self.reg_size; + c.1 = coord.1 + self.reg_coordinates.1 * self.reg_size; + c + } + + fn get_nodes(&self) -> Vec<(i32, i32)> { + self.node_set + .clone() + .into_iter() + .map(|x| self.to_global_coordinates(x)) + .collect() + } +} + +fn sqr_distance(p1: (i32, i32), p2: (i32, i32)) -> f32 { + (((p1.0 - p2.0).pow(2) + (p1.1 - p2.1).pow(2)) as f32).sqrt() +} + +fn mht_distance(p1: (i32, i32), p2: (i32, i32)) -> f32 { + ((p1.0 - p2.0).abs() + (p1.1 - p2.1).abs()) as f32 +} + +fn get_smallest_dist(centre: (i32, i32), set: &HashSet<(i32, i32)>) -> (i32, i32) { + set.iter() + .min_by(|a, b| { + mht_distance(**a, centre) + .partial_cmp(&mht_distance(**b, centre)) + .expect("Found NAN somehow") + }) + .cloned() + .expect("No minimum found") +} + +fn get_nth_smallest_dist(centre: (i32, i32), mut nth: u32, set: &HashSet<(i32, i32)>) -> f32 { + let mut our_set = set.clone(); + while nth > 0 && set.len() > 1 { + our_set.remove(&get_smallest_dist(centre, &our_set)); + nth -= 1; + } + sqr_distance(centre, get_smallest_dist(centre, &our_set)) +} diff --git a/tests/abc-tests.rs b/tests/abc-tests.rs new file mode 100644 index 00000000..763e8f5d --- /dev/null +++ b/tests/abc-tests.rs @@ -0,0 +1,67 @@ +extern crate regex; +use regex::{CaptureMatches, RegexBuilder}; +use std::cmp::Ordering; + +fn are_captures_sorted(matches: CaptureMatches, context: &str) -> Result<(), String> { + let mut prev_string = ""; + for cap in matches { + let capstring = cap.get(0).unwrap().as_str(); + match prev_string.cmp(capstring) { + Ordering::Greater => { + return Err(format!("{} is not sorted in {}", &capstring, &context)) + } + _ => { + prev_string = capstring; + } + }; + } + Ok(()) +} + +#[test] +fn test_readme() -> Result<(), String> { + let readme = std::fs::read_to_string("README.md").unwrap(); + let blocksre = RegexBuilder::new(r"^The default features are:\r?\n((:?^.+?\r?\n)*)\r?\nAdditional features are:\r?\n((:?^.+?\r?\n)*)").multi_line(true).build().unwrap(); + let linesre = RegexBuilder::new(r"^\*(.+?)$") + .multi_line(true) + .build() + .unwrap(); + let blocks = blocksre.captures(&readme).unwrap(); + are_captures_sorted( + linesre.captures_iter(blocks.get(1).unwrap().as_str()), + "README.md default features", + )?; + are_captures_sorted( + linesre.captures_iter(blocks.get(3).unwrap().as_str()), + "README.md additional features", + ) +} + +#[test] +fn test_librs() -> Result<(), String> { + let librs = std::fs::read_to_string("src/lib.rs").unwrap(); + let modsre = RegexBuilder::new(r"(^pub mod .+?$)") + .multi_line(true) + .build() + .unwrap(); + are_captures_sorted(modsre.captures_iter(&librs), "lib.rs") +} + +#[test] +fn test_cargotoml() -> Result<(), String> { + let cargotoml = std::fs::read_to_string("Cargo.toml").unwrap(); + let blocksre = RegexBuilder::new(r"^# default features\r?\n((:?^.+?\r?\n)*)\r?\n# additional features\r?\n((:?^.+?\r?\n)*)\r?\n#").multi_line(true).build().unwrap(); + let linesre = RegexBuilder::new(r"^(\w.+?)$") + .multi_line(true) + .build() + .unwrap(); + let blocks = blocksre.captures(&cargotoml).unwrap(); + are_captures_sorted( + linesre.captures_iter(blocks.get(1).unwrap().as_str()), + "Cargo.toml default features", + )?; + are_captures_sorted( + linesre.captures_iter(blocks.get(3).unwrap().as_str()), + "Cargo.toml additional features", + ) +} diff --git a/tests/dm-tests.rs b/tests/dm-tests.rs index cfffdbbb..40ed85e4 100644 --- a/tests/dm-tests.rs +++ b/tests/dm-tests.rs @@ -6,12 +6,24 @@ fn git() { run_dm_tests("git"); } +#[cfg(feature = "toml")] +#[test] +fn toml() { + run_dm_tests("toml"); +} + #[cfg(feature = "url")] #[test] fn url() { run_dm_tests("url"); } +#[cfg(feature = "hash")] +#[test] +fn hash() { + run_dm_tests("hash"); +} + fn run_dm_tests(name: &str) { std::env::remove_var("RUST_BACKTRACE"); diff --git a/tests/dm/hash.dme b/tests/dm/hash.dme new file mode 100644 index 00000000..dcd5411f --- /dev/null +++ b/tests/dm/hash.dme @@ -0,0 +1,23 @@ +#include "common.dm" + +var/list/reference = list() + +/proc/check_hash_base64(input) + var/expected = reference[input] + var/rust = rustg_hash_string("base64", input) + // Case sensitive + if (!cmptextEx(expected, rust)) + CRASH("[input]\n expected: [expected]\n rustg: [rust]") + +/test/proc/various_hash_base64() + reference["The quick brown fox jumps over the lazy dog."] = \ + "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=" + + reference["Résumé"] = \ + "UsOpc3Vtw6k=" + + reference["https://example.com/?foo=bar+baz&bar\[]=baz#foo"] = \ + "aHR0cHM6Ly9leGFtcGxlLmNvbS8/Zm9vPWJhcitiYXomYmFyW109YmF6I2Zvbw==" + + for (var/entry in reference) + check_hash_base64(entry) diff --git a/tests/dm/toml.dme b/tests/dm/toml.dme new file mode 100644 index 00000000..959217e9 --- /dev/null +++ b/tests/dm/toml.dme @@ -0,0 +1,29 @@ +#include "common.dm" + +var/test_toml = @{" +[database] +enabled = true +ports = [ 8000, 25565 ] +data = [ ["delta", "phi"] ] +temp_targets = { cpu = 79, case = 72 } +"} + +var/test_json = @{" +{"database":{"data":[["delta","phi"]],"enabled":true,"ports":[8000,25565],"temp_targets":{"case":72,"cpu":79}}} +"} + +/test/proc/check_toml_file2json() + rustg_file_write(test_toml, "test.toml") + + var/toml_output = rustg_read_toml_file("test.toml") + + if (toml_output ~! json_decode(test_json)) + CRASH("test:\n[test_toml]\n \nexpected:\n[test_json]\n \nrustg:\n[json_encode(toml_output)]") + +/test/proc/check_rustg_toml_encode() + var/json_value = json_decode(test_json) + rustg_file_write(rustg_toml_encode(json_value), "test_encode.toml") + var/toml_output = rustg_read_toml_file("test_encode.toml") + + if (toml_output ~! json_value) + CRASH("test:\n[test_toml]\n \nexpected:\n[test_json]\n \nrustg:\n[json_encode(toml_output)]") diff --git a/tests/rsc/ai_nodes_info.json b/tests/rsc/ai_nodes_info.json new file mode 100644 index 00000000..533f1d5d --- /dev/null +++ b/tests/rsc/ai_nodes_info.json @@ -0,0 +1 @@ +[{"unique_id":0,"x":64,"y":12,"z":1,"connected_nodes_id":[3]},{"unique_id":1,"x":57,"y":13,"z":1,"connected_nodes_id":[2,9]},{"unique_id":2,"x":62,"y":13,"z":1,"connected_nodes_id":[1,3,10]},{"unique_id":3,"x":65,"y":13,"z":1,"connected_nodes_id":[0,2,7]},{"unique_id":4,"x":73,"y":14,"z":1,"connected_nodes_id":[5,8,18]},{"unique_id":5,"x":78,"y":14,"z":1,"connected_nodes_id":[4,6,12]},{"unique_id":6,"x":85,"y":14,"z":1,"connected_nodes_id":[5,14]},{"unique_id":7,"x":65,"y":15,"z":1,"connected_nodes_id":[3,8,16]},{"unique_id":8,"x":72,"y":15,"z":1,"connected_nodes_id":[4,7]},{"unique_id":9,"x":57,"y":17,"z":1,"connected_nodes_id":[1]},{"unique_id":10,"x":62,"y":18,"z":1,"connected_nodes_id":[2,15]},{"unique_id":11,"x":74,"y":18,"z":1,"connected_nodes_id":[12,18]},{"unique_id":12,"x":78,"y":18,"z":1,"connected_nodes_id":[5,11,13,29]},{"unique_id":13,"x":81,"y":18,"z":1,"connected_nodes_id":[12,14,30]},{"unique_id":14,"x":85,"y":18,"z":1,"connected_nodes_id":[6,13,41]},{"unique_id":15,"x":61,"y":19,"z":1,"connected_nodes_id":[10,16,35]},{"unique_id":16,"x":65,"y":19,"z":1,"connected_nodes_id":[7,15,17]},{"unique_id":17,"x":70,"y":19,"z":1,"connected_nodes_id":[16,18,25]},{"unique_id":18,"x":73,"y":19,"z":1,"connected_nodes_id":[4,11,17]},{"unique_id":19,"x":99,"y":19,"z":1,"connected_nodes_id":[42]},{"unique_id":20,"x":47,"y":21,"z":1,"connected_nodes_id":[21,32]},{"unique_id":21,"x":49,"y":21,"z":1,"connected_nodes_id":[20,33]},{"unique_id":22,"x":54,"y":21,"z":1,"connected_nodes_id":[23,28]},{"unique_id":23,"x":58,"y":21,"z":1,"connected_nodes_id":[22,45]},{"unique_id":24,"x":65,"y":21,"z":1,"connected_nodes_id":[25]},{"unique_id":25,"x":70,"y":21,"z":1,"connected_nodes_id":[17,24,26,38]},{"unique_id":26,"x":74,"y":21,"z":1,"connected_nodes_id":[25,39]},{"unique_id":27,"x":50,"y":24,"z":1,"connected_nodes_id":[28,33]},{"unique_id":28,"x":54,"y":24,"z":1,"connected_nodes_id":[22,27,34]},{"unique_id":29,"x":78,"y":24,"z":1,"connected_nodes_id":[12,30,40]},{"unique_id":30,"x":81,"y":24,"z":1,"connected_nodes_id":[13,29]},{"unique_id":31,"x":45,"y":25,"z":1,"connected_nodes_id":[32]},{"unique_id":32,"x":47,"y":25,"z":1,"connected_nodes_id":[20,31,33]},{"unique_id":33,"x":49,"y":25,"z":1,"connected_nodes_id":[21,27,32,48]},{"unique_id":34,"x":55,"y":25,"z":1,"connected_nodes_id":[28,44]},{"unique_id":35,"x":61,"y":26,"z":1,"connected_nodes_id":[15,46]},{"unique_id":36,"x":65,"y":26,"z":1,"connected_nodes_id":[37]},{"unique_id":37,"x":68,"y":26,"z":1,"connected_nodes_id":[36,38,61]},{"unique_id":38,"x":70,"y":26,"z":1,"connected_nodes_id":[25,37,39]},{"unique_id":39,"x":74,"y":26,"z":1,"connected_nodes_id":[26,38,40,62]},{"unique_id":40,"x":78,"y":26,"z":1,"connected_nodes_id":[29,39,57]},{"unique_id":41,"x":85,"y":26,"z":1,"connected_nodes_id":[14,42,59]},{"unique_id":42,"x":99,"y":26,"z":1,"connected_nodes_id":[19,41,66]},{"unique_id":43,"x":52,"y":27,"z":1,"connected_nodes_id":[53]},{"unique_id":44,"x":55,"y":27,"z":1,"connected_nodes_id":[34,45]},{"unique_id":45,"x":58,"y":27,"z":1,"connected_nodes_id":[23,44,46]},{"unique_id":46,"x":60,"y":27,"z":1,"connected_nodes_id":[35,45,51]},{"unique_id":47,"x":42,"y":28,"z":1,"connected_nodes_id":[48,49]},{"unique_id":48,"x":49,"y":28,"z":1,"connected_nodes_id":[33,47,52]},{"unique_id":49,"x":42,"y":31,"z":1,"connected_nodes_id":[47,50,60]},{"unique_id":50,"x":45,"y":31,"z":1,"connected_nodes_id":[49,63]},{"unique_id":51,"x":60,"y":31,"z":1,"connected_nodes_id":[46,54]},{"unique_id":52,"x":49,"y":32,"z":1,"connected_nodes_id":[48,69]},{"unique_id":53,"x":52,"y":32,"z":1,"connected_nodes_id":[43,54]},{"unique_id":54,"x":59,"y":32,"z":1,"connected_nodes_id":[51,53,70]},{"unique_id":55,"x":64,"y":32,"z":1,"connected_nodes_id":[56,72]},{"unique_id":56,"x":67,"y":32,"z":1,"connected_nodes_id":[55,61]},{"unique_id":57,"x":78,"y":32,"z":1,"connected_nodes_id":[40,58,75]},{"unique_id":58,"x":81,"y":32,"z":1,"connected_nodes_id":[57,59,76]},{"unique_id":59,"x":85,"y":32,"z":1,"connected_nodes_id":[41,58,77]},{"unique_id":60,"x":42,"y":33,"z":1,"connected_nodes_id":[49]},{"unique_id":61,"x":68,"y":33,"z":1,"connected_nodes_id":[37,56,62]},{"unique_id":62,"x":74,"y":33,"z":1,"connected_nodes_id":[39,61,68]},{"unique_id":63,"x":45,"y":34,"z":1,"connected_nodes_id":[50]},{"unique_id":64,"x":91,"y":34,"z":1,"connected_nodes_id":[65,78]},{"unique_id":65,"x":96,"y":34,"z":1,"connected_nodes_id":[64,66,79]},{"unique_id":66,"x":99,"y":34,"z":1,"connected_nodes_id":[42,65,67]},{"unique_id":67,"x":109,"y":34,"z":1,"connected_nodes_id":[66,94]},{"unique_id":68,"x":74,"y":37,"z":1,"connected_nodes_id":[62,74]},{"unique_id":69,"x":49,"y":38,"z":1,"connected_nodes_id":[52,70]},{"unique_id":70,"x":59,"y":38,"z":1,"connected_nodes_id":[54,69,71,80]},{"unique_id":71,"x":61,"y":38,"z":1,"connected_nodes_id":[70,72,82]},{"unique_id":72,"x":64,"y":38,"z":1,"connected_nodes_id":[55,71,73]},{"unique_id":73,"x":66,"y":38,"z":1,"connected_nodes_id":[72,74,96]},{"unique_id":74,"x":73,"y":38,"z":1,"connected_nodes_id":[68,73,75,97]},{"unique_id":75,"x":78,"y":38,"z":1,"connected_nodes_id":[57,74,76]},{"unique_id":76,"x":81,"y":38,"z":1,"connected_nodes_id":[58,75,77,88]},{"unique_id":77,"x":85,"y":38,"z":1,"connected_nodes_id":[59,76,78]},{"unique_id":78,"x":91,"y":38,"z":1,"connected_nodes_id":[64,77,79,81]},{"unique_id":79,"x":96,"y":38,"z":1,"connected_nodes_id":[65,78,92]},{"unique_id":80,"x":58,"y":39,"z":1,"connected_nodes_id":[70,99]},{"unique_id":81,"x":92,"y":39,"z":1,"connected_nodes_id":[78,84]},{"unique_id":82,"x":61,"y":40,"z":1,"connected_nodes_id":[71,87]},{"unique_id":83,"x":87,"y":40,"z":1,"connected_nodes_id":[84,89]},{"unique_id":84,"x":93,"y":40,"z":1,"connected_nodes_id":[81,83,113]},{"unique_id":85,"x":51,"y":41,"z":1,"connected_nodes_id":[86,90]},{"unique_id":86,"x":54,"y":41,"z":1,"connected_nodes_id":[85,143]},{"unique_id":87,"x":62,"y":41,"z":1,"connected_nodes_id":[82,100]},{"unique_id":88,"x":81,"y":41,"z":1,"connected_nodes_id":[76,89,91]},{"unique_id":89,"x":86,"y":41,"z":1,"connected_nodes_id":[83,88]},{"unique_id":90,"x":50,"y":42,"z":1,"connected_nodes_id":[85,106]},{"unique_id":91,"x":80,"y":42,"z":1,"connected_nodes_id":[88,98,105]},{"unique_id":92,"x":96,"y":42,"z":1,"connected_nodes_id":[79,93,108]},{"unique_id":93,"x":103,"y":42,"z":1,"connected_nodes_id":[92,94]},{"unique_id":94,"x":109,"y":42,"z":1,"connected_nodes_id":[67,93,95,110]},{"unique_id":95,"x":114,"y":42,"z":1,"connected_nodes_id":[94,111]},{"unique_id":96,"x":66,"y":43,"z":1,"connected_nodes_id":[73,97]},{"unique_id":97,"x":73,"y":43,"z":1,"connected_nodes_id":[74,96,98,104]},{"unique_id":98,"x":79,"y":43,"z":1,"connected_nodes_id":[91,97]},{"unique_id":99,"x":58,"y":45,"z":1,"connected_nodes_id":[80,100,101,126]},{"unique_id":100,"x":62,"y":45,"z":1,"connected_nodes_id":[87,99,102]},{"unique_id":101,"x":57,"y":46,"z":1,"connected_nodes_id":[99,107]},{"unique_id":102,"x":63,"y":46,"z":1,"connected_nodes_id":[100,103]},{"unique_id":103,"x":71,"y":46,"z":1,"connected_nodes_id":[102,104,155]},{"unique_id":104,"x":73,"y":46,"z":1,"connected_nodes_id":[97,103,105]},{"unique_id":105,"x":80,"y":46,"z":1,"connected_nodes_id":[91,104,117]},{"unique_id":106,"x":50,"y":47,"z":1,"connected_nodes_id":[90,107,142]},{"unique_id":107,"x":56,"y":47,"z":1,"connected_nodes_id":[101,106]},{"unique_id":108,"x":96,"y":47,"z":1,"connected_nodes_id":[92,109,145]},{"unique_id":109,"x":102,"y":47,"z":1,"connected_nodes_id":[108,110]},{"unique_id":110,"x":109,"y":47,"z":1,"connected_nodes_id":[94,109,111,125]},{"unique_id":111,"x":114,"y":47,"z":1,"connected_nodes_id":[95,110,148]},{"unique_id":112,"x":88,"y":48,"z":1,"connected_nodes_id":[113,119]},{"unique_id":113,"x":93,"y":48,"z":1,"connected_nodes_id":[84,112,137]},{"unique_id":114,"x":65,"y":49,"z":1,"connected_nodes_id":[129]},{"unique_id":115,"x":68,"y":49,"z":1,"connected_nodes_id":[130]},{"unique_id":116,"x":75,"y":49,"z":1,"connected_nodes_id":[117,157]},{"unique_id":117,"x":80,"y":49,"z":1,"connected_nodes_id":[105,116,118,158]},{"unique_id":118,"x":84,"y":49,"z":1,"connected_nodes_id":[117,119,135]},{"unique_id":119,"x":87,"y":49,"z":1,"connected_nodes_id":[112,118,136]},{"unique_id":120,"x":99,"y":49,"z":1,"connected_nodes_id":[121,153]},{"unique_id":121,"x":102,"y":49,"z":1,"connected_nodes_id":[120,122,123]},{"unique_id":122,"x":106,"y":49,"z":1,"connected_nodes_id":[121,124]},{"unique_id":123,"x":103,"y":50,"z":1,"connected_nodes_id":[121,131]},{"unique_id":124,"x":107,"y":50,"z":1,"connected_nodes_id":[122,125]},{"unique_id":125,"x":109,"y":50,"z":1,"connected_nodes_id":[110,124]},{"unique_id":126,"x":58,"y":51,"z":1,"connected_nodes_id":[99,127,165]},{"unique_id":127,"x":60,"y":51,"z":1,"connected_nodes_id":[126,128,149]},{"unique_id":128,"x":63,"y":51,"z":1,"connected_nodes_id":[127,129,150]},{"unique_id":129,"x":65,"y":51,"z":1,"connected_nodes_id":[114,128,130,151]},{"unique_id":130,"x":68,"y":51,"z":1,"connected_nodes_id":[115,129,152]},{"unique_id":131,"x":102,"y":51,"z":1,"connected_nodes_id":[123,147]},{"unique_id":132,"x":29,"y":52,"z":1,"connected_nodes_id":[167]},{"unique_id":133,"x":45,"y":52,"z":1,"connected_nodes_id":[134,140]},{"unique_id":134,"x":47,"y":52,"z":1,"connected_nodes_id":[133,141,156]},{"unique_id":135,"x":84,"y":52,"z":1,"connected_nodes_id":[118,136,161]},{"unique_id":136,"x":87,"y":52,"z":1,"connected_nodes_id":[119,135,137,162]},{"unique_id":137,"x":93,"y":52,"z":1,"connected_nodes_id":[113,136,144,163]},{"unique_id":138,"x":34,"y":53,"z":1,"connected_nodes_id":[139,168]},{"unique_id":139,"x":39,"y":53,"z":1,"connected_nodes_id":[138,140,176]},{"unique_id":140,"x":44,"y":53,"z":1,"connected_nodes_id":[133,139,141,169]},{"unique_id":141,"x":48,"y":53,"z":1,"connected_nodes_id":[134,140,142]},{"unique_id":142,"x":50,"y":53,"z":1,"connected_nodes_id":[106,141,143]},{"unique_id":143,"x":54,"y":53,"z":1,"connected_nodes_id":[86,142]},{"unique_id":144,"x":92,"y":53,"z":1,"connected_nodes_id":[137,145]},{"unique_id":145,"x":96,"y":53,"z":1,"connected_nodes_id":[108,144,146,172]},{"unique_id":146,"x":98,"y":53,"z":1,"connected_nodes_id":[145,153]},{"unique_id":147,"x":102,"y":53,"z":1,"connected_nodes_id":[131,154]},{"unique_id":148,"x":114,"y":53,"z":1,"connected_nodes_id":[111]},{"unique_id":149,"x":60,"y":54,"z":1,"connected_nodes_id":[127,150]},{"unique_id":150,"x":63,"y":54,"z":1,"connected_nodes_id":[128,149]},{"unique_id":151,"x":65,"y":54,"z":1,"connected_nodes_id":[129]},{"unique_id":152,"x":68,"y":54,"z":1,"connected_nodes_id":[130]},{"unique_id":153,"x":99,"y":54,"z":1,"connected_nodes_id":[120,146,154]},{"unique_id":154,"x":101,"y":54,"z":1,"connected_nodes_id":[147,153,173]},{"unique_id":155,"x":71,"y":55,"z":1,"connected_nodes_id":[103,179]},{"unique_id":156,"x":47,"y":56,"z":1,"connected_nodes_id":[134,160]},{"unique_id":157,"x":75,"y":56,"z":1,"connected_nodes_id":[116,158,180]},{"unique_id":158,"x":80,"y":56,"z":1,"connected_nodes_id":[117,157,159,186]},{"unique_id":159,"x":83,"y":56,"z":1,"connected_nodes_id":[158,161]},{"unique_id":160,"x":48,"y":57,"z":1,"connected_nodes_id":[156,164]},{"unique_id":161,"x":84,"y":57,"z":1,"connected_nodes_id":[135,159,162]},{"unique_id":162,"x":87,"y":57,"z":1,"connected_nodes_id":[136,161,163]},{"unique_id":163,"x":93,"y":57,"z":1,"connected_nodes_id":[137,162,182]},{"unique_id":164,"x":49,"y":58,"z":1,"connected_nodes_id":[160,165]},{"unique_id":165,"x":58,"y":58,"z":1,"connected_nodes_id":[126,164,166]},{"unique_id":166,"x":61,"y":58,"z":1,"connected_nodes_id":[165,170]},{"unique_id":167,"x":29,"y":59,"z":1,"connected_nodes_id":[132,168]},{"unique_id":168,"x":34,"y":59,"z":1,"connected_nodes_id":[138,167,175]},{"unique_id":169,"x":44,"y":59,"z":1,"connected_nodes_id":[140,177]},{"unique_id":170,"x":61,"y":60,"z":1,"connected_nodes_id":[166,171,189]},{"unique_id":171,"x":68,"y":60,"z":1,"connected_nodes_id":[170,178]},{"unique_id":172,"x":96,"y":60,"z":1,"connected_nodes_id":[145,173,192]},{"unique_id":173,"x":101,"y":60,"z":1,"connected_nodes_id":[154,172,174]},{"unique_id":174,"x":104,"y":60,"z":1,"connected_nodes_id":[173]},{"unique_id":175,"x":34,"y":61,"z":1,"connected_nodes_id":[168,176]},{"unique_id":176,"x":39,"y":61,"z":1,"connected_nodes_id":[139,175,177,183]},{"unique_id":177,"x":44,"y":61,"z":1,"connected_nodes_id":[169,176]},{"unique_id":178,"x":69,"y":61,"z":1,"connected_nodes_id":[171,179]},{"unique_id":179,"x":71,"y":61,"z":1,"connected_nodes_id":[155,178,180]},{"unique_id":180,"x":75,"y":61,"z":1,"connected_nodes_id":[157,179,185]},{"unique_id":181,"x":86,"y":61,"z":1,"connected_nodes_id":[182,191]},{"unique_id":182,"x":93,"y":61,"z":1,"connected_nodes_id":[163,181]},{"unique_id":183,"x":39,"y":63,"z":1,"connected_nodes_id":[176]},{"unique_id":184,"x":72,"y":63,"z":1,"connected_nodes_id":[203]},{"unique_id":185,"x":75,"y":63,"z":1,"connected_nodes_id":[180,186]},{"unique_id":186,"x":80,"y":63,"z":1,"connected_nodes_id":[158,185,190,205]},{"unique_id":187,"x":90,"y":63,"z":1,"connected_nodes_id":[188,207]},{"unique_id":188,"x":92,"y":63,"z":1,"connected_nodes_id":[187]},{"unique_id":189,"x":61,"y":64,"z":1,"connected_nodes_id":[170,200]},{"unique_id":190,"x":81,"y":64,"z":1,"connected_nodes_id":[186,191,227]},{"unique_id":191,"x":86,"y":64,"z":1,"connected_nodes_id":[181,190]},{"unique_id":192,"x":96,"y":64,"z":1,"connected_nodes_id":[172,193,209]},{"unique_id":193,"x":103,"y":64,"z":1,"connected_nodes_id":[192,194,199]},{"unique_id":194,"x":108,"y":64,"z":1,"connected_nodes_id":[193,195]},{"unique_id":195,"x":111,"y":64,"z":1,"connected_nodes_id":[194]},{"unique_id":196,"x":64,"y":66,"z":1,"connected_nodes_id":[197,201]},{"unique_id":197,"x":67,"y":66,"z":1,"connected_nodes_id":[196]},{"unique_id":198,"x":99,"y":68,"z":1,"connected_nodes_id":[199,219]},{"unique_id":199,"x":103,"y":68,"z":1,"connected_nodes_id":[193,198]},{"unique_id":200,"x":61,"y":69,"z":1,"connected_nodes_id":[189,201,215]},{"unique_id":201,"x":64,"y":69,"z":1,"connected_nodes_id":[196,200,202]},{"unique_id":202,"x":66,"y":69,"z":1,"connected_nodes_id":[201,203,216]},{"unique_id":203,"x":72,"y":69,"z":1,"connected_nodes_id":[184,202,204]},{"unique_id":204,"x":76,"y":69,"z":1,"connected_nodes_id":[203,205,211]},{"unique_id":205,"x":80,"y":69,"z":1,"connected_nodes_id":[186,204,206]},{"unique_id":206,"x":87,"y":69,"z":1,"connected_nodes_id":[205,207,221]},{"unique_id":207,"x":90,"y":69,"z":1,"connected_nodes_id":[187,206,208,217]},{"unique_id":208,"x":95,"y":69,"z":1,"connected_nodes_id":[207,209]},{"unique_id":209,"x":96,"y":70,"z":1,"connected_nodes_id":[192,208,214]},{"unique_id":210,"x":73,"y":73,"z":1,"connected_nodes_id":[211,213]},{"unique_id":211,"x":76,"y":73,"z":1,"connected_nodes_id":[204,210,226]},{"unique_id":212,"x":67,"y":74,"z":1,"connected_nodes_id":[213,216]},{"unique_id":213,"x":72,"y":74,"z":1,"connected_nodes_id":[210,212,225]},{"unique_id":214,"x":96,"y":74,"z":1,"connected_nodes_id":[209,230]},{"unique_id":215,"x":61,"y":75,"z":1,"connected_nodes_id":[200,216,222]},{"unique_id":216,"x":66,"y":75,"z":1,"connected_nodes_id":[202,212,215]},{"unique_id":217,"x":90,"y":75,"z":1,"connected_nodes_id":[207,218,228]},{"unique_id":218,"x":94,"y":75,"z":1,"connected_nodes_id":[217]},{"unique_id":219,"x":99,"y":75,"z":1,"connected_nodes_id":[198,220]},{"unique_id":220,"x":102,"y":75,"z":1,"connected_nodes_id":[219]},{"unique_id":221,"x":87,"y":76,"z":1,"connected_nodes_id":[206,234]},{"unique_id":222,"x":61,"y":77,"z":1,"connected_nodes_id":[215,223]},{"unique_id":223,"x":64,"y":77,"z":1,"connected_nodes_id":[222]},{"unique_id":224,"x":68,"y":78,"z":1,"connected_nodes_id":[225]},{"unique_id":225,"x":72,"y":78,"z":1,"connected_nodes_id":[213,224]},{"unique_id":226,"x":76,"y":78,"z":1,"connected_nodes_id":[211,227,232]},{"unique_id":227,"x":81,"y":78,"z":1,"connected_nodes_id":[190,226,233]},{"unique_id":228,"x":90,"y":78,"z":1,"connected_nodes_id":[217,229]},{"unique_id":229,"x":94,"y":78,"z":1,"connected_nodes_id":[228]},{"unique_id":230,"x":96,"y":79,"z":1,"connected_nodes_id":[214,231]},{"unique_id":231,"x":99,"y":79,"z":1,"connected_nodes_id":[230]},{"unique_id":232,"x":76,"y":82,"z":1,"connected_nodes_id":[226,233]},{"unique_id":233,"x":81,"y":82,"z":1,"connected_nodes_id":[227,232,234]},{"unique_id":234,"x":87,"y":82,"z":1,"connected_nodes_id":[221,233,235]},{"unique_id":235,"x":86,"y":83,"z":1,"connected_nodes_id":[234]},{"unique_id":236,"x":7,"y":132,"z":2,"connected_nodes_id":[237,240]},{"unique_id":237,"x":7,"y":125,"z":2,"connected_nodes_id":[236,238]},{"unique_id":238,"x":7,"y":119,"z":2,"connected_nodes_id":[237,239]},{"unique_id":239,"x":8,"y":118,"z":2,"connected_nodes_id":[238,832]},{"unique_id":240,"x":9,"y":132,"z":2,"connected_nodes_id":[236,241,741]},{"unique_id":241,"x":12,"y":132,"z":2,"connected_nodes_id":[240,242]},{"unique_id":242,"x":12,"y":125,"z":2,"connected_nodes_id":[241,243]},{"unique_id":243,"x":12,"y":120,"z":2,"connected_nodes_id":[242,244,247]},{"unique_id":244,"x":12,"y":116,"z":2,"connected_nodes_id":[243,833]},{"unique_id":245,"x":13,"y":165,"z":2,"connected_nodes_id":[250,791]},{"unique_id":246,"x":20,"y":124,"z":2,"connected_nodes_id":[254]},{"unique_id":247,"x":20,"y":120,"z":2,"connected_nodes_id":[243,256]},{"unique_id":248,"x":21,"y":137,"z":2,"connected_nodes_id":[249]},{"unique_id":249,"x":21,"y":130,"z":2,"connected_nodes_id":[248,252]},{"unique_id":250,"x":23,"y":165,"z":2,"connected_nodes_id":[245,258]},{"unique_id":251,"x":23,"y":117,"z":2,"connected_nodes_id":[257]},{"unique_id":252,"x":26,"y":130,"z":2,"connected_nodes_id":[249,253]},{"unique_id":253,"x":26,"y":127,"z":2,"connected_nodes_id":[252,254,260]},{"unique_id":254,"x":26,"y":124,"z":2,"connected_nodes_id":[246,253,255]},{"unique_id":255,"x":27,"y":123,"z":2,"connected_nodes_id":[254,256,261]},{"unique_id":256,"x":27,"y":120,"z":2,"connected_nodes_id":[247,255,257,262]},{"unique_id":257,"x":27,"y":117,"z":2,"connected_nodes_id":[251,256,263]},{"unique_id":258,"x":29,"y":165,"z":2,"connected_nodes_id":[250]},{"unique_id":259,"x":31,"y":133,"z":2,"connected_nodes_id":[260]},{"unique_id":260,"x":31,"y":127,"z":2,"connected_nodes_id":[253,259]},{"unique_id":261,"x":32,"y":123,"z":2,"connected_nodes_id":[255,262]},{"unique_id":262,"x":32,"y":120,"z":2,"connected_nodes_id":[256,261,263]},{"unique_id":263,"x":32,"y":117,"z":2,"connected_nodes_id":[257,262]},{"unique_id":264,"x":37,"y":140,"z":2,"connected_nodes_id":[265]},{"unique_id":265,"x":37,"y":137,"z":2,"connected_nodes_id":[264,266,276]},{"unique_id":266,"x":37,"y":133,"z":2,"connected_nodes_id":[265,267]},{"unique_id":267,"x":37,"y":126,"z":2,"connected_nodes_id":[266,268]},{"unique_id":268,"x":38,"y":125,"z":2,"connected_nodes_id":[267,269,930]},{"unique_id":269,"x":38,"y":117,"z":2,"connected_nodes_id":[268,278]},{"unique_id":270,"x":42,"y":172,"z":2,"connected_nodes_id":[271,284,862]},{"unique_id":271,"x":42,"y":163,"z":2,"connected_nodes_id":[270,793]},{"unique_id":272,"x":45,"y":85,"z":2,"connected_nodes_id":[273,803]},{"unique_id":273,"x":45,"y":79,"z":2,"connected_nodes_id":[272,274,282,798]},{"unique_id":274,"x":45,"y":73,"z":2,"connected_nodes_id":[273,286,861]},{"unique_id":275,"x":45,"y":47,"z":2,"connected_nodes_id":[834,967]},{"unique_id":276,"x":46,"y":137,"z":2,"connected_nodes_id":[265,293]},{"unique_id":277,"x":46,"y":121,"z":2,"connected_nodes_id":[288,931]},{"unique_id":278,"x":46,"y":117,"z":2,"connected_nodes_id":[269,279,289]},{"unique_id":279,"x":46,"y":113,"z":2,"connected_nodes_id":[278,1000]},{"unique_id":280,"x":46,"y":103,"z":2,"connected_nodes_id":[281,821,995]},{"unique_id":281,"x":46,"y":97,"z":2,"connected_nodes_id":[280,989]},{"unique_id":282,"x":46,"y":78,"z":2,"connected_nodes_id":[273,296]},{"unique_id":283,"x":47,"y":167,"z":2,"connected_nodes_id":[285,787]},{"unique_id":284,"x":48,"y":172,"z":2,"connected_nodes_id":[270,285,299]},{"unique_id":285,"x":48,"y":168,"z":2,"connected_nodes_id":[283,284,784]},{"unique_id":286,"x":49,"y":73,"z":2,"connected_nodes_id":[274,287,297]},{"unique_id":287,"x":49,"y":66,"z":2,"connected_nodes_id":[286]},{"unique_id":288,"x":50,"y":121,"z":2,"connected_nodes_id":[277,289,927]},{"unique_id":289,"x":50,"y":117,"z":2,"connected_nodes_id":[278,288,295,1000]},{"unique_id":290,"x":52,"y":89,"z":2,"connected_nodes_id":[291,805,989]},{"unique_id":291,"x":52,"y":84,"z":2,"connected_nodes_id":[290,292,306]},{"unique_id":292,"x":52,"y":82,"z":2,"connected_nodes_id":[291,307]},{"unique_id":293,"x":54,"y":137,"z":2,"connected_nodes_id":[276,294,939]},{"unique_id":294,"x":55,"y":138,"z":2,"connected_nodes_id":[293,304,310,751]},{"unique_id":295,"x":55,"y":117,"z":2,"connected_nodes_id":[289,305,312]},{"unique_id":296,"x":55,"y":78,"z":2,"connected_nodes_id":[282,1051]},{"unique_id":297,"x":55,"y":73,"z":2,"connected_nodes_id":[286,298,1046]},{"unique_id":298,"x":55,"y":66,"z":2,"connected_nodes_id":[297,983,1041]},{"unique_id":299,"x":56,"y":172,"z":2,"connected_nodes_id":[284,300,313]},{"unique_id":300,"x":56,"y":166,"z":2,"connected_nodes_id":[299,301]},{"unique_id":301,"x":56,"y":158,"z":2,"connected_nodes_id":[300,302,779]},{"unique_id":302,"x":56,"y":152,"z":2,"connected_nodes_id":[301,303,771,1020]},{"unique_id":303,"x":56,"y":145,"z":2,"connected_nodes_id":[302,304,760]},{"unique_id":304,"x":56,"y":139,"z":2,"connected_nodes_id":[294,303]},{"unique_id":305,"x":56,"y":116,"z":2,"connected_nodes_id":[295,998]},{"unique_id":306,"x":58,"y":84,"z":2,"connected_nodes_id":[291,307,309]},{"unique_id":307,"x":58,"y":82,"z":2,"connected_nodes_id":[292,306,1052]},{"unique_id":308,"x":59,"y":94,"z":2,"connected_nodes_id":[309,311,990]},{"unique_id":309,"x":59,"y":85,"z":2,"connected_nodes_id":[306,308,1056]},{"unique_id":310,"x":61,"y":138,"z":2,"connected_nodes_id":[294,332]},{"unique_id":311,"x":61,"y":94,"z":2,"connected_nodes_id":[308,1056]},{"unique_id":312,"x":63,"y":117,"z":2,"connected_nodes_id":[295,314,1001]},{"unique_id":313,"x":64,"y":172,"z":2,"connected_nodes_id":[299,316]},{"unique_id":314,"x":64,"y":118,"z":2,"connected_nodes_id":[312,323]},{"unique_id":315,"x":64,"y":91,"z":2,"connected_nodes_id":[320,1063]},{"unique_id":316,"x":65,"y":171,"z":2,"connected_nodes_id":[313,317]},{"unique_id":317,"x":66,"y":170,"z":2,"connected_nodes_id":[316,321,1025]},{"unique_id":318,"x":66,"y":114,"z":2,"connected_nodes_id":[1002]},{"unique_id":319,"x":66,"y":94,"z":2,"connected_nodes_id":[320,328]},{"unique_id":320,"x":66,"y":91,"z":2,"connected_nodes_id":[315,319]},{"unique_id":321,"x":67,"y":169,"z":2,"connected_nodes_id":[317,322,330,1032]},{"unique_id":322,"x":68,"y":168,"z":2,"connected_nodes_id":[321,1034]},{"unique_id":323,"x":69,"y":118,"z":2,"connected_nodes_id":[314,324]},{"unique_id":324,"x":69,"y":115,"z":2,"connected_nodes_id":[323,325,336]},{"unique_id":325,"x":69,"y":108,"z":2,"connected_nodes_id":[324,999]},{"unique_id":326,"x":69,"y":100,"z":2,"connected_nodes_id":[327,991]},{"unique_id":327,"x":69,"y":96,"z":2,"connected_nodes_id":[326]},{"unique_id":328,"x":70,"y":94,"z":2,"connected_nodes_id":[319,331]},{"unique_id":329,"x":71,"y":172,"z":2,"connected_nodes_id":[330]},{"unique_id":330,"x":71,"y":169,"z":2,"connected_nodes_id":[321,329,340]},{"unique_id":331,"x":71,"y":93,"z":2,"connected_nodes_id":[328,341,1064]},{"unique_id":332,"x":72,"y":138,"z":2,"connected_nodes_id":[310,333]},{"unique_id":333,"x":73,"y":137,"z":2,"connected_nodes_id":[332,334,1085]},{"unique_id":334,"x":73,"y":132,"z":2,"connected_nodes_id":[333,335]},{"unique_id":335,"x":73,"y":123,"z":2,"connected_nodes_id":[334,336,929]},{"unique_id":336,"x":73,"y":115,"z":2,"connected_nodes_id":[324,335,337]},{"unique_id":337,"x":73,"y":109,"z":2,"connected_nodes_id":[336,338,343]},{"unique_id":338,"x":73,"y":103,"z":2,"connected_nodes_id":[337,339,997]},{"unique_id":339,"x":73,"y":96,"z":2,"connected_nodes_id":[338,344]},{"unique_id":340,"x":81,"y":169,"z":2,"connected_nodes_id":[330,347]},{"unique_id":341,"x":81,"y":93,"z":2,"connected_nodes_id":[331,1061]},{"unique_id":342,"x":83,"y":63,"z":2,"connected_nodes_id":[348,987]},{"unique_id":343,"x":85,"y":109,"z":2,"connected_nodes_id":[337,344,361]},{"unique_id":344,"x":85,"y":96,"z":2,"connected_nodes_id":[339,1086,362,1062]},{"unique_id":345,"x":87,"y":137,"z":2,"connected_nodes_id":[1085,355,1013]},{"unique_id":346,"x":89,"y":173,"z":2,"connected_nodes_id":[347,359]},{"unique_id":347,"x":89,"y":169,"z":2,"connected_nodes_id":[340,346,349]},{"unique_id":348,"x":89,"y":63,"z":2,"connected_nodes_id":[342,1045]},{"unique_id":349,"x":90,"y":169,"z":2,"connected_nodes_id":[347,350,360]},{"unique_id":350,"x":90,"y":162,"z":2,"connected_nodes_id":[349,351,385]},{"unique_id":351,"x":91,"y":161,"z":2,"connected_nodes_id":[350,352]},{"unique_id":352,"x":91,"y":152,"z":2,"connected_nodes_id":[351,353]},{"unique_id":353,"x":91,"y":147,"z":2,"connected_nodes_id":[352,354,1013]},{"unique_id":354,"x":91,"y":141,"z":2,"connected_nodes_id":[353,355,394]},{"unique_id":355,"x":91,"y":137,"z":2,"connected_nodes_id":[345,354,395,1084]},{"unique_id":356,"x":92,"y":56,"z":2,"connected_nodes_id":[357,374]},{"unique_id":357,"x":92,"y":50,"z":2,"connected_nodes_id":[356,973]},{"unique_id":358,"x":93,"y":180,"z":2,"connected_nodes_id":[359,383]},{"unique_id":359,"x":93,"y":173,"z":2,"connected_nodes_id":[346,358,360,384]},{"unique_id":360,"x":93,"y":169,"z":2,"connected_nodes_id":[349,359]},{"unique_id":361,"x":93,"y":109,"z":2,"connected_nodes_id":[343,1090,386]},{"unique_id":362,"x":93,"y":96,"z":2,"connected_nodes_id":[344,1087,363]},{"unique_id":363,"x":93,"y":92,"z":2,"connected_nodes_id":[362,364,379]},{"unique_id":364,"x":93,"y":90,"z":2,"connected_nodes_id":[363,365]},{"unique_id":365,"x":93,"y":82,"z":2,"connected_nodes_id":[364,366]},{"unique_id":366,"x":93,"y":79,"z":2,"connected_nodes_id":[365,367,390]},{"unique_id":367,"x":93,"y":77,"z":2,"connected_nodes_id":[366,368,1050]},{"unique_id":368,"x":93,"y":73,"z":2,"connected_nodes_id":[367,369,402]},{"unique_id":369,"x":93,"y":70,"z":2,"connected_nodes_id":[368,1045]},{"unique_id":370,"x":93,"y":43,"z":2,"connected_nodes_id":[382]},{"unique_id":371,"x":94,"y":68,"z":2,"connected_nodes_id":[372,420]},{"unique_id":372,"x":94,"y":63,"z":2,"connected_nodes_id":[371,373,391]},{"unique_id":373,"x":94,"y":60,"z":2,"connected_nodes_id":[372,374,396]},{"unique_id":374,"x":94,"y":56,"z":2,"connected_nodes_id":[356,373,376]},{"unique_id":375,"x":95,"y":155,"z":2,"connected_nodes_id":[1097]},{"unique_id":376,"x":95,"y":55,"z":2,"connected_nodes_id":[374,403]},{"unique_id":377,"x":96,"y":149,"z":2,"connected_nodes_id":[392]},{"unique_id":378,"x":97,"y":192,"z":2,"connected_nodes_id":[414,888]},{"unique_id":379,"x":97,"y":92,"z":2,"connected_nodes_id":[363,380,388]},{"unique_id":380,"x":97,"y":87,"z":2,"connected_nodes_id":[379,389]},{"unique_id":381,"x":98,"y":47,"z":2,"connected_nodes_id":[382,397,968]},{"unique_id":382,"x":98,"y":43,"z":2,"connected_nodes_id":[370,381]},{"unique_id":383,"x":99,"y":180,"z":2,"connected_nodes_id":[358,384]},{"unique_id":384,"x":99,"y":173,"z":2,"connected_nodes_id":[359,383,431]},{"unique_id":385,"x":99,"y":162,"z":2,"connected_nodes_id":[350,433,1097]},{"unique_id":386,"x":99,"y":109,"z":2,"connected_nodes_id":[361,387,400]},{"unique_id":387,"x":99,"y":100,"z":2,"connected_nodes_id":[386,388,438,1087]},{"unique_id":388,"x":99,"y":92,"z":2,"connected_nodes_id":[379,387,389]},{"unique_id":389,"x":99,"y":87,"z":2,"connected_nodes_id":[380,388,390,419]},{"unique_id":390,"x":99,"y":79,"z":2,"connected_nodes_id":[366,389,401]},{"unique_id":391,"x":100,"y":63,"z":2,"connected_nodes_id":[372,421]},{"unique_id":392,"x":101,"y":149,"z":2,"connected_nodes_id":[377,393,1093]},{"unique_id":393,"x":101,"y":145,"z":2,"connected_nodes_id":[392,394,398]},{"unique_id":394,"x":101,"y":141,"z":2,"connected_nodes_id":[354,393,395,408]},{"unique_id":395,"x":101,"y":137,"z":2,"connected_nodes_id":[355,394,409]},{"unique_id":396,"x":101,"y":60,"z":2,"connected_nodes_id":[373]},{"unique_id":397,"x":101,"y":47,"z":2,"connected_nodes_id":[381,404]},{"unique_id":398,"x":102,"y":146,"z":2,"connected_nodes_id":[393,405]},{"unique_id":399,"x":103,"y":159,"z":2,"connected_nodes_id":[]},{"unique_id":400,"x":103,"y":109,"z":2,"connected_nodes_id":[386,437,1066]},{"unique_id":401,"x":103,"y":79,"z":2,"connected_nodes_id":[390,402,444]},{"unique_id":402,"x":103,"y":73,"z":2,"connected_nodes_id":[368,401,445]},{"unique_id":403,"x":103,"y":55,"z":2,"connected_nodes_id":[376,404]},{"unique_id":404,"x":103,"y":47,"z":2,"connected_nodes_id":[397,403,423]},{"unique_id":405,"x":105,"y":146,"z":2,"connected_nodes_id":[398,406,407]},{"unique_id":406,"x":105,"y":143,"z":2,"connected_nodes_id":[405,446]},{"unique_id":407,"x":106,"y":147,"z":2,"connected_nodes_id":[405,439]},{"unique_id":408,"x":106,"y":141,"z":2,"connected_nodes_id":[394,409,440]},{"unique_id":409,"x":106,"y":137,"z":2,"connected_nodes_id":[395,408,410,441]},{"unique_id":410,"x":106,"y":128,"z":2,"connected_nodes_id":[409,411,442]},{"unique_id":411,"x":106,"y":116,"z":2,"connected_nodes_id":[410,443]},{"unique_id":412,"x":106,"y":39,"z":2,"connected_nodes_id":[425,957]},{"unique_id":413,"x":107,"y":196,"z":2,"connected_nodes_id":[414]},{"unique_id":414,"x":107,"y":192,"z":2,"connected_nodes_id":[378,413,468]},{"unique_id":415,"x":107,"y":159,"z":2,"connected_nodes_id":[]},{"unique_id":416,"x":107,"y":96,"z":2,"connected_nodes_id":[417]},{"unique_id":417,"x":107,"y":93,"z":2,"connected_nodes_id":[416,418,1115]},{"unique_id":418,"x":107,"y":90,"z":2,"connected_nodes_id":[417,419,1114]},{"unique_id":419,"x":107,"y":87,"z":2,"connected_nodes_id":[389,418]},{"unique_id":420,"x":107,"y":68,"z":2,"connected_nodes_id":[371,421,449]},{"unique_id":421,"x":107,"y":63,"z":2,"connected_nodes_id":[391,420,422,450]},{"unique_id":422,"x":107,"y":56,"z":2,"connected_nodes_id":[421,423]},{"unique_id":423,"x":107,"y":47,"z":2,"connected_nodes_id":[404,422,424]},{"unique_id":424,"x":107,"y":43,"z":2,"connected_nodes_id":[423,425,447]},{"unique_id":425,"x":107,"y":38,"z":2,"connected_nodes_id":[412,424,426,453]},{"unique_id":426,"x":107,"y":33,"z":2,"connected_nodes_id":[425,427,954]},{"unique_id":427,"x":107,"y":26,"z":2,"connected_nodes_id":[426,428]},{"unique_id":428,"x":107,"y":22,"z":2,"connected_nodes_id":[427,429,456]},{"unique_id":429,"x":107,"y":17,"z":2,"connected_nodes_id":[428,430]},{"unique_id":430,"x":107,"y":14,"z":2,"connected_nodes_id":[429,434,463]},{"unique_id":431,"x":108,"y":173,"z":2,"connected_nodes_id":[384,432,436]},{"unique_id":432,"x":108,"y":167,"z":2,"connected_nodes_id":[431]},{"unique_id":433,"x":108,"y":162,"z":2,"connected_nodes_id":[385,458]},{"unique_id":434,"x":108,"y":13,"z":2,"connected_nodes_id":[430]},{"unique_id":435,"x":109,"y":177,"z":2,"connected_nodes_id":[436,464]},{"unique_id":436,"x":109,"y":174,"z":2,"connected_nodes_id":[431,435]},{"unique_id":437,"x":109,"y":109,"z":2,"connected_nodes_id":[400,438]},{"unique_id":438,"x":109,"y":100,"z":2,"connected_nodes_id":[387,437,471]},{"unique_id":439,"x":110,"y":147,"z":2,"connected_nodes_id":[407,1094]},{"unique_id":440,"x":110,"y":141,"z":2,"connected_nodes_id":[408,441]},{"unique_id":441,"x":110,"y":137,"z":2,"connected_nodes_id":[409,440,442]},{"unique_id":442,"x":110,"y":128,"z":2,"connected_nodes_id":[410,441,443,448]},{"unique_id":443,"x":110,"y":116,"z":2,"connected_nodes_id":[411,442]},{"unique_id":444,"x":110,"y":79,"z":2,"connected_nodes_id":[401,445,1105]},{"unique_id":445,"x":110,"y":73,"z":2,"connected_nodes_id":[402,444,1103]},{"unique_id":446,"x":111,"y":143,"z":2,"connected_nodes_id":[406]},{"unique_id":447,"x":111,"y":43,"z":2,"connected_nodes_id":[424]},{"unique_id":448,"x":113,"y":128,"z":2,"connected_nodes_id":[442,481]},{"unique_id":449,"x":113,"y":68,"z":2,"connected_nodes_id":[420,450]},{"unique_id":450,"x":113,"y":63,"z":2,"connected_nodes_id":[421,449,461]},{"unique_id":451,"x":113,"y":54,"z":2,"connected_nodes_id":[452,462]},{"unique_id":452,"x":113,"y":48,"z":2,"connected_nodes_id":[451,473]},{"unique_id":453,"x":113,"y":38,"z":2,"connected_nodes_id":[425,454,475]},{"unique_id":454,"x":113,"y":30,"z":2,"connected_nodes_id":[453]},{"unique_id":455,"x":113,"y":26,"z":2,"connected_nodes_id":[456]},{"unique_id":456,"x":113,"y":22,"z":2,"connected_nodes_id":[428,455,457,483]},{"unique_id":457,"x":113,"y":17,"z":2,"connected_nodes_id":[456]},{"unique_id":458,"x":114,"y":162,"z":2,"connected_nodes_id":[433,466]},{"unique_id":459,"x":114,"y":146,"z":2,"connected_nodes_id":[460]},{"unique_id":460,"x":114,"y":137,"z":2,"connected_nodes_id":[459,479]},{"unique_id":461,"x":114,"y":62,"z":2,"connected_nodes_id":[450,462]},{"unique_id":462,"x":114,"y":53,"z":2,"connected_nodes_id":[451,461]},{"unique_id":463,"x":114,"y":14,"z":2,"connected_nodes_id":[430,491]},{"unique_id":464,"x":115,"y":177,"z":2,"connected_nodes_id":[435,465]},{"unique_id":465,"x":115,"y":171,"z":2,"connected_nodes_id":[464,466]},{"unique_id":466,"x":115,"y":163,"z":2,"connected_nodes_id":[458,465]},{"unique_id":467,"x":115,"y":159,"z":2,"connected_nodes_id":[1100]},{"unique_id":468,"x":116,"y":192,"z":2,"connected_nodes_id":[414,469]},{"unique_id":469,"x":116,"y":188,"z":2,"connected_nodes_id":[468,470,492]},{"unique_id":470,"x":116,"y":184,"z":2,"connected_nodes_id":[469,493]},{"unique_id":471,"x":118,"y":100,"z":2,"connected_nodes_id":[438,490,1116]},{"unique_id":472,"x":118,"y":52,"z":2,"connected_nodes_id":[473]},{"unique_id":473,"x":118,"y":48,"z":2,"connected_nodes_id":[452,472,474,496]},{"unique_id":474,"x":118,"y":44,"z":2,"connected_nodes_id":[473]},{"unique_id":475,"x":118,"y":38,"z":2,"connected_nodes_id":[453,476]},{"unique_id":476,"x":118,"y":32,"z":2,"connected_nodes_id":[475,497]},{"unique_id":477,"x":119,"y":155,"z":2,"connected_nodes_id":[486,1100,1135]},{"unique_id":478,"x":119,"y":150,"z":2,"connected_nodes_id":[487,1092]},{"unique_id":479,"x":119,"y":137,"z":2,"connected_nodes_id":[460,480,489]},{"unique_id":480,"x":119,"y":132,"z":2,"connected_nodes_id":[479,481,506]},{"unique_id":481,"x":119,"y":128,"z":2,"connected_nodes_id":[448,480,501]},{"unique_id":482,"x":119,"y":26,"z":2,"connected_nodes_id":[483]},{"unique_id":483,"x":119,"y":22,"z":2,"connected_nodes_id":[456,482,484,494]},{"unique_id":484,"x":119,"y":17,"z":2,"connected_nodes_id":[483]},{"unique_id":485,"x":120,"y":164,"z":2,"connected_nodes_id":[486,1142]},{"unique_id":486,"x":120,"y":156,"z":2,"connected_nodes_id":[477,485]},{"unique_id":487,"x":120,"y":149,"z":2,"connected_nodes_id":[478,488,1132]},{"unique_id":488,"x":120,"y":147,"z":2,"connected_nodes_id":[487,489]},{"unique_id":489,"x":120,"y":138,"z":2,"connected_nodes_id":[479,488]},{"unique_id":490,"x":122,"y":100,"z":2,"connected_nodes_id":[471,1119]},{"unique_id":491,"x":122,"y":14,"z":2,"connected_nodes_id":[463,495]},{"unique_id":492,"x":123,"y":188,"z":2,"connected_nodes_id":[469,493]},{"unique_id":493,"x":123,"y":184,"z":2,"connected_nodes_id":[470,492,512]},{"unique_id":494,"x":123,"y":22,"z":2,"connected_nodes_id":[483,495]},{"unique_id":495,"x":123,"y":15,"z":2,"connected_nodes_id":[491,494,511]},{"unique_id":496,"x":124,"y":48,"z":2,"connected_nodes_id":[473,498]},{"unique_id":497,"x":124,"y":32,"z":2,"connected_nodes_id":[476,499]},{"unique_id":498,"x":125,"y":47,"z":2,"connected_nodes_id":[496,500]},{"unique_id":499,"x":125,"y":31,"z":2,"connected_nodes_id":[497,525]},{"unique_id":500,"x":126,"y":46,"z":2,"connected_nodes_id":[498,503]},{"unique_id":501,"x":127,"y":128,"z":2,"connected_nodes_id":[481,502,507]},{"unique_id":502,"x":127,"y":125,"z":2,"connected_nodes_id":[501,1127]},{"unique_id":503,"x":127,"y":45,"z":2,"connected_nodes_id":[500,523]},{"unique_id":504,"x":129,"y":142,"z":2,"connected_nodes_id":[505,1132]},{"unique_id":505,"x":129,"y":137,"z":2,"connected_nodes_id":[504,506]},{"unique_id":506,"x":129,"y":132,"z":2,"connected_nodes_id":[480,505,507,533]},{"unique_id":507,"x":129,"y":128,"z":2,"connected_nodes_id":[501,506,513]},{"unique_id":508,"x":130,"y":190,"z":2,"connected_nodes_id":[509]},{"unique_id":509,"x":130,"y":185,"z":2,"connected_nodes_id":[508,512]},{"unique_id":510,"x":130,"y":101,"z":2,"connected_nodes_id":[517,1122]},{"unique_id":511,"x":130,"y":15,"z":2,"connected_nodes_id":[495,530]},{"unique_id":512,"x":131,"y":184,"z":2,"connected_nodes_id":[493,509,1155]},{"unique_id":513,"x":131,"y":128,"z":2,"connected_nodes_id":[507,534,1128]},{"unique_id":514,"x":131,"y":58,"z":2,"connected_nodes_id":[515,521]},{"unique_id":515,"x":131,"y":53,"z":2,"connected_nodes_id":[514,522]},{"unique_id":516,"x":133,"y":143,"z":2,"connected_nodes_id":[547,1133]},{"unique_id":517,"x":133,"y":101,"z":2,"connected_nodes_id":[510,519,1117]},{"unique_id":518,"x":134,"y":95,"z":2,"connected_nodes_id":[520,1117]},{"unique_id":519,"x":136,"y":101,"z":2,"connected_nodes_id":[517,520,541,1118]},{"unique_id":520,"x":136,"y":95,"z":2,"connected_nodes_id":[518,519]},{"unique_id":521,"x":136,"y":58,"z":2,"connected_nodes_id":[514,522]},{"unique_id":522,"x":136,"y":53,"z":2,"connected_nodes_id":[515,521,523]},{"unique_id":523,"x":136,"y":45,"z":2,"connected_nodes_id":[503,522,524,554]},{"unique_id":524,"x":136,"y":39,"z":2,"connected_nodes_id":[523,525]},{"unique_id":525,"x":136,"y":31,"z":2,"connected_nodes_id":[499,524,543]},{"unique_id":526,"x":136,"y":7,"z":2,"connected_nodes_id":[531]},{"unique_id":527,"x":137,"y":70,"z":2,"connected_nodes_id":[528,550,1102]},{"unique_id":528,"x":137,"y":66,"z":2,"connected_nodes_id":[527,551]},{"unique_id":529,"x":137,"y":17,"z":2,"connected_nodes_id":[530,545]},{"unique_id":530,"x":137,"y":15,"z":2,"connected_nodes_id":[511,529]},{"unique_id":531,"x":137,"y":8,"z":2,"connected_nodes_id":[526,553]},{"unique_id":532,"x":138,"y":139,"z":2,"connected_nodes_id":[533,548]},{"unique_id":533,"x":138,"y":132,"z":2,"connected_nodes_id":[506,532,534]},{"unique_id":534,"x":138,"y":128,"z":2,"connected_nodes_id":[513,533,537,1129]},{"unique_id":535,"x":140,"y":180,"z":2,"connected_nodes_id":[536,558]},{"unique_id":536,"x":140,"y":176,"z":2,"connected_nodes_id":[535,559,1147]},{"unique_id":537,"x":141,"y":128,"z":2,"connected_nodes_id":[534,538,565]},{"unique_id":538,"x":141,"y":121,"z":2,"connected_nodes_id":[537,539,566,1129]},{"unique_id":539,"x":141,"y":117,"z":2,"connected_nodes_id":[538,540]},{"unique_id":540,"x":141,"y":110,"z":2,"connected_nodes_id":[539,541,542,571,1122]},{"unique_id":541,"x":141,"y":101,"z":2,"connected_nodes_id":[519,540,572]},{"unique_id":542,"x":142,"y":111,"z":2,"connected_nodes_id":[540,576,1124]},{"unique_id":543,"x":142,"y":31,"z":2,"connected_nodes_id":[525,544,546]},{"unique_id":544,"x":142,"y":26,"z":2,"connected_nodes_id":[543,545]},{"unique_id":545,"x":142,"y":17,"z":2,"connected_nodes_id":[529,544,562]},{"unique_id":546,"x":143,"y":32,"z":2,"connected_nodes_id":[543,549]},{"unique_id":547,"x":144,"y":143,"z":2,"connected_nodes_id":[516,548,1168]},{"unique_id":548,"x":144,"y":139,"z":2,"connected_nodes_id":[532,547]},{"unique_id":549,"x":144,"y":33,"z":2,"connected_nodes_id":[546,552]},{"unique_id":550,"x":145,"y":70,"z":2,"connected_nodes_id":[527,551,1172]},{"unique_id":551,"x":145,"y":66,"z":2,"connected_nodes_id":[528,550]},{"unique_id":552,"x":145,"y":34,"z":2,"connected_nodes_id":[549,555]},{"unique_id":553,"x":145,"y":8,"z":2,"connected_nodes_id":[531,557]},{"unique_id":554,"x":146,"y":45,"z":2,"connected_nodes_id":[523,555,577]},{"unique_id":555,"x":146,"y":35,"z":2,"connected_nodes_id":[552,554]},{"unique_id":556,"x":146,"y":13,"z":2,"connected_nodes_id":[557,563]},{"unique_id":557,"x":146,"y":9,"z":2,"connected_nodes_id":[553,556]},{"unique_id":558,"x":147,"y":180,"z":2,"connected_nodes_id":[535,559,1148]},{"unique_id":559,"x":147,"y":176,"z":2,"connected_nodes_id":[536,558,580]},{"unique_id":560,"x":147,"y":164,"z":2,"connected_nodes_id":[561]},{"unique_id":561,"x":147,"y":159,"z":2,"connected_nodes_id":[560,568]},{"unique_id":562,"x":147,"y":17,"z":2,"connected_nodes_id":[545,563]},{"unique_id":563,"x":147,"y":14,"z":2,"connected_nodes_id":[556,562,567]},{"unique_id":564,"x":148,"y":148,"z":2,"connected_nodes_id":[583,1131]},{"unique_id":565,"x":148,"y":128,"z":2,"connected_nodes_id":[537,566,584]},{"unique_id":566,"x":148,"y":121,"z":2,"connected_nodes_id":[538,565]},{"unique_id":567,"x":148,"y":15,"z":2,"connected_nodes_id":[563]},{"unique_id":568,"x":149,"y":159,"z":2,"connected_nodes_id":[561,569]},{"unique_id":569,"x":149,"y":157,"z":2,"connected_nodes_id":[568,570]},{"unique_id":570,"x":150,"y":156,"z":2,"connected_nodes_id":[569,582]},{"unique_id":571,"x":150,"y":110,"z":2,"connected_nodes_id":[540,572,576]},{"unique_id":572,"x":150,"y":101,"z":2,"connected_nodes_id":[541,571,573,1200]},{"unique_id":573,"x":150,"y":92,"z":2,"connected_nodes_id":[572,574]},{"unique_id":574,"x":150,"y":87,"z":2,"connected_nodes_id":[573,575,1165]},{"unique_id":575,"x":150,"y":84,"z":2,"connected_nodes_id":[574,1190]},{"unique_id":576,"x":151,"y":111,"z":2,"connected_nodes_id":[542,571,586]},{"unique_id":577,"x":151,"y":45,"z":2,"connected_nodes_id":[554,579]},{"unique_id":578,"x":152,"y":50,"z":2,"connected_nodes_id":[579]},{"unique_id":579,"x":152,"y":46,"z":2,"connected_nodes_id":[577,578,1274]},{"unique_id":580,"x":153,"y":176,"z":2,"connected_nodes_id":[559,581,587,1149]},{"unique_id":581,"x":153,"y":167,"z":2,"connected_nodes_id":[580,589]},{"unique_id":582,"x":154,"y":156,"z":2,"connected_nodes_id":[570,583]},{"unique_id":583,"x":154,"y":148,"z":2,"connected_nodes_id":[564,582,592]},{"unique_id":584,"x":154,"y":128,"z":2,"connected_nodes_id":[565,585,594,1166]},{"unique_id":585,"x":154,"y":122,"z":2,"connected_nodes_id":[584,600]},{"unique_id":586,"x":159,"y":111,"z":2,"connected_nodes_id":[576,601,1203]},{"unique_id":587,"x":161,"y":176,"z":2,"connected_nodes_id":[580,588,595]},{"unique_id":588,"x":161,"y":172,"z":2,"connected_nodes_id":[587,589]},{"unique_id":589,"x":161,"y":167,"z":2,"connected_nodes_id":[581,588,590,602]},{"unique_id":590,"x":161,"y":161,"z":2,"connected_nodes_id":[589,591]},{"unique_id":591,"x":161,"y":154,"z":2,"connected_nodes_id":[590,596]},{"unique_id":592,"x":161,"y":148,"z":2,"connected_nodes_id":[583,593]},{"unique_id":593,"x":161,"y":138,"z":2,"connected_nodes_id":[592,594]},{"unique_id":594,"x":161,"y":128,"z":2,"connected_nodes_id":[584,593,599]},{"unique_id":595,"x":162,"y":177,"z":2,"connected_nodes_id":[587,597,628]},{"unique_id":596,"x":162,"y":153,"z":2,"connected_nodes_id":[591,598]},{"unique_id":597,"x":163,"y":178,"z":2,"connected_nodes_id":[595,605]},{"unique_id":598,"x":163,"y":152,"z":2,"connected_nodes_id":[596,603]},{"unique_id":599,"x":165,"y":128,"z":2,"connected_nodes_id":[594,632]},{"unique_id":600,"x":165,"y":122,"z":2,"connected_nodes_id":[585]},{"unique_id":601,"x":166,"y":111,"z":2,"connected_nodes_id":[586,1204]},{"unique_id":602,"x":167,"y":167,"z":2,"connected_nodes_id":[589,607]},{"unique_id":603,"x":167,"y":152,"z":2,"connected_nodes_id":[598,604]},{"unique_id":604,"x":167,"y":148,"z":2,"connected_nodes_id":[603,608]},{"unique_id":605,"x":168,"y":178,"z":2,"connected_nodes_id":[597,606,616]},{"unique_id":606,"x":168,"y":173,"z":2,"connected_nodes_id":[605,613]},{"unique_id":607,"x":168,"y":168,"z":2,"connected_nodes_id":[602,615]},{"unique_id":608,"x":168,"y":147,"z":2,"connected_nodes_id":[604,609]},{"unique_id":609,"x":168,"y":139,"z":2,"connected_nodes_id":[608,620]},{"unique_id":610,"x":169,"y":158,"z":2,"connected_nodes_id":[611,619]},{"unique_id":611,"x":169,"y":154,"z":2,"connected_nodes_id":[610]},{"unique_id":612,"x":171,"y":174,"z":2,"connected_nodes_id":[613,626]},{"unique_id":613,"x":171,"y":173,"z":2,"connected_nodes_id":[606,612,614]},{"unique_id":614,"x":171,"y":170,"z":2,"connected_nodes_id":[613,615]},{"unique_id":615,"x":171,"y":168,"z":2,"connected_nodes_id":[607,614,617]},{"unique_id":616,"x":172,"y":178,"z":2,"connected_nodes_id":[605,625]},{"unique_id":617,"x":173,"y":168,"z":2,"connected_nodes_id":[615,618]},{"unique_id":618,"x":173,"y":163,"z":2,"connected_nodes_id":[617,619]},{"unique_id":619,"x":173,"y":158,"z":2,"connected_nodes_id":[610,618,622]},{"unique_id":620,"x":173,"y":139,"z":2,"connected_nodes_id":[609,621]},{"unique_id":621,"x":173,"y":134,"z":2,"connected_nodes_id":[620,631]},{"unique_id":622,"x":174,"y":157,"z":2,"connected_nodes_id":[619,623,636]},{"unique_id":623,"x":174,"y":153,"z":2,"connected_nodes_id":[622]},{"unique_id":624,"x":175,"y":181,"z":2,"connected_nodes_id":[625]},{"unique_id":625,"x":175,"y":178,"z":2,"connected_nodes_id":[616,624,626,628]},{"unique_id":626,"x":175,"y":174,"z":2,"connected_nodes_id":[612,625]},{"unique_id":627,"x":175,"y":148,"z":2,"connected_nodes_id":[638]},{"unique_id":628,"x":176,"y":177,"z":2,"connected_nodes_id":[595,625,644]},{"unique_id":629,"x":176,"y":170,"z":2,"connected_nodes_id":[633]},{"unique_id":630,"x":179,"y":139,"z":2,"connected_nodes_id":[631,655]},{"unique_id":631,"x":179,"y":134,"z":2,"connected_nodes_id":[621,630,632,647]},{"unique_id":632,"x":179,"y":128,"z":2,"connected_nodes_id":[599,631,639,1308]},{"unique_id":633,"x":180,"y":170,"z":2,"connected_nodes_id":[629,634,640]},{"unique_id":634,"x":180,"y":167,"z":2,"connected_nodes_id":[633,650]},{"unique_id":635,"x":180,"y":162,"z":2,"connected_nodes_id":[636]},{"unique_id":636,"x":180,"y":157,"z":2,"connected_nodes_id":[622,635,637,643]},{"unique_id":637,"x":180,"y":155,"z":2,"connected_nodes_id":[636]},{"unique_id":638,"x":180,"y":148,"z":2,"connected_nodes_id":[627,641]},{"unique_id":639,"x":180,"y":127,"z":2,"connected_nodes_id":[632]},{"unique_id":640,"x":181,"y":169,"z":2,"connected_nodes_id":[633,649]},{"unique_id":641,"x":181,"y":147,"z":2,"connected_nodes_id":[638,654]},{"unique_id":642,"x":183,"y":159,"z":2,"connected_nodes_id":[643,651]},{"unique_id":643,"x":183,"y":157,"z":2,"connected_nodes_id":[636,642,645]},{"unique_id":644,"x":184,"y":177,"z":2,"connected_nodes_id":[628,646]},{"unique_id":645,"x":184,"y":156,"z":2,"connected_nodes_id":[643,652]},{"unique_id":646,"x":185,"y":176,"z":2,"connected_nodes_id":[644,648]},{"unique_id":647,"x":185,"y":134,"z":2,"connected_nodes_id":[631,660,1308]},{"unique_id":648,"x":186,"y":175,"z":2,"connected_nodes_id":[646,649,657]},{"unique_id":649,"x":186,"y":169,"z":2,"connected_nodes_id":[640,648,650,663]},{"unique_id":650,"x":186,"y":167,"z":2,"connected_nodes_id":[634,649,651,664]},{"unique_id":651,"x":186,"y":159,"z":2,"connected_nodes_id":[642,650]},{"unique_id":652,"x":187,"y":156,"z":2,"connected_nodes_id":[645,653,659]},{"unique_id":653,"x":187,"y":153,"z":2,"connected_nodes_id":[652,654]},{"unique_id":654,"x":187,"y":147,"z":2,"connected_nodes_id":[641,653,655]},{"unique_id":655,"x":187,"y":139,"z":2,"connected_nodes_id":[630,654,668]},{"unique_id":656,"x":189,"y":179,"z":2,"connected_nodes_id":[657]},{"unique_id":657,"x":189,"y":175,"z":2,"connected_nodes_id":[648,656,661]},{"unique_id":658,"x":190,"y":158,"z":2,"connected_nodes_id":[659,666]},{"unique_id":659,"x":190,"y":156,"z":2,"connected_nodes_id":[652,658]},{"unique_id":660,"x":190,"y":134,"z":2,"connected_nodes_id":[647]},{"unique_id":661,"x":193,"y":175,"z":2,"connected_nodes_id":[657,669,1153]},{"unique_id":662,"x":193,"y":171,"z":2,"connected_nodes_id":[663]},{"unique_id":663,"x":193,"y":169,"z":2,"connected_nodes_id":[649,662,664]},{"unique_id":664,"x":193,"y":167,"z":2,"connected_nodes_id":[650,663]},{"unique_id":665,"x":196,"y":153,"z":2,"connected_nodes_id":[676]},{"unique_id":666,"x":197,"y":158,"z":2,"connected_nodes_id":[658,667]},{"unique_id":667,"x":197,"y":146,"z":2,"connected_nodes_id":[666,668]},{"unique_id":668,"x":197,"y":139,"z":2,"connected_nodes_id":[655,667,670,675]},{"unique_id":669,"x":198,"y":175,"z":2,"connected_nodes_id":[661]},{"unique_id":670,"x":198,"y":138,"z":2,"connected_nodes_id":[668,671]},{"unique_id":671,"x":198,"y":132,"z":2,"connected_nodes_id":[670]},{"unique_id":672,"x":199,"y":168,"z":2,"connected_nodes_id":[673,680]},{"unique_id":673,"x":199,"y":162,"z":2,"connected_nodes_id":[672]},{"unique_id":674,"x":199,"y":115,"z":2,"connected_nodes_id":[682]},{"unique_id":675,"x":200,"y":139,"z":2,"connected_nodes_id":[668,683]},{"unique_id":676,"x":204,"y":153,"z":2,"connected_nodes_id":[665,692]},{"unique_id":677,"x":205,"y":183,"z":2,"connected_nodes_id":[678,696,1154]},{"unique_id":678,"x":205,"y":177,"z":2,"connected_nodes_id":[677,679,697]},{"unique_id":679,"x":205,"y":175,"z":2,"connected_nodes_id":[678,680]},{"unique_id":680,"x":205,"y":168,"z":2,"connected_nodes_id":[672,679]},{"unique_id":681,"x":205,"y":121,"z":2,"connected_nodes_id":[682,689]},{"unique_id":682,"x":205,"y":115,"z":2,"connected_nodes_id":[674,681,690]},{"unique_id":683,"x":206,"y":139,"z":2,"connected_nodes_id":[675,684]},{"unique_id":684,"x":207,"y":138,"z":2,"connected_nodes_id":[683,685]},{"unique_id":685,"x":208,"y":137,"z":2,"connected_nodes_id":[684,686]},{"unique_id":686,"x":209,"y":136,"z":2,"connected_nodes_id":[685,687]},{"unique_id":687,"x":210,"y":135,"z":2,"connected_nodes_id":[686,688]},{"unique_id":688,"x":210,"y":128,"z":2,"connected_nodes_id":[687,700]},{"unique_id":689,"x":211,"y":121,"z":2,"connected_nodes_id":[681,690,701]},{"unique_id":690,"x":211,"y":115,"z":2,"connected_nodes_id":[682,689,694]},{"unique_id":691,"x":212,"y":157,"z":2,"connected_nodes_id":[692]},{"unique_id":692,"x":212,"y":153,"z":2,"connected_nodes_id":[676,691,693]},{"unique_id":693,"x":212,"y":149,"z":2,"connected_nodes_id":[692,698]},{"unique_id":694,"x":212,"y":114,"z":2,"connected_nodes_id":[690,703]},{"unique_id":695,"x":213,"y":188,"z":2,"connected_nodes_id":[696]},{"unique_id":696,"x":213,"y":183,"z":2,"connected_nodes_id":[677,695,697]},{"unique_id":697,"x":213,"y":177,"z":2,"connected_nodes_id":[678,696]},{"unique_id":698,"x":216,"y":149,"z":2,"connected_nodes_id":[693,699]},{"unique_id":699,"x":216,"y":137,"z":2,"connected_nodes_id":[698,700]},{"unique_id":700,"x":216,"y":128,"z":2,"connected_nodes_id":[688,699,701]},{"unique_id":701,"x":216,"y":121,"z":2,"connected_nodes_id":[689,700]},{"unique_id":702,"x":218,"y":118,"z":2,"connected_nodes_id":[703]},{"unique_id":703,"x":218,"y":114,"z":2,"connected_nodes_id":[694,702,704]},{"unique_id":704,"x":218,"y":111,"z":2,"connected_nodes_id":[703]},{"unique_id":705,"x":8,"y":21,"z":3,"connected_nodes_id":[706]},{"unique_id":706,"x":8,"y":15,"z":3,"connected_nodes_id":[705,708]},{"unique_id":707,"x":13,"y":18,"z":3,"connected_nodes_id":[708,712]},{"unique_id":708,"x":13,"y":15,"z":3,"connected_nodes_id":[706,707]},{"unique_id":709,"x":22,"y":37,"z":3,"connected_nodes_id":[710,715]},{"unique_id":710,"x":22,"y":31,"z":3,"connected_nodes_id":[709,711,719]},{"unique_id":711,"x":22,"y":25,"z":3,"connected_nodes_id":[710,712,720]},{"unique_id":712,"x":22,"y":18,"z":3,"connected_nodes_id":[707,711,713]},{"unique_id":713,"x":22,"y":15,"z":3,"connected_nodes_id":[712,714,716]},{"unique_id":714,"x":22,"y":8,"z":3,"connected_nodes_id":[713]},{"unique_id":715,"x":29,"y":37,"z":3,"connected_nodes_id":[709,718]},{"unique_id":716,"x":29,"y":15,"z":3,"connected_nodes_id":[713,717,721]},{"unique_id":717,"x":29,"y":8,"z":3,"connected_nodes_id":[716,722]},{"unique_id":718,"x":34,"y":37,"z":3,"connected_nodes_id":[715,719,728]},{"unique_id":719,"x":34,"y":31,"z":3,"connected_nodes_id":[710,718,720,729]},{"unique_id":720,"x":34,"y":25,"z":3,"connected_nodes_id":[711,719,721]},{"unique_id":721,"x":34,"y":15,"z":3,"connected_nodes_id":[716,720,735]},{"unique_id":722,"x":35,"y":8,"z":3,"connected_nodes_id":[717,723]},{"unique_id":723,"x":36,"y":9,"z":3,"connected_nodes_id":[722,730]},{"unique_id":724,"x":38,"y":51,"z":3,"connected_nodes_id":[725]},{"unique_id":725,"x":38,"y":46,"z":3,"connected_nodes_id":[724,726]},{"unique_id":726,"x":38,"y":40,"z":3,"connected_nodes_id":[725,727]},{"unique_id":727,"x":39,"y":39,"z":3,"connected_nodes_id":[726,728]},{"unique_id":728,"x":39,"y":37,"z":3,"connected_nodes_id":[718,727,729,731]},{"unique_id":729,"x":39,"y":31,"z":3,"connected_nodes_id":[719,728,733]},{"unique_id":730,"x":42,"y":9,"z":3,"connected_nodes_id":[723]},{"unique_id":731,"x":46,"y":37,"z":3,"connected_nodes_id":[728,732]},{"unique_id":732,"x":46,"y":36,"z":3,"connected_nodes_id":[731,733,740]},{"unique_id":733,"x":46,"y":31,"z":3,"connected_nodes_id":[729,732,734,738]},{"unique_id":734,"x":46,"y":17,"z":3,"connected_nodes_id":[733,735,737]},{"unique_id":735,"x":46,"y":15,"z":3,"connected_nodes_id":[721,734]},{"unique_id":736,"x":49,"y":23,"z":3,"connected_nodes_id":[737,739]},{"unique_id":737,"x":49,"y":17,"z":3,"connected_nodes_id":[734,736]},{"unique_id":738,"x":50,"y":31,"z":3,"connected_nodes_id":[733,739]},{"unique_id":739,"x":50,"y":24,"z":3,"connected_nodes_id":[736,738]},{"unique_id":740,"x":51,"y":36,"z":3,"connected_nodes_id":[732]},{"unique_id":741,"x":9,"y":141,"z":2,"connected_nodes_id":[240,753]},{"unique_id":742,"x":14,"y":141,"z":2,"connected_nodes_id":[743,754]},{"unique_id":743,"x":18,"y":141,"z":2,"connected_nodes_id":[742,744]},{"unique_id":744,"x":22,"y":141,"z":2,"connected_nodes_id":[743,745]},{"unique_id":745,"x":26,"y":141,"z":2,"connected_nodes_id":[744,746]},{"unique_id":746,"x":30,"y":141,"z":2,"connected_nodes_id":[745,747]},{"unique_id":747,"x":35,"y":141,"z":2,"connected_nodes_id":[746,748,763]},{"unique_id":748,"x":41,"y":141,"z":2,"connected_nodes_id":[747,749,757]},{"unique_id":749,"x":47,"y":141,"z":2,"connected_nodes_id":[748,750,758]},{"unique_id":750,"x":52,"y":141,"z":2,"connected_nodes_id":[749,751,759]},{"unique_id":751,"x":55,"y":141,"z":2,"connected_nodes_id":[750,294,760]},{"unique_id":752,"x":6,"y":142,"z":2,"connected_nodes_id":[753,755,764]},{"unique_id":753,"x":10,"y":142,"z":2,"connected_nodes_id":[741,752,754,765]},{"unique_id":754,"x":13,"y":142,"z":2,"connected_nodes_id":[742,753,766]},{"unique_id":755,"x":5,"y":143,"z":2,"connected_nodes_id":[752]},{"unique_id":756,"x":36,"y":146,"z":2,"connected_nodes_id":[757,763]},{"unique_id":757,"x":41,"y":146,"z":2,"connected_nodes_id":[748,756,758]},{"unique_id":758,"x":47,"y":146,"z":2,"connected_nodes_id":[749,757,759]},{"unique_id":759,"x":52,"y":146,"z":2,"connected_nodes_id":[750,758,760]},{"unique_id":760,"x":55,"y":146,"z":2,"connected_nodes_id":[751,759,303,767]},{"unique_id":761,"x":26,"y":147,"z":2,"connected_nodes_id":[762,772]},{"unique_id":762,"x":30,"y":147,"z":2,"connected_nodes_id":[761,763,773]},{"unique_id":763,"x":35,"y":147,"z":2,"connected_nodes_id":[747,756,762,774]},{"unique_id":764,"x":6,"y":148,"z":2,"connected_nodes_id":[752,765]},{"unique_id":765,"x":10,"y":148,"z":2,"connected_nodes_id":[753,764,766,775]},{"unique_id":766,"x":13,"y":148,"z":2,"connected_nodes_id":[754,765,776]},{"unique_id":767,"x":55,"y":150,"z":2,"connected_nodes_id":[760]},{"unique_id":768,"x":34,"y":152,"z":2,"connected_nodes_id":[769,774,783]},{"unique_id":769,"x":42,"y":152,"z":2,"connected_nodes_id":[768,770]},{"unique_id":770,"x":48,"y":152,"z":2,"connected_nodes_id":[769,771,777]},{"unique_id":771,"x":53,"y":152,"z":2,"connected_nodes_id":[770,302]},{"unique_id":772,"x":26,"y":153,"z":2,"connected_nodes_id":[761,773]},{"unique_id":773,"x":30,"y":153,"z":2,"connected_nodes_id":[762,772,774,782]},{"unique_id":774,"x":35,"y":153,"z":2,"connected_nodes_id":[763,768,773,785]},{"unique_id":775,"x":10,"y":154,"z":2,"connected_nodes_id":[765,776,780]},{"unique_id":776,"x":13,"y":154,"z":2,"connected_nodes_id":[766,775,781]},{"unique_id":777,"x":48,"y":157,"z":2,"connected_nodes_id":[770,784,778]},{"unique_id":778,"x":53,"y":157,"z":2,"connected_nodes_id":[777,779,788]},{"unique_id":779,"x":54,"y":158,"z":2,"connected_nodes_id":[778,301]},{"unique_id":780,"x":10,"y":159,"z":2,"connected_nodes_id":[775,781,789]},{"unique_id":781,"x":13,"y":159,"z":2,"connected_nodes_id":[776,780,791]},{"unique_id":782,"x":30,"y":159,"z":2,"connected_nodes_id":[773,783]},{"unique_id":783,"x":34,"y":159,"z":2,"connected_nodes_id":[768,782,784,785]},{"unique_id":784,"x":48,"y":159,"z":2,"connected_nodes_id":[777,783,285,787]},{"unique_id":785,"x":35,"y":160,"z":2,"connected_nodes_id":[774,783,786]},{"unique_id":786,"x":41,"y":160,"z":2,"connected_nodes_id":[785,787,793]},{"unique_id":787,"x":47,"y":160,"z":2,"connected_nodes_id":[784,786,283,788]},{"unique_id":788,"x":53,"y":160,"z":2,"connected_nodes_id":[778,787]},{"unique_id":789,"x":10,"y":161,"z":2,"connected_nodes_id":[780,790]},{"unique_id":790,"x":11,"y":162,"z":2,"connected_nodes_id":[789,791]},{"unique_id":791,"x":13,"y":162,"z":2,"connected_nodes_id":[781,790,245,792]},{"unique_id":792,"x":16,"y":162,"z":2,"connected_nodes_id":[791]},{"unique_id":793,"x":41,"y":162,"z":2,"connected_nodes_id":[786,271]},{"unique_id":794,"x":13,"y":78,"z":2,"connected_nodes_id":[795]},{"unique_id":795,"x":16,"y":78,"z":2,"connected_nodes_id":[794,801,859]},{"unique_id":796,"x":27,"y":79,"z":2,"connected_nodes_id":[797,799]},{"unique_id":797,"x":34,"y":79,"z":2,"connected_nodes_id":[796,798]},{"unique_id":798,"x":42,"y":79,"z":2,"connected_nodes_id":[797,273,803]},{"unique_id":799,"x":27,"y":84,"z":2,"connected_nodes_id":[796,802]},{"unique_id":800,"x":11,"y":85,"z":2,"connected_nodes_id":[801,808]},{"unique_id":801,"x":16,"y":85,"z":2,"connected_nodes_id":[795,800,809]},{"unique_id":802,"x":28,"y":85,"z":2,"connected_nodes_id":[799,803,810]},{"unique_id":803,"x":42,"y":85,"z":2,"connected_nodes_id":[798,802,272,804]},{"unique_id":804,"x":41,"y":86,"z":2,"connected_nodes_id":[803,805]},{"unique_id":805,"x":41,"y":89,"z":2,"connected_nodes_id":[804,290,806]},{"unique_id":806,"x":41,"y":91,"z":2,"connected_nodes_id":[805,816]},{"unique_id":807,"x":8,"y":92,"z":2,"connected_nodes_id":[808,815]},{"unique_id":808,"x":11,"y":92,"z":2,"connected_nodes_id":[800,807]},{"unique_id":809,"x":16,"y":92,"z":2,"connected_nodes_id":[801,811]},{"unique_id":810,"x":28,"y":92,"z":2,"connected_nodes_id":[802,814]},{"unique_id":811,"x":16,"y":96,"z":2,"connected_nodes_id":[809,812]},{"unique_id":812,"x":17,"y":97,"z":2,"connected_nodes_id":[811,817]},{"unique_id":813,"x":23,"y":97,"z":2,"connected_nodes_id":[814,818]},{"unique_id":814,"x":28,"y":97,"z":2,"connected_nodes_id":[810,813,819]},{"unique_id":815,"x":8,"y":98,"z":2,"connected_nodes_id":[807,827]},{"unique_id":816,"x":41,"y":98,"z":2,"connected_nodes_id":[806,821]},{"unique_id":817,"x":17,"y":100,"z":2,"connected_nodes_id":[812]},{"unique_id":818,"x":23,"y":100,"z":2,"connected_nodes_id":[813,819,822]},{"unique_id":819,"x":28,"y":100,"z":2,"connected_nodes_id":[814,818,820]},{"unique_id":820,"x":27,"y":101,"z":2,"connected_nodes_id":[819,823]},{"unique_id":821,"x":41,"y":103,"z":2,"connected_nodes_id":[816,280,825]},{"unique_id":822,"x":23,"y":105,"z":2,"connected_nodes_id":[818,823]},{"unique_id":823,"x":27,"y":105,"z":2,"connected_nodes_id":[820,822,824,828]},{"unique_id":824,"x":34,"y":105,"z":2,"connected_nodes_id":[823,825,829]},{"unique_id":825,"x":41,"y":105,"z":2,"connected_nodes_id":[821,824,831]},{"unique_id":826,"x":6,"y":106,"z":2,"connected_nodes_id":[827]},{"unique_id":827,"x":8,"y":106,"z":2,"connected_nodes_id":[815,826,832]},{"unique_id":828,"x":27,"y":109,"z":2,"connected_nodes_id":[823,829]},{"unique_id":829,"x":34,"y":109,"z":2,"connected_nodes_id":[824,828,830]},{"unique_id":830,"x":34,"y":111,"z":2,"connected_nodes_id":[829,831]},{"unique_id":831,"x":41,"y":111,"z":2,"connected_nodes_id":[825,830]},{"unique_id":832,"x":8,"y":113,"z":2,"connected_nodes_id":[827,239,833]},{"unique_id":833,"x":12,"y":113,"z":2,"connected_nodes_id":[832,244]},{"unique_id":834,"x":36,"y":47,"z":2,"connected_nodes_id":[275,835]},{"unique_id":835,"x":35,"y":48,"z":2,"connected_nodes_id":[834,837]},{"unique_id":836,"x":29,"y":49,"z":2,"connected_nodes_id":[837,838]},{"unique_id":837,"x":34,"y":49,"z":2,"connected_nodes_id":[835,836]},{"unique_id":838,"x":28,"y":50,"z":2,"connected_nodes_id":[836]},{"unique_id":839,"x":40,"y":54,"z":2,"connected_nodes_id":[840,976]},{"unique_id":840,"x":40,"y":56,"z":2,"connected_nodes_id":[839,842,844]},{"unique_id":841,"x":34,"y":57,"z":2,"connected_nodes_id":[842,843]},{"unique_id":842,"x":39,"y":57,"z":2,"connected_nodes_id":[840,841,844,847]},{"unique_id":843,"x":35,"y":58,"z":2,"connected_nodes_id":[841,844]},{"unique_id":844,"x":40,"y":58,"z":2,"connected_nodes_id":[840,842,843]},{"unique_id":845,"x":25,"y":60,"z":2,"connected_nodes_id":[850]},{"unique_id":846,"x":33,"y":61,"z":2,"connected_nodes_id":[847,848,852]},{"unique_id":847,"x":39,"y":61,"z":2,"connected_nodes_id":[842,846]},{"unique_id":848,"x":34,"y":62,"z":2,"connected_nodes_id":[846,852]},{"unique_id":849,"x":22,"y":63,"z":2,"connected_nodes_id":[850]},{"unique_id":850,"x":25,"y":63,"z":2,"connected_nodes_id":[845,849,851,854]},{"unique_id":851,"x":30,"y":63,"z":2,"connected_nodes_id":[850,852,855]},{"unique_id":852,"x":33,"y":63,"z":2,"connected_nodes_id":[846,848,851]},{"unique_id":853,"x":20,"y":70,"z":2,"connected_nodes_id":[854,857]},{"unique_id":854,"x":25,"y":70,"z":2,"connected_nodes_id":[850,853,855]},{"unique_id":855,"x":30,"y":70,"z":2,"connected_nodes_id":[851,854,856,858]},{"unique_id":856,"x":35,"y":70,"z":2,"connected_nodes_id":[855,861]},{"unique_id":857,"x":19,"y":71,"z":2,"connected_nodes_id":[853,858]},{"unique_id":858,"x":29,"y":71,"z":2,"connected_nodes_id":[855,857]},{"unique_id":859,"x":16,"y":73,"z":2,"connected_nodes_id":[795,860]},{"unique_id":860,"x":22,"y":73,"z":2,"connected_nodes_id":[859]},{"unique_id":861,"x":35,"y":73,"z":2,"connected_nodes_id":[856,274]},{"unique_id":862,"x":42,"y":175,"z":2,"connected_nodes_id":[270,868]},{"unique_id":863,"x":11,"y":178,"z":2,"connected_nodes_id":[864,869]},{"unique_id":864,"x":15,"y":178,"z":2,"connected_nodes_id":[863,865,871]},{"unique_id":865,"x":20,"y":178,"z":2,"connected_nodes_id":[864,866,872]},{"unique_id":866,"x":26,"y":178,"z":2,"connected_nodes_id":[865,867,873]},{"unique_id":867,"x":31,"y":178,"z":2,"connected_nodes_id":[866,874]},{"unique_id":868,"x":42,"y":178,"z":2,"connected_nodes_id":[862,882]},{"unique_id":869,"x":11,"y":182,"z":2,"connected_nodes_id":[863,870,885]},{"unique_id":870,"x":13,"y":182,"z":2,"connected_nodes_id":[869,871]},{"unique_id":871,"x":15,"y":182,"z":2,"connected_nodes_id":[864,870,872]},{"unique_id":872,"x":20,"y":182,"z":2,"connected_nodes_id":[865,871,873,878]},{"unique_id":873,"x":26,"y":182,"z":2,"connected_nodes_id":[866,872,874]},{"unique_id":874,"x":31,"y":182,"z":2,"connected_nodes_id":[867,873,875]},{"unique_id":875,"x":34,"y":182,"z":2,"connected_nodes_id":[874,881]},{"unique_id":876,"x":47,"y":184,"z":2,"connected_nodes_id":[883]},{"unique_id":877,"x":59,"y":184,"z":2,"connected_nodes_id":[879]},{"unique_id":878,"x":20,"y":188,"z":2,"connected_nodes_id":[872,889]},{"unique_id":879,"x":59,"y":188,"z":2,"connected_nodes_id":[877,880]},{"unique_id":880,"x":68,"y":188,"z":2,"connected_nodes_id":[879,892]},{"unique_id":881,"x":34,"y":189,"z":2,"connected_nodes_id":[875,882,896]},{"unique_id":882,"x":42,"y":189,"z":2,"connected_nodes_id":[868,881,883,890]},{"unique_id":883,"x":47,"y":189,"z":2,"connected_nodes_id":[876,882,884]},{"unique_id":884,"x":50,"y":189,"z":2,"connected_nodes_id":[883,891]},{"unique_id":885,"x":11,"y":190,"z":2,"connected_nodes_id":[869,886]},{"unique_id":886,"x":16,"y":190,"z":2,"connected_nodes_id":[885,898]},{"unique_id":887,"x":84,"y":192,"z":2,"connected_nodes_id":[888,895]},{"unique_id":888,"x":90,"y":192,"z":2,"connected_nodes_id":[887,378,904]},{"unique_id":889,"x":20,"y":193,"z":2,"connected_nodes_id":[878,899]},{"unique_id":890,"x":42,"y":193,"z":2,"connected_nodes_id":[882,891,897,900]},{"unique_id":891,"x":50,"y":193,"z":2,"connected_nodes_id":[884,890]},{"unique_id":892,"x":68,"y":193,"z":2,"connected_nodes_id":[880,893]},{"unique_id":893,"x":72,"y":193,"z":2,"connected_nodes_id":[892,894,911]},{"unique_id":894,"x":77,"y":193,"z":2,"connected_nodes_id":[893,895]},{"unique_id":895,"x":83,"y":193,"z":2,"connected_nodes_id":[887,894,903]},{"unique_id":896,"x":34,"y":194,"z":2,"connected_nodes_id":[881,897,907]},{"unique_id":897,"x":41,"y":194,"z":2,"connected_nodes_id":[890,896,900]},{"unique_id":898,"x":16,"y":195,"z":2,"connected_nodes_id":[886,899]},{"unique_id":899,"x":20,"y":195,"z":2,"connected_nodes_id":[889,898,905]},{"unique_id":900,"x":42,"y":195,"z":2,"connected_nodes_id":[890,897,908]},{"unique_id":901,"x":49,"y":195,"z":2,"connected_nodes_id":[902]},{"unique_id":902,"x":48,"y":196,"z":2,"connected_nodes_id":[901,909]},{"unique_id":903,"x":83,"y":196,"z":2,"connected_nodes_id":[895,904]},{"unique_id":904,"x":90,"y":196,"z":2,"connected_nodes_id":[888,903]},{"unique_id":905,"x":20,"y":198,"z":2,"connected_nodes_id":[899,906]},{"unique_id":906,"x":19,"y":199,"z":2,"connected_nodes_id":[905,912]},{"unique_id":907,"x":34,"y":200,"z":2,"connected_nodes_id":[896,908,915]},{"unique_id":908,"x":42,"y":200,"z":2,"connected_nodes_id":[900,907,909]},{"unique_id":909,"x":48,"y":200,"z":2,"connected_nodes_id":[902,908]},{"unique_id":910,"x":65,"y":200,"z":2,"connected_nodes_id":[911,919]},{"unique_id":911,"x":72,"y":200,"z":2,"connected_nodes_id":[893,910]},{"unique_id":912,"x":19,"y":204,"z":2,"connected_nodes_id":[906,913]},{"unique_id":913,"x":24,"y":204,"z":2,"connected_nodes_id":[912,914]},{"unique_id":914,"x":32,"y":204,"z":2,"connected_nodes_id":[913,915]},{"unique_id":915,"x":34,"y":204,"z":2,"connected_nodes_id":[907,914,916]},{"unique_id":916,"x":39,"y":204,"z":2,"connected_nodes_id":[915,920]},{"unique_id":917,"x":43,"y":204,"z":2,"connected_nodes_id":[921]},{"unique_id":918,"x":57,"y":204,"z":2,"connected_nodes_id":[919,926]},{"unique_id":919,"x":65,"y":204,"z":2,"connected_nodes_id":[910,918]},{"unique_id":920,"x":38,"y":205,"z":2,"connected_nodes_id":[916]},{"unique_id":921,"x":44,"y":205,"z":2,"connected_nodes_id":[917,924]},{"unique_id":922,"x":42,"y":207,"z":2,"connected_nodes_id":[923]},{"unique_id":923,"x":49,"y":207,"z":2,"connected_nodes_id":[922,925]},{"unique_id":924,"x":44,"y":208,"z":2,"connected_nodes_id":[921,925]},{"unique_id":925,"x":48,"y":208,"z":2,"connected_nodes_id":[923,924,926]},{"unique_id":926,"x":57,"y":208,"z":2,"connected_nodes_id":[918,925]},{"unique_id":927,"x":51,"y":122,"z":2,"connected_nodes_id":[288,928]},{"unique_id":928,"x":52,"y":123,"z":2,"connected_nodes_id":[927,929]},{"unique_id":929,"x":63,"y":123,"z":2,"connected_nodes_id":[928,335]},{"unique_id":930,"x":43,"y":125,"z":2,"connected_nodes_id":[268,931,937]},{"unique_id":931,"x":46,"y":125,"z":2,"connected_nodes_id":[930,277,932]},{"unique_id":932,"x":48,"y":125,"z":2,"connected_nodes_id":[931,933,938]},{"unique_id":933,"x":58,"y":125,"z":2,"connected_nodes_id":[932,934,940]},{"unique_id":934,"x":59,"y":126,"z":2,"connected_nodes_id":[933,935]},{"unique_id":935,"x":67,"y":126,"z":2,"connected_nodes_id":[934,936]},{"unique_id":936,"x":66,"y":127,"z":2,"connected_nodes_id":[935,942]},{"unique_id":937,"x":43,"y":133,"z":2,"connected_nodes_id":[930,938]},{"unique_id":938,"x":48,"y":133,"z":2,"connected_nodes_id":[932,937,939]},{"unique_id":939,"x":54,"y":133,"z":2,"connected_nodes_id":[938,293,940]},{"unique_id":940,"x":58,"y":133,"z":2,"connected_nodes_id":[933,939,941]},{"unique_id":941,"x":63,"y":133,"z":2,"connected_nodes_id":[940,942]},{"unique_id":942,"x":66,"y":133,"z":2,"connected_nodes_id":[936,941]},{"unique_id":943,"x":99,"y":8,"z":2,"connected_nodes_id":[944,947]},{"unique_id":944,"x":104,"y":8,"z":2,"connected_nodes_id":[943]},{"unique_id":945,"x":85,"y":15,"z":2,"connected_nodes_id":[946,948]},{"unique_id":946,"x":92,"y":15,"z":2,"connected_nodes_id":[945,947]},{"unique_id":947,"x":99,"y":15,"z":2,"connected_nodes_id":[943,946,949]},{"unique_id":948,"x":85,"y":20,"z":2,"connected_nodes_id":[945,951]},{"unique_id":949,"x":99,"y":22,"z":2,"connected_nodes_id":[947,950]},{"unique_id":950,"x":99,"y":30,"z":2,"connected_nodes_id":[949,953]},{"unique_id":951,"x":85,"y":31,"z":2,"connected_nodes_id":[948,960]},{"unique_id":952,"x":93,"y":33,"z":2,"connected_nodes_id":[953,955]},{"unique_id":953,"x":99,"y":33,"z":2,"connected_nodes_id":[950,952,954]},{"unique_id":954,"x":103,"y":33,"z":2,"connected_nodes_id":[953,426]},{"unique_id":955,"x":93,"y":39,"z":2,"connected_nodes_id":[952,956]},{"unique_id":956,"x":98,"y":39,"z":2,"connected_nodes_id":[955]},{"unique_id":957,"x":103,"y":39,"z":2,"connected_nodes_id":[412]},{"unique_id":958,"x":86,"y":41,"z":2,"connected_nodes_id":[960,961]},{"unique_id":959,"x":79,"y":42,"z":2,"connected_nodes_id":[960,964]},{"unique_id":960,"x":85,"y":42,"z":2,"connected_nodes_id":[958,959,951]},{"unique_id":961,"x":86,"y":44,"z":2,"connected_nodes_id":[958,962]},{"unique_id":962,"x":88,"y":44,"z":2,"connected_nodes_id":[961,966,968]},{"unique_id":963,"x":74,"y":45,"z":2,"connected_nodes_id":[964,972]},{"unique_id":964,"x":79,"y":45,"z":2,"connected_nodes_id":[959,963,965]},{"unique_id":965,"x":82,"y":45,"z":2,"connected_nodes_id":[964,966,975]},{"unique_id":966,"x":89,"y":45,"z":2,"connected_nodes_id":[962,965]},{"unique_id":967,"x":51,"y":47,"z":2,"connected_nodes_id":[275,969]},{"unique_id":968,"x":88,"y":47,"z":2,"connected_nodes_id":[962,381,973]},{"unique_id":969,"x":52,"y":48,"z":2,"connected_nodes_id":[967,970]},{"unique_id":970,"x":61,"y":48,"z":2,"connected_nodes_id":[969,971]},{"unique_id":971,"x":70,"y":48,"z":2,"connected_nodes_id":[970,972]},{"unique_id":972,"x":74,"y":48,"z":2,"connected_nodes_id":[963,971]},{"unique_id":973,"x":88,"y":50,"z":2,"connected_nodes_id":[968,357]},{"unique_id":974,"x":78,"y":52,"z":2,"connected_nodes_id":[975,979]},{"unique_id":975,"x":82,"y":52,"z":2,"connected_nodes_id":[965,974,980]},{"unique_id":976,"x":47,"y":54,"z":2,"connected_nodes_id":[839,977]},{"unique_id":977,"x":52,"y":54,"z":2,"connected_nodes_id":[976,982]},{"unique_id":978,"x":73,"y":55,"z":2,"connected_nodes_id":[979,984]},{"unique_id":979,"x":78,"y":55,"z":2,"connected_nodes_id":[974,978]},{"unique_id":980,"x":82,"y":55,"z":2,"connected_nodes_id":[975,981]},{"unique_id":981,"x":85,"y":55,"z":2,"connected_nodes_id":[980,988]},{"unique_id":982,"x":52,"y":59,"z":2,"connected_nodes_id":[977,983]},{"unique_id":983,"x":55,"y":59,"z":2,"connected_nodes_id":[982,298]},{"unique_id":984,"x":73,"y":60,"z":2,"connected_nodes_id":[978,986]},{"unique_id":985,"x":63,"y":61,"z":2,"connected_nodes_id":[986,1041]},{"unique_id":986,"x":72,"y":61,"z":2,"connected_nodes_id":[984,985,987]},{"unique_id":987,"x":83,"y":61,"z":2,"connected_nodes_id":[986,342,988]},{"unique_id":988,"x":85,"y":61,"z":2,"connected_nodes_id":[981,987]},{"unique_id":989,"x":52,"y":97,"z":2,"connected_nodes_id":[281,290,990,992]},{"unique_id":990,"x":59,"y":97,"z":2,"connected_nodes_id":[989,308,996]},{"unique_id":991,"x":65,"y":100,"z":2,"connected_nodes_id":[326,997]},{"unique_id":992,"x":52,"y":102,"z":2,"connected_nodes_id":[989,995]},{"unique_id":993,"x":56,"y":102,"z":2,"connected_nodes_id":[998,994]},{"unique_id":994,"x":60,"y":102,"z":2,"connected_nodes_id":[993,996]},{"unique_id":995,"x":51,"y":103,"z":2,"connected_nodes_id":[992,280,996]},{"unique_id":996,"x":59,"y":103,"z":2,"connected_nodes_id":[990,994,995,997]},{"unique_id":997,"x":65,"y":103,"z":2,"connected_nodes_id":[991,996,338,999]},{"unique_id":998,"x":56,"y":107,"z":2,"connected_nodes_id":[993,305]},{"unique_id":999,"x":65,"y":108,"z":2,"connected_nodes_id":[997,325,1002]},{"unique_id":1000,"x":50,"y":113,"z":2,"connected_nodes_id":[279,289]},{"unique_id":1001,"x":63,"y":113,"z":2,"connected_nodes_id":[312,1002]},{"unique_id":1002,"x":65,"y":113,"z":2,"connected_nodes_id":[999,1001,318]},{"unique_id":1003,"x":70,"y":142,"z":2,"connected_nodes_id":[1010]},{"unique_id":1004,"x":76,"y":142,"z":2,"connected_nodes_id":[1011]},{"unique_id":1005,"x":60,"y":143,"z":2,"connected_nodes_id":[1006,1020]},{"unique_id":1006,"x":65,"y":143,"z":2,"connected_nodes_id":[1005,1009]},{"unique_id":1007,"x":81,"y":144,"z":2,"connected_nodes_id":[1008,1085]},{"unique_id":1008,"x":82,"y":145,"z":2,"connected_nodes_id":[1007,1012]},{"unique_id":1009,"x":65,"y":146,"z":2,"connected_nodes_id":[1006,1010,1014]},{"unique_id":1010,"x":70,"y":146,"z":2,"connected_nodes_id":[1003,1009,1011]},{"unique_id":1011,"x":76,"y":146,"z":2,"connected_nodes_id":[1004,1010,1016]},{"unique_id":1012,"x":83,"y":146,"z":2,"connected_nodes_id":[1008,1018]},{"unique_id":1013,"x":87,"y":147,"z":2,"connected_nodes_id":[345,353,1019]},{"unique_id":1014,"x":65,"y":149,"z":2,"connected_nodes_id":[1009,1015,1023]},{"unique_id":1015,"x":66,"y":150,"z":2,"connected_nodes_id":[1014,1016,1025]},{"unique_id":1016,"x":76,"y":150,"z":2,"connected_nodes_id":[1011,1015,1017,1027]},{"unique_id":1017,"x":80,"y":150,"z":2,"connected_nodes_id":[1016,1018,1028]},{"unique_id":1018,"x":83,"y":150,"z":2,"connected_nodes_id":[1012,1017,1019]},{"unique_id":1019,"x":87,"y":150,"z":2,"connected_nodes_id":[1013,1018]},{"unique_id":1020,"x":60,"y":152,"z":2,"connected_nodes_id":[1005,302,1021,1022]},{"unique_id":1021,"x":59,"y":153,"z":2,"connected_nodes_id":[1020,1022,1024]},{"unique_id":1022,"x":61,"y":153,"z":2,"connected_nodes_id":[1020,1021,1040]},{"unique_id":1023,"x":65,"y":154,"z":2,"connected_nodes_id":[1014,1025]},{"unique_id":1024,"x":59,"y":155,"z":2,"connected_nodes_id":[1021,1025,1039]},{"unique_id":1025,"x":66,"y":155,"z":2,"connected_nodes_id":[1015,1023,1024,317,1026,1030]},{"unique_id":1026,"x":73,"y":155,"z":2,"connected_nodes_id":[1025,1027]},{"unique_id":1027,"x":76,"y":155,"z":2,"connected_nodes_id":[1016,1026,1028,1031,1036]},{"unique_id":1028,"x":80,"y":155,"z":2,"connected_nodes_id":[1017,1027,1029,1037]},{"unique_id":1029,"x":83,"y":155,"z":2,"connected_nodes_id":[1028]},{"unique_id":1030,"x":67,"y":156,"z":2,"connected_nodes_id":[1025,1032,1031]},{"unique_id":1031,"x":77,"y":156,"z":2,"connected_nodes_id":[1027,1030]},{"unique_id":1032,"x":67,"y":160,"z":2,"connected_nodes_id":[1030,321,1033,1034]},{"unique_id":1033,"x":72,"y":160,"z":2,"connected_nodes_id":[1032,1035]},{"unique_id":1034,"x":68,"y":161,"z":2,"connected_nodes_id":[1032,322]},{"unique_id":1035,"x":73,"y":161,"z":2,"connected_nodes_id":[1033,1036]},{"unique_id":1036,"x":76,"y":161,"z":2,"connected_nodes_id":[1027,1035,1037]},{"unique_id":1037,"x":80,"y":161,"z":2,"connected_nodes_id":[1028,1036,1038]},{"unique_id":1038,"x":83,"y":161,"z":2,"connected_nodes_id":[1037]},{"unique_id":1039,"x":59,"y":162,"z":2,"connected_nodes_id":[1024,1040]},{"unique_id":1040,"x":61,"y":162,"z":2,"connected_nodes_id":[1022,1039]},{"unique_id":1041,"x":63,"y":66,"z":2,"connected_nodes_id":[298,985,1046]},{"unique_id":1042,"x":67,"y":70,"z":2,"connected_nodes_id":[1043,1047]},{"unique_id":1043,"x":76,"y":70,"z":2,"connected_nodes_id":[1042,1044,1048]},{"unique_id":1044,"x":85,"y":70,"z":2,"connected_nodes_id":[1043,1049]},{"unique_id":1045,"x":89,"y":70,"z":2,"connected_nodes_id":[348,369]},{"unique_id":1046,"x":63,"y":73,"z":2,"connected_nodes_id":[1041,297,1051]},{"unique_id":1047,"x":67,"y":74,"z":2,"connected_nodes_id":[1042,1048,1052]},{"unique_id":1048,"x":76,"y":74,"z":2,"connected_nodes_id":[1043,1047,1049]},{"unique_id":1049,"x":85,"y":74,"z":2,"connected_nodes_id":[1044,1048,1054]},{"unique_id":1050,"x":88,"y":77,"z":2,"connected_nodes_id":[367,1055]},{"unique_id":1051,"x":63,"y":78,"z":2,"connected_nodes_id":[1046,296]},{"unique_id":1052,"x":67,"y":82,"z":2,"connected_nodes_id":[1047,307,1053,1057]},{"unique_id":1053,"x":76,"y":82,"z":2,"connected_nodes_id":[1052,1054,1060]},{"unique_id":1054,"x":85,"y":82,"z":2,"connected_nodes_id":[1049,1053,1062,1055]},{"unique_id":1055,"x":88,"y":82,"z":2,"connected_nodes_id":[1050,1054]},{"unique_id":1056,"x":61,"y":85,"z":2,"connected_nodes_id":[309,311,1057]},{"unique_id":1057,"x":67,"y":85,"z":2,"connected_nodes_id":[1052,1056,1058]},{"unique_id":1058,"x":71,"y":85,"z":2,"connected_nodes_id":[1057,1059]},{"unique_id":1059,"x":71,"y":87,"z":2,"connected_nodes_id":[1058,1064,1060]},{"unique_id":1060,"x":76,"y":87,"z":2,"connected_nodes_id":[1053,1059,1061]},{"unique_id":1061,"x":81,"y":87,"z":2,"connected_nodes_id":[1060,341,1062]},{"unique_id":1062,"x":85,"y":87,"z":2,"connected_nodes_id":[1054,1061,344]},{"unique_id":1063,"x":64,"y":89,"z":2,"connected_nodes_id":[315,1064]},{"unique_id":1064,"x":71,"y":89,"z":2,"connected_nodes_id":[1059,1063,331]},{"unique_id":1065,"x":98,"y":115,"z":2,"connected_nodes_id":[1066,1069]},{"unique_id":1066,"x":103,"y":115,"z":2,"connected_nodes_id":[1065,400]},{"unique_id":1067,"x":85,"y":120,"z":2,"connected_nodes_id":[1068,1071]},{"unique_id":1068,"x":92,"y":120,"z":2,"connected_nodes_id":[1067,1069,1074]},{"unique_id":1069,"x":98,"y":120,"z":2,"connected_nodes_id":[1065,1068,1073]},{"unique_id":1070,"x":81,"y":124,"z":2,"connected_nodes_id":[1071,1079]},{"unique_id":1071,"x":85,"y":124,"z":2,"connected_nodes_id":[1067,1070,1072]},{"unique_id":1072,"x":88,"y":124,"z":2,"connected_nodes_id":[1071,1077]},{"unique_id":1073,"x":98,"y":124,"z":2,"connected_nodes_id":[1069,1082]},{"unique_id":1074,"x":92,"y":125,"z":2,"connected_nodes_id":[1068,1075]},{"unique_id":1075,"x":95,"y":125,"z":2,"connected_nodes_id":[1074,1076]},{"unique_id":1076,"x":95,"y":128,"z":2,"connected_nodes_id":[1075]},{"unique_id":1077,"x":88,"y":129,"z":2,"connected_nodes_id":[1072,1078]},{"unique_id":1078,"x":91,"y":129,"z":2,"connected_nodes_id":[1077,1081]},{"unique_id":1079,"x":81,"y":131,"z":2,"connected_nodes_id":[1070,1085,1080]},{"unique_id":1080,"x":88,"y":131,"z":2,"connected_nodes_id":[1079,1083]},{"unique_id":1081,"x":91,"y":132,"z":2,"connected_nodes_id":[1078,1084]},{"unique_id":1082,"x":98,"y":132,"z":2,"connected_nodes_id":[1073]},{"unique_id":1083,"x":88,"y":133,"z":2,"connected_nodes_id":[1080,1084]},{"unique_id":1084,"x":91,"y":133,"z":2,"connected_nodes_id":[1081,1083,355]},{"unique_id":1085,"x":81,"y":137,"z":2,"connected_nodes_id":[333,345,1007,1079]},{"unique_id":1086,"x":85,"y":100,"z":2,"connected_nodes_id":[344,1087]},{"unique_id":1087,"x":93,"y":100,"z":2,"connected_nodes_id":[1086,1090,362,387]},{"unique_id":1088,"x":78,"y":104,"z":2,"connected_nodes_id":[]},{"unique_id":1089,"x":84,"y":104,"z":2,"connected_nodes_id":[1090]},{"unique_id":1090,"x":93,"y":104,"z":2,"connected_nodes_id":[1087,1089,361]},{"unique_id":1091,"x":109,"y":150,"z":2,"connected_nodes_id":[1092,1094]},{"unique_id":1092,"x":115,"y":150,"z":2,"connected_nodes_id":[1091,1100,478]},{"unique_id":1093,"x":101,"y":151,"z":2,"connected_nodes_id":[392,1094,1095]},{"unique_id":1094,"x":110,"y":151,"z":2,"connected_nodes_id":[1091,1093,439,1099]},{"unique_id":1095,"x":101,"y":153,"z":2,"connected_nodes_id":[1093,1096]},{"unique_id":1096,"x":100,"y":154,"z":2,"connected_nodes_id":[1095,1097]},{"unique_id":1097,"x":99,"y":155,"z":2,"connected_nodes_id":[1096,375,385,1098]},{"unique_id":1098,"x":104,"y":155,"z":2,"connected_nodes_id":[1097,1099]},{"unique_id":1099,"x":110,"y":155,"z":2,"connected_nodes_id":[1094,1098,1100]},{"unique_id":1100,"x":115,"y":155,"z":2,"connected_nodes_id":[1092,1099,467,477,1101]},{"unique_id":1101,"x":116,"y":156,"z":2,"connected_nodes_id":[1100]},{"unique_id":1102,"x":129,"y":70,"z":2,"connected_nodes_id":[527,1104]},{"unique_id":1103,"x":120,"y":73,"z":2,"connected_nodes_id":[445,1104,1107]},{"unique_id":1104,"x":129,"y":73,"z":2,"connected_nodes_id":[1102,1103,1108]},{"unique_id":1105,"x":111,"y":80,"z":2,"connected_nodes_id":[444,1106]},{"unique_id":1106,"x":112,"y":81,"z":2,"connected_nodes_id":[1105,1107,1111]},{"unique_id":1107,"x":120,"y":81,"z":2,"connected_nodes_id":[1103,1106,1108,1112]},{"unique_id":1108,"x":129,"y":81,"z":2,"connected_nodes_id":[1104,1107,1109]},{"unique_id":1109,"x":129,"y":87,"z":2,"connected_nodes_id":[1108,1110,1113]},{"unique_id":1110,"x":133,"y":87,"z":2,"connected_nodes_id":[1109,1117,1165]},{"unique_id":1111,"x":112,"y":89,"z":2,"connected_nodes_id":[1106,1112,1114]},{"unique_id":1112,"x":120,"y":89,"z":2,"connected_nodes_id":[1107,1111,1113]},{"unique_id":1113,"x":129,"y":89,"z":2,"connected_nodes_id":[1109,1112]},{"unique_id":1114,"x":111,"y":90,"z":2,"connected_nodes_id":[1111,418]},{"unique_id":1115,"x":113,"y":93,"z":2,"connected_nodes_id":[417,1116]},{"unique_id":1116,"x":118,"y":93,"z":2,"connected_nodes_id":[1115,471]},{"unique_id":1117,"x":133,"y":94,"z":2,"connected_nodes_id":[1110,517,518]},{"unique_id":1118,"x":136,"y":105,"z":2,"connected_nodes_id":[519,1124]},{"unique_id":1119,"x":122,"y":110,"z":2,"connected_nodes_id":[490,1120]},{"unique_id":1120,"x":124,"y":110,"z":2,"connected_nodes_id":[1119,1121]},{"unique_id":1121,"x":127,"y":110,"z":2,"connected_nodes_id":[1120,1127,1122]},{"unique_id":1122,"x":130,"y":110,"z":2,"connected_nodes_id":[1121,510,540,1123]},{"unique_id":1123,"x":131,"y":111,"z":2,"connected_nodes_id":[1122,1124,1126]},{"unique_id":1124,"x":136,"y":111,"z":2,"connected_nodes_id":[1118,1123,542]},{"unique_id":1125,"x":117,"y":112,"z":2,"connected_nodes_id":[]},{"unique_id":1126,"x":131,"y":115,"z":2,"connected_nodes_id":[1123]},{"unique_id":1127,"x":127,"y":116,"z":2,"connected_nodes_id":[1121,502]},{"unique_id":1128,"x":131,"y":121,"z":2,"connected_nodes_id":[513,1129]},{"unique_id":1129,"x":138,"y":121,"z":2,"connected_nodes_id":[1128,534,538]},{"unique_id":1130,"x":134,"y":148,"z":2,"connected_nodes_id":[1131,1133,1134]},{"unique_id":1131,"x":141,"y":148,"z":2,"connected_nodes_id":[1130,564]},{"unique_id":1132,"x":129,"y":149,"z":2,"connected_nodes_id":[487,504,1133]},{"unique_id":1133,"x":133,"y":149,"z":2,"connected_nodes_id":[1130,1132,516,1136]},{"unique_id":1134,"x":134,"y":154,"z":2,"connected_nodes_id":[1130,1136]},{"unique_id":1135,"x":128,"y":155,"z":2,"connected_nodes_id":[477,1136,1138]},{"unique_id":1136,"x":133,"y":155,"z":2,"connected_nodes_id":[1133,1134,1135,1137]},{"unique_id":1137,"x":137,"y":155,"z":2,"connected_nodes_id":[1136,1140]},{"unique_id":1138,"x":128,"y":159,"z":2,"connected_nodes_id":[1135,1139]},{"unique_id":1139,"x":132,"y":159,"z":2,"connected_nodes_id":[1138,1143]},{"unique_id":1140,"x":137,"y":159,"z":2,"connected_nodes_id":[1137,1144]},{"unique_id":1141,"x":144,"y":159,"z":2,"connected_nodes_id":[1145]},{"unique_id":1142,"x":126,"y":164,"z":2,"connected_nodes_id":[485]},{"unique_id":1143,"x":132,"y":165,"z":2,"connected_nodes_id":[1139,1144,1146]},{"unique_id":1144,"x":137,"y":165,"z":2,"connected_nodes_id":[1140,1143,1145]},{"unique_id":1145,"x":144,"y":165,"z":2,"connected_nodes_id":[1141,1144]},{"unique_id":1146,"x":132,"y":169,"z":2,"connected_nodes_id":[1143,1147]},{"unique_id":1147,"x":140,"y":169,"z":2,"connected_nodes_id":[1146,536]},{"unique_id":1148,"x":147,"y":182,"z":2,"connected_nodes_id":[558,1151]},{"unique_id":1149,"x":153,"y":182,"z":2,"connected_nodes_id":[580,1150]},{"unique_id":1150,"x":158,"y":182,"z":2,"connected_nodes_id":[1149,1158]},{"unique_id":1151,"x":146,"y":183,"z":2,"connected_nodes_id":[1148,1156]},{"unique_id":1152,"x":187,"y":183,"z":2,"connected_nodes_id":[1153,1162]},{"unique_id":1153,"x":193,"y":183,"z":2,"connected_nodes_id":[1152,661,1154]},{"unique_id":1154,"x":195,"y":183,"z":2,"connected_nodes_id":[1153,677]},{"unique_id":1155,"x":140,"y":184,"z":2,"connected_nodes_id":[512,1156,1163]},{"unique_id":1156,"x":145,"y":184,"z":2,"connected_nodes_id":[1151,1155]},{"unique_id":1157,"x":186,"y":186,"z":2,"connected_nodes_id":[1162]},{"unique_id":1158,"x":158,"y":187,"z":2,"connected_nodes_id":[1150,1159]},{"unique_id":1159,"x":163,"y":187,"z":2,"connected_nodes_id":[1158,1160,1164]},{"unique_id":1160,"x":168,"y":187,"z":2,"connected_nodes_id":[1159,1161]},{"unique_id":1161,"x":178,"y":187,"z":2,"connected_nodes_id":[1160,1162]},{"unique_id":1162,"x":187,"y":187,"z":2,"connected_nodes_id":[1152,1157,1161]},{"unique_id":1163,"x":140,"y":189,"z":2,"connected_nodes_id":[1155]},{"unique_id":1164,"x":163,"y":191,"z":2,"connected_nodes_id":[1159]},{"unique_id":1165,"x":140,"y":87,"z":2,"connected_nodes_id":[574,1110]},{"unique_id":1166,"x":154,"y":135,"z":2,"connected_nodes_id":[584,1167,1170]},{"unique_id":1167,"x":153,"y":136,"z":2,"connected_nodes_id":[1166,1168]},{"unique_id":1168,"x":153,"y":143,"z":2,"connected_nodes_id":[1167,547,1169]},{"unique_id":1169,"x":153,"y":145,"z":2,"connected_nodes_id":[1168,1170]},{"unique_id":1170,"x":154,"y":146,"z":2,"connected_nodes_id":[1166,1169,1171]},{"unique_id":1171,"x":158,"y":146,"z":2,"connected_nodes_id":[1170]},{"unique_id":1172,"x":152,"y":70,"z":2,"connected_nodes_id":[550,1173]},{"unique_id":1173,"x":156,"y":70,"z":2,"connected_nodes_id":[1172,1174,1188]},{"unique_id":1174,"x":164,"y":70,"z":2,"connected_nodes_id":[1173,1175]},{"unique_id":1175,"x":172,"y":70,"z":2,"connected_nodes_id":[1174,1176]},{"unique_id":1176,"x":176,"y":70,"z":2,"connected_nodes_id":[1175,1177,1293]},{"unique_id":1177,"x":180,"y":70,"z":2,"connected_nodes_id":[1176,1178]},{"unique_id":1178,"x":184,"y":70,"z":2,"connected_nodes_id":[1177,1179,1184]},{"unique_id":1179,"x":186,"y":70,"z":2,"connected_nodes_id":[1178,1291]},{"unique_id":1180,"x":198,"y":71,"z":2,"connected_nodes_id":[1181,1187,1294]},{"unique_id":1181,"x":202,"y":71,"z":2,"connected_nodes_id":[1180,1295]},{"unique_id":1182,"x":178,"y":77,"z":2,"connected_nodes_id":[1183,1193]},{"unique_id":1183,"x":183,"y":77,"z":2,"connected_nodes_id":[1182,1184]},{"unique_id":1184,"x":184,"y":78,"z":2,"connected_nodes_id":[1178,1183,1185]},{"unique_id":1185,"x":185,"y":79,"z":2,"connected_nodes_id":[1184,1186]},{"unique_id":1186,"x":192,"y":79,"z":2,"connected_nodes_id":[1185,1187]},{"unique_id":1187,"x":198,"y":79,"z":2,"connected_nodes_id":[1180,1186,1194]},{"unique_id":1188,"x":156,"y":80,"z":2,"connected_nodes_id":[1173,1189]},{"unique_id":1189,"x":157,"y":81,"z":2,"connected_nodes_id":[1188,1190]},{"unique_id":1190,"x":157,"y":84,"z":2,"connected_nodes_id":[1189,575,1191]},{"unique_id":1191,"x":158,"y":85,"z":2,"connected_nodes_id":[1190,1192]},{"unique_id":1192,"x":158,"y":86,"z":2,"connected_nodes_id":[1191,1195]},{"unique_id":1193,"x":178,"y":87,"z":2,"connected_nodes_id":[1182,1197]},{"unique_id":1194,"x":198,"y":87,"z":2,"connected_nodes_id":[1187,1199]},{"unique_id":1195,"x":158,"y":89,"z":2,"connected_nodes_id":[1192,1196]},{"unique_id":1196,"x":164,"y":89,"z":2,"connected_nodes_id":[1195]},{"unique_id":1197,"x":178,"y":94,"z":2,"connected_nodes_id":[1193,1198,1202]},{"unique_id":1198,"x":188,"y":94,"z":2,"connected_nodes_id":[1197,1206]},{"unique_id":1199,"x":198,"y":96,"z":2,"connected_nodes_id":[1194,1207]},{"unique_id":1200,"x":159,"y":101,"z":2,"connected_nodes_id":[572,1203]},{"unique_id":1201,"x":175,"y":102,"z":2,"connected_nodes_id":[1202,1209]},{"unique_id":1202,"x":178,"y":102,"z":2,"connected_nodes_id":[1197,1201,1205]},{"unique_id":1203,"x":159,"y":105,"z":2,"connected_nodes_id":[1200,586,1204]},{"unique_id":1204,"x":166,"y":105,"z":2,"connected_nodes_id":[1203,601]},{"unique_id":1205,"x":178,"y":105,"z":2,"connected_nodes_id":[1202,1206,1210]},{"unique_id":1206,"x":188,"y":105,"z":2,"connected_nodes_id":[1198,1205,1207]},{"unique_id":1207,"x":198,"y":105,"z":2,"connected_nodes_id":[1199,1206,1211]},{"unique_id":1208,"x":172,"y":107,"z":2,"connected_nodes_id":[1209]},{"unique_id":1209,"x":175,"y":107,"z":2,"connected_nodes_id":[1201,1208]},{"unique_id":1210,"x":178,"y":110,"z":2,"connected_nodes_id":[1205,1296]},{"unique_id":1211,"x":198,"y":110,"z":2,"connected_nodes_id":[1207,1212]},{"unique_id":1212,"x":203,"y":110,"z":2,"connected_nodes_id":[1211,1213]},{"unique_id":1213,"x":209,"y":110,"z":2,"connected_nodes_id":[1212]},{"unique_id":1214,"x":169,"y":4,"z":2,"connected_nodes_id":[1215,1227]},{"unique_id":1215,"x":171,"y":4,"z":2,"connected_nodes_id":[1214,1216]},{"unique_id":1216,"x":180,"y":4,"z":2,"connected_nodes_id":[1215,1217,1218]},{"unique_id":1217,"x":193,"y":4,"z":2,"connected_nodes_id":[1216,1219]},{"unique_id":1218,"x":181,"y":5,"z":2,"connected_nodes_id":[1216,1229]},{"unique_id":1219,"x":193,"y":7,"z":2,"connected_nodes_id":[1217,1220,1232]},{"unique_id":1220,"x":199,"y":7,"z":2,"connected_nodes_id":[1219,1221]},{"unique_id":1221,"x":211,"y":7,"z":2,"connected_nodes_id":[1220,1234]},{"unique_id":1222,"x":216,"y":11,"z":2,"connected_nodes_id":[1235]},{"unique_id":1223,"x":199,"y":12,"z":2,"connected_nodes_id":[1224,1238]},{"unique_id":1224,"x":201,"y":12,"z":2,"connected_nodes_id":[1223,1225]},{"unique_id":1225,"x":206,"y":12,"z":2,"connected_nodes_id":[1224,1233]},{"unique_id":1226,"x":221,"y":12,"z":2,"connected_nodes_id":[1240]},{"unique_id":1227,"x":169,"y":15,"z":2,"connected_nodes_id":[1214,1228,1246]},{"unique_id":1228,"x":177,"y":15,"z":2,"connected_nodes_id":[1227,1236]},{"unique_id":1229,"x":181,"y":15,"z":2,"connected_nodes_id":[1218,1230,1237]},{"unique_id":1230,"x":183,"y":15,"z":2,"connected_nodes_id":[1229,1231,1237]},{"unique_id":1231,"x":185,"y":15,"z":2,"connected_nodes_id":[1230,1232,1241]},{"unique_id":1232,"x":193,"y":15,"z":2,"connected_nodes_id":[1219,1231,1249]},{"unique_id":1233,"x":206,"y":15,"z":2,"connected_nodes_id":[1225,1234,1239,1245]},{"unique_id":1234,"x":211,"y":15,"z":2,"connected_nodes_id":[1221,1233,1235,1242]},{"unique_id":1235,"x":216,"y":15,"z":2,"connected_nodes_id":[1222,1234,1243]},{"unique_id":1236,"x":178,"y":16,"z":2,"connected_nodes_id":[1228,1237]},{"unique_id":1237,"x":182,"y":16,"z":2,"connected_nodes_id":[1229,1230,1236]},{"unique_id":1238,"x":199,"y":16,"z":2,"connected_nodes_id":[1223,1239]},{"unique_id":1239,"x":205,"y":16,"z":2,"connected_nodes_id":[1233,1238]},{"unique_id":1240,"x":221,"y":16,"z":2,"connected_nodes_id":[1226,1244]},{"unique_id":1241,"x":185,"y":19,"z":2,"connected_nodes_id":[1231,1248]},{"unique_id":1242,"x":211,"y":19,"z":2,"connected_nodes_id":[1234]},{"unique_id":1243,"x":216,"y":19,"z":2,"connected_nodes_id":[1235]},{"unique_id":1244,"x":221,"y":19,"z":2,"connected_nodes_id":[1240,1254]},{"unique_id":1245,"x":206,"y":20,"z":2,"connected_nodes_id":[1233,1251]},{"unique_id":1246,"x":169,"y":24,"z":2,"connected_nodes_id":[1227,1247,1259]},{"unique_id":1247,"x":177,"y":24,"z":2,"connected_nodes_id":[1246,1248]},{"unique_id":1248,"x":185,"y":24,"z":2,"connected_nodes_id":[1241,1247,1249]},{"unique_id":1249,"x":193,"y":24,"z":2,"connected_nodes_id":[1232,1248,1256]},{"unique_id":1250,"x":203,"y":24,"z":2,"connected_nodes_id":[1251,1257]},{"unique_id":1251,"x":206,"y":24,"z":2,"connected_nodes_id":[1245,1250,1252]},{"unique_id":1252,"x":211,"y":24,"z":2,"connected_nodes_id":[1251,1253]},{"unique_id":1253,"x":217,"y":24,"z":2,"connected_nodes_id":[1252,1254,1255]},{"unique_id":1254,"x":221,"y":24,"z":2,"connected_nodes_id":[1244,1253]},{"unique_id":1255,"x":217,"y":26,"z":2,"connected_nodes_id":[1253]},{"unique_id":1256,"x":193,"y":31,"z":2,"connected_nodes_id":[1249,1268]},{"unique_id":1257,"x":203,"y":32,"z":2,"connected_nodes_id":[1250,1269]},{"unique_id":1258,"x":163,"y":34,"z":2,"connected_nodes_id":[1259,1274]},{"unique_id":1259,"x":169,"y":34,"z":2,"connected_nodes_id":[1246,1258,1260]},{"unique_id":1260,"x":171,"y":34,"z":2,"connected_nodes_id":[1259,1261]},{"unique_id":1261,"x":178,"y":34,"z":2,"connected_nodes_id":[1260,1263]},{"unique_id":1262,"x":165,"y":35,"z":2,"connected_nodes_id":[]},{"unique_id":1263,"x":178,"y":38,"z":2,"connected_nodes_id":[1261,1266]},{"unique_id":1264,"x":172,"y":39,"z":2,"connected_nodes_id":[1265]},{"unique_id":1265,"x":174,"y":39,"z":2,"connected_nodes_id":[1264,1266]},{"unique_id":1266,"x":179,"y":39,"z":2,"connected_nodes_id":[1263,1265,1267]},{"unique_id":1267,"x":183,"y":39,"z":2,"connected_nodes_id":[1266,1268,1270]},{"unique_id":1268,"x":193,"y":39,"z":2,"connected_nodes_id":[1256,1267,1271]},{"unique_id":1269,"x":203,"y":39,"z":2,"connected_nodes_id":[1257,1273]},{"unique_id":1270,"x":184,"y":40,"z":2,"connected_nodes_id":[1267]},{"unique_id":1271,"x":193,"y":44,"z":2,"connected_nodes_id":[1268,1272]},{"unique_id":1272,"x":198,"y":44,"z":2,"connected_nodes_id":[1271,1273,1279]},{"unique_id":1273,"x":203,"y":44,"z":2,"connected_nodes_id":[1269,1272]},{"unique_id":1274,"x":163,"y":46,"z":2,"connected_nodes_id":[1258,579]},{"unique_id":1275,"x":157,"y":51,"z":2,"connected_nodes_id":[1280]},{"unique_id":1276,"x":166,"y":51,"z":2,"connected_nodes_id":[1277]},{"unique_id":1277,"x":168,"y":51,"z":2,"connected_nodes_id":[1276,1283]},{"unique_id":1278,"x":192,"y":53,"z":2,"connected_nodes_id":[1279,1287]},{"unique_id":1279,"x":198,"y":53,"z":2,"connected_nodes_id":[1272,1278,1288]},{"unique_id":1280,"x":157,"y":54,"z":2,"connected_nodes_id":[1275,1281]},{"unique_id":1281,"x":161,"y":54,"z":2,"connected_nodes_id":[1280,1282]},{"unique_id":1282,"x":162,"y":55,"z":2,"connected_nodes_id":[1281,1283]},{"unique_id":1283,"x":168,"y":55,"z":2,"connected_nodes_id":[1277,1282,1284]},{"unique_id":1284,"x":168,"y":57,"z":2,"connected_nodes_id":[1283,1285]},{"unique_id":1285,"x":173,"y":57,"z":2,"connected_nodes_id":[1284,1289]},{"unique_id":1286,"x":190,"y":60,"z":2,"connected_nodes_id":[1287,1292]},{"unique_id":1287,"x":192,"y":60,"z":2,"connected_nodes_id":[1278,1286,1288]},{"unique_id":1288,"x":198,"y":60,"z":2,"connected_nodes_id":[1279,1287,1294]},{"unique_id":1289,"x":173,"y":61,"z":2,"connected_nodes_id":[1285,1290]},{"unique_id":1290,"x":176,"y":61,"z":2,"connected_nodes_id":[1289,1293]},{"unique_id":1291,"x":186,"y":63,"z":2,"connected_nodes_id":[1179,1292]},{"unique_id":1292,"x":190,"y":63,"z":2,"connected_nodes_id":[1286,1291]},{"unique_id":1293,"x":176,"y":66,"z":2,"connected_nodes_id":[1290,1176]},{"unique_id":1294,"x":198,"y":66,"z":2,"connected_nodes_id":[1288,1180,1295]},{"unique_id":1295,"x":202,"y":66,"z":2,"connected_nodes_id":[1294,1181]},{"unique_id":1296,"x":178,"y":112,"z":2,"connected_nodes_id":[1210,1297,1298,1299,1302]},{"unique_id":1297,"x":181,"y":112,"z":2,"connected_nodes_id":[1296,1300]},{"unique_id":1298,"x":177,"y":113,"z":2,"connected_nodes_id":[1296,1299,1305]},{"unique_id":1299,"x":179,"y":113,"z":2,"connected_nodes_id":[1296,1298,1300,1306]},{"unique_id":1300,"x":182,"y":113,"z":2,"connected_nodes_id":[1297,1299,1303]},{"unique_id":1301,"x":175,"y":116,"z":2,"connected_nodes_id":[1302]},{"unique_id":1302,"x":178,"y":116,"z":2,"connected_nodes_id":[1296,1301,1304]},{"unique_id":1303,"x":182,"y":119,"z":2,"connected_nodes_id":[1300,1307]},{"unique_id":1304,"x":178,"y":121,"z":2,"connected_nodes_id":[1302,1305,1306]},{"unique_id":1305,"x":177,"y":122,"z":2,"connected_nodes_id":[1298,1304,1306]},{"unique_id":1306,"x":179,"y":122,"z":2,"connected_nodes_id":[1299,1304,1305,1307]},{"unique_id":1307,"x":182,"y":122,"z":2,"connected_nodes_id":[1303,1306]},{"unique_id":1308,"x":185,"y":128,"z":2,"connected_nodes_id":[632,647]}]