diff --git a/Cargo.lock b/Cargo.lock index e557059..8e99c55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,54 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common 0.1.7", - "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 0.2.17", -] - -[[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.4" @@ -59,95 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aligned" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" -dependencies = [ - "as-slice", -] - -[[package]] -name = "aligned-vec" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" -dependencies = [ - "equator", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[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 = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anstream" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" - -[[package]] -name = "anstyle-parse" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", -] - [[package]] name = "any_spawner" version = "0.2.0" @@ -165,32 +28,6 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" - -[[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.117", -] - [[package]] name = "argon2" version = "0.5.3" @@ -200,61 +37,7 @@ dependencies = [ "base64ct", "blake2", "cpufeatures 0.2.17", - "password-hash 0.5.0", -] - -[[package]] -name = "arimaa_engine_step" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c6726d7896a539a62e157b05fa4b7308ffb7872f2b4a2a592d5adb19837861" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "log", - "regex", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "as-slice" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" -dependencies = [ - "stable_deref_trait", -] - -[[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.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", + "password-hash", ] [[package]] @@ -294,12 +77,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atomic_float" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628d228f918ac3b82fe590352cc719d30664a0c13ca3a60266fe02c7132d480a" - [[package]] name = "attribute-derive" version = "0.10.5" @@ -336,54 +113,11 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "av-scenechange" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" -dependencies = [ - "aligned", - "anyhow", - "arg_enum_proc_macro", - "arrayvec 0.7.6", - "log", - "num-rational", - "num-traits", - "pastey", - "rayon", - "thiserror 2.0.18", - "v_frame", - "y4m", -] - -[[package]] -name = "av1-grain" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" -dependencies = [ - "anyhow", - "arrayvec 0.7.6", - "log", - "nom 8.0.0", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" -dependencies = [ - "arrayvec 0.7.6", -] - [[package]] name = "axum" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core", "base64 0.22.1", @@ -468,21 +202,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link 0.2.1", -] - [[package]] name = "base64" version = "0.21.7" @@ -501,89 +220,11 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" -[[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 = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags 2.11.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 2.1.2", - "shlex", - "syn 2.0.117", -] - -[[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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" - [[package]] name = "bitflags" -version = "1.3.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -dependencies = [ - "serde_core", -] - -[[package]] -name = "bitstream-io" -version = "4.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" -dependencies = [ - "core2", -] +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "blake2" @@ -594,12 +235,6 @@ dependencies = [ "digest 0.10.7", ] -[[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" @@ -618,607 +253,23 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "board-game" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647fc8459363368aae04df3d21da37094430c57dd993d09be2792133d5365e3e" -dependencies = [ - "arimaa_engine_step", - "cast_trait", - "chess", - "decorum", - "internal-iterator", - "itertools 0.10.5", - "lazy_static", - "nohash-hasher", - "nom 7.1.3", - "num-traits", - "once_cell", - "rand 0.8.5", - "rand_xoshiro", - "rayon", - "static_assertions", -] - -[[package]] -name = "bstr" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" -dependencies = [ - "memchr", - "regex-automata 0.4.14", - "serde", -] - -[[package]] -name = "built" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" - [[package]] name = "bumpalo" version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" -[[package]] -name = "burn" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b78ff10ed98b73e1d477ea6e6e1ec1b9cf9f71a17afc3fea9f4dca482d43dcd4" -dependencies = [ - "burn-autodiff", - "burn-candle", - "burn-collective", - "burn-core", - "burn-cpu", - "burn-cuda", - "burn-ndarray", - "burn-nn", - "burn-optim", - "burn-remote", - "burn-rocm", - "burn-router", - "burn-store", - "burn-tch", - "burn-train", - "burn-wgpu", -] - -[[package]] -name = "burn-autodiff" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f04955e9b4acd5e6a6229f80217dae79742975a97dc2253003f226333ad307" -dependencies = [ - "burn-backend", - "burn-std", - "derive-new", - "hashbrown 0.16.1", - "log", - "num-traits", - "parking_lot", - "portable-atomic", - "spin 0.10.0", - "tracing", -] - -[[package]] -name = "burn-backend" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a724a5d8d5865a1f6b304f629eb19f51489760689501c583b3e1f4209f067357" -dependencies = [ - "burn-std", - "bytemuck", - "cubecl", - "derive-new", - "hashbrown 0.16.1", - "num-traits", - "rand 0.9.3", - "rand_distr", - "serde", - "thiserror 2.0.18", -] - -[[package]] -name = "burn-candle" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21c752d5008923eb9299783da5edae3242b94afdb956e88d2b37b025244b5071" -dependencies = [ - "burn-backend", - "burn-std", - "candle-core", - "derive-new", -] - -[[package]] -name = "burn-collective" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5b2199984291a0f3828d5ac04039fb864c56c3bdd9ee4172a63e457b668e4c" -dependencies = [ - "burn-communication", - "burn-std", - "burn-tensor", - "bytes", - "futures", - "log", - "rmp-serde", - "serde", - "tokio", - "tokio-util", -] - -[[package]] -name = "burn-communication" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585526cd672adc35918d8aea9bcb50669067904f36090caaffa9573d22fc7ade" -dependencies = [ - "axum", - "burn-std", - "burn-tensor", - "bytes", - "derive-new", - "futures", - "futures-util", - "log", - "rmp-serde", - "serde", - "serde_bytes", - "tokio", - "tokio-tungstenite", - "tokio-util", - "tracing", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "burn-core" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3634c3ba84397bcf2977ce746954d7e0a40e2d862e92362dd694c29e18df62" -dependencies = [ - "ahash", - "bincode 2.0.1", - "burn-dataset", - "burn-derive", - "burn-std", - "burn-tensor", - "data-encoding", - "derive-new", - "flate2", - "half", - "hashbrown 0.16.1", - "log", - "num-traits", - "portable-atomic", - "portable-atomic-util", - "rand 0.9.3", - "regex", - "rmp-serde", - "serde", - "serde_json", - "spin 0.10.0", - "uuid", -] - -[[package]] -name = "burn-cpu" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60aa53c4536719f1c91c250d4b4348daca473c44cf0c45b81096785f5510c192" -dependencies = [ - "burn-backend", - "burn-cubecl", - "burn-fusion", - "cubecl", -] - -[[package]] -name = "burn-cubecl" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6d13aff03fec966da4300459688883f8a1d741dddbf19d1bfc2562656a9a9b" -dependencies = [ - "burn-backend", - "burn-cubecl-fusion", - "burn-fusion", - "burn-ir", - "burn-std", - "cubecl", - "cubek", - "derive-new", - "futures-lite", - "log", - "serde", - "text_placeholder", -] - -[[package]] -name = "burn-cubecl-fusion" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d25b2e9fb805931401f79782aabd92462d65e60bc207035a3e554de8d7cd9f" -dependencies = [ - "burn-backend", - "burn-fusion", - "burn-ir", - "burn-std", - "cubecl", - "cubek", - "derive-new", - "serde", -] - -[[package]] -name = "burn-cuda" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0c68cf653eb9c27dcbe046bb7b04cc18c6b33afda4c09317c102e6f4ae7cb6" -dependencies = [ - "burn-backend", - "burn-cubecl", - "burn-fusion", - "cubecl", -] - -[[package]] -name = "burn-dataset" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e87741e2ff9015845ed2b41b47f9e82795cf274bf2328a29619a2e6f662495c" -dependencies = [ - "csv", - "derive-new", - "dirs", - "gix-tempfile", - "image", - "r2d2", - "r2d2_sqlite", - "rand 0.9.3", - "rmp-serde", - "rusqlite", - "sanitize-filename", - "serde", - "serde_json", - "serde_rusqlite", - "strum 0.27.2", - "tempfile", - "thiserror 2.0.18", -] - -[[package]] -name = "burn-derive" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "102d7e2f705b0cda2f89dd0e55e9bbfc6184029929d53487beb606c3303b29a5" -dependencies = [ - "derive-new", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "burn-fusion" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea83d7f8574bcc07967291c5bb679ddc0a655c8db0642eca62755e2fffc8047" -dependencies = [ - "burn-backend", - "burn-ir", - "derive-new", - "hashbrown 0.16.1", - "log", - "serde", - "spin 0.10.0", - "tracing", -] - -[[package]] -name = "burn-ir" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd2b1b37a7289bd85438800deaaebde50507336429b80f96a71730794db5bc31" -dependencies = [ - "burn-backend", - "hashbrown 0.16.1", - "serde", -] - -[[package]] -name = "burn-ndarray" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96be578991cecef163e41a73bf985d8d7eb7fb8ef7bececf8d48523c481ecddf" -dependencies = [ - "atomic_float", - "burn-autodiff", - "burn-backend", - "burn-ir", - "burn-std", - "bytemuck", - "const-random", - "itertools 0.14.0", - "libm", - "macerator", - "matrixmultiply", - "ndarray 0.17.2", - "num-traits", - "paste", - "portable-atomic", - "portable-atomic-util", - "rand 0.9.3", - "rayon", - "seq-macro", -] - -[[package]] -name = "burn-nn" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b8c6c14b94e5b1dddd68f8e6d669f20bac8f99fcb2e4f1a480212d1b598133" -dependencies = [ - "burn-core", - "num-traits", -] - -[[package]] -name = "burn-optim" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8c376d835d92ea363c05c6f48ac19bb687b683c7958c310a716ef8d5d77ba3" -dependencies = [ - "burn-core", - "derive-new", - "hashbrown 0.16.1", - "log", - "num-traits", - "serde", -] - -[[package]] -name = "burn-remote" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7238df1d59dcbb6880fe92ca0aa7b02b64d02394815e618da3d7933950bdaf39" -dependencies = [ - "async-channel", - "axum", - "burn-communication", - "burn-ir", - "burn-router", - "burn-std", - "burn-tensor", - "bytes", - "derive-new", - "futures-util", - "log", - "rmp-serde", - "serde", - "serde_bytes", - "tokio", - "tokio-tungstenite", - "tokio-util", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "burn-rl" -version = "0.1.0" -source = "git+https://github.com/yunjhongwu/burn-rl-examples.git#bf76ba61fdc89837cbf259a6f554a1fcec238690" -dependencies = [ - "burn", - "gym-rs", - "rand 0.8.5", - "ringbuffer", - "serde", -] - -[[package]] -name = "burn-rocm" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2abda6ee63bdcb730f1a335349a9ff83f03048130d405b6ecdccd2df3ff23" -dependencies = [ - "burn-backend", - "burn-cubecl", - "burn-fusion", - "cubecl", -] - -[[package]] -name = "burn-router" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823ccb88484736a2861d53dc7f67db375ef050b0446bb02dd7cb8783ac6b69a2" -dependencies = [ - "burn-backend", - "burn-ir", - "burn-std", - "hashbrown 0.16.1", - "log", - "spin 0.10.0", -] - -[[package]] -name = "burn-std" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a9ed8e34a4a49d3754586f306075d6b55a5e08343ac75c06f47e7d9f825271" -dependencies = [ - "bytemuck", - "bytes", - "cubecl", - "cubecl-common", - "half", - "num-traits", - "serde", -] - -[[package]] -name = "burn-store" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be80a7b084a19901dc1d0a2e9b77e226c5c575879fe66de891c67062db41a6d" -dependencies = [ - "burn-core", - "burn-nn", - "burn-tensor", - "byteorder", - "bytes", - "half", - "hashbrown 0.16.1", - "memmap2", - "regex", - "safetensors 0.7.0", - "textdistance", -] - -[[package]] -name = "burn-tch" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "061cd3df7b4126949561185454b9b67623f6885657361cad2a07a2340b3b3108" -dependencies = [ - "burn-backend", - "cc", - "libc", - "log", - "tch", - "torch-sys", -] - -[[package]] -name = "burn-tensor" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3720e52e00ed0155ced4f8681d0e8a362e699cee36494ec5b97ad44fcc5194c0" -dependencies = [ - "burn-backend", - "burn-std", - "colored", - "derive-new", - "num-traits", - "serde", -] - -[[package]] -name = "burn-train" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c3128c7571992c382a5ad057c72654c1048ea4dcf138d1f394313047e69803a" -dependencies = [ - "async-channel", - "burn-core", - "burn-ndarray", - "burn-optim", - "derive-new", - "log", - "nvml-wrapper", - "ratatui", - "rstest", - "serde", - "sysinfo 0.37.2", - "systemstat", - "thiserror 2.0.18", - "tracing-appender", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "burn-wgpu" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df78d62afc9b9fbb8ee4e49b72006485bb64f778a790e185a2d919479bcfc008" -dependencies = [ - "burn-backend", - "burn-cubecl", - "burn-fusion", - "cubecl", -] - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -dependencies = [ - "portable-atomic", -] - -[[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 = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "c_vec" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8" [[package]] name = "calendrical_calculations" @@ -1236,109 +287,28 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" -[[package]] -name = "candle-core" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15b675b80d994b2eadb20a4bbe434eabeb454eac3ee5e2b4cf6f147ee9be091" -dependencies = [ - "byteorder", - "float8 0.6.1", - "gemm", - "half", - "libm", - "memmap2", - "num-traits", - "num_cpus", - "rand 0.9.3", - "rand_distr", - "rayon", - "safetensors 0.7.0", - "thiserror 2.0.18", - "yoke 0.8.2", - "zip 7.2.0", -] - -[[package]] -name = "caseless" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8" -dependencies = [ - "unicode-normalization", -] - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" -[[package]] -name = "cast_trait" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f8d981c476baadf74cd52897866a1d279d3e14e2d5e2d9af045210e0ae6128" - -[[package]] -name = "castaway" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" -dependencies = [ - "rustversion", -] - [[package]] name = "cc" -version = "1.2.60" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom 7.1.3", -] - [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[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.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", -] - [[package]] name = "chacha20" version = "0.10.0" @@ -1347,135 +317,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20 0.9.1", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "chess" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ed299b171ec34f372945ad6726f7bc1d2afd5f59fb8380f64f48e2bab2f0ec8" -dependencies = [ - "arrayvec 0.5.2", - "failure", - "nodrop", - "rand 0.7.3", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.7", - "inout", - "zeroize", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" -dependencies = [ - "anstyle", - "clap_lex", -] - -[[package]] -name = "clap_lex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" - -[[package]] -name = "client_web" -version = "0.1.0" -dependencies = [ - "backbone-lib", - "futures", - "getrandom 0.3.4", - "gloo-net 0.5.0", - "gloo-storage", - "gloo-timers", - "leptos", - "leptos_i18n", - "rand 0.9.3", - "serde", - "serde_json", - "trictrac-store", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", + "rand_core 0.10.1", ] [[package]] @@ -1504,72 +346,12 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "codespan-reporting" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" -dependencies = [ - "serde", - "termcolor", - "unicode-width 0.2.0", -] - [[package]] name = "collection_literals" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2550f75b8cfac212855f6b1885455df8eaee8fe8e246b647d69146142e016084" -[[package]] -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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" - -[[package]] -name = "colored" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "compact_str" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "rustversion", - "ryu", - "static_assertions", -] - -[[package]] -name = "comrak" -version = "0.39.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fefab951771fc3beeed0773ce66a4f7b706273fc6c4c95b08dd1615744abcf5" -dependencies = [ - "caseless", - "entities", - "memchr", - "slug", - "typed-arena", - "unicode_categories", -] - [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1589,19 +371,7 @@ dependencies = [ "pathdiff", "serde_core", "toml 1.1.2+spec-1.1.0", - "winnow 1.0.1", -] - -[[package]] -name = "confy" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29222b549d4e3ded127989d523da9e928918d0d0d7f7c1690b439d0d538bae9" -dependencies = [ - "directories", - "serde", - "thiserror 2.0.18", - "toml 0.8.23", + "winnow 1.0.2", ] [[package]] @@ -1610,33 +380,14 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" -[[package]] -name = "const-random" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom 0.2.17", - "once_cell", - "tiny-keccak", -] - [[package]] name = "const_format" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" dependencies = [ "const_format_proc_macros", + "konst", ] [[package]] @@ -1656,18 +407,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f67855af358fcb20fac58f9d714c94e2b228fe5694c1c9b4ead4a366343eda1b" -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "constcat" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d3e02915a2cea4d74caa8681e2d44b1c3254bdbf17d11d41d587ff858832c" - [[package]] name = "convert_case" version = "0.6.0" @@ -1686,24 +425,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "convert_case" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "convert_case" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "cookie" version = "0.18.1" @@ -1715,42 +436,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.11.0", - "core-foundation", - "libc", -] - -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - [[package]] name = "core_maths" version = "0.1.1" @@ -1778,122 +463,18 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - [[package]] name = "critical-section" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" -[[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" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" -[[package]] -name = "crossterm" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" -dependencies = [ - "bitflags 2.11.0", - "crossterm_winapi", - "mio", - "parking_lot", - "rustix 0.38.44", - "signal-hook 0.3.18", - "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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - [[package]] name = "crypto-common" version = "0.1.7" @@ -1901,7 +482,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core 0.6.4", "typenum", ] @@ -1914,27 +494,6 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "csv" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde_core", -] - -[[package]] -name = "csv-core" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" -dependencies = [ - "memchr", -] - [[package]] name = "ctutils" version = "0.4.2" @@ -1944,458 +503,14 @@ dependencies = [ "cmov", ] -[[package]] -name = "cubecl" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053856efd5436224775b9423d43d86f53d5b1d3af9a6b9983d9a313a0922638f" -dependencies = [ - "cubecl-core", - "cubecl-cpu", - "cubecl-cuda", - "cubecl-hip", - "cubecl-ir", - "cubecl-runtime", - "cubecl-std", - "cubecl-wgpu", - "half", -] - -[[package]] -name = "cubecl-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60bf8aaeb572c8cf2f2ffd07fa9bb1a2cf9336d1aa11ecd4d9a2f2e30c4be706" -dependencies = [ - "backtrace", - "bytemuck", - "bytes", - "cfg-if", - "cfg_aliases", - "derive-new", - "derive_more", - "dirs", - "embassy-futures", - "embassy-time", - "float4", - "float8 0.4.2", - "futures-lite", - "half", - "hashbrown 0.15.5", - "log", - "num-traits", - "parking_lot", - "portable-atomic", - "portable-atomic-util", - "rand 0.9.3", - "sanitize-filename", - "serde", - "serde_bytes", - "serde_json", - "spin 0.10.0", - "tracing", - "wasm-bindgen-futures", - "web-time", -] - -[[package]] -name = "cubecl-core" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98374a31d2b68b55709891169832ccf205408c201c5e023964482441f213d0b9" -dependencies = [ - "bitflags 2.11.0", - "bytemuck", - "cubecl-common", - "cubecl-ir", - "cubecl-macros", - "cubecl-runtime", - "derive-new", - "derive_more", - "enumset", - "float-ord", - "half", - "hashbrown 0.15.5", - "log", - "num-traits", - "paste", - "serde", - "serde_json", - "tracing", - "variadics_please", -] - -[[package]] -name = "cubecl-cpp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb24d96c1ff84ab4def0a529e384311a15cb771310aaf2b640c312384c3bca23" -dependencies = [ - "bytemuck", - "cubecl-common", - "cubecl-core", - "cubecl-opt", - "cubecl-runtime", - "derive-new", - "half", - "itertools 0.14.0", - "log", -] - -[[package]] -name = "cubecl-cpu" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "152588a6e16b6bda5e8216af7a6fad3d7de4697294b6ce0f6acbe3a9029ff674" -dependencies = [ - "bytemuck", - "cubecl-common", - "cubecl-core", - "cubecl-opt", - "cubecl-runtime", - "cubecl-std", - "derive-new", - "half", - "log", - "paste", - "serde", - "sysinfo 0.36.1", - "tracel-llvm", - "tracel-llvm-bundler", -] - -[[package]] -name = "cubecl-cuda" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f74a5750c45090d1fc5ddf6a19fea9a099aa1f6800b78f1167a2d60182d1d96" -dependencies = [ - "bytemuck", - "cubecl-common", - "cubecl-core", - "cubecl-cpp", - "cubecl-runtime", - "cubecl-zspace", - "cudarc", - "derive-new", - "half", - "log", - "serde", - "tracing", -] - -[[package]] -name = "cubecl-hip" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbae9bc7ee6093d0d7a549c05873dff3478f9087b59eb09b223a97d642c849aa" -dependencies = [ - "bytemuck", - "cubecl-common", - "cubecl-core", - "cubecl-cpp", - "cubecl-hip-sys", - "cubecl-runtime", - "cubecl-zspace", - "derive-new", - "half", - "log", - "paste", - "serde", - "tracing", -] - -[[package]] -name = "cubecl-hip-sys" -version = "7.1.5280200" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcdd98f72d6f17836a0477bcd5ae5dd6b57a80fb62a3c0919f867a231f897f28" -dependencies = [ - "libc", - "regex", -] - -[[package]] -name = "cubecl-ir" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361b608ff9f05024c7a7e381852689acd95b6af5af956d68734692b27d5f75ef" -dependencies = [ - "cubecl-common", - "cubecl-macros-internal", - "derive-new", - "derive_more", - "enumset", - "float-ord", - "fnv", - "half", - "hashbrown 0.15.5", - "num-traits", - "portable-atomic", - "serde", - "variadics_please", -] - -[[package]] -name = "cubecl-macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9a872d16207c6a27ed45942fd311a281394dd384b14a21f72131db1556a977" -dependencies = [ - "cubecl-common", - "darling 0.21.3", - "derive-new", - "ident_case", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "cubecl-macros-internal" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa3fa0626cdf28b9c49084c2bb51493bfde44378e22d90624aacaafb81da3588" -dependencies = [ - "darling 0.21.3", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "cubecl-opt" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcff25fdcbd82ea4277c30a81e162722859f57c6ae105c0a3c53f8bb91154f6" -dependencies = [ - "cubecl-common", - "cubecl-core", - "cubecl-ir", - "float-ord", - "log", - "num", - "petgraph", - "smallvec", - "stable-vec", - "type-map", -] - -[[package]] -name = "cubecl-runtime" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b02e28997a8d75311afae4d2cea7b593eb125312f845874118a59d78c7a6b34c" -dependencies = [ - "async-channel", - "bytemuck", - "cfg-if", - "cfg_aliases", - "cubecl-common", - "cubecl-ir", - "derive-new", - "derive_more", - "dirs", - "enumset", - "foldhash 0.1.5", - "hashbrown 0.15.5", - "log", - "md5", - "serde", - "serde_json", - "spin 0.10.0", - "thiserror 2.0.18", - "toml 0.9.12+spec-1.1.0", - "tracing", - "variadics_please", - "wasm-bindgen-futures", - "web-time", -] - -[[package]] -name = "cubecl-std" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ff5741c98b7a7a5944b4afb0b67dd7f5e0be41ce7f303b587f8b0d6430b29b" -dependencies = [ - "cubecl-common", - "cubecl-core", - "cubecl-runtime", - "foldhash 0.1.5", - "half", - "num-traits", - "paste", - "serde", - "spin 0.10.0", - "variadics_please", -] - -[[package]] -name = "cubecl-wgpu" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29787364632fc7ec6a11cf3d95187f82f6fcce17d6bb4f0fb0dde580b837631d" -dependencies = [ - "async-channel", - "bytemuck", - "cfg-if", - "cfg_aliases", - "cubecl-common", - "cubecl-core", - "cubecl-ir", - "cubecl-runtime", - "derive-new", - "derive_more", - "half", - "hashbrown 0.15.5", - "log", - "sanitize-filename", - "tracing", - "wgpu", -] - -[[package]] -name = "cubecl-zspace" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0f819071413b19a00b7105497e0f6d2cf3e7e9d65cbb8d4ecf1ddb29c61dc2" - -[[package]] -name = "cubek" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb1cce47db02017925301bedec92ae84628493df3f9761ea7ac42a60c6146f8" -dependencies = [ - "cubecl", - "cubek-attention", - "cubek-convolution", - "cubek-matmul", - "cubek-quant", - "cubek-random", - "cubek-reduce", -] - -[[package]] -name = "cubek-attention" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7278bd122b2428af479f9af05285160613733c33c93b63ab3c6d25cd0460c18b" -dependencies = [ - "bytemuck", - "cubecl", - "cubecl-common", - "cubek-matmul", - "cubek-random", - "half", - "serde", -] - -[[package]] -name = "cubek-convolution" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18eb04bca4ae104d62a56def04b04f3d079c42fe49aac62202c96876f90fa28b" -dependencies = [ - "bytemuck", - "cubecl", - "cubecl-common", - "cubek-matmul", - "derive-new", - "enumset", - "half", - "serde", -] - -[[package]] -name = "cubek-matmul" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28f3b04b113760e97c65a8a4dca9afc220744031eeecd5ad6cd0e3be91ba3a9" -dependencies = [ - "bytemuck", - "cubecl", - "cubecl-common", - "half", - "serde", -] - -[[package]] -name = "cubek-quant" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ec3ae04af324df2d615c2b394e270d58d6f08cb833d67633e2ba794de75916" -dependencies = [ - "cubecl", - "cubecl-common", - "half", - "serde", -] - -[[package]] -name = "cubek-random" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65a34844d8b7f739185c1d24896137dcb73f458830444103b45f678585ad983e" -dependencies = [ - "cubecl", - "cubecl-common", - "half", - "num-traits", - "rand 0.9.3", - "serde", -] - -[[package]] -name = "cubek-reduce" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42397d9ed85bb3084dfb56ed26de75690b5b07caf42a32f4006b57eb23d5b6d6" -dependencies = [ - "cubecl", - "half", - "num-traits", - "serde", - "thiserror 2.0.18", -] - -[[package]] -name = "cudarc" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aa12038120eb13347a6ae2ffab1d34efe78150125108627fd85044dd4d6ff1e" -dependencies = [ - "libloading", -] - [[package]] name = "darling" version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", -] - -[[package]] -name = "darling" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" -dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", -] - -[[package]] -name = "darling" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" -dependencies = [ - "darling_core 0.23.0", - "darling_macro 0.23.0", + "darling_core", + "darling_macro", ] [[package]] @@ -2412,62 +527,13 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "darling_core" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - [[package]] name = "darling_macro" version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" -dependencies = [ - "darling_core 0.21.3", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" -dependencies = [ - "darling_core 0.23.0", + "darling_core", "quote", "syn 2.0.117", ] @@ -2488,9 +554,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "deadpool" @@ -2527,22 +593,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "decorum" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "281759d3c8a14f5c3f0c49363be56810fcd7f910422f97f2db850c2920fde5cf" -dependencies = [ - "num-traits", -] - [[package]] name = "default-struct-builder" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0df63c21a4383f94bd5388564829423f35c316aed85dc4f8427aded372c7c0d" dependencies = [ - "darling 0.20.11", + "darling", "proc-macro2", "quote", "syn 2.0.117", @@ -2558,28 +615,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[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.117", -] - [[package]] name = "derive-where" version = "1.6.1" @@ -2591,41 +626,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "derive_more" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" -dependencies = [ - "convert_case 0.10.0", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.117", - "unicode-xid", -] - -[[package]] -name = "deunicode" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" - -[[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" @@ -2639,9 +639,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer 0.12.0", "const-oid", @@ -2649,36 +649,6 @@ dependencies = [ "ctutils", ] -[[package]] -name = "directories" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - -[[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", - "windows-sys 0.61.2", -] - [[package]] name = "displaydoc" version = "0.2.5" @@ -2711,22 +681,6 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" -[[package]] -name = "dyn-stack" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4713e43e2886ba72b8271aa66c93d722116acf7a75555cce11dcde84388fe8" -dependencies = [ - "bytemuck", - "dyn-stack-macros", -] - -[[package]] -name = "dyn-stack-macros" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d926b4d407d372f141f93bb444696142c29d32962ccbd3531117cf3aa0bfa9" - [[package]] name = "either" version = "1.15.0" @@ -2735,69 +689,29 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "either_of" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f86eef3a7e4b9c2107583dbbbe3d9535c4b800796faf1774b82ba22033da" +checksum = "5060e0a4cbf26a87550792688ade88e6b8aec9208613631a7a363bda7bc2d4cd" dependencies = [ "paste", "pin-project-lite", ] [[package]] -name = "embassy-futures" -version = "0.1.2" +name = "email-encoding" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" - -[[package]] -name = "embassy-time" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8" +checksum = "9298e6504d9b9e780ed3f7dfd43a61be8cd0e09eb07f7706a945b0072b6670b6" dependencies = [ - "cfg-if", - "critical-section", - "document-features", - "embassy-time-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "futures-util", + "base64 0.22.1", + "memchr", ] [[package]] -name = "embassy-time-driver" -version = "0.2.2" +name = "email_address" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee71af1b3a0deaa53eaf2d39252f83504c853646e472400b763060389b9fcc9" -dependencies = [ - "document-features", -] - -[[package]] -name = "embedded-hal" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" -dependencies = [ - "nb 0.1.3", - "void", -] - -[[package]] -name = "embedded-hal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" - -[[package]] -name = "embedded-hal-async" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" -dependencies = [ - "embedded-hal 1.0.0", -] +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" [[package]] name = "embedded-io" @@ -2811,102 +725,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" -[[package]] -name = "entities" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" - -[[package]] -name = "enum-as-inner" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "enumset" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" -dependencies = [ - "enumset_derive", - "serde", -] - -[[package]] -name = "enumset_derive" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" -dependencies = [ - "darling 0.21.3", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "env_filter" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.11.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "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.117", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -2959,107 +777,18 @@ dependencies = [ "web-sys", ] -[[package]] -name = "exr" -version = "1.74.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - [[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -[[package]] -name = "fallible-iterator" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" -[[package]] -name = "fax" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" -dependencies = [ - "fax_derive", -] - -[[package]] -name = "fax_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "filetime" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" -dependencies = [ - "cfg-if", - "libc", - "libredox", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -3078,55 +807,6 @@ dependencies = [ "writeable 0.5.5", ] -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -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 = "float4" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5939bac0ef2ad7c83a53e4fb889c1d81f007b07061d648cd271071984d86f257" - -[[package]] -name = "float8" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4203231de188ebbdfb85c11f3c20ca2b063945710de04e7b59268731e728b462" -dependencies = [ - "half", -] - -[[package]] -name = "float8" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719a903cc23e4a89e87962c2a80fdb45cdaad0983a89bd150bb57b4c8571a7d5" -dependencies = [ - "half", - "num-traits", - "rand 0.9.3", - "rand_distr", -] - [[package]] name = "fnv" version = "1.0.7" @@ -3139,39 +819,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[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.117", -] - -[[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" @@ -3229,19 +876,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - [[package]] name = "futures-macro" version = "0.3.32" @@ -3265,12 +899,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" -[[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" @@ -3288,125 +916,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gemm" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa0673db364b12263d103b68337a68fbecc541d6f6b61ba72fe438654709eacb" -dependencies = [ - "dyn-stack", - "gemm-c32", - "gemm-c64", - "gemm-common", - "gemm-f16", - "gemm-f32", - "gemm-f64", - "num-complex", - "num-traits", - "paste", - "raw-cpuid", - "seq-macro", -] - -[[package]] -name = "gemm-c32" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "086936dbdcb99e37aad81d320f98f670e53c1e55a98bee70573e83f95beb128c" -dependencies = [ - "dyn-stack", - "gemm-common", - "num-complex", - "num-traits", - "paste", - "raw-cpuid", - "seq-macro", -] - -[[package]] -name = "gemm-c64" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c8aeeeec425959bda4d9827664029ba1501a90a0d1e6228e48bef741db3a3f" -dependencies = [ - "dyn-stack", - "gemm-common", - "num-complex", - "num-traits", - "paste", - "raw-cpuid", - "seq-macro", -] - -[[package]] -name = "gemm-common" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88027625910cc9b1085aaaa1c4bc46bb3a36aad323452b33c25b5e4e7c8e2a3e" -dependencies = [ - "bytemuck", - "dyn-stack", - "half", - "libm", - "num-complex", - "num-traits", - "once_cell", - "paste", - "pulp", - "raw-cpuid", - "rayon", - "seq-macro", - "sysctl", -] - -[[package]] -name = "gemm-f16" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3df7a55202e6cd6739d82ae3399c8e0c7e1402859b30e4cb780e61525d9486e" -dependencies = [ - "dyn-stack", - "gemm-common", - "gemm-f32", - "half", - "num-complex", - "num-traits", - "paste", - "raw-cpuid", - "rayon", - "seq-macro", -] - -[[package]] -name = "gemm-f32" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0b8c9da1fbec6e3e3ab2ce6bc259ef18eb5f6f0d3e4edf54b75f9fd41a81c" -dependencies = [ - "dyn-stack", - "gemm-common", - "num-complex", - "num-traits", - "paste", - "raw-cpuid", - "seq-macro", -] - -[[package]] -name = "gemm-f64" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056131e8f2a521bfab322f804ccd652520c79700d81209e9d9275bbdecaadc6a" -dependencies = [ - "dyn-stack", - "gemm-common", - "num-complex", - "num-traits", - "paste", - "raw-cpuid", - "seq-macro", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -3453,122 +962,11 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] -[[package]] -name = "gif" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - -[[package]] -name = "gix-features" -version = "0.45.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56aad357ae016449434705033df644ac6253dfcf1281aad3af3af9e907560d1" -dependencies = [ - "gix-trace", - "gix-utils", - "libc", -] - -[[package]] -name = "gix-fs" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785b9c499e46bc78d7b81c148c21b3fca18655379ee729a856ed19ce50d359ec" -dependencies = [ - "bstr", - "fastrand", - "gix-features", - "gix-path", - "gix-utils", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-path" -version = "0.10.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb06c3e4f8eed6e24fd915fa93145e28a511f4ea0e768bae16673e05ed3f366" -dependencies = [ - "bstr", - "gix-trace", - "gix-validate", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-tempfile" -version = "20.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad89218e74850f42d364ed3877c7291f0474c8533502df91bb877ecc5cb0dd40" -dependencies = [ - "dashmap", - "gix-fs", - "libc", - "parking_lot", - "signal-hook 0.4.4", - "signal-hook-registry", - "tempfile", -] - -[[package]] -name = "gix-trace" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f69a13643b8437d4ca6845e08143e847a36ca82903eed13303475d0ae8b162e0" - -[[package]] -name = "gix-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "befcdbdfb1238d2854591f760a48711bed85e72d80a10e8f2f93f656746ef7c5" -dependencies = [ - "fastrand", - "unicode-normalization", -] - -[[package]] -name = "gix-validate" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1e63a5b516e970a594f870ed4571a8fdcb8a344e7bd407a20db8bd61dbfde4" -dependencies = [ - "bstr", - "thiserror 2.0.18", -] - -[[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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - [[package]] name = "gloo-net" version = "0.5.0" @@ -3651,136 +1049,12 @@ dependencies = [ "web-sys", ] -[[package]] -name = "glow" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -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 = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" -dependencies = [ - "bitflags 2.11.0", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "gpu-allocator" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" -dependencies = [ - "log", - "presser", - "thiserror 1.0.69", - "windows 0.58.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.11.0", - "gpu-descriptor-types", - "hashbrown 0.15.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.11.0", -] - [[package]] name = "guardian" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f" -[[package]] -name = "gym-rs" -version = "0.3.1" -source = "git+https://github.com/MathisWellmann/gym-rs.git#5283afaa86a3a7c45c46c882cfad459f02539b62" -dependencies = [ - "derivative", - "derive-new", - "log", - "nalgebra", - "num-traits", - "ordered-float 5.3.0", - "rand 0.8.5", - "rand_pcg 0.3.1", - "sdl2", - "serde", -] - -[[package]] -name = "h2" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.4.0", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "bytemuck", - "cfg-if", - "crunchy", - "num-traits", - "rand 0.9.3", - "rand_distr", - "serde", - "zerocopy", -] - [[package]] name = "hash32" version = "0.2.1" @@ -3790,15 +1064,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -3811,23 +1076,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.1.5", - "serde", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", - "serde", - "serde_core", + "foldhash", ] [[package]] @@ -3836,15 +1085,6 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" -[[package]] -name = "hashlink" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown 0.15.5", -] - [[package]] name = "heapless" version = "0.7.17" @@ -3855,7 +1095,7 @@ dependencies = [ "hash32", "rustc_version", "serde", - "spin 0.9.8", + "spin", "stable_deref_trait", ] @@ -3871,28 +1111,24 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "hmac" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ - "digest 0.11.2", + "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]] @@ -3966,17 +1202,11 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" - [[package]] name = "hybrid-array" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" dependencies = [ "typenum", ] @@ -4005,7 +1235,6 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2", "http 1.4.0", "http-body", "httparse", @@ -4014,24 +1243,6 @@ dependencies = [ "pin-project-lite", "smallvec", "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http 1.4.0", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots 1.0.6", ] [[package]] @@ -4040,21 +1251,13 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64 0.22.1", "bytes", - "futures-channel", - "futures-util", "http 1.4.0", "http-body", "hyper", - "ipnet", - "libc", - "percent-encoding", "pin-project-lite", - "socket2", "tokio", "tower-service", - "tracing", ] [[package]] @@ -4464,54 +1667,14 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer 2.2.0", "icu_properties 2.2.0", ] -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", - "moxcms", - "num-traits", - "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "image-webp" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" - [[package]] name = "indexmap" version = "2.14.0" @@ -4524,111 +1687,12 @@ dependencies = [ "serde_core", ] -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instability" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" -dependencies = [ - "darling 0.23.0", - "indoc", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "internal-iterator" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" - -[[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.117", -] - [[package]] name = "interpolator" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" -[[package]] -name = "ipnet" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" - -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "is-terminal" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -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" version = "0.14.0" @@ -4644,73 +1708,11 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jiff" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", -] - -[[package]] -name = "jiff-static" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "jni-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" -dependencies = [ - "jni-sys 0.4.1", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if", "futures-util", @@ -4730,21 +1732,19 @@ dependencies = [ ] [[package]] -name = "khronos-egl" -version = "6.0.0" +name = "konst" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" dependencies = [ - "libc", - "libloading", - "pkg-config", + "konst_macro_rules", ] [[package]] -name = "khronos_api" -version = "3.1.0" +name = "konst_macro_rules" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" [[package]] name = "lazy_static" @@ -4758,12 +1758,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" -[[package]] -name = "lebe" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" - [[package]] name = "leptos" version = "0.7.8" @@ -4784,7 +1778,7 @@ dependencies = [ "or_poisoned", "paste", "reactive_graph", - "rustc-hash 2.1.2", + "rustc-hash", "send_wrapper", "serde", "serde_qs", @@ -4940,7 +1934,7 @@ dependencies = [ "cfg-if", "convert_case 0.7.1", "html-escape", - "itertools 0.14.0", + "itertools", "leptos_hot_reload", "prettyplease", "proc-macro-error2", @@ -5024,52 +2018,39 @@ dependencies = [ "tachys", ] +[[package]] +name = "lettre" +version = "0.11.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dabda5859ee7c06b995b9d1165aa52c39110e079ef609db97178d86aeb051fa7" +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", +] + [[package]] name = "libc" -version = "0.2.184" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" -dependencies = [ - "arbitrary", - "cc", -] - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link 0.2.1", -] - -[[package]] -name = "liblzma" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6033b77c21d1f56deeae8014eb9fbe7bdf1765185a6c508b5ca82eeaed7f899" -dependencies = [ - "liblzma-sys", - "num_cpus", -] - -[[package]] -name = "liblzma-sys" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a60851d15cd8c5346eca4ab8babff585be2ae4bc8097c067291d3ffe2add3b6" -dependencies = [ - "cc", - "libc", - "pkg-config", -] +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libm" @@ -5083,21 +2064,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.11.0", "libc", - "plain", - "redox_syscall 0.7.4", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", ] [[package]] @@ -5106,18 +2073,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - [[package]] name = "litemap" version = "0.7.5" @@ -5152,67 +2107,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[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.5", -] - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "macerator" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b0b2dbe8b22f9e96ba12e29964889010117f92e6bd006010887320ae58e2f0" -dependencies = [ - "bytemuck", - "cfg_aliases", - "half", - "macerator-macros", - "moddef", - "num-traits", - "paste", - "rustc_version", -] - -[[package]] -name = "macerator-macros" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ee1819976b67f4d782390c55a75c13401c7a988517f7f8e60a33484dc2e00a" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - [[package]] name = "manyhow" version = "0.11.4" @@ -5251,29 +2145,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" -[[package]] -name = "matrixmultiply" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" -dependencies = [ - "autocfg", - "num_cpus", - "once_cell", - "rawpointer", - "thread-tree", -] - -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "md-5" version = "0.11.0" @@ -5281,31 +2152,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" dependencies = [ "cfg-if", - "digest 0.11.2", + "digest 0.11.3", ] -[[package]] -name = "md5" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" - [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" -[[package]] -name = "memmap2" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" -dependencies = [ - "libc", - "stable_deref_trait", -] - [[package]] name = "merge" version = "0.1.0" @@ -5328,21 +2183,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "metal" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" -dependencies = [ - "bitflags 2.11.0", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", - "paste", -] - [[package]] name = "mime" version = "0.3.17" @@ -5360,19 +2200,13 @@ dependencies = [ ] [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "minicov" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d" dependencies = [ - "adler2", - "simd-adler32", + "cc", + "walkdir", ] [[package]] @@ -5382,169 +2216,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", - "log", "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] -[[package]] -name = "moddef" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0b3262dc837d2513fe2ef31ff8461352ef932dcca31ba0c0abe33547cf6b9b" - -[[package]] -name = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "naga" -version = "26.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916cbc7cb27db60be930a4e2da243cf4bc39569195f22fd8ee419cd31d5b662c" -dependencies = [ - "arrayvec 0.7.6", - "bit-set", - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "codespan-reporting", - "half", - "hashbrown 0.15.5", - "hexf-parse", - "indexmap", - "libm", - "log", - "num-traits", - "once_cell", - "rustc-hash 1.1.0", - "spirv", - "thiserror 2.0.18", - "unicode-ident", -] - -[[package]] -name = "nalgebra" -version = "0.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d43ddcacf343185dfd6de2ee786d9e8b1c2301622afab66b6c73baf9882abfd" -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.117", -] - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.1.0", -] - -[[package]] -name = "nb" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" - -[[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", -] - -[[package]] -name = "ndarray" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "portable-atomic", - "portable-atomic-util", - "rawpointer", - "rayon", -] - -[[package]] -name = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys 0.3.1", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "next_tuple" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60993920e071b0c9b66f14e2b32740a4e27ffc82854dcd72035887f336a09a28" -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nom" version = "8.0.0" @@ -5554,21 +2235,6 @@ dependencies = [ "memchr", ] -[[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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" -dependencies = [ - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -5578,20 +2244,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[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]] name = "num-bigint" version = "0.4.6" @@ -5602,33 +2254,12 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "bytemuck", - "num-traits", -] - [[package]] name = "num-conv" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" -[[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.117", -] - [[package]] name = "num-integer" version = "0.1.46" @@ -5638,17 +2269,6 @@ 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" @@ -5680,64 +2300,13 @@ dependencies = [ "libc", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "nvml-wrapper" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d5c6c0ef9702176a570f06ad94f3198bc29c524c8b498f1b9346e1b1bdcbb3a" -dependencies = [ - "bitflags 2.11.0", - "libloading", - "nvml-wrapper-sys", - "static_assertions", - "thiserror 1.0.69", - "wrapcenum-derive", -] - -[[package]] -name = "nvml-wrapper-sys" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4d594420fcda43b1c2c4bd44d48974aa3c7a9ab2cbf10dc18e35265767bf0b" -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 = "objc2-core-foundation" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "objc2-io-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" -dependencies = [ - "libc", - "objc2-core-foundation", + "bitflags", ] [[package]] @@ -5749,15 +2318,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "oco_ref" version = "0.2.1" @@ -5768,68 +2328,24 @@ dependencies = [ "thiserror 2.0.18", ] -[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - [[package]] name = "oorandom" version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - [[package]] name = "or_poisoned" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c04f5d74368e4d0dfe06c45c8627c81bd7c317d52762d118fb9b3076f6420fd" -[[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.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" -dependencies = [ - "num-traits", - "rand 0.8.5", - "serde", -] - [[package]] name = "parking" version = "2.2.1" @@ -5854,20 +2370,9 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", - "windows-link 0.2.1", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", + "windows-link", ] [[package]] @@ -5887,30 +2392,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pastey" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" - [[package]] name = "pathdiff" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", - "password-hash 0.4.2", - "sha2 0.10.9", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -5960,16 +2447,6 @@ dependencies = [ "sha2 0.10.9", ] -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap", -] - [[package]] name = "phf" version = "0.13.1" @@ -5989,26 +2466,20 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pico-args" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" - [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" dependencies = [ "proc-macro2", "quote", @@ -6021,88 +2492,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.11.0", - "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 0.2.17", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" -dependencies = [ - "serde", -] - -[[package]] -name = "portable-atomic-util" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" -dependencies = [ - "portable-atomic", -] - [[package]] name = "postcard" version = "1.1.3" @@ -6125,8 +2514,8 @@ dependencies = [ "base64 0.22.1", "byteorder", "bytes", - "fallible-iterator 0.2.0", - "hmac 0.13.0", + "fallible-iterator", + "hmac", "md-5", "memchr", "rand 0.10.1", @@ -6141,7 +2530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dc729a129e682e8d24170cd30ae1aa01b336b096cbb56df6d534ffec133d186" dependencies = [ "bytes", - "fallible-iterator 0.2.0", + "fallible-iterator", "postgres-protocol", ] @@ -6169,22 +2558,6 @@ dependencies = [ "zerocopy", ] -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" -dependencies = [ - "diff", - "yansi", -] - [[package]] name = "prettyplease" version = "0.2.37" @@ -6195,15 +2568,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "proc-macro-crate" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" -dependencies = [ - "toml_edit 0.25.11+spec-1.1.0", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -6283,25 +2647,6 @@ dependencies = [ "yansi", ] -[[package]] -name = "profiling" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -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 = [ - "quote", - "syn 2.0.117", -] - [[package]] name = "protocol" version = "0.1.0" @@ -6309,111 +2654,12 @@ dependencies = [ "serde", ] -[[package]] -name = "pulp" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e205bb30d5b916c55e584c22201771bcf2bad9aabd5d4127f38387140c38632" -dependencies = [ - "bytemuck", - "cfg-if", - "libm", - "num-complex", - "paste", - "pulp-wasm-simd-flag", - "raw-cpuid", - "reborrow", - "version_check", -] - -[[package]] -name = "pulp-wasm-simd-flag" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40e24eee682d89fb193496edf918a7f407d30175b2e785fe057e4392dfd182e0" - -[[package]] -name = "pxfm" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - [[package]] name = "qrcodegen" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.2", - "rustls", - "socket2", - "thiserror 2.0.18", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" -dependencies = [ - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.3", - "ring", - "rustc-hash 2.1.2", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.18", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - [[package]] name = "quote" version = "1.0.45" @@ -6445,6 +2691,12 @@ dependencies = [ "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" @@ -6457,57 +2709,22 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "r2d2" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" -dependencies = [ - "log", - "parking_lot", - "scheduled-thread-pool", -] - -[[package]] -name = "r2d2_sqlite" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63417e83dc891797eea3ad379f52a5986da4bca0d6ef28baf4d14034dd111b0c" -dependencies = [ - "r2d2", - "rusqlite", - "uuid", -] - [[package]] name = "rand" -version = "0.7.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg 0.2.1", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", - "serde", ] [[package]] name = "rand" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ec095654a25171c2124e9e3393a930bddbffdc939556c914957a4c3e0a87166" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -6519,19 +2736,9 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "chacha20 0.10.0", + "chacha20", "getrandom 0.4.2", - "rand_core 0.10.0", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_core 0.10.1", ] [[package]] @@ -6554,12 +2761,6 @@ dependencies = [ "rand_core 0.9.5", ] -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" - [[package]] name = "rand_core" version = "0.6.4" @@ -6567,7 +2768,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.17", - "serde", ] [[package]] @@ -6581,174 +2781,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" - -[[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.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.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 = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "range-alloc" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" - -[[package]] -name = "ratatui" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" -dependencies = [ - "bitflags 2.11.0", - "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.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" -dependencies = [ - "aligned-vec", - "arbitrary", - "arg_enum_proc_macro", - "arrayvec 0.7.6", - "av-scenechange", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.14.0", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "paste", - "profiling", - "rand 0.9.3", - "rand_chacha 0.9.0", - "simd_helpers", - "thiserror 2.0.18", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - -[[package]] -name = "raw-cpuid" -version = "11.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" -dependencies = [ - "bitflags 2.11.0", -] - -[[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.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "reactive_graph" @@ -6763,7 +2798,7 @@ dependencies = [ "hydration_context", "or_poisoned", "pin-project-lite", - "rustc-hash 2.1.2", + "rustc-hash", "send_wrapper", "serde", "slotmap", @@ -6778,12 +2813,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aadc7c19e3a360bf19cd595d2dc8b58ce67b9240b95a103fbc1317a8ff194237" dependencies = [ "guardian", - "itertools 0.14.0", + "itertools", "or_poisoned", "paste", "reactive_graph", "reactive_stores_macro", - "rustc-hash 2.1.2", + "rustc-hash", ] [[package]] @@ -6799,39 +2834,13 @@ dependencies = [ "syn 2.0.117", ] -[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_syscall" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 2.0.18", + "bitflags", ] [[package]] @@ -6872,12 +2881,6 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - [[package]] name = "relay-server" version = "0.1.0" @@ -6888,9 +2891,10 @@ dependencies = [ "bytes", "deadpool-postgres", "futures-util", + "lettre", "postcard", "protocol", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "thiserror 1.0.69", @@ -6903,81 +2907,6 @@ dependencies = [ "tracing-subscriber", ] -[[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 = [ - "bytes", - "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 = "reqwest" -version = "0.12.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http 1.4.0", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 1.0.6", -] - -[[package]] -name = "rgb" -version = "0.8.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" - [[package]] name = "ring" version = "0.17.14" @@ -6992,60 +2921,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ringbuffer" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6368f71f205ff9c33c076d170dd56ebf68e8161c733c0caa07a7a5509ed53" - -[[package]] -name = "rmp" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "rmp-serde" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" -dependencies = [ - "rmp", - "serde", -] - -[[package]] -name = "rstest" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" -dependencies = [ - "futures-timer", - "futures-util", - "rstest_macros", -] - -[[package]] -name = "rstest_macros" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" -dependencies = [ - "cfg-if", - "glob", - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn 2.0.117", - "unicode-ident", -] - [[package]] name = "rstml" version = "0.12.1" @@ -7061,32 +2936,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "rusqlite" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" -dependencies = [ - "bitflags 2.11.0", - "fallible-iterator 0.3.0", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.2" @@ -7102,37 +2951,11 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", -] - [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "log", "once_cell", @@ -7145,19 +2968,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ - "web-time", "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.11" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -7176,36 +2998,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[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.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675656c1eabb620b921efea4f9199f97fc86e36dd6ffd1fbbe48d0f59a4987f5" -dependencies = [ - "hashbrown 0.16.1", - "serde", - "serde_json", -] - [[package]] name = "same-file" version = "1.0.6" @@ -7215,55 +3007,12 @@ dependencies = [ "winapi-util", ] -[[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sdl2" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" -dependencies = [ - "bitflags 1.3.2", - "c_vec", - "lazy_static", - "libc", - "sdl2-sys", -] - -[[package]] -name = "sdl2-sys" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" -dependencies = [ - "cfg-if", - "cmake", - "libc", - "version-compare", -] - [[package]] name = "semver" version = "1.0.28" @@ -7279,12 +3028,6 @@ dependencies = [ "futures-core", ] -[[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" @@ -7295,16 +3038,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_bytes" -version = "0.11.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" -dependencies = [ - "serde", - "serde_core", -] - [[package]] name = "serde_core" version = "1.0.228" @@ -7360,16 +3093,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "serde_rusqlite" -version = "0.40.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8bd74f47e124e760475a7e863b5820dcef09cae50782d03d65961f5ca1e6d9" -dependencies = [ - "rusqlite", - "serde_core", -] - [[package]] name = "serde_spanned" version = "0.6.9" @@ -7497,7 +3220,7 @@ checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "digest 0.11.2", + "digest 0.11.3", ] [[package]] @@ -7515,37 +3238,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" -dependencies = [ - "libc", - "mio", - "signal-hook 0.3.18", -] - [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -7556,39 +3248,11 @@ dependencies = [ "libc", ] -[[package]] -name = "simba" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95" -dependencies = [ - "approx", - "num-complex", - "num-traits", - "paste", - "wide", -] - -[[package]] -name = "simd-adler32" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" - -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" @@ -7605,16 +3269,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "slug" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" -dependencies = [ - "deunicode", - "wasm-bindgen", -] - [[package]] name = "smallvec" version = "1.15.1" @@ -7631,19 +3285,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "spiel_bot" -version = "0.1.0" -dependencies = [ - "anyhow", - "burn", - "criterion", - "rand 0.9.3", - "rand_distr", - "trictrac-bot", - "trictrac-store", -] - [[package]] name = "spin" version = "0.9.8" @@ -7653,43 +3294,12 @@ dependencies = [ "lock_api", ] -[[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.11.0", -] - -[[package]] -name = "stable-vec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dac7bc0f7d0d44329b200020effbc25a534d89fa142af95e3ddf76113412a5e" - [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strength_reduce" version = "0.2.4" @@ -7713,49 +3323,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros 0.26.4", -] - -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros 0.27.2", -] - -[[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.117", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "subtle" version = "2.6.1" @@ -7801,21 +3368,6 @@ name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] [[package]] name = "synstructure" @@ -7828,62 +3380,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "sysctl" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc" -dependencies = [ - "bitflags 2.11.0", - "byteorder", - "enum-as-inner", - "libc", - "thiserror 1.0.69", - "walkdir", -] - -[[package]] -name = "sysinfo" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d" -dependencies = [ - "libc", - "memchr", - "ntapi", - "objc2-core-foundation", - "objc2-io-kit", - "windows 0.61.3", -] - -[[package]] -name = "sysinfo" -version = "0.37.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" -dependencies = [ - "libc", - "memchr", - "ntapi", - "objc2-core-foundation", - "objc2-io-kit", - "windows 0.61.3", -] - -[[package]] -name = "systemstat" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e89b75de097d0c52a1dc2114e19439d55f0e2e42d32168c6df44f139dfb66f" -dependencies = [ - "bytesize", - "lazy_static", - "libc", - "nom 7.1.3", - "time", - "winapi", -] - [[package]] name = "tachys" version = "0.1.9" @@ -7899,7 +3395,7 @@ dependencies = [ "futures", "html-escape", "indexmap", - "itertools 0.14.0", + "itertools", "js-sys", "linear-map", "next_tuple", @@ -7910,7 +3406,7 @@ dependencies = [ "paste", "reactive_graph", "reactive_stores", - "rustc-hash 2.1.2", + "rustc-hash", "send_wrapper", "slotmap", "throw_error", @@ -7918,73 +3414,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "tar" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tch" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e09b91610202dc4820c21eb474a42b386ef69f323b1c0902b5472ba7456ebb5" -dependencies = [ - "half", - "lazy_static", - "libc", - "ndarray 0.16.1", - "rand 0.8.5", - "safetensors 0.3.3", - "thiserror 1.0.69", - "torch-sys", - "zip 0.6.6", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix 1.1.4", - "windows-sys 0.61.2", -] - -[[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]] -name = "textdistance" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa672c55ab69f787dbc9126cc387dbe57fdd595f585e4524cf89018fa44ab819" - [[package]] name = "thiserror" version = "1.0.69" @@ -8025,15 +3454,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "thread-tree" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbd370cb847953a25954d9f63e14824a36113f8c72eecf6eccef5dc4b45d630" -dependencies = [ - "crossbeam-channel", -] - [[package]] name = "thread_local" version = "1.1.9" @@ -8052,20 +3472,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "tiff" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" -dependencies = [ - "fax", - "flate2", - "half", - "quick-error", - "weezl", - "zune-jpeg", -] - [[package]] name = "time" version = "0.3.47" @@ -8074,9 +3480,7 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde_core", "time-core", @@ -8099,15 +3503,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinystr" version = "0.7.6" @@ -8128,16 +3523,6 @@ dependencies = [ "zerovec 0.11.6", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "tinyvec" version = "1.11.0" @@ -8155,9 +3540,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.51.1" +version = "1.52.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" +checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" dependencies = [ "bytes", "libc", @@ -8167,7 +3552,6 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "tracing", "windows-sys 0.61.2", ] @@ -8191,7 +3575,7 @@ dependencies = [ "async-trait", "byteorder", "bytes", - "fallible-iterator 0.2.0", + "fallible-iterator", "futures-channel", "futures-util", "log", @@ -8220,14 +3604,14 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" dependencies = [ "futures-util", "log", "tokio", - "tungstenite 0.28.0", + "tungstenite 0.29.0", ] [[package]] @@ -8252,22 +3636,7 @@ dependencies = [ "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", - "toml_edit 0.22.27", -] - -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap", - "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", + "toml_edit", ] [[package]] @@ -8280,7 +3649,7 @@ dependencies = [ "serde_spanned 1.1.1", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -8292,15 +3661,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -8324,25 +3684,13 @@ dependencies = [ "winnow 0.7.15", ] -[[package]] -name = "toml_edit" -version = "0.25.11+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" -dependencies = [ - "indexmap", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "winnow 1.0.1", -] - [[package]] name = "toml_parser" version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -8351,27 +3699,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" -[[package]] -name = "toml_writer" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" - -[[package]] -name = "torch-sys" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef40c585e342df95b66a1fa7c923188623999c2b657227befb481dfb03a6a42" -dependencies = [ - "anyhow", - "cc", - "libc", - "serde", - "serde_json", - "ureq", - "zip 0.6.6", -] - [[package]] name = "tower" version = "0.5.3" @@ -8406,11 +3733,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51" dependencies = [ - "bitflags 2.11.0", + "bitflags", "bytes", "futures-core", "futures-util", @@ -8419,17 +3746,14 @@ dependencies = [ "http-body-util", "http-range-header", "httpdate", - "iri-string", "mime", "mime_guess", "percent-encoding", "pin-project-lite", "tokio", "tokio-util", - "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -8474,7 +3798,7 @@ dependencies = [ "futures", "http 1.4.0", "parking_lot", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "thiserror 2.0.18", @@ -8495,85 +3819,6 @@ dependencies = [ "tower-sessions-core", ] -[[package]] -name = "tracel-llvm" -version = "20.1.4-7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982535db9eb1a30ac0f2c50239a0eec3e5cf50993a88e92b04747bd2f4d365b2" -dependencies = [ - "tracel-mlir-rs", - "tracel-mlir-sys", -] - -[[package]] -name = "tracel-llvm-bundler" -version = "20.1.4-7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c75b8e477cb8d49d907afab029ca74d48459f5b88c27bdb4c6cd6acb5e61977" -dependencies = [ - "anyhow", - "bytes", - "constcat", - "dirs", - "liblzma", - "regex", - "reqwest", - "serde", - "serde_json", - "sha2 0.10.9", - "tar", - "walkdir", -] - -[[package]] -name = "tracel-mlir-rs" -version = "20.1.4-7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a478a35efd68d0ba73f747adfb7923b121c64e7f5be9cd8364ca1dcb772d5c" -dependencies = [ - "tracel-mlir-rs-macros", - "tracel-mlir-sys", -] - -[[package]] -name = "tracel-mlir-rs-macros" -version = "20.1.4-7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a94f36868c3b10b1825945223d99d106c73f4d249f063caa4651deeb9379344" -dependencies = [ - "comrak", - "convert_case 0.8.0", - "proc-macro2", - "quote", - "regex", - "syn 2.0.117", - "tracel-llvm-bundler", - "tracel-tblgen-rs", - "unindent", -] - -[[package]] -name = "tracel-mlir-sys" -version = "20.1.4-7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f26d31af0c225a6d2e3d65d012fd6de848c9fc776897b152ee83b7d1bd15c4" -dependencies = [ - "tracel-llvm-bundler", -] - -[[package]] -name = "tracel-tblgen-rs" -version = "20.1.4-7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00d2581070380418ccc33b500f3739e4d4869421fdb477fcea51ff97c6253a52" -dependencies = [ - "bindgen", - "cc", - "paste", - "thiserror 2.0.18", - "tracel-llvm-bundler", -] - [[package]] name = "tracing" version = "0.1.44" @@ -8586,18 +3831,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-appender" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" -dependencies = [ - "crossbeam-channel", - "thiserror 2.0.18", - "time", - "tracing-subscriber", -] - [[package]] name = "tracing-attributes" version = "0.1.31" @@ -8658,41 +3891,6 @@ dependencies = [ "strength_reduce", ] -[[package]] -name = "trictrac-bot" -version = "0.1.0" -dependencies = [ - "board-game", - "burn", - "burn-rl", - "confy", - "env_logger 0.10.2", - "internal-iterator", - "log", - "pretty_assertions", - "rand 0.9.3", - "serde", - "serde_json", - "trictrac-store", -] - -[[package]] -name = "trictrac-client_cli" -version = "0.1.0" -dependencies = [ - "anyhow", - "bincode 1.3.3", - "env_logger 0.11.10", - "itertools 0.13.0", - "log", - "pico-args", - "pretty_assertions", - "renet", - "spiel_bot", - "trictrac-bot", - "trictrac-store", -] - [[package]] name = "trictrac-store" version = "0.1.0" @@ -8701,7 +3899,7 @@ dependencies = [ "base64 0.21.7", "log", "merge", - "rand 0.9.3", + "rand 0.9.4", "serde", "transpose", ] @@ -8721,21 +3919,16 @@ dependencies = [ "leptos_i18n", "leptos_router", "qrcodegen", - "rand 0.9.3", + "rand 0.9.4", "serde", "serde_json", "trictrac-store", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-bindgen-test", "web-sys", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "tungstenite" version = "0.24.0" @@ -8748,7 +3941,7 @@ dependencies = [ "http 1.4.0", "httparse", "log", - "rand 0.8.5", + "rand 0.8.6", "sha1", "thiserror 1.0.69", "utf-8", @@ -8756,36 +3949,20 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" dependencies = [ "bytes", "data-encoding", "http 1.4.0", "httparse", "log", - "rand 0.9.3", + "rand 0.9.4", "sha1", "thiserror 2.0.18", - "utf-8", ] -[[package]] -name = "type-map" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" -dependencies = [ - "rustc-hash 2.1.2", -] - -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - [[package]] name = "typed-builder" version = "0.20.1" @@ -8806,17 +3983,11 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "typed-path" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" - [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ucd-trie" @@ -8863,57 +4034,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" -[[package]] -name = "unicode-truncate" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" -dependencies = [ - "itertools 0.13.0", - "unicode-segmentation", - "unicode-width 0.1.14", -] - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -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" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "unindent" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common 0.1.7", - "subtle", -] - [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -8926,30 +4052,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - -[[package]] -name = "ureq" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" -dependencies = [ - "base64 0.22.1", - "flate2", - "log", - "once_cell", - "rustls", - "rustls-pki-types", - "serde", - "serde_json", - "url", - "webpki-roots 0.26.11", -] - [[package]] name = "url" version = "2.5.8" @@ -8992,32 +4094,14 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", - "rand 0.10.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", ] @@ -9027,41 +4111,12 @@ 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.117", -] - -[[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_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "walkdir" version = "2.5.0" @@ -9072,15 +4127,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -9098,11 +4144,11 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -9111,7 +4157,7 @@ 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", + "wit-bindgen 0.51.0", ] [[package]] @@ -9125,9 +4171,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -9138,9 +4184,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.68" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -9148,9 +4194,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9158,9 +4204,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -9171,13 +4217,52 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-bindgen-test" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af5ec93229ad9ccd0a545a516dec76dc276613f278f6a91aa6b463d5b33d42d0" +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.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c81b9fef827e575e0e54431736d1baa0d700315d8c62cfef1f61fa3aad0cbeb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "wasm-bindgen-test-shared" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4d8ae7ad5440360e9799dfd42857d126454a88441ddf72d288ef83fa47f527" + [[package]] name = "wasm-encoder" version = "0.244.0" @@ -9219,7 +4304,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags", "hashbrown 0.15.5", "indexmap", "semver", @@ -9227,9 +4312,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.95" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" dependencies = [ "js-sys", "wasm-bindgen", @@ -9245,199 +4330,20 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-user-portal" -version = "0.1.0" -dependencies = [ - "gloo-net 0.5.0", - "js-sys", - "leptos", - "leptos_router", - "serde", - "serde_json", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "webpki-roots" -version = "0.26.11" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.6", -] - -[[package]] -name = "webpki-roots" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] -[[package]] -name = "weezl" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" - -[[package]] -name = "wgpu" -version = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70b6ff82bbf6e9206828e1a3178e851f8c20f1c9028e74dd3a8090741ccd5798" -dependencies = [ - "arrayvec 0.7.6", - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "document-features", - "hashbrown 0.15.5", - "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 = "26.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f62f1053bd28c2268f42916f31588f81f64796e2ff91b81293515017ca8bd9" -dependencies = [ - "arrayvec 0.7.6", - "bit-set", - "bit-vec", - "bitflags 2.11.0", - "cfg_aliases", - "document-features", - "hashbrown 0.15.5", - "indexmap", - "log", - "naga", - "once_cell", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "rustc-hash 1.1.0", - "smallvec", - "thiserror 2.0.18", - "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 = "26.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18ae5fbde6a4cbebae38358aa73fcd6e0f15c6144b67ef5dc91ded0db125dbdf" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-emscripten" -version = "26.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7670e390f416006f746b4600fdd9136455e3627f5bd763abf9a65daa216dd2d" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-windows-linux-android" -version = "26.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "720a5cb9d12b3d337c15ff0e24d3e97ed11490ff3f7506e7f3d98c68fa5d6f14" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-hal" -version = "26.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d0e67224cc7305b3b4eb2cc57ca4c4c3afc665c1d1bee162ea806e19c47bdd" -dependencies = [ - "android_system_properties", - "arrayvec 0.7.6", - "ash", - "bit-set", - "bitflags 2.11.0", - "block", - "bytemuck", - "cfg-if", - "cfg_aliases", - "core-graphics-types", - "glow", - "glutin_wgl_sys", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hashbrown 0.15.5", - "js-sys", - "khronos-egl", - "libc", - "libloading", - "log", - "metal", - "naga", - "ndk-sys", - "objc", - "ordered-float 4.6.0", - "parking_lot", - "portable-atomic", - "portable-atomic-util", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "smallvec", - "thiserror 2.0.18", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "windows 0.58.0", - "windows-core 0.58.0", -] - -[[package]] -name = "wgpu-types" -version = "26.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca7a8d8af57c18f57d393601a1fb159ace8b2328f1b6b5f80893f7d672c9ae2" -dependencies = [ - "bitflags 2.11.0", - "bytemuck", - "js-sys", - "log", - "thiserror 2.0.18", - "web-sys", -] - [[package]] name = "whoami" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6a5b12f9df4f978d2cfdb1bd3bac52433f44393342d7ee9c25f5a1c14c0f45d" +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" dependencies = [ "libc", "libredox", @@ -9446,32 +4352,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wide" -version = "0.7.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" -dependencies = [ - "bytemuck", - "safe_arch", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -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.11" @@ -9481,209 +4361,19 @@ dependencies = [ "windows-sys 0.61.2", ] -[[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.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" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core 0.61.2", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", -] - -[[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 0.1.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading", -] - -[[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.117", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[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.117", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - -[[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-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - -[[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-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -9692,7 +4382,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -9701,40 +4391,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "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-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link 0.2.1", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -9743,96 +4407,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.7.15" @@ -9844,9 +4460,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] @@ -9860,6 +4476,12 @@ 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" @@ -9909,7 +4531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "bitflags", "indexmap", "log", "serde", @@ -9939,18 +4561,6 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "wrapcenum-derive" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76ff259533532054cfbaefb115c613203c73707017459206380f03b3b3f266e" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "write16" version = "1.0.0" @@ -9972,34 +4582,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" -[[package]] -name = "xattr" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" -dependencies = [ - "libc", - "rustix 1.1.4", -] - -[[package]] -name = "xml-rs" -version = "0.8.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" - [[package]] name = "xxhash-rust" version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" -[[package]] -name = "y4m" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" - [[package]] name = "yansi" version = "1.0.1" @@ -10038,7 +4626,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.117", - "synstructure 0.13.2", + "synstructure", ] [[package]] @@ -10050,7 +4638,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.117", - "synstructure 0.13.2", + "synstructure", ] [[package]] @@ -10091,7 +4679,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.117", - "synstructure 0.13.2", + "synstructure", ] [[package]] @@ -10166,93 +4754,8 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac 0.12.1", - "pbkdf2", - "sha1", - "time", - "zstd", -] - -[[package]] -name = "zip" -version = "7.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" -dependencies = [ - "crc32fast", - "indexmap", - "memchr", - "typed-path", -] - [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "zune-core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "zune-jpeg" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" -dependencies = [ - "zune-core", -] diff --git a/Cargo.toml b/Cargo.toml index 94a1c6b..e78d862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,25 +3,17 @@ resolver = "2" members = [ "store", - "clients/cli", "clients/backbone-lib", "clients/web", - "clients/web-game", - "clients/web-user-portal", "server/protocol", "server/relay-server", - "bot", - "spiel_bot", ] default-members = [ "store", - "clients/cli", "clients/backbone-lib", "server/protocol", "server/relay-server", - "bot", - "spiel_bot", ] # For the server we will need opt-level='3' diff --git a/README.md b/README.md index 4e7789f..ca4c0de 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ just build-relay just run-relay # listens on :8080 # Run the game (separate terminal) -just dev-game +just dev ``` Open two browser windows at `http://127.0.0.1:9091`. In one, create a room; in the other, join with the same room name. @@ -52,7 +52,7 @@ The game state is defined by the `GameState` struct in _store/src/game.rs_. The ### multiplayer game -Pagckages "clients/backbone-lib", "clients/web-game", "server/protocol", "server/relay-server" are a Leptos-optimized adaptation of the macroquad-based [Carbonfreezer/multiplayer](https://github.com/Carbonfreezer/multiplayer) project. It is a multiplayer game system in Rust targeting browser-based board games compiled as WASM. The original project used Macroquad with a polling-based transport layer; this version replaces that with an async session API built for [Leptos](https://leptos.dev/). +Packages "clients/backbone-lib", "clients/web/game", "server/protocol", "server/relay-server" are a Leptos-optimized adaptation of the macroquad-based [Carbonfreezer/multiplayer](https://github.com/Carbonfreezer/multiplayer) project. It is a multiplayer game system in Rust targeting browser-based board games compiled as WASM. The original project used Macroquad with a polling-based transport layer; this version replaces that with an async session API built for [Leptos](https://leptos.dev/). The system consists of: diff --git a/clients/web-game/Cargo.toml b/clients/web-game/Cargo.toml deleted file mode 100644 index 578be7c..0000000 --- a/clients/web-game/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "client_web" -version = "0.1.0" -edition = "2021" - -[package.metadata.leptos-i18n] -default = "en" -locales = ["en", "fr"] - -[dependencies] -leptos_i18n = { version = "0.5", features = ["csr", "interpolate_display"] } -trictrac-store = { path = "../../store" } -backbone-lib = { path = "../backbone-lib" } -leptos = { version = "0.7", features = ["csr"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1" -futures = "0.3" -rand = "0.9" -gloo-storage = "0.3" - -[target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen-futures = "0.4" -gloo-net = { version = "0.5", features = ["http"] } -gloo-timers = { version = "0.3", features = ["futures"] } -# getrandom 0.3 requires an explicit WASM backend; "wasm_js" uses window.crypto.getRandomValues. -# Must be a direct dependency (not just transitive) for the feature to take effect. -getrandom = { version = "0.3", features = ["wasm_js"] } -web-sys = { version = "0.3", features = [ - "RequestCredentials", - "AudioContext", - "AudioParam", - "AudioNode", - "AudioDestinationNode", - "AudioScheduledSourceNode", - "GainNode", - "OscillatorNode", - "OscillatorType", - "BaseAudioContext", - "HtmlAudioElement", -] } diff --git a/clients/web-game/Trunk.toml b/clients/web-game/Trunk.toml deleted file mode 100644 index bae5297..0000000 --- a/clients/web-game/Trunk.toml +++ /dev/null @@ -1,2 +0,0 @@ -[serve] -port = 9091 diff --git a/clients/web-game/assets/diceroll.mp3 b/clients/web-game/assets/diceroll.mp3 deleted file mode 100644 index b16adff..0000000 Binary files a/clients/web-game/assets/diceroll.mp3 and /dev/null differ diff --git a/clients/web-game/assets/style.css b/clients/web-game/assets/style.css deleted file mode 100644 index 341be19..0000000 --- a/clients/web-game/assets/style.css +++ /dev/null @@ -1,1213 +0,0 @@ -/* ── Google Fonts ───────────────────────────────────────────────────── */ -@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&family=Jost:wght@300;400;500&display=swap'); - -/* ── Design tokens ──────────────────────────────────────────────────── */ -:root { - --board-felt: #1d3d28; - --board-rail: #2a1508; - --field-ivory: #f0e6c8; - --field-burgundy: #7a1e2a; - --field-corner: #b8900a; - --checker-white: #f5edd8; - --checker-black: #1a0f06; - --checker-ring: #c8a448; - --ui-parchment: #f2e8d0; - --ui-parchment-dark: #e4d8b8; - --ui-ink: #2a1a08; - --ui-gold: #c8a448; - --ui-gold-dark: #8a6a28; - --ui-green-accent: #3a6b2a; - --ui-red-accent: #7a1e2a; - --font-display: 'Cormorant Garamond', Georgia, serif; - --font-ui: 'Jost', system-ui, sans-serif; -} - -/* ── Reset & base ──────────────────────────────────────────────────── */ -*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - -body { - font-family: var(--font-ui); - background: #8a7050; - background-image: - radial-gradient(ellipse at 20% 10%, rgba(80,48,16,0.35) 0%, transparent 60%), - radial-gradient(ellipse at 80% 90%, rgba(40,24,8,0.3) 0%, transparent 55%), - repeating-linear-gradient( - 45deg, transparent, transparent 3px, - rgba(0,0,0,0.03) 3px, rgba(0,0,0,0.03) 4px - ); - display: flex; - justify-content: center; - padding: 1.5rem; - min-height: 100vh; -} - -.hidden { display: none !important; } - -/* ── Login card (§11) ───────────────────────────────────────────────── */ -.login-card { - width: 340px; - margin-top: 5vh; - border-radius: 8px; - overflow: hidden; - box-shadow: - 0 20px 60px rgba(0,0,0,0.55), - 0 0 0 1px rgba(200,164,72,0.35), - 0 0 0 5px rgba(42,21,8,0.9), - 0 0 0 6px rgba(200,164,72,0.2); - background: var(--ui-parchment); -} - -/* Decorative header — row of triangular flèches like the actual board */ -.login-card-header { - height: 52px; - background: var(--board-felt); - position: relative; - overflow: hidden; -} - -.login-board-stripe { - position: absolute; - inset: 0; - /* Alternating burgundy/ivory triangles pointing down from the top */ - background: - repeating-linear-gradient( - 90deg, - var(--field-burgundy) 0, var(--field-burgundy) 50%, - var(--field-ivory) 50%, var(--field-ivory) 100% - ); - background-size: 34px 100%; - /* Clip into downward-pointing triangles */ - clip-path: polygon( - 0% 0%, 2.94% 100%, 5.88% 0%, 8.82% 100%, 11.76% 0%, - 14.7% 100%, 17.65% 0%, 20.59% 100%, 23.53% 0%, - 26.47% 100%, 29.41% 0%, 32.35% 100%, 35.29% 0%, - 38.24% 100%, 41.18% 0%, 44.12% 100%, 47.06% 0%, - 50% 100%, 52.94% 0%, 55.88% 100%, 58.82% 0%, - 61.76% 100%, 64.71% 0%, 67.65% 100%, 70.59% 0%, - 73.53% 100%, 76.47% 0%, 79.41% 100%, 82.35% 0%, - 85.29% 100%, 88.24% 0%, 91.18% 100%, 94.12% 0%, - 97.06% 100%, 100% 0% - ); - opacity: 0.9; -} - -.login-card-body { - display: flex; - flex-direction: column; - align-items: center; - gap: 0; - padding: 1.5rem 2rem 2rem; -} - -.login-lang-switcher { - align-self: flex-end; - margin-bottom: 0.75rem; -} - -/* Override lang-switcher colours for the parchment card */ -.login-card .lang-switcher button { - color: var(--ui-ink); - border-color: rgba(42,21,8,0.2); - opacity: 0.5; -} -.login-card .lang-switcher button.lang-active { - opacity: 1; - background: rgba(42,21,8,0.08); - border-color: rgba(42,21,8,0.35); -} - -.login-title { - font-family: var(--font-display); - font-size: 3.25rem; - font-weight: 600; - color: var(--ui-ink); - letter-spacing: 0.12em; - text-align: center; - line-height: 1; - margin-bottom: 0.3rem; -} - -.login-subtitle { - font-family: var(--font-display); - font-size: 0.85rem; - color: rgba(42,26,8,0.55); - text-align: center; - letter-spacing: 0.06em; - font-style: italic; - margin-bottom: 1.25rem; -} -.login-subtitle sup { - font-size: 0.65em; - vertical-align: super; -} - -.login-ornament { - color: var(--ui-gold); - font-size: 1rem; - opacity: 0.7; - margin-bottom: 1.25rem; - letter-spacing: 0.3em; - text-align: center; -} - -.error-msg { - color: #c03030; - font-size: 0.85rem; - text-align: center; - margin-bottom: 0.5rem; -} - -.login-input { - width: 100%; - padding: 0.55rem 0.85rem; - font-size: 0.95rem; - font-family: var(--font-ui); - border: 1px solid rgba(138,106,40,0.4); - border-radius: 5px; - background: rgba(255,252,240,0.8); - color: var(--ui-ink); - outline: none; - transition: border-color 0.15s, box-shadow 0.15s; - margin-bottom: 1rem; -} -.login-input:focus { - border-color: var(--ui-gold); - box-shadow: 0 0 0 3px rgba(200,164,72,0.2); -} - -.login-actions { - display: flex; - flex-direction: column; - gap: 0.55rem; - width: 100%; -} - -/* Login buttons styled as embossed wooden tiles */ -.login-btn { - width: 100%; - padding: 0.65rem 1rem; - font-family: var(--font-ui); - font-size: 0.9rem; - font-weight: 500; - letter-spacing: 0.04em; - border: none; - border-radius: 5px; - cursor: pointer; - transition: opacity 0.15s, transform 0.1s, box-shadow 0.15s; - position: relative; -} -.login-btn:disabled { opacity: 0.35; cursor: default; } -.login-btn:not(:disabled):hover { opacity: 0.92; transform: translateY(-1px); } -.login-btn:not(:disabled):active { transform: translateY(0); } - -.login-btn-primary { - background: linear-gradient(160deg, #4a7a38 0%, #2e5222 100%); - color: #e8f0e0; - box-shadow: 0 2px 6px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.12); -} -.login-btn-secondary { - background: linear-gradient(160deg, #3a2010 0%, #241408 100%); - color: #e4d4b4; - box-shadow: 0 2px 6px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.08); -} -.login-btn-bot { - background: linear-gradient(160deg, #2a4a6a 0%, #183050 100%); - color: #d0e0f0; - box-shadow: 0 2px 6px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.08); -} - -/* ── Connecting screen ──────────────────────────────────────────────── */ -.connecting { - font-family: var(--font-display); - font-size: 1.4rem; - font-style: italic; - margin-top: 4rem; - text-align: center; - color: var(--ui-parchment); - text-shadow: 0 1px 4px rgba(0,0,0,0.4); -} - -/* ── Game-action buttons ─────────────────────────────────────────────── */ -.btn { - padding: 0.5rem 1.25rem; - font-size: 0.95rem; - font-family: var(--font-ui); - font-weight: 500; - letter-spacing: 0.03em; - border: none; - border-radius: 4px; - cursor: pointer; - transition: opacity 0.15s, box-shadow 0.15s; -} -.btn:disabled { opacity: 0.4; cursor: default; } -.btn-primary { background: var(--ui-green-accent); color: #fff; } -.btn-secondary { background: var(--board-rail); color: #e8d8b8; } -.btn-bot { background: #2a5a7a; color: #fff; } -.btn:not(:disabled):hover { - opacity: 0.9; - box-shadow: 0 2px 6px rgba(0,0,0,0.25); -} - -/* ── Game container ─────────────────────────────────────────────────── */ -/* No width: 100% — let it size to content (the board wrapper, ~832px). - This keeps the board pinned at the same horizontal position whether or - not the side panel is visible, and aligns the status bar / score panels - with the board rather than with the viewport edge. */ -.game-container { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.6rem; -} - -/* ── Language switcher (in-game) ────────────────────────────────────── */ -.lang-switcher { display: flex; gap: 0.25rem; } - -.lang-switcher button { - font-size: 0.7rem; - font-family: var(--font-ui); - letter-spacing: 0.05em; - padding: 0.15rem 0.4rem; - border: 1px solid rgba(200,164,72,0.3); - border-radius: 3px; - background: transparent; - cursor: pointer; - color: var(--ui-parchment); - opacity: 0.55; -} -.lang-switcher button.lang-active { - opacity: 1; - font-weight: 500; - background: rgba(200,164,72,0.15); - border-color: rgba(200,164,72,0.6); -} - -/* ── Top bar ─────────────────────────────────────────────────────────── */ -.top-bar { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - color: var(--ui-parchment); - font-size: 0.85rem; - opacity: 0.8; -} - -.quit-link { - font-size: 0.8rem; - color: var(--ui-parchment); - text-decoration: underline; - text-underline-offset: 2px; - cursor: pointer; - opacity: 0.7; -} -.quit-link:hover { opacity: 1; } - -/* ── Game status bar (§10b) — above board ───────────────────────────── */ -.game-status { - font-family: var(--font-display); - font-size: 1.2rem; - font-style: italic; - color: var(--ui-parchment); - text-align: center; - letter-spacing: 0.04em; - padding: 0.2rem 1rem 0; - width: 100%; - text-shadow: 0 1px 4px rgba(0,0,0,0.4); -} - -/* ── Contextual sub-prompt (§8a) ────────────────────────────────────── */ -.game-sub-prompt { - font-family: var(--font-ui); - font-size: 0.72rem; - color: rgba(240,228,192,0.5); - text-align: center; - letter-spacing: 0.04em; - padding: 0.15rem 1rem 0; - width: 100%; -} - -/* ── Player score panel ─────────────────────────────────────────────── */ -/* Horizontal banner: name on the left, score bars expanding to fill the - board width — no more empty right half on large screens. */ -.player-score-panel { - background: var(--ui-parchment); - border-radius: 5px; - padding: 0.45rem 1.25rem; - font-size: 0.88rem; - box-shadow: 0 2px 6px rgba(0,0,0,0.25); - width: 100%; - border-top: 2px solid var(--ui-gold-dark); - display: flex; - align-items: center; - gap: 1.5rem; -} - -.player-score-header { - flex-shrink: 0; - min-width: 90px; -} - -.player-name { - font-family: var(--font-display); - font-weight: 600; - font-size: 1.05rem; - color: var(--ui-ink); - letter-spacing: 0.02em; -} - -/* Bars sit side-by-side (points | holes) filling remaining width */ -.score-bars { display: flex; flex-direction: row; gap: 1.5rem; flex: 1; align-items: center; } - -.score-bar-row { - display: flex; - align-items: center; - gap: 0.5rem; - flex: 1; -} - -.score-bar-label { - font-size: 0.75rem; - color: #665544; - width: 3rem; - text-align: right; - flex-shrink: 0; -} - -/* ── Points bar ─────────────────────────────────────────────────────── */ -.score-bar { - flex: 1; - max-width: 220px; - height: 8px; - background: rgba(0,0,0,0.1); - border-radius: 4px; - overflow: hidden; - flex-shrink: 0; -} - -.score-bar-fill { - height: 100%; - border-radius: 4px; - transition: width 0.35s ease-out; -} - -.score-bar-points { background: linear-gradient(90deg, var(--ui-green-accent), #5a9b3a); } - -.score-bar-value { - font-size: 0.75rem; - color: #665544; - min-width: 2.5rem; - font-variant-numeric: tabular-nums; -} - -/* ── Hole peg tracker (§7a) ─────────────────────────────────────────── */ -.peg-track { - display: flex; - align-items: center; - gap: 3px; - flex-shrink: 0; -} - -.peg-hole { - width: 10px; - height: 10px; - border-radius: 50%; - border: 1.5px solid rgba(138,106,40,0.45); - background: rgba(0,0,0,0.06); - flex-shrink: 0; - transition: background 0.3s ease-out, border-color 0.3s, box-shadow 0.3s; -} - -.peg-hole.filled { - background: var(--ui-gold); - border-color: var(--ui-gold-dark); - box-shadow: 0 0 4px rgba(200,164,72,0.6); -} - -.bredouille-badge { - font-size: 0.62rem; - font-weight: 500; - color: #fff8e0; - background: linear-gradient(135deg, #c88800, #8a5800); - border: 1px solid rgba(200,164,72,0.5); - border-radius: 3px; - padding: 0.1em 0.4em; - letter-spacing: 0.06em; - cursor: default; - box-shadow: 0 1px 3px rgba(0,0,0,0.25); -} - -/* ── Board + side panel ─────────────────────────────────────────────── */ -/* .board-and-panel is sized to the board wrapper only; the side panel is - positioned absolutely so it floats to the right without pushing the - board and breaking its horizontal alignment. */ -.board-and-panel { - position: relative; -} - -/* The side panel is anchored to the board's RIGHT edge. Scoring panel - wrappers inside it initially overlap the board; they slide to a peek - strip after a few seconds, and reveal fully on hover. */ -.side-panel { - position: absolute; - right: -8px; - top: 10px; - z-index: 20; - display: flex; - flex-direction: column; - gap: 0.5rem; - padding-top: 0.15rem; - pointer-events: none; /* pass board clicks through the empty area */ -} - -.action-buttons { display: flex; flex-direction: column; gap: 0.5rem; } - -/* ── Dice bar ───────────────────────────────────────────────────────── */ -.dice-bar { - display: flex; - align-items: center; - gap: 0.6rem; - padding: 0.4rem 0.6rem; - background: rgba(42,21,8,0.15); - border-radius: 6px; - border: 1px solid rgba(200,164,72,0.2); - width: fit-content; -} - -/* ── Die face (SVG) ─────────────────────────────────────────────────── */ - -/* §5a — vigorous tumble: die bounces in from a random rotation */ -@keyframes die-tumble { - 0% { transform: rotate(-45deg) scale(0.4) translateY(-8px); opacity: 0; } - 25% { transform: rotate(18deg) scale(1.22) translateY(0); opacity: 1; } - 45% { transform: rotate(-10deg) scale(0.91); } - 62% { transform: rotate(6deg) scale(1.06); } - 76% { transform: rotate(-3deg) scale(0.98); } - 88% { transform: rotate(1.5deg) scale(1.01); } - 100% { transform: rotate(0deg) scale(1); opacity: 1; } -} - -.die-face { - filter: drop-shadow(0 2px 3px rgba(0,0,0,0.3)); - animation: die-tumble 0.55s cubic-bezier(0.22, 0.61, 0.36, 1) both; -} - -.die-face rect { - fill: #fffef0; - stroke: #2a1a00; - stroke-width: 2; - transition: fill 0.18s, stroke 0.18s; -} -.die-face circle { - fill: #1a0a00; - transition: fill 0.18s; -} - -/* Bar die slot — centered in the board bar */ -.bar-die-slot { - display: flex; - align-items: center; - justify-content: center; -} - -/* Double glow (§5c) */ -.die-face.die-double rect { stroke: var(--ui-gold); stroke-width: 2.5; } -.die-face.die-double { - filter: drop-shadow(0 0 6px rgba(200,164,72,0.7)) drop-shadow(0 2px 3px rgba(0,0,0,0.3)); -} - -.die-face.die-used { animation: none; opacity: 0.55; } -.die-face.die-used rect { fill: #d4d0c4; stroke: #9a8a70; } -.die-face.die-used circle { fill: #9a8a70; } - -.die-face .die-question { fill: #1a0a00; font-family: sans-serif; } -.die-face.die-used .die-question { fill: #9a8a70; } - -/* ── Jan panel ──────────────────────────────────────────────────────── */ -.jan-panel { - display: flex; - flex-direction: column; - gap: 2px; - background: var(--ui-parchment); - border-radius: 5px; - padding: 0.4rem 0.9rem; - font-size: 0.88rem; - box-shadow: 0 1px 4px rgba(0,0,0,0.15); - min-width: 260px; - border-top: 2px solid rgba(138,106,40,0.35); -} - -.jan-row { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 2px 4px; - border-radius: 3px; -} -.jan-expandable { cursor: pointer; } -.jan-expandable:hover { background: rgba(0,0,0,0.05); } - -.jan-positive { color: #1a5c1a; } -.jan-negative { color: #8b1a1a; } - -.jan-label { flex: 1; } -.jan-tag { - font-size: 0.72rem; - padding: 0.1em 0.4em; - border-radius: 3px; - background: rgba(0,0,0,0.07); - color: #665544; - white-space: nowrap; -} -.jan-pts { font-weight: 600; text-align: right; min-width: 3rem; } - -.jan-moves { padding: 1px 4px 4px 1rem; display: flex; flex-direction: column; gap: 2px; } -.jan-moves.hidden { display: none; } -.jan-move-line { font-family: monospace; font-size: 0.78rem; color: #555; } - -/* ── Game-over overlay (§12) ────────────────────────────────────────── */ -.game-over-overlay { - position: fixed; - inset: 0; - background: rgba(0,0,0,0.65); - display: flex; - align-items: center; - justify-content: center; - z-index: 100; -} - -@keyframes game-over-appear { - from { transform: translateY(-24px) scale(0.94); opacity: 0; } - to { transform: translateY(0) scale(1); opacity: 1; } -} - -.game-over-box { - background: var(--ui-parchment); - border-radius: 8px; - padding: 2.5rem 3rem; - text-align: center; - box-shadow: 0 12px 40px rgba(0,0,0,0.5), 0 0 0 2px var(--ui-gold-dark); - display: flex; - flex-direction: column; - gap: 1.1rem; - min-width: 300px; - animation: game-over-appear 0.4s cubic-bezier(0.22, 0.61, 0.36, 1); -} - -.game-over-box h2 { - font-family: var(--font-display); - font-size: 2rem; - font-weight: 600; - color: var(--ui-ink); - letter-spacing: 0.06em; -} - -.game-over-winner { - font-family: var(--font-display); - font-size: 1.25rem; - color: var(--ui-green-accent); - font-style: italic; -} - -/* Final score ledger */ -.game-over-score { - display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - padding: 0.6rem 1rem; - background: rgba(0,0,0,0.05); - border-radius: 5px; - border: 1px solid rgba(138,106,40,0.2); -} - -.game-over-score-name { - font-family: var(--font-display); - font-size: 0.9rem; - color: #665544; - font-style: italic; - max-width: 80px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.game-over-score-nums { - font-family: var(--font-display); - font-size: 2.25rem; - font-weight: 600; - color: var(--ui-ink); - letter-spacing: 0.08em; - line-height: 1; -} - -.game-over-actions { display: flex; gap: 0.75rem; justify-content: center; } - -/* ── Scoring notification panel (§6b) ───────────────────────────────── */ - -/* ── Wrapper: handles slide-in → peek → reveal lifecycle ────────────── - The wrapper starts off-screen right (translateX(100%)), slides in on - mount via animation, then Leptos adds .peeked after 3.4s to slide it - back to a 28px peek strip. */ -@keyframes scoring-panel-enter { - from { transform: translateX(100%); } - to { transform: translateX(0); } -} - -.scoring-panel-wrapper { - /* width: 290px; */ - pointer-events: auto; - animation: scoring-panel-enter 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); - transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); - filter: drop-shadow(-4px 0 14px rgba(0,0,0,0.38)); -} - -/* Peeked: slide right by the full panel width so the board is 100% clear. - The panel's left portion stays visible in whatever free space exists to - the right of the board. */ -.scoring-panel-wrapper.peeked { - transform: translateX(100%); -} - -/* Click on the visible left strip → .revealed slides it back over the board. - A second click removes .revealed and returns to the peeked position. */ -.scoring-panel-wrapper.revealed { - transform: translateX(0); -} - -/* Pointer cursor on the peeked (clickable) strip */ -.scoring-panel-wrapper.peeked:not(.revealed) { - cursor: pointer; -} - -/* ── Inner panel card ─────────────────────────────────────────────────── */ -.scoring-panel { - background: var(--ui-parchment); - border-radius: 5px; - padding: 0.45rem 0.85rem; - font-size: 0.84rem; - box-shadow: 0 1px 4px rgba(0,0,0,0.15); - border-left: 3px solid var(--ui-green-accent); - display: flex; - flex-direction: column; - gap: 4px; - width: 100%; -} - -.scoring-total { - font-family: var(--font-display); - font-weight: 600; - font-size: 1rem; - color: #1a5c1a; - white-space: nowrap; -} - -.scoring-jan-row { - display: flex; - align-items: center; - gap: 0.4rem; - padding: 2px 3px; - border-radius: 3px; - cursor: default; - white-space: nowrap; -} -.scoring-jan-row:hover { background: rgba(0,0,0,0.05); } - -.scoring-panel-opp { border-left-color: var(--board-rail); } -.scoring-panel-opp .scoring-total { color: var(--ui-red-accent); } - -.scoring-hole { - display: flex; - align-items: center; - gap: 0.4rem; - font-weight: 600; - color: var(--ui-red-accent); - margin-top: 3px; - padding-top: 4px; - border-top: 1px solid rgba(0,0,0,0.1); -} - -.hold-go-buttons { display: flex; gap: 0.5rem; margin-top: 4px; } - -/* ── Large-screen layout: panel in free space, no peek needed ───────── - Threshold: board (832) + body-padding (48) + panel-gap (16) + panel (290) - + symmetric left margin = 1492 px. - At this width the panel fits entirely to the right of the board. */ -@media (min-width: 1492px) { - .side-panel { - right: auto; - left: calc(100% + 1rem); /* outside board, no overlap */ - } - /* Already fully visible in free space — peeked/revealed are no-ops. */ - .scoring-panel-wrapper.peeked, - .scoring-panel-wrapper.revealed { - transform: none; - cursor: default; - } -} - -/* ── Board wrapper ──────────────────────────────────────────────────── */ -.board-wrapper { - display: flex; - flex-direction: column; - gap: 3px; -} - -/* ── Zone labels (§2a) — aligned with board quarters ───────────────── */ -/* Board border(4) + padding(4) = 8px inset each side */ -.zone-labels-row { - display: flex; - gap: 4px; - padding: 0 8px; -} - -.zone-label { - font-family: var(--font-display); - font-size: 0.57rem; - font-style: italic; - color: rgba(240,228,192,0.48); - letter-spacing: 0.1em; - text-align: center; - pointer-events: none; - line-height: 1; -} - -.zone-label-quarter { width: 370px; flex-shrink: 0; } -.zone-label-bar { width: 68px; flex-shrink: 0; } - -/* ── Board ──────────────────────────────────────────────────────────── */ -.board { - background: var(--board-felt); - border: 4px solid var(--board-rail); - border-radius: 6px; - padding: 4px; - display: flex; - flex-direction: column; - gap: 4px; - user-select: none; - box-shadow: - 0 6px 16px rgba(0,0,0,0.5), - inset 0 1px 0 rgba(255,255,255,0.04); - position: relative; -} - -.board-row { display: flex; gap: 4px; } -.board-quarter { display: flex; gap: 2px; } - -.board-bar { - width: 68px; - background: var(--board-rail); - border-radius: 4px; - box-shadow: inset 0 0 6px rgba(0,0,0,0.5); - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - overflow: visible; -} - -.board-center-bar { - height: 12px; - background: var(--board-rail); - border-radius: 2px; - box-shadow: inset 0 0 4px rgba(0,0,0,0.4); -} - -/* ── Fields (§1) ────────────────────────────────────────────────────── */ -/* - * Each field is a transparent rectangle over the felt. - * The triangular flèche is drawn by ::before using clip-path. - * --fc controls the triangle colour; z-index:-1 keeps the triangle - * behind checkers; isolation:isolate confines the negative z-index. - */ -.field { - --fc: var(--field-ivory); /* default triangle colour */ - width: 60px; - height: 180px; - background: transparent; /* felt shows through between triangle tips */ - isolation: isolate; /* stacking context for z-index:-1 ::before */ - border-radius: 3px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-end; - padding: 4px 2px; - position: relative; -} - -/* Bot-row triangle: wide base at bottom, tip at top */ -.field::before { - content: ''; - position: absolute; - inset: 0; - z-index: -1; /* behind checkers & corner crown */ - background: var(--fc); - clip-path: polygon(0% 100%, 50% 0%, 100% 100%); - transition: background 0.12s; -} - -/* Top-row triangle: wide base at top, tip at bottom */ -.top-row .field::before { - clip-path: polygon(0% 0%, 100% 0%, 50% 100%); -} - -.top-row .field { justify-content: flex-start; } - -/* ── Zone alternating colours (§2b) ────────────────────────────────── */ -/* petit-jan and grand-jan: burgundy / ivory */ -.board-quarter .field.zone-petit:nth-child(odd), -.board-quarter .field.zone-grand:nth-child(odd) { --fc: var(--field-burgundy); } -.board-quarter .field.zone-petit:nth-child(even), -.board-quarter .field.zone-grand:nth-child(even) { --fc: var(--field-ivory); } - -/* Opponent's grand-jan — deep slate-blue / silvery-green ivory. - Previously #1e3d32 was nearly identical to the felt (#1d3d28); now using - a clearly distinguishable cool blue that reads well against the green. */ -.board-quarter .field.zone-opponent:nth-child(odd) { --fc: #1a4f72; } -.board-quarter .field.zone-opponent:nth-child(even) { --fc: #e5eadc; } - -/* Jan de retour — warmer: amber-brown / warm amber ivory */ -.board-quarter .field.zone-retour:nth-child(odd) { --fc: #6a2810; } -.board-quarter .field.zone-retour:nth-child(even) { --fc: #f2dfa0; } - -/* ── Rest corner — before .clickable so green wins when interactive ── */ -/* .field.corner { --fc: var(--field-corner) !important; } */ - -/* Crown glyph sits behind checkers (z-index:-1) so it shows only on empty corners */ -.field.corner::after { - content: '♛'; - position: absolute; - z-index: -1; - bottom: 22px; - font-size: 0.7rem; - color: rgba(255,248,210,0.38); - pointer-events: none; - line-height: 1; -} -.top-row .field.corner::after { bottom: auto; top: 22px; } - -/* Corner pulse (§8d) — filter respects the triangle shape */ -@keyframes corner-pulse { - 0%, 100% { filter: drop-shadow(0 0 0px rgba(200,164,72,0)); } - 50% { filter: drop-shadow(0 0 7px rgba(200,164,72,0.55)); } -} -.field.corner.corner-available { - animation: corner-pulse 1.5s ease-in-out infinite; -} - -/* ── Exit-eligible highlight (§8c) — filter glow on triangle ───────── */ -@keyframes exit-glow { - 0%, 100% { filter: drop-shadow(0 0 0px rgba(232,192,96,0)); } - 50% { filter: drop-shadow(0 0 5px rgba(232,192,96,0.5)); } -} -.field.exit-eligible { - animation: exit-glow 2s ease-in-out infinite; -} - -/* ── §6c — Jan hover field highlight ────────────────────────────────── */ -.field.jan-hovered { - --fc: rgba(190, 140, 35, 0.8) !important; -} - -/* ── §6e — Hit (battue) ripple ──────────────────────────────────────── */ -@keyframes hit-ripple { - from { transform: translate(-50%, -50%) scale(0.4); opacity: 0.9; } - to { transform: translate(-50%, -50%) scale(2.2); opacity: 0; } -} -.hit-ripple { - position: absolute; - left: 50%; - width: 36px; - height: 36px; - border-radius: 50%; - border: 2px solid rgba(200, 164, 72, 0.9); - pointer-events: none; - animation: hit-ripple 0.5s ease-out forwards; -} -.hit-ripple-top { top: 26px; } -.hit-ripple-bot { bottom: 26px; } - -/* ── Interactive states — after .corner to take visual priority ─────── */ -.field.clickable { - cursor: pointer; - --fc: #8fc840 !important; -} -.field.clickable:hover { --fc: #74aa28 !important; } -.field.selected { - --fc: #5a8a18 !important; - outline: 2px solid rgba(255,255,255,0.3); - outline-offset: -2px; -} - -/* ── Field numbers ──────────────────────────────────────────────────── */ -.field-num { - font-size: 0.58rem; - color: rgba(0,0,0,0.28); - position: absolute; - bottom: 3px; - line-height: 1; - font-variant-numeric: tabular-nums; -} - -.board-quarter .field.zone-petit:nth-child(odd) .field-num, -.board-quarter .field.zone-grand:nth-child(odd) .field-num, -.board-quarter .field.zone-retour:nth-child(odd) .field-num, -.board-quarter .field.zone-opponent:nth-child(odd) .field-num { - color: rgba(240,215,190,0.38); -} - -.field.corner .field-num { color: rgba(255,248,200,0.4); } - -.top-row .field-num { bottom: auto; top: 3px; } - -/* ── Checkers ───────────────────────────────────────────────────────── */ -.checker-stack { - display: flex; - flex-direction: column; - align-items: center; -} - -.checker { - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 0.78rem; - font-weight: 600; - flex-shrink: 0; -} - -.checker + .checker { margin-top: -4px; } - -.checker.white { - background-image: - radial-gradient(ellipse 50% 35% at 36% 30%, - rgba(255,255,255,0.65) 0%, transparent 100%), - radial-gradient(circle, - transparent 68%, rgba(160,130,70,0.22) 68.5%, - rgba(160,130,70,0.22) 71.5%, transparent 72%), - radial-gradient(circle, - transparent 43%, rgba(160,130,70,0.17) 43.5%, - rgba(160,130,70,0.17) 46.5%, transparent 47%), - radial-gradient(circle at 38% 32%, - #ffffff 0%, var(--checker-white) 52%, #c0b288 100%); - border: 1.8px solid var(--checker-ring); - box-shadow: - 0 2px 6px rgba(0,0,0,0.4), - inset 0 -1px 3px rgba(0,0,0,0.15); - color: #443322; -} - -.checker.black { - background-image: - radial-gradient(ellipse 40% 28% at 36% 30%, - rgba(110,65,30,0.38) 0%, transparent 100%), - radial-gradient(circle, - transparent 68%, rgba(200,164,72,0.18) 68.5%, - rgba(200,164,72,0.18) 71.5%, transparent 72%), - radial-gradient(circle, - transparent 43%, rgba(200,164,72,0.13) 43.5%, - rgba(200,164,72,0.13) 46.5%, transparent 47%), - radial-gradient(circle at 38% 32%, - #4a2e1a 0%, #1c1008 45%, var(--checker-black) 100%); - border: 1.8px solid var(--checker-ring); - box-shadow: - 0 2px 6px rgba(0,0,0,0.55), - inset 0 -1px 3px rgba(0,0,0,0.4); - color: #c8b898; -} - -/* ── Hole toast (§6a) ───────────────────────────────────────────────── */ -@keyframes toast-rise { - from { transform: translate(-50%, -40%); opacity: 0; } - to { transform: translate(-50%, -50%); opacity: 1; } -} -@keyframes toast-fade { - from { opacity: 1; } - to { opacity: 0; pointer-events: none; } -} - -.hole-toast { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: rgba(22,10,2,0.93); - border: 2px solid var(--ui-gold); - border-radius: 8px; - padding: 1.5rem 3.5rem; - text-align: center; - z-index: 50; - pointer-events: none; - box-shadow: - 0 12px 40px rgba(0,0,0,0.65), - 0 0 0 1px rgba(200,164,72,0.25), - inset 0 1px 0 rgba(200,164,72,0.1); - animation: - toast-rise 0.25s cubic-bezier(0.22, 0.61, 0.36, 1), - toast-fade 0.5s ease-in 1.4s forwards; -} - -.hole-toast-title { - font-family: var(--font-display); - font-size: 3.25rem; - font-weight: 600; - color: var(--ui-gold); - letter-spacing: 0.1em; - line-height: 1; -} - -.hole-toast-count { - font-family: var(--font-display); - font-size: 1.1rem; - color: rgba(200,164,72,0.68); - margin-top: 0.35rem; - letter-spacing: 0.06em; -} - -.hole-toast-bredouille { - font-family: var(--font-ui); - font-size: 0.75rem; - letter-spacing: 0.08em; - color: rgba(200,164,72,0.55); - margin-top: 0.4rem; - text-transform: uppercase; -} - -/* ── Bredouille toast variant (§6d) — gold shimmer, larger entrance ─── */ -@keyframes bredouille-shimmer { - 0%, 100% { box-shadow: 0 12px 40px rgba(0,0,0,0.65), 0 0 0 2px rgba(200,164,72,0.4), inset 0 0 0 rgba(200,164,72,0); } - 50% { box-shadow: 0 12px 40px rgba(0,0,0,0.65), 0 0 0 4px rgba(200,164,72,0.7), inset 0 0 24px rgba(200,164,72,0.08); } -} -.hole-toast.hole-toast-bredouille { - border-width: 2.5px; - border-color: var(--ui-gold); - padding: 2rem 4rem; - animation: - toast-rise 0.3s cubic-bezier(0.22, 0.61, 0.36, 1), - bredouille-shimmer 0.9s ease-in-out 0.3s 2, - toast-fade 0.5s ease-in 2.2s forwards; -} -.hole-toast.hole-toast-bredouille .hole-toast-title { - font-size: 3.75rem; -} -.hole-toast.hole-toast-bredouille .hole-toast-bredouille { - font-size: 0.85rem; - color: rgba(200,164,72,0.8); - letter-spacing: 0.14em; -} - -/* ── §4a — Checker slide animation ─────────────────────────────────── */ -@keyframes checker-slide-in { - from { transform: translate(var(--slide-dx, 0px), var(--slide-dy, 0px)); } - to { transform: none; } -} -/* Only the arriving (outermost) checker animates; --slide-dx/dy are set - as inline styles on that element at render time, so no flash occurs. */ -.checker.arriving { - animation: checker-slide-in 0.28s cubic-bezier(0.25, 0.46, 0.45, 0.94); -} -/* Lift the field that owns an arriving checker above its siblings so the - checker doesn't slide under adjacent fields (isolation:isolate traps - z-index within each field's stacking context). */ -.field:has(.checker.arriving) { - isolation: auto; - z-index: 10; - position: relative; -} - -/* ── Checker lift on selected field (§4b) ───────────────────────────── */ -.field.selected .checker-stack { - transform: translateY(-5px); - filter: drop-shadow(0 8px 12px rgba(0,0,0,0.6)); - transition: transform 0.12s ease-out, filter 0.12s ease-out; -} - -/* ── Action buttons below board (§10c) ──────────────────────────────── */ -.board-actions { - display: flex; - gap: 0.55rem; - justify-content: center; - align-items: center; - flex-wrap: wrap; - min-height: 2rem; /* reserve height so layout doesn't shift when buttons appear */ -} - -/* ── Pre-game ceremony overlay ──────────────────────────────────────────── */ -.ceremony-overlay { - position: fixed; - inset: 0; - background: rgba(0,0,0,0.65); - display: flex; - align-items: center; - justify-content: center; - z-index: 100; -} - -.ceremony-box { - background: var(--ui-parchment); - border-radius: 8px; - padding: 2.5rem 3rem; - text-align: center; - box-shadow: 0 12px 40px rgba(0,0,0,0.5), 0 0 0 2px var(--ui-gold-dark); - display: flex; - flex-direction: column; - align-items: center; - gap: 1.4rem; - min-width: 300px; - animation: game-over-appear 0.4s cubic-bezier(0.22, 0.61, 0.36, 1); -} - -.ceremony-box h2 { - font-family: var(--font-display); - font-size: 1.8rem; - font-weight: 600; - color: var(--ui-ink); - letter-spacing: 0.06em; -} - -.ceremony-dice { - display: flex; - gap: 3rem; - align-items: flex-end; -} - -.ceremony-die-slot { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.5rem; -} - -.ceremony-die-label { - font-family: var(--font-ui); - font-size: 0.85rem; - color: var(--ui-ink); - font-weight: 500; -} - -.ceremony-tie { - font-family: var(--font-display); - font-size: 1rem; - color: var(--ui-red-accent); - font-style: italic; -} - - -.auth-badge { - font-size: 0.8rem; - text-align: center; - padding: 0.35rem 0.6rem; - border-radius: 5px; -} -.auth-badge--in { background: rgba(96,165,250,0.15); color: #93c5fd; } -.auth-badge--out { background: rgba(148,163,184,0.1); color: #64748b; } -.auth-badge a { color: #60a5fa; } - -.playing-as { - font-size: 0.8rem; - color: #64748b; - text-align: center; -} diff --git a/clients/web-game/index.html b/clients/web-game/index.html deleted file mode 100644 index 7399dbc..0000000 --- a/clients/web-game/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Trictrac - - - - - - diff --git a/clients/web-game/locales/en.json b/clients/web-game/locales/en.json deleted file mode 100644 index c29121d..0000000 --- a/clients/web-game/locales/en.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "room_name_placeholder": "Room name", - "create_room": "Create Room", - "join_room": "Join Room", - "connecting": "Connecting…", - "game_over": "Game over", - "waiting_for_opponent": "Waiting for opponent…", - "your_turn_roll": "Your turn — roll the dice", - "hold_or_go": "Hold or Go?", - "select_move": "Move a checker ({{ n }} of 2)", - "your_turn": "Your turn", - "opponent_turn": "Opponent's turn", - "room_label": "Room: {{ id }}", - "quit": "Quit", - "roll_dice": "Roll dice", - "go": "Go", - "empty_move": "Empty move", - "you_suffix": " (you)", - "points_label": "Points", - "holes_label": "Holes", - "bredouille_title": "Can bredouille", - "jan_double": "double", - "jan_simple": "simple", - "jan_filled_quarter": "Quarter filled", - "jan_true_hit_small": "True hit (small jan)", - "jan_true_hit_big": "True hit (big jan)", - "jan_true_hit_corner": "True hit (opp. corner)", - "jan_first_exit": "First to exit", - "jan_six_tables": "Six tables", - "jan_two_tables": "Two tables", - "jan_mezeas": "Mezeas", - "jan_false_hit_small": "False hit (small jan)", - "jan_false_hit_big": "False hit (big jan)", - "jan_contre_two": "Contre two tables", - "jan_contre_mezeas": "Contre mezeas", - "jan_helpless_man": "Helpless man", - "play_vs_bot": "Play vs Bot", - "vs_bot_label": "vs Bot", - "you_win": "You win!", - "opp_wins": "{{ name }} wins!", - "play_again": "Play again", - "after_opponent_roll": "Opponent rolled", - "after_opponent_go": "Opponent chose to continue", - "after_opponent_move": "Opponent moved — your turn", - "after_opponent_pre_game_roll": "Opponent rolled — your turn", - "pre_game_roll_title": "Who goes first?", - "pre_game_roll_btn": "Roll", - "pre_game_roll_tie": "Tie! Roll again", - "pre_game_roll_your_die": "Your die", - "pre_game_roll_opp_die": "Opponent's die", - "continue_btn": "Continue", - "scored_pts": "+{{ n }} pts", - "hole_made": "Hole! {{ holes }}/12", - "bredouille_applied": "Bredouille!", - "hold": "Hold", - "opp_scored_pts": "Opponent +{{ n }} pts", - "opp_hole_made": "Opponent hole! {{ holes }}/12", - "hint_move": "Click a highlighted field to move a checker", - "hint_hold_or_go": "Hold to keep points — Go to reset the setting", - "hint_continue": "Click Continue when ready" -} diff --git a/clients/web-game/locales/fr.json b/clients/web-game/locales/fr.json deleted file mode 100644 index 93f76e5..0000000 --- a/clients/web-game/locales/fr.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "room_name_placeholder": "Nom de la salle", - "create_room": "Créer une salle", - "join_room": "Rejoindre", - "connecting": "Connexion en cours…", - "game_over": "Partie terminée", - "waiting_for_opponent": "En attente de l'adversaire…", - "your_turn_roll": "À votre tour — lancez les dés", - "hold_or_go": "Tenir ou s'en aller ?", - "select_move": "Déplacez une dame ({{ n }} sur 2)", - "your_turn": "Votre tour", - "opponent_turn": "Tour de l'adversaire", - "room_label": "Salle : {{ id }}", - "quit": "Quitter", - "roll_dice": "Lancer les dés", - "go": "S'en aller", - "empty_move": "Mouvement impossible", - "you_suffix": " (vous)", - "points_label": "Points", - "holes_label": "Trous", - "bredouille_title": "Peut faire bredouille", - "jan_double": "double", - "jan_simple": "simple", - "jan_filled_quarter": "Remplissage", - "jan_true_hit_small": "Battage à vrai (petit jan)", - "jan_true_hit_big": "Battage à vrai (grand jan)", - "jan_true_hit_corner": "Battage coin adverse", - "jan_first_exit": "Premier sorti", - "jan_six_tables": "Jan de six tables", - "jan_two_tables": "Jan de deux tables", - "jan_mezeas": "Jan de mézéas", - "jan_false_hit_small": "Battage à faux (petit jan)", - "jan_false_hit_big": "Battage à faux (grand jan)", - "jan_contre_two": "Contre jan de deux tables", - "jan_contre_mezeas": "Contre jan de mezeas", - "jan_helpless_man": "Dame impuissante", - "play_vs_bot": "Jouer contre le bot", - "vs_bot_label": "contre le bot", - "you_win": "Vous avez gagné !", - "opp_wins": "{{ name }} gagne !", - "play_again": "Rejouer", - "after_opponent_roll": "L'adversaire a lancé les dés", - "after_opponent_go": "L'adversaire s'en va", - "after_opponent_move": "L'adversaire a joué — à vous", - "after_opponent_pre_game_roll": "L'adversaire a lancé — à vous", - "pre_game_roll_title": "Qui joue en premier ?", - "pre_game_roll_btn": "Lancer", - "pre_game_roll_tie": "Égalité ! Relancez", - "pre_game_roll_your_die": "Votre dé", - "pre_game_roll_opp_die": "Dé adverse", - "continue_btn": "Continuer", - "scored_pts": "+{{ n }} pts", - "hole_made": "Trou ! {{ holes }}/12", - "bredouille_applied": "Bredouille !", - "hold": "Tenir", - "opp_scored_pts": "Adversaire +{{ n }} pts", - "opp_hole_made": "Trou adverse ! {{ holes }}/12", - "hint_move": "Cliquez un champ surligné pour déplacer", - "hint_hold_or_go": "Tenir pour garder les points — S'en aller pour repartir", - "hint_continue": "Cliquez Continuer quand vous êtes prêt" -} diff --git a/clients/web-game/src/app.rs b/clients/web-game/src/app.rs deleted file mode 100644 index ce355f4..0000000 --- a/clients/web-game/src/app.rs +++ /dev/null @@ -1,726 +0,0 @@ -use futures::channel::mpsc; -use futures::{FutureExt, StreamExt}; -use gloo_storage::{LocalStorage, Storage}; -use leptos::prelude::*; -use leptos::task::spawn_local; -use serde::{Deserialize, Serialize}; - -use backbone_lib::session::{ConnectError, GameSession, RoomConfig, RoomRole, SessionEvent}; -use backbone_lib::traits::{BackEndArchitecture, BackendCommand, ViewStateUpdate}; - -use crate::components::{ConnectingScreen, GameScreen, LoginScreen}; -use crate::i18n::I18nContextProvider; -use crate::trictrac::backend::TrictracBackend; -use crate::trictrac::bot_local::bot_decide; -use crate::trictrac::types::{ - GameDelta, JanEntry, PlayerAction, ScoredEvent, SerStage, SerTurnStage, ViewState, -}; -use trictrac_store::CheckerMove; - -use std::collections::VecDeque; - -const RELAY_URL: &str = "ws://localhost:8080/ws"; -const GAME_ID: &str = "trictrac"; -const STORAGE_KEY: &str = "trictrac_session"; - -// In debug builds trunk serves on 9091, relay is on 8080. -// In release the game is served by the relay itself — use relative paths. -#[cfg(debug_assertions)] -const HTTP_BASE: &str = "http://localhost:8080"; -#[cfg(not(debug_assertions))] -const HTTP_BASE: &str = ""; - -/// The state the UI needs to render the game screen. -#[derive(Clone, PartialEq)] -pub struct GameUiState { - pub view_state: ViewState, - /// 0 = host, 1 = guest - pub player_id: u16, - pub room_id: String, - pub is_bot_game: bool, - /// True when this state is a buffered snapshot awaiting player confirmation. - pub waiting_for_confirm: bool, - /// Why we are paused — drives the status-bar message in GameScreen. - pub pause_reason: Option, - /// Points scored by this player in the transition to this state (if any). - pub my_scored_event: Option, - pub opp_scored_event: Option, - /// Checker moves to animate on this render. None when board is unchanged. - pub last_moves: Option<(CheckerMove, CheckerMove)>, -} - -/// Reason the UI is paused waiting for the player to click Continue. -#[derive(Clone, Debug, PartialEq)] -pub enum PauseReason { - AfterOpponentRoll, - AfterOpponentGo, - AfterOpponentMove, - /// Opponent rolled their die in the pre-game ceremony. - AfterOpponentPreGameRoll, -} - -/// Which screen is currently shown. -#[derive(Clone, PartialEq)] -pub enum Screen { - Login { error: Option }, - Connecting, - Playing(GameUiState), -} - -/// Commands sent from UI event handlers into the network task. -pub enum NetCommand { - CreateRoom { - room: String, - }, - JoinRoom { - room: String, - }, - Reconnect { - relay_url: String, - game_id: String, - room_id: String, - token: u64, - host_state: Option>, - }, - PlayVsBot, - Action(PlayerAction), - Disconnect, -} - -/// Stored in localStorage to reconnect after a page refresh. -#[derive(Serialize, Deserialize)] -struct StoredSession { - relay_url: String, - game_id: String, - room_id: String, - token: u64, - #[serde(default)] - is_host: bool, - #[serde(default)] - view_state: Option, -} - -#[derive(Deserialize)] -struct MeResponse { - username: String, -} - -fn save_session(session: &StoredSession) { - LocalStorage::set(STORAGE_KEY, session).ok(); -} - -fn load_session() -> Option { - LocalStorage::get::(STORAGE_KEY).ok() -} - -fn clear_session() { - LocalStorage::delete(STORAGE_KEY); -} - -/// Fire-and-forget: tell the relay server who won. Only called by the host. -async fn submit_game_result(room_code: String, game_state: ViewState) { - let [score_pl1, score_pl2] = game_state.scores; - let result_str = format!("{:?} - {:?}", score_pl1.holes, score_pl2.holes); - let outcomes = if score_pl1.holes < score_pl2.holes { - [("0", "loss"), ("1", "win")] - } else if score_pl2.holes < score_pl1.holes { - [("0", "win"), ("1", "loss")] - } else { - [("0", "draw"), ("1", "draw")] - }; - let body = serde_json::json!({ - "room_code": room_code, - "game_id": GAME_ID, - "result": result_str, - "outcomes": std::collections::HashMap::from(outcomes), - }); - let _ = gloo_net::http::Request::post(&format!("{HTTP_BASE}/games/result")) - .credentials(web_sys::RequestCredentials::Include) - .json(&body) - .unwrap() - .send() - .await; -} - -#[component] -pub fn App() -> impl IntoView { - let stored = load_session(); - let initial_screen = if stored.is_some() { - Screen::Connecting - } else { - Screen::Login { error: None } - }; - let screen = RwSignal::new(initial_screen); - - // Auth: fetch once and expose to all child components via context. - let auth_username: RwSignal> = RwSignal::new(None); - provide_context(auth_username); - spawn_local(async move { - if let Ok(resp) = gloo_net::http::Request::get(&format!("{HTTP_BASE}/auth/me")) - .credentials(web_sys::RequestCredentials::Include) - .send() - .await - { - if resp.status() == 200 { - if let Ok(me) = resp.json::().await { - auth_username.set(Some(me.username)); - } - } - } - }); - - let (cmd_tx, mut cmd_rx) = mpsc::unbounded::(); - let pending: RwSignal> = RwSignal::new(VecDeque::new()); - provide_context(pending); - provide_context(cmd_tx.clone()); - - if let Some(s) = stored { - let host_state = s - .view_state - .as_ref() - .and_then(|vs| serde_json::to_vec(vs).ok()); - cmd_tx - .unbounded_send(NetCommand::Reconnect { - relay_url: s.relay_url, - game_id: s.game_id, - room_id: s.room_id, - token: s.token, - host_state, - }) - .ok(); - } - - spawn_local(async move { - loop { - // Wait for a connect/reconnect command (or PlayVsBot). - // None means "play vs bot"; Some((config, is_reconnect)) means "connect to relay". - let remote_config: Option<(RoomConfig, bool)> = loop { - match cmd_rx.next().await { - Some(NetCommand::PlayVsBot) => break None, - Some(NetCommand::CreateRoom { room }) => { - break Some(( - RoomConfig { - relay_url: RELAY_URL.to_string(), - game_id: GAME_ID.to_string(), - room_id: room, - rule_variation: 0, - role: RoomRole::Create, - reconnect_token: None, - host_state: None, - }, - false, - )); - } - Some(NetCommand::JoinRoom { room }) => { - break Some(( - RoomConfig { - relay_url: RELAY_URL.to_string(), - game_id: GAME_ID.to_string(), - room_id: room, - rule_variation: 0, - role: RoomRole::Join, - reconnect_token: None, - host_state: None, - }, - false, - )); - } - Some(NetCommand::Reconnect { - relay_url, - game_id, - room_id, - token, - host_state, - }) => { - break Some(( - RoomConfig { - relay_url, - game_id, - room_id, - rule_variation: 0, - role: RoomRole::Join, - reconnect_token: Some(token), - host_state, - }, - true, - )); - } - _ => {} // Ignore game commands while disconnected. - } - }; - - if remote_config.is_none() { - loop { - let restart = run_local_bot_game(screen, &mut cmd_rx, pending).await; - if !restart { - break; - } - } - pending.update(|q| q.clear()); - screen.set(Screen::Login { error: None }); - continue; - } - let (config, is_reconnect) = remote_config.unwrap(); - - screen.set(Screen::Connecting); - - let room_id_for_storage = config.room_id.clone(); - let mut session: GameSession = - match GameSession::connect::(config).await { - Ok(s) => s, - Err(ConnectError::WebSocket(e) | ConnectError::Handshake(e)) => { - if is_reconnect { - clear_session(); - } - screen.set(Screen::Login { error: Some(e) }); - continue; - } - }; - - if !session.is_host { - save_session(&StoredSession { - relay_url: RELAY_URL.to_string(), - game_id: GAME_ID.to_string(), - room_id: room_id_for_storage.clone(), - token: session.reconnect_token, - is_host: false, - view_state: None, - }); - } - - let is_host = session.is_host; - let player_id = session.player_id; - let reconnect_token = session.reconnect_token; - let mut vs = ViewState::default_with_names("Blancs", "Noirs"); - let mut result_submitted = false; - - loop { - futures::select! { - cmd = cmd_rx.next().fuse() => match cmd { - Some(NetCommand::Action(action)) => { - session.send_action(action); - } - _ => { - clear_session(); - session.disconnect(); - pending.update(|q| q.clear()); - screen.set(Screen::Login { error: None }); - break; - } - }, - event = session.next_event().fuse() => match event { - Some(SessionEvent::Update(u)) => { - let prev_vs = vs.clone(); - match u { - ViewStateUpdate::Full(state) => vs = state, - ViewStateUpdate::Incremental(delta) => vs.apply_delta(&delta), - } - - // Host reports outcomes once per terminal game state. - if is_host && !result_submitted && vs.stage == SerStage::Ended { - result_submitted = true; - let room = room_id_for_storage.clone(); - let gs = vs.clone(); - spawn_local(submit_game_result(room, gs)); - } - - if is_host { - save_session(&StoredSession { - relay_url: RELAY_URL.to_string(), - game_id: GAME_ID.to_string(), - room_id: room_id_for_storage.clone(), - token: reconnect_token, - is_host: true, - view_state: Some(vs.clone()), - }); - } - let is_own_move = prev_vs.active_mp_player == Some(player_id); - push_or_show( - &prev_vs, - GameUiState { - view_state: vs.clone(), - player_id, - room_id: room_id_for_storage.clone(), - is_bot_game: false, - waiting_for_confirm: false, - pause_reason: None, - my_scored_event: None, - opp_scored_event: None, - last_moves: compute_last_moves(&prev_vs, &vs, is_own_move), - }, - pending, - screen, - ); - } - Some(SessionEvent::Disconnected(reason)) => { - pending.update(|q| q.clear()); - screen.set(Screen::Login { error: reason }); - break; - } - None => { - pending.update(|q| q.clear()); - screen.set(Screen::Login { error: None }); - break; - } - } - } - } - } - }); - - view! { - - {move || { - let q = pending.get(); - if let Some(front) = q.front() { - view! { }.into_any() - } else { - match screen.get() { - Screen::Login { error } => view! { }.into_any(), - Screen::Connecting => view! { }.into_any(), - Screen::Playing(state) => view! { }.into_any(), - } - } - }} - - } -} - -/// Runs one local bot game. Returns `true` if the player wants to play again. -async fn run_local_bot_game( - screen: RwSignal, - cmd_rx: &mut futures::channel::mpsc::UnboundedReceiver, - pending: RwSignal>, -) -> bool { - let mut backend = TrictracBackend::new(0); - backend.player_arrival(0); - backend.player_arrival(1); - - let mut vs = ViewState::default_with_names("You", "Bot"); - for cmd in backend.drain_commands() { - match cmd { - BackendCommand::ResetViewState => { - vs = backend.get_view_state().clone(); - } - BackendCommand::Delta(delta) => { - vs.apply_delta(&delta); - } - _ => {} - } - } - screen.set(Screen::Playing(GameUiState { - view_state: vs.clone(), - player_id: 0, - room_id: String::new(), - is_bot_game: true, - waiting_for_confirm: false, - pause_reason: None, - my_scored_event: None, - opp_scored_event: None, - last_moves: None, - })); - - loop { - match cmd_rx.next().await { - Some(NetCommand::Action(action)) => { - let prev_vs = vs.clone(); - backend.inform_rpc(0, action); - for cmd in backend.drain_commands() { - if let BackendCommand::Delta(delta) = cmd { - vs.apply_delta(&delta); - } - } - let scored = compute_scored_event(&prev_vs, &vs, 0); - let opp_scored = compute_scored_event(&prev_vs, &vs, 1); - screen.set(Screen::Playing(GameUiState { - view_state: vs.clone(), - player_id: 0, - room_id: String::new(), - is_bot_game: true, - waiting_for_confirm: false, - pause_reason: None, - my_scored_event: scored, - opp_scored_event: opp_scored, - last_moves: compute_last_moves(&prev_vs, &vs, true), - })); - } - Some(NetCommand::PlayVsBot) => return true, - _ => return false, - } - - loop { - let pgr = backend.get_view_state().pre_game_roll.clone(); - match bot_decide(backend.get_game(), pgr.as_ref()) { - None => break, - Some(action) => { - backend.inform_rpc(1, action); - // Process each delta individually so intermediate ceremony - // states (both dice shown) can trigger a pause via push_or_show. - for cmd in backend.drain_commands() { - if let BackendCommand::Delta(delta) = cmd { - let delta_prev_vs = vs.clone(); - vs.apply_delta(&delta); - push_or_show( - &delta_prev_vs, - GameUiState { - view_state: vs.clone(), - player_id: 0, - room_id: String::new(), - is_bot_game: true, - waiting_for_confirm: false, - pause_reason: None, - my_scored_event: None, - opp_scored_event: None, - last_moves: compute_last_moves(&delta_prev_vs, &vs, false), - }, - pending, - screen, - ); - } - } - } - } - } - } -} - -/// Returns the checker moves to animate when the board changed between two ViewStates. -/// Returns `None` when the board is unchanged or no real moves were recorded. -/// `own_move`: when true, m1 was already shown via staged-moves UI, so only animate m2. -fn compute_last_moves( - prev: &ViewState, - next: &ViewState, - own_move: bool, -) -> Option<(CheckerMove, CheckerMove)> { - if prev.board == next.board { - return None; - } - let (m1, m2) = next.dice_moves; - if m1 == CheckerMove::default() && m2 == CheckerMove::default() { - // Relies on the engine invariant: dice_moves is updated atomically with the board - // change in the Move event handler. Any future engine path that mutates the board - // without setting dice_moves would bypass this guard and replay stale animation. - return None; - } - if own_move { - // m1 was already shown via the staged-moves overlay; only animate m2. - if m2 == CheckerMove::default() { - return None; - } - return Some((m2, CheckerMove::default())); - } - Some((m1, m2)) -} - -/// Computes a scoring event for `player_id` by comparing the previous and next -/// ViewState. Returns `None` when no points changed for that player. -fn compute_scored_event(prev: &ViewState, next: &ViewState, player_id: u16) -> Option { - let prev_score = &prev.scores[player_id as usize]; - let next_score = &next.scores[player_id as usize]; - - let holes_gained = next_score.holes.saturating_sub(prev_score.holes); - if holes_gained == 0 && prev_score.points == next_score.points { - return None; - } - - let bredouille = holes_gained > 0 && prev_score.can_bredouille; - - // Determine which dice_jans are "mine" depending on who was the active roller. - let my_jans: Vec = if next.active_mp_player == Some(player_id) - && prev.active_mp_player == Some(player_id) - { - // My own roll: positive totals are mine. - next.dice_jans - .iter() - .filter(|e| e.total > 0) - .cloned() - .collect() - } else if next.active_mp_player == Some(player_id) && prev.active_mp_player != Some(player_id) { - // Opponent just moved: negative totals (their penalty) are scored for me. - next.dice_jans - .iter() - .filter(|e| e.total < 0) - .map(|e| JanEntry { - total: -e.total, - points_per: -e.points_per, - ..e.clone() - }) - .collect() - } else { - return None; - }; - - let points_earned: u8 = my_jans - .iter() - .fold(0u8, |acc, e| acc.saturating_add(e.total.unsigned_abs())); - - if points_earned == 0 && holes_gained == 0 { - return None; - } - - Some(ScoredEvent { - points_earned, - holes_gained, - holes_total: next_score.holes, - bredouille, - jans: my_jans, - }) -} - -/// Either queues the state as a buffered confirmation step (when the transition -/// warrants a pause) or shows it immediately. Always updates `screen` to the -/// live state so the UI falls through to the right content once pending drains. -fn push_or_show( - prev_vs: &ViewState, - new_state: GameUiState, - pending: RwSignal>, - screen: RwSignal, -) { - let scored = compute_scored_event(prev_vs, &new_state.view_state, new_state.player_id); - let opp_scored = compute_scored_event(prev_vs, &new_state.view_state, 1 - new_state.player_id); - - if let Some(reason) = infer_pause_reason(prev_vs, &new_state.view_state, new_state.player_id) { - // Scoring notifications go on the buffered (paused) state only. - pending.update(|q| { - q.push_back(GameUiState { - waiting_for_confirm: true, - pause_reason: Some(reason), - my_scored_event: scored, - opp_scored_event: opp_scored, - ..new_state.clone() - }); - }); - // Animation belongs to the buffered confirmation step; clear it on the - // fallback live state so it doesn't fire again after the queue drains. - screen.set(Screen::Playing(GameUiState { - last_moves: None, - ..new_state - })); - } else { - // No pause: show scoring directly on the live state. - screen.set(Screen::Playing(GameUiState { - my_scored_event: scored, - opp_scored_event: opp_scored, - ..new_state - })); - } -} - -/// Compares the previous and next ViewState to decide whether the transition -/// warrants a confirmation pause. Returns None when it is the local player's -/// own action (no pause needed). -fn infer_pause_reason(prev: &ViewState, next: &ViewState, player_id: u16) -> Option { - let opponent_id = 1 - player_id; - - // Pre-game ceremony: pause when both dice are revealed simultaneously - // (i.e. the second die was just rolled). Both players see this pause. - if next.stage == SerStage::PreGameRoll { - if let (Some(prev_pgr), Some(next_pgr)) = (&prev.pre_game_roll, &next.pre_game_roll) { - let both_now = next_pgr.host_die.is_some() && next_pgr.guest_die.is_some(); - let both_before = prev_pgr.host_die.is_some() && prev_pgr.guest_die.is_some(); - if both_now && !both_before { - return Some(PauseReason::AfterOpponentPreGameRoll); - } - } - return None; - } - - // Don't fire normal pause rules on the PreGameRoll → InGame transition. - if prev.stage == SerStage::PreGameRoll { - return None; - } - - if next.active_mp_player == Some(opponent_id) { - // Dice changed → opponent just rolled. - if next.dice != prev.dice { - return Some(PauseReason::AfterOpponentRoll); - } - // Was at HoldOrGoChoice, now Move, opponent still active → opponent went. - if prev.turn_stage == SerTurnStage::HoldOrGoChoice && next.turn_stage == SerTurnStage::Move - { - return Some(PauseReason::AfterOpponentGo); - } - } - - // Turn switched to us → opponent moved. - if next.active_mp_player == Some(player_id) && prev.active_mp_player == Some(opponent_id) { - return Some(PauseReason::AfterOpponentMove); - } - - None -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::trictrac::types::{PlayerScore, SerStage, SerTurnStage}; - - fn score() -> PlayerScore { - PlayerScore { - name: String::new(), - points: 0, - holes: 0, - can_bredouille: false, - } - } - - fn vs(dice: (u8, u8), turn_stage: SerTurnStage, active: Option) -> ViewState { - ViewState { - board: [0i8; 24], - stage: SerStage::InGame, - turn_stage, - active_mp_player: active, - scores: [score(), score()], - dice, - dice_jans: Vec::new(), - dice_moves: (CheckerMove::default(), CheckerMove::default()), - pre_game_roll: None, - } - } - - #[test] - fn dice_change_is_after_roll() { - let prev = vs((0, 0), SerTurnStage::RollDice, Some(1)); - let next = vs((3, 5), SerTurnStage::Move, Some(1)); - assert_eq!( - infer_pause_reason(&prev, &next, 0), - Some(PauseReason::AfterOpponentRoll) - ); - } - - #[test] - fn hold_to_move_is_after_go() { - let prev = vs((3, 5), SerTurnStage::HoldOrGoChoice, Some(1)); - let next = vs((3, 5), SerTurnStage::Move, Some(1)); - assert_eq!( - infer_pause_reason(&prev, &next, 0), - Some(PauseReason::AfterOpponentGo) - ); - } - - #[test] - fn turn_switch_is_after_move() { - let prev = vs((3, 5), SerTurnStage::Move, Some(1)); - let next = vs((3, 5), SerTurnStage::RollDice, Some(0)); - assert_eq!( - infer_pause_reason(&prev, &next, 0), - Some(PauseReason::AfterOpponentMove) - ); - } - - #[test] - fn own_action_returns_none() { - let prev = vs((0, 0), SerTurnStage::RollDice, Some(0)); - let next = vs((2, 4), SerTurnStage::Move, Some(0)); - assert_eq!(infer_pause_reason(&prev, &next, 0), None); - } - - #[test] - fn no_active_player_returns_none() { - let mut prev = vs((0, 0), SerTurnStage::RollDice, None); - prev.stage = SerStage::PreGame; - let mut next = prev.clone(); - next.active_mp_player = Some(0); - assert_eq!(infer_pause_reason(&prev, &next, 0), None); - } -} diff --git a/clients/web-game/src/components/board.rs b/clients/web-game/src/components/board.rs deleted file mode 100644 index 0610c86..0000000 --- a/clients/web-game/src/components/board.rs +++ /dev/null @@ -1,594 +0,0 @@ -use leptos::prelude::*; -use trictrac_store::CheckerMove; - -use super::die::Die; -use crate::trictrac::types::{SerTurnStage, ViewState}; - -/// Field numbers in visual display order (left-to-right for each quarter), white's perspective. -const TOP_LEFT_W: [u8; 6] = [13, 14, 15, 16, 17, 18]; -const TOP_RIGHT_W: [u8; 6] = [19, 20, 21, 22, 23, 24]; -const BOT_LEFT_W: [u8; 6] = [12, 11, 10, 9, 8, 7]; -const BOT_RIGHT_W: [u8; 6] = [6, 5, 4, 3, 2, 1]; - -/// 180° rotation of white's layout: black's pieces (field 24) appear at the bottom. -const TOP_LEFT_B: [u8; 6] = [1, 2, 3, 4, 5, 6]; -const TOP_RIGHT_B: [u8; 6] = [7, 8, 9, 10, 11, 12]; -const BOT_LEFT_B: [u8; 6] = [24, 23, 22, 21, 20, 19]; -const BOT_RIGHT_B: [u8; 6] = [18, 17, 16, 15, 14, 13]; - -/// The rest corner is field 12 (White) or field 13 (Black) in the store's coordinate system. -/// Returns true when `field_num` is the rest corner for this perspective. -#[allow(dead_code)] -fn is_rest_corner(field_num: u8, is_white: bool) -> bool { - if is_white { - field_num == 12 - } else { - field_num == 13 - } -} - -/// Zone CSS class for a field number (field coordinates are always White's 1-24). -fn field_zone_class(field_num: u8) -> &'static str { - match field_num { - 1..=6 => "zone-petit", - 7..=12 => "zone-grand", - 13..=18 => "zone-opponent", - 19..=24 => "zone-retour", - _ => "", - } -} - -/// Returns (d0_used, d1_used) for the bar dice display. -fn bar_matched_dice_used(staged: &[(u8, u8)], dice: (u8, u8)) -> (bool, bool) { - let mut d0 = false; - let mut d1 = false; - for &(from, to) in staged { - let dist = if from < to { - to.saturating_sub(from) - } else { - from.saturating_sub(to) - }; - if !d0 && dist == dice.0 { - d0 = true; - } else if !d1 && dist == dice.1 { - d1 = true; - } else if !d0 { - d0 = true; - } else { - d1 = true; - } - } - (d0, d1) -} - -/// Returns the displayed board value for `field_num` after applying `staged_moves`. -/// Field numbers are always in white's coordinate system (1–24). -fn displayed_value( - base_board: [i8; 24], - staged_moves: &[(u8, u8)], - is_white: bool, - field_num: u8, -) -> i8 { - let mut val = base_board[(field_num - 1) as usize]; - let delta: i8 = if is_white { 1 } else { -1 }; - for &(from, to) in staged_moves { - if from == field_num { - val -= delta; - } - if to == field_num { - val += delta; - } - } - val -} - -/// Fields whose checkers may be selected as the next origin given already-staged moves. -fn valid_origins_for(seqs: &[(CheckerMove, CheckerMove)], staged: &[(u8, u8)]) -> Vec { - let mut v: Vec = match staged.len() { - 0 => seqs - .iter() - .map(|(m1, _)| m1.get_from() as u8) - .filter(|&f| f != 0) - .collect(), - 1 => { - let (f0, t0) = staged[0]; - seqs.iter() - .filter(|(m1, _)| m1.get_from() as u8 == f0 && m1.get_to() as u8 == t0) - .map(|(_, m2)| m2.get_from() as u8) - .filter(|&f| f != 0) - .collect() - } - _ => vec![], - }; - v.sort_unstable(); - v.dedup(); - v -} - -/// Pixel center of a board field in the SVG overlay coordinate space. -/// Geometry: field 60×180px, board padding 4px, gap 4px, bar 20px, center-bar 12px. -/// With triangular flèches, arrows target the WIDE BASE of each triangle — -/// that is where the checker stack actually sits. -fn field_center(f: usize, is_white: bool) -> Option<(f32, f32)> { - if f == 0 || f > 24 { - return None; - } - let (qi, right, top): (usize, bool, bool) = if is_white { - match f { - 13..=18 => (f - 13, false, true), - 19..=24 => (f - 19, true, true), - 7..=12 => (12 - f, false, false), - 1..=6 => (6 - f, true, false), - _ => return None, - } - } else { - match f { - 1..=6 => (f - 1, false, true), - 7..=12 => (f - 7, true, true), - 19..=24 => (24 - f, false, false), - 13..=18 => (18 - f, true, false), - _ => return None, - } - }; - // Left-quarter field i center x: 4(pad) + i*62 + 30(half field) = 34 + 62i - // Right-quarter: 4 + 370(quarter) + 4(gap) + 68(bar) + 4(gap) + i*62 + 30 = 480 + 62i - let x = if right { - 480.0 + qi as f32 * 62.0 - } else { - 34.0 + qi as f32 * 62.0 - }; - // Top row triangle base (wide end) ≈ y=30; bot row triangle base ≈ y=358. - // (Top base: 4pad + 4field-pad + 20half-checker ≈ 28; Bot base: 388 − 4pad − 4field-pad − 20 ≈ 360) - let y = if top { 30.0 } else { 358.0 }; - Some((x, y)) -} - -/// SVG `` element drawing one arrow (shadow + gold) from `fp` to `tp`. -fn arrow_svg(fp: (f32, f32), tp: (f32, f32)) -> AnyView { - let (x1, y1) = fp; - let (x2, y2) = tp; - let dx = x2 - x1; - let dy = y2 - y1; - let len = (dx * dx + dy * dy).sqrt(); - if len < 10.0 { - return view! { }.into_any(); - } - let nx = dx / len; - let ny = dy / len; - let px = -ny; - let py = nx; - - // Shrink line ends so arrows don't overlap the checker stack - let lx1 = x1 + nx * 20.0; - let ly1 = y1 + ny * 20.0; - let lx2 = x2 - nx * 15.0; - let ly2 = y2 - ny * 15.0; - - // Arrowhead triangle at (x2, y2) - let ah = 15.0_f32; - let aw = 7.0_f32; - let bx = x2 - nx * ah; - let bary = y2 - ny * ah; - let pts = format!( - "{:.1},{:.1} {:.1},{:.1} {:.1},{:.1}", - x2, - y2, - bx + px * aw, - bary + py * aw, - bx - px * aw, - bary - py * aw, - ); - let shadow_pts = format!( - "{:.1},{:.1} {:.1},{:.1} {:.1},{:.1}", - x2, - y2, - bx + px * (aw + 1.5), - bary + py * (aw + 1.5), - bx - px * (aw + 1.5), - bary - py * (aw + 1.5), - ); - - view! { - - // Drop-shadow for readability on coloured fields - - - // Gold arrow - - - - } - .into_any() -} - -/// Valid destinations for a selected origin given already-staged moves. -/// May include 0 (exit); callers handle that case. -fn valid_dests_for( - seqs: &[(CheckerMove, CheckerMove)], - staged: &[(u8, u8)], - origin: u8, -) -> Vec { - let mut v: Vec = match staged.len() { - 0 => seqs - .iter() - .filter(|(m1, _)| m1.get_from() as u8 == origin) - .map(|(m1, _)| m1.get_to() as u8) - .collect(), - 1 => { - let (f0, t0) = staged[0]; - seqs.iter() - .filter(|(m1, m2)| { - m1.get_from() as u8 == f0 - && m1.get_to() as u8 == t0 - && m2.get_from() as u8 == origin - }) - .map(|(_, m2)| m2.get_to() as u8) - .collect() - } - _ => vec![], - }; - v.sort_unstable(); - v.dedup(); - v -} - -#[component] -pub fn Board( - view_state: ViewState, - player_id: u16, - /// Pending origin selection (first click of a move pair). - selected_origin: RwSignal>, - /// Moves staged so far this turn (max 2). Each entry is (from, to), 0 = empty move. - staged_moves: RwSignal>, - /// All valid two-move sequences for this turn (empty when not in move stage). - valid_sequences: Vec<(CheckerMove, CheckerMove)>, - /// Dice to display in the center bars; None means dice not yet rolled (cups shown upright). - #[prop(default = None)] - bar_dice: Option<(u8, u8)>, - /// Whether we're in the move stage (determines used/unused die appearance). - #[prop(default = false)] - bar_is_move: bool, - #[prop(default = false)] is_my_turn: bool, - /// Whether the dice are a double (golden glow). - #[prop(default = false)] - bar_is_double: bool, - /// Checker moves to animate on mount (None when board unchanged). - #[prop(default = None)] - last_moves: Option<(CheckerMove, CheckerMove)>, - /// Fields where a hit (battue) was scored this turn — show ripple animation. - #[prop(default = vec![])] - hit_fields: Vec, -) -> impl IntoView { - let board = view_state.board; - let is_move_stage = view_state.active_mp_player == Some(player_id) - && matches!( - view_state.turn_stage, - SerTurnStage::Move | SerTurnStage::HoldOrGoChoice - ); - let is_white = player_id == 0; - let hovered_moves = use_context::>>(); - - // Exit-eligible (§8c): all the player's checkers are in their last jan. - // White last jan = fields 19-24 (board indices 18-23, positive values). - // Black last jan = fields 1-6 (board indices 0-5, negative values). - let board_snapshot = view_state.board; - let all_in_exit: bool; - let exit_field_test: fn(u8) -> bool; - if is_white { - let in_exit: i8 = board_snapshot[18..24].iter().map(|&v| v.max(0)).sum(); - let total: i8 = board_snapshot.iter().map(|&v| v.max(0)).sum(); - all_in_exit = total > 0 && in_exit == total; - exit_field_test = |f| matches!(f, 19..=24); - } else { - let in_exit: i8 = board_snapshot[0..6].iter().map(|&v| (-v).max(0)).sum(); - let total: i8 = board_snapshot.iter().map(|&v| (-v).max(0)).sum(); - all_in_exit = total > 0 && in_exit == total; - exit_field_test = |f| matches!(f, 1..=6); - } - - // `valid_sequences` is cloned per field (the Vec is small; Send-safe unlike Rc). - let fields_from = |nums: &[u8], is_top_row: bool| -> Vec { - nums.iter() - .map(|&field_num| { - // Each reactive closure gets its own owned clone — Vec<(CheckerMove,CheckerMove)> - // is Send, which Leptos requires for reactive attribute functions. - let seqs_c = valid_sequences.clone(); - let seqs_k = valid_sequences.clone(); - let corner_title = if is_rest_corner(field_num, is_white) { - Some("Coin de repos — must enter and leave with 2 checkers") - } else { - None - }; - // §4a — slide delta for the arriving checker at this field. - // Computed once per field at render time; Option<(f32,f32)> is Copy. - let slide_delta: Option<(f32, f32)> = last_moves.and_then(|(m1, m2)| { - [m1, m2].iter().find_map(|m| { - if m.get_to() != field_num as usize || m.get_from() == m.get_to() { - return None; - } - let (fx, fy) = field_center(m.get_from(), is_white)?; - let (tx, ty) = field_center(m.get_to(), is_white)?; - let dx = fx - tx; - let dy = fy - ty; - (dx.abs() >= 1.0 || dy.abs() >= 1.0).then_some((dx, dy)) - }) - }); - // §6e — ripple on hit fields (battue). - let is_hit_field = hit_fields.contains(&field_num); - view! { -
0 } else { val < 0 }; - let can_stage = is_move_stage && staged.len() < 2; - let sel = selected_origin.get(); - - let mut cls = format!("field {}", field_zone_class(field_num)); - if is_rest_corner(field_num, is_white) { - cls.push_str(" corner"); - // Pulse when the corner can be reached this turn - if !seqs_c.is_empty() && seqs_c.iter().any(|(m1, m2)| { - m1.get_to() as u8 == field_num - || m2.get_to() as u8 == field_num - }) { - cls.push_str(" corner-available"); - } - } - if is_rest_corner(field_num, !is_white) { - cls.push_str(" corner"); - } - if all_in_exit && exit_field_test(field_num) { - cls.push_str(" exit-eligible"); - } - - if seqs_c.is_empty() { - // No restriction (dice not rolled or not move stage) - if can_stage && (sel.is_some() || is_mine) { - cls.push_str(" clickable"); - } - if sel == Some(field_num) { cls.push_str(" selected"); } - if can_stage && sel.is_some() && sel != Some(field_num) { - cls.push_str(" dest"); - } - } else if can_stage { - if let Some(origin) = sel { - if origin == field_num { - cls.push_str(" selected clickable"); - } else { - let dests = valid_dests_for(&seqs_c, &staged, origin); - // Only highlight non-exit destinations (field 0 = exit has no tile) - if dests.iter().any(|&d| d == field_num && d != 0) { - cls.push_str(" clickable dest"); - } - } - } else { - let origins = valid_origins_for(&seqs_c, &staged); - if origins.iter().any(|&o| o == field_num) { - cls.push_str(" clickable"); - } - } - } - - // §6c: highlight fields touched by the hovered jan - if let Some(hm) = hovered_moves { - let pairs = hm.get(); - let f = field_num as usize; - let highlighted = pairs.iter().any(|(m1, m2)| { - (m1.get_from() != 0 && m1.get_from() == f) - || (m1.get_to() != 0 && m1.get_to() == f) - || (m2.get_from() != 0 && m2.get_from() == f) - || (m2.get_to() != 0 && m2.get_to() == f) - }); - if highlighted { - cls.push_str(" jan-hovered"); - } - } - - cls - } - on:click=move |_| { - if !is_move_stage { return; } - let staged = staged_moves.get_untracked(); - if staged.len() >= 2 { return; } - - match selected_origin.get_untracked() { - Some(origin) if origin == field_num => { - selected_origin.set(None); - } - Some(origin) => { - let valid = if seqs_k.is_empty() { - true - } else { - valid_dests_for(&seqs_k, &staged, origin) - .iter() - .any(|&d| d == field_num) - }; - if valid { - staged_moves.update(|v| v.push((origin, field_num))); - selected_origin.set(None); - } - } - None => { - if seqs_k.is_empty() { - let val = displayed_value(board, &staged, is_white, field_num); - if is_white && val > 0 || !is_white && val < 0 { - selected_origin.set(Some(field_num)); - } - } else { - let origins = valid_origins_for(&seqs_k, &staged); - if origins.iter().any(|&o| o == field_num) { - let dests = valid_dests_for(&seqs_k, &staged, field_num); - if !dests.is_empty() && dests.iter().all(|&d| d == 0) { - // All destinations are exits: auto-stage - staged_moves.update(|v| v.push((field_num, 0))); - } else { - selected_origin.set(Some(field_num)); - } - } - } - } - } - } - > - {field_num} - {move || { - let moves = staged_moves.get(); - let val = displayed_value(board, &moves, is_white, field_num); - let count = val.unsigned_abs(); - // §6e — ripple on hit (battue) fields; must be inside the - // reactive closure so Leptos uses the same direct rendering - // path as .arriving (avoids node-move that resets animation). - let ripple = is_hit_field.then(|| { - let cls = if is_top_row { "hit-ripple hit-ripple-top" } else { "hit-ripple hit-ripple-bot" }; - view! {
}.into_any() - }); - let stack = (count > 0).then(|| { - let color = if val > 0 { "white" } else { "black" }; - let display_n = (count as usize).min(4); - // outermost index: last for top rows, first for bottom rows. - let outer_idx = if is_top_row { display_n - 1 } else { 0 }; - let chips: Vec = (0..display_n).map(|i| { - let label = if i == outer_idx && count >= 5 { - count.to_string() - } else { - String::new() - }; - if i == outer_idx { - if let Some((dx, dy)) = slide_delta { - return view! { -
{label}
- }.into_any(); - } - } - view! { -
{label}
- }.into_any() - }).collect(); - view! {
{chips}
}.into_any() - }); - (ripple, stack) - }} -
- } - .into_any() - }) - .collect() - }; - - // ── Bar content: die in the center bar (die_idx 0 = top bar, 1 = bottom bar) ── - let bar_content = move |die_idx: u8| -> AnyView { - match bar_dice { - None => view! {
}.into_any(), - Some(dice_vals) => { - let die_val = if die_idx == 0 { - dice_vals.0 - } else { - dice_vals.1 - }; - view! { -
- {move || { - let staged = staged_moves.get(); - let (u0, u1) = if bar_is_move { - bar_matched_dice_used(&staged, dice_vals) - } else if is_my_turn { - (true, true) - } else { - (false, false) - }; - let used = if die_idx == 0 { u0 } else { u1 }; - view! { } - }} -
- } - .into_any() - } - } - }; - - let (tl, tr, bl, br) = if is_white { - (&TOP_LEFT_W, &TOP_RIGHT_W, &BOT_LEFT_W, &BOT_RIGHT_W) - } else { - (&TOP_LEFT_B, &TOP_RIGHT_B, &BOT_LEFT_B, &BOT_RIGHT_B) - }; - - // Zone label pairs (top-left, top-right, bot-left, bot-right) per perspective. - let (label_tl, label_tr, label_bl, label_br) = if is_white { - ("", "jan de retour", "grand jan", "petit jan") - } else { - ("petit jan", "grand jan", "jan de retour", "") - }; - - view! { - // board-wrapper keeps zone labels outside .board so the SVG overlay - // inside .board stays correctly positioned (position:absolute top:0 left:0 - // is relative to .board, not the wrapper). -
-
-
{label_tl}
-
-
{label_tr}
-
-
-
-
{fields_from(tl, true)}
-
{bar_content(0)}
-
{fields_from(tr, true)}
-
-
-
-
{fields_from(bl, false)}
-
{bar_content(1)}
-
{fields_from(br, false)}
-
- // SVG overlay: arrows for hovered jan moves - - {move || { - let Some(hm) = hovered_moves else { return vec![]; }; - let pairs = hm.get(); - if pairs.is_empty() { return vec![]; } - // Collect unique individual (from, to) moves; skip empty/exit. - let mut moves: Vec<(usize, usize)> = pairs.iter() - .flat_map(|(m1, m2)| [ - (m1.get_from(), m1.get_to()), - (m2.get_from(), m2.get_to()), - ]) - .filter(|&(f, t)| f != 0 && t != 0) - .collect(); - moves.sort_unstable(); - moves.dedup(); - moves.into_iter() - .filter_map(|(from, to)| { - let p1 = field_center(from, is_white)?; - let p2 = field_center(to, is_white)?; - Some(arrow_svg(p1, p2)) - }) - .collect() - }} - -
-
-
{label_bl}
-
-
{label_br}
-
-
- } -} diff --git a/clients/web-game/src/components/connecting_screen.rs b/clients/web-game/src/components/connecting_screen.rs deleted file mode 100644 index 6f40da5..0000000 --- a/clients/web-game/src/components/connecting_screen.rs +++ /dev/null @@ -1,9 +0,0 @@ -use leptos::prelude::*; - -use crate::i18n::*; - -#[component] -pub fn ConnectingScreen() -> impl IntoView { - let i18n = use_i18n(); - view! {

