summaryrefslogtreecommitdiff
path: root/rs
diff options
context:
space:
mode:
authorgrothedev <grothedev@gmail.com>2025-10-03 20:28:33 -0400
committergrothedev <grothedev@gmail.com>2025-10-03 20:28:33 -0400
commit0d58ccc4e90b93fa1498a3fa97712697ac606775 (patch)
treec303ee4ff66fa0930869efe2160a49c561082770 /rs
parentbcc93c8d058e6db05e32e262760d0903a721e402 (diff)
move rust proj into own fowdowh
Diffstat (limited to 'rs')
-rw-r--r--rs/Cargo.lock2888
-rw-r--r--rs/Cargo.toml12
-rw-r--r--rs/metrics.csv1045
-rw-r--r--rs/src/graph.rs122
-rw-r--r--rs/src/main.rs89
-rw-r--r--rs/src/metrics.rs290
-rw-r--r--rs/src/renderer.rs682
-rw-r--r--rs/src/shader.wgsl22
-rw-r--r--rs/src/vertex.rs27
9 files changed, 5177 insertions, 0 deletions
diff --git a/rs/Cargo.lock b/rs/Cargo.lock
new file mode 100644
index 0000000..f99e0bf
--- /dev/null
+++ b/rs/Cargo.lock
@@ -0,0 +1,2888 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "ab_glyph"
+version = "0.2.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2"
+dependencies = [
+ "ab_glyph_rasterizer",
+ "owned_ttf_parser",
+]
+
+[[package]]
+name = "ab_glyph_rasterizer"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
+
+[[package]]
+name = "ahash"
+version = "0.8.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
+dependencies = [
+ "cfg-if",
+ "getrandom",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "android-activity"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046"
+dependencies = [
+ "android-properties",
+ "bitflags 2.9.4",
+ "cc",
+ "cesu8",
+ "jni",
+ "jni-sys",
+ "libc",
+ "log",
+ "ndk",
+ "ndk-context",
+ "ndk-sys 0.6.0+11769913",
+ "num_enum",
+ "thiserror",
+]
+
+[[package]]
+name = "android-properties"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
+dependencies = [
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys 0.60.2",
+]
+
+[[package]]
+name = "arrayref"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
+[[package]]
+name = "as-raw-xcb-connection"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
+
+[[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 = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "bit-set"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
+
+[[package]]
+name = "block"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
+
+[[package]]
+name = "block2"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
+dependencies = [
+ "objc2",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
+[[package]]
+name = "bytemuck"
+version = "1.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "bytes"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+
+[[package]]
+name = "calloop"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
+dependencies = [
+ "bitflags 2.9.4",
+ "log",
+ "polling",
+ "rustix 0.38.44",
+ "slab",
+ "thiserror",
+]
+
+[[package]]
+name = "calloop-wayland-source"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
+dependencies = [
+ "calloop",
+ "rustix 0.38.44",
+ "wayland-backend",
+ "wayland-client",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"
+dependencies = [
+ "find-msvc-tools",
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cesu8"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+[[package]]
+name = "com"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6"
+dependencies = [
+ "com_macros",
+]
+
+[[package]]
+name = "com_macros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5"
+dependencies = [
+ "com_macros_support",
+ "proc-macro2",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "com_macros_support"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "combine"
+version = "4.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+dependencies = [
+ "bytes",
+ "memchr",
+]
+
+[[package]]
+name = "concurrent-queue"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+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"
+version = "0.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "core-graphics-types",
+ "foreign-types",
+ "libc",
+]
+
+[[package]]
+name = "core-graphics-types"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "libc",
+]
+
+[[package]]
+name = "cosmic-text"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59fd57d82eb4bfe7ffa9b1cec0c05e2fd378155b47f255a67983cb4afe0e80c2"
+dependencies = [
+ "bitflags 2.9.4",
+ "fontdb",
+ "log",
+ "rangemap",
+ "rayon",
+ "rustc-hash 1.1.0",
+ "rustybuzz",
+ "self_cell",
+ "swash",
+ "sys-locale",
+ "ttf-parser 0.21.1",
+ "unicode-bidi",
+ "unicode-linebreak",
+ "unicode-script",
+ "unicode-segmentation",
+]
+
+[[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 = "cursor-icon"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
+
+[[package]]
+name = "d3d12"
+version = "22.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdbd1f579714e3c809ebd822c81ef148b1ceaeb3d535352afc73fd0c4c6a0017"
+dependencies = [
+ "bitflags 2.9.4",
+ "libloading",
+ "winapi",
+]
+
+[[package]]
+name = "dispatch"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
+
+[[package]]
+name = "dlib"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
+dependencies = [
+ "libloading",
+]
+
+[[package]]
+name = "document-features"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d"
+dependencies = [
+ "litrs",
+]
+
+[[package]]
+name = "downcast-rs"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
+
+[[package]]
+name = "dpi"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "env_filter"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "jiff",
+ "log",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.1",
+]
+
+[[package]]
+name = "etagere"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc89bf99e5dc15954a60f707c1e09d7540e5cd9af85fa75caa0b510bc08c5342"
+dependencies = [
+ "euclid",
+ "svg_fmt",
+]
+
+[[package]]
+name = "euclid"
+version = "0.22.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
+
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
+name = "font-types"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "fontconfig-parser"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646"
+dependencies = [
+ "roxmltree",
+]
+
+[[package]]
+name = "fontdb"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3"
+dependencies = [
+ "fontconfig-parser",
+ "log",
+ "memmap2",
+ "slotmap",
+ "tinyvec",
+ "ttf-parser 0.20.0",
+]
+
+[[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.106",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
+
+[[package]]
+name = "gethostname"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55"
+dependencies = [
+ "rustix 1.1.2",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi",
+]
+
+[[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 = "glow"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1"
+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 = "glyphon"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b11b1afb04c1a1be055989042258499473d0a9447f16450b433aba10bc2a46e7"
+dependencies = [
+ "cosmic-text",
+ "etagere",
+ "lru",
+ "rustc-hash 2.1.1",
+ "wgpu",
+]
+
+[[package]]
+name = "gpu-alloc"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
+dependencies = [
+ "bitflags 2.9.4",
+ "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.9.4",
+]
+
+[[package]]
+name = "gpu-allocator"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7"
+dependencies = [
+ "log",
+ "presser",
+ "thiserror",
+ "winapi",
+ "windows",
+]
+
+[[package]]
+name = "gpu-descriptor"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca"
+dependencies = [
+ "bitflags 2.9.4",
+ "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.9.4",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
+
+[[package]]
+name = "hassle-rs"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890"
+dependencies = [
+ "bitflags 2.9.4",
+ "com",
+ "libc",
+ "libloading",
+ "thiserror",
+ "widestring",
+ "winapi",
+]
+
+[[package]]
+name = "hermit-abi"
+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 = "indexmap"
+version = "2.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.16.0",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "jiff"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "jni"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
+dependencies = [
+ "cesu8",
+ "cfg-if",
+ "combine",
+ "jni-sys",
+ "log",
+ "thiserror",
+ "walkdir",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+
+[[package]]
+name = "jobserver"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
+dependencies = [
+ "getrandom",
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "khronos-egl"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
+dependencies = [
+ "libc",
+ "libloading",
+ "pkg-config",
+]
+
+[[package]]
+name = "khronos_api"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
+
+[[package]]
+name = "libc"
+version = "0.2.176"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
+
+[[package]]
+name = "libloading"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
+dependencies = [
+ "cfg-if",
+ "windows-link",
+]
+
+[[package]]
+name = "libm"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
+
+[[package]]
+name = "libredox"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
+dependencies = [
+ "bitflags 2.9.4",
+ "libc",
+ "redox_syscall 0.5.17",
+]
+
+[[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.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
+
+[[package]]
+name = "litrs"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
+
+[[package]]
+name = "lock_api"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+
+[[package]]
+name = "lru"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
+
+[[package]]
+name = "malloc_buf"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+
+[[package]]
+name = "memmap2"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "metal"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
+dependencies = [
+ "bitflags 2.9.4",
+ "block",
+ "core-graphics-types",
+ "foreign-types",
+ "log",
+ "objc",
+ "paste",
+]
+
+[[package]]
+name = "naga"
+version = "22.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad"
+dependencies = [
+ "arrayvec",
+ "bit-set",
+ "bitflags 2.9.4",
+ "cfg_aliases 0.1.1",
+ "codespan-reporting",
+ "hexf-parse",
+ "indexmap",
+ "log",
+ "rustc-hash 1.1.0",
+ "spirv",
+ "termcolor",
+ "thiserror",
+ "unicode-xid",
+]
+
+[[package]]
+name = "ndk"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
+dependencies = [
+ "bitflags 2.9.4",
+ "jni-sys",
+ "log",
+ "ndk-sys 0.6.0+11769913",
+ "num_enum",
+ "raw-window-handle",
+ "thiserror",
+]
+
+[[package]]
+name = "ndk-context"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
+
+[[package]]
+name = "ndk-sys"
+version = "0.5.0+25.2.9519653"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691"
+dependencies = [
+ "jni-sys",
+]
+
+[[package]]
+name = "ndk-sys"
+version = "0.6.0+11769913"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
+dependencies = [
+ "jni-sys",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_enum"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
+dependencies = [
+ "num_enum_derive",
+ "rustversion",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "objc"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
+dependencies = [
+ "malloc_buf",
+]
+
+[[package]]
+name = "objc-sys"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310"
+
+[[package]]
+name = "objc2"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804"
+dependencies = [
+ "objc-sys",
+ "objc2-encode",
+]
+
+[[package]]
+name = "objc2-app-kit"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "libc",
+ "objc2",
+ "objc2-core-data",
+ "objc2-core-image",
+ "objc2-foundation",
+ "objc2-quartz-core",
+]
+
+[[package]]
+name = "objc2-cloud-kit"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "objc2",
+ "objc2-core-location",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-contacts"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
+dependencies = [
+ "block2",
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-data"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-core-image"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
+dependencies = [
+ "block2",
+ "objc2",
+ "objc2-foundation",
+ "objc2-metal",
+]
+
+[[package]]
+name = "objc2-core-location"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
+dependencies = [
+ "block2",
+ "objc2",
+ "objc2-contacts",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-encode"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
+
+[[package]]
+name = "objc2-foundation"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "dispatch",
+ "libc",
+ "objc2",
+]
+
+[[package]]
+name = "objc2-link-presentation"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
+dependencies = [
+ "block2",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-metal"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-quartz-core"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "objc2",
+ "objc2-foundation",
+ "objc2-metal",
+]
+
+[[package]]
+name = "objc2-symbols"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
+dependencies = [
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-ui-kit"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "objc2",
+ "objc2-cloud-kit",
+ "objc2-core-data",
+ "objc2-core-image",
+ "objc2-core-location",
+ "objc2-foundation",
+ "objc2-link-presentation",
+ "objc2-quartz-core",
+ "objc2-symbols",
+ "objc2-uniform-type-identifiers",
+ "objc2-user-notifications",
+]
+
+[[package]]
+name = "objc2-uniform-type-identifiers"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
+dependencies = [
+ "block2",
+ "objc2",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "objc2-user-notifications"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
+dependencies = [
+ "bitflags 2.9.4",
+ "block2",
+ "objc2",
+ "objc2-core-location",
+ "objc2-foundation",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+
+[[package]]
+name = "orbclient"
+version = "0.3.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43"
+dependencies = [
+ "libredox",
+]
+
+[[package]]
+name = "owned_ttf_parser"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b"
+dependencies = [
+ "ttf-parser 0.25.1",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.5.17",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
+[[package]]
+name = "pin-project"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "polling"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
+dependencies = [
+ "cfg-if",
+ "concurrent-queue",
+ "hermit-abi",
+ "pin-project-lite",
+ "rustix 1.1.2",
+ "windows-sys 0.61.1",
+]
+
+[[package]]
+name = "pollster"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
+
+[[package]]
+name = "portable-atomic"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
+
+[[package]]
+name = "presser"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
+
+[[package]]
+name = "proc-macro-crate"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
+dependencies = [
+ "toml_edit",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "profiling"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
+
+[[package]]
+name = "quick-xml"
+version = "0.37.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "range-alloc"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
+
+[[package]]
+name = "rangemap"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223"
+
+[[package]]
+name = "raw-window-handle"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
+
+[[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",
+]
+
+[[package]]
+name = "read-fonts"
+version = "0.22.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69aacb76b5c29acfb7f90155d39759a29496aebb49395830e928a9703d2eec2f"
+dependencies = [
+ "bytemuck",
+ "font-types",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
+dependencies = [
+ "bitflags 2.9.4",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
+
+[[package]]
+name = "renderdoc-sys"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
+
+[[package]]
+name = "roxmltree"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
+
+[[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.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+
+[[package]]
+name = "rustix"
+version = "0.38.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
+dependencies = [
+ "bitflags 2.9.4",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.4.15",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "rustix"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
+dependencies = [
+ "bitflags 2.9.4",
+ "errno",
+ "libc",
+ "linux-raw-sys 0.11.0",
+ "windows-sys 0.61.1",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "rustybuzz"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c"
+dependencies = [
+ "bitflags 2.9.4",
+ "bytemuck",
+ "libm",
+ "smallvec",
+ "ttf-parser 0.21.1",
+ "unicode-bidi-mirroring",
+ "unicode-ccc",
+ "unicode-properties",
+ "unicode-script",
+]
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scoped-tls"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "sctk-adwaita"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec"
+dependencies = [
+ "ab_glyph",
+ "log",
+ "memmap2",
+ "smithay-client-toolkit",
+ "tiny-skia",
+]
+
+[[package]]
+name = "self_cell"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "skrifa"
+version = "0.22.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe"
+dependencies = [
+ "bytemuck",
+ "read-fonts",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
+
+[[package]]
+name = "slotmap"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "smithay-client-toolkit"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
+dependencies = [
+ "bitflags 2.9.4",
+ "calloop",
+ "calloop-wayland-source",
+ "cursor-icon",
+ "libc",
+ "log",
+ "memmap2",
+ "rustix 0.38.44",
+ "thiserror",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-csd-frame",
+ "wayland-cursor",
+ "wayland-protocols",
+ "wayland-protocols-wlr",
+ "wayland-scanner",
+ "xkeysym",
+]
+
+[[package]]
+name = "smol_str"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "spirv"
+version = "0.3.0+sdk-1.3.268.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
+dependencies = [
+ "bitflags 2.9.4",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strict-num"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
+
+[[package]]
+name = "svg_fmt"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb"
+
+[[package]]
+name = "swash"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbd59f3f359ddd2c95af4758c18270eddd9c730dde98598023cdabff472c2ca2"
+dependencies = [
+ "skrifa",
+ "yazi",
+ "zeno",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sys-locale"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "timeplot"
+version = "0.1.0"
+dependencies = [
+ "bytemuck",
+ "env_logger",
+ "glyphon",
+ "pollster",
+ "wgpu",
+ "winit",
+]
+
+[[package]]
+name = "tiny-skia"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "bytemuck",
+ "cfg-if",
+ "log",
+ "tiny-skia-path",
+]
+
+[[package]]
+name = "tiny-skia-path"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"
+dependencies = [
+ "arrayref",
+ "bytemuck",
+ "strict-num",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "toml_datetime"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.23.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "toml_parser",
+ "winnow",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
+dependencies = [
+ "winnow",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+dependencies = [
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
+
+[[package]]
+name = "ttf-parser"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
+
+[[package]]
+name = "ttf-parser"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8"
+
+[[package]]
+name = "ttf-parser"
+version = "0.25.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
+name = "unicode-bidi-mirroring"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86"
+
+[[package]]
+name = "unicode-ccc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+
+[[package]]
+name = "unicode-properties"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
+
+[[package]]
+name = "unicode-script"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.14.7+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
+dependencies = [
+ "wasip2",
+]
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "wayland-backend"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
+dependencies = [
+ "cc",
+ "downcast-rs",
+ "rustix 1.1.2",
+ "scoped-tls",
+ "smallvec",
+ "wayland-sys",
+]
+
+[[package]]
+name = "wayland-client"
+version = "0.31.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d"
+dependencies = [
+ "bitflags 2.9.4",
+ "rustix 1.1.2",
+ "wayland-backend",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-csd-frame"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
+dependencies = [
+ "bitflags 2.9.4",
+ "cursor-icon",
+ "wayland-backend",
+]
+
+[[package]]
+name = "wayland-cursor"
+version = "0.31.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29"
+dependencies = [
+ "rustix 1.1.2",
+ "wayland-client",
+ "xcursor",
+]
+
+[[package]]
+name = "wayland-protocols"
+version = "0.32.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901"
+dependencies = [
+ "bitflags 2.9.4",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-protocols-plasma"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032"
+dependencies = [
+ "bitflags 2.9.4",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-protocols-wlr"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec"
+dependencies = [
+ "bitflags 2.9.4",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-scanner"
+version = "0.31.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3"
+dependencies = [
+ "proc-macro2",
+ "quick-xml",
+ "quote",
+]
+
+[[package]]
+name = "wayland-sys"
+version = "0.31.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142"
+dependencies = [
+ "dlib",
+ "log",
+ "once_cell",
+ "pkg-config",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "web-time"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "wgpu"
+version = "22.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1d1c4ba43f80542cf63a0a6ed3134629ae73e8ab51e4b765a67f3aa062eb433"
+dependencies = [
+ "arrayvec",
+ "cfg_aliases 0.1.1",
+ "document-features",
+ "js-sys",
+ "log",
+ "naga",
+ "parking_lot",
+ "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 = "22.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0348c840d1051b8e86c3bcd31206080c5e71e5933dabd79be1ce732b0b2f089a"
+dependencies = [
+ "arrayvec",
+ "bit-vec",
+ "bitflags 2.9.4",
+ "cfg_aliases 0.1.1",
+ "document-features",
+ "indexmap",
+ "log",
+ "naga",
+ "once_cell",
+ "parking_lot",
+ "profiling",
+ "raw-window-handle",
+ "rustc-hash 1.1.0",
+ "smallvec",
+ "thiserror",
+ "wgpu-hal",
+ "wgpu-types",
+]
+
+[[package]]
+name = "wgpu-hal"
+version = "22.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6bbf4b4de8b2a83c0401d9e5ae0080a2792055f25859a02bf9be97952bbed4f"
+dependencies = [
+ "android_system_properties",
+ "arrayvec",
+ "ash",
+ "bit-set",
+ "bitflags 2.9.4",
+ "block",
+ "cfg_aliases 0.1.1",
+ "core-graphics-types",
+ "d3d12",
+ "glow",
+ "glutin_wgl_sys",
+ "gpu-alloc",
+ "gpu-allocator",
+ "gpu-descriptor",
+ "hassle-rs",
+ "js-sys",
+ "khronos-egl",
+ "libc",
+ "libloading",
+ "log",
+ "metal",
+ "naga",
+ "ndk-sys 0.5.0+25.2.9519653",
+ "objc",
+ "once_cell",
+ "parking_lot",
+ "profiling",
+ "range-alloc",
+ "raw-window-handle",
+ "renderdoc-sys",
+ "rustc-hash 1.1.0",
+ "smallvec",
+ "thiserror",
+ "wasm-bindgen",
+ "web-sys",
+ "wgpu-types",
+ "winapi",
+]
+
+[[package]]
+name = "wgpu-types"
+version = "22.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc9d91f0e2c4b51434dfa6db77846f2793149d8e73f800fa2e41f52b8eac3c5d"
+dependencies = [
+ "bitflags 2.9.4",
+ "js-sys",
+ "web-sys",
+]
+
+[[package]]
+name = "widestring"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
+
+[[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"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
+dependencies = [
+ "windows-sys 0.61.1",
+]
+
+[[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.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
+dependencies = [
+ "windows-core",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[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.4",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.61.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+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.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[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.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
+[[package]]
+name = "winit"
+version = "0.30.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732"
+dependencies = [
+ "ahash",
+ "android-activity",
+ "atomic-waker",
+ "bitflags 2.9.4",
+ "block2",
+ "bytemuck",
+ "calloop",
+ "cfg_aliases 0.2.1",
+ "concurrent-queue",
+ "core-foundation",
+ "core-graphics",
+ "cursor-icon",
+ "dpi",
+ "js-sys",
+ "libc",
+ "memmap2",
+ "ndk",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
+ "objc2-ui-kit",
+ "orbclient",
+ "percent-encoding",
+ "pin-project",
+ "raw-window-handle",
+ "redox_syscall 0.4.1",
+ "rustix 0.38.44",
+ "sctk-adwaita",
+ "smithay-client-toolkit",
+ "smol_str",
+ "tracing",
+ "unicode-segmentation",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-protocols-plasma",
+ "web-sys",
+ "web-time",
+ "windows-sys 0.52.0",
+ "x11-dl",
+ "x11rb",
+ "xkbcommon-dl",
+]
+
+[[package]]
+name = "winnow"
+version = "0.7.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
+[[package]]
+name = "x11-dl"
+version = "2.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f"
+dependencies = [
+ "libc",
+ "once_cell",
+ "pkg-config",
+]
+
+[[package]]
+name = "x11rb"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
+dependencies = [
+ "as-raw-xcb-connection",
+ "gethostname",
+ "libc",
+ "libloading",
+ "once_cell",
+ "rustix 1.1.2",
+ "x11rb-protocol",
+]
+
+[[package]]
+name = "x11rb-protocol"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
+
+[[package]]
+name = "xcursor"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b"
+
+[[package]]
+name = "xkbcommon-dl"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
+dependencies = [
+ "bitflags 2.9.4",
+ "dlib",
+ "log",
+ "once_cell",
+ "xkeysym",
+]
+
+[[package]]
+name = "xkeysym"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
+
+[[package]]
+name = "xml-rs"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
+
+[[package]]
+name = "yazi"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1"
+
+[[package]]
+name = "zeno"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
diff --git a/rs/Cargo.toml b/rs/Cargo.toml
new file mode 100644
index 0000000..92458e1
--- /dev/null
+++ b/rs/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "timeplot"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+wgpu = { version = "22", features = ["wgsl"] }
+winit = "0.30"
+pollster = "0.3"
+bytemuck = { version = "1.14", features = ["derive"] }
+env_logger = "0.11"
+glyphon = "0.6"
diff --git a/rs/metrics.csv b/rs/metrics.csv
new file mode 100644
index 0000000..329e70c
--- /dev/null
+++ b/rs/metrics.csv
@@ -0,0 +1,1045 @@
+frame,total_ms,update_ms,render_ms,vertex_count,line_count,fps
+0,20.585355999999997,0.020693,20.584712000000003,304,2,48.57822230521542
+1,12.802973,0.002634,12.802714,304,2,78.10685846170261
+2,9.668886,0.003483,9.668671,304,2,103.42453101629287
+3,10.223832999999999,0.002,10.223467,304,2,97.81067433319774
+4,8.824733,0.002637,8.824481,304,2,113.31787601959175
+5,9.340967000000001,0.001766,9.340724999999999,304,2,107.05529737981088
+6,8.676965,0.002006,8.676746000000001,304,2,115.24767012428886
+7,8.564975,0.001603,8.56463,304,2,116.75457313068631
+8,8.774607,0.002961,8.774395,304,2,113.9652180433836
+9,9.376443,0.001887,9.376206999999999,304,2,106.6502510600235
+10,8.823737999999999,0.016567,8.823476,504,4,113.33065419666814
+11,9.399063,0.003183,9.398831999999999,504,4,106.39358412641771
+12,9.544553,0.002565,9.544139,504,4,104.77180020897782
+13,11.734409,0.003143,11.734183999999999,504,4,85.21946013642443
+14,16.307796,0.00265,16.307633,504,4,61.32036481201997
+15,17.068881,0.002518,17.068562,504,4,58.58614867606142
+16,26.337062000000003,0.003478,26.336861,504,4,37.96930728264223
+17,8.962518,0.0038870000000000003,8.962314000000001,504,4,111.57578707233839
+18,15.467921,0.00244,15.467604,504,4,64.64992936025469
+19,15.356398,0.0033079999999999997,15.356159,504,4,65.11943751392742
+20,16.26383,0.017325,16.263552,704,6,61.48613211033318
+21,17.342502999999997,0.003905,17.34211,704,6,57.661803489380986
+22,16.55788,0.004430999999999999,16.557701,704,6,60.39420505523654
+23,27.963865000000002,0.014707,27.963635,704,6,35.76043583388777
+24,8.961756,0.006088,8.961514000000001,704,6,111.58527413600639
+25,12.729468,0.003685,12.729178000000001,704,6,78.55787845964969
+26,15.449618,0.00378,15.449423,704,6,64.7265194518078
+27,17.082518,0.003216,17.082309,704,6,58.5393792648133
+28,16.682744,0.003359,16.682559,704,6,59.94217737801407
+29,17.514577,0.004037,17.514398,704,6,57.09529839059202
+30,18.860458,0.004269,18.860067,704,6,53.02098178103628
+31,13.230066,0.042867,13.229762000000001,904,8,75.58541280141762
+32,18.250951,0.004262999999999999,18.25075,904,8,54.79166537677954
+33,15.342804999999998,0.004948,15.3425,904,8,65.17713025747248
+34,16.938457,0.005633,16.938185,904,8,59.037254692089135
+35,16.541091,0.005096,16.54081,904,8,60.455504416244366
+36,15.82304,0.005094,15.822883999999998,904,8,63.19898072683883
+37,17.354155,0.004086,17.353795,904,8,57.62308795789827
+38,16.542184000000002,0.004856,16.541891,904,8,60.4515099094533
+39,15.877367,0.005339999999999999,15.877196,904,8,62.982735109669
+40,17.704497,0.0058579999999999995,17.704245,904,8,56.48282467443158
+41,15.912214,0.019885999999999997,15.912003,1104,10,62.844805883078244
+42,16.320653,0.021303,16.320396000000002,1104,10,61.272058170711674
+43,17.253076,0.005789,17.252828,1104,10,57.96067901167305
+44,15.502711000000001,0.019284,15.502563,1104,10,64.50484692645047
+45,17.291728,0.004775,17.291441000000003,1104,10,57.831120174918325
+46,16.249458,0.007081,16.24924,1104,10,61.540514151302766
+47,16.904926,0.00589,16.904741,1104,10,59.1543553636378
+48,16.770086,0.006070000000000001,16.7698,1104,10,59.62998639362971
+49,16.641548999999998,0.005116,16.641277,1104,10,60.09056007947338
+50,16.164299,0.0054659999999999995,16.164143,1104,10,61.86473041608547
+51,16.648135,0.005594,16.647529000000002,1104,10,60.066788261868375
+52,17.123464000000002,0.019183,17.123226,1304,12,58.3993986263527
+53,29.310091,0.007357,29.309849999999997,1304,12,34.11794252020575
+54,9.648267,0.010475,9.647891000000001,1304,12,103.64555624341656
+55,9.792821,0.007602,9.792634,1304,12,102.11562122906157
+56,16.905698,0.005496,16.905447,1304,12,59.151654075448405
+57,16.942531,0.006468,16.942237,1304,12,59.02305859732528
+58,15.751287,0.006229999999999999,15.751099000000002,1304,12,63.486875707362834
+59,17.180539000000003,0.0055119999999999995,17.180335000000003,1304,12,58.20539157706285
+60,16.577558,0.006564,16.577278,1304,12,60.322515535762264
+61,16.921288999999998,0.007706,16.921097,1304,12,59.09715270509239
+62,17.084543,0.020509999999999997,17.08419,1504,14,58.53244069800404
+63,15.285663999999999,0.012614,15.285425,1504,14,65.4207759636742
+64,16.839092,0.006849,16.838901,1504,14,59.3856248306025
+65,17.00865,0.006964,17.008344,1504,14,58.79361383766496
+66,16.039631,0.008415,16.039409000000003,1504,14,62.34557391002324
+67,16.656771,0.006919,16.656559,1504,14,60.03564556419729
+68,24.927260999999998,0.017674000000000002,24.92672,1504,14,40.11672200969052
+69,14.515953,0.012724999999999998,14.51567,1504,14,68.88972429161214
+70,10.947745,0.011239,10.947422999999999,1504,14,91.34301173438001
+71,15.840964999999999,0.020725,15.840768000000002,1504,14,63.12746729760467
+72,16.198642999999997,0.033045,16.198447,1704,16,61.7335662005762
+73,16.984214,0.006851,16.984008,1704,16,58.87820301840285
+74,16.745624,0.008107999999999999,16.745376,1704,16,59.71709385090696
+75,16.608743,0.007951000000000001,16.608094,1704,16,60.20925244011542
+76,17.011011999999997,0.007467,17.010751000000003,1704,16,58.785450271859204
+77,16.147173000000002,0.008585,16.146973,1704,16,61.93034533041789
+78,16.240849,0.008481,16.240646,1704,16,61.57313573939392
+79,18.04271,0.008454999999999999,18.0424,1704,16,55.42404660940624
+80,14.616415,0.040323,14.616228,1704,16,68.41622928741418
+81,17.151954,0.007019,17.151752,1704,16,58.302395167337785
+82,16.280562,0.007599,16.280365,1704,16,61.42294105080648
+83,17.768831,0.02155,17.768572,1904,18,56.27832241749613
+84,16.828582,0.010635,16.828198999999998,1904,18,59.42271309608854
+85,16.686888,0.013926000000000001,16.686269,1904,18,59.927291415870954
+86,15.820153999999999,0.010625,15.819939000000002,1904,18,63.21050983448076
+87,16.465339999999998,0.008812,16.465119,1904,18,60.733638054240004
+88,15.942459,0.009027,15.942262,1904,18,62.725580790265795
+89,16.923947000000002,0.0075179999999999995,16.923569,1904,18,59.08787116858732
+90,16.186000999999997,0.009582,16.185807,1904,18,61.78178291228328
+91,16.808137000000002,0.008121999999999999,16.807846,1904,18,59.494993407062296
+92,17.335651000000002,0.008609,17.334981,1904,18,57.68459459641867
+93,24.92418,0.023683,24.924016,2104,20,40.121681034240645
+94,9.247332,0.010159,9.247065000000001,2104,20,108.13929898915708
+95,14.185127000000001,0.010309,14.184929,2104,20,70.4963727148865
+96,16.709347,0.008468,16.709119,2104,20,59.84674326291745
+97,16.524467,0.010083,16.52429,2104,20,60.516324066609826
+98,17.053248,0.008886,17.052992,2104,20,58.63985558645485
+99,15.880458,0.009509,15.880229,2104,20,62.97047604042654
+100,16.650681,0.008638,16.65049,2104,20,60.05760364996483
+101,16.851830000000003,0.008929000000000001,16.851537,2104,20,59.3407362879877
+102,16.728346000000002,0.009907000000000001,16.728073,2104,20,59.77877310763419
+103,16.89492,0.009881000000000001,16.894581,2104,20,59.189389473285466
+104,15.459456999999999,0.02717,15.459242999999999,2304,22,64.68532497616185
+105,17.133239000000003,0.013497,17.132959,2304,22,58.36608010896246
+106,15.923347000000001,0.011646,15.92316,2304,22,62.800867179494354
+107,17.703038,0.008769,17.702665999999997,2304,22,56.487479719582595
+108,16.420952,0.014013,16.42068,2304,22,60.89780909170187
+109,16.176705,0.010179,16.176550000000002,2304,22,61.817286029509724
+110,17.264822,0.010246,17.264556,2204,21,57.921245872097614
+111,15.974644,0.010635,15.974428999999999,2204,21,62.599204088679535
+112,16.75742,0.009398,16.75705,2204,21,59.67505737756767
+113,16.579594,0.010727,16.579402,2204,21,60.31510783677815
+114,16.326130000000003,0.023158,16.325937,2404,23,61.25150295875384
+115,16.880195,0.023155000000000002,16.879890000000003,2404,23,59.24102180099223
+116,24.358542,0.016220000000000002,24.358117,2404,23,41.05336025448485
+117,8.708713,0.013162,8.708499999999999,2404,23,114.82752962464144
+118,16.4451,0.010173000000000001,16.444806999999997,2404,23,60.80838669269266
+119,16.704871,0.010446,16.704597000000003,2404,23,59.862778946332476
+120,16.573409,0.011287,16.573116,2404,23,60.33761672085688
+121,16.315715,0.010779,16.315507999999998,2404,23,61.29060234258811
+122,16.909184,0.01121,16.908901,2404,23,59.13945936125599
+123,16.38371,0.011574,16.38342,2404,23,61.036236603309014
+124,16.715712,0.023607,16.715423,2604,25,59.82395485157916
+125,16.481638,0.025716,16.481462,2704,26,60.67358110886794
+126,16.030023,0.012228000000000001,16.029842,2704,26,62.382942307693504
+127,16.975489,0.011262,16.975272,2704,26,58.90846502271599
+128,16.474492,0.012529,16.474221,2704,26,60.699898971088146
+129,16.281421,0.012054,16.281214,2704,26,61.41970040575696
+130,17.757978,0.010567,17.757604,2704,26,56.312717585301655
+131,15.865929000000001,0.012089,15.865726,2704,26,63.02814036291225
+132,18.875919,0.012122,18.875771999999998,2704,26,52.97755303993411
+133,14.201629,0.011458,14.201347,2704,26,70.4144573837269
+134,17.307956,0.010733000000000001,17.307554999999997,2704,26,57.77689751464586
+135,16.156562,0.026813,16.156326,2904,28,61.89435598984487
+136,15.693735,0.019924,15.693546999999999,2904,28,63.71969451504056
+137,17.091777,0.013058,17.091572,2804,27,58.50766716649767
+138,17.177613,0.013384,17.177323,2804,27,58.21530616622926
+139,15.769389000000002,0.014107999999999999,15.769119000000002,2704,26,63.413997841007024
+140,17.347545,0.013285,17.346987000000002,2704,26,57.64504429877542
+141,16.054378,0.011185,16.054112999999997,2704,26,62.28830540803263
+142,15.50344,0.012133999999999999,15.503243,2704,26,64.50181379100381
+143,17.450364,0.01046,17.450018,2704,26,57.30539489033008
+144,16.446595000000002,0.013156000000000001,16.446318,2604,25,60.80285919365071
+145,15.882684000000001,0.0235,15.882480000000001,2804,27,62.961650562335684
+146,17.206034,0.011547,17.20584,2804,27,58.119145876382674
+147,16.746482,0.012242000000000001,16.746288,2804,27,59.71403426701799
+148,16.244293,0.013365,16.244042,2804,27,61.56008143906294
+149,16.188226999999998,0.013493999999999999,16.187988999999998,2804,27,61.77328746378465
+150,17.853043,0.01218,17.852856,2804,27,56.01286010457713
+151,15.020545,0.036403,15.020316000000001,2704,26,66.5754804502766
+152,17.132082,0.026642,17.131826,2704,26,58.37002181054235
+153,16.827308,0.012309,16.826948,2704,26,59.427212005628
+154,15.493924,0.013345000000000001,15.493729,2704,26,64.5414292725329
+155,17.224239999999998,0.010839999999999999,17.22402,2604,25,58.0577140123454
+156,16.536739,0.024757,16.536518,2804,27,60.471414587845885
+157,16.625395,0.012869,16.625056,2804,27,60.14894683705259
+158,17.57366,0.014149,17.573169999999998,2704,26,56.9033428437787
+159,19.211087000000003,0.015834,19.210912,2704,26,52.05327527796839
+160,17.498132,0.013351,17.497850999999997,2704,26,57.14895738585125
+161,11.764649,0.016998,11.764352,2704,26,85.00041097698707
+162,16.796706,0.012883,16.79643,2704,26,59.535482730959274
+163,16.153149,0.01223,16.152945,2704,26,61.90743365271998
+164,16.902619,0.014602,16.902420000000003,2604,25,59.16242920697674
+165,16.521362,0.011151000000000001,16.521103,2604,25,60.52769741380886
+166,16.721388,0.025198,16.721218,2804,27,59.80364787899186
+167,16.572058000000002,0.013348,16.571874,2804,27,60.342535610242244
+168,16.015502,0.012627,16.015323000000002,2804,27,62.43950392563404
+169,16.588171,0.025137999999999997,16.587975,2704,26,60.2839215969018
+170,17.564225999999998,0.011647999999999999,17.563898000000002,2604,25,56.93390645280925
+171,16.159924,0.020032,16.159713999999997,2604,25,61.88147914557024
+172,15.968157999999999,0.01194,15.967974,2604,25,62.62463084345734
+173,16.749919,0.010557,16.749763,2604,25,59.70178124443468
+174,16.710376999999998,0.010733000000000001,16.710172,2604,25,59.8430544086468
+175,16.415143999999998,0.011744,16.414885,2504,24,60.91935593132781
+176,16.974333,0.011972,16.974062,2504,24,58.912476855497054
+177,16.174113000000002,0.025622,16.173915,2704,26,61.82719262564815
+178,16.14304,0.010693000000000001,16.142844999999998,2704,26,61.94620096338732
+179,17.407024,0.010975,17.406671,2704,26,57.448073835022
+180,16.597614,0.013139000000000001,16.596855,2704,26,60.249623831473606
+181,16.133385,0.013939,16.133166,2604,25,61.98327257423039
+182,17.377981000000002,0.011242,17.377296,2604,25,57.544084091241665
+183,16.046026,0.013313,16.045845999999997,2604,25,62.32072663972998
+184,16.158949999999997,0.012184,16.158699,2504,24,61.88520912559295
+185,17.202598,0.011972,17.202405,2504,24,58.13075443604507
+186,23.157334000000002,0.015174,23.156799,2404,23,43.18286379597927
+187,11.881444,0.045598,11.880989999999999,2604,25,84.16485403626024
+188,14.320544,0.013264,14.320213,2604,25,69.82974948437713
+189,16.554438,0.011255,16.554144,2604,25,60.40676222291569
+190,16.629960999999998,0.012,16.629659,2604,25,60.13243206042396
+191,16.203067,0.011508000000000001,16.202841,2604,25,61.71671079308627
+192,16.549951,0.011131,16.549736999999997,2504,24,60.423139621380145
+193,17.223759,0.010857,17.223413,2504,24,58.05933536343605
+194,15.846513999999999,0.012551999999999999,15.846222000000001,2504,24,63.105361848038
+195,16.625373999999997,0.012143000000000001,16.625118,2504,24,60.14902281296049
+196,16.399562,0.010179,16.399365,2504,24,60.97723829453494
+197,17.130661,0.024531,17.130383,2604,25,58.374863643615384
+198,17.578561,0.01239,17.578259,2504,24,56.887477877170944
+199,16.019407,0.012032,16.019218000000002,2504,24,62.42428324594037
+200,17.15061,0.010185,17.150406999999998,2504,24,58.30696400886033
+201,16.371222,0.010768,16.371004000000003,2504,24,61.08279516336655
+202,16.251497999999998,0.011169,16.25132,2504,24,61.53278916195911
+203,17.416044,0.011798,17.415835,2504,24,57.41832071623154
+204,21.870902,0.017002,21.870534,2404,23,45.72285130261203
+205,10.258562000000001,0.011487,10.258372999999999,2404,23,97.47954927795922
+206,17.169033,0.009212999999999999,17.168692,2404,23,58.24439850514587
+207,16.189246,0.01202,16.188897,2404,23,61.76939926664898
+208,16.435914,0.024579999999999998,16.435727,2604,25,60.842372380386024
+209,16.785602,0.010937,16.785436,2504,24,59.57486660293744
+210,17.015798,0.010244999999999999,17.015563,2504,24,58.76891580400755
+211,16.219726,0.012778000000000001,16.219455,2304,22,61.653322627028345
+212,16.733801,0.010334,16.733495,2304,22,59.75928601039298
+213,16.287557,0.010022,16.287370999999997,2304,22,61.39656180481824
+214,16.664324,0.010079,16.664026,2304,22,60.00843478559346
+215,17.013673999999998,0.009878,17.013476999999998,2304,22,58.776252560146624
+216,17.427027000000002,0.011033,17.426607999999998,2304,22,57.38213408402935
+217,15.42889,0.011117,15.428658,2304,22,64.81347653654929
+218,16.736151,0.022387999999999998,16.735514,2504,24,59.7508949339666
+219,16.369331000000003,0.010786,16.369122,2404,23,61.089851503399856
+220,18.631972,0.010634,18.631714000000002,2404,23,53.67118413445447
+221,17.763777,0.01586,17.763503,2404,23,56.29433425109986
+222,14.089744,0.010672000000000001,14.089433999999999,2304,22,70.97361030832072
+223,15.765758000000002,0.010754000000000001,15.765561000000002,2304,22,63.42860267168885
+224,16.499824999999998,0.009633000000000001,16.499654,2304,22,60.60670340443006
+225,16.801945,0.010059,16.801617,2304,22,59.516919023363066
+226,16.128505,0.017496,16.128286,2304,22,62.0020268462576
+227,17.078118,0.009807,17.077962,2204,21,58.55446132881855
+228,17.06792,0.009269999999999999,17.067736,2204,21,58.58944733746115
+229,16.473662,0.023584,16.473323,2404,23,60.702957241686754
+230,16.188306,0.011833,16.188017,2404,23,61.77298600607129
+231,16.545537,0.009832,16.545355,2404,23,60.43925923951577
+232,16.373352,0.01204,16.373174000000002,2304,22,61.07484893746864
+233,17.231577,0.009948,17.231272,2304,22,58.03299373005732
+234,16.049894,0.011352000000000001,16.049632000000003,2304,22,62.30570743956316
+235,17.136034000000002,0.011424,17.135748999999997,2304,22,58.356560216908996
+236,15.826450999999999,0.010975,15.826251,2204,21,63.18535974995279
+237,18.728991,0.017190999999999998,18.728672,2204,21,53.393159300466316
+238,17.132073000000002,0.010468,17.131856,2204,21,58.37005247409347
+239,13.811800000000002,0.022860000000000002,13.811618,2404,23,72.40185927974629
+240,20.837373,0.009611,20.837035,2404,23,47.99069441239066
+241,14.994335,0.022274000000000002,14.994031,2404,23,66.69185395684437
+242,14.651703,0.009649,14.651276,2404,23,68.25145172544107
+243,16.435368,0.012310000000000001,16.435096,2304,22,60.844393627206884
+244,15.930122,0.010639,15.929957000000002,2304,22,62.774158289559864
+245,16.755418000000002,0.009464,16.755216,2304,22,59.6821875765797
+246,16.652238,0.010244000000000001,16.651989999999998,2204,21,60.051988207230764
+247,17.036893,0.009585999999999999,17.036589000000003,2204,21,58.69614841156777
+248,15.700177,0.010879,15.699991,2204,21,63.6935494421496
+249,17.63319,0.036292,17.63281,2404,23,56.71123602706034
+250,15.818472,0.027061,15.818278000000001,2604,25,63.217231095392776
+251,16.98313,0.010929,16.98292,2604,25,58.881961099043586
+252,16.433941,0.012348,16.43374,2504,24,60.84967689734312
+253,16.590353,0.011186,16.590158000000002,2504,24,60.2759929219107
+254,16.688911,0.010801999999999999,16.688549000000002,2504,24,59.920027136581886
+255,16.246029,0.011775,16.245849,2504,24,61.55350332071917
+256,16.794318999999998,0.010109,16.794052,2504,24,59.54394459221598
+257,16.131937,0.012021,16.131721000000002,2404,23,61.98883618253654
+258,17.152791,0.010367,17.15249,2404,23,58.29955020148033
+259,16.759735000000003,0.01146,16.759351,2404,23,59.666814540922026
+260,15.929094000000001,0.026479,15.928892,2604,25,62.778209482598314
+261,20.796449000000003,0.012646000000000001,20.796181999999998,2504,24,48.08513222617957
+262,12.839808,0.012074,12.839453,2404,23,77.88278454008035
+263,16.631075,0.020912,16.63071,2404,23,60.128404207184445
+264,16.712756,0.012048999999999999,16.712494000000003,2404,23,59.834535967616596
+265,16.416775,0.011243999999999999,16.416588,2404,23,60.91330361779338
+266,15.667494000000001,0.011657,15.667285,2404,23,63.82641665603956
+267,17.771312,0.009885,17.770916,2404,23,56.2704655683272
+268,15.789475000000001,0.012179,15.789285,2304,22,63.33332805555599
+269,17.035398,0.010023,17.035211,2204,21,58.70129949414742
+270,16.039689,0.036163,16.039489,2404,23,62.34534846654446
+271,17.255798,0.009829000000000001,17.255617,2404,23,57.95153605761959
+272,16.3521,0.011908,16.351682,2404,23,61.15422483962305
+273,16.175673000000003,0.011232,16.175462000000003,2404,23,61.82122994202466
+274,17.966505,0.009864999999999999,17.966274000000002,2404,23,55.65912791608607
+275,16.174589,0.011212999999999999,16.174412999999998,2404,23,61.825373120763686
+276,16.853736,0.010908,16.853467000000002,2304,22,59.334025405405654
+277,16.383239,0.011931,16.382880999999998,2304,22,61.03799132760012
+278,16.393234,0.01153,16.392997,2304,22,61.00077629587914
+279,16.868591,0.008771,16.868295,2304,22,59.28177403791461
+280,16.268808,0.010898,16.268468000000002,2204,21,61.46731831858855
+281,16.744401999999997,0.024776000000000003,16.744205,2404,23,59.7214519813846
+282,16.662836,0.011824000000000001,16.662634,2404,23,60.013793570314206
+283,16.45385,0.010594000000000001,16.453566,2304,22,60.77604937446252
+284,16.170507,0.010360000000000001,16.170305,2304,22,61.840980001431
+285,17.421302,0.008653,17.420946,2304,22,57.400991039590494
+286,15.941218,0.01129,15.940875,2304,22,62.73046388299815
+287,16.669878,0.010704,16.669638,2304,22,59.988441427105826
+288,16.623306,0.009588000000000001,16.623135,2304,22,60.15650557115414
+289,16.900098,0.00992,16.899925,2204,21,59.17125450988509
+290,16.222362,0.010740000000000001,16.222075999999998,2204,21,61.64330447070531
+291,17.261822,0.023071,17.261559,2404,23,57.931312233436316
+292,15.817263000000002,0.010801999999999999,15.817049999999998,2404,23,63.22206313443735
+293,17.115222,0.010471,17.114964999999998,2304,22,58.427521419237216
+294,16.273072,0.010332999999999998,16.272774000000002,2304,22,61.45121216203063
+295,16.823049,0.011972,16.822853,2204,21,59.44225687032119
+296,16.964116,0.012518,16.963828,2204,21,58.947958148836044
+297,17.681316,0.010081,17.681097,2204,21,56.55687619631933
+298,19.451801,0.011719,19.451567,2204,21,51.40912144844583
+299,12.649113999999999,0.013231,12.648842,2204,21,79.05692050842455
+300,15.986064,0.010994,15.985857999999999,2104,20,62.55448495639702
+301,16.415319,0.009375,16.415107000000003,2104,20,60.91870648386425
+302,16.822378,0.022758,16.822072000000002,2304,22,59.4446278641462
+303,17.066065,0.011774,17.065592000000002,2304,22,58.595815731394445
+304,15.851565,0.011943,15.850996999999998,2304,22,63.08525372731336
+305,16.677498,0.010636,16.677272,2304,22,59.96103252418318
+306,17.162464999999997,0.011127,17.162174,2104,20,58.26668838071921
+307,15.958704000000001,0.010081999999999999,15.958485000000001,2104,20,62.66172992493626
+308,16.854853,0.009075999999999999,16.854451,2104,20,59.33009323783483
+309,16.851584,0.009995,16.851222,2104,20,59.34160254608707
+310,15.794929999999999,0.011398,15.794737999999999,2104,20,63.311455004865486
+311,16.679672999999998,0.009502,16.679485,2004,19,59.95321371108415
+312,17.474146,0.028665,17.473794,2204,21,57.227403273384574
+313,15.726483,0.011080999999999999,15.726202000000002,2204,21,63.58700797883417
+314,16.84467,0.010572,16.844378,2204,21,59.365959677452864
+315,16.25593,0.008758,16.255644,2204,21,61.51601292574464
+316,17.261304000000003,0.009616000000000001,17.26102,2204,21,57.933050712738726
+317,16.111301,0.010941000000000001,16.111113,2104,20,62.06823396819412
+318,16.358406,0.010981999999999999,16.358200999999998,2104,20,61.13065050470077
+319,16.489928000000003,0.008872999999999999,16.489714,2104,20,60.643078611380226
+320,17.410012,0.008476,17.409696,2104,20,57.438214287273325
+321,20.926238,0.010956,20.925863999999997,2004,19,47.78689796035006
+322,11.638572,0.040799,11.638348,2204,21,85.92119376844514
+323,16.400057999999998,0.010986,16.399848000000002,2104,20,60.97539411141108
+324,17.219527,0.009565,17.219216,2104,20,58.07360446079617
+325,16.09818,0.008698000000000001,16.097939,2104,20,62.11882337009526
+326,16.814686,0.009979,16.814358000000002,2104,20,59.4718212400755
+327,16.578428,0.009413,16.578141000000002,2104,20,60.319349940778466
+328,16.273009000000002,0.009249,16.272709,2104,20,61.45145006679465
+329,16.589443999999997,0.011828,16.589222,2004,19,60.279295677419945
+330,16.729034,0.009641,16.728781,2004,19,59.77631463956616
+331,16.584467,0.018536,16.584187,2004,19,60.29738549933501
+332,16.737119000000003,0.009765000000000001,16.736797000000003,2004,19,59.747439209818594
+333,16.330653,0.022139,16.33035,2204,21,61.23453850865608
+334,16.246507,0.009455,16.246278999999998,2204,21,61.55169231146116
+335,16.986311,0.010431999999999999,16.985996,2204,21,58.87093436591382
+336,16.490142,0.012052,16.489917,1904,18,60.64229161883507
+337,16.426838999999998,0.007500000000000001,16.42661,1904,18,60.87598472231938
+338,16.625892,0.008291999999999999,16.625652000000002,1904,18,60.14714879658788
+339,17.041218,0.008346,17.040966,1904,18,58.68125153964934
+340,16.184154999999997,0.009349,16.183974,1904,18,61.78882987712365
+341,16.535866,0.009571999999999999,16.535598,1904,18,60.47460713578594
+342,16.847775,0.008773999999999999,16.847438999999998,1904,18,59.355018689411516
+343,16.722325,0.022061,16.721989999999998,2104,20,59.800296908474145
+344,16.16356,0.010839999999999999,16.163248000000003,2004,19,61.867558879355784
+345,16.498327,0.008992,16.498113,2004,19,60.61220631643439
+346,16.699261,0.008872000000000001,16.699077,2004,19,59.88288942846034
+347,17.707415,0.008196,17.706968,2004,19,56.47351688544036
+348,16.012144999999997,0.013557000000000001,16.011784000000002,2004,19,62.452594577428584
+349,16.564013999999997,0.010213,16.563601000000002,2004,19,60.37183982095162
+350,16.222353,0.011714,16.222047,1904,18,61.64333866979717
+351,15.958379000000003,0.008019,15.958131,1904,18,62.663006060953926
+352,17.127756,0.00865,17.127487,1704,16,58.38476447235703
+353,16.520538000000002,0.008164,16.5202,1704,16,60.53071637255396
+354,17.419222,0.023195999999999998,17.418928,1904,18,57.40784519538243
+355,15.222595,0.009498,15.222379,1904,18,65.69182192655063
+356,16.696677,0.008053999999999999,16.696445,1904,18,59.89215698429094
+357,17.346093,0.008759000000000001,17.345844999999997,1904,18,57.64986962770233
+358,16.373251,0.009687999999999999,16.372899999999998,1904,18,61.07522568364707
+359,16.426369,0.009455,16.426151,1904,18,60.877726538348185
+360,16.178597999999997,0.008876,16.17839,1904,18,61.810053009537675
+361,16.956170999999998,0.007989,16.955973,1804,17,58.975578861524816
+362,17.243858,0.008681999999999999,17.243398,1804,17,57.991662886576776
+363,15.570627,0.009908,15.570416999999999,1804,17,64.22348952293315
+364,17.198313,0.021233000000000002,17.197989,2004,19,58.145237849782134
+365,16.57453,0.010402,16.57422,2004,19,60.33353585290202
+366,16.030863999999998,0.011172999999999999,16.030647,1904,18,62.379669617308224
+367,17.203733999999997,0.009129,17.203446,1904,18,58.1269159358079
+368,16.306030999999997,0.009697,16.305824,1904,18,61.32700226069729
+369,16.909046,0.0086,16.908734000000003,1904,18,59.13994201683525
+370,15.955555,0.008949,15.95533,1904,18,62.6740968897666
+371,16.672884999999997,0.009758999999999999,16.672687,1804,17,59.97762234910156
+372,17.117505,0.00872,17.117224,1804,17,58.419728809776885
+373,15.701513,0.007928,15.701296,1804,17,63.68812992735159
+374,17.061973000000002,0.007812999999999999,17.061795,1804,17,58.60986885866013
+375,16.602136,0.022263,16.601866,2004,19,60.2332133648345
+376,16.443657,0.009003,16.443345,2004,19,60.81372288414918
+377,16.743472,0.008686,16.743111000000003,2004,19,59.72476915182227
+378,16.25751,0.009969,16.257268,2004,19,61.510034439468285
+379,17.192,0.009340999999999999,17.191693,2004,19,58.16658911121452
+380,16.268146,0.009836000000000001,16.267929,2004,19,61.46981960943797
+381,16.427936,0.009361000000000001,16.427733,1904,18,60.871919637378674
+382,17.48183,0.008362999999999999,17.481532,1804,17,57.20224942125625
+383,15.604814,0.012435,15.604631000000001,1804,17,64.08278881119634
+384,16.590015,0.007768000000000001,16.589831999999998,1804,17,60.277220966949095
+385,16.587358,0.021489,16.587079000000003,2004,19,60.28687630664269
+386,17.663155,0.008777,17.662881,2004,19,56.615027156813156
+387,15.137500999999999,0.010346999999999999,15.13727,2004,19,66.06110215946477
+388,16.819741,0.008478000000000001,16.819543,2004,19,59.45394759645823
+389,17.044681999999998,0.008659,17.044455,2004,19,58.6693257169597
+390,16.127572999999998,0.009807,16.127391000000003,2004,19,62.005609895549696
+391,16.755267,0.009042000000000001,16.754897,2004,19,59.68272543791752
+392,16.12663,0.009528,16.126403,2004,19,62.00923565555854
+393,17.794527000000002,0.008735,17.794234999999997,1904,18,56.19705429652611
+394,16.11147,0.00936,16.111161999999997,1904,18,62.067582908325555
+395,16.333672,0.023183000000000002,16.333468,2104,20,61.223220351186185
+396,16.435031,0.010069,16.434821,2104,20,60.84564124034814
+397,16.785884,0.00933,16.785602,2004,19,59.573865755297724
+398,16.928041,0.008796,16.927738,2004,19,59.07358093000838
+399,15.745060000000002,0.009503000000000001,15.744833,2004,19,63.51198407627534
+400,17.412602999999997,0.00822,17.412216,2004,19,57.42966746557078
+401,16.274444,0.009815,16.274269,2004,19,61.44603158178553
+402,16.725244,0.008713,16.724841,2004,19,59.789860165866635
+403,16.348633,0.020567000000000002,16.348325,2004,19,61.1671936118451
+404,16.564695,0.009928000000000001,16.564342,2004,19,60.36935784208523
+405,16.265439,0.011064,16.265227,1904,18,61.48004981605476
+406,16.997088,0.023557,16.996879999999997,2104,20,58.833607262608744
+407,16.683614,0.009256,16.683404,2104,20,59.939051574796686
+408,15.826930999999998,0.012849,15.826712,2104,20,63.183443461022236
+409,17.364981,0.008832,17.36458,2104,20,57.58716349876801
+410,15.781727999999998,0.011193999999999999,15.781512000000001,2104,20,63.36441738192422
+411,17.645929000000002,0.008454000000000001,17.645609999999998,2104,20,56.67029488784636
+412,21.179023,0.016399,21.178721,2004,19,47.21653118748679
+413,11.32137,0.009085000000000001,11.321062,2004,19,88.3285326775823
+414,17.627494000000002,0.019045000000000003,17.627172,2004,19,56.7295612184012
+415,15.205774,0.011226,15.205592000000001,2004,19,65.76449183053754
+416,16.625205,0.022512,16.624924,2204,21,60.14963424511156
+417,16.963494,0.010487,16.963203,2204,21,58.95011959210761
+418,16.938950000000002,0.011013,16.938603999999998,2104,20,59.03553644116075
+419,15.851008,0.010611,15.850824,2104,20,63.08747052553377
+420,16.762049,0.008957000000000001,16.761851,2104,20,59.65857754025179
+421,16.653259,0.009193,16.65305,2104,20,60.048306460615315
+422,16.860507000000002,0.008794000000000001,16.860127,2104,20,59.31019749287491
+423,17.413815999999997,0.012768999999999999,17.413336,2104,20,57.4256670680338
+424,17.57154,0.012437,17.571299,2104,20,56.91020821168777
+425,14.229442,0.011249,14.229211000000001,2104,20,70.27682462882241
+426,16.801874,0.010512,16.801611,2104,20,59.51717052514499
+427,16.603831,0.024671000000000002,16.603544000000003,2304,22,60.2270644648214
+428,15.843631,0.011319,15.843438,2204,21,63.11684486971453
+429,17.367316000000002,0.008858999999999999,17.36707,2204,21,57.57942102279937
+430,16.171885,0.014735999999999999,16.171650999999997,2204,21,61.83571055569589
+431,16.704084,0.008994,16.703892,2104,20,59.86559933486924
+432,16.83404,0.010655999999999999,16.833730000000003,2104,20,59.4034468255986
+433,16.082133,0.010943,16.081920999999998,2104,20,62.18080648879101
+434,16.616879,0.009398,16.616666,2104,20,60.17977262757946
+435,16.767947,0.008195000000000001,16.767715,2104,20,59.637593081609815
+436,16.955135,0.009767,16.954822,2104,20,58.979182412879645
+437,16.813024,0.024338,16.812706,2304,22,59.4777001448401
+438,16.791955,0.011504,16.791711,2304,22,59.55232729006241
+439,16.706211,0.01056,16.705672,2304,22,59.85797737140995
+440,16.762365000000003,0.012664,16.761891000000002,2304,22,59.65745287135794
+441,16.123876999999997,0.012586,16.123366,2204,21,62.01982314799351
+442,17.207914000000002,0.012957,17.207529,2204,21,58.11279624014857
+443,15.706547,0.011729999999999999,15.706147999999999,2204,21,63.667717672127424
+444,16.710254,0.012527,16.709872,2204,21,59.84349489840191
+445,16.400662999999998,0.012161,16.400296,2204,21,60.97314480518258
+446,16.083607,0.012998,16.083065,2104,20,62.17510785982274
+447,17.059734,0.026587000000000003,17.059293,2304,22,58.617561094446145
+448,16.161890000000003,0.011902000000000001,16.161445999999998,2304,22,61.87395162323217
+449,17.096613,0.01244,17.095942,2304,22,58.49111750964942
+450,16.068586,0.012924,16.068112999999997,2304,22,62.233229482668854
+451,16.445310000000003,0.031445,16.444854,2304,22,60.80761019403099
+452,16.662291999999997,0.01311,16.66191,2304,22,60.015752934830346
+453,16.689338000000003,0.012146,16.688962,2304,22,59.918494070885245
+454,16.818406,0.012324,16.817713,2304,22,59.45866689149971
+455,16.281076,0.013063,16.280648000000003,2204,21,61.421001904296745
+456,17.731195000000003,0.011901,17.730672,2204,21,56.397778040340754
+457,14.912809000000001,0.014481,14.9125,2204,21,67.05644791668692
+458,16.766195,0.02546,16.765787,2404,23,59.64382497042412
+459,21.597234,0.012716,21.596885999999998,2404,23,46.30222555351301
+460,10.908097999999999,0.014004,10.907897,2404,23,91.67501062054998
+461,16.602161000000002,0.009994,16.601993999999998,2304,22,60.233122663971265
+462,16.880924,0.009616999999999999,16.880714,2304,22,59.238463486951304
+463,16.624778,0.011008,16.624461,2304,22,60.151179161610465
+464,16.435239,0.020189,16.435054,2304,22,60.8448711941457
+465,16.465287,0.011472,16.465061,2304,22,60.73383354933321
+466,17.210426000000002,0.023581,17.21014,2304,22,58.104314210467535
+467,16.050044999999997,0.009295,16.049787,2304,22,62.305121262899895
+468,16.682332000000002,0.02634,16.682184,2504,24,59.943657757200846
+469,19.60669,0.012286,19.606391000000002,2404,23,51.002999486399794
+470,13.473270000000001,0.012525,13.472989,2404,23,74.22103171687348
+471,16.505388999999997,0.010694,16.50523,2404,23,60.58627276218695
+472,16.748321999999998,0.0115,16.748017,2404,23,59.70747397858724
+473,16.567176,0.010665000000000001,16.566911,2404,23,60.36031729245829
+474,15.773504,0.011562000000000001,15.773299000000002,2404,23,63.39745436397645
+475,17.812266,0.010793,17.811871,2404,23,56.141088393806825
+476,23.047418999999998,0.016560000000000002,23.047102,2404,23,43.38880635614773
+477,9.435526,0.013088,9.435172,2304,22,105.98243277587281
+478,16.262838000000002,0.011786,16.262621000000003,2304,22,61.48988263918019
+479,16.878418999999997,0.022838999999999998,16.878217,2504,24,59.24725532646157
+480,16.612381,0.009783,16.612064,2504,24,60.19606701772612
+481,16.618584,0.012163,16.618195999999998,2404,23,60.17359842451078
+482,16.429648,0.012745000000000001,16.429271,2404,23,60.86557666968884
+483,16.551360000000003,0.016533,16.551094,2404,23,60.41799586257564
+484,16.263237,0.024556,16.262965,2404,23,61.48837405493138
+485,16.833460000000002,0.010227,16.833159000000002,2404,23,59.40549358242452
+486,17.476576,0.011717,17.476202,2404,23,57.21944618900178
+487,15.826443,0.012317999999999999,15.826171,2404,23,63.18539168908642
+488,16.713896,0.010424000000000001,16.713609,2404,23,59.83045485026352
+489,16.407268,0.023892,16.406995000000002,2604,25,60.94859912082865
+490,16.761927999999997,0.012088,16.761578999999998,2604,25,59.65900820001137
+491,15.953321999999998,0.012605,15.953122,2504,24,62.6828694362215
+492,17.641545,0.019768,17.641265,2504,24,56.68437770047918
+493,15.598185,0.013189000000000001,15.597932,2404,23,64.11002305716978
+494,16.63997,0.028826,16.63976,2404,23,60.09626219278039
+495,16.504209,0.011799,16.503919,2404,23,60.59060449367795
+496,17.316381,0.01196,17.316095999999998,2404,23,57.74878711666138
+497,15.719961000000001,0.010073,15.719758,2404,23,63.613389371640295
+498,17.367621,0.010045,17.367413000000003,2404,23,57.57840984669115
+499,16.088298,0.011652,16.087937,2404,23,62.15697894208572
+500,16.805009,0.039012,16.804794,2604,25,59.506067506420266
+501,15.998809,0.010506000000000001,15.998556,2604,25,62.50465269008462
+502,17.163325999999998,0.011438,17.163085000000002,2604,25,58.26376542635152
+503,17.179857,0.012583,17.179527,2504,24,58.20770219449441
+504,16.215377,0.012128,16.215031,2504,24,61.66985818461082
+505,15.679695,0.013036,15.679495000000001,2504,24,63.776750759501375
+506,16.281052,0.011812,16.280845,2404,23,61.42109244537761
+507,17.251674,0.009817,17.251493999999997,2404,23,57.965389329754316
+508,16.704692,0.011607,16.703929,2404,23,59.8634204090683
+509,16.272361,0.011497,16.272171,2404,23,61.453897194144105
+510,17.215937,0.024471,17.215505999999998,2604,25,58.08571441682204
+511,16.052813,0.016144,16.052545000000002,2604,25,62.29437793862048
+512,16.290245,0.01235,16.289987999999997,2604,25,61.38643095914151
+513,17.234488,0.010752,17.234106,2604,25,58.02319163760479
+514,16.142284,0.013191,16.142079,2504,24,61.94910212210366
+515,16.378529999999998,0.010302,16.378321,2504,24,61.0555403934297
+516,17.04626,0.010703,17.046069,2504,24,58.6638946021004
+517,16.419677,0.010504,16.419396,2504,24,60.90253785138405
+518,16.561283,0.019862,16.560958,2504,24,60.38179529931347
+519,17.021295,0.010168,17.020647999999998,2504,24,58.74993647663119
+520,15.689176999999999,0.027745,15.688959999999998,2704,26,63.738206280673616
+521,17.200229,0.011177,17.199894,2704,26,58.138760826963406
+522,16.391627999999997,0.012456,16.39127,2604,25,61.006752959498606
+523,16.243879,0.012267,16.243675,2504,24,61.561650391510554
+524,17.003652000000002,0.010272,17.003353999999998,2504,24,58.81089544763677
+525,16.784595,0.010417000000000001,16.784339,2504,24,59.57844082624573
+526,16.327261,0.011519999999999999,16.326989,2504,24,61.24726002726361
+527,16.956707,0.011351,16.956442,2504,24,58.97371464872277
+528,16.099683,0.010823,16.099439,2504,24,62.113024212961214
+529,16.368988,0.011654000000000001,16.368785,2504,24,61.09113159591784
+530,16.397034,0.010891,16.396804,2504,24,60.98663941295724
+531,17.61929,0.026438999999999997,17.61892,2604,25,56.75597597860073
+532,16.311215999999998,0.012398999999999999,16.310896,2604,25,61.307507668343064
+533,16.249504,0.011928,16.249275,2604,25,61.54033993899136
+534,16.930441000000002,0.01056,16.930226,2604,25,59.06520686614128
+535,17.02432,0.020564000000000002,17.023964999999997,2604,25,58.73949737786884
+536,15.216504,0.013318,15.216304,2604,25,65.7181176438425
+537,17.451477999999998,0.018033,17.45111,2504,24,57.30173685002497
+538,16.811902,0.01285,16.81158,2504,24,59.48166959336309
+539,16.082847,0.012068,16.08262,2404,23,62.17804596412562
+540,16.178106,0.011867,16.177799999999998,2404,23,61.81193274416672
+541,16.706004,0.037975,16.705765,2604,25,59.85871905693306
+542,16.526843,0.010859,16.526616,2604,25,60.507623869846164
+543,16.950435,0.010767,16.950135000000003,2604,25,58.99553610276079
+544,16.592415,0.011473,16.592221000000002,2604,25,60.2685022041698
+545,16.134545,0.011477000000000001,16.134238,2604,25,61.97881626039037
+546,17.300302,0.010527,17.299918,2504,24,57.802459170943955
+547,15.903283,0.012281,15.903091000000002,2504,24,62.8800984048388
+548,16.889691,0.011119,16.889408000000003,2504,24,59.207714338882816
+549,16.710664,0.011071,16.710362999999997,2504,24,59.842026624435746
+550,16.451578,0.01115,16.451263,2504,24,60.784442683856824
+551,16.331487,0.024539,16.331115999999998,2504,24,61.2314114446529
+552,16.438019,0.033763999999999995,16.437694,2704,26,60.834581101287206
+553,16.55453,0.012548,16.554237,2504,24,60.406426518904496
+554,16.71252,0.011658,16.712310000000002,2504,24,59.835380900067726
+555,16.912957,0.009871999999999999,16.912661,2504,24,59.12626632941833
+556,16.403904999999998,0.012319,16.403623,2504,24,60.96109432479645
+557,16.577041,0.010688,16.576851,2504,24,60.32439685707479
+558,16.613725,0.011061,16.613487,2504,24,60.191197338345255
+559,16.395416,0.011385000000000001,16.395132999999998,2404,23,60.99265794780687
+560,17.189841,0.012008999999999999,17.189388,2404,23,58.173894685820535
+561,15.731499,0.0117,15.730813,2404,23,63.56673321467967
+562,16.752975,0.023424,16.752682,2604,25,59.69089072239409
+563,18.043191,0.011316,18.042915999999998,2604,25,55.42256910099771
+564,15.189848000000001,0.012490000000000001,15.189604000000001,2504,24,65.83344349462878
+565,16.374758999999997,0.011439,16.374572,2504,24,61.06960108542667
+566,17.028771000000003,0.010284,17.028536,2404,23,58.7241439796213
+567,16.432163,0.010761999999999999,16.431881,2404,23,60.85626098037124
+568,16.348532,0.009953,16.348204000000003,2404,23,61.16757149816265
+569,17.445871,0.01061,17.445555000000002,2404,23,57.32015329013954
+570,15.337817,0.013099,15.337610999999999,2304,22,65.19832646327701
+571,17.263277000000002,0.008741,17.263044,2304,22,57.926429611249354
+572,15.909455999999999,0.032705,15.909239,2504,24,62.85570040861234
+573,17.26318,0.01032,17.262835,2504,24,57.92675509378921
+574,16.463345,0.011899000000000002,16.463136,2504,24,60.74099765266414
+575,16.534322,0.011925,16.534106,2404,23,60.48025434608084
+576,16.217202,0.010779,16.216992,2404,23,61.66291817787063
+577,17.270231,0.009737,17.269821,2404,23,57.903105059799145
+578,16.195902,0.012695,16.195618,2404,23,61.744014010457704
+579,16.741279000000002,0.011087000000000001,16.740978,2404,23,59.73259271289845
+580,16.785031,0.010875,16.784797,2304,22,59.57689324493949
+581,16.824946999999998,0.009902,16.824628,2204,21,59.435551268006975
+582,15.640827999999999,0.010244000000000001,15.640533000000001,2204,21,63.935234119319006
+583,16.756191,0.026045,16.755969,2404,23,59.679434305803746
+584,16.773251,0.010628,16.773037000000002,2404,23,59.61873461501292
+585,16.309694999999998,0.010273,16.309465,2404,23,61.31322504804658
+586,17.408959000000003,0.010855,17.408564000000002,2304,22,57.44168850073114
+587,16.412368999999998,0.012021,16.41207,2304,22,60.929656163592234
+588,15.702853,0.011183,15.702631000000002,2304,22,63.682695112792565
+589,17.148359,0.009408999999999999,17.148072,2304,22,58.314617742723954
+590,16.262212,0.010253,16.261979999999998,2304,22,61.49224963983989
+591,17.276329,0.012238,17.275905,2304,22,57.88266708743507
+592,16.676356,0.012405000000000001,16.676046,2304,22,59.965138666984565
+593,16.042072,0.026824,16.04185,2404,23,62.33608725855363
+594,16.181122,0.009816,16.180935,2304,22,61.80041161546153
+595,17.204696,0.00957,17.204367,2304,22,58.12366577125223
+596,17.368381,0.011271,17.367989,2304,22,57.57589034925017
+597,15.699731000000002,0.012331,15.699477,2304,22,63.695358856785504
+598,16.451222,0.010416,16.450941,2304,22,60.78575804277639
+599,16.831479,0.010469,16.831165,2204,21,59.41248537933
+600,16.726772,0.010573,16.726385999999998,2204,21,59.78439832861953
+601,16.824531,0.010981000000000001,16.824101000000002,2204,21,59.43702085960078
+602,15.822955,0.012417,15.822706999999998,2204,21,63.199320228111624
+603,17.738477,0.009668,17.738078,2204,21,56.37462562315807
+604,15.662275999999999,0.029767000000000002,15.661998,2404,23,63.84768088622625
+605,19.47225,0.012174,19.471939,2404,23,51.355133587541246
+606,14.341882,0.015776,14.341651,2204,21,69.7258560626841
+607,18.734648999999997,0.010154,18.734287,2204,21,53.37703417875617
+608,14.960711,0.012209,14.960541000000001,2204,21,66.84174301609062
+609,15.857109000000001,0.01064,15.856940999999999,2204,21,63.063197711512224
+610,16.403237,0.011633000000000001,16.402898999999998,2204,21,60.96357688424547
+611,15.789790000000002,0.011963999999999999,15.789607,2204,21,63.33206458097289
+612,16.708374000000003,0.010797,16.708095,2204,21,59.850228394456565
+613,18.377867,0.009160999999999999,18.377433,2204,21,54.41327875536373
+614,16.116782999999998,0.028357999999999998,16.116437,2304,22,62.047121934941984
+615,18.102933,0.015351,18.102746,2304,22,55.239667516860386
+616,14.601674000000001,0.011594,14.601462000000001,2304,22,68.4852983294929
+617,15.822688000000001,0.009139,15.822374,2304,22,63.20038668524589
+618,17.669213,0.027629,17.668588999999997,2204,21,56.5956163412598
+619,15.819864999999998,0.013169,15.819625,2204,21,63.21166457488734
+620,22.830856,0.011352000000000001,22.830571000000003,2204,21,43.80037261852994
+621,10.083165,0.018695999999999997,10.082927,2204,21,99.17520937126389
+622,16.535092000000002,0.009927,16.534797,2104,20,60.47743792414338
+623,16.250148,0.010366,16.249889,2104,20,61.537901070193335
+624,17.189059,0.01071,17.188843,2104,20,58.17654125220002
+625,16.710875,0.024193,16.710493,2304,22,59.841271028596644
+626,26.457019,0.012256,26.456779,2304,22,37.797153186456875
+627,10.070149,0.021602,10.069922,2304,22,99.30339660316842
+628,12.426627000000002,0.011026000000000001,12.426464999999999,2204,21,80.47235987689982
+629,16.280409,0.010992,16.280258,2204,21,61.423518291217384
+630,16.856185999999997,0.009523,16.855915,2204,21,59.32540136896924
+631,17.333531,0.009174,17.333181,2204,21,57.69164978560917
+632,16.642904,0.013264,16.642466000000002,2104,20,60.08566774163931
+633,16.359980999999998,0.011853,16.359628,2104,20,61.12476536494756
+634,16.137587,0.012483999999999999,16.137235999999998,2104,20,61.96713300445723
+635,16.70388,0.028144,16.703479,2304,22,59.86633045735481
+636,16.606423,0.012931,16.606051,2304,22,60.21766397254846
+637,16.981634,0.012905,16.981171,2304,22,58.88714831564501
+638,15.947649000000002,0.012452999999999999,15.947241000000002,2304,22,62.705167388622606
+639,16.332897,0.012594,16.3325,2204,21,61.226125408125704
+640,16.685069,0.011965,16.684662,2204,21,59.93382466683237
+641,16.931769,0.011817000000000001,16.931407,2204,21,59.06057423769484
+642,15.347174,0.028449000000000002,15.346810000000001,2104,20,65.1585757742761
+643,17.571037,0.011564,17.570666,2104,20,56.91183736053825
+644,16.128266,0.012348,16.127867000000002,2104,20,62.00294563594127
+645,16.511194,0.023684,16.510832,2304,22,60.56497186090842
+646,16.888457,0.012638,16.888067,2304,22,59.212040507904305
+647,15.95408,0.011762,15.953716,2304,22,62.679891287996554
+648,16.443441999999997,0.018264,16.442981,2204,21,60.814518030957274
+649,18.983881,0.013766,18.983465000000002,2204,21,52.676267829533906
+650,13.841759999999999,0.01441,13.841104999999999,2204,21,72.24514801585926
+651,18.451389,0.011208000000000001,18.451192000000002,2204,21,54.19646184902395
+652,14.659221,0.012700999999999999,14.659009000000001,2104,20,68.21644888224279
+653,16.511708,0.011659,16.511476000000002,2104,20,60.56308650807052
+654,16.716732,0.009683,16.716548,2104,20,59.8203045906341
+655,16.516874,0.009574000000000001,16.516704,2104,20,60.54414412799903
+656,16.958329000000003,0.025074000000000003,16.958033,2204,21,58.968074036068046
+657,16.05934,0.009438,16.059052,2204,21,62.26905962511536
+658,16.536500999999998,0.009204,16.536325,2204,21,60.47228491686362
+659,16.668962,0.010258000000000001,16.668771999999997,2204,21,59.9917379378512
+660,16.222328,0.016855000000000002,16.222145,2204,21,61.643433667473616
+661,17.29753,0.008886999999999999,17.297254000000002,2204,21,57.81172225167409
+662,15.8891,0.010402,15.888912000000001,2204,21,62.93622672146314
+663,17.325077,0.009519,17.32473,2204,21,57.719801187608
+664,15.826507999999999,0.011284,15.826317,2004,19,63.18513218456024
+665,16.937337,0.008581,16.937027,2004,19,59.04115859535652
+666,16.087913999999998,0.025026,16.087712,2204,21,62.158462557669075
+667,17.038277,0.009086,17.038059,2204,21,58.69138058971573
+668,17.666534000000002,0.010439,17.666173,2204,21,56.60419865039741
+669,17.211889,0.011673,17.211643,2204,21,58.09937537942523
+670,25.668024000000003,0.023433000000000002,25.667678,2204,21,38.95897868881531
+671,8.676464,0.016115,8.676229000000001,2104,20,115.25432480328392
+672,13.196434,0.008879,13.19616,2104,20,75.77804731187229
+673,17.313829,0.009422999999999999,17.313548,2104,20,57.75729909311222
+674,16.271776000000003,0.009496000000000001,16.271489,2104,20,61.45610657373847
+675,16.410557999999998,0.009755999999999999,16.410363,2104,20,60.936380103589414
+676,17.173023,0.009496000000000001,17.172854,2004,19,58.230865934320356
+677,16.162014999999997,0.022648,16.161804,2204,21,61.873473078697195
+678,20.477668,0.010535,20.477377,2104,20,48.83368555442934
+679,18.289882,0.027563,18.289518,2104,20,54.67503836274067
+680,11.25193,0.01025,11.251671,2104,20,88.87364212184043
+681,16.396461000000002,0.010448,16.396282000000003,2104,20,60.988770686552414
+682,16.391748,0.010180999999999999,16.391563,2104,20,61.00630634389938
+683,16.433640999999998,0.023274,16.433455,2104,20,60.850787722574694
+684,16.326539,0.011835,16.326328,2004,19,61.24996853282867
+685,17.923134,0.008071,17.922912999999998,2004,19,55.793813738155386
+686,15.233117,0.010111,15.232958,2004,19,65.64644648892279
+687,17.460046,0.039487,17.459793,2204,21,57.273617721282065
+688,16.302228,0.009595999999999999,16.301982,2204,21,61.34130868492331
+689,16.403194,0.012454,16.403006,2104,20,60.96373669664579
+690,16.270094,0.009840000000000002,16.269932,2004,19,61.46245989728148
+691,16.413966,0.009007000000000001,16.413731000000002,2004,19,60.923728000898755
+692,17.365807,0.015248999999999999,17.365545,2004,19,57.58442438062337
+693,16.09903,0.009843999999999999,16.098827,2004,19,62.11554360728566
+694,16.589735,0.008757,16.589568,2004,19,60.278238320262496
+695,16.99769,0.009659000000000001,16.997419,1904,18,58.83152357761555
+696,15.856462000000002,0.009491,15.856288999999999,1904,18,63.06577091409167
+697,17.755976999999998,0.021693999999999998,17.755778,2104,20,56.31906371584059
+698,15.350226999999999,0.009826,15.349928,2104,20,65.14561641335989
+699,16.800682000000002,0.008663,16.800524,2104,20,59.52139323867923
+700,16.377389,0.010292,16.377180000000003,2004,19,61.05979408561401
+701,17.96126,0.0084,17.960950999999998,2004,19,55.675381348524546
+702,15.037450000000002,0.010716999999999999,15.037254,2004,19,66.50063674359681
+703,17.627568,0.008107,17.627231000000002,2004,19,56.72932306941037
+704,15.852807,0.01206,15.852533,1904,18,63.08031126601112
+705,16.384278,0.009882,16.384064,1904,18,61.03412063686908
+706,17.126811,0.009602000000000001,17.126614,1804,17,58.387985947880196
+707,16.141099,0.009184999999999999,16.140874999999998,1804,17,61.95365012010644
+708,16.68147,0.039707,16.681207,2004,19,59.946755291949685
+709,16.178766,0.008709000000000001,16.178502,2004,19,61.80941117511682
+710,17.893583,0.00824,17.892858,2004,19,55.88595643477329
+711,16.127848,0.022949999999999998,16.127496,1904,18,62.00455262227174
+712,15.918108,0.016758000000000002,15.917902000000002,1904,18,62.82153632831238
+713,16.737571,0.008783999999999998,16.737395,1904,18,59.74582572345773
+714,16.068397,0.009391,16.068196999999998,1904,18,62.233961483525704
+715,17.755785,0.023819999999999997,17.755546,1904,18,56.31967271511792
+716,15.167446,0.009972,15.167245,1904,18,65.93067811152913
+717,17.706514,0.007837,17.706196000000002,1904,18,56.476390553216746
+718,15.885835,0.025117999999999998,15.885653999999999,2004,19,62.94916194206977
+719,17.169292,0.008772,17.168995,1904,18,58.24351988422121
+720,15.947084,0.009935000000000001,15.946869,1904,18,62.70738901231096
+721,16.926638,0.008074,16.926368,1904,18,59.07847736803965
+722,16.112009999999998,0.009457,16.111793,1904,18,62.06550269022922
+723,17.548332,0.00812,17.547988,1904,18,56.98547303527196
+724,16.069022,0.010642,16.068836,1804,17,62.231540911450615
+725,16.178756999999997,0.008608,16.17858,1804,17,61.809445558765745
+726,16.8353,0.00818,16.835104,1804,17,59.399000908804716
+727,16.817789,0.008261,16.817496000000002,1804,17,59.4608482720291
+728,16.336724,0.007708,16.336477,1804,17,61.21178272951174
+729,16.782576,0.036232999999999994,16.782383000000003,2004,19,59.585608311858685
+730,15.980167999999999,0.010832000000000001,15.979974,2004,19,62.577564891683245
+731,16.861197,0.009099000000000001,16.861015,1904,18,59.307770379528804
+732,17.603088,0.008322,17.602812999999998,1904,18,56.80821455871833
+733,16.20028,0.010051000000000001,16.199848,1804,17,61.72732816963658
+734,15.589943,0.010424999999999999,15.589737,1804,17,64.14391636967498
+735,16.717409999999997,0.007376000000000001,16.717263,1804,17,59.817878487158005
+736,17.177564999999998,0.008656,17.177293,1804,17,58.215468839733695
+737,16.086508,0.007585000000000001,16.086339000000002,1804,17,62.16389535876898
+738,16.374298,0.009535,16.374010000000002,1804,17,61.071320431569035
+739,16.746454,0.023718,16.746146,1904,18,59.7141341086298
+740,16.551462,0.010196,16.551277,1904,18,60.41762353077933
+741,17.031613,0.007781999999999999,17.031228,1904,18,58.714344906733146
+742,16.384664,0.010253,16.384489,1904,18,61.0326827574859
+743,16.032606,0.009297,16.032382000000002,1904,18,62.37289184303537
+744,16.78665,0.008497,16.786474,1904,18,59.57114731051162
+745,16.380981,0.008131999999999999,16.38071,1904,18,61.046404974158754
+746,17.919872,0.014678,17.919528,1904,18,55.80397002835734
+747,16.133122,0.010056,16.132744000000002,1804,17,61.98428301726101
+748,15.401722,0.010041,15.401527,1704,16,64.92780482597985
+749,16.878735,0.007162,16.878529,1704,16,59.246146112253086
+750,16.626864,0.022784000000000002,16.626661000000002,1904,18,60.14363261767222
+751,20.166794,0.008704,20.166467,1904,18,49.58646376811307
+752,17.587721000000002,0.010786,17.587438,1904,18,56.85784986013821
+753,11.775609,0.009007000000000001,11.775402000000001,1904,18,84.92129791333934
+754,16.904685,0.007975999999999999,16.904490000000003,1904,18,59.155198691960244
+755,16.754099,0.007949,16.753811,1904,18,59.68688617633213
+756,16.417398,0.010116,16.417102999999997,1904,18,60.91099210727547
+757,16.410502,0.009592999999999999,16.410317,1804,17,60.93658804587452
+758,16.689624,0.007859999999999999,16.689453,1804,17,59.91746728386452
+759,16.972472,0.006994,16.971908,1804,17,58.91893649905565
+760,16.766775000000003,0.022974,16.766536,2004,19,59.64176175800056
+761,16.175974999999998,0.010013000000000001,16.175629,2004,19,61.82007576050285
+762,16.163376,0.010038,16.163197,2004,19,61.868263164823986
+763,17.152842,0.00796,17.152613000000002,2004,19,58.29937686128048
+764,16.653716,0.008874,16.653360999999997,1904,18,60.046658655641785
+765,16.847102999999997,0.009592999999999999,16.84674,1904,18,59.357386252105194
+766,15.817787,0.008907,15.817583999999998,1904,18,63.21996876048464
+767,16.649303,0.008555,16.649085,1804,17,60.0625743912523
+768,16.549757,0.007226,16.549571,1804,17,60.42384791510836
+769,17.164964,0.021454,17.164561,1804,17,58.258205493469134
+770,16.195795999999998,0.023139999999999997,16.195465,2004,19,61.74441811936876
+771,16.431874999999998,0.009252999999999999,16.431681,2004,19,60.85732760260166
+772,16.813841999999998,0.008347,16.813644,2004,19,59.4748065314281
+773,16.962061000000002,0.008164,16.961775,2004,19,58.9550998549056
+774,16.08018,0.010077000000000001,16.079857,2004,19,62.188358588025764
+775,16.138225,0.022515,16.138023,2004,19,61.96468322879375
+776,20.444244,0.009105,20.443884,2004,19,48.913523043454184
+777,16.744904000000002,0.017282000000000002,16.744629,1904,18,59.7196615758442
+778,13.065836000000001,0.008771,13.065584,1904,18,76.53547771455267
+779,16.277608999999998,0.009498,16.277412,1804,17,61.43408408446229
+780,16.291878999999998,0.01047,16.29166,1804,17,61.380274184457186
+781,17.324139,0.023995,17.323837,2004,19,57.72292637458058
+782,16.046545,0.010125,16.046362000000002,2004,19,62.31871097485472
+783,17.313989,0.009680999999999999,17.313603,2004,19,57.756765353148836
+784,19.983998,0.012660000000000001,19.983777,2004,19,50.04003703363061
+785,12.458796,0.008422,12.458587,2004,19,80.26457773287243
+786,16.397026,0.008185,16.396823,2004,19,60.98666916793326
+787,17.405329000000002,0.009042000000000001,17.404923,2004,19,57.4536683563982
+788,16.112925999999998,0.01071,16.112713,2004,19,62.06197434283507
+789,16.391296,0.00911,16.391099999999998,1904,18,61.007988630063174
+790,16.581211,0.008538,16.580917,1904,18,60.30922590635871
+791,17.180633,0.023609,17.180257,2104,20,58.20507311925003
+792,16.061166,0.010355,16.060855,2104,20,62.261980232319374
+793,16.994169,0.00962,16.99389,2104,20,58.843712805256914
+794,16.405365000000003,0.009075,16.405074,2104,20,60.955669075329915
+795,16.568678,0.011075,16.568455999999998,2004,19,60.35484544995081
+796,17.052473,0.009675,17.05203,2004,19,58.642520647884915
+797,15.662279000000002,0.0099,15.662103,2004,19,63.84766865664952
+798,16.353392000000003,0.008528,16.353201000000002,2004,19,61.14939334909845
+799,17.511200000000002,0.008452,17.510993,2004,19,57.106309105029915
+800,15.893983,0.009473,15.893785000000001,2004,19,62.91689125375307
+801,18.287359,0.009379,18.286977,1904,18,54.682581558113455
+802,18.318597,0.026477,18.318395000000002,2104,20,54.589333451683004
+803,24.679018,0.019813,24.67863,2104,20,40.5202508462857
+804,8.387346,0.013329,8.387156,2104,20,119.22722634788167
+805,13.394547999999999,0.008871,13.394249,2104,20,74.65724114020124
+806,16.478642,0.010350999999999999,16.478374,2104,20,60.68461223928525
+807,17.508713,0.009325,17.508506999999998,2104,20,57.11442068871653
+808,15.931908000000002,0.00956,15.931717,2104,20,62.76712117594452
+809,16.744412999999998,0.010499999999999999,16.744139,2004,19,59.72141274824027
+810,15.960861,0.010665999999999998,15.960598999999998,2004,19,62.65326162542234
+811,17.503922000000003,0.009466,17.503761,2004,19,57.130053481728254
+812,16.504649,0.026862,16.504454000000003,2204,21,60.588989199346194
+813,16.586965,0.008842,16.586743000000002,2204,21,60.28830470191503
+814,16.005221,0.011673,16.004962000000003,2204,21,62.47961212156959
+815,16.451549999999997,0.024046,16.451389,2104,20,60.784546136990144
+816,17.003867999999997,0.009016,17.003291,2104,20,58.81014837329954
+817,16.096762000000002,0.00919,16.096455,2104,20,62.124295557081595
+818,16.875261,0.009687000000000001,16.874972,2104,20,59.25834273022504
+819,16.665902,0.011099,16.665558,2104,20,60.00275292630426
+820,16.273187,0.01083,16.272969000000003,2104,20,61.45077789617977
+821,16.471989999999998,0.008449,16.471766,2104,20,60.70911893462782
+822,16.690112,0.032291,16.6899,2304,22,59.91571536488192
+823,17.153483,0.023798000000000003,17.152810000000002,2204,21,58.29719830077658
+824,16.123216,0.011685000000000001,16.123001000000002,2204,21,62.02236576127245
+825,16.880678,0.009459,16.880262,2204,21,59.23932676163837
+826,16.102014,0.022512,16.101797,2204,21,62.104032452089534
+827,16.865381,0.009332,16.865181,2204,21,59.293057180267674
+828,16.399265,0.011312,16.398989999999998,2204,21,60.9783426269409
+829,16.583562999999998,0.010639,16.583341,2104,20,60.30067241882821
+830,15.925186,0.009186,15.925000000000002,2104,20,62.79361509498225
+831,18.126442,0.008432,18.126238999999998,2104,20,55.16802470115205
+832,15.548002,0.01025,15.547747000000001,2104,20,64.3169456757209
+833,17.102649,0.038378999999999996,17.102341,2304,22,58.470474369204446
+834,16.043093000000002,0.010597,16.042785000000002,2304,22,62.33212012172465
+835,11.497692,0.012923,11.497482,2304,22,86.97397703817427
+836,19.213962000000002,0.010646,19.213608999999998,2304,22,52.04548650611466
+837,17.5739,0.016405999999999997,17.573569,2304,22,56.90256573668907
+838,17.932759,0.016095,17.932256,2304,22,55.76386767925671
+839,15.704971000000002,0.01812,15.704612999999998,2204,21,63.67410675256897
+840,17.023294,0.028534,17.022916,2204,21,58.743037628322696
+841,16.510680999999998,0.020188,16.51012,2204,21,60.56685366278957
+842,12.674558000000001,0.01594,12.674121,2204,21,78.89821483321154
+843,19.740066,0.040803,19.739659,2404,23,50.658391922296516
+844,16.835233000000002,0.023354,16.834818000000002,2304,22,59.39923730191319
+845,15.475666,0.016867999999999998,15.475236,2304,22,64.61757445527708
+846,18.214399,0.016513,18.214056,2304,22,54.90161931777161
+847,11.932228,0.017358,11.931834,2304,22,83.80664533061218
+848,22.355365,0.016676,22.354952,2304,22,44.73199162706581
+849,14.821124,0.021566,14.820805,2304,22,67.4712660119435
+850,16.273978000000003,0.016711,16.2736,2304,22,61.44779106866187
+851,16.628673,0.019613,16.628218,2304,22,60.1370897124503
+852,16.549172000000002,0.019456,16.548683,2204,21,60.42598384982644
+853,16.33401,0.0167,16.333633,2204,21,61.221953457846546
+854,16.542565,0.042666,16.542286,2404,23,60.450117620816364
+855,16.434422,0.016343,16.434106,2404,23,60.84789595886
+856,17.930602,0.016319,17.93006,2404,23,55.77057591262134
+857,14.895296,0.018198000000000002,14.894903,2404,23,67.13528888583349
+858,16.981700999999997,0.016371999999999998,16.981307,2304,22,58.88691598091382
+859,14.499225,0.017243,14.498845,2304,22,68.96920352639538
+860,19.522601,0.012353,19.522246,2304,22,51.22268287919217
+861,17.176083000000002,0.010908,17.175829,2304,22,58.22049183157766
+862,19.643298,0.014085,19.642901000000002,2304,22,50.90794834961013
+863,10.772542,0.021263999999999998,10.772231999999999,2304,22,92.82860071466884
+864,18.23207,0.035431,18.231631,2504,24,54.84840722967825
+865,15.841746,0.01866,15.841309,2404,23,63.12435510580715
+866,17.055128,0.01597,17.054645999999998,2404,23,58.63339166964915
+867,15.607814,0.020285,15.607471,2404,23,64.07047136773926
+868,24.420645,0.014641,24.420288,2404,23,40.94895937433266
+869,10.716723,0.030701000000000003,10.716512,2404,23,93.31210669530229
+870,16.210966,0.010213,16.210667,2404,23,61.686638538381985
+871,16.706644999999998,0.0109,16.706357,2404,23,59.85642239959011
+872,16.663763000000003,0.010379,16.66348,2404,23,60.01045502147383
+873,15.830401,0.010176000000000001,15.830245,2304,22,63.16959374560379
+874,17.376713,0.00937,17.376462,2304,22,57.548283153436444
+875,16.232394,0.025406,16.232212,2504,24,61.605207463544815
+876,16.170129,0.011759,16.16993,2504,24,61.842425623196945
+877,17.357471999999998,0.011164,17.357214,2404,23,57.6120762286121
+878,16.296809999999997,0.009677,16.296514000000002,2404,23,61.36170207543686
+879,18.841174,0.011262,18.840895,2404,23,53.075248920263675
+880,27.763049000000002,0.019542999999999998,27.76253,2404,23,36.01909862277734
+881,8.650534,0.014468,8.65033,2404,23,115.59979996610613
+882,10.390685,0.01027,10.390494,2404,23,96.24004577176578
+883,17.55657,0.009698,17.556332,2404,23,56.95873396682837
+884,16.212384999999998,0.012193,16.212134,2404,23,61.68123937347899
+885,16.052513,0.025239,16.052353,2604,25,62.29554213723421
+886,17.003643999999998,0.01073,17.003438,2604,25,58.81092311742119
+887,16.529512999999998,0.011512999999999999,16.529329,2604,25,60.49785011814929
+888,16.740489,0.010495,16.740254,2604,25,59.7354115521954
+889,18.9866,0.02685,18.986154000000003,2404,23,52.66872425816102
+890,24.737996000000003,0.019697000000000003,24.737709,2404,23,40.42364628080625
+891,8.907959,0.014134,8.907753,2404,23,112.25916060008808
+892,13.888224,0.009935999999999999,13.887932000000001,2404,23,72.00344694901234
+893,16.543924,0.01169,16.543739,2404,23,60.44515194823187
+894,15.781875000000001,0.011559999999999999,15.781678000000001,2404,23,63.363827175161376
+895,17.074473,0.025336,17.074269,2604,25,58.56696133461922
+896,26.203489,0.017617999999999998,26.203071,2604,25,38.162856862305624
+897,9.07014,0.016089000000000003,9.069851,2604,25,110.25188144835691
+898,14.698321,0.012895,14.697959,2604,25,68.03498168260171
+899,16.540525,0.025295,16.540365,2504,24,60.45757314232771
+900,15.732989,0.011814999999999999,15.732838,2504,24,63.56071309780996
+901,17.662354,0.016121999999999997,17.661983,2504,24,56.61759468754844
+902,16.639927999999998,0.012089,16.639526,2504,24,60.0964138787139
+903,16.17397,0.012373,16.173782000000003,2504,24,61.82773926253109
+904,16.417661,0.013198,16.41736,2404,23,60.91001635373029
+905,16.839073,0.012306999999999998,16.83879,2404,23,59.385691837074404
+906,16.354147,0.026874000000000002,16.353919,2604,25,61.14657034695848
+907,17.404041,0.011944,17.403683,2604,25,57.457920261162336
+908,15.235824000000001,0.014671,15.235639,2604,25,65.63478286438593
+909,17.209388,0.024966000000000002,17.208766,2504,24,58.10781882539925
+910,16.249071999999998,0.01079,16.248842999999997,2504,24,61.54197605869431
+911,16.590056,0.012466999999999999,16.589769,2504,24,60.27707200023918
+912,16.200615000000003,0.012618,16.200474,2504,24,61.72605175791165
+913,16.876695,0.010183000000000001,16.876153000000002,2504,24,59.25330759369651
+914,16.703677,0.010978,16.703391,2504,24,59.867058013633766
+915,16.295086,0.012159,16.294744,2504,24,61.36819406783124
+916,17.077445,0.026645,17.077185,2704,26,58.556768884338375
+917,15.990755999999998,0.013054000000000001,15.990579000000002,2704,26,62.536130249251514
+918,16.892509,0.011841,16.892283000000003,2604,25,59.197837337248124
+919,17.033561,0.010716999999999999,17.033289,2604,25,58.70763018960041
+920,16.034983,0.014013,16.034720999999998,2504,24,62.363645786216296
+921,16.415917,0.011157,16.415665999999998,2504,24,60.91648733360433
+922,17.147561,0.011183,17.147343999999997,2504,24,58.31733154353555
+923,16.122391999999998,0.011446,16.122197,2504,24,62.02553566493112
+924,16.565242,0.011448,16.564922,2504,24,60.36736438863977
+925,17.089785,0.011512,17.089012,2504,24,58.514486870373155
+926,16.851462,0.013156000000000001,16.851173,2404,23,59.34203216314406
+927,9.820788,0.046677,9.820056000000001,2604,25,101.82482301827511
+928,8.574152,0.014627000000000001,8.573951999999998,2604,25,116.62960955205833
+929,17.737522,0.016572,17.737185999999998,2604,25,56.37766087055453
+930,15.914416000000001,0.0158,15.914202,2604,25,62.83611035428507
+931,15.543908,0.010727,15.543691,2604,25,64.33388566118636
+932,20.900916,0.015494,20.900637,2604,25,47.844793022468494
+933,14.929153000000001,0.013068,14.928839,2604,25,66.98303647902864
+934,16.10406,0.024045,16.10372,2404,23,62.096142215068745
+935,14.69518,0.011276,14.69491,2404,23,68.04952372138347
+936,15.659873000000001,0.01064,15.659685999999999,2404,23,63.85747828223128
+937,17.431321,0.023793,17.431027,2604,25,57.36799867319292
+938,16.827816,0.01183,16.827475,2604,25,59.42541801027537
+939,18.249145000000002,0.012657999999999999,18.248849,2604,25,54.79708775397422
+940,18.886996,0.025673,18.886620999999998,2604,25,52.9464823310176
+941,12.118475,0.012495,12.118285,2504,24,82.51863373898118
+942,16.448551,0.017447,16.448203000000003,2504,24,60.79562874565669
+943,16.955726000000002,0.012518,16.95535,2504,24,58.97712666505698
+944,16.511688,0.012074,16.511395,2504,24,60.56315986590832
+945,16.326441,0.028034999999999997,16.326148,2504,24,61.25033618778276
+946,16.529489,0.011644999999999999,16.529282,2504,24,60.49793795803366
+947,16.861467,0.026817,16.861171000000002,2604,25,59.30682069359682
+948,16.544857,0.01374,16.544572,2504,24,60.44174331636713
+949,15.897463,0.010753,15.897262999999999,2504,24,62.90311856678012
+950,17.222769,0.02254,17.222494,2504,24,58.06267273282246
+951,16.853375,0.010526,16.853,2504,24,59.335296342720675
+952,16.159794,0.012548,16.159157,2504,24,61.881976960844916
+953,16.584522,0.013524,16.584245,2404,23,60.29718553238978
+954,15.923594,0.011470000000000001,15.923392000000002,2404,23,62.79989303922218
+955,17.00844,0.023745000000000002,17.007932,2404,23,58.79433975132346
+956,9.677705999999999,0.016773999999999997,9.677163,2404,23,103.33027269065624
+957,8.583012,0.016299,8.582823999999999,2404,23,116.5092161120129
+958,18.05115,0.031859,18.050943999999998,2604,25,55.39813252895245
+959,14.889499,0.011106,14.889228,2504,24,67.16142698958507
+960,16.513044,0.011294,16.512854,2504,24,60.558186606903
+961,23.453857000000003,0.011032,23.45355,2504,24,42.63691042373115
+962,17.116778999999998,0.015666,17.115936,2504,24,58.42220665465156
+963,9.781416,0.023585,9.780895,2504,24,102.23468667522167
+964,17.376797,0.014514,17.37647,2304,22,57.54800496317014
+965,17.600955000000003,0.018375,17.600564,2304,22,56.81509895343746
+966,13.463305,0.011862,13.463095,2304,22,74.27596715665284
+967,17.457114,0.009151,17.456819,2304,22,57.283237080310066
+968,28.883163,0.039117,28.882723,2504,24,34.6222468778783
+969,12.520648000000001,0.035494000000000005,12.520283000000001,2504,24,79.86807072605187
+970,8.225767,0.012133999999999999,8.225566,2404,23,121.56921050644883
+971,16.049627,0.009584,16.049277,2404,23,62.306743951121106
+972,16.835514,0.011821000000000002,16.835226,2404,23,59.398245874762125
+973,16.698330000000002,0.009748999999999999,16.698155999999997,2404,23,59.886228143772456
+974,16.301168,0.011341,16.30092,2404,23,61.345297465801224
+975,16.754944000000002,0.011326,16.754654000000002,2304,22,59.683875995049576
+976,15.749144999999999,0.009500999999999999,15.748936000000002,2304,22,63.49551039119902
+977,17.562299,0.009392,17.562066,2204,21,56.94015345029714
+978,9.576795,0.016019000000000002,9.575697,2204,21,104.41906713049616
+979,9.176388000000001,0.030168999999999998,9.176145,2404,23,108.97533975241673
+980,15.08373,0.02408,15.083422,2404,23,66.2965990507653
+981,16.762994,0.012218999999999999,16.762802999999998,2304,22,59.65521433700925
+982,19.235636,0.010589,19.235440999999998,2304,22,51.98684358552013
+983,14.121284,0.018427000000000002,14.121029,2304,22,70.81509018584995
+984,21.944482,0.012248,21.944304000000002,2304,22,45.56954226579602
+985,10.379436,0.010048,10.379235000000001,2304,22,96.34434857539465
+986,17.527433,0.009361000000000001,17.527173,2304,22,57.05342020134951
+987,15.848339999999999,0.011486,15.848145,2204,21,63.09809103035397
+988,17.197993,0.009857000000000001,17.197734,2204,21,58.14631974789151
+989,16.097621999999998,0.041430999999999996,16.097442,2404,23,62.1209766262371
+990,16.985498000000003,0.012322,16.98533,2304,22,58.87375218554085
+991,16.321194000000002,0.009428,16.320997000000002,2304,22,61.27002718060945
+992,16.183177,0.011068,16.182903,2304,22,61.79256396936152
+993,16.720508,0.010205,16.72037,2304,22,59.806795343777836
+994,17.974731000000002,0.010291,17.97431,2204,21,55.633655936214005
+995,14.932739999999999,0.012267,14.93254,2204,21,66.96694645456896
+996,16.689943,0.009026,16.689739,2204,21,59.916322062933354
+997,16.994348,0.009517999999999999,16.994101,2204,21,58.843093009511165
+998,16.89216,0.010227,16.891917,2204,21,59.199060392513445
+999,15.771558,0.010326,15.771288000000002,2204,21,63.40527676466713
+1000,16.985316,0.024999,16.985159,2404,23,58.87438302590308
+1001,17.132959,0.011084,17.132646,2304,22,58.36703397235702
+1002,15.46376,0.012051000000000001,15.463561,2204,21,64.66732541115485
+1003,17.477928,0.008335,17.477574999999998,2204,21,57.215019995505195
+1004,15.543932999999999,0.010876,15.543764,2204,21,64.33378219013167
+1005,17.159707,0.008895,17.159439,2204,21,58.27605331489634
+1006,16.192970000000003,0.009701999999999999,16.19279,2204,21,61.75519376618371
+1007,9.699892,0.015817,9.699316,2204,21,103.09393135511199
+1008,8.459995,0.010825000000000001,8.459729,2204,21,118.2033795528248
+1009,16.46831,0.010067,16.468018,2104,20,60.722684962816466
+1010,16.04561,0.024094,16.045342,2304,22,62.32234237277361
+1011,17.173335,0.010020000000000001,17.172981,2304,22,58.229808013411485
+1012,15.919287,0.01192,15.918986,2304,22,62.81688369585899
+1013,16.708686,0.010648999999999999,16.708384,2304,22,59.849110815775695
+1014,16.230838000000002,0.010727,16.230623,2204,21,61.611113363339584
+1015,17.503227,0.021433999999999998,17.502938999999998,2204,21,57.132321942690915
+1016,16.021271,0.010499000000000001,16.020666,2204,21,62.417020472345804
+1017,16.785307,0.010541,16.784988000000002,2204,21,59.575913624933996
+1018,16.217557,0.010742,16.217276,2104,20,61.66156838542328
+1019,16.179605,0.009269999999999999,16.179413,2104,20,61.80620602295298
+1020,17.093359,0.02489,17.092998,2304,22,58.50225224895821
+1021,16.987164,0.011036,16.986858,2304,22,58.867978198126536
+1022,15.754391,0.011714,15.754204000000001,2304,22,63.47436724148842
+1023,16.998541999999997,0.013949,16.998251999999997,2304,22,58.82857482718225
+1024,16.857528,0.011948,16.857263,2204,21,59.32067857161501
+1025,16.131686,0.011175000000000001,16.131389,2204,21,61.989800694112205
+1026,16.500599,0.010218,16.50039,2204,21,60.603860502276305
+1027,16.79334,0.010395,16.793157,2104,20,59.54741582079562
+1028,9.796621,0.01282,9.796264,2104,20,102.07601171873445
+1029,8.983414,0.011101999999999999,8.983125,2104,20,111.31625459986593
+1030,15.287471,0.010336000000000001,15.2868,2104,20,65.41304313839746
+1031,19.786303,0.028853,19.785997,2304,22,50.540012452048266
+1032,12.686164999999999,0.011777,12.685963999999998,2304,22,78.82602819685856
+1033,17.200736000000003,0.009374,17.200436,2304,22,58.13704715891226
+1034,16.662408,0.009995,16.662169000000002,2204,21,60.01533511842946
+1035,16.132644000000003,0.010539,16.132428,2204,21,61.986119572216424
+1036,16.336244,0.011073999999999999,16.336023,2204,21,61.213581285881865
+1037,16.737871000000002,0.010465,16.737613,2204,21,59.74475487354395
+1038,19.001261,0.010065,19.000937999999998,2104,20,52.628086104390654
+1039,16.408847,0.025485,16.408527999999997,2104,20,60.94273412385404
+1040,14.349423,0.009832,14.349139000000001,2104,20,69.68921328753079
+1041,16.58855,0.023669,16.588337000000003,2304,22,60.28254428506409
+1042,16.383245000000002,0.010243,16.382966999999997,2304,22,61.03796897378998
+1043,17.051349000000002,0.009798,17.050943,2204,21,58.64638627712094
diff --git a/rs/src/graph.rs b/rs/src/graph.rs
new file mode 100644
index 0000000..7426bee
--- /dev/null
+++ b/rs/src/graph.rs
@@ -0,0 +1,122 @@
+use crate::vertex::Vertex;
+
+#[derive(Clone)]
+pub struct SubView {
+ pub x: f32,
+ pub y: f32,
+ pub width: f32,
+ pub height: f32,
+}
+
+pub struct GraphView {
+ pub viewport: SubView,
+ pub lines: Vec<Vec<Vertex>>,
+ pub show_grid: bool,
+ pub title: String,
+ pub x_axis_label: String,
+ pub y_axis_label: String,
+ pub legend_items: Vec<LegendItem>,
+}
+
+#[derive(Clone)]
+pub struct LegendItem {
+ pub label: String,
+ pub color: [f32; 3],
+}
+
+impl GraphView {
+ pub fn new(viewport: SubView, title: String, x_axis_label: String, y_axis_label: String) -> Self {
+ Self {
+ viewport,
+ lines: Vec::new(),
+ show_grid: true,
+ title,
+ x_axis_label,
+ y_axis_label,
+ legend_items: Vec::new(),
+ }
+ }
+
+ pub fn add_legend_item(&mut self, label: String, color: [f32; 3]) {
+ self.legend_items.push(LegendItem { label, color });
+ }
+
+ pub fn generate_grid_lines(&self) -> Vec<Vertex> {
+ let mut vertices = Vec::new();
+ let grid_color = [0.3, 0.7, 0.9];
+
+ // Vertical grid lines (10 divisions)
+ for i in 0..=10 {
+ let x = -1.0 + (i as f32 / 10.0) * 2.0;
+ vertices.push(Vertex { position: [x, -1.0], color: grid_color });
+ vertices.push(Vertex { position: [x, 1.0], color: grid_color });
+ }
+
+ // Horizontal grid lines (10 divisions)
+ for i in 0..=10 {
+ let y = -1.0 + (i as f32 / 10.0) * 2.0;
+ vertices.push(Vertex { position: [-1.0, y], color: grid_color });
+ vertices.push(Vertex { position: [1.0, y], color: grid_color });
+ }
+
+ vertices
+ }
+
+ pub fn generate_border(&self) -> Vec<Vertex> {
+ let border_color = [0.6, 0.7, 0.7];
+ vec![
+ // Top border
+ Vertex { position: [-1.0, 1.0], color: border_color },
+ Vertex { position: [1.0, 1.0], color: border_color },
+ // Right border
+ Vertex { position: [1.0, 1.0], color: border_color },
+ Vertex { position: [1.0, -1.0], color: border_color },
+ // Bottom border
+ Vertex { position: [1.0, -1.0], color: border_color },
+ Vertex { position: [-1.0, -1.0], color: border_color },
+ // Left border
+ Vertex { position: [-1.0, -1.0], color: border_color },
+ Vertex { position: [-1.0, 1.0], color: border_color },
+ ]
+ }
+
+ pub fn update(&mut self, time: f32, graph_idx: usize) {
+ // Add new line every 10 frames
+ if (time * 60.0) as u32 % 10 == 0 && self.lines.len() < 50 {
+ let mut line = Vec::new();
+ let phase = time + (graph_idx as f32 * 2.0);
+ let freq = 2.0 + (time * 0.5 + graph_idx as f32).sin() * 1.0;
+
+ for i in 0..100 {
+ let x = (i as f32 / 100.0) * 2.0 - 1.0;
+ let y = ((i as f32) * 0.1 * freq + phase).sin() * 0.3;
+
+ // Different color per graph
+ let hue = (time * 0.1 + graph_idx as f32 * 0.5) % 1.0;
+ let color = [
+ (hue * 6.0).sin().abs(),
+ ((hue + 0.33) * 6.0).sin().abs(),
+ ((hue + 0.66) * 6.0).sin().abs(),
+ ];
+
+ line.push(Vertex {
+ position: [x, y],
+ color,
+ });
+ }
+ self.lines.push(line);
+ }
+
+ // Scroll lines down
+ for line in self.lines.iter_mut() {
+ for vertex in line.iter_mut() {
+ vertex.position[1] -= 0.01;
+ }
+ }
+
+ // Remove lines that have scrolled off screen
+ self.lines.retain(|line| {
+ line.first().map(|v| v.position[1] > -1.1).unwrap_or(false)
+ });
+ }
+}
diff --git a/rs/src/main.rs b/rs/src/main.rs
new file mode 100644
index 0000000..917515d
--- /dev/null
+++ b/rs/src/main.rs
@@ -0,0 +1,89 @@
+mod vertex;
+mod graph;
+mod renderer;
+mod metrics;
+
+use winit::{
+ event::*,
+ event_loop::EventLoop,
+ keyboard::{KeyCode, PhysicalKey},
+};
+
+use renderer::State;
+
+fn main() {
+ env_logger::init();
+ let event_loop = EventLoop::new().unwrap();
+ let window = std::sync::Arc::new(
+ event_loop
+ .create_window(
+ winit::window::Window::default_attributes()
+ .with_title("TimePlot - Waterfall Display")
+ .with_inner_size(winit::dpi::LogicalSize::new(1280, 720))
+ )
+ .unwrap(),
+ );
+
+ let mut state = pollster::block_on(State::new(window.clone()));
+
+ event_loop
+ .run(move |event, control_flow| match event {
+ Event::WindowEvent {
+ ref event,
+ window_id,
+ } if window_id == state.window.id() => match event {
+ WindowEvent::CloseRequested => control_flow.exit(),
+ WindowEvent::Resized(physical_size) => {
+ state.resize(*physical_size);
+ }
+ WindowEvent::KeyboardInput {
+ event: key_event,
+ ..
+ } => {
+ if key_event.state == winit::event::ElementState::Pressed {
+ if let PhysicalKey::Code(keycode) = key_event.physical_key {
+ match keycode {
+ KeyCode::KeyG => {
+ println!("Grid toggle pressed");
+ // Toggle grid for all graphs
+ for graph in &mut state.graphs {
+ graph.show_grid = !graph.show_grid;
+ println!("Grid now: {}", graph.show_grid);
+ }
+ }
+ KeyCode::KeyM => {
+ // Toggle metrics display
+ state.toggle_metrics();
+ }
+ KeyCode::KeyE => {
+ // Export metrics to CSV
+ if let Err(e) = state.export_metrics("metrics.csv") {
+ eprintln!("Failed to export metrics: {}", e);
+ } else {
+ println!("Metrics exported to metrics.csv");
+ }
+ }
+ KeyCode::Escape => control_flow.exit(),
+ _ => {}
+ }
+ }
+ }
+ }
+ WindowEvent::RedrawRequested => {
+ state.update();
+ match state.render() {
+ Ok(_) => {}
+ Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
+ Err(wgpu::SurfaceError::OutOfMemory) => control_flow.exit(),
+ Err(e) => eprintln!("{:?}", e),
+ }
+ }
+ _ => {}
+ },
+ Event::AboutToWait => {
+ state.window.request_redraw();
+ }
+ _ => {}
+ })
+ .unwrap();
+}
diff --git a/rs/src/metrics.rs b/rs/src/metrics.rs
new file mode 100644
index 0000000..369aff8
--- /dev/null
+++ b/rs/src/metrics.rs
@@ -0,0 +1,290 @@
+use std::time::{Duration, Instant};
+use std::collections::VecDeque;
+
+/// Rolling average calculator for smooth metric display
+pub struct RollingAverage {
+ values: VecDeque<f64>,
+ capacity: usize,
+ sum: f64,
+}
+
+impl RollingAverage {
+ pub fn new(capacity: usize) -> Self {
+ Self {
+ values: VecDeque::with_capacity(capacity),
+ capacity,
+ sum: 0.0,
+ }
+ }
+
+ pub fn push(&mut self, value: f64) {
+ if self.values.len() >= self.capacity {
+ if let Some(old) = self.values.pop_front() {
+ self.sum -= old;
+ }
+ }
+ self.values.push_back(value);
+ self.sum += value;
+ }
+
+ pub fn average(&self) -> f64 {
+ if self.values.is_empty() {
+ 0.0
+ } else {
+ self.sum / self.values.len() as f64
+ }
+ }
+
+ pub fn min(&self) -> f64 {
+ self.values.iter().copied().fold(f64::INFINITY, f64::min)
+ }
+
+ pub fn max(&self) -> f64 {
+ self.values.iter().copied().fold(f64::NEG_INFINITY, f64::max)
+ }
+
+ pub fn latest(&self) -> f64 {
+ self.values.back().copied().unwrap_or(0.0)
+ }
+}
+
+/// Frame timing breakdown
+#[derive(Debug, Clone)]
+pub struct FrameTiming {
+ pub total_ms: f64,
+ pub update_ms: f64,
+ pub render_ms: f64,
+ pub vertex_count: usize,
+ pub line_count: usize,
+}
+
+/// Performance metrics collector with rolling averages
+pub struct PerformanceMetrics {
+ // Rolling averages (default: 60 frames)
+ frame_time: RollingAverage,
+ update_time: RollingAverage,
+ render_time: RollingAverage,
+ vertex_count: RollingAverage,
+ line_count: RollingAverage,
+
+ // Session-wide statistics
+ pub total_frames: u64,
+ session_start: Instant,
+
+ // Current frame timing
+ frame_start: Option<Instant>,
+ update_start: Option<Instant>,
+ render_start: Option<Instant>,
+
+ // Historical data for export
+ history: VecDeque<FrameTiming>,
+ history_capacity: usize,
+}
+
+impl PerformanceMetrics {
+ pub fn new(rolling_window: usize, history_capacity: usize) -> Self {
+ Self {
+ frame_time: RollingAverage::new(rolling_window),
+ update_time: RollingAverage::new(rolling_window),
+ render_time: RollingAverage::new(rolling_window),
+ vertex_count: RollingAverage::new(rolling_window),
+ line_count: RollingAverage::new(rolling_window),
+ total_frames: 0,
+ session_start: Instant::now(),
+ frame_start: None,
+ update_start: None,
+ render_start: None,
+ history: VecDeque::with_capacity(history_capacity),
+ history_capacity,
+ }
+ }
+
+ // Frame timing markers
+ pub fn begin_frame(&mut self) {
+ self.frame_start = Some(Instant::now());
+ }
+
+ pub fn begin_update(&mut self) {
+ self.update_start = Some(Instant::now());
+ }
+
+ pub fn end_update(&mut self) -> f64 {
+ if let Some(start) = self.update_start.take() {
+ let duration = start.elapsed();
+ duration.as_secs_f64() * 1000.0
+ } else {
+ 0.0
+ }
+ }
+
+ pub fn begin_render(&mut self) {
+ self.render_start = Some(Instant::now());
+ }
+
+ pub fn end_render(&mut self) -> f64 {
+ if let Some(start) = self.render_start.take() {
+ let duration = start.elapsed();
+ duration.as_secs_f64() * 1000.0
+ } else {
+ 0.0
+ }
+ }
+
+ pub fn end_frame(&mut self, update_ms: f64, render_ms: f64, vertex_count: usize, line_count: usize) {
+ if let Some(start) = self.frame_start.take() {
+ let total_ms = start.elapsed().as_secs_f64() * 1000.0;
+
+ // Update rolling averages
+ self.frame_time.push(total_ms);
+ self.update_time.push(update_ms);
+ self.render_time.push(render_ms);
+ self.vertex_count.push(vertex_count as f64);
+ self.line_count.push(line_count as f64);
+
+ // Record to history
+ let timing = FrameTiming {
+ total_ms,
+ update_ms,
+ render_ms,
+ vertex_count,
+ line_count,
+ };
+
+ if self.history.len() >= self.history_capacity {
+ self.history.pop_front();
+ }
+ self.history.push_back(timing);
+
+ self.total_frames += 1;
+ }
+ }
+
+ // Getters for current metrics
+ pub fn fps(&self) -> f64 {
+ let avg_frame_time = self.frame_time.average();
+ if avg_frame_time > 0.0 {
+ 1000.0 / avg_frame_time
+ } else {
+ 0.0
+ }
+ }
+
+ pub fn avg_frame_time_ms(&self) -> f64 {
+ self.frame_time.average()
+ }
+
+ pub fn avg_update_time_ms(&self) -> f64 {
+ self.update_time.average()
+ }
+
+ pub fn avg_render_time_ms(&self) -> f64 {
+ self.render_time.average()
+ }
+
+ pub fn avg_vertex_count(&self) -> f64 {
+ self.vertex_count.average()
+ }
+
+ pub fn avg_line_count(&self) -> f64 {
+ self.line_count.average()
+ }
+
+ pub fn min_fps(&self) -> f64 {
+ let max_frame_time = self.frame_time.max();
+ if max_frame_time > 0.0 && max_frame_time.is_finite() {
+ 1000.0 / max_frame_time
+ } else {
+ 0.0
+ }
+ }
+
+ pub fn max_fps(&self) -> f64 {
+ let min_frame_time = self.frame_time.min();
+ if min_frame_time > 0.0 && min_frame_time.is_finite() {
+ 1000.0 / min_frame_time
+ } else {
+ 0.0
+ }
+ }
+
+ pub fn session_duration(&self) -> Duration {
+ self.session_start.elapsed()
+ }
+
+ // Export functionality
+ pub fn export_to_csv(&self, path: &str) -> std::io::Result<()> {
+ use std::io::Write;
+ let mut file = std::fs::File::create(path)?;
+
+ // Write header
+ writeln!(file, "frame,total_ms,update_ms,render_ms,vertex_count,line_count,fps")?;
+
+ // Write data
+ for (i, timing) in self.history.iter().enumerate() {
+ let fps = if timing.total_ms > 0.0 {
+ 1000.0 / timing.total_ms
+ } else {
+ 0.0
+ };
+ writeln!(
+ file,
+ "{},{},{},{},{},{},{}",
+ i,
+ timing.total_ms,
+ timing.update_ms,
+ timing.render_ms,
+ timing.vertex_count,
+ timing.line_count,
+ fps
+ )?;
+ }
+
+ Ok(())
+ }
+
+ pub fn format_summary(&self) -> String {
+ format!(
+ "FPS: {:.1} (min: {:.1}, max: {:.1}) | Frame: {:.2}ms | Update: {:.2}ms | Render: {:.2}ms | Vertices: {:.0} | Lines: {:.0}",
+ self.fps(),
+ self.min_fps(),
+ self.max_fps(),
+ self.avg_frame_time_ms(),
+ self.avg_update_time_ms(),
+ self.avg_render_time_ms(),
+ self.avg_vertex_count(),
+ self.avg_line_count()
+ )
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_rolling_average() {
+ let mut avg = RollingAverage::new(3);
+ avg.push(10.0);
+ avg.push(20.0);
+ avg.push(30.0);
+ assert_eq!(avg.average(), 20.0);
+
+ avg.push(40.0);
+ assert_eq!(avg.average(), 30.0); // (20 + 30 + 40) / 3
+ }
+
+ #[test]
+ fn test_metrics_lifecycle() {
+ let mut metrics = PerformanceMetrics::new(60, 1000);
+
+ metrics.begin_frame();
+ metrics.begin_update();
+ let update_ms = metrics.end_update();
+ metrics.begin_render();
+ let render_ms = metrics.end_render();
+ metrics.end_frame(update_ms, render_ms, 1000, 10);
+
+ assert_eq!(metrics.total_frames, 1);
+ assert!(metrics.fps() > 0.0);
+ }
+}
diff --git a/rs/src/renderer.rs b/rs/src/renderer.rs
new file mode 100644
index 0000000..2b9c0d0
--- /dev/null
+++ b/rs/src/renderer.rs
@@ -0,0 +1,682 @@
+use glyphon::{
+ Attrs, Buffer, Color as TextColor, Family, FontSystem, Metrics, Resolution, Shaping,
+ SwashCache, TextArea, TextAtlas, TextBounds, TextRenderer, Viewport
+};
+use crate::vertex::Vertex;
+use crate::graph::{GraphView, SubView};
+use crate::metrics::PerformanceMetrics;
+
+pub struct State {
+ surface: wgpu::Surface<'static>,
+ device: wgpu::Device,
+ queue: wgpu::Queue,
+ config: wgpu::SurfaceConfiguration,
+ pub size: winit::dpi::PhysicalSize<u32>,
+ pub window: std::sync::Arc<winit::window::Window>,
+ line_pipeline: wgpu::RenderPipeline,
+ line_list_pipeline: wgpu::RenderPipeline,
+ vertex_buffer: wgpu::Buffer,
+ time: f32,
+ pub graphs: Vec<GraphView>,
+ font_system: FontSystem,
+ swash_cache: SwashCache,
+ text_atlas: TextAtlas,
+ text_renderer: TextRenderer,
+ viewport: Viewport,
+ metrics: PerformanceMetrics,
+ show_metrics: bool,
+}
+
+impl State {
+ pub async fn new(window: std::sync::Arc<winit::window::Window>) -> Self {
+ let size = window.inner_size();
+
+ let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
+ backends: wgpu::Backends::VULKAN,
+ ..Default::default()
+ });
+
+ let surface = instance.create_surface(window.clone()).unwrap();
+
+ let adapter = instance
+ .request_adapter(&wgpu::RequestAdapterOptions {
+ power_preference: wgpu::PowerPreference::HighPerformance,
+ compatible_surface: Some(&surface),
+ force_fallback_adapter: false,
+ })
+ .await
+ .unwrap();
+
+ let (device, queue) = adapter
+ .request_device(
+ &wgpu::DeviceDescriptor {
+ required_features: wgpu::Features::empty(),
+ required_limits: wgpu::Limits::default(),
+ label: None,
+ memory_hints: Default::default(),
+ },
+ None,
+ )
+ .await
+ .unwrap();
+
+ let surface_caps = surface.get_capabilities(&adapter);
+ let surface_format = surface_caps
+ .formats
+ .iter()
+ .copied()
+ .find(|f| f.is_srgb())
+ .unwrap_or(surface_caps.formats[0]);
+
+ let config = wgpu::SurfaceConfiguration {
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
+ format: surface_format,
+ width: size.width,
+ height: size.height,
+ present_mode: surface_caps.present_modes[0],
+ alpha_mode: surface_caps.alpha_modes[0],
+ view_formats: vec![],
+ desired_maximum_frame_latency: 2,
+ };
+ surface.configure(&device, &config);
+
+ let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
+ label: Some("Waterfall Shader"),
+ source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
+ });
+
+ let render_pipeline_layout =
+ device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: Some("Render Pipeline Layout"),
+ bind_group_layouts: &[],
+ push_constant_ranges: &[],
+ });
+
+ let line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+ label: Some("Line Strip Pipeline"),
+ layout: Some(&render_pipeline_layout),
+ vertex: wgpu::VertexState {
+ module: &shader,
+ entry_point: "vs_main",
+ buffers: &[Vertex::desc()],
+ compilation_options: Default::default(),
+ },
+ fragment: Some(wgpu::FragmentState {
+ module: &shader,
+ entry_point: "fs_main",
+ targets: &[Some(wgpu::ColorTargetState {
+ format: config.format,
+ blend: Some(wgpu::BlendState::REPLACE),
+ write_mask: wgpu::ColorWrites::ALL,
+ })],
+ compilation_options: Default::default(),
+ }),
+ primitive: wgpu::PrimitiveState {
+ topology: wgpu::PrimitiveTopology::LineStrip,
+ strip_index_format: None,
+ front_face: wgpu::FrontFace::Ccw,
+ cull_mode: None,
+ polygon_mode: wgpu::PolygonMode::Fill,
+ unclipped_depth: false,
+ conservative: false,
+ },
+ depth_stencil: None,
+ multisample: wgpu::MultisampleState {
+ count: 1,
+ mask: !0,
+ alpha_to_coverage_enabled: false,
+ },
+ multiview: None,
+ cache: None,
+ });
+
+ let line_list_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
+ label: Some("Line List Pipeline"),
+ layout: Some(&render_pipeline_layout),
+ vertex: wgpu::VertexState {
+ module: &shader,
+ entry_point: "vs_main",
+ buffers: &[Vertex::desc()],
+ compilation_options: Default::default(),
+ },
+ fragment: Some(wgpu::FragmentState {
+ module: &shader,
+ entry_point: "fs_main",
+ targets: &[Some(wgpu::ColorTargetState {
+ format: config.format,
+ blend: Some(wgpu::BlendState::REPLACE),
+ write_mask: wgpu::ColorWrites::ALL,
+ })],
+ compilation_options: Default::default(),
+ }),
+ primitive: wgpu::PrimitiveState {
+ topology: wgpu::PrimitiveTopology::LineList,
+ strip_index_format: None,
+ front_face: wgpu::FrontFace::Ccw,
+ cull_mode: None,
+ polygon_mode: wgpu::PolygonMode::Fill,
+ unclipped_depth: false,
+ conservative: false,
+ },
+ depth_stencil: None,
+ multisample: wgpu::MultisampleState {
+ count: 1,
+ mask: !0,
+ alpha_to_coverage_enabled: false,
+ },
+ multiview: None,
+ cache: None,
+ });
+
+ // Create initial empty buffer (will be updated each frame)
+ let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
+ label: Some("Vertex Buffer"),
+ size: (std::mem::size_of::<Vertex>() * 100 * 100) as u64,
+ usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
+ mapped_at_creation: false,
+ });
+
+ // Create 2 graph views side-by-side with header area
+ // Reserve top 60px for header
+ let header_height = 60.0 / size.height as f32;
+ let graph_area_height = 1.0 - header_height;
+
+ let mut graphs = vec![
+ GraphView::new(
+ SubView {
+ x: 0.0,
+ y: header_height,
+ width: 0.5,
+ height: graph_area_height
+ },
+ "Frequency vs Time".to_string(),
+ "Time (s)".to_string(),
+ "Frequency (Hz)".to_string()
+ ),
+ GraphView::new(
+ SubView {
+ x: 0.5,
+ y: header_height,
+ width: 0.5,
+ height: graph_area_height
+ },
+ "Position vs Time".to_string(),
+ "Time (s)".to_string(),
+ "Position (m)".to_string()
+ ),
+ ];
+
+ // Add legend items
+ graphs[0].add_legend_item("Signal A".to_string(), [1.0, 0.3, 0.3]);
+ graphs[0].add_legend_item("Signal B".to_string(), [0.3, 1.0, 0.3]);
+ graphs[1].add_legend_item("Object 1".to_string(), [0.3, 0.6, 1.0]);
+ graphs[1].add_legend_item("Object 2".to_string(), [1.0, 0.8, 0.3]);
+
+ // Initialize text rendering
+ let font_system = FontSystem::new();
+ let swash_cache = SwashCache::new();
+ let cache = glyphon::Cache::new(&device);
+ let mut text_atlas = TextAtlas::new(&device, &queue, &cache, config.format);
+ let text_renderer = TextRenderer::new(
+ &mut text_atlas,
+ &device,
+ wgpu::MultisampleState::default(),
+ None,
+ );
+
+ let mut viewport = Viewport::new(&device, &cache);
+
+ // Initialize viewport with current resolution
+ viewport.update(
+ &queue,
+ Resolution {
+ width: size.width,
+ height: size.height,
+ },
+ );
+
+ Self {
+ surface,
+ device,
+ queue,
+ config,
+ size,
+ window,
+ line_pipeline,
+ line_list_pipeline,
+ vertex_buffer,
+ time: 0.0,
+ graphs,
+ font_system,
+ swash_cache,
+ text_atlas,
+ text_renderer,
+ viewport,
+ metrics: PerformanceMetrics::new(60, 10000), // 60 frame rolling avg, 10k frame history
+ show_metrics: true, // Show metrics by default
+ }
+ }
+
+ pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
+ if new_size.width > 0 && new_size.height > 0 {
+ self.size = new_size;
+ self.config.width = new_size.width;
+ self.config.height = new_size.height;
+ self.surface.configure(&self.device, &self.config);
+
+ // Update text viewport resolution
+ self.viewport.update(
+ &self.queue,
+ Resolution {
+ width: new_size.width,
+ height: new_size.height,
+ },
+ );
+ }
+ }
+
+ pub fn update(&mut self) {
+ self.metrics.begin_update();
+
+ self.time += 0.016; // ~60fps
+
+ // Update each graph independently
+ for (graph_idx, graph) in self.graphs.iter_mut().enumerate() {
+ graph.update(self.time, graph_idx);
+ }
+ }
+
+ pub fn toggle_metrics(&mut self) {
+ self.show_metrics = !self.show_metrics;
+ println!("Metrics display: {}", if self.show_metrics { "ON" } else { "OFF" });
+ }
+
+ pub fn export_metrics(&self, path: &str) -> std::io::Result<()> {
+ self.metrics.export_to_csv(path)
+ }
+
+ pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
+ self.metrics.begin_frame();
+
+ // End update timing from previous update() call
+ let update_ms = self.metrics.end_update();
+
+ self.metrics.begin_render();
+
+ let output = self.surface.get_current_texture()?;
+ let view = output
+ .texture
+ .create_view(&wgpu::TextureViewDescriptor::default());
+
+ let mut encoder = self
+ .device
+ .create_command_encoder(&wgpu::CommandEncoderDescriptor {
+ label: Some("Render Encoder"),
+ });
+
+ // Collect all vertex data for all graphs
+ struct DrawData {
+ viewport: SubView,
+ border_offset: usize,
+ border_count: usize,
+ grid_offset: usize,
+ grid_count: usize,
+ show_grid: bool,
+ lines_offset: usize,
+ lines_count: usize,
+ num_lines: usize,
+ }
+
+ let mut all_vertices = Vec::new();
+ let mut draw_data = Vec::new();
+ let mut total_line_count = 0;
+
+ for graph in &self.graphs {
+ total_line_count += graph.lines.len();
+ let border_vertices = graph.generate_border();
+ let border_offset = all_vertices.len();
+ all_vertices.extend_from_slice(&border_vertices);
+ let border_count = border_vertices.len();
+
+ let grid_offset = all_vertices.len();
+ let grid_vertices = graph.generate_grid_lines();
+ all_vertices.extend_from_slice(&grid_vertices);
+ let grid_count = grid_vertices.len();
+
+ let lines_offset = all_vertices.len();
+ let mut line_vertices = Vec::new();
+ for line in &graph.lines {
+ line_vertices.extend_from_slice(line);
+ }
+ all_vertices.extend_from_slice(&line_vertices);
+ let lines_count = line_vertices.len();
+
+ draw_data.push(DrawData {
+ viewport: graph.viewport.clone(),
+ border_offset,
+ border_count,
+ grid_offset,
+ grid_count,
+ show_grid: graph.show_grid,
+ lines_offset,
+ lines_count,
+ num_lines: graph.lines.len(),
+ });
+ }
+
+ // Write all vertices at once
+ if !all_vertices.is_empty() {
+ self.queue.write_buffer(
+ &self.vertex_buffer,
+ 0,
+ bytemuck::cast_slice(&all_vertices),
+ );
+ }
+
+ {
+ let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: Some("Render Pass"),
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
+ view: &view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Clear(wgpu::Color {
+ r: 0.1,
+ g: 0.1,
+ b: 0.15,
+ a: 1.0,
+ }),
+ store: wgpu::StoreOp::Store,
+ },
+ })],
+ depth_stencil_attachment: None,
+ occlusion_query_set: None,
+ timestamp_writes: None,
+ });
+
+ // Render each graph view
+ for data in &draw_data {
+ // Set viewport for this graph
+ render_pass.set_viewport(
+ data.viewport.x * self.size.width as f32,
+ data.viewport.y * self.size.height as f32,
+ data.viewport.width * self.size.width as f32,
+ data.viewport.height * self.size.height as f32,
+ 0.0,
+ 1.0,
+ );
+
+ render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
+
+ // Draw border
+ render_pass.set_pipeline(&self.line_list_pipeline);
+ render_pass.draw(
+ data.border_offset as u32..(data.border_offset + data.border_count) as u32,
+ 0..1,
+ );
+
+ // Draw grid if enabled
+ if data.show_grid {
+ render_pass.set_pipeline(&self.line_list_pipeline);
+ render_pass.draw(
+ data.grid_offset as u32..(data.grid_offset + data.grid_count) as u32,
+ 0..1,
+ );
+ }
+
+ // Draw waterfall lines
+ if data.lines_count > 0 {
+ render_pass.set_pipeline(&self.line_pipeline);
+ let points_per_line = 100;
+ for i in 0..data.num_lines {
+ let start = (data.lines_offset + i * points_per_line) as u32;
+ let end = start + points_per_line as u32;
+ render_pass.draw(start..end, 0..1);
+ }
+ }
+ }
+ }
+
+ // Render text (header and labels)
+ self.viewport.update(
+ &self.queue,
+ Resolution {
+ width: self.size.width,
+ height: self.size.height,
+ },
+ );
+
+ let mut text_areas = Vec::new();
+
+ // Main header
+ let mut header_buffer = Buffer::new(&mut self.font_system, Metrics::new(24.0, 32.0));
+ header_buffer.set_size(&mut self.font_system, Some(500.0), Some(40.0));
+ header_buffer.set_text(
+ &mut self.font_system,
+ "TimePlot - Waterfall Display",
+ Attrs::new().family(Family::SansSerif),
+ Shaping::Advanced,
+ );
+
+ // Performance metrics (if enabled)
+ let mut metrics_buffer = Buffer::new(&mut self.font_system, Metrics::new(11.0, 14.0));
+ if self.show_metrics {
+ let metrics_text = self.metrics.format_summary();
+ metrics_buffer.set_size(&mut self.font_system, Some(self.size.width as f32 - 520.0), Some(40.0));
+ metrics_buffer.set_text(
+ &mut self.font_system,
+ &metrics_text,
+ Attrs::new().family(Family::Monospace),
+ Shaping::Advanced,
+ );
+ }
+
+ // Graph titles and labels - create all buffers first
+ let mut graph_buffers = Vec::new();
+ let mut x_axis_buffers = Vec::new();
+ let mut y_axis_buffers = Vec::new();
+ let mut legend_buffers = Vec::new();
+
+ for graph in &self.graphs {
+ let width = graph.viewport.width * self.size.width as f32;
+ let height = graph.viewport.height * self.size.height as f32;
+
+ // Title
+ let mut title_buffer = Buffer::new(&mut self.font_system, Metrics::new(18.0, 24.0));
+ title_buffer.set_size(&mut self.font_system, Some(width), Some(30.0));
+ title_buffer.set_text(
+ &mut self.font_system,
+ &graph.title,
+ Attrs::new().family(Family::SansSerif),
+ Shaping::Advanced,
+ );
+ graph_buffers.push(title_buffer);
+
+ // X-axis label
+ let mut x_buffer = Buffer::new(&mut self.font_system, Metrics::new(14.0, 18.0));
+ x_buffer.set_size(&mut self.font_system, Some(width), Some(20.0));
+ x_buffer.set_text(
+ &mut self.font_system,
+ &graph.x_axis_label,
+ Attrs::new().family(Family::SansSerif),
+ Shaping::Advanced,
+ );
+ x_axis_buffers.push(x_buffer);
+
+ // Y-axis label
+ let mut y_buffer = Buffer::new(&mut self.font_system, Metrics::new(14.0, 18.0));
+ y_buffer.set_size(&mut self.font_system, Some(height * 0.5), Some(20.0));
+ y_buffer.set_text(
+ &mut self.font_system,
+ &graph.y_axis_label,
+ Attrs::new().family(Family::SansSerif),
+ Shaping::Advanced,
+ );
+ y_axis_buffers.push(y_buffer);
+
+ // Legend
+ let mut legend_text = String::new();
+ for (i, item) in graph.legend_items.iter().enumerate() {
+ if i > 0 { legend_text.push_str(" "); }
+ legend_text.push_str(&format!("● {}", item.label));
+ }
+ let mut legend_buffer = Buffer::new(&mut self.font_system, Metrics::new(12.0, 16.0));
+ legend_buffer.set_size(&mut self.font_system, Some(width * 0.8), Some(20.0));
+ legend_buffer.set_text(
+ &mut self.font_system,
+ &legend_text,
+ Attrs::new().family(Family::SansSerif),
+ Shaping::Advanced,
+ );
+ legend_buffers.push(legend_buffer);
+ }
+
+ // Now create text areas with references to the buffers
+ text_areas.push(TextArea {
+ buffer: &header_buffer,
+ left: 10.0,
+ top: 15.0,
+ scale: 1.0,
+ bounds: TextBounds {
+ left: 0,
+ top: 0,
+ right: 500,
+ bottom: 40,
+ },
+ default_color: TextColor::rgb(255, 255, 255),
+ custom_glyphs: &[]
+ });
+
+ // Metrics display
+ if self.show_metrics {
+ text_areas.push(TextArea {
+ buffer: &metrics_buffer,
+ left: 520.0,
+ top: 18.0,
+ scale: 1.0,
+ bounds: TextBounds {
+ left: 0,
+ top: 0,
+ right: (self.size.width as i32 - 520).max(0),
+ bottom: 40,
+ },
+ default_color: TextColor::rgb(100, 255, 100),
+ custom_glyphs: &[]
+ });
+ }
+
+ for (i, graph) in self.graphs.iter().enumerate() {
+ let x_offset = graph.viewport.x * self.size.width as f32;
+ let y_offset = graph.viewport.y * self.size.height as f32;
+ let width = graph.viewport.width * self.size.width as f32;
+ let height = graph.viewport.height * self.size.height as f32;
+
+ // Graph title
+ text_areas.push(TextArea {
+ buffer: &graph_buffers[i],
+ left: x_offset + 10.0,
+ top: y_offset + 5.0,
+ scale: 1.0,
+ bounds: TextBounds {
+ left: 0,
+ top: 0,
+ right: width as i32,
+ bottom: 30,
+ },
+ default_color: TextColor::rgb(230, 230, 230),
+ custom_glyphs: &[]
+ });
+
+ // X-axis label (bottom center)
+ text_areas.push(TextArea {
+ buffer: &x_axis_buffers[i],
+ left: x_offset + width * 0.5 - 50.0,
+ top: y_offset + height - 20.0,
+ scale: 1.0,
+ bounds: TextBounds {
+ left: 0,
+ top: 0,
+ right: 200,
+ bottom: 20,
+ },
+ default_color: TextColor::rgb(200, 200, 200),
+ custom_glyphs: &[]
+ });
+
+ // Y-axis label (left center, rotated appearance via positioning)
+ text_areas.push(TextArea {
+ buffer: &y_axis_buffers[i],
+ left: x_offset + 5.0,
+ top: y_offset + height * 0.3,
+ scale: 1.0,
+ bounds: TextBounds {
+ left: 0,
+ top: 0,
+ right: 150,
+ bottom: 20,
+ },
+ default_color: TextColor::rgb(200, 200, 200),
+ custom_glyphs: &[]
+ });
+
+ // Legend (top right)
+ text_areas.push(TextArea {
+ buffer: &legend_buffers[i],
+ left: x_offset + width * 0.3,
+ top: y_offset + 30.0,
+ scale: 1.0,
+ bounds: TextBounds {
+ left: 0,
+ top: 0,
+ right: (width * 0.7) as i32,
+ bottom: 20,
+ },
+ default_color: TextColor::rgb(220, 220, 220),
+ custom_glyphs: &[]
+ });
+ }
+
+ self.text_renderer
+ .prepare(
+ &self.device,
+ &self.queue,
+ &mut self.font_system,
+ &mut self.text_atlas,
+ &self.viewport,
+ text_areas,
+ &mut self.swash_cache,
+ )
+ .expect("Failed to prepare text");
+
+ {
+ let mut text_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: Some("Text Render Pass"),
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
+ view: &view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: wgpu::StoreOp::Store,
+ },
+ })],
+ depth_stencil_attachment: None,
+ occlusion_query_set: None,
+ timestamp_writes: None,
+ });
+
+ self.text_renderer
+ .render(&self.text_atlas, &self.viewport, &mut text_pass)
+ .expect("Failed to render text");
+ }
+
+ self.queue.submit(std::iter::once(encoder.finish()));
+ output.present();
+
+ // Finalize metrics
+ let render_ms = self.metrics.end_render();
+ let vertex_count = all_vertices.len();
+ self.metrics.end_frame(update_ms, render_ms, vertex_count, total_line_count);
+
+ Ok(())
+ }
+}
diff --git a/rs/src/shader.wgsl b/rs/src/shader.wgsl
new file mode 100644
index 0000000..6655301
--- /dev/null
+++ b/rs/src/shader.wgsl
@@ -0,0 +1,22 @@
+struct VertexInput {
+ @location(0) position: vec2<f32>,
+ @location(1) color: vec3<f32>,
+}
+
+struct VertexOutput {
+ @builtin(position) clip_position: vec4<f32>,
+ @location(0) color: vec3<f32>,
+}
+
+@vertex
+fn vs_main(in: VertexInput) -> VertexOutput {
+ var out: VertexOutput;
+ out.clip_position = vec4<f32>(in.position, 0.0, 1.0);
+ out.color = in.color;
+ return out;
+}
+
+@fragment
+fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
+ return vec4<f32>(in.color, 1.0);
+}
diff --git a/rs/src/vertex.rs b/rs/src/vertex.rs
new file mode 100644
index 0000000..8a25c30
--- /dev/null
+++ b/rs/src/vertex.rs
@@ -0,0 +1,27 @@
+#[repr(C)]
+#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
+pub struct Vertex {
+ pub position: [f32; 2],
+ pub color: [f32; 3],
+}
+
+impl Vertex {
+ pub fn desc() -> wgpu::VertexBufferLayout<'static> {
+ wgpu::VertexBufferLayout {
+ array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
+ step_mode: wgpu::VertexStepMode::Vertex,
+ attributes: &[
+ wgpu::VertexAttribute {
+ offset: 0,
+ shader_location: 0,
+ format: wgpu::VertexFormat::Float32x2,
+ },
+ wgpu::VertexAttribute {
+ offset: std::mem::size_of::<[f32; 2]>() as wgpu::BufferAddress,
+ shader_location: 1,
+ format: wgpu::VertexFormat::Float32x3,
+ },
+ ],
+ }
+ }
+}