diff --git a/.gitignore b/.gitignore index 3736e04..f0487b3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,9 +12,5 @@ devenv.local.nix # generated by samply rust profiler profile.json -bot/models -client_web/dist -var - -deploy -clients/**/dist +# IA modles used by bots +/models diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..bdbc72d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,26 @@ +# Trictrac Project Guidelines + +## Build & Run Commands +- Build: `cargo build` +- Test: `cargo test` +- Test specific: `cargo test -- test_name` +- Lint: `cargo clippy` +- Format: `cargo fmt` +- Run CLI: `RUST_LOG=info cargo run --bin=client_cli` +- Run CLI with bots: `RUST_LOG=info cargo run --bin=client_cli -- --bot dummy,dummy` +- Build Python lib: `maturin build -m store/Cargo.toml --release` + +## Code Style +- Use Rust 2021 edition idioms +- Error handling: Use Result pattern with custom Error types +- Naming: snake_case for functions/variables, CamelCase for types +- Imports: Group standard lib, external crates, then internal modules +- Module structure: Prefer small, focused modules with clear responsibilities +- Documentation: Document public APIs with doc comments +- Testing: Write unit tests in same file as implementation +- Python bindings: Use pyo3 for creating Python modules + +## Architecture +- Core game logic in `store` crate +- Multiple clients: CLI, TUI, Bevy (graphical) +- Bot interfaces in `bot` crate \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index b9533db..2ba864f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,203 +3,221 @@ version = 4 [[package]] -name = "aho-corasick" -version = "1.1.4" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] -name = "any_spawner" -version = "0.2.0" +name = "aligned-vec" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41058deaa38c9d9dd933d6d238d825227cffa668e2839b52879f6619c63eee3b" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" dependencies = [ - "futures", - "thiserror 2.0.18", - "wasm-bindgen-futures", + "equator", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] -name = "argon2" -version = "0.5.3" +name = "approx" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ - "base64ct", - "blake2", - "cpufeatures 0.2.17", - "password-hash", + "num-traits", ] [[package]] -name = "async-lock" -version = "3.4.2" +name = "arbitrary" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ - "event-listener", + "derive_arbitrary", +] + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", "event-listener-strategy", + "futures-core", "pin-project-lite", ] [[package]] -name = "async-trait" -version = "0.1.89" +name = "atomic_float" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "attribute-derive" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05832cdddc8f2650cc2cc187cc2e952b8c133a48eb055f35211f61ee81502d77" -dependencies = [ - "attribute-derive-macro", - "derive-where", - "manyhow", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "attribute-derive-macro" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7cdbbd4bd005c5d3e2e9c885e6fa575db4f4a3572335b974d8db853b6beb61" -dependencies = [ - "collection_literals", - "interpolator", - "manyhow", - "proc-macro-utils", - "proc-macro2", - "quote", - "quote-use", - "syn 2.0.117", -] +checksum = "628d228f918ac3b82fe590352cc719d30664a0c13ca3a60266fe02c7132d480a" [[package]] name = "autocfg" -version = "1.5.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "axum" -version = "0.8.9" +name = "av1-grain" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" dependencies = [ - "axum-core", - "base64 0.22.1", - "bytes", - "form_urlencoded", - "futures-util", - "http 1.4.1", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde_core", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sha1", - "sync_wrapper", - "tokio", - "tokio-tungstenite", - "tower", - "tower-layer", - "tower-service", - "tracing", + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", ] [[package]] -name = "axum-core" -version = "0.5.6" +name = "avif-serialize" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" dependencies = [ - "bytes", - "futures-core", - "http 1.4.1", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-login" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964ea6eb764a227baa8c3368e45c94d23b6863cc7b880c6c9e341c143c5a5ff7" -dependencies = [ - "axum", - "form_urlencoded", - "serde", - "subtle", - "thiserror 2.0.18", - "tower-cookies", - "tower-layer", - "tower-service", - "tower-sessions", - "tracing", - "urlencoding", -] - -[[package]] -name = "backbone-lib" -version = "0.2.16" -dependencies = [ - "bytes", - "ewebsock", - "futures", - "gloo-timers", - "postcard", - "protocol", - "serde", - "wasm-bindgen-futures", - "web-time", + "arrayvec", ] [[package]] @@ -216,25 +234,77 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "serde", + "unty", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] name = "bitflags" -version = "2.13.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "blake2" -version = "0.10.6" +name = "bitflags" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" dependencies = [ - "digest 0.10.7", + "serde", ] +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -245,19 +315,407 @@ dependencies = [ ] [[package]] -name = "block-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +name = "bot" +version = "0.1.0" dependencies = [ - "hybrid-array", + "burn", + "burn-rl", + "env_logger 0.10.0", + "pretty_assertions", + "rand 0.8.5", + "serde", + "serde_json", + "store", ] [[package]] -name = "bumpalo" -version = "3.20.3" +name = "bstr" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "built" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" + +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + +[[package]] +name = "burn" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec639306f45bd663957465e840cfb07bcd2ae18f7c045dd9aba8cb7a69c0654a" +dependencies = [ + "burn-autodiff", + "burn-candle", + "burn-core", + "burn-cuda", + "burn-ndarray", + "burn-rocm", + "burn-router", + "burn-tch", + "burn-train", + "burn-wgpu", +] + +[[package]] +name = "burn-autodiff" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a178966322ab7ce71405f1324cdc14f79256d85a47138bbd2c8c4f0056148601" +dependencies = [ + "burn-common", + "burn-tensor", + "derive-new 0.7.0", + "hashbrown 0.15.4", + "log", + "num-traits", + "portable-atomic", + "spin 0.10.0", +] + +[[package]] +name = "burn-candle" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed0981b3c1d07e9df0f5bef1042921b6db6e88b5d91916fa5dbdd7f0ca921c3" +dependencies = [ + "burn-tensor", + "candle-core", + "derive-new 0.7.0", + "half", +] + +[[package]] +name = "burn-common" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c3fae76798ea4dd14e6290b6753eb6235ac28c6ceaf6da35ff8396775d5494d" +dependencies = [ + "cubecl-common", + "rayon", + "serde", +] + +[[package]] +name = "burn-core" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2afa81c868c1a9b3fad25c31176945d0cc5181ba7b77c0456bc05cf57fca975c" +dependencies = [ + "ahash", + "bincode 2.0.1", + "burn-common", + "burn-dataset", + "burn-derive", + "burn-tensor", + "data-encoding", + "derive-new 0.7.0", + "flate2", + "half", + "hashbrown 0.15.4", + "log", + "num-traits", + "portable-atomic-util", + "rand 0.9.1", + "rmp-serde", + "serde", + "serde_json", + "spin 0.10.0", + "uuid", +] + +[[package]] +name = "burn-cubecl" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c547cbe414274ab4022abcc85993e1e41aa7cdccc92395ba5658acfdac285e07" +dependencies = [ + "burn-common", + "burn-cubecl-fusion", + "burn-fusion", + "burn-ir", + "burn-tensor", + "bytemuck", + "cubecl", + "cubecl-std", + "derive-new 0.7.0", + "futures-lite", + "half", + "hashbrown 0.15.4", + "log", + "num-traits", + "rand 0.9.1", + "serde", + "spin 0.10.0", + "text_placeholder", +] + +[[package]] +name = "burn-cubecl-fusion" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c98a5cf4d17f2db71f68c44bda21bb85fe8fe06166ea83fdd2eaff557da7fc86" +dependencies = [ + "burn-common", + "burn-fusion", + "burn-ir", + "burn-tensor", + "cubecl", + "derive-new 0.7.0", + "half", + "serde", +] + +[[package]] +name = "burn-cuda" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995bd0b3f52a4cfe0cfe47c16b40b3fd33285d17a086dd583e5b432074857e02" +dependencies = [ + "burn-cubecl", + "burn-fusion", + "burn-tensor", + "bytemuck", + "cubecl", + "derive-new 0.7.0", + "half", + "log", +] + +[[package]] +name = "burn-dataset" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136c784dfc474c822f34d69e865f88a5675e9de9803ef38cee4ce14cdba34d54" +dependencies = [ + "csv", + "derive-new 0.7.0", + "dirs 6.0.0", + "gix-tempfile", + "image", + "r2d2", + "r2d2_sqlite", + "rand 0.9.1", + "rmp-serde", + "rusqlite", + "sanitize-filename 0.6.0", + "serde", + "serde_json", + "serde_rusqlite", + "strum 0.27.1", + "tempfile", + "thiserror 2.0.12", +] + +[[package]] +name = "burn-derive" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e9f07ccc658ef072bce2e996f0c38c80ee4c241598b6557afe1877dd87ae98" +dependencies = [ + "derive-new 0.7.0", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "burn-fusion" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ed8e016795ec066c1028fc0d395a00bd5459922b4fa0eeae839b4d4ec58c45" +dependencies = [ + "burn-common", + "burn-ir", + "burn-tensor", + "derive-new 0.7.0", + "half", + "hashbrown 0.15.4", + "log", + "serde", + "spin 0.10.0", +] + +[[package]] +name = "burn-ir" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63629f2c8b82ee52dbb9c18becded5117c2faf57365dc271a55c16d139cd91a" +dependencies = [ + "burn-tensor", + "hashbrown 0.15.4", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "burn-ndarray" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e883846578e6915e1dbaeeb5bce32cc04cff03e7cb79c5836e1e888bbce974f" +dependencies = [ + "atomic_float", + "burn-autodiff", + "burn-common", + "burn-ir", + "burn-tensor", + "bytemuck", + "derive-new 0.7.0", + "itertools 0.14.0", + "libm", + "macerator", + "matrixmultiply", + "ndarray", + "num-traits", + "paste", + "portable-atomic-util", + "rand 0.9.1", + "seq-macro", + "spin 0.10.0", +] + +[[package]] +name = "burn-rl" +version = "0.1.0" +source = "git+https://github.com/yunjhongwu/burn-rl-examples.git#4d59261f26429f9df16dabd2b183f7fccd27ff9a" +dependencies = [ + "burn", + "gym-rs", + "rand 0.8.5", + "ringbuffer", + "serde", +] + +[[package]] +name = "burn-rocm" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd39d58202558b65b575921b57bff933845e6171296e2b8faf6a9d3610a344c5" +dependencies = [ + "burn-cubecl", + "burn-fusion", + "burn-tensor", + "bytemuck", + "cubecl", + "derive-new 0.7.0", + "half", + "log", +] + +[[package]] +name = "burn-router" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ed8614e180f7a58f77e658bd52e206d2f4a1ee37fcb4665c635ea9da90ea8b" +dependencies = [ + "burn-common", + "burn-ir", + "burn-tensor", + "hashbrown 0.15.4", + "log", + "spin 0.10.0", +] + +[[package]] +name = "burn-tch" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cacd39695f87086360a6457fa912062b2bbc04deacb281361539cf1bf6dcfac5" +dependencies = [ + "burn-tensor", + "cc", + "half", + "libc", + "log", + "tch", + "torch-sys", +] + +[[package]] +name = "burn-tensor" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a70d1562c0d00083939e34daad61dabebb0f8bc8c250d1ef2f5efc31eb93aaf" +dependencies = [ + "burn-common", + "bytemuck", + "colored", + "cubecl", + "derive-new 0.7.0", + "half", + "hashbrown 0.15.4", + "num-traits", + "rand 0.9.1", + "rand_distr", + "serde", + "serde_bytes", +] + +[[package]] +name = "burn-train" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140182cf5f1255d60e1d8c677fa45c6f71018c3c3c66aad093a9e4c3c222cf1c" +dependencies = [ + "async-channel", + "burn-core", + "burn-ndarray", + "derive-new 0.7.0", + "log", + "nvml-wrapper", + "ratatui 0.29.0", + "rstest", + "serde", + "sysinfo", + "systemstat", + "tracing-appender", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "burn-wgpu" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "215bf0e641a27e17bcd3941a11867dcda411c9cb009488c6b6650c8206437c30" +dependencies = [ + "burn-cubecl", + "burn-fusion", + "burn-tensor", + "cubecl", +] + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] [[package]] name = "byteorder" @@ -266,91 +724,234 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "bytes" -version = "1.11.1" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] -name = "calendrical_calculations" -version = "0.1.3" +name = "bytes" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97f73e95d668625c9b28a3072e6326773785a0cf807de9f3d632778438f3d38" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "bytesize" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ - "core_maths", - "displaydoc", + "bzip2-sys", + "libc", ] [[package]] -name = "camino" -version = "1.2.2" +name = "bzip2-sys" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] [[package]] -name = "cast" +name = "c_vec" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8" + +[[package]] +name = "candle-core" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ccf5ee3532e66868516d9b315f73aec9f34ea1a37ae98514534d458915dbf1" +dependencies = [ + "byteorder", + "gemm 0.17.1", + "half", + "memmap2", + "num-traits", + "num_cpus", + "rand 0.9.1", + "rand_distr", + "rayon", + "safetensors 0.4.5", + "thiserror 1.0.69", + "ug", + "yoke", + "zip 1.1.4", +] + +[[package]] +name = "cassowary" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] [[package]] name = "cc" -version = "1.2.63" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ - "find-msvc-tools", + "jobserver", + "libc", "shlex", ] [[package]] -name = "cfg-if" -version = "1.0.4" +name = "cfg-expr" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", + "cipher", + "cpufeatures", ] [[package]] -name = "cmov" -version = "0.5.4" +name = "chacha20poly1305" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" - -[[package]] -name = "cobs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ - "thiserror 2.0.18", + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", ] [[package]] -name = "codee" -version = "0.3.5" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dbbdc4b4d349732bc6690de10a9de952bd39ba6a065c586e26600b6b0b91f5" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "client_cli" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode 1.3.3", + "bot", + "env_logger 0.11.6", + "itertools 0.13.0", + "pico-args", + "pretty_assertions", + "renet", + "store", +] + +[[package]] +name = "client_tui" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode 1.3.3", + "crossterm", + "ratatui 0.28.1", + "store", +] + +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ "serde", - "serde_json", - "thiserror 2.0.18", + "termcolor", + "unicode-width 0.1.14", ] [[package]] -name = "collection_literals" +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "colored" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "compact_str" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] [[package]] name = "concurrent-queue" @@ -362,112 +963,83 @@ dependencies = [ ] [[package]] -name = "config" -version = "0.15.23" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f316c6237b2d38be61949ecd15268a4c6ca32570079394a2444d9ce2c72a72d8" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "convert_case 0.6.0", - "pathdiff", - "serde_core", - "toml 1.1.2+spec-1.1.0", - "winnow 1.0.3", + "core-foundation-sys", + "libc", ] [[package]] -name = "const-oid" -version = "0.10.2" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "const_format" -version = "0.2.36" +name = "core-graphics-types" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" -dependencies = [ - "const_format_proc_macros", - "konst", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "const_str_slice_concat" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f67855af358fcb20fac58f9d714c94e2b228fe5694c1c9b4ead4a366343eda1b" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "convert_case" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "core_maths" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" -dependencies = [ - "libm", -] - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ + "bitflags 1.3.2", + "core-foundation", "libc", ] [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] [[package]] -name = "critical-section" -version = "1.2.0" +name = "crc32fast" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] [[package]] name = "crossbeam-utils" @@ -476,31 +1048,332 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "crypto-common" -version = "0.1.7" +name = "crossterm" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.9.1", + "crossterm_winapi", + "mio", + "parking_lot", + "rustix 0.38.37", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] [[package]] -name = "crypto-common" -version = "0.2.2" +name = "csv" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ - "hybrid-array", + "csv-core", + "itoa", + "ryu", + "serde", ] [[package]] -name = "ctutils" -version = "0.4.2" +name = "csv-core" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" dependencies = [ - "cmov", + "memchr", +] + +[[package]] +name = "cubecl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e438056cf7c25b3adde38240b89842e1c924b8e914731c82ad81161d23e6ff" +dependencies = [ + "cubecl-core", + "cubecl-cuda", + "cubecl-hip", + "cubecl-linalg", + "cubecl-reduce", + "cubecl-runtime", + "cubecl-std", + "cubecl-wgpu", + "half", +] + +[[package]] +name = "cubecl-common" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79251bfc7f067ac9038232fe38a317adc2f31cb2fc3800e69fd409ccac7abc1f" +dependencies = [ + "bytemuck", + "derive-new 0.6.0", + "derive_more", + "dirs 5.0.1", + "embassy-futures", + "futures-lite", + "half", + "hashbrown 0.14.5", + "log", + "num-traits", + "portable-atomic", + "rand 0.9.1", + "sanitize-filename 0.5.0", + "serde", + "serde_json", + "spin 0.9.8", +] + +[[package]] +name = "cubecl-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03bf4211cdbd68bb0fb8291e0ed825c13da0d1ac01b7c02dce3cee44a6138be" +dependencies = [ + "bitflags 2.9.1", + "bytemuck", + "cubecl-common", + "cubecl-ir", + "cubecl-macros", + "cubecl-runtime", + "derive-new 0.6.0", + "derive_more", + "half", + "hashbrown 0.14.5", + "log", + "num-traits", + "paste", + "serde", + "serde_json", + "variadics_please", +] + +[[package]] +name = "cubecl-cpp" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5eef85cbcc34be7e25fc9d39edf99ed68559862dbf25c1877ebdf4a9595d31b" +dependencies = [ + "bytemuck", + "cubecl-common", + "cubecl-core", + "cubecl-runtime", + "derive-new 0.6.0", + "half", + "log", +] + +[[package]] +name = "cubecl-cuda" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e091e4e3a3900faff440aec4053805ec4456f94f4acc4afe8e6b27519c6d16" +dependencies = [ + "bytemuck", + "cubecl-common", + "cubecl-core", + "cubecl-cpp", + "cubecl-runtime", + "cudarc", + "derive-new 0.6.0", + "half", + "log", + "serde", +] + +[[package]] +name = "cubecl-hip" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2f8c00207517de61cccdc4ca2724bc1db9dab94840beaf4329e43cead3bc4a" +dependencies = [ + "bytemuck", + "cubecl-common", + "cubecl-core", + "cubecl-cpp", + "cubecl-hip-sys", + "cubecl-runtime", + "derive-new 0.6.0", + "half", + "log", + "paste", +] + +[[package]] +name = "cubecl-hip-sys" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7557762176858fa0357504025f09ae6e979c3547776ff8b6a1025ef0702450" +dependencies = [ + "libc", +] + +[[package]] +name = "cubecl-ir" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e096d77646590f0180ed4ce1aa7df4ecc7219f3c4616e9fe72d93ab63a352855" +dependencies = [ + "cubecl-common", + "cubecl-macros-internal", + "derive_more", + "float-ord", + "fnv", + "half", + "hashbrown 0.14.5", + "num-traits", + "portable-atomic", + "serde", + "variadics_please", +] + +[[package]] +name = "cubecl-linalg" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75aacf86f6004c274e63589aed55c5edcbcdf1b292eaf4ce2c1688c04c41a194" +dependencies = [ + "bytemuck", + "cubecl-common", + "cubecl-core", + "cubecl-reduce", + "cubecl-runtime", + "cubecl-std", + "half", + "serde", +] + +[[package]] +name = "cubecl-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd74622b5c8cb161e3f7fa0b2b751784ef89ab45acfa355f511eb2219dde337e" +dependencies = [ + "cubecl-common", + "darling", + "derive-new 0.6.0", + "ident_case", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "cubecl-macros-internal" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89898212c1eaba0e2f0dffcadc9790b20b75d2ec8836da084370b043be2623" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "cubecl-reduce" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7afbdfe03e7e3ca71f61890ebebc6b4390494204b545e6f6bf51a43755449073" +dependencies = [ + "cubecl-core", + "cubecl-runtime", + "cubecl-std", + "num-traits", + "serde", +] + +[[package]] +name = "cubecl-runtime" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385234520c9e392382737f32ad372b05f345656eb798ba00b72d2722c68b698c" +dependencies = [ + "async-channel", + "bytemuck", + "cfg-if", + "cfg_aliases", + "cubecl-common", + "cubecl-ir", + "derive-new 0.6.0", + "hashbrown 0.14.5", + "log", + "md5", + "serde", + "serde_json", + "spin 0.9.8", + "variadics_please", + "wasm-bindgen-futures", +] + +[[package]] +name = "cubecl-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38868eea6fdc183feb3c46bcf5e666c78e6cf0ddca2c4f3a877785cc0eabd71e" +dependencies = [ + "cubecl-core", + "cubecl-runtime", + "half", + "serde", +] + +[[package]] +name = "cubecl-wgpu" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fa2dcfaa6d75cfbc5ff05cafe99ec4a7fb7c0fa7197917e0fd20f5b90979fe" +dependencies = [ + "async-channel", + "bytemuck", + "cfg-if", + "cfg_aliases", + "cubecl-common", + "cubecl-core", + "cubecl-runtime", + "derive-new 0.6.0", + "derive_more", + "hashbrown 0.14.5", + "log", + "web-time", + "wgpu", +] + +[[package]] +name = "cudarc" +version = "0.13.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486c221362668c63a1636cfa51463b09574433b39029326cff40864b3ba12b6e" +dependencies = [ + "libloading", ] [[package]] @@ -524,7 +1397,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] @@ -535,14 +1408,14 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "dashmap" -version = "6.2.1" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", "crossbeam-utils", @@ -554,198 +1427,283 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.11.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" - -[[package]] -name = "deadpool" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" -dependencies = [ - "deadpool-runtime", - "lazy_static", - "num_cpus", - "tokio", -] - -[[package]] -name = "deadpool-postgres" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" -dependencies = [ - "async-trait", - "deadpool", - "getrandom 0.2.17", - "tokio", - "tokio-postgres", - "tracing", -] - -[[package]] -name = "deadpool-runtime" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" -dependencies = [ - "tokio", -] - -[[package]] -name = "default-struct-builder" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0df63c21a4383f94bd5388564829423f35c316aed85dc4f8427aded372c7c0d" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "deranged" -version = "0.5.8" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", - "serde_core", ] [[package]] -name = "derive-where" -version = "1.6.1" +name = "derivative" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 1.0.109", ] +[[package]] +name = "derive-new" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "derive-new" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "unicode-xid", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", - "crypto-common 0.1.7", + "block-buffer", + "crypto-common", "subtle", ] [[package]] -name = "digest" -version = "0.11.3" +name = "dirs" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "block-buffer 0.12.0", - "const-oid", - "crypto-common 0.2.2", - "ctutils", + "dirs-sys 0.4.1", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys 0.5.0", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.4.6", + "windows-sys 0.48.0", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.5.0", + "windows-sys 0.59.0", ] [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "document-features" -version = "0.2.12" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" dependencies = [ "litrs", ] [[package]] -name = "drain_filter_polyfill" -version = "0.1.3" +name = "dyn-stack" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" +checksum = "56e53799688f5632f364f8fb387488dd05db9fe45db7011be066fc20e7027f8b" +dependencies = [ + "bytemuck", + "reborrow", +] [[package]] -name = "dyn-clone" -version = "1.0.20" +name = "dyn-stack" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +checksum = "490bd48eb68fffcfed519b4edbfd82c69cbe741d175b84f0e0cbe8c57cbe0bdd" +dependencies = [ + "bytemuck", +] [[package]] name = "either" -version = "1.16.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] -name = "either_of" -version = "0.1.9" +name = "embassy-futures" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5060e0a4cbf26a87550792688ade88e6b8aec9208613631a7a363bda7bc2d4cd" -dependencies = [ - "paste", - "pin-project-lite", -] +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" [[package]] -name = "email-encoding" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9298e6504d9b9e780ed3f7dfd43a61be8cd0e09eb07f7706a945b0072b6670b6" -dependencies = [ - "base64 0.22.1", - "memchr", -] - -[[package]] -name = "email_address" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "embedded-io" +name = "enum-as-inner" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.14" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", @@ -763,50 +1721,63 @@ dependencies = [ ] [[package]] -name = "ewebsock" -version = "0.8.0" +name = "exr" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "679247b4a005c82218a5f13b713239b0b6d484ec25347a719f5b7066152a748a" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" dependencies = [ - "document-features", - "js-sys", - "log", - "tungstenite 0.24.0", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", ] [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.4.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "find-msvc-tools" -version = "0.1.9" +name = "fdeflate" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "fixed_decimal" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0febbeb1118a9ecdee6e4520ead6b54882e843dd0592ad233247dbee84c53db8" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ - "displaydoc", - "ryu", - "smallvec", - "writeable 0.5.5", + "simd-adler32", ] +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "float-ord" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + [[package]] name = "fnv" version = "1.0.7" @@ -815,107 +1786,345 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.5" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "form_urlencoded" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] -name = "futures-macro" -version = "0.3.32" +name = "futures-lite" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", ] [[package]] -name = "futures-sink" -version = "0.3.32" +name = "futures-macro" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", + "pin-utils", "slab", ] +[[package]] +name = "gemm" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab24cc62135b40090e31a76a9b2766a501979f3070fa27f689c27ec04377d32" +dependencies = [ + "dyn-stack 0.10.0", + "gemm-c32 0.17.1", + "gemm-c64 0.17.1", + "gemm-common 0.17.1", + "gemm-f16 0.17.1", + "gemm-f32 0.17.1", + "gemm-f64 0.17.1", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 10.7.0", + "seq-macro", +] + +[[package]] +name = "gemm" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab96b703d31950f1aeddded248bc95543c9efc7ac9c4a21fda8703a83ee35451" +dependencies = [ + "dyn-stack 0.13.0", + "gemm-c32 0.18.2", + "gemm-c64 0.18.2", + "gemm-common 0.18.2", + "gemm-f16 0.18.2", + "gemm-f32 0.18.2", + "gemm-f64 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 11.5.0", + "seq-macro", +] + +[[package]] +name = "gemm-c32" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9c030d0b983d1e34a546b86e08f600c11696fde16199f971cd46c12e67512c0" +dependencies = [ + "dyn-stack 0.10.0", + "gemm-common 0.17.1", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 10.7.0", + "seq-macro", +] + +[[package]] +name = "gemm-c32" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6db9fd9f40421d00eea9dd0770045a5603b8d684654816637732463f4073847" +dependencies = [ + "dyn-stack 0.13.0", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 11.5.0", + "seq-macro", +] + +[[package]] +name = "gemm-c64" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb5f2e79fefb9693d18e1066a557b4546cd334b226beadc68b11a8f9431852a" +dependencies = [ + "dyn-stack 0.10.0", + "gemm-common 0.17.1", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 10.7.0", + "seq-macro", +] + +[[package]] +name = "gemm-c64" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfcad8a3d35a43758330b635d02edad980c1e143dc2f21e6fd25f9e4eada8edf" +dependencies = [ + "dyn-stack 0.13.0", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 11.5.0", + "seq-macro", +] + +[[package]] +name = "gemm-common" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2e7ea062c987abcd8db95db917b4ffb4ecdfd0668471d8dc54734fdff2354e8" +dependencies = [ + "bytemuck", + "dyn-stack 0.10.0", + "half", + "num-complex", + "num-traits", + "once_cell", + "paste", + "pulp 0.18.22", + "raw-cpuid 10.7.0", + "rayon", + "seq-macro", + "sysctl 0.5.5", +] + +[[package]] +name = "gemm-common" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a352d4a69cbe938b9e2a9cb7a3a63b7e72f9349174a2752a558a8a563510d0f3" +dependencies = [ + "bytemuck", + "dyn-stack 0.13.0", + "half", + "libm", + "num-complex", + "num-traits", + "once_cell", + "paste", + "pulp 0.21.5", + "raw-cpuid 11.5.0", + "rayon", + "seq-macro", + "sysctl 0.6.0", +] + +[[package]] +name = "gemm-f16" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca4c06b9b11952071d317604acb332e924e817bd891bec8dfb494168c7cedd4" +dependencies = [ + "dyn-stack 0.10.0", + "gemm-common 0.17.1", + "gemm-f32 0.17.1", + "half", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 10.7.0", + "rayon", + "seq-macro", +] + +[[package]] +name = "gemm-f16" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff95ae3259432f3c3410eaa919033cd03791d81cebd18018393dc147952e109" +dependencies = [ + "dyn-stack 0.13.0", + "gemm-common 0.18.2", + "gemm-f32 0.18.2", + "half", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 11.5.0", + "rayon", + "seq-macro", +] + +[[package]] +name = "gemm-f32" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a69f51aaefbd9cf12d18faf273d3e982d9d711f60775645ed5c8047b4ae113" +dependencies = [ + "dyn-stack 0.10.0", + "gemm-common 0.17.1", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 10.7.0", + "seq-macro", +] + +[[package]] +name = "gemm-f32" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc8d3d4385393304f407392f754cd2dc4b315d05063f62cf09f47b58de276864" +dependencies = [ + "dyn-stack 0.13.0", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 11.5.0", + "seq-macro", +] + +[[package]] +name = "gemm-f64" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa397a48544fadf0b81ec8741e5c0fba0043008113f71f2034def1935645d2b0" +dependencies = [ + "dyn-stack 0.10.0", + "gemm-common 0.17.1", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 10.7.0", + "seq-macro", +] + +[[package]] +name = "gemm-f64" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b2a4f76ce4b8b16eadc11ccf2e083252d8237c1b589558a49b0183545015bd" +dependencies = [ + "dyn-stack 0.13.0", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid 11.5.0", + "seq-macro", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -927,150 +2136,247 @@ dependencies = [ ] [[package]] -name = "getopts" -version = "0.2.24" +name = "getrandom" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "unicode-width", + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.17" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi 5.3.0", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "r-efi 6.0.0", - "rand_core 0.10.1", - "wasip2", - "wasip3", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] -name = "gloo-net" -version = "0.5.0" +name = "gif" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43aaa242d1239a8822c15c645f02166398da4f8b5c4bae795c1f5b44e9eee173" +checksum = "fcc37f9a2bfe731e69f1e08d29d91d30604b9ce24bcb2880a961e82d89c6ed89" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gix-features" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f4399af6ec4fd9db84dd4cf9656c5c785ab492ab40a7c27ea92b4241923fed" +dependencies = [ + "gix-trace", + "gix-utils", + "libc", +] + +[[package]] +name = "gix-fs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a0637149b4ef24d3ea55f81f77231401c8463fae6da27331c987957eb597c7" +dependencies = [ + "bstr", + "fastrand", + "gix-features", + "gix-path", + "gix-utils", + "thiserror 2.0.12", +] + +[[package]] +name = "gix-path" +version = "0.10.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567f65fec4ef10dfab97ae71f26a27fd4d7fe7b8e3f90c8a58551c41ff3fb65b" +dependencies = [ + "bstr", + "gix-trace", + "gix-validate", + "home", + "once_cell", + "thiserror 2.0.12", +] + +[[package]] +name = "gix-tempfile" +version = "17.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c750e8c008453a2dba67a2b0d928b7716e05da31173a3f5e351d5457ad4470aa" +dependencies = [ + "dashmap", + "gix-fs", + "libc", + "once_cell", + "parking_lot", + "signal-hook", + "signal-hook-registry", + "tempfile", +] + +[[package]] +name = "gix-trace" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7" + +[[package]] +name = "gix-utils" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5351af2b172caf41a3728eb4455326d84e0d70fe26fc4de74ab0bd37df4191c5" +dependencies = [ + "fastrand", + "unicode-normalization", +] + +[[package]] +name = "gix-validate" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77b9e00cacde5b51388d28ed746c493b18a6add1f19b5e01d686b3b9ece66d4d" +dependencies = [ + "bstr", + "thiserror 2.0.12", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" dependencies = [ - "futures-channel", - "futures-core", - "futures-sink", - "gloo-utils", - "http 0.2.12", "js-sys", - "pin-project", - "serde", - "serde_json", - "thiserror 1.0.69", + "slotmap", "wasm-bindgen", - "wasm-bindgen-futures", "web-sys", ] [[package]] -name = "gloo-net" +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "futures-channel", - "futures-core", - "futures-sink", - "gloo-utils", - "http 1.4.1", - "js-sys", - "pin-project", - "serde", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "bitflags 2.9.1", + "gpu-alloc-types", ] [[package]] -name = "gloo-storage" +name = "gpu-alloc-types" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "gloo-utils", - "js-sys", - "serde", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "web-sys", + "bitflags 2.9.1", ] [[package]] -name = "gloo-timers" -version = "0.3.0" +name = "gpu-allocator" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", + "log", + "presser", + "thiserror 1.0.69", + "windows 0.58.0", ] [[package]] -name = "gloo-utils" +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.9.1", + "gpu-descriptor-types", + "hashbrown 0.15.4", +] + +[[package]] +name = "gpu-descriptor-types" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "js-sys", - "serde", - "serde_json", - "wasm-bindgen", - "web-sys", + "bitflags 2.9.1", ] [[package]] -name = "guardian" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f" +name = "gym-rs" +version = "0.3.1" +source = "git+https://github.com/MathisWellmann/gym-rs.git#5283afaa86a3a7c45c46c882cfad459f02539b62" +dependencies = [ + "derivative", + "derive-new 0.7.0", + "log", + "nalgebra", + "num-traits", + "ordered-float 5.0.0", + "rand 0.8.5", + "rand_pcg", + "sdl2", + "serde", +] [[package]] -name = "hash32" -version = "0.2.1" +name = "half" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ - "byteorder", + "bytemuck", + "cfg-if", + "crunchy", + "num-traits", + "rand 0.9.1", + "rand_distr", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", ] [[package]] @@ -1078,34 +2384,31 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "ahash", + "allocator-api2", + "serde", ] [[package]] name = "hashbrown" -version = "0.17.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "serde", +] [[package]] -name = "heapless" -version = "0.7.17" +name = "hashlink" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", + "hashbrown 0.15.4", ] [[package]] @@ -1114,6 +2417,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hermit-abi" version = "0.5.2" @@ -1121,541 +2430,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "hmac" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" -dependencies = [ - "digest 0.11.3", -] - -[[package]] -name = "hostname" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" -dependencies = [ - "cfg-if", - "libc", - "windows-link", -] - -[[package]] -name = "html-escape" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" -dependencies = [ - "utf8-width", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.4.1", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http 1.4.1", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "http-range-header" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hybrid-array" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" -dependencies = [ - "typenum", -] - -[[package]] -name = "hydration_context" +name = "hexf-parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d35485b3dcbf7e044b8f28c73f04f13e7b509c2466fd10cb2a8a447e38f8a93a" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "futures", - "once_cell", - "or_poisoned", - "pin-project-lite", - "serde", - "throw_error", + "digest", ] [[package]] -name = "hyper" -version = "1.10.1" +name = "home" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "http 1.4.1", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", + "windows-sys 0.59.0", ] [[package]] -name = "hyper-util" -version = "0.1.20" +name = "humantime" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "bytes", - "http 1.4.1", - "http-body", - "hyper", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "icu_calendar" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7265b2137f9a36f7634a308d91f984574bbdba8cfd95ceffe1c345552275a8ff" -dependencies = [ - "calendrical_calculations", - "displaydoc", - "icu_calendar_data", - "icu_locid", - "icu_locid_transform", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "writeable 0.5.5", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_calendar_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820499e77e852162190608b4f444e7b4552619150eafc39a9e39333d9efae9e1" - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke 0.7.5", - "zerofrom", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_collections" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke 0.8.3", - "zerofrom", - "zerovec 0.11.6", -] - -[[package]] -name = "icu_datetime" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d115efb85e08df3fd77e77f52e7e087545a783fffba8be80bfa2102f306b1780" -dependencies = [ - "displaydoc", - "either", - "fixed_decimal", - "icu_calendar", - "icu_datetime_data", - "icu_decimal", - "icu_locid", - "icu_locid_transform", - "icu_plurals", - "icu_provider 1.5.0", - "icu_timezone", - "smallvec", - "tinystr 0.7.6", - "writeable 0.5.5", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_datetime_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef5f04076123cab1b7a926a7083db27fe0d7a0e575adb984854aae3f3a6507d" - -[[package]] -name = "icu_decimal" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8fd98f86ec0448d85e1edf8884e4e318bb2e121bd733ec929a05c0a5e8b0eb" -dependencies = [ - "displaydoc", - "fixed_decimal", - "icu_decimal_data", - "icu_locid_transform", - "icu_provider 1.5.0", - "writeable 0.5.5", -] - -[[package]] -name = "icu_decimal_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c95dd97f5ccf6d837a9c115496ec7d36646fa86ca18e7f1412115b4c820ae2" - -[[package]] -name = "icu_experimental" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "844ad7b682a165c758065d694bc4d74ac67f176da1c499a04d85d492c0f193b7" -dependencies = [ - "displaydoc", - "fixed_decimal", - "icu_collections 1.5.0", - "icu_decimal", - "icu_experimental_data", - "icu_locid", - "icu_locid_transform", - "icu_normalizer 1.5.0", - "icu_pattern", - "icu_plurals", - "icu_properties 1.5.1", - "icu_provider 1.5.0", - "litemap 0.7.5", - "num-bigint", - "num-rational", - "num-traits", - "smallvec", - "tinystr 0.7.6", - "writeable 0.5.5", - "zerofrom", - "zerotrie 0.1.3", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_experimental_data" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121df92eafb8f5286d4e8ff401c1e7db8384377f806db3f8db77b91e5b7bd4dd" - -[[package]] -name = "icu_list" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365" -dependencies = [ - "displaydoc", - "icu_list_data", - "icu_locid_transform", - "icu_provider 1.5.0", - "regex-automata 0.2.0", - "writeable 0.5.5", -] - -[[package]] -name = "icu_list_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120" - -[[package]] -name = "icu_locale_core" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" -dependencies = [ - "displaydoc", - "litemap 0.8.2", - "tinystr 0.8.3", - "writeable 0.6.3", - "zerovec 0.11.6", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap 0.7.5", - "tinystr 0.7.6", - "writeable 0.5.5", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections 1.5.0", - "icu_normalizer_data 1.5.1", - "icu_properties 1.5.1", - "icu_provider 1.5.0", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_normalizer" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" -dependencies = [ - "icu_collections 2.2.0", - "icu_normalizer_data 2.2.0", - "icu_properties 2.2.0", - "icu_provider 2.2.0", - "smallvec", - "zerovec 0.11.6", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" - -[[package]] -name = "icu_normalizer_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" - -[[package]] -name = "icu_pattern" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f36aafd098d6717de34e668a8120822275c1fba22b936e757b7de8a2fd7e4" -dependencies = [ - "displaydoc", - "either", - "writeable 0.5.5", - "yoke 0.7.5", - "zerofrom", -] - -[[package]] -name = "icu_plurals" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a70e7c025dbd5c501b0a5c188cd11666a424f0dadcd4f0a95b7dafde3b114" -dependencies = [ - "displaydoc", - "fixed_decimal", - "icu_locid_transform", - "icu_plurals_data", - "icu_provider 1.5.0", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_plurals_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a483403238cb7d6a876a77a5f8191780336d80fe7b8b00bfdeb20be6abbfd112" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections 1.5.0", - "icu_locid_transform", - "icu_properties_data 1.5.1", - "icu_provider 1.5.0", - "tinystr 0.7.6", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_properties" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" -dependencies = [ - "icu_collections 2.2.0", - "icu_locale_core", - "icu_properties_data 2.2.0", - "icu_provider 2.2.0", - "zerotrie 0.2.4", - "zerovec 0.11.6", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" - -[[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr 0.7.6", - "writeable 0.5.5", - "yoke 0.7.5", - "zerofrom", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_provider" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable 0.6.3", - "yoke 0.8.3", - "zerofrom", - "zerotrie 0.2.4", - "zerovec 0.11.6", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "icu_timezone" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa91ba6a585939a020c787235daa8aee856d9bceebd6355e283c0c310bc6de96" -dependencies = [ - "displaydoc", - "icu_calendar", - "icu_provider 1.5.0", - "icu_timezone_data", - "tinystr 0.7.6", - "zerotrie 0.1.3", - "zerovec 0.10.4", -] - -[[package]] -name = "icu_timezone_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adcf7b613a268af025bc2a2532b4b9ee294e6051c5c0832d8bff20ac0232e68" - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "ident_case" @@ -1665,42 +2467,133 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.1.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "idna_adapter" -version = "1.2.2" +name = "image" +version = "0.25.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" dependencies = [ - "icu_normalizer 2.2.0", - "icu_properties 2.2.0", + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", ] +[[package]] +name = "image-webp" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + [[package]] name = "indexmap" -version = "2.14.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.17.1", - "serde", - "serde_core", + "hashbrown 0.15.4", ] [[package]] -name = "interpolator" -version = "0.5.0" +name = "indoc" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instability" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +dependencies = [ + "quote", + "syn 2.0.104", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.9", + "rustix 0.38.37", + "windows-sys 0.48.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] [[package]] name = "itertools" @@ -1713,47 +2606,58 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.18" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "cfg-if", - "futures-util", "once_cell", "wasm-bindgen", ] [[package]] -name = "json5" -version = "0.4.1" +name = "khronos-egl" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ - "pest", - "pest_derive", - "serde", + "libc", + "libloading", + "pkg-config", ] [[package]] -name = "konst" -version = "0.2.20" +name = "khronos_api" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" -dependencies = [ - "konst_macro_rules", -] - -[[package]] -name = "konst_macro_rules" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "lazy_static" @@ -1762,413 +2666,196 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "leb128fmt" -version = "0.1.0" +name = "lebe" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "leptos" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b8731cb00f3f0894058155410b95c8955b17273181d2bc72600ab84edd24f1" -dependencies = [ - "any_spawner", - "cfg-if", - "either_of", - "futures", - "hydration_context", - "leptos_config", - "leptos_dom", - "leptos_hot_reload", - "leptos_macro", - "leptos_server", - "oco_ref", - "or_poisoned", - "paste", - "reactive_graph", - "rustc-hash", - "send_wrapper", - "serde", - "serde_qs", - "server_fn", - "slotmap", - "tachys", - "thiserror 2.0.18", - "throw_error", - "typed-builder", - "typed-builder-macro", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "leptos-use" -version = "0.15.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2457c1abaa00dd4601695a989ed796bb19bc44e47ecffe2ad1336cc4c9e4f505" -dependencies = [ - "cfg-if", - "codee", - "cookie", - "default-struct-builder", - "js-sys", - "lazy_static", - "leptos", - "paste", - "send_wrapper", - "thiserror 2.0.18", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "leptos_config" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bae3e0ead5a7a814c8340eef7cb8b6cba364125bd8174b15dc9fe1b3cab7e03" -dependencies = [ - "config", - "regex", - "serde", - "thiserror 2.0.18", - "typed-builder", -] - -[[package]] -name = "leptos_dom" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89d4eb263bd5a9e7c49f780f17063f15aca56fd638c90b9dfd5f4739152e87d" -dependencies = [ - "js-sys", - "or_poisoned", - "reactive_graph", - "send_wrapper", - "tachys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "leptos_hot_reload" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e80219388501d99b246f43b6e7d08a28f327cdd34ba630a35654d917f3e1788e" -dependencies = [ - "anyhow", - "camino", - "indexmap", - "parking_lot", - "proc-macro2", - "quote", - "rstml", - "serde", - "syn 2.0.117", - "walkdir", -] - -[[package]] -name = "leptos_i18n" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d368a184611a7f6bd1d23568887da4cea80e457b7932ff7c8c00b39032f4dd66" -dependencies = [ - "codee", - "default-struct-builder", - "icu_calendar", - "icu_datetime", - "icu_decimal", - "icu_experimental", - "icu_list", - "icu_locid", - "icu_plurals", - "leptos", - "leptos-use", - "leptos_i18n_macro", - "leptos_meta", - "serde", - "typed-builder", - "wasm-bindgen", - "writeable 0.5.5", -] - -[[package]] -name = "leptos_i18n_macro" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f56a479ebc4416dae57732d3524a0a67f6e84af8f51501f5e2df7c26392d601" -dependencies = [ - "fixed_decimal", - "icu_locid", - "icu_locid_transform", - "leptos_i18n_parser", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn 2.0.117", - "tinystr 0.7.6", - "toml 0.8.23", -] - -[[package]] -name = "leptos_i18n_parser" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c389bd7767d52dc3e3676d8a71584ee490e801ac0eb7e02c04beeb611a7c4f" -dependencies = [ - "fixed_decimal", - "icu_locid", - "icu_plurals", - "json5", - "proc-macro2", - "quote", - "serde", - "serde_json", - "serde_yaml", - "syn 2.0.117", - "tinystr 0.7.6", - "toml 0.8.23", -] - -[[package]] -name = "leptos_macro" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e621f8f5342b9bdc93bb263b839cee7405027a74560425a2dabea9de7952b1fd" -dependencies = [ - "attribute-derive", - "cfg-if", - "convert_case 0.7.1", - "html-escape", - "itertools", - "leptos_hot_reload", - "prettyplease", - "proc-macro-error2", - "proc-macro2", - "quote", - "rstml", - "server_fn_macro", - "syn 2.0.117", - "uuid", -] - -[[package]] -name = "leptos_meta" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "448a6387e9e2cccbb756f474a54e36a39557127a3b8e46744b6ef6372b50f575" -dependencies = [ - "futures", - "indexmap", - "leptos", - "once_cell", - "or_poisoned", - "send_wrapper", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "leptos_router" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4168ead6a9715daba953aa842795cb2ad81b6e011a15745bd3d1baf86f76de95" -dependencies = [ - "any_spawner", - "either_of", - "futures", - "gloo-net 0.6.0", - "js-sys", - "leptos", - "leptos_router_macro", - "once_cell", - "or_poisoned", - "reactive_graph", - "send_wrapper", - "tachys", - "thiserror 2.0.18", - "url", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "leptos_router_macro" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31197af38d209ffc5d9f89715381c415a1570176f8d23455fbe00d148e79640" -dependencies = [ - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "leptos_server" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66985242812ec95e224fb48effe651ba02728beca92c461a9464c811a71aab11" -dependencies = [ - "any_spawner", - "base64 0.22.1", - "codee", - "futures", - "hydration_context", - "or_poisoned", - "reactive_graph", - "send_wrapper", - "serde", - "serde_json", - "server_fn", - "tachys", -] - -[[package]] -name = "lettre" -version = "0.11.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da65617f6cb926332d039cb578aad56178da86e128db6a1b09f4c94fa5b3349" -dependencies = [ - "async-trait", - "base64 0.22.1", - "email-encoding", - "email_address", - "fastrand", - "futures-io", - "futures-util", - "hostname", - "httpdate", - "idna", - "mime", - "nom", - "percent-encoding", - "quoted_printable", - "rustls", - "socket2", - "tokio", - "tokio-rustls", - "url", - "webpki-roots", -] +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] [[package]] name = "libm" -version = "0.2.16" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.9.1", + "libc", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb8270bb4060bd76c6e96f20c52d80620f1d82a3470885694e41e0f81ef6fe7" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.4", +] + +[[package]] +name = "macerator" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bce07f822458c4c303081d133a90610406162e7c8df17434956ac1892faf447b" +dependencies = [ + "bytemuck", + "cfg_aliases", + "half", + "macerator-macros", + "moddef", + "num-traits", + "paste", +] + +[[package]] +name = "macerator-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b955a106dca78c0577269d67a6d56114abb8644b810fc995a22348276bb9dd" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ "libc", ] [[package]] -name = "linear-map" -version = "1.2.0" +name = "matrixmultiply" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" - -[[package]] -name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ - "scopeguard", - "serde", + "autocfg", + "num_cpus", + "once_cell", + "rawpointer", + "thread-tree", ] [[package]] -name = "log" -version = "0.4.32" +name = "maybe-rayon" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" - -[[package]] -name = "manyhow" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" -dependencies = [ - "manyhow-macros", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "manyhow-macros" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" -dependencies = [ - "proc-macro-utils", - "proc-macro2", - "quote", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata 0.4.14", -] - -[[package]] -name = "matchit" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" - -[[package]] -name = "md-5" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ "cfg-if", - "digest 0.11.3", + "rayon", ] +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "memchr" -version = "2.8.1" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", + "stable_deref_trait", +] [[package]] name = "merge" @@ -2193,64 +2880,185 @@ dependencies = [ ] [[package]] -name = "mime" -version = "0.3.17" +name = "metal" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" dependencies = [ - "mime", - "unicase", + "bitflags 2.9.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", ] [[package]] -name = "minicov" -version = "0.3.8" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "cc", - "walkdir", + "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.2.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi 0.3.9", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.61.2", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] -name = "next_tuple" -version = "0.1.0" +name = "moddef" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60993920e071b0c9b66f14e2b32740a4e27ffc82854dcd72035887f336a09a28" +checksum = "4e519fd9c6131c1c9a4a67f8bdc4f32eb4105b16c1468adea1b8e68c98c85ec4" + +[[package]] +name = "naga" +version = "25.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b977c445f26e49757f9aca3631c3b8b836942cb278d69a92e7b80d3b24da632" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.9.1", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.15.4", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "once_cell", + "rustc-hash", + "spirv", + "strum 0.26.3", + "thiserror 2.0.12", + "unicode-ident", +] + +[[package]] +name = "nalgebra" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "ndarray" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", + "rayon", +] + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nom" -version = "8.0.0" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", ] [[package]] name = "nu-ansi-term" -version = "0.50.3" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "windows-sys 0.61.2", + "overload", + "winapi", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", ] [[package]] @@ -2264,10 +3072,31 @@ dependencies = [ ] [[package]] -name = "num-conv" -version = "0.2.2" +name = "num-complex" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "bytemuck", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] [[package]] name = "num-integer" @@ -2278,6 +3107,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-rational" version = "0.4.2" @@ -2305,55 +3145,121 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi", + "hermit-abi 0.5.2", "libc", ] [[package]] -name = "objc2-core-foundation" -version = "0.3.2" +name = "num_enum" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ - "bitflags", + "num_enum_derive", ] [[package]] -name = "objc2-system-configuration" -version = "0.3.2" +name = "num_enum_derive" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "objc2-core-foundation", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] -name = "oco_ref" -version = "0.2.1" +name = "num_threads" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0423ff9973dea4d6bd075934fdda86ebb8c05bdf9d6b0507067d4a1226371d" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ - "serde", - "thiserror 2.0.18", + "libc", ] +[[package]] +name = "nvml-wrapper" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9bff0aa1d48904a1385ea2a8b97576fbdcbc9a3cfccd0d31fe978e1c4038c5" +dependencies = [ + "bitflags 2.9.1", + "libloading", + "nvml-wrapper-sys", + "static_assertions", + "thiserror 1.0.69", + "wrapcenum-derive", +] + +[[package]] +name = "nvml-wrapper-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "698d45156f28781a4e79652b6ebe2eaa0589057d588d3aec1333f6466f13fcb5" +dependencies = [ + "libloading", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "octets" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a74f2cda724d43a0a63140af89836d4e7db6138ef67c9f96d3a0f0150d05000" + [[package]] name = "once_cell" -version = "1.21.4" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "oorandom" -version = "11.1.5" +name = "opaque-debug" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "or_poisoned" -version = "0.1.0" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c04f5d74368e4d0dfe06c45c8627c81bd7c317d52762d118fb9b3076f6420fd" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-float" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" +dependencies = [ + "num-traits", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" @@ -2363,9 +3269,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", @@ -2373,22 +3279,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.12" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-link", + "windows-targets 0.48.5", ] [[package]] name = "password-hash" -version = "0.5.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" dependencies = [ "base64ct", "rand_core 0.6.4", @@ -2402,154 +3308,87 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "pathdiff" -version = "0.2.3" +name = "pbkdf2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] [[package]] name = "percent-encoding" -version = "2.3.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] -name = "pest" -version = "2.8.6" +name = "pico-args" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "pest_meta" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" -dependencies = [ - "pest", - "sha2 0.10.9", -] - -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_shared", - "serde", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project-lite" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] -name = "postcard" -version = "1.1.3" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" dependencies = [ - "cobs", - "embedded-io 0.4.0", - "embedded-io 0.6.1", - "heapless", "serde", ] [[package]] -name = "postgres-protocol" -version = "0.6.11" +name = "portable-atomic-util" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56201207dac53e2f38e848e31b4b91616a6bb6e0c7205b77718994a7f49e70fc" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ - "base64 0.22.1", - "byteorder", - "bytes", - "fallible-iterator", - "hmac", - "md-5", - "memchr", - "rand 0.10.1", - "sha2 0.11.0", - "stringprep", -] - -[[package]] -name = "postgres-types" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc729a129e682e8d24170cd30ae1aa01b336b096cbb56df6d534ffec133d186" -dependencies = [ - "bytes", - "fallible-iterator", - "postgres-protocol", -] - -[[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "zerovec 0.11.6", + "portable-atomic", ] [[package]] @@ -2560,21 +3399,43 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.21" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "zerocopy", + "diff", + "yansi", ] [[package]] name = "prettyplease" -version = "0.2.37" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn 2.0.104", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", ] [[package]] @@ -2601,130 +3462,84 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "proc-macro-utils" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" -dependencies = [ - "proc-macro2", - "quote", - "smallvec", -] - [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" +name = "profiling" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ - "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", +] + +[[package]] +name = "pulp" +version = "0.18.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a01a0dc67cf4558d279f0c25b0962bd08fc6dec0137699eae304103e882fe6" +dependencies = [ + "bytemuck", + "libm", + "num-complex", + "reborrow", +] + +[[package]] +name = "pulp" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b86df24f0a7ddd5e4b95c94fc9ed8a98f1ca94d3b01bdce2824097e7835907" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "reborrow", "version_check", - "yansi", ] [[package]] -name = "protocol" -version = "0.2.16" +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" dependencies = [ - "serde", + "bytemuck", ] [[package]] -name = "pulldown-cmark" -version = "0.13.4" +name = "quick-error" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" -dependencies = [ - "bitflags", - "getopts", - "memchr", - "pulldown-cmark-escape", - "unicase", -] - -[[package]] -name = "pulldown-cmark-escape" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" - -[[package]] -name = "qrcodegen" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.45" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] -[[package]] -name = "quote-use" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" -dependencies = [ - "quote", - "quote-use-macros", -] - -[[package]] -name = "quote-use-macros" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" -dependencies = [ - "proc-macro-utils", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "quoted_printable" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478e0585659a122aa407eb7e3c0e1fa51b1d8a870038bd29f0cf4a8551eea972" - [[package]] name = "r-efi" version = "5.3.0" @@ -2732,41 +3547,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "r-efi" -version = "6.0.0" +name = "r2d2" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2_sqlite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180da684f0a188977d3968f139eb44260192ef8d9a5b7b7cbd01d881e0353179" +dependencies = [ + "r2d2", + "rusqlite", + "uuid", +] [[package]] name = "rand" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] name = "rand" -version = "0.9.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.5", -] - -[[package]] -name = "rand" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" -dependencies = [ - "chacha20", - "getrandom 0.4.2", - "rand_core 0.10.1", + "rand_core 0.9.3", ] [[package]] @@ -2786,7 +3607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.5", + "rand_core 0.9.3", ] [[package]] @@ -2795,108 +3616,241 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - -[[package]] -name = "rand_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" - -[[package]] -name = "reactive_graph" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a0ccddbc11a648bd09761801dac9e3f246ef7641130987d6120fced22515e6" -dependencies = [ - "any_spawner", - "async-lock", - "futures", - "guardian", - "hydration_context", - "or_poisoned", - "pin-project-lite", - "rustc-hash", - "send_wrapper", + "getrandom 0.2.16", "serde", - "slotmap", - "thiserror 2.0.18", - "web-sys", ] [[package]] -name = "reactive_stores" -version = "0.1.8" +name = "rand_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aadc7c19e3a360bf19cd595d2dc8b58ce67b9240b95a103fbc1317a8ff194237" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "guardian", - "itertools", - "or_poisoned", + "getrandom 0.3.3", +] + +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.1", +] + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "range-alloc" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" + +[[package]] +name = "ratatui" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" +dependencies = [ + "bitflags 2.9.1", + "cassowary", + "compact_str", + "crossterm", + "instability", + "itertools 0.13.0", + "lru", "paste", - "reactive_graph", - "reactive_stores_macro", - "rustc-hash", + "strum 0.26.3", + "strum_macros 0.26.4", + "unicode-segmentation", + "unicode-truncate", + "unicode-width 0.1.14", ] [[package]] -name = "reactive_stores_macro" -version = "0.1.8" +name = "ratatui" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "221095cb028dc51fbc2833743ea8b1a585da1a2af19b440b3528027495bf1f2d" +checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "convert_case 0.7.1", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.117", + "bitflags 2.9.1", + "cassowary", + "compact_str", + "crossterm", + "indoc", + "instability", + "itertools 0.13.0", + "lru", + "paste", + "strum 0.26.3", + "time", + "unicode-segmentation", + "unicode-truncate", + "unicode-width 0.2.0", ] +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps", + "thiserror 1.0.69", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "raw-cpuid" +version = "11.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "reborrow" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" + [[package]] name = "redox_syscall" -version = "0.5.18" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 2.0.12", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.14", + "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.2.0" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782" -dependencies = [ - "memchr", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2905,36 +3859,50 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] -name = "relay-server" -version = "0.2.16" +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "renet" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "751424a2b0a8640bc41ca8b969250491b1a29e9b872dee4c7c56bcc56575b76e" dependencies = [ - "argon2", - "axum", - "axum-login", "bytes", - "deadpool-postgres", - "futures-util", - "lettre", - "postcard", - "protocol", - "rand 0.8.6", - "serde", - "serde_json", - "thiserror 1.0.69", - "time", - "tokio", - "tokio-postgres", - "tower-http", - "tower-sessions", - "tracing", - "tracing-subscriber", + "log", + "octets", + "renetcode", ] +[[package]] +name = "renetcode" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed06c64c06cd7d80c61d6049c7dea9cc39bbf685b73ef9a6c5d01fada276094f" +dependencies = [ + "chacha20poly1305", + "log", +] + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + [[package]] name = "ring" version = "0.17.14" @@ -2943,32 +3911,89 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.17", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", ] [[package]] -name = "rstml" -version = "0.12.1" +name = "ringbuffer" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cf4616de7499fc5164570d40ca4e1b24d231c6833a88bff0fe00725080fd56" +checksum = "3df6368f71f205ff9c33c076d170dd56ebf68e8161c733c0caa07a7a5509ed53" + +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ - "derive-where", + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "rstest" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fc39292f8613e913f7df8fa892b8944ceb47c247b78e1b1ae2f09e019be789d" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f168d99749d307be9de54d23fd226628d99768225ef08f6ffb52e0182a27746" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", "proc-macro2", - "proc-macro2-diagnostics", "quote", - "syn 2.0.117", - "syn_derive", - "thiserror 2.0.18", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.104", + "unicode-ident", +] + +[[package]] +name = "rusqlite" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e34486da88d8e051c7c0e23c3f15fd806ea8546260aa2fec247e97242ec143" +dependencies = [ + "bitflags 2.9.1", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", ] [[package]] name = "rustc-hash" -version = "2.1.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" @@ -2980,13 +4005,38 @@ dependencies = [ ] [[package]] -name = "rustls" -version = "0.23.40" +name = "rustix" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.14", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "once_cell", "ring", "rustls-pki-types", "rustls-webpki", @@ -2996,18 +4046,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.13" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -3016,15 +4066,44 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.23" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "safetensors" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93279b86b3de76f820a8854dd06cbc33cfa57a417b19c47f6a25280112fb1df" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "safetensors" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" +dependencies = [ + "serde", + "serde_json", +] [[package]] name = "same-file" @@ -3035,6 +4114,34 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sanitize-filename" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ed72fbaf78e6f2d41744923916966c4fbe3d7c74e3037a8ee482f1115572603" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "sanitize-filename" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d" +dependencies = [ + "regex", +] + +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3042,83 +4149,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "semver" -version = "1.0.28" +name = "sdl2" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" +dependencies = [ + "bitflags 1.3.2", + "c_vec", + "lazy_static", + "libc", + "sdl2-sys", +] [[package]] -name = "send_wrapper" -version = "0.6.0" +name = "sdl2-sys" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" dependencies = [ - "futures-core", + "cfg-if", + "cmake", + "libc", + "version-compare 0.1.1", ] +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" -version = "1.0.228" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ - "serde_core", "serde_derive", ] [[package]] -name = "serde_core" -version = "1.0.228" +name = "serde_bytes" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" dependencies = [ - "serde_derive", + "serde", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", + "ryu", "serde", - "serde_core", - "zmij", ] [[package]] -name = "serde_path_to_error" -version = "0.1.20" +name = "serde_rusqlite" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +checksum = "1e77d42c863496aee3253704aa621691088f718cd8800bd50bcdc19f9bd2a8ea" dependencies = [ - "itoa", + "rusqlite", "serde", - "serde_core", -] - -[[package]] -name = "serde_qs" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror 1.0.69", ] [[package]] @@ -3130,94 +4245,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "server_fn" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d05a9e3fd8d7404985418db38c6617cc793a1a27f398d4fbc9dfe8e41b804e6" -dependencies = [ - "bytes", - "const_format", - "dashmap", - "futures", - "gloo-net 0.6.0", - "http 1.4.1", - "js-sys", - "once_cell", - "pin-project-lite", - "send_wrapper", - "serde", - "serde_json", - "serde_qs", - "server_fn_macro_default", - "thiserror 2.0.18", - "throw_error", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "xxhash-rust", -] - -[[package]] -name = "server_fn_macro" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504b35e883267b3206317b46d02952ed7b8bf0e11b2e209e2eb453b609a5e052" -dependencies = [ - "const_format", - "convert_case 0.6.0", - "proc-macro2", - "quote", - "syn 2.0.117", - "xxhash-rust", -] - -[[package]] -name = "server_fn_macro_default" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb8b274f568c94226a8045668554aace8142a59b8bca5414ac5a79627c825568" -dependencies = [ - "server_fn_macro", - "syn 2.0.117", -] - [[package]] name = "sha1" version = "0.10.6" @@ -3225,8 +4252,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", + "cpufeatures", + "digest", ] [[package]] @@ -3236,19 +4263,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.3", + "cpufeatures", + "digest", ] [[package]] @@ -3262,56 +4278,88 @@ dependencies = [ [[package]] name = "shlex" -version = "2.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio", + "signal-hook", +] [[package]] name = "signal-hook-registry" -version = "1.4.8" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ - "errno", "libc", ] [[package]] -name = "siphasher" -version = "1.0.3" +name = "simba" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] [[package]] name = "slab" -version = "0.4.12" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "slotmap" -version = "1.1.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" dependencies = [ "version_check", ] [[package]] name = "smallvec" -version = "1.15.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "spin" @@ -3320,13 +4368,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", + "portable-atomic", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", + "portable-atomic", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.9.1", ] [[package]] name = "stable_deref_trait" -version = "1.2.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "store" +version = "0.1.0" +dependencies = [ + "base64 0.21.7", + "log", + "merge", + "rand 0.8.5", + "serde", + "transpose", +] [[package]] name = "strength_reduce" @@ -3334,17 +4420,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" -[[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", -] - [[package]] name = "strsim" version = "0.11.1" @@ -3352,10 +4427,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "subtle" -version = "2.6.1" +name = "strum" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros 0.27.1", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.104", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.104", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -3370,33 +4489,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb066a04799e45f5d582e8fc6ec8e6d6896040d00898eb4e6a835196815b219" -dependencies = [ - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" - [[package]] name = "synstructure" version = "0.13.2" @@ -3405,41 +4506,132 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] -name = "tachys" -version = "0.1.9" +name = "sysctl" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66c3b70c32844a6f1e2943c72a33ebb777ad6acbeb20d1329d62e3a7806d6ec" +checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea" dependencies = [ - "any_spawner", - "async-trait", - "const_str_slice_concat", - "drain_filter_polyfill", - "dyn-clone", - "either_of", - "futures", - "html-escape", - "indexmap", - "itertools", - "js-sys", - "linear-map", - "next_tuple", - "oco_ref", + "bitflags 2.9.1", + "byteorder", + "enum-as-inner", + "libc", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "sysctl" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc" +dependencies = [ + "bitflags 2.9.1", + "byteorder", + "enum-as-inner", + "libc", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "sysinfo" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare 0.2.0", +] + +[[package]] +name = "systemstat" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668a4db78b439df482c238f559e4ea869017f9e62ef0a059c8bfcd841a4df544" +dependencies = [ + "bytesize", + "lazy_static", + "libc", + "nom", + "time", + "winapi", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tch" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa1ed622c8f13b0c42f8b1afa0e5e9ccccd82ecb6c0e904120722ab52fdc5234" +dependencies = [ + "half", + "lazy_static", + "libc", + "ndarray", + "rand 0.8.5", + "safetensors 0.3.3", + "thiserror 1.0.69", + "torch-sys", + "zip 0.6.6", +] + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", "once_cell", - "or_poisoned", - "parking_lot", - "paste", - "reactive_graph", - "reactive_stores", - "rustc-hash", - "send_wrapper", - "slotmap", - "throw_error", - "wasm-bindgen", - "web-sys", + "rustix 1.0.7", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "text_placeholder" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5008f74a09742486ef0047596cf35df2b914e2a8dca5727fcb6ba6842a766b" +dependencies = [ + "hashbrown 0.13.2", + "serde", + "serde_json", ] [[package]] @@ -3453,11 +4645,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.12", ] [[package]] @@ -3468,18 +4660,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", +] + +[[package]] +name = "thread-tree" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbd370cb847953a25954d9f63e14824a36113f8c72eecf6eccef5dc4b45d630" +dependencies = [ + "crossbeam-channel", ] [[package]] @@ -3492,70 +4693,54 @@ dependencies = [ ] [[package]] -name = "throw_error" -version = "0.2.0" +name = "tiff" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ef8bf264c6ae02a065a4a16553283f0656bd6266fc1fcb09fd2e6b5e91427b" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ - "pin-project-lite", + "flate2", + "jpeg-decoder", + "weezl", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", - "serde_core", + "serde", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", ] -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec 0.10.4", -] - -[[package]] -name = "tinystr" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" -dependencies = [ - "displaydoc", - "zerovec 0.11.6", -] - [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -3566,95 +4751,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "1.52.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tokio-postgres" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd8df5ef180f6364759a6f00f7aadda4fbbac86cdee37480826a6ff9f3574ce" -dependencies = [ - "async-trait", - "byteorder", - "bytes", - "fallible-iterator", - "futures-channel", - "futures-util", - "log", - "parking_lot", - "percent-encoding", - "phf", - "pin-project-lite", - "postgres-protocol", - "postgres-types", - "rand 0.10.1", - "socket2", - "tokio", - "tokio-util", - "whoami", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.29.0", -] - -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - [[package]] name = "toml" version = "0.8.23" @@ -3662,24 +4758,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", + "serde_spanned", + "toml_datetime", "toml_edit", ] -[[package]] -name = "toml" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" -dependencies = [ - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "winnow 1.0.3", -] - [[package]] name = "toml_datetime" version = "0.6.11" @@ -3689,15 +4772,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_datetime" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" -dependencies = [ - "serde_core", -] - [[package]] name = "toml_edit" version = "0.22.27" @@ -3706,175 +4780,65 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_write", - "winnow 0.7.15", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] -name = "toml_parser" -version = "1.1.2+spec-1.1.0" +name = "torch-sys" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +checksum = "ef14f5d239e3d60f4919f536a5dfe1d4f71b27b7abf6fe6875fd3a4b22c2dcd5" dependencies = [ - "winnow 1.0.3", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-cookies" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36" -dependencies = [ - "axum-core", - "cookie", - "futures-util", - "http 1.4.1", - "parking_lot", - "pin-project-lite", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http 1.4.1", - "http-body", - "http-body-util", - "http-range-header", - "httpdate", - "mime", - "mime_guess", - "percent-encoding", - "pin-project-lite", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tower-sessions" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a05911f23e8fae446005fe9b7b97e66d95b6db589dc1c4d59f6a2d4d4927d3" -dependencies = [ - "async-trait", - "http 1.4.1", - "time", - "tokio", - "tower-cookies", - "tower-layer", - "tower-service", - "tower-sessions-core", - "tower-sessions-memory-store", - "tracing", -] - -[[package]] -name = "tower-sessions-core" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8cce604865576b7751b7a6bc3058f754569a60d689328bb74c52b1d87e355b" -dependencies = [ - "async-trait", - "axum-core", - "base64 0.22.1", - "futures", - "http 1.4.1", - "parking_lot", - "rand 0.8.6", + "anyhow", + "cc", + "libc", "serde", "serde_json", - "thiserror 2.0.18", - "time", - "tokio", - "tracing", -] - -[[package]] -name = "tower-sessions-memory-store" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb05909f2e1420135a831dd5df9f5596d69196d0a64c3499ca474c4bd3d33242" -dependencies = [ - "async-trait", - "time", - "tokio", - "tower-sessions-core", + "ureq", + "zip 0.6.6", ] [[package]] name = "tracing" -version = "0.1.44" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", ] [[package]] -name = "tracing-attributes" -version = "0.1.31" +name = "tracing-appender" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror 1.0.69", + "time", + "tracing-subscriber", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "tracing-core" -version = "0.1.36" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -3893,142 +4857,66 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.23" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ - "matchers", "nu-ansi-term", - "once_cell", - "regex-automata 0.4.14", "sharded-slab", "smallvec", "thread_local", - "tracing", "tracing-core", "tracing-log", ] [[package]] name = "transpose" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +checksum = "e6522d49d03727ffb138ae4cbc1283d3774f0d10aa7f9bf52e6784c45daf9b23" dependencies = [ "num-integer", "strength_reduce", ] [[package]] -name = "trictrac-store" -version = "0.2.16" +name = "trictrac-server" +version = "0.1.0" dependencies = [ - "anyhow", - "base64 0.21.7", + "bincode 1.3.3", + "env_logger 0.10.0", "log", - "merge", - "rand 0.9.4", - "serde", - "transpose", -] - -[[package]] -name = "trictrac-web" -version = "0.2.16" -dependencies = [ - "backbone-lib", - "futures", - "getrandom 0.3.4", - "gloo-net 0.5.0", - "gloo-storage", - "gloo-timers", - "js-sys", - "leptos", - "leptos_i18n", - "leptos_router", - "pulldown-cmark", - "qrcodegen", - "rand 0.9.4", - "serde", - "serde_json", - "trictrac-store", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test", - "web-sys", -] - -[[package]] -name = "tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http 1.4.1", - "httparse", - "log", - "rand 0.8.6", - "sha1", - "thiserror 1.0.69", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" -dependencies = [ - "bytes", - "data-encoding", - "http 1.4.1", - "httparse", - "log", - "rand 0.9.4", - "sha1", - "thiserror 2.0.18", -] - -[[package]] -name = "typed-builder" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9d30e3a08026c78f246b173243cf07b3696d274debd26680773b6773c2afc7" -dependencies = [ - "typed-builder-macro", -] - -[[package]] -name = "typed-builder-macro" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c36781cc0e46a83726d9879608e4cf6c2505237e263a8eb8c24502989cfdb28" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "pico-args", + "renet", + "store", ] [[package]] name = "typenum" -version = "1.20.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] -name = "ucd-trie" -version = "0.1.7" +name = "ug" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "unicase" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" +checksum = "03719c61a91b51541f076dfdba45caacf750b230cefaa4b32d6f5411c3f7f437" +dependencies = [ + "gemm 0.18.2", + "half", + "libloading", + "memmap2", + "num", + "num-traits", + "num_cpus", + "rayon", + "safetensors 0.4.5", + "serde", + "thiserror 1.0.69", + "tracing", + "yoke", +] [[package]] name = "unicode-bidi" @@ -4038,36 +4926,47 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-normalization" -version = "0.1.25" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] -name = "unicode-properties" -version = "0.1.4" +name = "unicode-segmentation" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] -name = "unicode-segmentation" -version = "1.13.3" +name = "unicode-truncate" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +dependencies = [ + "itertools 0.13.0", + "unicode-segmentation", + "unicode-width 0.1.14", +] [[package]] name = "unicode-width" -version = "0.2.2" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" @@ -4076,10 +4975,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] -name = "unsafe-libyaml" -version = "0.2.11" +name = "universal-hash" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] [[package]] name = "untrusted" @@ -4088,55 +4991,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] -name = "url" -version = "2.5.8" +name = "unty" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + +[[package]] +name = "ureq" +version = "2.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "serde", + "serde_json", + "url", + "webpki-roots 0.26.11", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] -name = "urlencoding" -version = "2.1.3" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.2" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.4.2", + "getrandom 0.3.3", "js-sys", + "rand 0.9.1", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", "wasm-bindgen", ] @@ -4146,6 +5061,35 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "variadics_please" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "version_check" version = "0.9.5" @@ -4164,74 +5108,63 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.14.7+wasi-0.2.4" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ - "wasip2", -] - -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", -] - -[[package]] -name = "wasite" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" -dependencies = [ - "wasi 0.14.7+wasi-0.2.4", + "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.68" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ + "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", + "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4239,117 +5172,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", + "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-bindgen-test" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb55e2540ad1c56eec35fd63e2aea15f83b11ce487fd2de9ad11578dfc047ea" -dependencies = [ - "async-trait", - "cast", - "js-sys", - "libm", - "minicov", - "nu-ansi-term", - "num-traits", - "oorandom", - "serde", - "serde_json", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test-macro", - "wasm-bindgen-test-shared", -] - -[[package]] -name = "wasm-bindgen-test-macro" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf0ca1bd612b988616bac1ab34c4e4290ef18f7148a1d8b7f31c150080e9295" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "wasm-bindgen-test-shared" -version = "0.2.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cda5ecc67248c48d3e705d3e03e00af905769b78b9d2a1678b663b8b9d4472" - -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "web-sys" -version = "0.3.95" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -4367,40 +5214,341 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.7" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.1", +] + +[[package]] +name = "webpki-roots" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" dependencies = [ "rustls-pki-types", ] [[package]] -name = "whoami" -version = "2.1.2" +name = "weezl" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "wgpu" +version = "25.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8fb398f119472be4d80bc3647339f56eb63b2a331f6a3d16e25d8144197dd9" dependencies = [ + "arrayvec", + "bitflags 2.9.1", + "cfg_aliases", + "document-features", + "hashbrown 0.15.4", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "25.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b882196f8368511d613c6aeec80655160db6646aebddf8328879a88d54e500" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.9.1", + "cfg_aliases", + "document-features", + "hashbrown 0.15.4", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror 2.0.12", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd488b3239b6b7b185c3b045c39ca6bf8af34467a4c5de4e0b1a564135d093d" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09ad7aceb3818e52539acc679f049d3475775586f3f4e311c30165cf2c00445" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cba5fb5f7f9c98baa7c889d444f63ace25574833df56f5b817985f641af58e46" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "25.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f968767fe4d3d33747bbd1473ccd55bf0f6451f55d733b5597e67b5deab4ad17" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.9.1", + "block", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.15.4", + "js-sys", + "khronos-egl", "libc", - "libredox", - "objc2-system-configuration", - "wasite", + "libloading", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "ordered-float 4.6.0", + "parking_lot", + "portable-atomic", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.12", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "wgpu-types" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aa49460c2a8ee8edba3fca54325540d904dd85b2e086ada762767e17d06e8bc" +dependencies = [ + "bitflags 2.9.1", + "bytemuck", + "js-sys", + "log", + "thiserror 2.0.12", "web-sys", ] [[package]] -name = "winapi-util" -version = "0.1.11" +name = "wide" +version = "0.7.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" dependencies = [ - "windows-sys 0.61.2", + "bytemuck", + "safe_arch", ] [[package]] -name = "windows-link" -version = "0.2.1" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] [[package]] name = "windows-sys" @@ -4408,16 +5556,31 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] name = "windows-sys" -version = "0.61.2" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-link", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -4426,28 +5589,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -4460,24 +5641,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -4486,148 +5691,45 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.15" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] [[package]] -name = "winnow" -version = "1.0.3" +name = "wit-bindgen-rt" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "memchr", + "bitflags 2.9.1", ] [[package]] -name = "wit-bindgen" -version = "0.51.0" +name = "wrapcenum-derive" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +checksum = "a76ff259533532054cfbaefb115c613203c73707017459206380f03b3b3f266e" dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", + "darling", "proc-macro2", "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", + "syn 2.0.104", ] [[package]] -name = "wit-component" -version = "0.244.0" +name = "xml-rs" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" -dependencies = [ - "either", -] - -[[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" [[package]] name = "yansi" -version = "1.0.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "yoke" @@ -4637,18 +5739,7 @@ checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", - "yoke-derive 0.7.5", - "zerofrom", -] - -[[package]] -name = "yoke" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" -dependencies = [ - "stable_deref_trait", - "yoke-derive 0.8.2", + "yoke-derive", "zerofrom", ] @@ -4660,137 +5751,141 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "syn 2.0.104", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.50" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.50" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "zerofrom" -version = "0.1.8" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" [[package]] -name = "zerotrie" -version = "0.1.3" +name = "zip" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb594dd55d87335c5f60177cee24f19457a5ec10a065e0a3014722ad252d0a1f" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zip" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", "displaydoc", - "yoke 0.7.5", - "zerofrom", + "indexmap", + "num_enum", + "thiserror 1.0.69", ] [[package]] -name = "zerotrie" -version = "0.2.4" +name = "zstd" +version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ - "displaydoc", - "yoke 0.8.3", - "zerofrom", + "zstd-safe", ] [[package]] -name = "zerovec" -version = "0.10.4" +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ - "yoke 0.7.5", - "zerofrom", - "zerovec-derive 0.10.3", + "libc", + "zstd-sys", ] [[package]] -name = "zerovec" -version = "0.11.6" +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ - "yoke 0.8.3", - "zerofrom", - "zerovec-derive 0.11.3", + "cc", + "pkg-config", ] [[package]] -name = "zerovec-derive" -version = "0.10.3" +name = "zune-core" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "simd-adler32", ] [[package]] -name = "zerovec-derive" -version = "0.11.3" +name = "zune-jpeg" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +checksum = "7384255a918371b5af158218d131530f694de9ad3815ebdd0453a940485cb0fa" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "zune-core", ] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index f8efdb7..6068644 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,26 +1,4 @@ -[workspace.package] -version = "0.2.18" - [workspace] resolver = "2" -members = [ - "store", - "clients/backbone-lib", - "clients/web", - "server/protocol", - "server/relay-server", -] - -default-members = [ - "store", - "clients/backbone-lib", - "server/protocol", - "server/relay-server", -] - -# For the server we will need opt-level='3' -[profile.release] -opt-level = 'z' # Minimum space -lto = "fat" # Aggressive Link Time Optimization -codegen-units = 1 +members = ["client_tui", "client_cli", "bot", "server", "store"] diff --git a/README.md b/README.md index 2094edb..d2808fa 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,7 @@ # Trictrac -This is a game of [Trictrac](https://en.wikipedia.org/wiki/Trictrac) rust implementation. +Game of [Trictrac](https://en.wikipedia.org/wiki/Trictrac) in rust. -## Usage +wip -Install [devenv](https://devenv.sh/getting-started/), start a devenv shell `devenv shell`, and run the following commands. -```bash -# Run the relay server -just build-relay -just run-relay # listens on :8080 - -# Run the game (separate terminal) -just dev -``` - -Open a browser window at `http://127.0.0.1:9091`. You can play against a very basic bot, or invite an other player to connect at the same address. - -## Code structure - -- game rules and game state are implemented in the _store/_ folder. -- a server for the network game is implemented in _server/relay-server_, which uses _server/protocol_ -- the web client is in _clients/web_, it connects to the server using the _clients/backbone-lib_ library -- the command-line application is implemented in _clients/cli/_; it allows you to play against a bot, or to have two bots play against each other -- the bots algorithms and the training of their models are implemented in the _bot/_ and _spiel_bot_ folders. This is a work in progress, they are not performant at all. - -## Inspirations - -The multiplayer game architecture, implemented in packages _clients/backbone-lib_, _clients/web/game_, _server/protocol_ and _server/relay-server_ is a [Leptos](https://leptos.dev/)-optimized adaptation of the macroquad-based [Carbonfreezer/multiplayer](https://github.com/Carbonfreezer/multiplayer) project. - -The web client UX/UI is inspired by https://playtiao.com. diff --git a/bot/Cargo.toml b/bot/Cargo.toml index de957df..3fd08c4 100644 --- a/bot/Cargo.toml +++ b/bot/Cargo.toml @@ -1,24 +1,24 @@ [package] -name = "trictrac-bot" +name = "bot" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] -name = "burn_train" -path = "src/burnrl/main.rs" +name = "train_dqn_burn" +path = "src/dqn/burnrl/main.rs" + +[[bin]] +name = "train_dqn" +path = "src/bin/train_dqn.rs" [dependencies] pretty_assertions = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -trictrac-store = { path = "../store" } -rand = "0.9" +store = { path = "../store" } +rand = "0.8" env_logger = "0.10" -burn = { version = "0.20", features = ["ndarray", "autodiff"] } +burn = { version = "0.17", features = ["ndarray", "autodiff"] } burn-rl = { git = "https://github.com/yunjhongwu/burn-rl-examples.git", package = "burn-rl" } -log = "0.4.20" -confy = "1.0.0" -board-game = "0.8.2" -internal-iterator = "0.2.3" diff --git a/bot/scripts/train.sh b/bot/scripts/train.sh deleted file mode 100755 index d96e690..0000000 --- a/bot/scripts/train.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -ROOT="$(cd "$(dirname "$0")" && pwd)/../.." -LOGS_DIR="$ROOT/bot/models/logs" - -CFG_SIZE=17 -BINBOT=burn_train -# BINBOT=train_ppo_burn -# BINBOT=train_dqn_burn -# BINBOT=train_dqn_burn_big -# BINBOT=train_dqn_burn_before -OPPONENT="random" - -PLOT_EXT="png" - -train() { - ALGO=$1 - cargo build --release --bin=$BINBOT - NAME="$(date +%Y-%m-%d_%H:%M:%S)" - LOGS="$LOGS_DIR/$ALGO/$NAME.out" - mkdir -p "$LOGS_DIR/$ALGO" - LD_LIBRARY_PATH="$ROOT/target/release" "$ROOT/target/release/$BINBOT" $ALGO | tee "$LOGS" -} - -plot() { - ALGO=$1 - NAME=$(ls -rt "$LOGS_DIR/$ALGO" | grep -v png | tail -n 1) - LOGS="$LOGS_DIR/$ALGO/$NAME" - cfgs=$(grep -v "info:" "$LOGS" | head -n $CFG_SIZE) - for cfg in $cfgs; do - eval "$cfg" - done - - tail -n +$((CFG_SIZE + 2)) "$LOGS" | - grep -v "info:" | - awk -F '[ ,]' '{print $5}' | - feedgnuplot --lines --points --unset grid --title "adv = $OPPONENT ; density = $dense_size ; decay = $eps_decay ; max steps = $max_steps" --terminal $PLOT_EXT >"$LOGS_DIR/$ALGO/$NAME.$PLOT_EXT" -} - -if [[ -z "$1" ]]; then - echo "Usage : train [plot] " -elif [ "$1" = "plot" ]; then - if [[ -z "$2" ]]; then - echo "Usage : train [plot] " - else - plot $2 - fi -else - train $1 -fi diff --git a/bot/scripts/trainValid.sh b/bot/scripts/trainValid.sh deleted file mode 100755 index 55424a2..0000000 --- a/bot/scripts/trainValid.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env sh - -ROOT="$(cd "$(dirname "$0")" && pwd)/../.." -LOGS_DIR="$ROOT/bot/models/logs" - -CFG_SIZE=11 -OPPONENT="random" - -PLOT_EXT="png" - -train() { - cargo build --release --bin=train_dqn_burn_valid - NAME="trainValid_$(date +%Y-%m-%d_%H:%M:%S)" - LOGS="$LOGS_DIR/$NAME.out" - mkdir -p "$LOGS_DIR" - LD_LIBRARY_PATH="$ROOT/target/release" "$ROOT/target/release/train_dqn_burn_valid" | tee "$LOGS" -} - -plot() { - NAME=$(ls -rt "$LOGS_DIR" | grep -v "png" | tail -n 1) - LOGS="$LOGS_DIR/$NAME" - cfgs=$(head -n $CFG_SIZE "$LOGS") - for cfg in $cfgs; do - eval "$cfg" - done - - # tail -n +$((CFG_SIZE + 2)) "$LOGS" - tail -n +$((CFG_SIZE + 2)) "$LOGS" | - grep -v "info:" | - awk -F '[ ,]' '{print $5}' | - feedgnuplot --lines --points --unset grid --title "adv = $OPPONENT ; density = $dense_size ; decay = $eps_decay ; max steps = $max_steps" --terminal $PLOT_EXT >"$LOGS_DIR/$OPPONENT-$dense_size-$eps_decay-$max_steps-$NAME.$PLOT_EXT" -} - -avg() { - NAME=$(ls -rt "$LOGS_DIR" | grep -v "png" | tail -n 1) - LOGS="$LOGS_DIR/$NAME" - echo $LOGS - tail -n +$((CFG_SIZE + 2)) "$LOGS" | - grep -v "info:" | - awk -F '[ ,]' '{print $5}' | awk '{ sum += $1; n++ } END { if (n > 0) print sum / n; }' -} - -if [ "$1" = "plot" ]; then - plot -elif [ "$1" = "avg" ]; then - avg -else - train -fi diff --git a/bot/src/bin/train_dqn.rs b/bot/src/bin/train_dqn.rs new file mode 100644 index 0000000..e0929fb --- /dev/null +++ b/bot/src/bin/train_dqn.rs @@ -0,0 +1,111 @@ +use bot::dqn::dqn_common::{DqnConfig, TrictracAction}; +use bot::dqn::simple::dqn_trainer::DqnTrainer; +use std::env; + +fn main() -> Result<(), Box> { + env_logger::init(); + + let args: Vec = env::args().collect(); + + // Paramètres par défaut + let mut episodes = 1000; + let mut model_path = "models/dqn_model".to_string(); + let mut save_every = 100; + + // Parser les arguments de ligne de commande + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--episodes" => { + if i + 1 < args.len() { + episodes = args[i + 1].parse().unwrap_or(1000); + i += 2; + } else { + eprintln!("Erreur : --episodes nécessite une valeur"); + std::process::exit(1); + } + } + "--model-path" => { + if i + 1 < args.len() { + model_path = args[i + 1].clone(); + i += 2; + } else { + eprintln!("Erreur : --model-path nécessite une valeur"); + std::process::exit(1); + } + } + "--save-every" => { + if i + 1 < args.len() { + save_every = args[i + 1].parse().unwrap_or(100); + i += 2; + } else { + eprintln!("Erreur : --save-every nécessite une valeur"); + std::process::exit(1); + } + } + "--help" | "-h" => { + print_help(); + std::process::exit(0); + } + _ => { + eprintln!("Argument inconnu : {}", args[i]); + print_help(); + std::process::exit(1); + } + } + } + + // Créer le dossier models s'il n'existe pas + std::fs::create_dir_all("models")?; + + println!("Configuration d'entraînement DQN :"); + println!(" Épisodes : {}", episodes); + println!(" Chemin du modèle : {}", model_path); + println!(" Sauvegarde tous les {} épisodes", save_every); + println!(); + + // Configuration DQN + let config = DqnConfig { + state_size: 36, // state.to_vec size + hidden_size: 256, + num_actions: TrictracAction::action_space_size(), + learning_rate: 0.001, + gamma: 0.99, + epsilon: 0.9, // Commencer avec plus d'exploration + epsilon_decay: 0.995, + epsilon_min: 0.01, + replay_buffer_size: 10000, + batch_size: 32, + }; + + // Créer et lancer l'entraîneur + let mut trainer = DqnTrainer::new(config); + trainer.train(episodes, save_every, &model_path)?; + + println!("Entraînement terminé avec succès !"); + println!("Pour utiliser le modèle entraîné :"); + println!( + " cargo run --bin=client_cli -- --bot dqn:{}_final.json,dummy", + model_path + ); + + Ok(()) +} + +fn print_help() { + println!("Entraîneur DQN pour Trictrac"); + println!(); + println!("USAGE:"); + println!(" cargo run --bin=train_dqn [OPTIONS]"); + println!(); + println!("OPTIONS:"); + println!(" --episodes Nombre d'épisodes d'entraînement (défaut: 1000)"); + println!(" --model-path Chemin de base pour sauvegarder les modèles (défaut: models/dqn_model)"); + println!(" --save-every Sauvegarder le modèle tous les N épisodes (défaut: 100)"); + println!(" -h, --help Afficher cette aide"); + println!(); + println!("EXEMPLES:"); + println!(" cargo run --bin=train_dqn"); + println!(" cargo run --bin=train_dqn -- --episodes 5000 --save-every 500"); + println!(" cargo run --bin=train_dqn -- --model-path models/my_model --episodes 2000"); +} diff --git a/bot/src/burnrl/algos/dqn.rs b/bot/src/burnrl/algos/dqn.rs deleted file mode 100644 index efec37e..0000000 --- a/bot/src/burnrl/algos/dqn.rs +++ /dev/null @@ -1,195 +0,0 @@ -use crate::burnrl::environment::TrictracEnvironment; -use crate::burnrl::utils::{soft_update_linear, Config}; -use burn::backend::{ndarray::NdArrayDevice, NdArray}; -use burn::module::Module; -use burn::nn::{Linear, LinearConfig}; -use burn::optim::AdamWConfig; -use burn::record::{CompactRecorder, Recorder}; -use burn::tensor::activation::relu; -use burn::tensor::backend::{AutodiffBackend, Backend}; -use burn::tensor::Tensor; -use burn_rl::agent::DQN; -use burn_rl::agent::{DQNModel, DQNTrainingConfig}; -use burn_rl::base::{Action, Agent, ElemType, Environment, Memory, Model, State}; -use std::time::SystemTime; - -#[derive(Module, Debug)] -pub struct Net { - linear_0: Linear, - linear_1: Linear, - linear_2: Linear, -} - -impl Net { - #[allow(unused)] - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - Self { - linear_0: LinearConfig::new(input_size, dense_size).init(&Default::default()), - linear_1: LinearConfig::new(dense_size, dense_size).init(&Default::default()), - linear_2: LinearConfig::new(dense_size, output_size).init(&Default::default()), - } - } - - fn consume(self) -> (Linear, Linear, Linear) { - (self.linear_0, self.linear_1, self.linear_2) - } -} - -impl Model, Tensor> for Net { - fn forward(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear_0.forward(input)); - let layer_1_output = relu(self.linear_1.forward(layer_0_output)); - - relu(self.linear_2.forward(layer_1_output)) - } - - fn infer(&self, input: Tensor) -> Tensor { - self.forward(input) - } -} - -impl DQNModel for Net { - fn soft_update(this: Self, that: &Self, tau: ElemType) -> Self { - let (linear_0, linear_1, linear_2) = this.consume(); - - Self { - linear_0: soft_update_linear(linear_0, &that.linear_0, tau), - linear_1: soft_update_linear(linear_1, &that.linear_1, tau), - linear_2: soft_update_linear(linear_2, &that.linear_2, tau), - } - } -} - -#[allow(unused)] -const MEMORY_SIZE: usize = 8192; - -type MyAgent = DQN>; - -#[allow(unused)] -// pub fn run, B: AutodiffBackend>( -pub fn run< - E: Environment + AsMut, - B: AutodiffBackend, ->( - conf: &Config, - visualized: bool, - // ) -> DQN> { -) -> impl Agent { - let mut env = E::new(visualized); - // env.as_mut().min_steps = conf.min_steps; - env.as_mut().max_steps = conf.max_steps; - - let model = Net::::new( - <::StateType as State>::size(), - conf.dense_size, - <::ActionType as Action>::size(), - ); - - let mut agent = MyAgent::new(model); - - // let config = DQNTrainingConfig::default(); - let config = DQNTrainingConfig { - gamma: conf.gamma, - tau: conf.tau, - learning_rate: conf.learning_rate, - batch_size: conf.batch_size, - clip_grad: Some(burn::grad_clipping::GradientClippingConfig::Value( - conf.clip_grad, - )), - }; - - let mut memory = Memory::::default(); - - let mut optimizer = AdamWConfig::new() - .with_grad_clipping(config.clip_grad.clone()) - .init(); - - let mut policy_net = agent.model().as_ref().unwrap().clone(); - - let mut step = 0_usize; - - for episode in 0..conf.num_episodes { - let mut episode_done = false; - let mut episode_reward: ElemType = 0.0; - let mut episode_duration = 0_usize; - let mut state = env.state(); - let mut now = SystemTime::now(); - - while !episode_done { - let eps_threshold = conf.eps_end - + (conf.eps_start - conf.eps_end) * f64::exp(-(step as f64) / conf.eps_decay); - let action = - DQN::>::react_with_exploration(&policy_net, state, eps_threshold); - let snapshot = env.step(action); - - episode_reward += - <::RewardType as Into>::into(snapshot.reward().clone()); - - memory.push( - state, - *snapshot.state(), - action, - snapshot.reward().clone(), - snapshot.done(), - ); - - if config.batch_size < memory.len() { - policy_net = - agent.train::(policy_net, &memory, &mut optimizer, &config); - } - - step += 1; - episode_duration += 1; - - if snapshot.done() || episode_duration >= conf.max_steps { - let envmut = env.as_mut(); - let goodmoves_ratio = ((envmut.goodmoves_count as f32 / episode_duration as f32) - * 100.0) - .round() as u32; - println!( - "{{\"episode\": {episode}, \"reward\": {episode_reward:.4}, \"steps count\": {episode_duration}, \"epsilon\": {eps_threshold:.3}, \"goodmoves\": {}, \"ratio\": {}%, \"rollpoints\":{}, \"duration\": {}}}", - envmut.goodmoves_count, - goodmoves_ratio, - envmut.pointrolls_count, - now.elapsed().unwrap().as_secs(), - ); - env.reset(); - episode_done = true; - now = SystemTime::now(); - } else { - state = *snapshot.state(); - } - } - } - let valid_agent = agent.valid(); - if let Some(path) = &conf.save_path { - save_model(valid_agent.model().as_ref().unwrap(), path); - } - valid_agent -} - -pub fn save_model(model: &Net>, path: &String) { - let recorder = CompactRecorder::new(); - let model_path = format!("{path}.mpk"); - println!("info: Modèle de validation sauvegardé : {model_path}"); - recorder - .record(model.clone().into_record(), model_path.into()) - .unwrap(); -} - -pub fn load_model(dense_size: usize, path: &String) -> Option>> { - let model_path = format!("{path}.mpk"); - // println!("Chargement du modèle depuis : {model_path}"); - - CompactRecorder::new() - .load(model_path.into(), &NdArrayDevice::default()) - .map(|record| { - Net::new( - ::StateType::size(), - dense_size, - ::ActionType::size(), - ) - .load_record(record) - }) - .ok() -} diff --git a/bot/src/burnrl/algos/mod.rs b/bot/src/burnrl/algos/mod.rs deleted file mode 100644 index 5a67dfc..0000000 --- a/bot/src/burnrl/algos/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod dqn; -pub mod dqn_valid; -pub mod ppo; -pub mod ppo_valid; -pub mod sac; -pub mod sac_valid; diff --git a/bot/src/burnrl/algos/ppo.rs b/bot/src/burnrl/algos/ppo.rs deleted file mode 100644 index df6818c..0000000 --- a/bot/src/burnrl/algos/ppo.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::burnrl::environment::TrictracEnvironment; -use crate::burnrl::utils::Config; -use burn::backend::{ndarray::NdArrayDevice, NdArray}; -use burn::module::Module; -use burn::nn::{Initializer, Linear, LinearConfig}; -use burn::optim::AdamWConfig; -use burn::record::{CompactRecorder, Recorder}; -use burn::tensor::activation::{relu, softmax}; -use burn::tensor::backend::{AutodiffBackend, Backend}; -use burn::tensor::Tensor; -use burn_rl::agent::{PPOModel, PPOOutput, PPOTrainingConfig, PPO}; -use burn_rl::base::{Action, Agent, ElemType, Environment, Memory, Model, State}; -use std::env; -use std::fs; -use std::time::SystemTime; - -#[derive(Module, Debug)] -pub struct Net { - linear: Linear, - linear_actor: Linear, - linear_critic: Linear, -} - -impl Net { - #[allow(unused)] - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - let initializer = Initializer::XavierUniform { gain: 1.0 }; - Self { - linear: LinearConfig::new(input_size, dense_size) - .with_initializer(initializer.clone()) - .init(&Default::default()), - linear_actor: LinearConfig::new(dense_size, output_size) - .with_initializer(initializer.clone()) - .init(&Default::default()), - linear_critic: LinearConfig::new(dense_size, 1) - .with_initializer(initializer) - .init(&Default::default()), - } - } -} - -impl Model, PPOOutput, Tensor> for Net { - fn forward(&self, input: Tensor) -> PPOOutput { - let layer_0_output = relu(self.linear.forward(input)); - let policies = softmax(self.linear_actor.forward(layer_0_output.clone()), 1); - let values = self.linear_critic.forward(layer_0_output); - - PPOOutput::::new(policies, values) - } - - fn infer(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear.forward(input)); - softmax(self.linear_actor.forward(layer_0_output.clone()), 1) - } -} - -impl PPOModel for Net {} -#[allow(unused)] -const MEMORY_SIZE: usize = 512; - -type MyAgent = PPO>; - -#[allow(unused)] -pub fn run< - E: Environment + AsMut, - B: AutodiffBackend, ->( - conf: &Config, - visualized: bool, - // ) -> PPO> { -) -> impl Agent { - let mut env = E::new(visualized); - env.as_mut().max_steps = conf.max_steps; - - let mut model = Net::::new( - <::StateType as State>::size(), - conf.dense_size, - <::ActionType as Action>::size(), - ); - let agent = MyAgent::default(); - let config = PPOTrainingConfig { - gamma: conf.gamma, - lambda: conf.lambda, - epsilon_clip: conf.epsilon_clip, - critic_weight: conf.critic_weight, - entropy_weight: conf.entropy_weight, - learning_rate: conf.learning_rate, - epochs: conf.epochs, - batch_size: conf.batch_size, - clip_grad: Some(burn::grad_clipping::GradientClippingConfig::Value( - conf.clip_grad, - )), - }; - - let mut optimizer = AdamWConfig::new() - .with_grad_clipping(config.clip_grad.clone()) - .init(); - let mut memory = Memory::::default(); - for episode in 0..conf.num_episodes { - let mut episode_done = false; - let mut episode_reward = 0.0; - let mut episode_duration = 0_usize; - let mut now = SystemTime::now(); - - env.reset(); - while !episode_done { - let state = env.state(); - if let Some(action) = MyAgent::::react_with_model(&state, &model) { - let snapshot = env.step(action); - episode_reward += <::RewardType as Into>::into( - snapshot.reward().clone(), - ); - - memory.push( - state, - *snapshot.state(), - action, - snapshot.reward().clone(), - snapshot.done(), - ); - - episode_duration += 1; - episode_done = snapshot.done() || episode_duration >= conf.max_steps; - } - } - println!( - "{{\"episode\": {episode}, \"reward\": {episode_reward:.4}, \"steps count\": {episode_duration}, \"duration\": {}}}", - now.elapsed().unwrap().as_secs(), - ); - - now = SystemTime::now(); - model = MyAgent::train::(model, &memory, &mut optimizer, &config); - memory.clear(); - } - - if let Some(path) = &conf.save_path { - let device = NdArrayDevice::default(); - let recorder = CompactRecorder::new(); - let tmp_path = env::temp_dir().join("tmp_model.mpk"); - - // Save the trained model (backend B) to a temporary file - recorder - .record(model.clone().into_record(), tmp_path.clone()) - .expect("Failed to save temporary model"); - - // Create a new model instance with the target backend (NdArray) - let model_to_save: Net> = Net::new( - <::StateType as State>::size(), - conf.dense_size, - <::ActionType as Action>::size(), - ); - - // Load the record from the temporary file into the new model - let record = recorder - .load(tmp_path.clone(), &device) - .expect("Failed to load temporary model"); - let model_with_loaded_weights = model_to_save.load_record(record); - - // Clean up the temporary file - fs::remove_file(tmp_path).expect("Failed to remove temporary model file"); - - save_model(&model_with_loaded_weights, path); - } - agent.valid(model) -} - -pub fn save_model(model: &Net>, path: &String) { - let recorder = CompactRecorder::new(); - let model_path = format!("{path}.mpk"); - println!("info: Modèle de validation sauvegardé : {model_path}"); - recorder - .record(model.clone().into_record(), model_path.into()) - .unwrap(); -} - -pub fn load_model(dense_size: usize, path: &String) -> Option>> { - let model_path = format!("{path}.mpk"); - // println!("Chargement du modèle depuis : {model_path}"); - - CompactRecorder::new() - .load(model_path.into(), &NdArrayDevice::default()) - .map(|record| { - Net::new( - ::StateType::size(), - dense_size, - ::ActionType::size(), - ) - .load_record(record) - }) - .ok() -} diff --git a/bot/src/burnrl/algos/ppo_valid.rs b/bot/src/burnrl/algos/ppo_valid.rs deleted file mode 100644 index 8a391fb..0000000 --- a/bot/src/burnrl/algos/ppo_valid.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::burnrl::environment_valid::TrictracEnvironment; -use crate::burnrl::utils::Config; -use burn::backend::{ndarray::NdArrayDevice, NdArray}; -use burn::module::Module; -use burn::nn::{Initializer, Linear, LinearConfig}; -use burn::optim::AdamWConfig; -use burn::record::{CompactRecorder, Recorder}; -use burn::tensor::activation::{relu, softmax}; -use burn::tensor::backend::{AutodiffBackend, Backend}; -use burn::tensor::Tensor; -use burn_rl::agent::{PPOModel, PPOOutput, PPOTrainingConfig, PPO}; -use burn_rl::base::{Action, Agent, ElemType, Environment, Memory, Model, State}; -use std::env; -use std::fs; -use std::time::SystemTime; - -#[derive(Module, Debug)] -pub struct Net { - linear: Linear, - linear_actor: Linear, - linear_critic: Linear, -} - -impl Net { - #[allow(unused)] - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - let initializer = Initializer::XavierUniform { gain: 1.0 }; - Self { - linear: LinearConfig::new(input_size, dense_size) - .with_initializer(initializer.clone()) - .init(&Default::default()), - linear_actor: LinearConfig::new(dense_size, output_size) - .with_initializer(initializer.clone()) - .init(&Default::default()), - linear_critic: LinearConfig::new(dense_size, 1) - .with_initializer(initializer) - .init(&Default::default()), - } - } -} - -impl Model, PPOOutput, Tensor> for Net { - fn forward(&self, input: Tensor) -> PPOOutput { - let layer_0_output = relu(self.linear.forward(input)); - let policies = softmax(self.linear_actor.forward(layer_0_output.clone()), 1); - let values = self.linear_critic.forward(layer_0_output); - - PPOOutput::::new(policies, values) - } - - fn infer(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear.forward(input)); - softmax(self.linear_actor.forward(layer_0_output.clone()), 1) - } -} - -impl PPOModel for Net {} -#[allow(unused)] -const MEMORY_SIZE: usize = 512; - -type MyAgent = PPO>; - -#[allow(unused)] -pub fn run< - E: Environment + AsMut, - B: AutodiffBackend, ->( - conf: &Config, - visualized: bool, - // ) -> PPO> { -) -> impl Agent { - let mut env = E::new(visualized); - env.as_mut().max_steps = conf.max_steps; - - let mut model = Net::::new( - <::StateType as State>::size(), - conf.dense_size, - <::ActionType as Action>::size(), - ); - let agent = MyAgent::default(); - let config = PPOTrainingConfig { - gamma: conf.gamma, - lambda: conf.lambda, - epsilon_clip: conf.epsilon_clip, - critic_weight: conf.critic_weight, - entropy_weight: conf.entropy_weight, - learning_rate: conf.learning_rate, - epochs: conf.epochs, - batch_size: conf.batch_size, - clip_grad: Some(burn::grad_clipping::GradientClippingConfig::Value( - conf.clip_grad, - )), - }; - - let mut optimizer = AdamWConfig::new() - .with_grad_clipping(config.clip_grad.clone()) - .init(); - let mut memory = Memory::::default(); - for episode in 0..conf.num_episodes { - let mut episode_done = false; - let mut episode_reward = 0.0; - let mut episode_duration = 0_usize; - let mut now = SystemTime::now(); - - env.reset(); - while !episode_done { - let state = env.state(); - if let Some(action) = MyAgent::::react_with_model(&state, &model) { - let snapshot = env.step(action); - episode_reward += <::RewardType as Into>::into( - snapshot.reward().clone(), - ); - - memory.push( - state, - *snapshot.state(), - action, - snapshot.reward().clone(), - snapshot.done(), - ); - - episode_duration += 1; - episode_done = snapshot.done() || episode_duration >= conf.max_steps; - } - } - println!( - "{{\"episode\": {episode}, \"reward\": {episode_reward:.4}, \"steps count\": {episode_duration}, \"duration\": {}}}", - now.elapsed().unwrap().as_secs(), - ); - - now = SystemTime::now(); - model = MyAgent::train::(model, &memory, &mut optimizer, &config); - memory.clear(); - } - - if let Some(path) = &conf.save_path { - let device = NdArrayDevice::default(); - let recorder = CompactRecorder::new(); - let tmp_path = env::temp_dir().join("tmp_model.mpk"); - - // Save the trained model (backend B) to a temporary file - recorder - .record(model.clone().into_record(), tmp_path.clone()) - .expect("Failed to save temporary model"); - - // Create a new model instance with the target backend (NdArray) - let model_to_save: Net> = Net::new( - <::StateType as State>::size(), - conf.dense_size, - <::ActionType as Action>::size(), - ); - - // Load the record from the temporary file into the new model - let record = recorder - .load(tmp_path.clone(), &device) - .expect("Failed to load temporary model"); - let model_with_loaded_weights = model_to_save.load_record(record); - - // Clean up the temporary file - fs::remove_file(tmp_path).expect("Failed to remove temporary model file"); - - save_model(&model_with_loaded_weights, path); - } - agent.valid(model) -} - -pub fn save_model(model: &Net>, path: &String) { - let recorder = CompactRecorder::new(); - let model_path = format!("{path}.mpk"); - println!("info: Modèle de validation sauvegardé : {model_path}"); - recorder - .record(model.clone().into_record(), model_path.into()) - .unwrap(); -} - -pub fn load_model(dense_size: usize, path: &String) -> Option>> { - let model_path = format!("{path}.mpk"); - // println!("Chargement du modèle depuis : {model_path}"); - - CompactRecorder::new() - .load(model_path.into(), &NdArrayDevice::default()) - .map(|record| { - Net::new( - ::StateType::size(), - dense_size, - ::ActionType::size(), - ) - .load_record(record) - }) - .ok() -} diff --git a/bot/src/burnrl/algos/sac.rs b/bot/src/burnrl/algos/sac.rs deleted file mode 100644 index 67db72a..0000000 --- a/bot/src/burnrl/algos/sac.rs +++ /dev/null @@ -1,221 +0,0 @@ -use crate::burnrl::environment::TrictracEnvironment; -use crate::burnrl::utils::{soft_update_linear, Config}; -use burn::backend::{ndarray::NdArrayDevice, NdArray}; -use burn::module::Module; -use burn::nn::{Linear, LinearConfig}; -use burn::optim::AdamWConfig; -use burn::record::{CompactRecorder, Recorder}; -use burn::tensor::activation::{relu, softmax}; -use burn::tensor::backend::{AutodiffBackend, Backend}; -use burn::tensor::Tensor; -use burn_rl::agent::{SACActor, SACCritic, SACNets, SACOptimizer, SACTrainingConfig, SAC}; -use burn_rl::base::{Action, Agent, ElemType, Environment, Memory, Model, State}; -use std::time::SystemTime; - -#[derive(Module, Debug)] -pub struct Actor { - linear_0: Linear, - linear_1: Linear, - linear_2: Linear, -} - -impl Actor { - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - Self { - linear_0: LinearConfig::new(input_size, dense_size).init(&Default::default()), - linear_1: LinearConfig::new(dense_size, dense_size).init(&Default::default()), - linear_2: LinearConfig::new(dense_size, output_size).init(&Default::default()), - } - } -} - -impl Model, Tensor> for Actor { - fn forward(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear_0.forward(input)); - let layer_1_output = relu(self.linear_1.forward(layer_0_output)); - - softmax(self.linear_2.forward(layer_1_output), 1) - } - - fn infer(&self, input: Tensor) -> Tensor { - self.forward(input) - } -} - -impl SACActor for Actor {} - -#[derive(Module, Debug)] -pub struct Critic { - linear_0: Linear, - linear_1: Linear, - linear_2: Linear, -} - -impl Critic { - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - Self { - linear_0: LinearConfig::new(input_size, dense_size).init(&Default::default()), - linear_1: LinearConfig::new(dense_size, dense_size).init(&Default::default()), - linear_2: LinearConfig::new(dense_size, output_size).init(&Default::default()), - } - } - - fn consume(self) -> (Linear, Linear, Linear) { - (self.linear_0, self.linear_1, self.linear_2) - } -} - -impl Model, Tensor> for Critic { - fn forward(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear_0.forward(input)); - let layer_1_output = relu(self.linear_1.forward(layer_0_output)); - - self.linear_2.forward(layer_1_output) - } - - fn infer(&self, input: Tensor) -> Tensor { - self.forward(input) - } -} - -impl SACCritic for Critic { - fn soft_update(this: Self, that: &Self, tau: ElemType) -> Self { - let (linear_0, linear_1, linear_2) = this.consume(); - - Self { - linear_0: soft_update_linear(linear_0, &that.linear_0, tau), - linear_1: soft_update_linear(linear_1, &that.linear_1, tau), - linear_2: soft_update_linear(linear_2, &that.linear_2, tau), - } - } -} - -#[allow(unused)] -const MEMORY_SIZE: usize = 4096; - -type MyAgent = SAC>; - -#[allow(unused)] -pub fn run< - E: Environment + AsMut, - B: AutodiffBackend, ->( - conf: &Config, - visualized: bool, -) -> impl Agent { - let mut env = E::new(visualized); - env.as_mut().max_steps = conf.max_steps; - let state_dim = <::StateType as State>::size(); - let action_dim = <::ActionType as Action>::size(); - - let actor = Actor::::new(state_dim, conf.dense_size, action_dim); - let critic_1 = Critic::::new(state_dim, conf.dense_size, action_dim); - let critic_2 = Critic::::new(state_dim, conf.dense_size, action_dim); - let mut nets = SACNets::, Critic>::new(actor, critic_1, critic_2); - - let mut agent = MyAgent::default(); - - let config = SACTrainingConfig { - gamma: conf.gamma, - tau: conf.tau, - learning_rate: conf.learning_rate, - min_probability: conf.min_probability, - batch_size: conf.batch_size, - clip_grad: Some(burn::grad_clipping::GradientClippingConfig::Value( - conf.clip_grad, - )), - }; - - let mut memory = Memory::::default(); - - let optimizer_config = AdamWConfig::new().with_grad_clipping(config.clip_grad.clone()); - - let mut optimizer = SACOptimizer::new( - optimizer_config.clone().init(), - optimizer_config.clone().init(), - optimizer_config.clone().init(), - optimizer_config.init(), - ); - - let mut step = 0_usize; - - for episode in 0..conf.num_episodes { - let mut episode_done = false; - let mut episode_reward = 0.0; - let mut episode_duration = 0_usize; - let mut state = env.state(); - let mut now = SystemTime::now(); - - while !episode_done { - if let Some(action) = MyAgent::::react_with_model(&state, &nets.actor) { - let snapshot = env.step(action); - - episode_reward += <::RewardType as Into>::into( - snapshot.reward().clone(), - ); - - memory.push( - state, - *snapshot.state(), - action, - snapshot.reward().clone(), - snapshot.done(), - ); - - if config.batch_size < memory.len() { - nets = agent.train::(nets, &memory, &mut optimizer, &config); - } - - step += 1; - episode_duration += 1; - - if snapshot.done() || episode_duration >= conf.max_steps { - env.reset(); - episode_done = true; - - println!( - "{{\"episode\": {episode}, \"reward\": {episode_reward:.4}, \"steps count\": {episode_duration}, \"duration\": {}}}", - now.elapsed().unwrap().as_secs() - ); - now = SystemTime::now(); - } else { - state = *snapshot.state(); - } - } - } - } - - let valid_agent = agent.valid(nets.actor); - if let Some(path) = &conf.save_path { - if let Some(model) = valid_agent.model() { - save_model(model, path); - } - } - valid_agent -} - -pub fn save_model(model: &Actor>, path: &String) { - let recorder = CompactRecorder::new(); - let model_path = format!("{path}.mpk"); - println!("info: Modèle de validation sauvegardé : {model_path}"); - recorder - .record(model.clone().into_record(), model_path.into()) - .unwrap(); -} - -pub fn load_model(dense_size: usize, path: &String) -> Option>> { - let model_path = format!("{path}.mpk"); - // println!("Chargement du modèle depuis : {model_path}"); - - CompactRecorder::new() - .load(model_path.into(), &NdArrayDevice::default()) - .map(|record| { - Actor::new( - ::StateType::size(), - dense_size, - ::ActionType::size(), - ) - .load_record(record) - }) - .ok() -} \ No newline at end of file diff --git a/bot/src/burnrl/algos/sac_valid.rs b/bot/src/burnrl/algos/sac_valid.rs deleted file mode 100644 index 81523c4..0000000 --- a/bot/src/burnrl/algos/sac_valid.rs +++ /dev/null @@ -1,222 +0,0 @@ -use crate::burnrl::environment_valid::TrictracEnvironment; -use crate::burnrl::utils::{soft_update_linear, Config}; -use burn::backend::{ndarray::NdArrayDevice, NdArray}; -use burn::module::Module; -use burn::nn::{Linear, LinearConfig}; -use burn::optim::AdamWConfig; -use burn::record::{CompactRecorder, Recorder}; -use burn::tensor::activation::{relu, softmax}; -use burn::tensor::backend::{AutodiffBackend, Backend}; -use burn::tensor::Tensor; -use burn_rl::agent::{SACActor, SACCritic, SACNets, SACOptimizer, SACTrainingConfig, SAC}; -use burn_rl::base::{Action, Agent, ElemType, Environment, Memory, Model, State}; -use std::time::SystemTime; - -#[derive(Module, Debug)] -pub struct Actor { - linear_0: Linear, - linear_1: Linear, - linear_2: Linear, -} - -impl Actor { - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - Self { - linear_0: LinearConfig::new(input_size, dense_size).init(&Default::default()), - linear_1: LinearConfig::new(dense_size, dense_size).init(&Default::default()), - linear_2: LinearConfig::new(dense_size, output_size).init(&Default::default()), - } - } -} - -impl Model, Tensor> for Actor { - fn forward(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear_0.forward(input)); - let layer_1_output = relu(self.linear_1.forward(layer_0_output)); - - softmax(self.linear_2.forward(layer_1_output), 1) - } - - fn infer(&self, input: Tensor) -> Tensor { - self.forward(input) - } -} - -impl SACActor for Actor {} - -#[derive(Module, Debug)] -pub struct Critic { - linear_0: Linear, - linear_1: Linear, - linear_2: Linear, -} - -impl Critic { - pub fn new(input_size: usize, dense_size: usize, output_size: usize) -> Self { - Self { - linear_0: LinearConfig::new(input_size, dense_size).init(&Default::default()), - linear_1: LinearConfig::new(dense_size, dense_size).init(&Default::default()), - linear_2: LinearConfig::new(dense_size, output_size).init(&Default::default()), - } - } - - fn consume(self) -> (Linear, Linear, Linear) { - (self.linear_0, self.linear_1, self.linear_2) - } -} - -impl Model, Tensor> for Critic { - fn forward(&self, input: Tensor) -> Tensor { - let layer_0_output = relu(self.linear_0.forward(input)); - let layer_1_output = relu(self.linear_1.forward(layer_0_output)); - - self.linear_2.forward(layer_1_output) - } - - fn infer(&self, input: Tensor) -> Tensor { - self.forward(input) - } -} - -impl SACCritic for Critic { - fn soft_update(this: Self, that: &Self, tau: ElemType) -> Self { - let (linear_0, linear_1, linear_2) = this.consume(); - - Self { - linear_0: soft_update_linear(linear_0, &that.linear_0, tau), - linear_1: soft_update_linear(linear_1, &that.linear_1, tau), - linear_2: soft_update_linear(linear_2, &that.linear_2, tau), - } - } -} - -#[allow(unused)] -const MEMORY_SIZE: usize = 4096; - -type MyAgent = SAC>; - -#[allow(unused)] -pub fn run< - E: Environment + AsMut, - B: AutodiffBackend, ->( - conf: &Config, - visualized: bool, -) -> impl Agent { - let mut env = E::new(visualized); - env.as_mut().max_steps = conf.max_steps; - let state_dim = <::StateType as State>::size(); - let action_dim = <::ActionType as Action>::size(); - - let actor = Actor::::new(state_dim, conf.dense_size, action_dim); - let critic_1 = Critic::::new(state_dim, conf.dense_size, action_dim); - let critic_2 = Critic::::new(state_dim, conf.dense_size, action_dim); - let mut nets = SACNets::, Critic>::new(actor, critic_1, critic_2); - - let mut agent = MyAgent::default(); - - let config = SACTrainingConfig { - gamma: conf.gamma, - tau: conf.tau, - learning_rate: conf.learning_rate, - min_probability: conf.min_probability, - batch_size: conf.batch_size, - clip_grad: Some(burn::grad_clipping::GradientClippingConfig::Value( - conf.clip_grad, - )), - }; - - let mut memory = Memory::::default(); - - let optimizer_config = AdamWConfig::new().with_grad_clipping(config.clip_grad.clone()); - - let mut optimizer = SACOptimizer::new( - optimizer_config.clone().init(), - optimizer_config.clone().init(), - optimizer_config.clone().init(), - optimizer_config.init(), - ); - - let mut step = 0_usize; - - for episode in 0..conf.num_episodes { - let mut episode_done = false; - let mut episode_reward = 0.0; - let mut episode_duration = 0_usize; - let mut state = env.state(); - let mut now = SystemTime::now(); - - while !episode_done { - if let Some(action) = MyAgent::::react_with_model(&state, &nets.actor) { - let snapshot = env.step(action); - - episode_reward += <::RewardType as Into>::into( - snapshot.reward().clone(), - ); - - memory.push( - state, - *snapshot.state(), - action, - snapshot.reward().clone(), - snapshot.done(), - ); - - if config.batch_size < memory.len() { - nets = agent.train::(nets, &memory, &mut optimizer, &config); - } - - step += 1; - episode_duration += 1; - - if snapshot.done() || episode_duration >= conf.max_steps { - env.reset(); - episode_done = true; - - println!( - "{{\"episode\": {episode}, \"reward\": {episode_reward:.4}, \"steps count\": {episode_duration}, \"duration\": {}}}", - now.elapsed().unwrap().as_secs() - ); - now = SystemTime::now(); - } else { - state = *snapshot.state(); - } - } - } - } - - let valid_agent = agent.valid(nets.actor); - if let Some(path) = &conf.save_path { - if let Some(model) = valid_agent.model() { - save_model(model, path); - } - } - valid_agent -} - -pub fn save_model(model: &Actor>, path: &String) { - let recorder = CompactRecorder::new(); - let model_path = format!("{path}.mpk"); - println!("info: Modèle de validation sauvegardé : {model_path}"); - recorder - .record(model.clone().into_record(), model_path.into()) - .unwrap(); -} - -pub fn load_model(dense_size: usize, path: &String) -> Option>> { - let model_path = format!("{path}.mpk"); - // println!("Chargement du modèle depuis : {model_path}"); - - CompactRecorder::new() - .load(model_path.into(), &NdArrayDevice::default()) - .map(|record| { - Actor::new( - ::StateType::size(), - dense_size, - ::ActionType::size(), - ) - .load_record(record) - }) - .ok() -} - diff --git a/bot/src/burnrl/environment.rs b/bot/src/burnrl/environment.rs deleted file mode 100644 index 4a7bdcb..0000000 --- a/bot/src/burnrl/environment.rs +++ /dev/null @@ -1,424 +0,0 @@ -use std::io::Write; - -use burn::{prelude::Backend, tensor::Tensor}; -use burn_rl::base::{Action, Environment, Snapshot, State}; -use rand::{rng, Rng}; -use trictrac_store::training_common; -use trictrac_store::{GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage}; - -const ERROR_REWARD: f32 = -1.0012121; -const REWARD_VALID_MOVE: f32 = 1.0012121; -const REWARD_RATIO: f32 = 0.1; -const WIN_POINTS: f32 = 100.0; - -/// État du jeu Trictrac pour burn-rl -#[derive(Debug, Clone, Copy)] -pub struct TrictracState { - pub data: [i8; 36], // Représentation vectorielle de l'état du jeu -} - -impl State for TrictracState { - type Data = [i8; 36]; - - fn to_tensor(&self) -> Tensor { - Tensor::from_floats(self.data, &B::Device::default()) - } - - fn size() -> usize { - 36 - } -} - -impl TrictracState { - /// Convertit un GameState en TrictracState - pub fn from_game_state(game_state: &GameState) -> Self { - let state_vec = game_state.to_vec(); - let mut data = [0; 36]; - - // Copier les données en s'assurant qu'on ne dépasse pas la taille - let copy_len = state_vec.len().min(36); - data[..copy_len].copy_from_slice(&state_vec[..copy_len]); - - TrictracState { data } - } -} - -/// Actions possibles dans Trictrac pour burn-rl -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct TrictracAction { - // u32 as required by burn_rl::base::Action type - pub index: u32, -} - -impl Action for TrictracAction { - fn random() -> Self { - use rand::{rng, Rng}; - let mut rng = rng(); - TrictracAction { - index: rng.random_range(0..Self::size() as u32), - } - } - - fn enumerate() -> Vec { - (0..Self::size() as u32) - .map(|index| TrictracAction { index }) - .collect() - } - - fn size() -> usize { - 514 - } -} - -impl From for TrictracAction { - fn from(index: u32) -> Self { - TrictracAction { index } - } -} - -impl From for u32 { - fn from(action: TrictracAction) -> u32 { - action.index - } -} - -/// Environnement Trictrac pour burn-rl -#[derive(Debug)] -pub struct TrictracEnvironment { - pub game: GameState, - active_player_id: PlayerId, - opponent_id: PlayerId, - current_state: TrictracState, - episode_reward: f32, - pub step_count: usize, - pub best_ratio: f32, - pub max_steps: usize, - pub pointrolls_count: usize, - pub goodmoves_count: usize, - pub goodmoves_ratio: f32, - pub visualized: bool, -} - -impl Environment for TrictracEnvironment { - type StateType = TrictracState; - type ActionType = TrictracAction; - type RewardType = f32; - - fn new(visualized: bool) -> Self { - let mut game = GameState::new(false); - - // Ajouter deux joueurs - game.init_player("DQN Agent"); - game.init_player("Opponent"); - let player1_id = 1; - let player2_id = 2; - - // Commencer la partie - let _ = game.consume(&GameEvent::BeginGame { goes_first: 1 }); - - let current_state = TrictracState::from_game_state(&game); - TrictracEnvironment { - game, - active_player_id: player1_id, - opponent_id: player2_id, - current_state, - episode_reward: 0.0, - step_count: 0, - best_ratio: 0.0, - max_steps: 2000, - pointrolls_count: 0, - goodmoves_count: 0, - goodmoves_ratio: 0.0, - visualized, - } - } - - fn state(&self) -> Self::StateType { - self.current_state - } - - fn reset(&mut self) -> Snapshot { - // Réinitialiser le jeu - let history = self.game.history.clone(); - self.game = GameState::new(false); - self.game.init_player("DQN Agent"); - self.game.init_player("Opponent"); - - // Commencer la partie - let _ = self.game.consume(&GameEvent::BeginGame { goes_first: 1 }); - - self.current_state = TrictracState::from_game_state(&self.game); - self.episode_reward = 0.0; - self.goodmoves_ratio = if self.step_count == 0 { - 0.0 - } else { - self.goodmoves_count as f32 / self.step_count as f32 - }; - self.best_ratio = self.best_ratio.max(self.goodmoves_ratio); - let _warning = if self.best_ratio > 0.7 && self.goodmoves_ratio < 0.1 { - let path = "bot/models/logs/debug.log"; - if let Ok(mut out) = std::fs::File::create(path) { - write!(out, "{history:?}").expect("could not write history log"); - } - "!!!!" - } else { - "" - }; - // println!( - // "info: correct moves: {} ({}%) {}", - // self.goodmoves_count, - // (100.0 * self.goodmoves_ratio).round() as u32, - // warning - // ); - self.step_count = 0; - self.pointrolls_count = 0; - self.goodmoves_count = 0; - - Snapshot::new(self.current_state, 0.0, false) - } - - fn step(&mut self, action: Self::ActionType) -> Snapshot { - self.step_count += 1; - - // Convertir l'action burn-rl vers une action Trictrac - let trictrac_action = Self::convert_action(action); - - let mut reward = 0.0; - let is_rollpoint; - - // Exécuter l'action si c'est le tour de l'agent DQN - if self.game.active_player_id == self.active_player_id { - if let Some(action) = trictrac_action { - (reward, is_rollpoint) = self.execute_action(action); - if is_rollpoint { - self.pointrolls_count += 1; - } - if reward != ERROR_REWARD { - self.goodmoves_count += 1; - } - } else { - // Action non convertible, pénalité - panic!("action non convertible"); - //reward = -0.5; - } - } - - // Faire jouer l'adversaire (stratégie simple) - while self.game.active_player_id == self.opponent_id && self.game.stage != Stage::Ended { - reward += self.play_opponent_if_needed(); - } - - // Vérifier si la partie est terminée - // let max_steps = self.max_steps; - // let max_steps = self.min_steps - // + (self.max_steps as f32 - self.min_steps) - // * f32::exp((self.goodmoves_ratio - 1.0) / 0.25); - let done = self.game.stage == Stage::Ended || self.game.determine_winner().is_some(); - - if done { - // Récompense finale basée sur le résultat - if let Some(winner_id) = self.game.determine_winner() { - if winner_id == self.active_player_id { - reward += WIN_POINTS; // Victoire - } else { - reward -= WIN_POINTS; // Défaite - } - } - } - let terminated = done || self.step_count >= self.max_steps; - // let terminated = done || self.step_count >= max_steps.round() as usize; - - // Mettre à jour l'état - self.current_state = TrictracState::from_game_state(&self.game); - self.episode_reward += reward; - - if self.visualized && terminated { - println!( - "Episode terminé. Récompense totale: {:.2}, Étapes: {}", - self.episode_reward, self.step_count - ); - } - - Snapshot::new(self.current_state, reward, terminated) - } -} - -impl TrictracEnvironment { - /// Convertit une action burn-rl vers une action Trictrac - pub fn convert_action(action: TrictracAction) -> Option { - training_common::TrictracAction::from_action_index(action.index.try_into().unwrap()) - } - - /// Convertit l'index d'une action au sein des actions valides vers une action Trictrac - #[allow(dead_code)] - fn convert_valid_action_index( - &self, - action: TrictracAction, - game_state: &GameState, - ) -> Option { - use training_common::get_valid_actions; - - // Obtenir les actions valides dans le contexte actuel - if let Ok(valid_actions) = get_valid_actions(game_state) { - // Mapper l'index d'action sur une action valide - let action_index = (action.index as usize) % valid_actions.len(); - Some(valid_actions[action_index].clone()) - } else { - None - } - } - - /// Exécute une action Trictrac dans le jeu - // fn execute_action( - // &mut self, - // action: training_common::TrictracAction, - // ) -> Result> { - fn execute_action(&mut self, action: training_common::TrictracAction) -> (f32, bool) { - use training_common::TrictracAction; - - let mut reward = 0.0; - let mut is_rollpoint = false; - - // Appliquer l'événement si valide - if let Some(event) = action.to_event(&self.game) { - if self.game.validate(&event) { - let _ = self.game.consume(&event); - // reward += REWARD_VALID_MOVE; - // Simuler le résultat des dés après un Roll - if matches!(action, TrictracAction::Roll) { - let mut rng = rng(); - let dice_values = (rng.random_range(1..=6), rng.random_range(1..=6)); - let dice_event = GameEvent::RollResult { - player_id: self.active_player_id, - dice: trictrac_store::Dice { - values: dice_values, - }, - }; - if self.game.validate(&dice_event) { - let _ = self.game.consume(&dice_event); - let (points, adv_points) = self.game.dice_points; - reward += REWARD_RATIO * (points as f32 - adv_points as f32); - if points > 0 { - is_rollpoint = true; - // println!("info: rolled for {reward}"); - } - // Récompense proportionnelle aux points - } - } - } else { - // Pénalité pour action invalide - // on annule les précédents reward - // et on indique une valeur reconnaissable pour statistiques - reward = ERROR_REWARD; - self.game.mark_points_for_bot_training(self.opponent_id, 1); - } - } else { - reward = ERROR_REWARD; - self.game.mark_points_for_bot_training(self.opponent_id, 1); - } - - (reward, is_rollpoint) - } - - /// Fait jouer l'adversaire avec une stratégie simple - fn play_opponent_if_needed(&mut self) -> f32 { - let mut reward = 0.0; - - // Si c'est le tour de l'adversaire, jouer automatiquement - if self.game.active_player_id == self.opponent_id && self.game.stage != Stage::Ended { - // Utiliser la stratégie default pour l'adversaire - use crate::BotStrategy; - - let mut strategy = crate::strategy::random::RandomStrategy::default(); - strategy.set_player_id(self.opponent_id); - if let Some(color) = self.game.player_color_by_id(&self.opponent_id) { - strategy.set_color(color); - } - *strategy.get_mut_game() = self.game.clone(); - - // Exécuter l'action selon le turn_stage - let mut calculate_points = false; - let opponent_color = trictrac_store::Color::Black; - let event = match self.game.turn_stage { - TurnStage::RollDice => GameEvent::Roll { - player_id: self.opponent_id, - }, - TurnStage::RollWaiting => { - let mut rng = rng(); - let dice_values = (rng.random_range(1..=6), rng.random_range(1..=6)); - calculate_points = true; - GameEvent::RollResult { - player_id: self.opponent_id, - dice: trictrac_store::Dice { - values: dice_values, - }, - } - } - TurnStage::MarkPoints => { - let dice_roll_count = self - .game - .players - .get(&self.opponent_id) - .unwrap() - .dice_roll_count; - let points_rules = - PointsRules::new(&opponent_color, &self.game.board, self.game.dice); - GameEvent::Mark { - player_id: self.opponent_id, - points: points_rules.get_points(dice_roll_count).0, - } - } - TurnStage::MarkAdvPoints => { - let opponent_color = trictrac_store::Color::Black; - let dice_roll_count = self - .game - .players - .get(&self.opponent_id) - .unwrap() - .dice_roll_count; - let points_rules = - PointsRules::new(&opponent_color, &self.game.board, self.game.dice); - // pas de reward : déjà comptabilisé lors du tour de blanc - GameEvent::Mark { - player_id: self.opponent_id, - points: points_rules.get_points(dice_roll_count).1, - } - } - TurnStage::HoldOrGoChoice => { - // Stratégie simple : toujours continuer - GameEvent::Go { - player_id: self.opponent_id, - } - } - TurnStage::Move => GameEvent::Move { - player_id: self.opponent_id, - moves: strategy.choose_move(), - }, - }; - - if self.game.validate(&event) { - let _ = self.game.consume(&event); - if calculate_points { - let dice_roll_count = self - .game - .players - .get(&self.opponent_id) - .unwrap() - .dice_roll_count; - let points_rules = - PointsRules::new(&opponent_color, &self.game.board, self.game.dice); - let (points, adv_points) = points_rules.get_points(dice_roll_count); - // Récompense proportionnelle aux points - reward -= REWARD_RATIO * (points as f32 - adv_points as f32); - } - } - } - reward - } -} - -impl AsMut for TrictracEnvironment { - fn as_mut(&mut self) -> &mut Self { - self - } -} diff --git a/bot/src/burnrl/main.rs b/bot/src/burnrl/main.rs deleted file mode 100644 index 9275f59..0000000 --- a/bot/src/burnrl/main.rs +++ /dev/null @@ -1,90 +0,0 @@ -use trictrac_bot::burnrl::algos::{dqn, dqn_valid, ppo, ppo_valid, sac, sac_valid}; -use trictrac_bot::burnrl::environment::TrictracEnvironment; -use trictrac_bot::burnrl::environment_valid::TrictracEnvironment as TrictracEnvironmentValid; -use trictrac_bot::burnrl::utils::{demo_model, Config}; -use burn::backend::{Autodiff, NdArray}; -use burn_rl::base::ElemType; -use std::env; - -type Backend = Autodiff>; - -fn main() { - let args: Vec = env::args().collect(); - let algo = &args[1]; - // let dir_path = &args[2]; - - let path = format!("bot/models/burnrl_{algo}"); - println!( - "info: loading configuration from file {:?}", - confy::get_configuration_file_path("trictrac_bot", None).unwrap() - ); - let mut conf: Config = confy::load("trictrac_bot", None).expect("Could not load config"); - conf.save_path = Some(path.clone()); - println!("{conf}----------"); - - match algo.as_str() { - "dqn" => { - let _agent = dqn::run::(&conf, false); - println!("> Chargement du modèle pour test"); - let loaded_model = dqn::load_model(conf.dense_size, &path); - let loaded_agent: burn_rl::agent::DQN = - burn_rl::agent::DQN::new(loaded_model.unwrap()); - - println!("> Test avec le modèle chargé"); - demo_model(loaded_agent); - } - "dqn_valid" => { - let _agent = dqn_valid::run::(&conf, false); - println!("> Chargement du modèle pour test"); - let loaded_model = dqn_valid::load_model(conf.dense_size, &path); - let loaded_agent: burn_rl::agent::DQN = - burn_rl::agent::DQN::new(loaded_model.unwrap()); - - println!("> Test avec le modèle chargé"); - demo_model(loaded_agent); - } - "sac" => { - let _agent = sac::run::(&conf, false); - println!("> Chargement du modèle pour test"); - let loaded_model = sac::load_model(conf.dense_size, &path); - let loaded_agent: burn_rl::agent::SAC = - burn_rl::agent::SAC::new(loaded_model.unwrap()); - - println!("> Test avec le modèle chargé"); - demo_model(loaded_agent); - } - "sac_valid" => { - let _agent = sac_valid::run::(&conf, false); - println!("> Chargement du modèle pour test"); - let loaded_model = sac_valid::load_model(conf.dense_size, &path); - let loaded_agent: burn_rl::agent::SAC = - burn_rl::agent::SAC::new(loaded_model.unwrap()); - - println!("> Test avec le modèle chargé"); - demo_model(loaded_agent); - } - "ppo" => { - let _agent = ppo::run::(&conf, false); - println!("> Chargement du modèle pour test"); - let loaded_model = ppo::load_model(conf.dense_size, &path); - let loaded_agent: burn_rl::agent::PPO = - burn_rl::agent::PPO::new(loaded_model.unwrap()); - - println!("> Test avec le modèle chargé"); - demo_model(loaded_agent); - } - "ppo_valid" => { - let _agent = ppo_valid::run::(&conf, false); - println!("> Chargement du modèle pour test"); - let loaded_model = ppo_valid::load_model(conf.dense_size, &path); - let loaded_agent: burn_rl::agent::PPO = - burn_rl::agent::PPO::new(loaded_model.unwrap()); - - println!("> Test avec le modèle chargé"); - demo_model(loaded_agent); - } - &_ => { - println!("unknown algo {algo}"); - } - } -} diff --git a/bot/src/burnrl/mod.rs b/bot/src/burnrl/mod.rs deleted file mode 100644 index 292bbb8..0000000 --- a/bot/src/burnrl/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod algos; -pub mod environment; -pub mod environment_valid; -pub mod utils; diff --git a/bot/src/burnrl/utils.rs b/bot/src/burnrl/utils.rs deleted file mode 100644 index 9233819..0000000 --- a/bot/src/burnrl/utils.rs +++ /dev/null @@ -1,132 +0,0 @@ -use burn::module::{Param, ParamId}; -use burn::nn::Linear; -use burn::tensor::backend::Backend; -use burn::tensor::Tensor; -use burn_rl::base::{Agent, ElemType, Environment}; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct Config { - pub save_path: Option, - pub max_steps: usize, // max steps by episode - pub num_episodes: usize, - pub dense_size: usize, // neural network complexity - - // discount factor. Plus élevé = encourage stratégies à long terme - pub gamma: f32, - // soft update rate. Taux de mise à jour du réseau cible. Plus bas = adaptation plus lente moins sensible aux coups de chance - pub tau: f32, - // taille du pas. Bas : plus lent, haut : risque de ne jamais - pub learning_rate: f32, - // nombre d'expériences passées sur lesquelles pour calcul de l'erreur moy. - pub batch_size: usize, - // limite max de correction à apporter au gradient (default 100) - pub clip_grad: f32, - - // ---- for SAC - pub min_probability: f32, - - // ---- for DQN - // epsilon initial value (0.9 => more exploration) - pub eps_start: f64, - pub eps_end: f64, - // eps_decay higher = epsilon decrease slower - // used in : epsilon = eps_end + (eps_start - eps_end) * e^(-step / eps_decay); - // epsilon is updated at the start of each episode - pub eps_decay: f64, - - // ---- for PPO - pub lambda: f32, - pub epsilon_clip: f32, - pub critic_weight: f32, - pub entropy_weight: f32, - pub epochs: usize, -} - -impl Default for Config { - fn default() -> Self { - Self { - save_path: None, - max_steps: 2000, - num_episodes: 1000, - dense_size: 256, - gamma: 0.999, - tau: 0.005, - learning_rate: 0.001, - batch_size: 32, - clip_grad: 100.0, - min_probability: 1e-9, - eps_start: 0.9, - eps_end: 0.05, - eps_decay: 1000.0, - lambda: 0.95, - epsilon_clip: 0.2, - critic_weight: 0.5, - entropy_weight: 0.01, - epochs: 8, - } - } -} - -impl std::fmt::Display for Config { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let mut s = String::new(); - s.push_str(&format!("max_steps={:?}\n", self.max_steps)); - s.push_str(&format!("num_episodes={:?}\n", self.num_episodes)); - s.push_str(&format!("dense_size={:?}\n", self.dense_size)); - s.push_str(&format!("eps_start={:?}\n", self.eps_start)); - s.push_str(&format!("eps_end={:?}\n", self.eps_end)); - s.push_str(&format!("eps_decay={:?}\n", self.eps_decay)); - s.push_str(&format!("gamma={:?}\n", self.gamma)); - s.push_str(&format!("tau={:?}\n", self.tau)); - s.push_str(&format!("learning_rate={:?}\n", self.learning_rate)); - s.push_str(&format!("batch_size={:?}\n", self.batch_size)); - s.push_str(&format!("clip_grad={:?}\n", self.clip_grad)); - s.push_str(&format!("min_probability={:?}\n", self.min_probability)); - s.push_str(&format!("lambda={:?}\n", self.lambda)); - s.push_str(&format!("epsilon_clip={:?}\n", self.epsilon_clip)); - s.push_str(&format!("critic_weight={:?}\n", self.critic_weight)); - s.push_str(&format!("entropy_weight={:?}\n", self.entropy_weight)); - s.push_str(&format!("epochs={:?}\n", self.epochs)); - write!(f, "{s}") - } -} - -pub fn demo_model(agent: impl Agent) { - let mut env = E::new(true); - let mut state = env.state(); - let mut done = false; - while !done { - if let Some(action) = agent.react(&state) { - let snapshot = env.step(action); - state = *snapshot.state(); - done = snapshot.done(); - } - } -} - -fn soft_update_tensor( - this: &Param>, - that: &Param>, - tau: ElemType, -) -> Param> { - let that_weight = that.val(); - let this_weight = this.val(); - let new_weight = this_weight * (1.0 - tau) + that_weight * tau; - - Param::initialized(ParamId::new(), new_weight) -} - -pub fn soft_update_linear( - this: Linear, - that: &Linear, - tau: ElemType, -) -> Linear { - let weight = soft_update_tensor(&this.weight, &that.weight, tau); - let bias = match (&this.bias, &that.bias) { - (Some(this_bias), Some(that_bias)) => Some(soft_update_tensor(this_bias, that_bias, tau)), - _ => None, - }; - - Linear:: { weight, bias } -} diff --git a/bot/src/burnrl/algos/dqn_valid.rs b/bot/src/dqn/burnrl/dqn_model.rs similarity index 62% rename from bot/src/burnrl/algos/dqn_valid.rs rename to bot/src/dqn/burnrl/dqn_model.rs index 6198100..0c333b0 100644 --- a/bot/src/burnrl/algos/dqn_valid.rs +++ b/bot/src/dqn/burnrl/dqn_model.rs @@ -1,16 +1,13 @@ -use crate::burnrl::environment_valid::TrictracEnvironment; -use crate::burnrl::utils::{soft_update_linear, Config}; -use burn::backend::{ndarray::NdArrayDevice, NdArray}; +use crate::dqn::burnrl::utils::soft_update_linear; use burn::module::Module; use burn::nn::{Linear, LinearConfig}; use burn::optim::AdamWConfig; -use burn::record::{CompactRecorder, Recorder}; use burn::tensor::activation::relu; use burn::tensor::backend::{AutodiffBackend, Backend}; use burn::tensor::Tensor; use burn_rl::agent::DQN; use burn_rl::agent::{DQNModel, DQNTrainingConfig}; -use burn_rl::base::{Action, Agent, ElemType, Environment, Memory, Model, State}; +use burn_rl::base::{Action, ElemType, Environment, Memory, Model, State}; use std::time::SystemTime; #[derive(Module, Debug)] @@ -63,20 +60,37 @@ impl DQNModel for Net { #[allow(unused)] const MEMORY_SIZE: usize = 8192; +pub struct DqnConfig { + pub num_episodes: usize, + // pub memory_size: usize, + pub dense_size: usize, + pub eps_start: f64, + pub eps_end: f64, + pub eps_decay: f64, +} + +impl Default for DqnConfig { + fn default() -> Self { + Self { + num_episodes: 1000, + // memory_size: 8192, + dense_size: 256, + eps_start: 0.9, + eps_end: 0.05, + eps_decay: 1000.0, + } + } +} + type MyAgent = DQN>; #[allow(unused)] -// pub fn run, B: AutodiffBackend>( -pub fn run< - E: Environment + AsMut, - B: AutodiffBackend, ->( - conf: &Config, +pub fn run( + conf: &DqnConfig, visualized: bool, - // ) -> DQN> { -) -> impl Agent { +) -> DQN> { + // ) -> impl Agent { let mut env = E::new(visualized); - env.as_mut().max_steps = conf.max_steps; let model = Net::::new( <::StateType as State>::size(), @@ -86,16 +100,7 @@ pub fn run< let mut agent = MyAgent::new(model); - // let config = DQNTrainingConfig::default(); - let config = DQNTrainingConfig { - gamma: conf.gamma, - tau: conf.tau, - learning_rate: conf.learning_rate, - batch_size: conf.batch_size, - clip_grad: Some(burn::grad_clipping::GradientClippingConfig::Value( - conf.clip_grad, - )), - }; + let config = DQNTrainingConfig::default(); let mut memory = Memory::::default(); @@ -140,50 +145,22 @@ pub fn run< step += 1; episode_duration += 1; - if snapshot.done() || episode_duration >= conf.max_steps { - let envmut = env.as_mut(); - println!( - "{{\"episode\": {episode}, \"reward\": {episode_reward:.4}, \"steps count\": {episode_duration}, \"epsilon\": {eps_threshold:.3}, \"rollpoints\":{}, \"duration\": {}}}", - envmut.pointrolls_count, - now.elapsed().unwrap().as_secs(), - ); + if snapshot.done() || episode_duration >= E::MAX_STEPS { env.reset(); episode_done = true; + + println!( + "{{\"episode\": {}, \"reward\": {:.4}, \"steps count\": {}, \"duration\": {}}}", + episode, + episode_reward, + episode_duration, + now.elapsed().unwrap().as_secs() + ); now = SystemTime::now(); } else { state = *snapshot.state(); } } } - let valid_agent = agent.valid(); - if let Some(path) = &conf.save_path { - save_model(valid_agent.model().as_ref().unwrap(), path); - } - valid_agent -} - -pub fn save_model(model: &Net>, path: &String) { - let recorder = CompactRecorder::new(); - let model_path = format!("{path}.mpk"); - println!("info: Modèle de validation sauvegardé : {model_path}"); - recorder - .record(model.clone().into_record(), model_path.into()) - .unwrap(); -} - -pub fn load_model(dense_size: usize, path: &String) -> Option>> { - let model_path = format!("{path}.mpk"); - // println!("Chargement du modèle depuis : {model_path}"); - - CompactRecorder::new() - .load(model_path.into(), &NdArrayDevice::default()) - .map(|record| { - Net::new( - ::StateType::size(), - dense_size, - ::ActionType::size(), - ) - .load_record(record) - }) - .ok() + agent } diff --git a/bot/src/burnrl/environment_valid.rs b/bot/src/dqn/burnrl/environment.rs similarity index 60% rename from bot/src/burnrl/environment_valid.rs rename to bot/src/dqn/burnrl/environment.rs index eaf4223..5716fa1 100644 --- a/bot/src/burnrl/environment_valid.rs +++ b/bot/src/dqn/burnrl/environment.rs @@ -1,20 +1,17 @@ +use crate::dqn::dqn_common; use burn::{prelude::Backend, tensor::Tensor}; use burn_rl::base::{Action, Environment, Snapshot, State}; -use rand::{rng, Rng}; -use trictrac_store::training_common; -use trictrac_store::{GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage}; - -const ERROR_REWARD: f32 = -1.0012121; -const REWARD_RATIO: f32 = 0.1; +use rand::{thread_rng, Rng}; +use store::{GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage}; /// État du jeu Trictrac pour burn-rl #[derive(Debug, Clone, Copy)] pub struct TrictracState { - pub data: [i8; 36], // Représentation vectorielle de l'état du jeu + pub data: [f32; 36], // Représentation vectorielle de l'état du jeu } impl State for TrictracState { - type Data = [i8; 36]; + type Data = [f32; 36]; fn to_tensor(&self) -> Tensor { Tensor::from_floats(self.data, &B::Device::default()) @@ -28,8 +25,8 @@ impl State for TrictracState { impl TrictracState { /// Convertit un GameState en TrictracState pub fn from_game_state(game_state: &GameState) -> Self { - let state_vec = game_state.to_vec(); - let mut data = [0; 36]; + let state_vec = game_state.to_vec_float(); + let mut data = [0.0; 36]; // Copier les données en s'assurant qu'on ne dépasse pas la taille let copy_len = state_vec.len().min(36); @@ -42,16 +39,15 @@ impl TrictracState { /// Actions possibles dans Trictrac pour burn-rl #[derive(Debug, Clone, Copy, PartialEq)] pub struct TrictracAction { - // u32 as required by burn_rl::base::Action type pub index: u32, } impl Action for TrictracAction { fn random() -> Self { - use rand::{rng, Rng}; - let mut rng = rng(); + use rand::{thread_rng, Rng}; + let mut rng = thread_rng(); TrictracAction { - index: rng.random_range(0..Self::size() as u32), + index: rng.gen_range(0..Self::size() as u32), } } @@ -62,9 +58,7 @@ impl Action for TrictracAction { } fn size() -> usize { - // état avec le plus de choix : mouvement - // choix premier dé : 16 (15 pions + aucun pion), choix deuxième dé 16, x2 ordre dé - 64 + 1252 } } @@ -88,9 +82,7 @@ pub struct TrictracEnvironment { opponent_id: PlayerId, current_state: TrictracState, episode_reward: f32, - pub step_count: usize, - pub max_steps: usize, - pub pointrolls_count: usize, + step_count: usize, pub visualized: bool, } @@ -99,6 +91,8 @@ impl Environment for TrictracEnvironment { type ActionType = TrictracAction; type RewardType = f32; + const MAX_STEPS: usize = 700; // Limite max pour éviter les parties infinies + fn new(visualized: bool) -> Self { let mut game = GameState::new(false); @@ -109,7 +103,7 @@ impl Environment for TrictracEnvironment { let player2_id = 2; // Commencer la partie - let _ = game.consume(&GameEvent::BeginGame { goes_first: 1 }); + game.consume(&GameEvent::BeginGame { goes_first: 1 }); let current_state = TrictracState::from_game_state(&game); TrictracEnvironment { @@ -119,8 +113,6 @@ impl Environment for TrictracEnvironment { current_state, episode_reward: 0.0, step_count: 0, - max_steps: 2000, - pointrolls_count: 0, visualized, } } @@ -136,12 +128,11 @@ impl Environment for TrictracEnvironment { self.game.init_player("Opponent"); // Commencer la partie - let _ = self.game.consume(&GameEvent::BeginGame { goes_first: 1 }); + self.game.consume(&GameEvent::BeginGame { goes_first: 1 }); self.current_state = TrictracState::from_game_state(&self.game); self.episode_reward = 0.0; self.step_count = 0; - self.pointrolls_count = 0; Snapshot::new(self.current_state, 0.0, false) } @@ -150,52 +141,50 @@ impl Environment for TrictracEnvironment { self.step_count += 1; // Convertir l'action burn-rl vers une action Trictrac - // let trictrac_action = Self::convert_action(action); - let trictrac_action = self.convert_valid_action_index(action); + let trictrac_action = self.convert_action(action, &self.game); + let mut reward = 0.0; - let is_rollpoint: bool; + let mut terminated = false; // Exécuter l'action si c'est le tour de l'agent DQN if self.game.active_player_id == self.active_player_id { if let Some(action) = trictrac_action { - (reward, is_rollpoint) = self.execute_action(action); - // if reward != 0.0 { - // println!("info: self rew {reward}"); - // } - if is_rollpoint { - self.pointrolls_count += 1; + match self.execute_action(action) { + Ok(action_reward) => { + reward = action_reward; + } + Err(_) => { + // Action invalide, pénalité + reward = -1.0; + } } } else { // Action non convertible, pénalité - println!("info: action non convertible -> -1 {trictrac_action:?}"); - reward = -1.0; + reward = -0.5; } } // Faire jouer l'adversaire (stratégie simple) while self.game.active_player_id == self.opponent_id && self.game.stage != Stage::Ended { - // let op_rew = self.play_opponent_if_needed(); - // if op_rew != 0.0 { - // println!("info: op rew {op_rew}"); - // } - // reward += op_rew; reward += self.play_opponent_if_needed(); } // Vérifier si la partie est terminée - let done = self.game.stage == Stage::Ended || self.game.determine_winner().is_some(); + let done = self.game.stage == Stage::Ended + || self.game.determine_winner().is_some() + || self.step_count >= Self::MAX_STEPS; if done { + terminated = true; // Récompense finale basée sur le résultat if let Some(winner_id) = self.game.determine_winner() { if winner_id == self.active_player_id { - reward += 100.0; // Victoire + reward += 50.0; // Victoire } else { - reward -= 100.0; // Défaite + reward -= 25.0; // Défaite } } } - let terminated = done || self.step_count >= self.max_steps; // Mettre à jour l'état self.current_state = TrictracState::from_game_state(&self.game); @@ -213,81 +202,128 @@ impl Environment for TrictracEnvironment { } impl TrictracEnvironment { - const ERROR_REWARD: f32 = -1.12121; - const REWARD_RATIO: f32 = 1.0; - /// Convertit une action burn-rl vers une action Trictrac - pub fn convert_action(action: TrictracAction) -> Option { - training_common::TrictracAction::from_action_index(action.index.try_into().unwrap()) + fn convert_action( + &self, + action: TrictracAction, + game_state: &GameState, + ) -> Option { + dqn_common::TrictracAction::from_action_index(action.index.try_into().unwrap()) } /// Convertit l'index d'une action au sein des actions valides vers une action Trictrac fn convert_valid_action_index( &self, action: TrictracAction, - ) -> Option { - use training_common::get_valid_actions; + game_state: &GameState, + ) -> Option { + use dqn_common::get_valid_actions; // Obtenir les actions valides dans le contexte actuel - if let Ok(valid_actions) = get_valid_actions(&self.game) { - // Mapper l'index d'action sur une action valide - let action_index = (action.index as usize) % valid_actions.len(); - Some(valid_actions[action_index]) - } else { - None + let valid_actions = get_valid_actions(game_state); + + if valid_actions.is_empty() { + return None; } + + // Mapper l'index d'action sur une action valide + let action_index = (action.index as usize) % valid_actions.len(); + Some(valid_actions[action_index].clone()) } /// Exécute une action Trictrac dans le jeu - // fn execute_action( - // &mut self, - // action: training_common::TrictracAction, - // ) -> Result> { - fn execute_action(&mut self, action: training_common::TrictracAction) -> (f32, bool) { - use training_common::TrictracAction; + fn execute_action( + &mut self, + action: dqn_common::TrictracAction, + ) -> Result> { + use dqn_common::TrictracAction; let mut reward = 0.0; - let mut is_rollpoint = false; + + let event = match action { + TrictracAction::Roll => { + // Lancer les dés + reward += 0.1; + Some(GameEvent::Roll { + player_id: self.active_player_id, + }) + } + // TrictracAction::Mark => { + // // Marquer des points + // let points = self.game. + // reward += 0.1 * points as f32; + // Some(GameEvent::Mark { + // player_id: self.active_player_id, + // points, + // }) + // } + TrictracAction::Go => { + // Continuer après avoir gagné un trou + reward += 0.2; + Some(GameEvent::Go { + player_id: self.active_player_id, + }) + } + TrictracAction::Move { + dice_order, + from1, + from2, + } => { + // Effectuer un mouvement + let (dice1, dice2) = if dice_order { + (self.game.dice.values.0, self.game.dice.values.1) + } else { + (self.game.dice.values.1, self.game.dice.values.0) + }; + let mut to1 = from1 + dice1 as usize; + let mut to2 = from2 + dice2 as usize; + + // Gestion prise de coin par puissance + let opp_rest_field = 13; + if to1 == opp_rest_field && to2 == opp_rest_field { + to1 -= 1; + to2 -= 1; + } + + let checker_move1 = store::CheckerMove::new(from1, to1).unwrap_or_default(); + let checker_move2 = store::CheckerMove::new(from2, to2).unwrap_or_default(); + + reward += 0.2; + Some(GameEvent::Move { + player_id: self.active_player_id, + moves: (checker_move1, checker_move2), + }) + } + }; // Appliquer l'événement si valide - if let Some(event) = action.to_event(&self.game) { + if let Some(event) = event { if self.game.validate(&event) { - let _ = self.game.consume(&event); - // reward += REWARD_VALID_MOVE; + self.game.consume(&event); + // Simuler le résultat des dés après un Roll if matches!(action, TrictracAction::Roll) { - let mut rng = rng(); - let dice_values = (rng.random_range(1..=6), rng.random_range(1..=6)); + let mut rng = thread_rng(); + let dice_values = (rng.gen_range(1..=6), rng.gen_range(1..=6)); let dice_event = GameEvent::RollResult { player_id: self.active_player_id, - dice: trictrac_store::Dice { + dice: store::Dice { values: dice_values, }, }; if self.game.validate(&dice_event) { - let _ = self.game.consume(&dice_event); + self.game.consume(&dice_event); let (points, adv_points) = self.game.dice_points; - reward += REWARD_RATIO * (points as f32 - adv_points as f32); - if points > 0 { - is_rollpoint = true; - // println!("info: rolled for {reward}"); - } - // Récompense proportionnelle aux points + reward += 0.3 * (points - adv_points) as f32; // Récompense proportionnelle aux points } } } else { // Pénalité pour action invalide - // on annule les précédents reward - // et on indique une valeur reconnaissable pour statistiques - reward = ERROR_REWARD; - self.game.mark_points_for_bot_training(self.opponent_id, 1); + reward -= 2.0; } - } else { - reward = ERROR_REWARD; - self.game.mark_points_for_bot_training(self.opponent_id, 1); } - (reward, is_rollpoint) + Ok(reward) } /// Fait jouer l'adversaire avec une stratégie simple @@ -297,34 +333,33 @@ impl TrictracEnvironment { // Si c'est le tour de l'adversaire, jouer automatiquement if self.game.active_player_id == self.opponent_id && self.game.stage != Stage::Ended { // Utiliser la stratégie default pour l'adversaire + use crate::strategy::default::DefaultStrategy; use crate::BotStrategy; - let mut strategy = crate::strategy::random::RandomStrategy::default(); - strategy.set_player_id(self.opponent_id); + let mut default_strategy = DefaultStrategy::default(); + default_strategy.set_player_id(self.opponent_id); if let Some(color) = self.game.player_color_by_id(&self.opponent_id) { - strategy.set_color(color); + default_strategy.set_color(color); } - *strategy.get_mut_game() = self.game.clone(); + *default_strategy.get_mut_game() = self.game.clone(); // Exécuter l'action selon le turn_stage - let mut calculate_points = false; - let opponent_color = trictrac_store::Color::Black; let event = match self.game.turn_stage { TurnStage::RollDice => GameEvent::Roll { player_id: self.opponent_id, }, TurnStage::RollWaiting => { - let mut rng = rng(); - let dice_values = (rng.random_range(1..=6), rng.random_range(1..=6)); - calculate_points = true; + let mut rng = thread_rng(); + let dice_values = (rng.gen_range(1..=6), rng.gen_range(1..=6)); GameEvent::RollResult { player_id: self.opponent_id, - dice: trictrac_store::Dice { + dice: store::Dice { values: dice_values, }, } } TurnStage::MarkPoints => { + let opponent_color = store::Color::Black; let dice_roll_count = self .game .players @@ -333,12 +368,16 @@ impl TrictracEnvironment { .dice_roll_count; let points_rules = PointsRules::new(&opponent_color, &self.game.board, self.game.dice); + let (points, adv_points) = points_rules.get_points(dice_roll_count); + reward -= 0.3 * (points - adv_points) as f32; // Récompense proportionnelle aux points + GameEvent::Mark { player_id: self.opponent_id, - points: points_rules.get_points(dice_roll_count).0, + points, } } TurnStage::MarkAdvPoints => { + let opponent_color = store::Color::Black; let dice_roll_count = self .game .players @@ -362,33 +401,14 @@ impl TrictracEnvironment { } TurnStage::Move => GameEvent::Move { player_id: self.opponent_id, - moves: strategy.choose_move(), + moves: default_strategy.choose_move(), }, }; if self.game.validate(&event) { - let _ = self.game.consume(&event); - if calculate_points { - let dice_roll_count = self - .game - .players - .get(&self.opponent_id) - .unwrap() - .dice_roll_count; - let points_rules = - PointsRules::new(&opponent_color, &self.game.board, self.game.dice); - let (points, adv_points) = points_rules.get_points(dice_roll_count); - reward -= Self::REWARD_RATIO * (points - adv_points) as f32; - // Récompense proportionnelle aux points - } + self.game.consume(&event); } } reward } } - -impl AsMut for TrictracEnvironment { - fn as_mut(&mut self) -> &mut Self { - self - } -} diff --git a/bot/src/dqn/burnrl/main.rs b/bot/src/dqn/burnrl/main.rs new file mode 100644 index 0000000..7b4584c --- /dev/null +++ b/bot/src/dqn/burnrl/main.rs @@ -0,0 +1,68 @@ +use bot::dqn::burnrl::{dqn_model, environment, utils::demo_model}; +use burn::backend::{ndarray::NdArrayDevice, Autodiff, NdArray}; +use burn::module::Module; +use burn::record::{CompactRecorder, Recorder}; +use burn_rl::agent::DQN; +use burn_rl::base::{Action, Agent, ElemType, Environment, State}; + +type Backend = Autodiff>; +type Env = environment::TrictracEnvironment; + +fn main() { + // println!("> Entraînement"); + let conf = dqn_model::DqnConfig { + num_episodes: 40, + // memory_size: 8192, // must be set in dqn_model.rs with the MEMORY_SIZE constant + // max_steps: 700, // must be set in environment.rs with the MAX_STEPS constant + dense_size: 256, // neural network complexity + eps_start: 0.9, // epsilon initial value (0.9 => more exploration) + eps_end: 0.05, + eps_decay: 3000.0, + }; + let agent = dqn_model::run::(&conf, false); //true); + + let valid_agent = agent.valid(); + + println!("> Sauvegarde du modèle de validation"); + + let path = "models/burn_dqn_50".to_string(); + save_model(valid_agent.model().as_ref().unwrap(), &path); + + // println!("> Test avec le modèle entraîné"); + // demo_model::(valid_agent); + + println!("> Chargement du modèle pour test"); + let loaded_model = load_model(conf.dense_size, &path); + let loaded_agent = DQN::new(loaded_model); + + println!("> Test avec le modèle chargé"); + demo_model(loaded_agent); +} + +fn save_model(model: &dqn_model::Net>, path: &String) { + let recorder = CompactRecorder::new(); + let model_path = format!("{}_model.mpk", path); + println!("Modèle de validation sauvegardé : {}", model_path); + recorder + .record(model.clone().into_record(), model_path.into()) + .unwrap(); +} + +fn load_model(dense_size: usize, path: &String) -> dqn_model::Net> { + let model_path = format!("{}_model.mpk", path); + println!("Chargement du modèle depuis : {}", model_path); + + let device = NdArrayDevice::default(); + let recorder = CompactRecorder::new(); + + let record = recorder + .load(model_path.into(), &device) + .expect("Impossible de charger le modèle"); + + dqn_model::Net::new( + ::StateType::size(), + dense_size, + ::ActionType::size(), + ) + .load_record(record) +} diff --git a/bot/src/dqn/burnrl/mod.rs b/bot/src/dqn/burnrl/mod.rs new file mode 100644 index 0000000..f4380eb --- /dev/null +++ b/bot/src/dqn/burnrl/mod.rs @@ -0,0 +1,3 @@ +pub mod dqn_model; +pub mod environment; +pub mod utils; diff --git a/bot/src/dqn/burnrl/utils.rs b/bot/src/dqn/burnrl/utils.rs new file mode 100644 index 0000000..ba04cb6 --- /dev/null +++ b/bot/src/dqn/burnrl/utils.rs @@ -0,0 +1,83 @@ +use crate::dqn::burnrl::environment::{TrictracAction, TrictracEnvironment}; +use crate::dqn::dqn_common::get_valid_action_indices; +use burn::module::{Param, ParamId}; +use burn::nn::Linear; +use burn::tensor::backend::Backend; +use burn::tensor::cast::ToElement; +use burn::tensor::Tensor; +use burn_rl::agent::{DQNModel, DQN}; +use burn_rl::base::{ElemType, Environment, State}; + +pub fn demo_model>(agent: DQN) { + let mut env = TrictracEnvironment::new(true); + let mut done = false; + while !done { + // let action = match infer_action(&agent, &env, state) { + let action = match infer_action(&agent, &env) { + Some(value) => value, + None => break, + }; + // Execute action + let snapshot = env.step(action); + done = snapshot.done(); + } +} + +fn infer_action>( + agent: &DQN, + env: &TrictracEnvironment, +) -> Option { + let state = env.state(); + // Get q-values + let q_values = agent + .model() + .as_ref() + .unwrap() + .infer(state.to_tensor().unsqueeze()); + // Get valid actions + let valid_actions_indices = get_valid_action_indices(&env.game); + if valid_actions_indices.is_empty() { + return None; // No valid actions, end of episode + } + // Set non valid actions q-values to lowest + let mut masked_q_values = q_values.clone(); + let q_values_vec: Vec = q_values.into_data().into_vec().unwrap(); + for (index, q_value) in q_values_vec.iter().enumerate() { + if !valid_actions_indices.contains(&index) { + masked_q_values = masked_q_values.clone().mask_fill( + masked_q_values.clone().equal_elem(*q_value), + f32::NEG_INFINITY, + ); + } + } + // Get best action (highest q-value) + let action_index = masked_q_values.argmax(1).into_scalar().to_u32(); + let action = TrictracAction::from(action_index); + Some(action) +} + +fn soft_update_tensor( + this: &Param>, + that: &Param>, + tau: ElemType, +) -> Param> { + let that_weight = that.val(); + let this_weight = this.val(); + let new_weight = this_weight * (1.0 - tau) + that_weight * tau; + + Param::initialized(ParamId::new(), new_weight) +} + +pub fn soft_update_linear( + this: Linear, + that: &Linear, + tau: ElemType, +) -> Linear { + let weight = soft_update_tensor(&this.weight, &that.weight, tau); + let bias = match (&this.bias, &that.bias) { + (Some(this_bias), Some(that_bias)) => Some(soft_update_tensor(this_bias, that_bias, tau)), + _ => None, + }; + + Linear:: { weight, bias } +} diff --git a/bot/src/dqn/dqn_common.rs b/bot/src/dqn/dqn_common.rs new file mode 100644 index 0000000..3ea0738 --- /dev/null +++ b/bot/src/dqn/dqn_common.rs @@ -0,0 +1,406 @@ +use std::cmp::{max, min}; + +use serde::{Deserialize, Serialize}; +use store::{CheckerMove, Dice}; + +/// Types d'actions possibles dans le jeu +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum TrictracAction { + /// Lancer les dés + Roll, + /// Continuer après avoir gagné un trou + Go, + /// Effectuer un mouvement de pions + Move { + dice_order: bool, // true = utiliser dice[0] en premier, false = dice[1] en premier + from1: usize, // position de départ du premier pion (0-24) + from2: usize, // position de départ du deuxième pion (0-24) + }, + // Marquer les points : à activer si support des écoles + // Mark, +} + +impl TrictracAction { + /// Encode une action en index pour le réseau de neurones + pub fn to_action_index(&self) -> usize { + match self { + TrictracAction::Roll => 0, + TrictracAction::Go => 1, + TrictracAction::Move { + dice_order, + from1, + from2, + } => { + // Encoder les mouvements dans l'espace d'actions + // Indices 2+ pour les mouvements + // de 2 à 1251 (2 à 626 pour dé 1 en premier, 627 à 1251 pour dé 2 en premier) + let mut start = 2; + if !dice_order { + // 25 * 25 = 625 + start += 625; + } + start + from1 * 25 + from2 + } // TrictracAction::Mark => 1252, + } + } + + /// Décode un index d'action en TrictracAction + pub fn from_action_index(index: usize) -> Option { + match index { + 0 => Some(TrictracAction::Roll), + // 1252 => Some(TrictracAction::Mark), + 1 => Some(TrictracAction::Go), + i if i >= 3 => { + let move_code = i - 3; + let (dice_order, from1, from2) = Self::decode_move(move_code); + Some(TrictracAction::Move { + dice_order, + from1, + from2, + }) + } + _ => None, + } + } + + /// Décode un entier en paire de mouvements + fn decode_move(code: usize) -> (bool, usize, usize) { + let mut encoded = code; + let dice_order = code < 626; + if !dice_order { + encoded -= 625 + } + let from1 = encoded / 25; + let from2 = 1 + encoded % 25; + (dice_order, from1, from2) + } + + /// Retourne la taille de l'espace d'actions total + pub fn action_space_size() -> usize { + // 1 (Roll) + 1 (Go) + mouvements possibles + // Pour les mouvements : 2*25*25 = 1250 (choix du dé + position 0-24 pour chaque from) + // Mais on peut optimiser en limitant aux positions valides (1-24) + 2 + (2 * 25 * 25) // = 1252 + } + + // pub fn to_game_event(&self, player_id: PlayerId, dice: Dice) -> GameEvent { + // match action { + // TrictracAction::Roll => Some(GameEvent::Roll { player_id }), + // TrictracAction::Mark => Some(GameEvent::Mark { player_id, points }), + // TrictracAction::Go => Some(GameEvent::Go { player_id }), + // TrictracAction::Move { + // dice_order, + // from1, + // from2, + // } => { + // // Effectuer un mouvement + // let checker_move1 = store::CheckerMove::new(move1.0, move1.1).unwrap_or_default(); + // let checker_move2 = store::CheckerMove::new(move2.0, move2.1).unwrap_or_default(); + // + // Some(GameEvent::Move { + // player_id: self.agent_player_id, + // moves: (checker_move1, checker_move2), + // }) + // } + // }; + // } +} + +/// Configuration pour l'agent DQN +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DqnConfig { + pub state_size: usize, + pub hidden_size: usize, + pub num_actions: usize, + pub learning_rate: f64, + pub gamma: f64, + pub epsilon: f64, + pub epsilon_decay: f64, + pub epsilon_min: f64, + pub replay_buffer_size: usize, + pub batch_size: usize, +} + +impl Default for DqnConfig { + fn default() -> Self { + Self { + state_size: 36, + hidden_size: 512, // Augmenter la taille pour gérer l'espace d'actions élargi + num_actions: TrictracAction::action_space_size(), + learning_rate: 0.001, + gamma: 0.99, + epsilon: 0.1, + epsilon_decay: 0.995, + epsilon_min: 0.01, + replay_buffer_size: 10000, + batch_size: 32, + } + } +} + +/// Réseau de neurones DQN simplifié (matrice de poids basique) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SimpleNeuralNetwork { + pub weights1: Vec>, + pub biases1: Vec, + pub weights2: Vec>, + pub biases2: Vec, + pub weights3: Vec>, + pub biases3: Vec, +} + +impl SimpleNeuralNetwork { + pub fn new(input_size: usize, hidden_size: usize, output_size: usize) -> Self { + use rand::{thread_rng, Rng}; + let mut rng = thread_rng(); + + // Initialisation aléatoire des poids avec Xavier/Glorot + let scale1 = (2.0 / input_size as f32).sqrt(); + let weights1 = (0..hidden_size) + .map(|_| { + (0..input_size) + .map(|_| rng.gen_range(-scale1..scale1)) + .collect() + }) + .collect(); + let biases1 = vec![0.0; hidden_size]; + + let scale2 = (2.0 / hidden_size as f32).sqrt(); + let weights2 = (0..hidden_size) + .map(|_| { + (0..hidden_size) + .map(|_| rng.gen_range(-scale2..scale2)) + .collect() + }) + .collect(); + let biases2 = vec![0.0; hidden_size]; + + let scale3 = (2.0 / hidden_size as f32).sqrt(); + let weights3 = (0..output_size) + .map(|_| { + (0..hidden_size) + .map(|_| rng.gen_range(-scale3..scale3)) + .collect() + }) + .collect(); + let biases3 = vec![0.0; output_size]; + + Self { + weights1, + biases1, + weights2, + biases2, + weights3, + biases3, + } + } + + pub fn forward(&self, input: &[f32]) -> Vec { + // Première couche + let mut layer1: Vec = self.biases1.clone(); + for (i, neuron_weights) in self.weights1.iter().enumerate() { + for (j, &weight) in neuron_weights.iter().enumerate() { + if j < input.len() { + layer1[i] += input[j] * weight; + } + } + layer1[i] = layer1[i].max(0.0); // ReLU + } + + // Deuxième couche + let mut layer2: Vec = self.biases2.clone(); + for (i, neuron_weights) in self.weights2.iter().enumerate() { + for (j, &weight) in neuron_weights.iter().enumerate() { + if j < layer1.len() { + layer2[i] += layer1[j] * weight; + } + } + layer2[i] = layer2[i].max(0.0); // ReLU + } + + // Couche de sortie + let mut output: Vec = self.biases3.clone(); + for (i, neuron_weights) in self.weights3.iter().enumerate() { + for (j, &weight) in neuron_weights.iter().enumerate() { + if j < layer2.len() { + output[i] += layer2[j] * weight; + } + } + } + + output + } + + pub fn get_best_action(&self, input: &[f32]) -> usize { + let q_values = self.forward(input); + q_values + .iter() + .enumerate() + .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap()) + .map(|(index, _)| index) + .unwrap_or(0) + } + + pub fn save>( + &self, + path: P, + ) -> Result<(), Box> { + let data = serde_json::to_string_pretty(self)?; + std::fs::write(path, data)?; + Ok(()) + } + + pub fn load>(path: P) -> Result> { + let data = std::fs::read_to_string(path)?; + let network = serde_json::from_str(&data)?; + Ok(network) + } +} + +/// Obtient les actions valides pour l'état de jeu actuel +pub fn get_valid_actions(game_state: &crate::GameState) -> Vec { + use store::TurnStage; + + let mut valid_actions = Vec::new(); + + let active_player_id = game_state.active_player_id; + let player_color = game_state.player_color_by_id(&active_player_id); + + if let Some(color) = player_color { + match game_state.turn_stage { + TurnStage::RollDice | TurnStage::RollWaiting => { + valid_actions.push(TrictracAction::Roll); + } + TurnStage::MarkPoints | TurnStage::MarkAdvPoints => { + // valid_actions.push(TrictracAction::Mark); + } + TurnStage::HoldOrGoChoice => { + valid_actions.push(TrictracAction::Go); + + // Ajoute aussi les mouvements possibles + let rules = store::MoveRules::new(&color, &game_state.board, game_state.dice); + let possible_moves = rules.get_possible_moves_sequences(true, vec![]); + + // Modififier checker_moves_to_trictrac_action si on doit gérer Black + assert_eq!(color, store::Color::White); + for (move1, move2) in possible_moves { + valid_actions.push(checker_moves_to_trictrac_action( + &move1, + &move2, + &game_state.dice, + )); + } + } + TurnStage::Move => { + let rules = store::MoveRules::new(&color, &game_state.board, game_state.dice); + let possible_moves = rules.get_possible_moves_sequences(true, vec![]); + + // Modififier checker_moves_to_trictrac_action si on doit gérer Black + assert_eq!(color, store::Color::White); + for (move1, move2) in possible_moves { + valid_actions.push(checker_moves_to_trictrac_action( + &move1, + &move2, + &game_state.dice, + )); + } + } + } + } + + valid_actions +} + +// Valid only for White player +fn checker_moves_to_trictrac_action( + move1: &CheckerMove, + move2: &CheckerMove, + dice: &Dice, +) -> TrictracAction { + let to1 = move1.get_to(); + let to2 = move2.get_to(); + let from1 = move1.get_from(); + let from2 = move2.get_from(); + + let mut diff_move1 = if to1 > 0 { + // Mouvement sans sortie + to1 - from1 + } else { + // sortie, on utilise la valeur du dé + if to2 > 0 { + // sortie pour le mouvement 1 uniquement + let dice2 = to2 - from2; + if dice2 == dice.values.0 as usize { + dice.values.1 as usize + } else { + dice.values.0 as usize + } + } else { + // double sortie + if from1 < from2 { + max(dice.values.0, dice.values.1) as usize + } else { + min(dice.values.0, dice.values.1) as usize + } + } + }; + + // modification de diff_move1 si on est dans le cas d'un mouvement par puissance + let rest_field = 12; + if to1 == rest_field + && to2 == rest_field + && max(dice.values.0 as usize, dice.values.1 as usize) + min(from1, from2) != rest_field + { + // prise par puissance + diff_move1 += 1; + } + TrictracAction::Move { + dice_order: diff_move1 == dice.values.0 as usize, + from1: move1.get_from(), + from2: move2.get_from(), + } +} + +/// Retourne les indices des actions valides +pub fn get_valid_action_indices(game_state: &crate::GameState) -> Vec { + get_valid_actions(game_state) + .into_iter() + .map(|action| action.to_action_index()) + .collect() +} + +/// Sélectionne une action valide aléatoire +pub fn sample_valid_action(game_state: &crate::GameState) -> Option { + use rand::{seq::SliceRandom, thread_rng}; + + let valid_actions = get_valid_actions(game_state); + let mut rng = thread_rng(); + valid_actions.choose(&mut rng).cloned() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn to_action_index() { + let action = TrictracAction::Move { + dice_order: true, + from1: 3, + from2: 4, + }; + let index = action.to_action_index(); + assert_eq!(Some(action), TrictracAction::from_action_index(index)); + assert_eq!(81, index); + } + + #[test] + fn from_action_index() { + let action = TrictracAction::Move { + dice_order: true, + from1: 3, + from2: 4, + }; + assert_eq!(Some(action), TrictracAction::from_action_index(81)); + } +} diff --git a/bot/src/dqn/mod.rs b/bot/src/dqn/mod.rs new file mode 100644 index 0000000..6eafa27 --- /dev/null +++ b/bot/src/dqn/mod.rs @@ -0,0 +1,3 @@ +pub mod dqn_common; +pub mod simple; +pub mod burnrl; \ No newline at end of file diff --git a/bot/src/dqn/simple/dqn_trainer.rs b/bot/src/dqn/simple/dqn_trainer.rs new file mode 100644 index 0000000..dedf382 --- /dev/null +++ b/bot/src/dqn/simple/dqn_trainer.rs @@ -0,0 +1,489 @@ +use crate::{CheckerMove, Color, GameState, PlayerId}; +use rand::prelude::SliceRandom; +use rand::{thread_rng, Rng}; +use serde::{Deserialize, Serialize}; +use std::collections::VecDeque; +use store::{GameEvent, MoveRules, PointsRules, Stage, TurnStage}; + +use crate::dqn::dqn_common::{get_valid_actions, DqnConfig, SimpleNeuralNetwork, TrictracAction}; + +/// Expérience pour le buffer de replay +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Experience { + pub state: Vec, + pub action: TrictracAction, + pub reward: f32, + pub next_state: Vec, + pub done: bool, +} + +/// Buffer de replay pour stocker les expériences +#[derive(Debug)] +pub struct ReplayBuffer { + buffer: VecDeque, + capacity: usize, +} + +impl ReplayBuffer { + pub fn new(capacity: usize) -> Self { + Self { + buffer: VecDeque::with_capacity(capacity), + capacity, + } + } + + pub fn push(&mut self, experience: Experience) { + if self.buffer.len() >= self.capacity { + self.buffer.pop_front(); + } + self.buffer.push_back(experience); + } + + pub fn sample(&self, batch_size: usize) -> Vec { + let mut rng = thread_rng(); + let len = self.buffer.len(); + if len < batch_size { + return self.buffer.iter().cloned().collect(); + } + + let mut batch = Vec::with_capacity(batch_size); + for _ in 0..batch_size { + let idx = rng.gen_range(0..len); + batch.push(self.buffer[idx].clone()); + } + batch + } + + pub fn len(&self) -> usize { + self.buffer.len() + } +} + +/// Agent DQN pour l'apprentissage par renforcement +#[derive(Debug)] +pub struct DqnAgent { + config: DqnConfig, + model: SimpleNeuralNetwork, + target_model: SimpleNeuralNetwork, + replay_buffer: ReplayBuffer, + epsilon: f64, + step_count: usize, +} + +impl DqnAgent { + pub fn new(config: DqnConfig) -> Self { + let model = + SimpleNeuralNetwork::new(config.state_size, config.hidden_size, config.num_actions); + let target_model = model.clone(); + let replay_buffer = ReplayBuffer::new(config.replay_buffer_size); + let epsilon = config.epsilon; + + Self { + config, + model, + target_model, + replay_buffer, + epsilon, + step_count: 0, + } + } + + pub fn select_action(&mut self, game_state: &GameState, state: &[f32]) -> TrictracAction { + let valid_actions = get_valid_actions(game_state); + + if valid_actions.is_empty() { + // Fallback si aucune action valide + return TrictracAction::Roll; + } + + let mut rng = thread_rng(); + if rng.gen::() < self.epsilon { + // Exploration : action valide aléatoire + valid_actions + .choose(&mut rng) + .cloned() + .unwrap_or(TrictracAction::Roll) + } else { + // Exploitation : meilleure action valide selon le modèle + let q_values = self.model.forward(state); + + let mut best_action = &valid_actions[0]; + let mut best_q_value = f32::NEG_INFINITY; + + for action in &valid_actions { + let action_index = action.to_action_index(); + if action_index < q_values.len() { + let q_value = q_values[action_index]; + if q_value > best_q_value { + best_q_value = q_value; + best_action = action; + } + } + } + + best_action.clone() + } + } + + pub fn store_experience(&mut self, experience: Experience) { + self.replay_buffer.push(experience); + } + + pub fn train(&mut self) { + if self.replay_buffer.len() < self.config.batch_size { + return; + } + + // Pour l'instant, on simule l'entraînement en mettant à jour epsilon + // Dans une implémentation complète, ici on ferait la backpropagation + self.epsilon = (self.epsilon * self.config.epsilon_decay).max(self.config.epsilon_min); + self.step_count += 1; + + // Mise à jour du target model tous les 100 steps + if self.step_count % 100 == 0 { + self.target_model = self.model.clone(); + } + } + + pub fn save_model>( + &self, + path: P, + ) -> Result<(), Box> { + self.model.save(path) + } + + pub fn get_epsilon(&self) -> f64 { + self.epsilon + } + + pub fn get_step_count(&self) -> usize { + self.step_count + } +} + +/// Environnement Trictrac pour l'entraînement +#[derive(Debug)] +pub struct TrictracEnv { + pub game_state: GameState, + pub agent_player_id: PlayerId, + pub opponent_player_id: PlayerId, + pub agent_color: Color, + pub max_steps: usize, + pub current_step: usize, +} + +impl Default for TrictracEnv { + fn default() -> Self { + let mut game_state = GameState::new(false); + game_state.init_player("agent"); + game_state.init_player("opponent"); + + Self { + game_state, + agent_player_id: 1, + opponent_player_id: 2, + agent_color: Color::White, + max_steps: 1000, + current_step: 0, + } + } +} + +impl TrictracEnv { + pub fn reset(&mut self) -> Vec { + self.game_state = GameState::new(false); + self.game_state.init_player("agent"); + self.game_state.init_player("opponent"); + + // Commencer la partie + self.game_state.consume(&GameEvent::BeginGame { + goes_first: self.agent_player_id, + }); + + self.current_step = 0; + self.game_state.to_vec_float() + } + + pub fn step(&mut self, action: TrictracAction) -> (Vec, f32, bool) { + let mut reward = 0.0; + + // Appliquer l'action de l'agent + if self.game_state.active_player_id == self.agent_player_id { + reward += self.apply_agent_action(action); + } + + // Faire jouer l'adversaire (stratégie simple) + while self.game_state.active_player_id == self.opponent_player_id + && self.game_state.stage != Stage::Ended + { + reward += self.play_opponent_turn(); + } + + // Vérifier si la partie est terminée + let done = self.game_state.stage == Stage::Ended + || self.game_state.determine_winner().is_some() + || self.current_step >= self.max_steps; + + // Récompense finale si la partie est terminée + if done { + if let Some(winner) = self.game_state.determine_winner() { + if winner == self.agent_player_id { + reward += 100.0; // Bonus pour gagner + } else { + reward -= 50.0; // Pénalité pour perdre + } + } + } + + self.current_step += 1; + let next_state = self.game_state.to_vec_float(); + (next_state, reward, done) + } + + fn apply_agent_action(&mut self, action: TrictracAction) -> f32 { + let mut reward = 0.0; + + let event = match action { + TrictracAction::Roll => { + // Lancer les dés + reward += 0.1; + Some(GameEvent::Roll { + player_id: self.agent_player_id, + }) + } + // TrictracAction::Mark => { + // // Marquer des points + // let points = self.game_state. + // reward += 0.1 * points as f32; + // Some(GameEvent::Mark { + // player_id: self.agent_player_id, + // points, + // }) + // } + TrictracAction::Go => { + // Continuer après avoir gagné un trou + reward += 0.2; + Some(GameEvent::Go { + player_id: self.agent_player_id, + }) + } + TrictracAction::Move { + dice_order, + from1, + from2, + } => { + // Effectuer un mouvement + let (dice1, dice2) = if dice_order { + (self.game_state.dice.values.0, self.game_state.dice.values.1) + } else { + (self.game_state.dice.values.1, self.game_state.dice.values.0) + }; + let mut to1 = from1 + dice1 as usize; + let mut to2 = from2 + dice2 as usize; + + // Gestion prise de coin par puissance + let opp_rest_field = 13; + if to1 == opp_rest_field && to2 == opp_rest_field { + to1 -= 1; + to2 -= 1; + } + + let checker_move1 = store::CheckerMove::new(from1, to1).unwrap_or_default(); + let checker_move2 = store::CheckerMove::new(from2, to2).unwrap_or_default(); + + reward += 0.2; + Some(GameEvent::Move { + player_id: self.agent_player_id, + moves: (checker_move1, checker_move2), + }) + } + }; + + // Appliquer l'événement si valide + if let Some(event) = event { + if self.game_state.validate(&event) { + self.game_state.consume(&event); + + // Simuler le résultat des dés après un Roll + if matches!(action, TrictracAction::Roll) { + let mut rng = thread_rng(); + let dice_values = (rng.gen_range(1..=6), rng.gen_range(1..=6)); + let dice_event = GameEvent::RollResult { + player_id: self.agent_player_id, + dice: store::Dice { + values: dice_values, + }, + }; + if self.game_state.validate(&dice_event) { + self.game_state.consume(&dice_event); + } + } + } else { + // Pénalité pour action invalide + reward -= 2.0; + } + } + + reward + } + + // TODO : use default bot strategy + fn play_opponent_turn(&mut self) -> f32 { + let mut reward = 0.0; + let event = match self.game_state.turn_stage { + TurnStage::RollDice => GameEvent::Roll { + player_id: self.opponent_player_id, + }, + TurnStage::RollWaiting => { + let mut rng = thread_rng(); + let dice_values = (rng.gen_range(1..=6), rng.gen_range(1..=6)); + GameEvent::RollResult { + player_id: self.opponent_player_id, + dice: store::Dice { + values: dice_values, + }, + } + } + TurnStage::MarkAdvPoints | TurnStage::MarkPoints => { + let opponent_color = self.agent_color.opponent_color(); + let dice_roll_count = self + .game_state + .players + .get(&self.opponent_player_id) + .unwrap() + .dice_roll_count; + let points_rules = PointsRules::new( + &opponent_color, + &self.game_state.board, + self.game_state.dice, + ); + let (points, adv_points) = points_rules.get_points(dice_roll_count); + reward -= 0.3 * (points - adv_points) as f32; // Récompense proportionnelle aux points + + GameEvent::Mark { + player_id: self.opponent_player_id, + points, + } + } + TurnStage::Move => { + let opponent_color = self.agent_color.opponent_color(); + let rules = MoveRules::new( + &opponent_color, + &self.game_state.board, + self.game_state.dice, + ); + let possible_moves = rules.get_possible_moves_sequences(true, vec![]); + + // Stratégie simple : choix aléatoire + let mut rng = thread_rng(); + let choosen_move = *possible_moves + .choose(&mut rng) + .unwrap_or(&(CheckerMove::default(), CheckerMove::default())); + + GameEvent::Move { + player_id: self.opponent_player_id, + moves: if opponent_color == Color::White { + choosen_move + } else { + (choosen_move.0.mirror(), choosen_move.1.mirror()) + }, + } + } + TurnStage::HoldOrGoChoice => { + // Stratégie simple : toujours continuer + GameEvent::Go { + player_id: self.opponent_player_id, + } + } + }; + if self.game_state.validate(&event) { + self.game_state.consume(&event); + } + reward + } +} + +/// Entraîneur pour le modèle DQN +pub struct DqnTrainer { + agent: DqnAgent, + env: TrictracEnv, +} + +impl DqnTrainer { + pub fn new(config: DqnConfig) -> Self { + Self { + agent: DqnAgent::new(config), + env: TrictracEnv::default(), + } + } + + pub fn train_episode(&mut self) -> f32 { + let mut total_reward = 0.0; + let mut state = self.env.reset(); + // let mut step_count = 0; + + loop { + // step_count += 1; + let action = self.agent.select_action(&self.env.game_state, &state); + let (next_state, reward, done) = self.env.step(action.clone()); + total_reward += reward; + + let experience = Experience { + state: state.clone(), + action, + reward, + next_state: next_state.clone(), + done, + }; + self.agent.store_experience(experience); + self.agent.train(); + + if done { + break; + } + // if step_count % 100 == 0 { + // println!("{:?}", next_state); + // } + state = next_state; + } + + total_reward + } + + pub fn train( + &mut self, + episodes: usize, + save_every: usize, + model_path: &str, + ) -> Result<(), Box> { + println!("Démarrage de l'entraînement DQN pour {} épisodes", episodes); + + for episode in 1..=episodes { + let reward = self.train_episode(); + + if episode % 100 == 0 { + println!( + "Épisode {}/{}: Récompense = {:.2}, Epsilon = {:.3}, Steps = {}", + episode, + episodes, + reward, + self.agent.get_epsilon(), + self.agent.get_step_count() + ); + } + + if episode % save_every == 0 { + let save_path = format!("{}_episode_{}.json", model_path, episode); + self.agent.save_model(&save_path)?; + println!("Modèle sauvegardé : {}", save_path); + } + } + + // Sauvegarder le modèle final + let final_path = format!("{}_final.json", model_path); + self.agent.save_model(&final_path)?; + println!("Modèle final sauvegardé : {}", final_path); + + Ok(()) + } +} diff --git a/bot/src/dqn/simple/mod.rs b/bot/src/dqn/simple/mod.rs new file mode 100644 index 0000000..114bd10 --- /dev/null +++ b/bot/src/dqn/simple/mod.rs @@ -0,0 +1 @@ +pub mod dqn_trainer; diff --git a/bot/src/lib.rs b/bot/src/lib.rs index a9b04d5..65424fc 100644 --- a/bot/src/lib.rs +++ b/bot/src/lib.rs @@ -1,16 +1,11 @@ -pub mod burnrl; +pub mod dqn; pub mod strategy; -pub mod trictrac_board; -use log::debug; +use store::{CheckerMove, Color, GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage}; pub use strategy::default::DefaultStrategy; -pub use strategy::dqnburn::DqnBurnStrategy; +pub use strategy::dqn::DqnStrategy; pub use strategy::erroneous_moves::ErroneousStrategy; -pub use strategy::random::RandomStrategy; pub use strategy::stable_baselines3::StableBaselines3Strategy; -use trictrac_store::{ - CheckerMove, Color, GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage, -}; pub trait BotStrategy: std::fmt::Debug { fn get_game(&self) -> &GameState; @@ -31,7 +26,7 @@ pub trait BotStrategy: std::fmt::Debug { pub struct Bot { pub player_id: PlayerId, strategy: Box, - color: Color, + // color: Color, // schools_enabled: bool, } @@ -39,9 +34,9 @@ impl Default for Bot { fn default() -> Self { let strategy = DefaultStrategy::default(); Self { - player_id: 1, + player_id: 2, strategy: Box::new(strategy), - color: Color::White, + // color: Color::Black, // schools_enabled: false, } } @@ -57,86 +52,57 @@ impl Bot { Color::White => 1, Color::Black => 2, }; - // strategy.set_player_id(player_id); - // strategy.set_color(color); + strategy.set_player_id(player_id); + strategy.set_color(color); Self { player_id, strategy, - color, + // color, // schools_enabled: false, } } pub fn handle_event(&mut self, event: &GameEvent) -> Option { - debug!(">>>> {:?} BOT handle", self.color); let game = self.strategy.get_mut_game(); - let internal_event = if self.color == Color::Black { - &event.get_mirror(false) - } else { - event - }; - - let init_player_points = game.who_plays().map(|p| (p.points, p.holes)); - let turn_stage = game.turn_stage; - let _ = game.consume(internal_event); + game.consume(event); if game.stage == Stage::Ended { - debug!("<<<< end {:?} BOT handle", self.color); return None; } - let active_player_id = if self.color == Color::Black { - if game.active_player_id == 1 { - 2 - } else { - 1 - } - } else { - game.active_player_id - }; - if active_player_id == self.player_id { - let player_points = game.who_plays().map(|p| (p.points, p.holes)); - if self.color == Color::Black { - debug!( " input (internal) evt : {internal_event:?}, points : {init_player_points:?}, stage : {turn_stage:?}"); - } - let internal_event = match game.turn_stage { + if game.active_player_id == self.player_id { + return match game.turn_stage { TurnStage::MarkAdvPoints => Some(GameEvent::Mark { - player_id: 1, + player_id: self.player_id, points: self.strategy.calculate_adv_points(), }), - TurnStage::RollDice => Some(GameEvent::Roll { player_id: 1 }), + TurnStage::RollDice => Some(GameEvent::Roll { + player_id: self.player_id, + }), TurnStage::MarkPoints => Some(GameEvent::Mark { - player_id: 1, + player_id: self.player_id, points: self.strategy.calculate_points(), }), TurnStage::Move => Some(GameEvent::Move { - player_id: 1, + player_id: self.player_id, moves: self.strategy.choose_move(), }), TurnStage::HoldOrGoChoice => { if self.strategy.choose_go() { - Some(GameEvent::Go { player_id: 1 }) + Some(GameEvent::Go { + player_id: self.player_id, + }) } else { Some(GameEvent::Move { - player_id: 1, + player_id: self.player_id, moves: self.strategy.choose_move(), }) } } _ => None, }; - return if self.color == Color::Black { - debug!(" bot (internal) evt : {internal_event:?} ; points : {player_points:?}"); - debug!("<<<< end {:?} BOT handle", self.color); - internal_event.map(|evt| evt.get_mirror(false)) - } else { - debug!("<<<< end {:?} BOT handle", self.color); - internal_event - }; } - debug!("<<<< end {:?} BOT handle", self.color); None } - // Only used in tests below pub fn get_state(&self) -> &GameState { self.strategy.get_game() } @@ -145,7 +111,7 @@ impl Bot { #[cfg(test)] mod tests { use super::*; - use trictrac_store::{Dice, Stage}; + use store::{Dice, Stage}; #[test] fn test_new() { @@ -155,31 +121,17 @@ mod tests { } #[test] - fn test_handle_event() { + fn test_consume() { let mut bot = Bot::new(Box::new(DefaultStrategy::default()), Color::Black); // let mut bot = Bot::new(Box::new(DefaultStrategy::default()), Color::Black, false); let mut event = bot.handle_event(&GameEvent::BeginGame { goes_first: 2 }); assert_eq!(event, Some(GameEvent::Roll { player_id: 2 })); - assert_eq!(bot.get_state().active_player_id, 1); // bot internal active_player_id for black - event = bot.handle_event(&GameEvent::RollResult { - player_id: 2, - dice: Dice { values: (2, 3) }, - }); - assert_eq!( - event, - Some(GameEvent::Move { - player_id: 2, - moves: ( - CheckerMove::new(24, 21).unwrap(), - CheckerMove::new(24, 22).unwrap() - ) - }) - ); + assert_eq!(bot.get_state().active_player_id, 2); event = bot.handle_event(&GameEvent::BeginGame { goes_first: 1 }); assert_eq!(event, None); - assert_eq!(bot.get_state().active_player_id, 2); //internal active_player_id + assert_eq!(bot.get_state().active_player_id, 1); bot.handle_event(&GameEvent::RollResult { player_id: 1, dice: Dice { values: (2, 3) }, diff --git a/bot/src/strategy/default.rs b/bot/src/strategy/default.rs index f8b191d..e01f406 100644 --- a/bot/src/strategy/default.rs +++ b/bot/src/strategy/default.rs @@ -1,5 +1,5 @@ use crate::{BotStrategy, CheckerMove, Color, GameState, PlayerId}; -use trictrac_store::MoveRules; +use store::MoveRules; #[derive(Debug)] pub struct DefaultStrategy { @@ -13,8 +13,8 @@ impl Default for DefaultStrategy { let game = GameState::default(); Self { game, - player_id: 1, - color: Color::White, + player_id: 2, + color: Color::Black, } } } diff --git a/bot/src/strategy/dqn.rs b/bot/src/strategy/dqn.rs new file mode 100644 index 0000000..af08341 --- /dev/null +++ b/bot/src/strategy/dqn.rs @@ -0,0 +1,175 @@ +use crate::{BotStrategy, CheckerMove, Color, GameState, PlayerId}; +use std::path::Path; +use store::MoveRules; + +use crate::dqn::dqn_common::{ + get_valid_actions, sample_valid_action, SimpleNeuralNetwork, TrictracAction, +}; + +/// Stratégie DQN pour le bot - ne fait que charger et utiliser un modèle pré-entraîné +#[derive(Debug)] +pub struct DqnStrategy { + pub game: GameState, + pub player_id: PlayerId, + pub color: Color, + pub model: Option, +} + +impl Default for DqnStrategy { + fn default() -> Self { + Self { + game: GameState::default(), + player_id: 2, + color: Color::Black, + model: None, + } + } +} + +impl DqnStrategy { + pub fn new() -> Self { + Self::default() + } + + pub fn new_with_model>(model_path: P) -> Self { + let mut strategy = Self::new(); + if let Ok(model) = SimpleNeuralNetwork::load(model_path) { + strategy.model = Some(model); + } + strategy + } + + /// Utilise le modèle DQN pour choisir une action valide + fn get_dqn_action(&self) -> Option { + if let Some(ref model) = self.model { + let state = self.game.to_vec_float(); + let valid_actions = get_valid_actions(&self.game); + + if valid_actions.is_empty() { + return None; + } + + // Obtenir les Q-values pour toutes les actions + let q_values = model.forward(&state); + + // Trouver la meilleure action valide + let mut best_action = &valid_actions[0]; + let mut best_q_value = f32::NEG_INFINITY; + + for action in &valid_actions { + let action_index = action.to_action_index(); + if action_index < q_values.len() { + let q_value = q_values[action_index]; + if q_value > best_q_value { + best_q_value = q_value; + best_action = action; + } + } + } + + Some(best_action.clone()) + } else { + // Fallback : action aléatoire valide + sample_valid_action(&self.game) + } + } +} + +impl BotStrategy for DqnStrategy { + fn get_game(&self) -> &GameState { + &self.game + } + + fn get_mut_game(&mut self) -> &mut GameState { + &mut self.game + } + + fn set_color(&mut self, color: Color) { + self.color = color; + } + + fn set_player_id(&mut self, player_id: PlayerId) { + self.player_id = player_id; + } + + fn calculate_points(&self) -> u8 { + self.game.dice_points.0 + } + + fn calculate_adv_points(&self) -> u8 { + self.game.dice_points.1 + } + + fn choose_go(&self) -> bool { + // Utiliser le DQN pour décider si on continue + if let Some(action) = self.get_dqn_action() { + matches!(action, TrictracAction::Go) + } else { + // Fallback : toujours continuer + true + } + } + + fn choose_move(&self) -> (CheckerMove, CheckerMove) { + // Utiliser le DQN pour choisir le mouvement + if let Some(action) = self.get_dqn_action() { + if let TrictracAction::Move { + dice_order, + from1, + from2, + } = action + { + let dicevals = self.game.dice.values; + let (mut dice1, mut dice2) = if dice_order { + (dicevals.0, dicevals.1) + } else { + (dicevals.1, dicevals.0) + }; + + if from1 == 0 { + // empty move + dice1 = 0; + } + let mut to1 = from1 + dice1 as usize; + if 24 < to1 { + // sortie + to1 = 0; + } + if from2 == 0 { + // empty move + dice2 = 0; + } + let mut to2 = from2 + dice2 as usize; + if 24 < to2 { + // sortie + to2 = 0; + } + + let checker_move1 = CheckerMove::new(from1, to1).unwrap_or_default(); + let checker_move2 = CheckerMove::new(from2, to2).unwrap_or_default(); + + let chosen_move = if self.color == Color::White { + (checker_move1, checker_move2) + } else { + (checker_move1.mirror(), checker_move2.mirror()) + }; + + return chosen_move; + } + } + + // Fallback : utiliser la stratégie par défaut + let rules = MoveRules::new(&self.color, &self.game.board, self.game.dice); + let possible_moves = rules.get_possible_moves_sequences(true, vec![]); + + let chosen_move = *possible_moves + .first() + .unwrap_or(&(CheckerMove::default(), CheckerMove::default())); + + if self.color == Color::White { + chosen_move + } else { + (chosen_move.0.mirror(), chosen_move.1.mirror()) + } + } +} diff --git a/bot/src/strategy/dqnburn.rs b/bot/src/strategy/dqnburn.rs deleted file mode 100644 index 37f9b7f..0000000 --- a/bot/src/strategy/dqnburn.rs +++ /dev/null @@ -1,224 +0,0 @@ -use burn::backend::NdArray; -use burn::tensor::cast::ToElement; -use burn_rl::base::{ElemType, Model, State}; - -use crate::{BotStrategy, CheckerMove, Color, GameState, PlayerId}; -use log::info; -use trictrac_store::MoveRules; - -use crate::burnrl::algos::dqn; -use crate::burnrl::environment; -use trictrac_store::training_common::{ - get_valid_action_indices, sample_valid_action, TrictracAction, -}; - -type DqnBurnNetwork = dqn::Net>; - -/// Stratégie DQN pour le bot - ne fait que charger et utiliser un modèle pré-entraîné -#[derive(Debug)] -pub struct DqnBurnStrategy { - pub game: GameState, - pub player_id: PlayerId, - pub color: Color, - pub model: Option, -} - -impl Default for DqnBurnStrategy { - fn default() -> Self { - Self { - game: GameState::default(), - player_id: 1, - color: Color::White, - model: None, - } - } -} - -impl DqnBurnStrategy { - pub fn new() -> Self { - Self::default() - } - - pub fn new_with_model(model_path: &String) -> Self { - info!("Loading model {model_path:?}"); - let mut strategy = Self::new(); - strategy.model = dqn::load_model(256, model_path); - strategy - } - - /// Utilise le modèle DQN pour choisir une action valide - fn get_dqn_action(&self) -> Option { - if let Some(ref model) = self.model { - let state = environment::TrictracState::from_game_state(&self.game); - if let Ok(valid_actions_indices) = get_valid_action_indices(&self.game) { - if valid_actions_indices.is_empty() { - return None; // No valid actions, end of episode - } - - // Obtenir les Q-values pour toutes les actions - let q_values = model.infer(state.to_tensor().unsqueeze()); - - // Set non valid actions q-values to lowest - let mut masked_q_values = q_values.clone(); - let q_values_vec: Vec = q_values.into_data().into_vec().unwrap(); - for (index, q_value) in q_values_vec.iter().enumerate() { - if !valid_actions_indices.contains(&index) { - masked_q_values = masked_q_values.clone().mask_fill( - masked_q_values.clone().equal_elem(*q_value), - f32::NEG_INFINITY, - ); - } - } - // Get best action (highest q-value) - let action_index = masked_q_values.argmax(1).into_scalar().to_u32(); - return environment::TrictracEnvironment::convert_action( - environment::TrictracAction::from(action_index), - ); - } - return None; - } else { - // Fallback : action aléatoire valide - sample_valid_action(&self.game) - } - } -} - -impl BotStrategy for DqnBurnStrategy { - fn get_game(&self) -> &GameState { - &self.game - } - - fn get_mut_game(&mut self) -> &mut GameState { - &mut self.game - } - - fn set_color(&mut self, color: Color) { - self.color = color; - } - - fn set_player_id(&mut self, player_id: PlayerId) { - self.player_id = player_id; - } - - fn calculate_points(&self) -> u8 { - self.game.dice_points.0 - } - - fn calculate_adv_points(&self) -> u8 { - self.game.dice_points.1 - } - - fn choose_go(&self) -> bool { - // Utiliser le DQN pour décider si on continue - if let Some(action) = self.get_dqn_action() { - matches!(action, TrictracAction::Go) - } else { - // Fallback : toujours continuer - true - } - } - - fn choose_move(&self) -> (CheckerMove, CheckerMove) { - // Utiliser le DQN pour choisir le mouvement - if let Some(TrictracAction::Move { - dice_order, - checker1, - checker2, - }) = self.get_dqn_action() - { - let dicevals = self.game.dice.values; - let (mut dice1, mut dice2) = if dice_order { - (dicevals.0, dicevals.1) - } else { - (dicevals.1, dicevals.0) - }; - - assert_eq!(self.color, Color::White); - let from1 = self - .game - .board - .get_checker_field(&self.color, checker1 as u8) - .unwrap_or(0); - - if from1 == 0 { - // empty move - dice1 = 0; - } - let mut to1 = from1; - if self.color == Color::White { - to1 += dice1 as usize; - if 24 < to1 { - // sortie - to1 = 0; - } - } else { - let fto1 = to1 as i16 - dice1 as i16; - to1 = if fto1 < 0 { 0 } else { fto1 as usize }; - } - - let checker_move1 = trictrac_store::CheckerMove::new(from1, to1).unwrap_or_default(); - - let mut tmp_board = self.game.board.clone(); - let move_res = tmp_board.move_checker(&self.color, checker_move1); - if move_res.is_err() { - panic!("could not move {move_res:?}"); - } - let from2 = tmp_board - .get_checker_field(&self.color, checker2 as u8) - .unwrap_or(0); - if from2 == 0 { - // empty move - dice2 = 0; - } - let mut to2 = from2; - if self.color == Color::White { - to2 += dice2 as usize; - if 24 < to2 { - // sortie - to2 = 0; - } - } else { - let fto2 = to2 as i16 - dice2 as i16; - to2 = if fto2 < 0 { 0 } else { fto2 as usize }; - } - - // Gestion prise de coin par puissance - let opp_rest_field = if self.color == Color::White { 13 } else { 12 }; - if to1 == opp_rest_field && to2 == opp_rest_field { - if self.color == Color::White { - to1 -= 1; - to2 -= 1; - } else { - to1 += 1; - to2 += 1; - } - } - - let checker_move1 = CheckerMove::new(from1, to1).unwrap_or_default(); - let checker_move2 = CheckerMove::new(from2, to2).unwrap_or_default(); - - let chosen_move = if self.color == Color::White { - (checker_move1, checker_move2) - } else { - // XXX : really ? - (checker_move1.mirror(), checker_move2.mirror()) - }; - - return chosen_move; - } - - // Fallback : utiliser la stratégie par défaut - let rules = MoveRules::new(&self.color, &self.game.board, self.game.dice); - let possible_moves = rules.get_possible_moves_sequences(true, vec![]); - - let chosen_move = *possible_moves - .first() - .unwrap_or(&(CheckerMove::default(), CheckerMove::default())); - - if self.color == Color::White { - chosen_move - } else { - (chosen_move.0.mirror(), chosen_move.1.mirror()) - } - } -} diff --git a/bot/src/strategy/mod.rs b/bot/src/strategy/mod.rs index 00293cb..3812188 100644 --- a/bot/src/strategy/mod.rs +++ b/bot/src/strategy/mod.rs @@ -1,6 +1,5 @@ pub mod client; pub mod default; -pub mod dqnburn; +pub mod dqn; pub mod erroneous_moves; -pub mod random; pub mod stable_baselines3; diff --git a/bot/src/strategy/random.rs b/bot/src/strategy/random.rs deleted file mode 100644 index 08d851d..0000000 --- a/bot/src/strategy/random.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::{BotStrategy, CheckerMove, Color, GameState, PlayerId}; -use rand::{prelude::IndexedRandom, rng}; -use trictrac_store::MoveRules; - -#[derive(Debug)] -pub struct RandomStrategy { - pub game: GameState, - pub player_id: PlayerId, - pub color: Color, -} - -impl Default for RandomStrategy { - fn default() -> Self { - let game = GameState::default(); - Self { - game, - player_id: 1, - color: Color::White, - } - } -} - -impl BotStrategy for RandomStrategy { - fn get_game(&self) -> &GameState { - &self.game - } - fn get_mut_game(&mut self) -> &mut GameState { - &mut self.game - } - - fn set_color(&mut self, color: Color) { - self.color = color; - } - - fn set_player_id(&mut self, player_id: PlayerId) { - self.player_id = player_id; - } - - fn calculate_points(&self) -> u8 { - self.game.dice_points.0 - } - - fn calculate_adv_points(&self) -> u8 { - self.game.dice_points.1 - } - - fn choose_go(&self) -> bool { - true - } - - fn choose_move(&self) -> (CheckerMove, CheckerMove) { - let rules = MoveRules::new(&self.color, &self.game.board, self.game.dice); - let possible_moves = rules.get_possible_moves_sequences(true, vec![]); - - let mut rng = rng(); - let choosen_move = possible_moves - .choose(&mut rng) - .cloned() - .unwrap_or((CheckerMove::default(), CheckerMove::default())); - - if self.color == Color::White { - choosen_move - } else { - (choosen_move.0.mirror(), choosen_move.1.mirror()) - } - } -} diff --git a/bot/src/strategy/stable_baselines3.rs b/bot/src/strategy/stable_baselines3.rs index 78aa583..4b94311 100644 --- a/bot/src/strategy/stable_baselines3.rs +++ b/bot/src/strategy/stable_baselines3.rs @@ -5,7 +5,7 @@ use std::io::Read; use std::io::Write; use std::path::Path; use std::process::Command; -use trictrac_store::MoveRules; +use store::MoveRules; #[derive(Debug)] pub struct StableBaselines3Strategy { @@ -66,25 +66,25 @@ impl StableBaselines3Strategy { // Remplir les positions des pièces blanches (valeurs positives) for (pos, count) in self.game.board.get_color_fields(Color::White) { if pos < 24 { - board[pos] = count; + board[pos] = count as i8; } } // Remplir les positions des pièces noires (valeurs négatives) for (pos, count) in self.game.board.get_color_fields(Color::Black) { if pos < 24 { - board[pos] = -count; + board[pos] = -(count as i8); } } // Convertir l'étape du tour en entier let turn_stage = match self.game.turn_stage { - trictrac_store::TurnStage::RollDice => 0, - trictrac_store::TurnStage::RollWaiting => 1, - trictrac_store::TurnStage::MarkPoints => 2, - trictrac_store::TurnStage::HoldOrGoChoice => 3, - trictrac_store::TurnStage::Move => 4, - trictrac_store::TurnStage::MarkAdvPoints => 5, + store::TurnStage::RollDice => 0, + store::TurnStage::RollWaiting => 1, + store::TurnStage::MarkPoints => 2, + store::TurnStage::HoldOrGoChoice => 3, + store::TurnStage::Move => 4, + store::TurnStage::MarkAdvPoints => 5, }; // Récupérer les points et trous des joueurs @@ -270,3 +270,4 @@ impl BotStrategy for StableBaselines3Strategy { } } } + diff --git a/bot/src/trictrac_board.rs b/bot/src/trictrac_board.rs deleted file mode 100644 index 7fce992..0000000 --- a/bot/src/trictrac_board.rs +++ /dev/null @@ -1,171 +0,0 @@ -// https://docs.rs/board-game/ implementation -use board_game::board::{ - Board as BoardGameBoard, BoardDone, BoardMoves, Outcome, PlayError, Player as BoardGamePlayer, -}; -use board_game::impl_unit_symmetry_board; -use internal_iterator::InternalIterator; -use std::fmt; -use std::hash::Hash; -use std::ops::ControlFlow; -use trictrac_store::training_common::{get_valid_actions, TrictracAction}; -use trictrac_store::Color; - -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub struct TrictracBoard(crate::GameState); - -impl Default for TrictracBoard { - fn default() -> Self { - TrictracBoard(crate::GameState::new_with_players("white", "black")) - } -} - -impl fmt::Display for TrictracBoard { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl_unit_symmetry_board!(TrictracBoard); - -impl BoardGameBoard for TrictracBoard { - // impl TrictracBoard { - type Move = TrictracAction; - - fn next_player(&self) -> BoardGamePlayer { - self.0 - .who_plays() - .map(|p| { - if p.color == Color::Black { - BoardGamePlayer::B - } else { - BoardGamePlayer::A - } - }) - .unwrap_or(BoardGamePlayer::A) - } - - fn is_available_move(&self, mv: Self::Move) -> Result { - self.check_done()?; - let is_valid = mv - .to_event(&self.0) - .map(|evt| self.0.validate(&evt)) - .unwrap_or(false); - Ok(is_valid) - } - - fn play(&mut self, mv: Self::Move) -> Result<(), PlayError> { - self.check_can_play(mv)?; - if let Some(evt) = mv.to_event(&self.0) { - let _ = self.0.consume(&evt); - Ok(()) - } else { - Err(PlayError::UnavailableMove) - } - } - - fn outcome(&self) -> Option { - if self.0.stage == crate::Stage::Ended { - self.0.determine_winner().map(|player_id| { - Outcome::WonBy(if player_id == 1 { - BoardGamePlayer::A - } else { - BoardGamePlayer::B - }) - }) - } else { - None - } - } - - fn can_lose_after_move() -> bool { - true - } -} - -impl TrictracBoard { - pub fn inner(&self) -> &crate::GameState { - &self.0 - } - - pub fn to_fen(&self) -> String { - self.0.to_string_id() - } - - pub fn from_fen(fen: &str) -> Result { - crate::GameState::from_string_id(fen).map(TrictracBoard) - } -} - -impl<'a> BoardMoves<'a, TrictracBoard> for TrictracBoard { - type AllMovesIterator = TrictracAllMovesIterator; - type AvailableMovesIterator = TrictracAvailableMovesIterator<'a>; - - fn all_possible_moves() -> Self::AllMovesIterator { - TrictracAllMovesIterator::default() - } - - fn available_moves(&'a self) -> Result { - TrictracAvailableMovesIterator::new(self) - } -} - -#[derive(Debug, Clone)] -pub struct TrictracAllMovesIterator; - -impl Default for TrictracAllMovesIterator { - fn default() -> Self { - TrictracAllMovesIterator - } -} - -impl InternalIterator for TrictracAllMovesIterator { - type Item = TrictracAction; - - fn try_for_each ControlFlow>(self, mut f: F) -> ControlFlow { - f(TrictracAction::Roll)?; - f(TrictracAction::Go)?; - for dice_order in [false, true] { - for checker1 in 0..16 { - for checker2 in 0..16 { - f(TrictracAction::Move { - dice_order, - checker1, - checker2, - })?; - } - } - } - - ControlFlow::Continue(()) - } -} - -#[derive(Debug, Clone)] -pub struct TrictracAvailableMovesIterator<'a> { - board: &'a TrictracBoard, -} - -impl<'a> TrictracAvailableMovesIterator<'a> { - pub fn new(board: &'a TrictracBoard) -> Result { - board.check_done()?; - Ok(TrictracAvailableMovesIterator { board }) - } - - pub fn board(&self) -> &'a TrictracBoard { - self.board - } -} - -impl InternalIterator for TrictracAvailableMovesIterator<'_> { - type Item = TrictracAction; - - fn try_for_each(self, f: F) -> ControlFlow - where - F: FnMut(Self::Item) -> ControlFlow, - { - match get_valid_actions(&self.board.0) { - Ok(actions) => actions.into_iter().try_for_each(f), - Err(_) => ControlFlow::Continue(()), - } - } -} diff --git a/client_bevy/.cargo/config.toml b/client_bevy/.cargo/config.toml new file mode 100644 index 0000000..b6bc0d3 --- /dev/null +++ b/client_bevy/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.x86_64-unknown-linux-gnu] +linker = "clang" +rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"] + +# Optional: Uncommenting the following improves compile times, but reduces the amount of debug info to 'line number tables only' +# In most cases the gains are negligible, but if you are on macos and have slow compile times you should see significant gains. +#[profile.dev] +#debug = 1 diff --git a/client_bevy/Cargo.toml b/client_bevy/Cargo.toml new file mode 100644 index 0000000..aaa6b7d --- /dev/null +++ b/client_bevy/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "trictrac-client" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.75" +bevy = { version = "0.11.3" } +bevy_renet = "0.0.9" +bincode = "1.3.3" +renet = "0.0.13" +store = { path = "../store" } diff --git a/client_bevy/assets/Inconsolata.ttf b/client_bevy/assets/Inconsolata.ttf new file mode 100644 index 0000000..34848ca Binary files /dev/null and b/client_bevy/assets/Inconsolata.ttf differ diff --git a/client_bevy/assets/board.png b/client_bevy/assets/board.png new file mode 100644 index 0000000..5d16ac3 Binary files /dev/null and b/client_bevy/assets/board.png differ diff --git a/client_bevy/assets/sound/click.wav b/client_bevy/assets/sound/click.wav new file mode 100644 index 0000000..8b6c99d Binary files /dev/null and b/client_bevy/assets/sound/click.wav differ diff --git a/client_bevy/assets/sound/throw.wav b/client_bevy/assets/sound/throw.wav new file mode 100755 index 0000000..cb5e438 Binary files /dev/null and b/client_bevy/assets/sound/throw.wav differ diff --git a/client_bevy/assets/tac.png b/client_bevy/assets/tac.png new file mode 100644 index 0000000..2c18813 Binary files /dev/null and b/client_bevy/assets/tac.png differ diff --git a/client_bevy/assets/tic.png b/client_bevy/assets/tic.png new file mode 100644 index 0000000..786e0c7 Binary files /dev/null and b/client_bevy/assets/tic.png differ diff --git a/client_bevy/src/main.rs b/client_bevy/src/main.rs new file mode 100644 index 0000000..504602e --- /dev/null +++ b/client_bevy/src/main.rs @@ -0,0 +1,334 @@ +use std::{net::UdpSocket, time::SystemTime}; + +use renet::transport::{NetcodeClientTransport, NetcodeTransportError, NETCODE_USER_DATA_BYTES}; +use store::{GameEvent, GameState, CheckerMove}; + +use bevy::prelude::*; +use bevy::window::PrimaryWindow; +use bevy_renet::{ + renet::{transport::ClientAuthentication, ConnectionConfig, RenetClient}, + transport::{client_connected, NetcodeClientPlugin}, + RenetClientPlugin, +}; + +#[derive(Debug, Resource)] +struct CurrentClientId(u64); + +#[derive(Resource)] +struct BevyGameState(GameState); + +impl Default for BevyGameState { + fn default() -> Self { + Self { + 0: GameState::default(), + } + } +} + +#[derive(Resource, Deref, DerefMut)] +struct GameUIState { + selected_tile: Option, +} + +impl Default for GameUIState { + fn default() -> Self { + Self { + selected_tile: None, + } + } +} + +#[derive(Event)] +struct BevyGameEvent(GameEvent); + +// This id needs to be the same as the server is using +const PROTOCOL_ID: u64 = 2878; + +fn main() { + // Get username from stdin args + let args = std::env::args().collect::>(); + let username = &args[1]; + + let (client, transport, client_id) = new_renet_client(&username).unwrap(); + App::new() + // Lets add a nice dark grey background color + .insert_resource(ClearColor(Color::hex("282828").unwrap())) + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + // Adding the username to the window title makes debugging a whole lot easier. + title: format!("TricTrac <{}>", username), + resolution: (1080.0, 1080.0).into(), + ..default() + }), + ..default() + })) + // Add our game state and register GameEvent as a bevy event + .insert_resource(BevyGameState::default()) + .insert_resource(GameUIState::default()) + .add_event::() + // Renet setup + .add_plugins(RenetClientPlugin) + .add_plugins(NetcodeClientPlugin) + .insert_resource(client) + .insert_resource(transport) + .insert_resource(CurrentClientId(client_id)) + .add_systems(Startup, setup) + .add_systems(Update, (update_waiting_text, input, update_board, panic_on_error_system)) + .add_systems( + PostUpdate, + receive_events_from_server.run_if(client_connected()), + ) + .run(); +} + +////////// COMPONENTS ////////// +#[derive(Component)] +struct UIRoot; + +#[derive(Component)] +struct WaitingText; + +#[derive(Component)] +struct Board { + squares: [Square; 26] +} + +impl Default for Board { + fn default() -> Self { + Self { + squares: [Square { count: 0, color: None, position: 0}; 26] + } + } +} + +impl Board { + fn square_at(&self, position: usize) -> Square { + self.squares[position] + } +} + +#[derive(Component, Clone, Copy)] +struct Square { + count: usize, + color: Option, + position: usize, +} + +////////// UPDATE SYSTEMS ////////// +fn update_board( + mut commands: Commands, + game_state: Res, + mut game_events: EventReader, + asset_server: Res, +) { + for event in game_events.iter() { + match event.0 { + GameEvent::Move { player_id, moves } => { + // trictrac positions, TODO : dépend de player_id + let (x, y) = if moves.0.get_to() < 13 { (13 - moves.0.get_to(), 1) } else { (moves.0.get_to() - 13, 0)}; + let texture = + asset_server.load(match game_state.0.players[&player_id].color { + store::Color::Black => "tac.png", + store::Color::White => "tic.png", + }); + + info!("spawning tictac sprite"); + commands.spawn(SpriteBundle { + transform: Transform::from_xyz( + 83.0 * (x as f32 - 1.0), + -30.0 + 540.0 * (y as f32 - 1.0), + 0.0, + ), + sprite: Sprite { + custom_size: Some(Vec2::new(83.0, 83.0)), + ..default() + }, + texture: texture.into(), + ..default() + }); + } + _ => {} + } + } +} + +fn update_waiting_text(mut text_query: Query<&mut Text, With>, time: Res