{t!(i18n, connecting)}

} -} diff --git a/clients/web-game/src/components/die.rs b/clients/web-game/src/components/die.rs deleted file mode 100644 index 7576280..0000000 --- a/clients/web-game/src/components/die.rs +++ /dev/null @@ -1,53 +0,0 @@ -use leptos::prelude::*; - -/// (cx, cy) positions for dots on a 48×48 die face. -fn dot_positions(value: u8) -> &'static [(&'static str, &'static str)] { - match value { - 1 => &[("24", "24")], - 2 => &[("35", "13"), ("13", "35")], - 3 => &[("35", "13"), ("24", "24"), ("13", "35")], - 4 => &[("13", "13"), ("35", "13"), ("13", "35"), ("35", "35")], - 5 => &[("13", "13"), ("35", "13"), ("24", "24"), ("13", "35"), ("35", "35")], - 6 => &[("13", "13"), ("35", "13"), ("13", "24"), ("35", "24"), ("13", "35"), ("35", "35")], - _ => &[], - } -} - -/// A single die face rendered as SVG. -/// `value` 1–6 shows dots; 0 shows an empty face (not-yet-rolled). -/// `used` dims the die. -/// `is_double` applies a golden glow (both dice same value). -#[component] -pub fn Die( - value: u8, - used: bool, - #[prop(default = false)] is_double: bool, -) -> AnyView { - let mut cls = if used { - "die-face die-used".to_string() - } else { - "die-face".to_string() - }; - if is_double && !used { - cls.push_str(" die-double"); - } - if value == 0 { - return view! { - - - {"?"} - - }.into_any(); - } - let dots: Vec = dot_positions(value) - .iter() - .map(|&(cx, cy)| view! { }.into_any()) - .collect(); - view! { - - - {dots} - - }.into_any() -} diff --git a/clients/web-game/src/components/game_screen.rs b/clients/web-game/src/components/game_screen.rs deleted file mode 100644 index 2493680..0000000 --- a/clients/web-game/src/components/game_screen.rs +++ /dev/null @@ -1,470 +0,0 @@ -use std::cell::Cell; -use std::collections::VecDeque; - -use futures::channel::mpsc::UnboundedSender; -use leptos::prelude::*; -use trictrac_store::{Board as StoreBoard, CheckerMove, Color, Dice as StoreDice, Jan, MoveRules}; - -use super::die::Die; -use crate::app::{GameUiState, NetCommand, PauseReason}; -use crate::i18n::*; -use crate::trictrac::types::{PlayerAction, PreGameRollState, SerStage, SerTurnStage}; - -use super::board::Board; -use super::score_panel::PlayerScorePanel; -use super::scoring::ScoringPanel; - -#[component] -pub fn GameScreen(state: GameUiState) -> impl IntoView { - let i18n = use_i18n(); - - let auth_username = - use_context::>>().expect("auth_username not found in context"); - let vs = state.view_state.clone(); - let player_id = state.player_id; - let is_my_turn = vs.active_mp_player == Some(player_id); - let is_move_stage = is_my_turn - && matches!( - vs.turn_stage, - SerTurnStage::Move | SerTurnStage::HoldOrGoChoice - ); - let waiting_for_confirm = state.waiting_for_confirm; - let pause_reason = state.pause_reason.clone(); - - // ── Hovered jan moves (shown as arrows on the board) ────────────────────── - let hovered_jan_moves: RwSignal> = RwSignal::new(vec![]); - provide_context(hovered_jan_moves); - - // ── Staged move state ────────────────────────────────────────────────────── - let selected_origin: RwSignal> = RwSignal::new(None); - let staged_moves: RwSignal> = RwSignal::new(Vec::new()); - - let cmd_tx = use_context::>() - .expect("UnboundedSender not found in context"); - let pending = - use_context::>>().expect("pending not found in context"); - let cmd_tx_effect = cmd_tx.clone(); - // Non-reactive counter so we can detect when staged_moves grows without - // returning a value from the Effect (which causes a Leptos reactive loop - // when the Effect also writes to the same signal it reads). - let prev_staged_len = Cell::new(0usize); - - Effect::new(move |_| { - let moves = staged_moves.get(); - let n = moves.len(); - // Play checker sound whenever a move is added (own moves, immediate feedback). - if n > prev_staged_len.get() { - crate::sound::play_checker_move(); - } - prev_staged_len.set(n); - if n == 2 { - let to_cm = |&(from, to): &(u8, u8)| { - CheckerMove::new(from as usize, to as usize).unwrap_or_default() - }; - cmd_tx_effect - .unbounded_send(NetCommand::Action(PlayerAction::Move( - to_cm(&moves[0]), - to_cm(&moves[1]), - ))) - .ok(); - staged_moves.set(vec![]); - selected_origin.set(None); - // Reset the counter so the next turn starts clean. - prev_staged_len.set(0); - } - }); - - // ── Auto-roll effect ───────────────────────────────────────────────────── - // GameScreen is fully re-mounted on every ViewState update (state is a - // plain prop, not a signal), so this effect fires exactly once per - // RollDice phase entry and will not double-send. - // Guard: suppressed while waiting_for_confirm — the AfterOpponentMove - // buffered state shows the human's RollDice turn but the auto-roll must - // wait until the buffer is drained and the live screen state is shown. - // Guard: never auto-roll during the pre-game ceremony (the ceremony overlay - // has its own Roll button for PlayerAction::PreGameRoll). - let show_roll = - is_my_turn && vs.turn_stage == SerTurnStage::RollDice && vs.stage != SerStage::PreGameRoll; - if show_roll && !waiting_for_confirm { - let cmd_tx_auto = cmd_tx.clone(); - Effect::new(move |_| { - cmd_tx_auto - .unbounded_send(NetCommand::Action(PlayerAction::Roll)) - .ok(); - }); - } - - let dice = vs.dice; - let show_dice = dice != (0, 0); - - // ── Button senders ───────────────────────────────────────────────────────── - let cmd_tx_go = cmd_tx.clone(); - let cmd_tx_quit = cmd_tx.clone(); - let cmd_tx_end_quit = cmd_tx.clone(); - let cmd_tx_end_replay = cmd_tx.clone(); - // Only show the fallback Go button when there is no ScoringPanel showing it. - let show_hold_go = is_my_turn - && vs.turn_stage == SerTurnStage::HoldOrGoChoice - && state.my_scored_event.is_none(); - - // ── Valid move sequences for this turn ───────────────────────────────────── - // Computed once per ViewState snapshot; used by Board (highlighting) and the - // empty-move button (visibility). - let valid_sequences: Vec<(CheckerMove, CheckerMove)> = if is_move_stage && dice != (0, 0) { - let mut store_board = StoreBoard::new(); - store_board.set_positions(&Color::White, vs.board); - let store_dice = StoreDice { values: dice }; - let color = if player_id == 0 { - Color::White - } else { - Color::Black - }; - let rules = MoveRules::new(&color, &store_board, store_dice); - let raw = rules.get_possible_moves_sequences(true, vec![]); - if player_id == 0 { - raw - } else { - raw.into_iter() - .map(|(m1, m2)| (m1.mirror(), m2.mirror())) - .collect() - } - } else { - vec![] - }; - // Clone for the empty-move button reactive closure (Board consumes the original). - let valid_seqs_empty = valid_sequences.clone(); - - // ── Scores ───────────────────────────────────────────────────────────────── - let my_score = vs.scores[player_id as usize].clone(); - let opp_score = vs.scores[1 - player_id as usize].clone(); - - // ── Ceremony state (extracted before vs is moved into Board) ──────────────── - let is_ceremony = vs.stage == SerStage::PreGameRoll; - let pre_game_roll_data: Option = vs.pre_game_roll.clone(); - let my_name_ceremony = my_score.name.clone(); - let opp_name_ceremony = opp_score.name.clone(); - let cmd_tx_ceremony = cmd_tx.clone(); - - // ── Scoring notifications ────────────────────────────────────────────────── - let my_scored_event = state.my_scored_event.clone(); - let opp_scored_event = state.opp_scored_event.clone(); - let hole_toast_info = my_scored_event - .as_ref() - .filter(|e| e.holes_gained > 0) - .map(|e| (e.holes_total, e.bredouille)); - - let is_double_dice = dice.0 == dice.1 && dice.0 != 0; - - let last_moves = state.last_moves; - - // §6e — fields where a battue (hit) was scored; ripple animation shown there. - let hit_fields: Vec = { - let is_hit_jan = |jan: &Jan| { - matches!( - jan, - Jan::TrueHitSmallJan - | Jan::TrueHitBigJan - | Jan::TrueHitOpponentCorner - | Jan::FalseHitSmallJan - | Jan::FalseHitBigJan - ) - }; - let mut fields: Vec = vec![]; - for event_opt in [&my_scored_event, &opp_scored_event] { - if let Some(event) = event_opt { - for entry in &event.jans { - if is_hit_jan(&entry.jan) { - for (m1, m2) in &entry.moves { - for m in [m1, m2] { - let to = m.get_to() as u8; - if to != 0 && !fields.contains(&to) { - fields.push(to); - } - } - } - } - } - } - } - fields - }; - - // ── Sound effects (fire once on mount = once per state snapshot) ────────── - // Dice roll: dice just appeared (no preceding moves in this snapshot). - if show_dice && last_moves.is_none() { - crate::sound::play_dice_roll(); - } - // Checker move: moves were committed in the preceding action. - if last_moves.is_some() { - crate::sound::play_checker_move(); - } - // Scoring: hole takes priority over plain points. - if let Some(ref ev) = my_scored_event { - if ev.holes_gained > 0 { - crate::sound::play_hole_scored(); - } else { - crate::sound::play_points_scored(); - } - } - - // ── Capture for closures ─────────────────────────────────────────────────── - let stage = vs.stage.clone(); - let turn_stage = vs.turn_stage.clone(); - let turn_stage_for_panel = turn_stage.clone(); - let turn_stage_for_sub = turn_stage.clone(); - let room_id = state.room_id.clone(); - let is_bot_game = state.is_bot_game; - - // ── Game-over info ───────────────────────────────────────────────────────── - let stage_is_ended = stage == SerStage::Ended; - let winner_is_me = my_score.holes >= 12; - let my_name_end = my_score.name.clone(); - let my_holes_end = my_score.holes; - let opp_name_end = opp_score.name.clone(); - let opp_holes_end = opp_score.holes; - - view! { -
- // ── Top bar ────────────────────────────────────────────────────── -
- {move || if is_bot_game { - t_string!(i18n, vs_bot_label).to_owned() - } else { - t_string!(i18n, room_label, id = room_id.as_str()) - }} -
- - -
- - {move || auth_username.get().map(|u| view! { -

"Playing as " {u}

- })} - - {t!(i18n, quit)} -
- - // ── Opponent score (above board) ───────────────────────────────── - - - // ── Status bar — full width, above board (§10b) ────────────────── -
- {move || { - if let Some(ref reason) = pause_reason { - return String::from(match reason { - PauseReason::AfterOpponentRoll => t_string!(i18n, after_opponent_roll), - PauseReason::AfterOpponentGo => t_string!(i18n, after_opponent_go), - PauseReason::AfterOpponentMove => t_string!(i18n, after_opponent_move), - PauseReason::AfterOpponentPreGameRoll => t_string!(i18n, after_opponent_pre_game_roll), - }); - } - let n = staged_moves.get().len(); - if is_move_stage { - t_string!(i18n, select_move, n = n + 1) - } else { - String::from(match (&stage, is_my_turn, &turn_stage) { - (SerStage::Ended, _, _) => t_string!(i18n, game_over), - (SerStage::PreGame, _, _) | (SerStage::PreGameRoll, _, _) => t_string!(i18n, waiting_for_opponent), - (SerStage::InGame, true, SerTurnStage::RollDice) => t_string!(i18n, your_turn_roll), - (SerStage::InGame, true, SerTurnStage::HoldOrGoChoice) => t_string!(i18n, hold_or_go), - (SerStage::InGame, true, _) => t_string!(i18n, your_turn), - (SerStage::InGame, false, _) => t_string!(i18n, opponent_turn), - }) - } - }} -
- - // ── Contextual sub-prompt (§8a) ────────────────────────────────── - {move || { - let hint: String = if waiting_for_confirm { - t_string!(i18n, hint_continue).to_owned() - } else if is_move_stage { - t_string!(i18n, hint_move).to_owned() - } else if is_my_turn && turn_stage_for_sub == SerTurnStage::HoldOrGoChoice { - t_string!(i18n, hint_hold_or_go).to_owned() - } else { - String::new() - }; - (!hint.is_empty()).then(|| view! {

{hint}

}) - }} - - // ── Board + side panel ─────────────────────────────────────────── -
- - - // ── Side panel (scoring panels only) ───────────────────────── -
- {my_scored_event.map(|event| view! { - - })} - {opp_scored_event.map(|event| view! { - - })} -
-
- - // ── Action buttons below board (§10c) ──────────────────────────── -
- {waiting_for_confirm.then(|| view! { - - })} - // Fallback Go button when no scoring panel (e.g. after reconnect) - {show_hold_go.then(|| view! { - - })} - {move || { - // Show the empty-move button only when (0,0) is a valid - // first or second move given what has already been staged. - let staged = staged_moves.get(); - let show = is_move_stage && staged.len() < 2 && ( - valid_seqs_empty.is_empty() || match staged.len() { - 0 => valid_seqs_empty.iter().any(|(m1, _)| m1.get_from() == 0), - 1 => { - let (f0, t0) = staged[0]; - valid_seqs_empty.iter() - .filter(|(m1, _)| { - m1.get_from() as u8 == f0 - && m1.get_to() as u8 == t0 - }) - .any(|(_, m2)| m2.get_from() == 0) - } - _ => false, - } - ); - show.then(|| view! { - - }) - }} -
- - // ── Player score (below board) ──────────────────────────────────── - - - // ── Pre-game ceremony overlay ───────────────────────────────────── - {is_ceremony.then(|| { - let pgr = pre_game_roll_data.unwrap_or(PreGameRollState { - host_die: None, - guest_die: None, - tie_count: 0, - }); - let my_die = if player_id == 0 { pgr.host_die } else { pgr.guest_die }; - let opp_die = if player_id == 0 { pgr.guest_die } else { pgr.host_die }; - let can_roll = my_die.is_none() && !waiting_for_confirm; - let show_tie = pgr.tie_count > 0; - view! { -
-
-

{t!(i18n, pre_game_roll_title)}

- {show_tie.then(|| view! { -

{t!(i18n, pre_game_roll_tie)}

- })} -
-
- {my_name_ceremony}{t!(i18n, you_suffix)} - -
-
- {opp_name_ceremony} - -
-
- {waiting_for_confirm.then(|| { - let pending_c = pending; - view! { - - } - })} - {can_roll.then(|| { - let cmd_tx_c = cmd_tx_ceremony.clone(); - view! { - - } - })} -
-
- } - })} - - // ── Game-over overlay ───────────────────────────────────────────── - {stage_is_ended.then(|| { - let opp_name_end_clone = opp_name_end.clone(); - let winner_text = move || if winner_is_me { - t_string!(i18n, you_win).to_owned() - } else { - t_string!(i18n, opp_wins, name = opp_name_end_clone.as_str()) - }; - view! { -
-
-

{t!(i18n, game_over)}

-

{winner_text}

-
- {my_name_end} - - {format!("{my_holes_end} — {opp_holes_end}")} - - {opp_name_end.clone()} -
-
- - {is_bot_game.then(|| view! { - - })} -
-
-
- } - })} - - // ── Hole toast (§6a) — board-centered overlay when a hole is won ── - {hole_toast_info.map(|(holes_total, bredouille)| view! { -
-
"Trou !"
-
{format!("{holes_total} / 12")}
- {bredouille.then(|| view! { -
"× 2 bredouille"
- })} -
- })} -
- } -} diff --git a/clients/web-game/src/components/login_screen.rs b/clients/web-game/src/components/login_screen.rs deleted file mode 100644 index 1328b03..0000000 --- a/clients/web-game/src/components/login_screen.rs +++ /dev/null @@ -1,115 +0,0 @@ -use futures::channel::mpsc::UnboundedSender; -use leptos::prelude::*; - -use crate::app::NetCommand; -use crate::i18n::*; - -#[cfg(debug_assertions)] -const PORTAL_URL: &str = "http://localhost:9092"; -#[cfg(not(debug_assertions))] -const PORTAL_URL: &str = "/portal"; - -#[component] -pub fn LoginScreen(error: Option) -> impl IntoView { - let i18n = use_i18n(); - let (room_name, set_room_name) = signal(String::new()); - - let cmd_tx = use_context::>() - .expect("UnboundedSender not found in context"); - let auth_username = - use_context::>>().expect("auth_username not found in context"); - - let cmd_tx_create = cmd_tx.clone(); - let cmd_tx_join = cmd_tx.clone(); - let cmd_tx_bot = cmd_tx; - - view! { - - } -} diff --git a/clients/web-game/src/components/mod.rs b/clients/web-game/src/components/mod.rs deleted file mode 100644 index 7ae2fcb..0000000 --- a/clients/web-game/src/components/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod board; -mod connecting_screen; -mod die; -mod game_screen; -mod login_screen; -mod score_panel; -mod scoring; - -pub use connecting_screen::ConnectingScreen; -pub use game_screen::GameScreen; -pub use login_screen::LoginScreen; diff --git a/clients/web-game/src/components/score_panel.rs b/clients/web-game/src/components/score_panel.rs deleted file mode 100644 index ab97a39..0000000 --- a/clients/web-game/src/components/score_panel.rs +++ /dev/null @@ -1,70 +0,0 @@ -use leptos::prelude::*; -use trictrac_store::Jan; - -use crate::i18n::*; -use crate::trictrac::types::PlayerScore; - -pub fn jan_label(jan: &Jan) -> String { - let i18n = use_i18n(); - match jan { - Jan::FilledQuarter => t_string!(i18n, jan_filled_quarter).to_owned(), - Jan::TrueHitSmallJan => t_string!(i18n, jan_true_hit_small).to_owned(), - Jan::TrueHitBigJan => t_string!(i18n, jan_true_hit_big).to_owned(), - Jan::TrueHitOpponentCorner => t_string!(i18n, jan_true_hit_corner).to_owned(), - Jan::FirstPlayerToExit => t_string!(i18n, jan_first_exit).to_owned(), - Jan::SixTables => t_string!(i18n, jan_six_tables).to_owned(), - Jan::TwoTables => t_string!(i18n, jan_two_tables).to_owned(), - Jan::Mezeas => t_string!(i18n, jan_mezeas).to_owned(), - Jan::FalseHitSmallJan => t_string!(i18n, jan_false_hit_small).to_owned(), - Jan::FalseHitBigJan => t_string!(i18n, jan_false_hit_big).to_owned(), - Jan::ContreTwoTables => t_string!(i18n, jan_contre_two).to_owned(), - Jan::ContreMezeas => t_string!(i18n, jan_contre_mezeas).to_owned(), - Jan::HelplessMan => t_string!(i18n, jan_helpless_man).to_owned(), - } -} - -#[component] -pub fn PlayerScorePanel(score: PlayerScore, is_you: bool) -> impl IntoView { - let i18n = use_i18n(); - - let points_pct = format!("{}%", (score.points as u32 * 100 / 12).min(100)); - let points_val = format!("{}/12", score.points); - let holes = score.holes; - let can_bredouille = score.can_bredouille; - - // 12 peg holes; filled up to `holes` - let pegs: Vec = (1u8..=12) - .map(|i| { - let cls = if i <= holes { "peg-hole filled" } else { "peg-hole" }; - view! {
}.into_any() - }) - .collect(); - - view! { -
-
- - {score.name} - {is_you.then(|| t!(i18n, you_suffix))} - -
-
-
- {t!(i18n, points_label)} -
-
-
- {points_val} - {can_bredouille.then(|| view! { - "B" - })} -
-
- {t!(i18n, holes_label)} -
{pegs}
- {format!("{holes}/12")} -
-
-
- } -} diff --git a/clients/web-game/src/components/scoring.rs b/clients/web-game/src/components/scoring.rs deleted file mode 100644 index 4a19a81..0000000 --- a/clients/web-game/src/components/scoring.rs +++ /dev/null @@ -1,209 +0,0 @@ -use futures::channel::mpsc::UnboundedSender; -#[cfg(target_arch = "wasm32")] -use gloo_timers::future::TimeoutFuture; -use leptos::prelude::*; -use trictrac_store::CheckerMove; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen_futures::spawn_local; -#[cfg(target_arch = "wasm32")] -use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; - -use crate::app::NetCommand; -use crate::i18n::*; -use crate::trictrac::types::{JanEntry, PlayerAction, ScoredEvent, SerTurnStage}; - -use super::score_panel::jan_label; - -/// One row in the scoring panel. Sets the hovered-moves context on enter -/// (so board shows arrows for that jan's moves), but does NOT clear on -/// leave — clearing is handled by the outer wrapper's mouseleave so that -/// arrows persist while the pointer moves between rows. -fn scoring_jan_row(entry: JanEntry) -> impl IntoView { - let i18n = use_i18n(); - let hovered = use_context::>>(); - let jan = entry.jan; - let is_double = entry.is_double; - let ways_tag = format!("×{}", entry.ways); - let pts_str = format!("+{}", entry.total); - let moves_hover = entry.moves.clone(); - - view! { -
- {move || jan_label(&jan)} - {move || if is_double { - t_string!(i18n, jan_double).to_owned() - } else { - t_string!(i18n, jan_simple).to_owned() - }} - {ways_tag} - {pts_str} -
- } -} - -#[component] -pub fn ScoringPanel( - event: ScoredEvent, - turn_stage: SerTurnStage, - #[prop(default = false)] is_opponent: bool, -) -> impl IntoView { - let i18n = use_i18n(); - let cmd_tx = use_context::>() - .expect("UnboundedSender not found in context"); - - let points_earned = event.points_earned; - let holes_gained = event.holes_gained; - let holes_total = event.holes_total; - let bredouille = event.bredouille; - let show_hold_go = !is_opponent && turn_stage == SerTurnStage::HoldOrGoChoice; - let panel_class = if is_opponent { - "scoring-panel scoring-panel-opp" - } else { - "scoring-panel" - }; - - // ── Lifecycle signals ────────────────────────────────────────────────── - // peeked: added after 3.4 s (slide to peek strip) - // revealed: added on first hover of the peek strip (stay open permanently) - let peeked = RwSignal::new(false); - let revealed = RwSignal::new(false); - - // ── Collect all moves from all jans for automatic arrow display ──────── - let all_moves: Vec<(CheckerMove, CheckerMove)> = event - .jans - .iter() - .flat_map(|e| e.moves.iter().cloned()) - .collect(); - let all_moves_click = all_moves.clone(); - let all_moves_enter = all_moves.clone(); - - let hovered_ctx = use_context::>>(); - - // On mount: show all this event's moves as board arrows immediately, - // then after 3.4 s slide to peek and clear the arrows. - // - // Two important constraints: - // 1. The initial hm.set() must be deferred (spawn_local, not sync in body) - // to avoid writing a reactive signal mid-render while Board reads it — - // that triggers Leptos's cycle guard → `unreachable` WASM panic. - // 2. The cancellation flag must be Rc>, NOT RwSignal. - // RwSignal is a NodeId into Leptos's arena; the arena slot is freed - // when ScoringPanel's owner drops (on every GameScreen remount). If the - // 3.4 s future outlives the component and calls is_alive.get_untracked() - // on a freed slot, that also panics with `unreachable`. Rc> - // is reference-counted outside the arena and stays valid for as long as - // the future holds onto it. - #[cfg(target_arch = "wasm32")] - if let Some(hm) = hovered_ctx { - let is_alive = Arc::new(AtomicBool::new(true)); - let is_alive_cleanup = is_alive.clone(); - // on_cleanup requires Send + Sync; Arc satisfies both. - on_cleanup(move || is_alive_cleanup.store(false, Ordering::Relaxed)); - - spawn_local(async move { - // Show arrows (runs in the next microtask, after render settles). - hm.set(all_moves); - - TimeoutFuture::new(3_400).await; - // Guard: component may have been destroyed while we were waiting. - // is_alive was set to false by on_cleanup, which runs before Leptos - // frees the signal arena slots — so peeked is still valid iff this - // returns true. - if !is_alive.load(Ordering::Relaxed) { - return; - } - hm.set(vec![]); - peeked.set(true); - }); - } - - let jan_rows: Vec<_> = event.jans.into_iter().map(scoring_jan_row).collect(); - - view! { - // ── Outer wrapper: owns the slide / peek / reveal animation ─────── - // pointer-events are on by default (parent .side-panel sets none, - // and .scoring-panel-wrapper overrides back to auto in CSS). -
-
-
- {move || if is_opponent { - t_string!(i18n, opp_scored_pts, n = points_earned) - } else { - t_string!(i18n, scored_pts, n = points_earned) - }} -
- {jan_rows} - {(holes_gained > 0).then(|| view! { -
- {move || if is_opponent { - t_string!(i18n, opp_hole_made, holes = holes_total) - } else { - t_string!(i18n, hole_made, holes = holes_total) - }} - {bredouille.then(|| view! { - - {move || t_string!(i18n, bredouille_applied)} - - })} -
- })} - {show_hold_go.then(|| { - let dismissed = RwSignal::new(false); - view! { -
- // stop_propagation so these buttons don't also toggle the panel - - -
- } - })} -
-
- } -} diff --git a/clients/web-game/src/main.rs b/clients/web-game/src/main.rs deleted file mode 100644 index f0952a0..0000000 --- a/clients/web-game/src/main.rs +++ /dev/null @@ -1,13 +0,0 @@ -leptos_i18n::load_locales!(); - -mod app; -mod components; -mod sound; -mod trictrac; - -use app::App; -use leptos::prelude::*; - -fn main() { - mount_to_body(|| view! { }) -} diff --git a/clients/web-game/src/sound.rs b/clients/web-game/src/sound.rs deleted file mode 100644 index 5637ccd..0000000 --- a/clients/web-game/src/sound.rs +++ /dev/null @@ -1,182 +0,0 @@ -//! Synthesised sound effects using the Web Audio API. -//! -//! All public functions are no-ops on non-WASM targets so callers need no -//! `#[cfg]` guards themselves. - -#[cfg(target_arch = "wasm32")] -mod inner { - use std::cell::RefCell; - use web_sys::{AudioContext, OscillatorType}; - - thread_local! { - static CTX: RefCell> = const { RefCell::new(None) }; - } - - fn with_ctx(f: F) { - CTX.with(|cell| { - let mut opt = cell.borrow_mut(); - if opt.is_none() { - *opt = AudioContext::new().ok(); - } - if let Some(ctx) = opt.as_ref() { - f(ctx); - } - }); - } - - /// Schedule a single oscillator tone with an exponential gain decay. - /// - /// - `start_offset`: seconds from `ctx.current_time()` when the tone starts - /// - `duration`: how long (in seconds) until gain reaches ~0 - fn play_tone( - ctx: &AudioContext, - freq: f32, - gain: f32, - duration: f64, - start_offset: f64, - wave: OscillatorType, - ) { - let t0 = ctx.current_time() + start_offset; - let t1 = t0 + duration; - - let Ok(osc) = ctx.create_oscillator() else { - return; - }; - let Ok(gain_node) = ctx.create_gain() else { - return; - }; - - osc.set_type(wave); - osc.frequency().set_value(freq); - - let gain_param = gain_node.gain(); - let _ = gain_param.set_value_at_time(gain, t0); - // exponential_ramp requires a positive target; 0.001 is inaudible - let _ = gain_param.exponential_ramp_to_value_at_time(0.001, t1); - - let dest = ctx.destination(); - let _ = osc.connect_with_audio_node(&gain_node); - let _ = gain_node.connect_with_audio_node(&dest); - - let _ = osc.start_with_when(t0); - let _ = osc.stop_with_when(t1); - } - - /// Short wooden clack: sine fundamental + triangle body resonance, ~80 ms. - pub fn play_checker_move() { - with_ctx(|ctx| { - // Sine at 300 Hz for the clean attack click - play_tone(ctx, 300.0, 0.55, 0.080, 0.000, OscillatorType::Sine); - // Triangle at 150 Hz for the woody body resonance - play_tone(ctx, 150.0, 0.35, 0.070, 0.005, OscillatorType::Triangle); - // Sub at 80 Hz for weight - play_tone(ctx, 80.0, 0.20, 0.060, 0.008, OscillatorType::Triangle); - }); - } - - /// Cinematic dice roll: ~500 ms of rolling texture + 5 impact transients. - /// - /// Two layers: - /// - A dense series of detuned sawtooth bursts that thin out over time, - /// modelling the continuous scrape/rattle of dice tumbling. - /// - Five percussive impacts (square clicks + triangle thuds) whose - /// inter-arrival gap shrinks as the dice decelerate and settle. - pub fn play_dice_roll_cinematic() { - with_ctx(|ctx| { - // ── Continuous rolling texture ───────────────────────────────── - // 16 steps over 440 ms; each step is two detuned sawtooth waves - // (the interference between them produces a noise-like texture). - // Gain fades by ~55 % from first to last step. - const N: u32 = 16; - for i in 0..N { - let t = i as f64 * 0.028; - let g = 0.017 * (1.0 - i as f32 / N as f32 * 0.55); - // Quasi-random frequencies so each step sounds different. - let f1 = 310.0 + (i as f32 * 29.3 % 280.0); - let f2 = 480.0 + (i as f32 * 43.7 % 220.0); - play_tone(ctx, f1, g, 0.028, t, OscillatorType::Sawtooth); - play_tone(ctx, f2, g * 0.70, 0.028, t, OscillatorType::Sawtooth); - } - - // ── Impact transients ────────────────────────────────────────── - // Gaps narrow toward the end (0.13 → 0.11 → 0.10 → 0.08 s), - // mimicking dice decelerating and settling. - let impacts: &[(f64, f32)] = &[(0.00, 1.00), (0.13, 0.8), (0.24, 0.54), (0.34, 0.30)]; - for &(t_off, amp) in impacts { - // Hard click: bright square partials → percussive attack - for &freq in &[700.0f32, 1_050.0, 1_500.0] { - play_tone(ctx, freq, amp * 0.03, 0.022, t_off, OscillatorType::Square); - } - // Woody body thud: two low triangle partials - play_tone( - ctx, - 130.0, - amp * 0.05, - 0.070, - t_off, - OscillatorType::Triangle, - ); - play_tone( - ctx, - 68.0, - amp * 0.07, - 0.090, - t_off, - OscillatorType::Triangle, - ); - } - }); - } - - /// Play the pre-recorded dice-roll MP3 asset. - pub fn play_dice_roll() { - if let Ok(audio) = web_sys::HtmlAudioElement::new_with_src("/diceroll.mp3") { - audio.set_volume(0.2); - let _ = audio.play(); - } - } - - /// Ascending three-note chime (C5 – E5 – G5). - pub fn play_points_scored() { - with_ctx(|ctx| { - let notes: [(f32, f64); 3] = [(523.25, 0.0), (659.25, 0.14), (783.99, 0.28)]; - for (freq, offset) in notes { - play_tone(ctx, freq, 0.28, 0.30, offset, OscillatorType::Sine); - } - }); - } - - /// Triumphant four-note fanfare (C5 – E5 – G5 – C6). - pub fn play_hole_scored() { - with_ctx(|ctx| { - let notes: [(f32, f64, f64); 4] = [ - (523.25, 0.0, 0.35), - (659.25, 0.17, 0.35), - (783.99, 0.34, 0.35), - (1046.5, 0.51, 0.55), - ]; - for (freq, offset, dur) in notes { - play_tone(ctx, freq, 0.32, dur, offset, OscillatorType::Sine); - } - }); - } -} - -// ── Public API: WASM delegates to `inner`, other targets are no-ops ─────────── - -#[cfg(target_arch = "wasm32")] -pub use inner::{ - play_checker_move, play_dice_roll, play_dice_roll_cinematic, play_hole_scored, - play_points_scored, -}; - -#[cfg(not(target_arch = "wasm32"))] -pub fn play_checker_move() {} -#[cfg(not(target_arch = "wasm32"))] -pub fn play_dice_roll() {} -#[cfg(not(target_arch = "wasm32"))] -pub fn play_dice_roll_cinematic() {} -#[cfg(not(target_arch = "wasm32"))] -pub fn play_points_scored() {} -#[cfg(not(target_arch = "wasm32"))] -pub fn play_hole_scored() {} diff --git a/clients/web-game/src/trictrac/backend.rs b/clients/web-game/src/trictrac/backend.rs deleted file mode 100644 index 04b2a36..0000000 --- a/clients/web-game/src/trictrac/backend.rs +++ /dev/null @@ -1,487 +0,0 @@ -use backbone_lib::traits::{BackEndArchitecture, BackendCommand}; -use trictrac_store::{Dice, DiceRoller, GameEvent, GameState, TurnStage}; - -use crate::trictrac::types::{GameDelta, PlayerAction, PreGameRollState, SerStage, ViewState}; - -// Store PlayerId (u64) values used for the two players. -const HOST_PLAYER_ID: u64 = 1; -const GUEST_PLAYER_ID: u64 = 2; - -pub struct TrictracBackend { - game: GameState, - dice_roller: DiceRoller, - commands: Vec>, - view_state: ViewState, - /// Arrival flags: have host (index 0) and guest (index 1) joined? - arrived: [bool; 2], - /// Die rolled by each player during the ceremony ([host, guest]). - pre_game_dice: [Option; 2], - /// Number of tied rounds so far. - tie_count: u8, - /// True while the first-player ceremony is running. - ceremony_started: bool, -} - -impl TrictracBackend { - fn sync_view_state(&mut self) { - let mut vs = ViewState::from_game_state(&self.game, HOST_PLAYER_ID, GUEST_PLAYER_ID); - if self.ceremony_started { - vs.stage = SerStage::PreGameRoll; - vs.pre_game_roll = Some(PreGameRollState { - host_die: self.pre_game_dice[0], - guest_die: self.pre_game_dice[1], - tie_count: self.tie_count, - }); - // Both players roll independently; no single "active" player. - vs.active_mp_player = None; - } - self.view_state = vs; - } - - fn broadcast_state(&mut self) { - self.sync_view_state(); - let delta = GameDelta { - state: self.view_state.clone(), - }; - self.commands.push(BackendCommand::Delta(delta)); - } - - /// Process one ceremony die-roll for `mp_player` (0 = host, 1 = guest). - fn handle_pre_game_roll(&mut self, mp_player: u16) { - let idx = mp_player as usize; - // Ignore if this player already rolled. - if self.pre_game_dice[idx].is_some() { - return; - } - let single = self.dice_roller.roll().values.0; - self.pre_game_dice[idx] = Some(single); - - if let [Some(h), Some(g)] = self.pre_game_dice { - // Both have rolled — broadcast both dice before resolving. - self.broadcast_state(); - if h == g { - // Tie: reset for another round. - self.tie_count += 1; - self.pre_game_dice = [None; 2]; - self.broadcast_state(); - } else { - // Highest die goes first. - let goes_first = if h > g { - HOST_PLAYER_ID - } else { - GUEST_PLAYER_ID - }; - self.ceremony_started = false; - let _ = self.game.consume(&GameEvent::BeginGame { goes_first }); - // Use pre-game dice roll for the first move - let _ = self.game.consume(&GameEvent::Roll { - player_id: goes_first, - }); - let _ = self.game.consume(&GameEvent::RollResult { - player_id: goes_first, - dice: Dice { values: (g, h) }, - }); - self.broadcast_state(); - } - } else { - // Only one die rolled so far — broadcast the partial result. - self.broadcast_state(); - } - } - - /// Roll dice using the store's DiceRoller and fire Roll + RollResult events. - fn do_roll(&mut self) { - let dice = self.dice_roller.roll(); - let player_id = self.game.active_player_id; - let _ = self.game.consume(&GameEvent::Roll { player_id }); - let _ = self - .game - .consume(&GameEvent::RollResult { player_id, dice }); - - // Drive automatic stages that require no player input. - self.drive_automatic_stages(); - } - - /// Advance through stages that can be resolved without player input - /// (MarkPoints, MarkAdvPoints). - fn drive_automatic_stages(&mut self) { - loop { - // Stop if the game has already ended (stage transitions to Ended but - // turn_stage may still be MarkPoints when schools_enabled=false, which - // makes consume(Mark) a no-op and would cause an infinite loop). - if self.game.stage == trictrac_store::Stage::Ended { - break; - } - let player_id = self.game.active_player_id; - match self.game.turn_stage { - TurnStage::MarkPoints | TurnStage::MarkAdvPoints => { - let _ = self.game.consume(&GameEvent::Mark { - player_id, - points: self.game.dice_points.0.max(self.game.dice_points.1), - }); - } - _ => break, - } - } - } -} - -impl TrictracBackend { - pub fn get_game(&self) -> &GameState { - &self.game - } -} - -impl BackEndArchitecture for TrictracBackend { - fn new(_rule_variation: u16) -> Self { - let mut game = GameState::new(false); - game.init_player("Blancs"); - game.init_player("Noirs"); - - let view_state = ViewState::from_game_state(&game, HOST_PLAYER_ID, GUEST_PLAYER_ID); - - TrictracBackend { - game, - dice_roller: DiceRoller::default(), - commands: Vec::new(), - view_state, - arrived: [false; 2], - pre_game_dice: [None; 2], - tie_count: 0, - ceremony_started: false, - } - } - - fn from_bytes(_rule_variation: u16, bytes: &[u8]) -> Option { - let view_state: ViewState = serde_json::from_slice(bytes).ok()?; - // Reconstruct a fresh game; full state restore is not yet implemented. - let mut backend = Self::new(_rule_variation); - backend.view_state = view_state; - Some(backend) - } - - fn player_arrival(&mut self, mp_player: u16) { - if mp_player > 1 { - self.commands - .push(BackendCommand::KickPlayer { player: mp_player }); - return; - } - self.arrived[mp_player as usize] = true; - - // Cancel any reconnect timer for this player. - self.commands.push(BackendCommand::CancelTimer { - timer_id: mp_player, - }); - - // Start the ceremony once both players have arrived. - if self.arrived[0] - && self.arrived[1] - && self.game.stage == trictrac_store::Stage::PreGame - && !self.ceremony_started - { - self.ceremony_started = true; - self.pre_game_dice = [None; 2]; - self.tie_count = 0; - self.sync_view_state(); - self.commands.push(BackendCommand::ResetViewState); - } else { - self.broadcast_state(); - } - } - - fn player_departure(&mut self, mp_player: u16) { - if mp_player > 1 { - return; - } - self.arrived[mp_player as usize] = false; - // Give 60 seconds to reconnect before terminating the room. - self.commands.push(BackendCommand::SetTimer { - timer_id: mp_player, - duration: 60.0, - }); - } - - fn inform_rpc(&mut self, mp_player: u16, action: PlayerAction) { - // During the first-player ceremony only PreGameRoll actions are accepted. - if self.ceremony_started { - if matches!(action, PlayerAction::PreGameRoll) { - self.handle_pre_game_roll(mp_player); - } - return; - } - - if self.game.stage == trictrac_store::Stage::Ended { - return; - } - - let store_id = if mp_player == 0 { - HOST_PLAYER_ID - } else { - GUEST_PLAYER_ID - }; - - // Only the active player may act (except during Chance-like waiting stages). - if self.game.active_player_id != store_id { - return; - } - - match action { - PlayerAction::Roll => { - if self.game.turn_stage == TurnStage::RollDice { - self.do_roll(); - } - } - PlayerAction::Move(m1, m2) => { - if self.game.turn_stage != TurnStage::Move - && self.game.turn_stage != TurnStage::HoldOrGoChoice - { - return; - } - let event = GameEvent::Move { - player_id: store_id, - moves: (m1, m2), - }; - if self.game.validate(&event) { - let _ = self.game.consume(&event); - self.drive_automatic_stages(); - } - } - PlayerAction::Go => { - if self.game.turn_stage == TurnStage::HoldOrGoChoice { - let _ = self.game.consume(&GameEvent::Go { - player_id: store_id, - }); - } - } - PlayerAction::Mark => { - if matches!( - self.game.turn_stage, - TurnStage::MarkPoints | TurnStage::MarkAdvPoints - ) { - self.drive_automatic_stages(); - } - } - PlayerAction::PreGameRoll => {} // ignored outside ceremony - } - - self.broadcast_state(); - } - - fn timer_triggered(&mut self, timer_id: u16) { - match timer_id { - 0 | 1 => { - // Reconnect grace period expired for host (0) or guest (1). - self.commands.push(BackendCommand::TerminateRoom); - } - _ => {} - } - } - - fn get_view_state(&self) -> &ViewState { - &self.view_state - } - - fn drain_commands(&mut self) -> Vec> { - std::mem::take(&mut self.commands) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::trictrac::types::{SerStage, SerTurnStage}; - use backbone_lib::traits::BackEndArchitecture; - - fn make_backend() -> TrictracBackend { - TrictracBackend::new(0) - } - - /// Helper: drain and return only Delta commands, extracting their ViewStates. - fn drain_deltas(b: &mut TrictracBackend) -> Vec { - b.drain_commands() - .into_iter() - .filter_map(|cmd| match cmd { - BackendCommand::Delta(d) => Some(d.state), - BackendCommand::ResetViewState => Some(b.view_state.clone()), - _ => None, - }) - .collect() - } - - /// Drive the ceremony to completion (both players roll until one wins). - fn complete_ceremony(b: &mut TrictracBackend) { - loop { - if b.get_view_state().stage != SerStage::PreGameRoll { - break; - } - let pgr = b.get_view_state().pre_game_roll.clone().unwrap_or_default(); - let host_needs = pgr.host_die.is_none(); - let guest_needs = pgr.guest_die.is_none(); - if !host_needs && !guest_needs { - break; // both rolled but stage not yet resolved — shouldn't happen - } - if host_needs { - b.inform_rpc(0, PlayerAction::PreGameRoll); - } - if guest_needs { - b.inform_rpc(1, PlayerAction::PreGameRoll); - } - b.drain_commands(); - } - } - - #[test] - fn both_players_arrive_starts_ceremony() { - let mut b = make_backend(); - b.player_arrival(0); // host - b.drain_commands(); - b.player_arrival(1); // guest - let cmds = b.drain_commands(); - - // ResetViewState should have been issued to start the ceremony. - let has_reset = cmds - .iter() - .any(|c| matches!(c, BackendCommand::ResetViewState)); - assert!( - has_reset, - "expected ResetViewState after both players arrive" - ); - - // Stage should now be PreGameRoll, not InGame. - assert_eq!(b.get_view_state().stage, SerStage::PreGameRoll); - } - - #[test] - fn ceremony_resolves_to_in_game() { - let mut b = make_backend(); - b.player_arrival(0); - b.player_arrival(1); - b.drain_commands(); - - complete_ceremony(&mut b); - - assert_eq!(b.get_view_state().stage, SerStage::InGame); - } - - #[test] - fn ceremony_any_order_allowed() { - let mut b = make_backend(); - b.player_arrival(0); - b.player_arrival(1); - b.drain_commands(); - - // Guest may roll before host. - b.inform_rpc(1, PlayerAction::PreGameRoll); - let states = drain_deltas(&mut b); - assert!( - !states.is_empty(), - "guest PreGameRoll should broadcast a state" - ); - let pgr = states.last().unwrap().pre_game_roll.as_ref().unwrap(); - assert!( - pgr.guest_die.is_some(), - "guest die should be set after guest rolls" - ); - assert!(pgr.host_die.is_none(), "host die should still be blank"); - } - - #[test] - fn unknown_player_kicked() { - let mut b = make_backend(); - b.player_arrival(99); - let cmds = b.drain_commands(); - assert!(cmds - .iter() - .any(|c| matches!(c, BackendCommand::KickPlayer { player: 99 }))); - } - - #[test] - fn roll_advances_to_move_or_hold() { - let mut b = make_backend(); - b.player_arrival(0); - b.player_arrival(1); - b.drain_commands(); - - // Complete ceremony before rolling. - complete_ceremony(&mut b); - - // Roll for whoever won the ceremony (either player could go first). - let first_player = b - .get_view_state() - .active_mp_player - .expect("someone should be active"); - b.inform_rpc(first_player, PlayerAction::Roll); - let states = drain_deltas(&mut b); - assert!(!states.is_empty(), "expected a state broadcast after roll"); - - let last = states.last().unwrap(); - assert!( - matches!( - last.turn_stage, - SerTurnStage::Move | SerTurnStage::HoldOrGoChoice - ), - "expected Move or HoldOrGoChoice after roll, got {:?}", - last.turn_stage - ); - assert_eq!(last.dice, b.get_view_state().dice); - assert!(last.dice.0 >= 1 && last.dice.0 <= 6); - assert!(last.dice.1 >= 1 && last.dice.1 <= 6); - } - - #[test] - fn wrong_player_roll_ignored() { - let mut b = make_backend(); - b.player_arrival(0); - b.player_arrival(1); - b.drain_commands(); - complete_ceremony(&mut b); - - // Identify who goes first and have the OTHER player try to roll. - let active = b.get_view_state().active_mp_player; - let wrong_player = if active == Some(0) { 1u16 } else { 0u16 }; - b.inform_rpc(wrong_player, PlayerAction::Roll); - let cmds = b.drain_commands(); - assert!(cmds.is_empty(), "wrong player roll should be ignored"); - } - - #[test] - fn departure_sets_reconnect_timer() { - let mut b = make_backend(); - b.player_arrival(0); - b.drain_commands(); - b.player_departure(0); - let cmds = b.drain_commands(); - assert!( - cmds.iter() - .any(|c| matches!(c, BackendCommand::SetTimer { timer_id: 0, .. })), - "expected reconnect timer after host departure" - ); - } - - #[test] - fn timer_triggers_terminate_room() { - let mut b = make_backend(); - b.timer_triggered(0); - let cmds = b.drain_commands(); - assert!(cmds - .iter() - .any(|c| matches!(c, BackendCommand::TerminateRoom))); - } -} - -// ── Public API: WASM delegates to `inner`, other targets are no-ops ─────────── - -#[cfg(target_arch = "wasm32")] -mod inner { - use web_sys::console; - - pub fn console_log(message: String) { - console::log_1(&message.into()); - } -} - -#[cfg(target_arch = "wasm32")] -pub use inner::console_log; - -#[cfg(not(target_arch = "wasm32"))] -pub fn console_log(message: String) {} diff --git a/clients/web-game/src/trictrac/bot_local.rs b/clients/web-game/src/trictrac/bot_local.rs deleted file mode 100644 index f94bfc9..0000000 --- a/clients/web-game/src/trictrac/bot_local.rs +++ /dev/null @@ -1,43 +0,0 @@ -use rand::prelude::IndexedRandom; -use trictrac_store::{CheckerMove, Color, GameState, MoveRules, Stage, TurnStage}; - -use crate::trictrac::types::{PlayerAction, PreGameRollState}; - -const GUEST_PLAYER_ID: u64 = 2; - -/// Returns the next action for the bot (mp_player 1 / guest), or None if it is not the bot's turn. -/// `pgr` is the current pre-game ceremony state if the ceremony is in progress. -pub fn bot_decide(game: &GameState, pgr: Option<&PreGameRollState>) -> Option { - // During the ceremony, the bot (guest) rolls when its die is missing. - if game.stage == Stage::PreGame { - if let Some(pgr) = pgr { - if pgr.guest_die.is_none() { - return Some(PlayerAction::PreGameRoll); - } - } - return None; - } - if game.stage == Stage::Ended { - return None; - } - if game.active_player_id != GUEST_PLAYER_ID { - return None; - } - match game.turn_stage { - TurnStage::RollDice => Some(PlayerAction::Roll), - // TurnStage::HoldOrGoChoice => Some(PlayerAction::Go), - TurnStage::Move | TurnStage::HoldOrGoChoice => { - let rules = MoveRules::new(&Color::Black, &game.board, game.dice); - let sequences = rules.get_possible_moves_sequences(true, vec![]); - let mut rng = rand::rng(); - let (m1, m2) = sequences - .choose(&mut rng) - .cloned() - .unwrap_or((CheckerMove::default(), CheckerMove::default())); - // MoveRules with Color::Black mirrors the board internally, so - // returned move coordinates are in mirrored (White) space — mirror back. - Some(PlayerAction::Move(m1.mirror(), m2.mirror())) - } - _ => None, - } -} diff --git a/clients/web-game/src/trictrac/mod.rs b/clients/web-game/src/trictrac/mod.rs deleted file mode 100644 index 38d05bb..0000000 --- a/clients/web-game/src/trictrac/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod backend; -pub mod bot_local; -pub mod types; diff --git a/clients/web-game/src/trictrac/types.rs b/clients/web-game/src/trictrac/types.rs deleted file mode 100644 index 3c0dfe2..0000000 --- a/clients/web-game/src/trictrac/types.rs +++ /dev/null @@ -1,256 +0,0 @@ -use serde::{Deserialize, Serialize}; -use trictrac_store::{CheckerMove, GameState, Jan, Stage, TurnStage}; - -// ── Actions sent by a player to the host backend ───────────────────────────── - -#[derive(Clone, Serialize, Deserialize)] -pub enum PlayerAction { - /// Active player requests a dice roll. - Roll, - /// Both checker moves for this turn. Use `EMPTY_MOVE` (from=0, to=0) when a die - /// has no valid move. - Move(CheckerMove, CheckerMove), - /// Choose to "go" (advance) during HoldOrGoChoice. - Go, - /// Acknowledge point marking (hold / advance points). - Mark, - /// Roll a single die during the pre-game ceremony to decide who goes first. - PreGameRoll, -} - -// ── Incremental state update broadcast to all clients ──────────────────────── - -/// Carries a full state snapshot; `apply_delta` replaces the local state. -/// Simple and correct; can be refined to true diffs later. -#[derive(Clone, Serialize, Deserialize)] -pub struct GameDelta { - pub state: ViewState, -} - -// ── Full game snapshot ──────────────────────────────────────────────────────── - -/// State of the pre-game ceremony where each player rolls one die to decide -/// who goes first. Present only when `stage == SerStage::PreGameRoll`. -#[derive(Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct PreGameRollState { - /// Die value (1–6) rolled by the host; `None` = not yet rolled this round. - pub host_die: Option, - /// Die value (1–6) rolled by the guest; `None` = not yet rolled this round. - pub guest_die: Option, - /// Number of tied rounds so far (0 on the first round). - pub tie_count: u8, -} - -#[derive(Clone, PartialEq, Serialize, Deserialize)] -pub struct ViewState { - /// Board positions: index i = field i+1. Positive = white, negative = black. - pub board: [i8; 24], - pub stage: SerStage, - pub turn_stage: SerTurnStage, - /// Which multiplayer player_id (0 = host, 1 = guest) is the active player. - pub active_mp_player: Option, - /// Scores indexed by multiplayer player_id (0 = host, 1 = guest). - pub scores: [PlayerScore; 2], - /// Last rolled dice values. - pub dice: (u8, u8), - /// Jans (scoring events) triggered by the last dice roll. - pub dice_jans: Vec, - /// Last two checker moves played; default when no move has occurred yet. - pub dice_moves: (CheckerMove, CheckerMove), - /// Present while the pre-game ceremony is in progress. - #[serde(default)] - pub pre_game_roll: Option, -} - -/// One scoring event from a dice roll. -#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)] -pub struct JanEntry { - pub jan: Jan, - /// True when the dice are doubles (both same value) — changes the point value. - /// Special case for HelplessMan: true when *both* dice are unplayable. - pub is_double: bool, - /// Number of distinct move pairs that produce this jan. - pub ways: usize, - /// Points per way (negative = scored against the active player). - pub points_per: i8, - /// Total = points_per × ways. - pub total: i8, - /// The move pairs that produce this jan (for move display). - pub moves: Vec<(CheckerMove, CheckerMove)>, -} - -impl ViewState { - pub fn default_with_names(host_name: &str, guest_name: &str) -> Self { - ViewState { - board: [0i8; 24], - stage: SerStage::PreGame, - turn_stage: SerTurnStage::RollDice, - active_mp_player: None, - scores: [ - PlayerScore { - name: host_name.to_string(), - points: 0, - holes: 0, - can_bredouille: false, - }, - PlayerScore { - name: guest_name.to_string(), - points: 0, - holes: 0, - can_bredouille: false, - }, - ], - dice: (0, 0), - dice_jans: Vec::new(), - dice_moves: (CheckerMove::default(), CheckerMove::default()), - pre_game_roll: None, - } - } - - pub fn apply_delta(&mut self, delta: &GameDelta) { - *self = delta.state.clone(); - } - - /// Convert a store `GameState` to a `ViewState`. - /// `host_store_id` and `guest_store_id` are the trictrac `PlayerId`s assigned - /// to the host (mp player 0) and guest (mp player 1) respectively. - pub fn from_game_state(gs: &GameState, host_store_id: u64, guest_store_id: u64) -> Self { - let board_vec = gs.board.to_vec(); - let board: [i8; 24] = board_vec.try_into().expect("board is always 24 fields"); - - let stage = match gs.stage { - Stage::PreGame => SerStage::PreGame, - Stage::InGame => SerStage::InGame, - Stage::Ended => SerStage::Ended, - }; - let turn_stage = match gs.turn_stage { - TurnStage::RollDice => SerTurnStage::RollDice, - TurnStage::RollWaiting => SerTurnStage::RollWaiting, - TurnStage::MarkPoints => SerTurnStage::MarkPoints, - TurnStage::HoldOrGoChoice => SerTurnStage::HoldOrGoChoice, - TurnStage::Move => SerTurnStage::Move, - TurnStage::MarkAdvPoints => SerTurnStage::MarkAdvPoints, - }; - - let active_mp_player = if gs.active_player_id == host_store_id { - Some(0) - } else if gs.active_player_id == guest_store_id { - Some(1) - } else { - None - }; - - let score_for = |store_id: u64| -> PlayerScore { - gs.players - .get(&store_id) - .map(|p| PlayerScore { - name: p.name.clone(), - points: p.points, - holes: p.holes, - can_bredouille: p.can_bredouille, - }) - .unwrap_or_else(|| PlayerScore { - name: String::new(), - points: 0, - holes: 0, - can_bredouille: false, - }) - }; - - // is_double for scoring: dice show the same value (both dice identical). - // Exception: HelplessMan uses a special rule (see below). - let dice_are_double = gs.dice.values.0 == gs.dice.values.1; - - // Build JanEntry list from the PossibleJans map. - let empty_move = CheckerMove::new(0, 0).unwrap_or_default(); - let mut dice_jans: Vec = gs - .dice_jans - .iter() - .map(|(jan, moves)| { - // HelplessMan: is_double = true only when *both* dice are unplayable - // (the moves list contains a single (empty, empty) sentinel). - let is_double = if *jan == Jan::HelplessMan { - moves - .first() - .map(|&(m1, m2)| m1 == empty_move && m2 == empty_move) - .unwrap_or(false) - } else { - dice_are_double - }; - let points_per = jan.get_points(is_double); - let ways = moves.len(); - let total = points_per.saturating_mul(ways as i8); - JanEntry { - jan: jan.clone(), - is_double, - ways, - points_per, - total, - moves: moves.clone(), - } - }) - .collect(); - // Sort: highest total first, most-negative last. - dice_jans.sort_by_key(|e| std::cmp::Reverse(e.total)); - - ViewState { - board, - stage, - turn_stage, - active_mp_player, - scores: [score_for(host_store_id), score_for(guest_store_id)], - dice: (gs.dice.values.0, gs.dice.values.1), - dice_jans, - dice_moves: gs.dice_moves, - pre_game_roll: None, - } - } -} - -// ── Scored event (notification) ────────────────────────────────────────── - -/// Points scored in a single scoring event, used for the notification panel. -#[derive(Clone, PartialEq)] -pub struct ScoredEvent { - /// Raw points earned (sum of jan values; before hole wrapping). - pub points_earned: u8, - /// Number of holes gained (0 = no hole). - pub holes_gained: u8, - /// Total holes after this event. - pub holes_total: u8, - /// Was bredouille active when the hole was made (doubles hole count)? - pub bredouille: bool, - /// Contributing jans from this player's perspective (totals always positive). - pub jans: Vec, -} - -// ── Score snapshot ──────────────────────────────────────────────────────────── - -#[derive(Clone, PartialEq, Serialize, Deserialize)] -pub struct PlayerScore { - pub name: String, - pub points: u8, - pub holes: u8, - pub can_bredouille: bool, -} - -// ── Serialisable mirrors of store enums ────────────────────────────────────── - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum SerStage { - PreGame, - /// Both players have arrived; ceremony in progress to decide who goes first. - PreGameRoll, - InGame, - Ended, -} - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub enum SerTurnStage { - RollDice, - RollWaiting, - MarkPoints, - HoldOrGoChoice, - Move, - MarkAdvPoints, -} diff --git a/clients/web-user-portal/Cargo.toml b/clients/web-user-portal/Cargo.toml deleted file mode 100644 index 6afa767..0000000 --- a/clients/web-user-portal/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "web-user-portal" -version = "0.1.0" -edition = "2024" - -[dependencies] -leptos = { version = "0.7", features = ["csr"] } -leptos_router = { version = "0.7" } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1" - -[target.'cfg(target_arch = "wasm32")'.dependencies] -wasm-bindgen = "0.2" -wasm-bindgen-futures = "0.4" -gloo-net = { version = "0.5", features = ["http"] } -js-sys = "0.3" -web-sys = { version = "0.3", features = ["RequestCredentials"] } diff --git a/clients/web-user-portal/Trunk.toml b/clients/web-user-portal/Trunk.toml deleted file mode 100644 index 57a2aaa..0000000 --- a/clients/web-user-portal/Trunk.toml +++ /dev/null @@ -1,2 +0,0 @@ -[serve] -port = 9092 diff --git a/clients/web-user-portal/assets/style.css b/clients/web-user-portal/assets/style.css deleted file mode 100644 index 3e7462a..0000000 --- a/clients/web-user-portal/assets/style.css +++ /dev/null @@ -1,103 +0,0 @@ -*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - -body { - font-family: system-ui, sans-serif; - background: #f5f5f5; - color: #1a1a1a; - min-height: 100vh; -} - -nav { - background: #1a1a2e; - color: #fff; - padding: 0.75rem 1.5rem; - display: flex; - align-items: center; - gap: 1.5rem; -} -nav a { color: #ccc; text-decoration: none; } -nav a:hover { color: #fff; } -nav .brand { font-weight: 700; font-size: 1.1rem; color: #fff; } -nav .spacer { flex: 1; } - -main { max-width: 800px; margin: 2rem auto; padding: 0 1rem; } - -h1 { font-size: 1.6rem; margin-bottom: 1rem; } -h2 { font-size: 1.2rem; margin-bottom: 0.75rem; } - -.card { - background: #fff; - border-radius: 8px; - padding: 1.5rem; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); - margin-bottom: 1.5rem; -} - -.tabs { display: flex; gap: 0; margin-bottom: 1.5rem; } -.tab-btn { - padding: 0.5rem 1.25rem; - border: 1px solid #ddd; - background: #f5f5f5; - cursor: pointer; - font-size: 0.95rem; -} -.tab-btn:first-child { border-radius: 6px 0 0 6px; } -.tab-btn:last-child { border-radius: 0 6px 6px 0; border-left: none; } -.tab-btn.active { background: #1a1a2e; color: #fff; border-color: #1a1a2e; } - -label { display: block; font-size: 0.85rem; margin-bottom: 0.25rem; color: #555; } -input[type=text], input[type=email], input[type=password] { - width: 100%; - padding: 0.5rem 0.75rem; - border: 1px solid #ddd; - border-radius: 5px; - font-size: 0.95rem; - margin-bottom: 0.75rem; -} -input:focus { outline: none; border-color: #1a1a2e; } - -button[type=submit], .btn { - padding: 0.5rem 1.25rem; - background: #1a1a2e; - color: #fff; - border: none; - border-radius: 5px; - cursor: pointer; - font-size: 0.95rem; -} -button[type=submit]:hover, .btn:hover { background: #2d2d5e; } -button[type=submit]:disabled { opacity: 0.6; cursor: not-allowed; } - -.error { color: #c0392b; font-size: 0.875rem; margin-top: 0.5rem; } -.success { color: #27ae60; font-size: 0.875rem; margin-top: 0.5rem; } - -.stats-grid { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 1rem; - margin-bottom: 1.5rem; -} -.stat-box { - background: #fff; - border-radius: 8px; - padding: 1rem; - text-align: center; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); -} -.stat-box .value { font-size: 2rem; font-weight: 700; } -.stat-box .label { font-size: 0.8rem; color: #777; margin-top: 0.25rem; } - -table { width: 100%; border-collapse: collapse; font-size: 0.9rem; } -th { text-align: left; padding: 0.5rem 0.75rem; border-bottom: 2px solid #eee; color: #555; } -td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #f0f0f0; } -tr:last-child td { border-bottom: none; } -tr:hover td { background: #fafafa; } -a { color: #2c5cc5; text-decoration: none; } -a:hover { text-decoration: underline; } - -.outcome-win { color: #27ae60; font-weight: 600; } -.outcome-loss { color: #c0392b; font-weight: 600; } -.outcome-draw { color: #e67e22; font-weight: 600; } - -.loading { color: #777; padding: 1rem 0; } -.empty { color: #aaa; font-style: italic; padding: 1rem 0; } diff --git a/clients/web-user-portal/index.html b/clients/web-user-portal/index.html deleted file mode 100644 index 135091c..0000000 --- a/clients/web-user-portal/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - Player Portal - - - - - diff --git a/clients/web-user-portal/src/api.rs b/clients/web-user-portal/src/api.rs deleted file mode 100644 index b6dced9..0000000 --- a/clients/web-user-portal/src/api.rs +++ /dev/null @@ -1,191 +0,0 @@ -use serde::{Deserialize, Serialize}; - -// In debug builds trunk serves on 9092 while the relay is on 8080 — use full URL. -// In release builds the portal is served by the relay itself — use relative paths. -#[cfg(debug_assertions)] -const BASE: &str = "http://localhost:8080"; -#[cfg(not(debug_assertions))] -const BASE: &str = ""; - -fn url(path: &str) -> String { - format!("{BASE}{path}") -} - -// ── Response types ──────────────────────────────────────────────────────────── - -#[derive(Clone, Debug, Deserialize)] -pub struct MeResponse { - pub id: i64, - pub username: String, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct UserProfile { - pub id: i64, - pub username: String, - pub created_at: i64, - pub total_games: i64, - pub wins: i64, - pub losses: i64, - pub draws: i64, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct GameSummary { - pub id: i64, - pub game_id: String, - pub room_code: String, - pub started_at: i64, - pub ended_at: Option, - pub result: Option, - pub outcome: Option, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct GamesResponse { - pub games: Vec, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct Participant { - pub player_id: i64, - pub outcome: Option, - pub username: Option, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct GameDetail { - pub id: i64, - pub game_id: String, - pub room_code: String, - pub started_at: i64, - pub ended_at: Option, - pub result: Option, - pub participants: Vec, -} - -// ── Request bodies ──────────────────────────────────────────────────────────── - -#[derive(Serialize)] -pub struct RegisterBody<'a> { - pub username: &'a str, - pub email: &'a str, - pub password: &'a str, -} - -#[derive(Serialize)] -pub struct LoginBody<'a> { - pub username: &'a str, - pub password: &'a str, -} - -// ── Fetch helpers ───────────────────────────────────────────────────────────── - -pub async fn get_me() -> Result { - let resp = gloo_net::http::Request::get(&url("/auth/me")) - .credentials(web_sys::RequestCredentials::Include) - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 200 { - resp.json::().await.map_err(|e| e.to_string()) - } else { - Err(format!("status {}", resp.status())) - } -} - -pub async fn post_login(username: &str, password: &str) -> Result { - let body = LoginBody { username, password }; - let resp = gloo_net::http::Request::post(&url("/auth/login")) - .credentials(web_sys::RequestCredentials::Include) - .json(&body) - .map_err(|e| e.to_string())? - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 200 { - resp.json::().await.map_err(|e| e.to_string()) - } else { - let text = resp.text().await.unwrap_or_default(); - Err(text) - } -} - -pub async fn post_register(username: &str, email: &str, password: &str) -> Result { - let body = RegisterBody { username, email, password }; - let resp = gloo_net::http::Request::post(&url("/auth/register")) - .credentials(web_sys::RequestCredentials::Include) - .json(&body) - .map_err(|e| e.to_string())? - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 201 { - resp.json::().await.map_err(|e| e.to_string()) - } else { - let text = resp.text().await.unwrap_or_default(); - Err(text) - } -} - -pub async fn post_logout() -> Result<(), String> { - let resp = gloo_net::http::Request::post(&url("/auth/logout")) - .credentials(web_sys::RequestCredentials::Include) - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 204 { - Ok(()) - } else { - Err(format!("status {}", resp.status())) - } -} - -pub async fn get_user_profile(username: &str) -> Result { - let resp = gloo_net::http::Request::get(&url(&format!("/users/{username}"))) - .credentials(web_sys::RequestCredentials::Include) - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 200 { - resp.json::().await.map_err(|e| e.to_string()) - } else { - Err(format!("status {}", resp.status())) - } -} - -pub async fn get_user_games(username: &str, page: i64) -> Result { - let resp = gloo_net::http::Request::get(&url(&format!("/users/{username}/games?page={page}&per_page=20"))) - .credentials(web_sys::RequestCredentials::Include) - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 200 { - resp.json::().await.map_err(|e| e.to_string()) - } else { - Err(format!("status {}", resp.status())) - } -} - -pub async fn get_game_detail(id: i64) -> Result { - let resp = gloo_net::http::Request::get(&url(&format!("/games/{id}"))) - .credentials(web_sys::RequestCredentials::Include) - .send() - .await - .map_err(|e| e.to_string())?; - if resp.status() == 200 { - resp.json::().await.map_err(|e| e.to_string()) - } else { - Err(format!("status {}", resp.status())) - } -} - -// ── Utilities ───────────────────────────────────────────────────────────────── - -pub fn format_ts(ts: i64) -> String { - let ms = (ts * 1000) as f64; - let date = js_sys::Date::new(&wasm_bindgen::JsValue::from_f64(ms)); - date.to_locale_string("en-GB", &wasm_bindgen::JsValue::UNDEFINED) - .as_string() - .unwrap_or_default() -} diff --git a/clients/web-user-portal/src/app.rs b/clients/web-user-portal/src/app.rs deleted file mode 100644 index 92a121a..0000000 --- a/clients/web-user-portal/src/app.rs +++ /dev/null @@ -1,67 +0,0 @@ -use leptos::prelude::*; -use leptos_router::{components::{Route, Router, Routes, A}, path}; - -use crate::api::{self, MeResponse}; -use crate::pages::{home::HomePage, profile::ProfilePage, game::GamePage}; - -#[derive(Clone, Debug)] -pub struct AuthState { - pub user: RwSignal>, -} - -#[component] -pub fn App() -> impl IntoView { - let user = RwSignal::new(None::); - provide_context(AuthState { user }); - - // Probe session on load. - let auth = use_context::().unwrap(); - let _ = LocalResource::new(move || async move { - if let Ok(me) = api::get_me().await { - auth.user.set(Some(me)); - } - }); - - view! { - -