//! Odem-rs is an Object-based Discrete-Event Modeling library for Rust,
//! enabling [Monte Carlo]–style simulation models via `async`/`await`. It
//! provides a flexible, extensible framework where concurrent agents
//! represent simulation actors.
//!
//! # Overview
//!
//! - *Process-Based*: Models simulation entities as asynchronous [agents]
//! with isolated state and [behavior], while allowing internal concurrency
//! via [jobs].
//! - *Discrete-Event*: Schedules and executes events at distinct points in
//! model time, skipping from event to event rather than at a fixed rate.
//! - *Deterministic*: Results of simulation runs are fully portable due to
//! the use of deterministic pseudo-random-number generators (PRNG) in
//! combination with cooperative concurrency. This also enables the use of
//! `!Send` closures while still allowing independent simulation runs to be
//! parallelized safely.
//! - *Adaptable*: Exposes [library traits] to tailor simulators and data
//! structures to specific simulation models.
//! - *Sound*: Validated with [Miri] to detect undefined behavior and tests
//! compliance with [stacked borrow] rules.
//! - *Batteries Included*: Provides essential components for simulation:
//! - [Executor] and event calendar for scheduling
//! - [Concurrency primitives] for internal synchronization
//! - Synchronization structures: [channels] and [control variables]
//! - PRNG [generator streams] and [random variables]
//! - Automatically garbage-collected [object pools]
//! - *Ecosystem*: Integrates seamlessly with [`tracing`], [`uom`], and
//! [`rand`] for logging, unit-of-measure modeling, and random number
//! generation.
//! - *`no_std`/`no_alloc`*: Supports execution in bare-metal environments even
//! without a memory allocator, albeit with fewer dynamic-collection-based
//! features.
//!
//! # Execution Principle
//!
//! The core of odem-rs is its *event-driven execution model*, which ensures
//! that simulation models evolve incrementally in a structured manner. At any
//! given model time, all [continuations] (representing [agents] and [jobs])
//! that are scheduled for execution are processed *instantaneously* in terms of
//! model time before the clock is advanced. Thus, the passing of model time is
//! explicit, allowing for deterministic execution.
//! The execution order is determined by:
//!
//! - *Model time*: Monotonically increasing time preserves cause-and-effect
//! relationships between processes.
//! - *Rank* (between [agents]): Determines execution priority among agents.
//! - *Precedence* (between [jobs]): Ensures the correct sequencing of dependent
//! jobs within one agent.
//! - *Insertion Order*: Resolves ties between *jobs* with equal precedence by
//! executing them in the order they were scheduled.
//!
//! Once all active continuations have been executed at a given model time,
//! the simulation time advances to the next scheduled event, skipping idle
//! periods where no actions occur.
//!
//! This execution model is managed by an [event calendar], which is a part of
//! the `async`/`await` runtime executor. The executor schedules and processes
//! continuations in deterministic order as described above. This allows odem-rs
//! to seamlessly integrate with Rust’s async runtime model, leveraging native
//! concurrency while maintaining strict event sequencing.
//!
//! # Introductory Example
//!
//! ## Barbershop Simulation
//!
//! To get you started quickly, here is an example scenario featuring a simple
//! barbershop model. Customers arrive at random intervals and request
//! service from a single barber. Once a customer arrives, they occupy the
//! barber for a random duration simulating the haircut, then release the barber
//! for the next customer. The simulation will run for 12 hours.
//!
//! ```
//! use odem_rs::{prelude::*, sync::facility::Facility};
//! use core::pin::pin;
//! use rand::RngExt;
//!
//! #[derive(Config, Default)]
//! struct Barbershop {
//! barber: Facility,
//! rng_stream: RngStream,
//! }
//!
//! struct Customer(f64);
//!
//! impl Behavior<Barbershop> for Customer {
//! type Output = ();
//!
//! async fn actions(&self, sim: &Sim<Barbershop>) {
//! // Acquire the barber
//! let chair = sim.global().barber.seize().await;
//! // Simulate the haircut duration
//! sim.advance(self.0).await;
//! // Release the barber for the next customer
//! chair.release();
//! }
//! }
//!
//! #[odem_rs::main]
//! async fn main(sim: &Sim<Barbershop>) {
//! // Process responsible for generating customers
//! sim.fork(async {
//! let mut rng_a = sim.global().rng_stream.rng();
//! let mut rng_s = sim.global().rng_stream.rng();
//! let pool = pin!(Pool::dynamic().with(Agent::new));
//!
//! loop {
//! // Wait a random time before creating the next customer
//! let arrival = rng_a.random_range(12.0..24.0);
//! let service = rng_s.random_range(12.0..18.0);
//! sim.advance(arrival).await;
//! sim.activate(pool.alloc(Customer(service)));
//! }
//! })
//! // Run the barbershop for 12 hours
//! .or(sim.advance(12.0 * 60.0))
//! .await;
//! }
//! ```
//!
//! More examples can be found in the `examples` directory.
//!
//! # Crate Organization
//!
//! Odem-rs is structured into multiple crates for modularity, which can be
//! accessed from the root crate as follows:
//!
//! | Crate Name | Description |
//! |-------------------|----------------------------------------------------------------------------------|
//! | [`odem_rs`] | Entry crate providing access to the core simulation framework. |
//! | [`odem_rs::core`] | Defines the foundational structures and traits for event-driven modeling. |
//! | [`odem_rs::sync`] | Provides synchronization and communication primitives for agent-job interaction. |
//! | [`odem_rs::util`] | Utility crate with pools, PRNG streams, statistics, and physical quantities. |
//!
//! # Feature Flags
//!
//! Odem-rs uses Cargo feature flags to control optional functionality. All
//! flags listed as "default" are enabled when you add `odem-rs` as a
//! dependency without further configuration. To start from a minimal base,
//! set `default-features = false` and enable only what you need.
//!
//! | Feature | Default | Description |
//! |-----------------|---------|-------------------------------------------------------|
//! | `std` | yes | Standard library support (implies `alloc`). |
//! | `alloc` | yes | Heap allocation for dynamic data structures. |
//! | `tracing` | yes | Structured instrumentation via the [`tracing`] crate. |
//! | `debug-tracing` | no | Debug-level trace output for internal state machines. |
//! | `uom` | yes | Type-safe SI quantities for model time. |
//! | `rand_pcg` | yes | PCG-family pseudo-random number generators. |
//! | `rand_xoshiro` | no | XoShiRo-family pseudo-random number generators. |
//! | `rayon` | yes | Parallel iteration for independent simulation runs. |
//! | `libm` | no | Software math functions for `no_std` environments. |
//!
//! ## Environment
//!
//! - **`std`**: Enables standard library support and implies `alloc`. Disable
//! this for bare-metal or WebAssembly targets that do not provide a standard
//! library.
//! - **`alloc`**: Enables heap-allocated data structures such as dynamic
//! [channels], dynamic [object pools], and per-type agent identifiers.
//! Automatically activated by `std`, but can be enabled independently on
//! targets that provide an allocator without the full standard library.
//! - **`libm`**: Provides software implementations of math functions (e.g.
//! `sqrt`) via the [`libm`](https://docs.rs/libm) crate. Only needed in
//! `no_std` environments where hardware floating-point or standard-library
//! math is unavailable. When `std` is active, math functions from the
//! standard library are used instead.
//!
//! ## Integrations
//!
//! - **`tracing`**: Integrates with the [`tracing`] ecosystem to provide
//! structured, span-based instrumentation of agents and continuations.
//! Useful for debugging simulation models and understanding execution flow.
//! - **`debug-tracing`**: Emits additional debug-level trace events for
//! finite-state machine transitions and channel operations. A `tracing`
//! subscriber must be configured for these events to be visible.
//! - **`uom`**: Enables the [`uom`] crate for modeling time with type-safe
//! SI quantities. With this feature, model time can be expressed using units
//! like `hour::new(12.0)` or `second::new(0.5)` rather than raw numeric
//! values.
//!
//! ## Random Number Generators
//!
//! The [`rand`] crate is always enabled. The following features control which
//! PRNG backends are available:
//!
//! - **`rand_pcg`**: Provides PCG-family generators (`Pcg32`, `Pcg64Dxsm`,
//! etc.) and sets the `DefaultRng` type alias to a PCG variant matching the
//! target's pointer width.
//! - **`rand_xoshiro`**: Provides XoShiRo-family generators
//! (`Xoshiro256PlusPlus`, etc.) as an alternative backend.
//!
//! ## Parallelism
//!
//! - **`rayon`**: Enables parallel iteration support via the [`rayon`] crate,
//! allowing independent simulation replications to run across multiple
//! threads.
//!
//! # Re-exported Crates
//!
//! Odem-rs re-exports its ecosystem dependencies so that simulation models can
//! use version-compatible crates without adding them as separate dependencies.
//! Each re-export is available as a module under `odem_rs::`, e.g.
//! `odem_rs::rand` or `odem_rs::uom`.
//!
//! | Crate | Version | Feature |
//! |---------------------------|---------|----------------|
//! | [`rand`] | 0.10 | *always* |
//! | [`intrusive_collections`] | 0.10 | *always* |
//! | [`uom`] | 0.38 | `uom` |
//! | [`tracing`] | 0.1 | `tracing` |
//! | [`rayon`] | 1 | `rayon` |
//! | [`typed_arena`] | 2 | `alloc` |
//! | [`rand_pcg`] | 0.10 | `rand_pcg` |
//! | [`rand_xoshiro`] | 0.8 | `rand_xoshiro` |
//!
//! This means you can depend on `odem-rs` alone and use its re-exports:
//!
//! ```
//! use odem_rs::rand; // rand 0.10
//! use odem_rs::uom; // uom 0.38 (requires feature "uom")
//! use odem_rs::rayon; // rayon 1 (requires feature "rayon")
//! ```
//!
//! If you need additional items from these crates (e.g. `rand_distr`), add
//! them to your `Cargo.toml` with a compatible version to avoid duplication:
//!
//! ```toml
//! [dependencies]
//! odem-rs = "0.3"
//! rand_distr = "0.6" # compatible with rand 0.10
//! ```
//!
//! # Contributors & Acknowledgments
//!
//! Inspired by the Scandinavian approach to discrete-event simulation as
//! exemplified - among others - through [Simula], [GPSS], [SLX], [ODEMx],
//! odem-rs refines these concepts in a Rust-centric framework.
//!
//! Odem-rs is part of ongoing doctoral research and has benefited from
//! contributions by:
//!
//! - **Lukas Markeffsky**, with whom I enjoyed in-depth discussions on Rust’s
//! type system and whose incredible insight and sharp mind helped a lot to
//! find and resolve soundness issues in addition to improving the ergonomics
//! of the library.
//! - **Paula Wiesner**, with whom I performed early prototyping of agent-based
//! approaches and who is still interested in the progress of this project,
//! despite having successfully moved past academia. I appreciate the
//! enthusiasm!
//!
//! Explore the modules and traits to uncover the library’s full potential.
//!
//! [Monte Carlo]: https://en.wikipedia.org/wiki/Monte_Carlo_method
//! [Simula]: https://twobithistory.org/2019/01/31/simula.html
//! [GPSS]: https://en.wikipedia.org/wiki/GPSS
//! [SLX]: https://informs-sim.org/wsc00papers/027.PDF
//! [ODEMx]: https://edoc.hu-berlin.de/server/api/core/bitstreams/92cdf38e-1110-4ba7-88f1-8d17bc8485b4/content
//!
//! [agents]: odem_rs_core::agent
//! [behavior]: odem_rs_core::agent::Behavior
//! [jobs]: odem_rs_core::job
//! [continuations]: odem_rs_core::continuation
//! [library traits]: odem_rs_core::config
//! [concurrency primitives]: odem_rs_sync::fork
//! [executor]: odem_rs_core::simulator
//! [event calendar]: odem_rs_core::DefaultPlan
//! [channels]: odem_rs_sync::channel
//! [control variables]: odem_rs_sync::control
//! [generator streams]: odem_rs_util::random
//! [random variables]: odem_rs_util::random_variable
//! [object pools]: mod@odem_rs_util::pool
//! [Miri]: https://github.com/rust-lang/miri
//! [stacked borrow]: https://plv.mpi-sws.org/rustbelt/stacked-borrows/paper.pdf
//!
//! [`tracing`]: https://docs.rs/tracing/0.1
//! [`uom`]: https://docs.rs/uom/0.38
//! [`rand`]: https://docs.rs/rand/0.10
//! [`intrusive_collections`]: https://docs.rs/intrusive-collections/0.10
//! [`rayon`]: https://docs.rs/rayon/1
//! [`typed_arena`]: https://docs.rs/typed-arena/2
//! [`rand_pcg`]: https://docs.rs/rand_pcg/0.10
//! [`rand_xoshiro`]: https://docs.rs/rand_xoshiro/0.8
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(
html_logo_url = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxjaXJjbGUgY3k9IjE5Ny41IiBjeD0iMjAwLjUiIHN0cm9rZT0iIzAwMCIgZmlsbD0iI2ZmZiIgcj0iMTUyLjUiLz48cGF0aCBkPSJNMTkxLjI0NyAzLjYyNmMtMTAuMDIuNjEtMTAuMDg1LjcxLTEyLjgzOSAxOS40NzYtMS41NDEgMTAuNDk2LTIuMTE2IDExLjU2Ni02LjczMiAxMi41MjMtMTIuNzIyIDIuNjM3LTIwLjg2MyA0Ljg0OS0yOS45ODcgOC4xNDgtMTEuNDUyIDQuMTQtMTkuOTcyIDguMjA5LTMwLjU3IDE0LjU5OS03LjIxMyA0LjM0OS01LjgzOCA0Ljc5Ny0xOC45MDgtNi4xNTgtOS4wODQtNy42MTMtMTAuMDA3LTguMDc3LTEzLjkxNi02Ljk5Mi00LjMyNSAxLjIwMS0yMi42NzUgMTguNDU5LTI1LjAwMyAyMy41MTUtMS43MjUgMy43NDQtMS40MTcgNC40MjggNy4xNDEgMTUuODYzIDguMjQzIDExLjAxNSA4LjEwMSAxMC42MjMgNS4yMzkgMTQuNDEtMTQuMzY2IDE5LjAwNy0yNS4zNjYgNDMuNjAzLTMwLjA2NiA2Ny4yMjUtMS42MDggOC4wODQuNjI1IDYuOTI2LTIxLjEwOCAxMC45NDdDMy44MTIgMTc5LjE1OCAzLjgxNiAxNzkuMTUyIDMuODMzIDE5OGMuMDIgMjAuNDcxLTIuMDg1IDE4LjQ4MyAyMy45NjcgMjIuNjQ0IDYuNDggMS4wMzUgNi40NDMuOTkyIDcuODI1IDkuMTIgMy45OTMgMjMuNDcgMTQuMTU0IDQ4LjEwMiAyNy40ODMgNjYuNjIyIDQuMDk1IDUuNjkgNC43MzcgNy4xNzQgMy44NTMgOC45MDUtLjgyNCAxLjYxMy01LjY1NSA4LjY2Ni05Ljg0NCAxNC4zNzMtNS4xMTkgNi45NzQtNS43NjYgOS41OTItMy4yNjUgMTMuMjIgMS43NjYgMi41NjMgMTMuMDg4IDEzLjc3NiAxNy4zODQgMTcuMjE3IDkuMTcxIDcuMzQ2IDkuNTAxIDcuMjk3IDIyLjU2NC0zLjM0MiAxMS43NDQtOS41NjQgMTAuMzExLTkuMTk4IDE3Ljk4OC00LjU5MiAxNy4wNzQgMTAuMjQ0IDM1LjYzNyAxNy4yOTIgNTcuNTU0IDIxLjg1MiA3LjAyNSAxLjQ2MSA3LjAyMSAxLjQ1MyA5LjY1OSAxNi4wMzEgMi4zMjMgMTIuODM0IDMuMDI0IDE0LjQzNyA2Ljc5OSAxNS41NDIgMi4yMzUuNjU0IDE5Ljg0Ny45OTggMjQuODc0LjQ4NSA3LjgwNS0uNzk2IDcuODU4LS44NzIgMTAuNzMtMTUuNDQyIDIuOTc4LTE1LjExIDIuOTYzLTE1LjA4NyAxMC43MTYtMTYuNjEyIDE5LjMwNC0zLjc5OSAzOC4xNDctMTAuODMzIDU2Ljg3NS0yMS4yMjkgMy45NTgtMi4xOTcgNy41MDEtMy45OTQgNy44NzUtMy45OTQgMS4wMDIgMCA0LjY0OSAyLjcxNCAxMi4wOTEgOSAxMi4xMzggMTAuMjUzIDEzLjU0NiAxMC4wMjEgMjguNjAyLTQuNzIzIDEyLjQ4My0xMi4yMjUgMTMuMDA4LTE0LjE3OSA2LjI1Mi0yMy4yNzctMTEuODQyLTE1Ljk0Ny0xMS42MzMtMTUuNDY0LTguNTk0LTE5Ljg3IDE3LjQwMy0yNS4yMzMgMjUuNjY1LTQ0Ljk3MSAzMC41NTYtNzIuOTkzLjk3MS01LjU2Mi40MzgtNS4zMTUgMTcuMjIzLTcuOTgzIDkuNzk3LTEuNTU3IDExLjMyMi0yLjA3IDEyLjQwOC00LjE3IDIuMTMyLTQuMTIzIDIuMzctMjguMTEzLjMyOS0zMy4yMjMtLjk4NS0yLjQ2Ni0yLjE1Ny0yLjk4OC0xMC4xOTQtNC41MzktMjEuMDU3LTQuMDY1LTE4LjU5Ni0yLjU2OS0yMC43NTEtMTIuNjIyLTQuNzIzLTIyLjAyNy0xMy43NDEtNDIuNTUzLTI2Ljg4OC02MS4yLTYuMDA3LTguNTE5LTYuMDgxLTcuNjA5IDEuMzg0LTE3LjA1NyA4LjczMy0xMS4wNTQgOS42MzMtMTIuNzIyIDguNzEyLTE2LjE0Mi0xLjMyOS00LjkzOC0yMC44Mi0yMy40ODgtMjYuMDY3LTI0LjgwOS0zLjYzOC0uOTE2LTQuNDY4LS40MjgtMTUuNDc4IDkuMTEzLTkuODgyIDguNTYyLTkuMjA5IDguMzUzLTE1LjAxNSA0LjY2Ni0xNS44NDEtMTAuMDYtMzcuMDE4LTE4LjMyMy01OC43NDktMjIuOTI1LTguNzQ1LTEuODUxLTcuNjU2LjE4OS0xMi4wNDgtMjIuNTYxLTEuNDEyLTcuMzE1LTIuNDg2LTguOC02Ljg0OC05LjQ2My0zLjcxNy0uNTY1LTE2LjE3Ni0uNzg0LTIyLjU0OC0uMzk2TTIwOS40IDU1LjIxMWM5Ni4xMTQgNi4zODEgMTU5LjYzMSA5OS42NDIgMTI5LjY2NyAxOTAuMzg5LTMzLjk1NCAxMDIuODMzLTE2NC42NzcgMTMzLjQ1LTI0MS42OTIgNTYuNjA3LTQyLjMzNS00Mi4yNDEtNTQuNTAzLTk5LjE0Mi0zMy4yMzYtMTU1LjQyOSAyMS4yMy01Ni4xODYgODMuODI3LTk1LjY0NiAxNDUuMjYxLTkxLjU2N20tMjIuNiAxMC41ODdjLTI0LjcyNiAyLjI5My00NS4zMzEgMTAuODExLTU1LjI4MSAyMi44NTFsLTEuNjEzIDEuOTUxIDcwLjE0Ny4yIDcwLjI5MS4xMjNjLjg5Ni0uNDgtNy4xOTctNy44MjMtMTIuNTQ0LTExLjM3OS0xNi40NDctMTAuOTQtNDMuOTE3LTE2LjI1OC03MS0xMy43NDZtOTUuNjMxIDI4LjU2OGMzLjc5NCAxMS43OTYgNC4wOTMgMjYuNTc2Ljc1OCAzNy4zNzQtMS4wNTQgMy40MTUtMS43MzUgMy4yNjIgNi4yMDggMS4zOWw2Ljc5OC0xLjYwMiAxLjEzNCAxLjMzNmMzLjIgMy43NyAxMS4wNzEgMTcuNDkzIDExLjA3MSAxOS4zMDIgMCAuNzUyLTQuNDUgNC44NDgtMTQuNiAxMy40NDFsLTExLjA3MiA5LjUxM2MtMS42NTMgMS41NTktMi40ODkgMS41MDQtMi45MDEtLjE4OC0uNTI4LTIuMTcyLTUuMzgxLTExLjU2Mi03Ljk5NC0xNS40NjctMy4xMzUtNC42ODUtMy4wNDktMy41MDItLjY1Ni05LjA2NSA1LjMzMS0xMi4zOSA3LjU4NC0zMS44NjYgNS4zMjMtNDZsLS43MzYtNC42LTkuNTE1LjA2NmMtMTAuNDU2LjA3Mi0xMC4yOTIuMDQ0LTkuMTExIDEuNTQ2IDMuOTIzIDQuOTg4IDUuNTYzIDIwLjA2MyAzLjM0MSAzMC43MDQtMy43MzQgMTcuODcxLTEyLjk3MSAzMS41MjEtMzIuMTM2IDQ3LjQ4OC0xMy41MTIgMTEuMjU2LTE1LjkgMTQuNTU2LTE1LjkzMyAyMi4wMTItLjAzMSA3LjAzNSAyLjMxIDEwLjUzNiAxMy4xOSAxOS43MjkgMTUuMzEgMTIuOTM0IDIzLjEwOCAyMS45NDQgMjguODYxIDMzLjM0MiA3LjY1NiAxNS4xNzEgOS4yMDkgMzMuOTUxIDMuNzMzIDQ1LjE2OS0uNzY3IDEuNTctMS4zOTQgMi45NjUtMS4zOTQgMy4xczQuMTQ0LjI0NCA5LjIxLjI0NGg5LjIxbC4zNTUtLjkzNWMxLjI0MS0zLjI2MyAyLjIzMi0xOC4wMjQgMS42NTItMjQuNjA1LS45OTQtMTEuMjk0LTIuOTUtMTguODYzLTcuMzkxLTI4LjYwOGwtMS40MS0zLjA5NSAyLjQ0Ny0zLjYzNGMyLjg3My00LjI2NiA2LjUwNy0xMS40NDcgOC4zNjItMTYuNTIzLjcyMy0xLjk4IDEuNDQ2LTMuNzU2IDEuNjA2LTMuOTQ2czIuMTUxIDEuMzQ4IDQuNDI1IDMuNDE3YTQ0NyA0NDcgMCAwIDAgOC41MzQgNy41MjdjNy4wOTMgNi4wNjggMTIuNjM1IDExLjI3MyAxMy42NzIgMTIuODM5bC45NjUgMS40NTgtMi41NDYgNS4zNTNjLTIuNzczIDUuODI2LTYuNTU3IDEyLjMxLTguMjAyIDE0LjA1Mi0xLjMzMyAxLjQxMi0xLjUyOSAxLjQwMS05LjA3Ny0uNDk3LTcuMzg2LTEuODU3LTYuODI4LTEuOTU2LTUuOCAxLjAzMSAzLjM1MyA5Ljc0NCAzLjY5OSAyNy4xMTguNzU5IDM4LjA5NC0xLjMwNSA0Ljg3NS0uOTk0IDQuNzE1IDkuMTY1LTQuNyA2Mi45OTQtNTguMzc4IDU5LjMwMy0xNTUuNTQ1LTcuODc3LTIwNy4zNTktMy43OC0yLjkxNS0zLjc4Mi0yLjkxNC0yLjQyOCAxLjI5N00xMTUuNCA5My4wNDRjLTMuMTQ1IDIuMzU1LTguMTQ4IDYuOS0xMy42IDEyLjM1Ni01NS44MTEgNTUuODUtNTAuNSAxNTAuODAyIDExLjEyMyAxOTguODMxIDQuNTE2IDMuNTIgNC42MDMgMy41MjEgMy41MzUuMDY0LTMuMjg0LTEwLjYzNS0zLjIwNS0yNS42MjUuMTk0LTM2LjM4MiAxLjI0LTMuOTI2IDEuOTA2LTMuNzE3LTUuNzQzLTEuNzk5LTcuMzk3IDEuODU1LTYuODIyIDEuOTU4LTkuNDk1LTEuNzA3LTEuNzM2LTIuMzgtNy4wNTItMTIuMDAyLTguMjEtMTQuODYyLTEuNDkyLTMuNjgyLTIuNjM3LTIuMzMgMTYuMzMtMTkuMjg2bDYuMzY0LTUuNzI1YzMuMjE3LTIuOTExIDQuMTAyLTMuMjgyIDQuMTAyLTEuNzIxIDAgMi4yNTEgNC41NTEgMTEuNTUzIDguOTg1IDE4LjM2M2wyLjYyNSA0LjAzMy0xLjk5NiA0LjA5NWMtNi43MzUgMTMuODE5LTkuNDggMzQuOTQ2LTYuNTExIDUwLjA5NmwuNzA2IDMuNiA5LjE4Ny4xMDhjMTEuMDMuMTI5IDEwLjUzMS4yNTggOC44MjgtMi4yNzMtNS4xMTctNy42MDMtNS41OTktMjIuNjc4LTEuMTUyLTM2LjAzIDUuMTY3LTE1LjUxNSAxNS4zNjQtMjguOTI4IDMzLjQxLTQzLjk1MSA5LjAxNy03LjUwNiAxMS4zNjctMTAuNTM2IDEyLjYwOC0xNi4yNTQgMS43MjYtNy45NTYtLjk2OC0xMi44OTQtMTEuODItMjEuNjY1LTI0Ljk5NS0yMC4yMDItMzUuMTc3LTM1Ljk3Mi0zNi45NTUtNTcuMjM2LS44NjQtMTAuMzM4LjI2Ni0xNy41MjQgMy42NTgtMjMuMjYuOTEyLTEuNTQzIDEuMTQyLTIuMjQ0LjgwMi0yLjQ1NC0uNzI0LS40NDgtMTguMTMuMDQ2LTE4LjQzNC41MjItLjU1Ni44NzMtMS41MjkgOC43ODgtMS43ODEgMTQuNDkzLS41OTQgMTMuMzkyIDIuMDIxIDI3LjQ3IDcuMDIyIDM3LjgxMy44NzggMS44MTQgMS40ODIgMy40OTkgMS4zNDQgMy43NDNzLTEuMTkgMS44ODQtMi4zMzYgMy42NDRjLTIuODk1IDQuNDQ1LTYuMTUgMTAuOTktNy45MjcgMTUuOTMzLS4yOTguODMxLS45NjcuMzg1LTUuNjkxLTMuNzg4LTEuMzM1LTEuMTgtNC41NjgtMy45NDUtNy4xODYtNi4xNDUtMTAuNzcyLTkuMDU1LTE0Ljk4Ni0xMy4xMDMtMTQuOTg2LTE0LjM5NCAwLTIuMTg5IDcuMzY5LTE1LjEzMiAxMC41MzYtMTguNTA2IDEuNTI2LTEuNjI1IDIuMTY5LTEuNjM0IDguNjYxLS4xMjQgNS44NTcgMS4zNjIgNS40MDIgMS41MDcgNC42MzEtMS40Ny0zLjIzMy0xMi40NzUtMi44ODgtMjUuNTA2Ljk4My0zNy4xMzkgMS4xNTMtMy40NjQuOTc4LTMuNjExLTEuODExLTEuNTIzbTM4LjMyOSA3Ljc4NGMtNC45MTkgMi40MzUtOC45MTggMTAuMTcxLTYuNTUgMTIuNjcybC44NTIuOWgxMDMuNTUxbC42ODItMS4wNDJjMS42Ni0yLjUzMy0xLjI3MS04LjU3NS01LjYwNS0xMS41NTRsLTIuMzM0LTEuNjA0LTM5LjM2Mi0uMTA2Yy0yMS42NS0uMDU4LTM5LjM2My0uMDM0LTM5LjM2My4wNTVzLjI2OS42NzUuNTk4IDEuMzA1YzEuNzQ2IDMuMzUtLjUwNyA2Ljk0Ni00LjM1MyA2Ljk0Ni0zLjQ4NiAwLTUuODE2LTMuNTQ3LTQuNTExLTYuODY4bC42MDItMS41MzJoLTEuMjY4Yy0uNjk3IDAtMi4wMi4zNzMtMi45MzkuODI4bTQyLjA3MSAyNS40MjNjLTE2LjMxMSAyLjM4Mi0zMS40MDkgNy42MjgtNDEuMSAxNC4yODEtNC4wNzMgMi43OTYtMy44ODcgMi4yNzItMi4wMzQgNS43MzEgNC43NTkgOC44ODEgMTIuMjMzIDE3LjA3NyAyNC45MyAyNy4zMzcgMTAuNTMxIDguNTA5IDEyLjc4MSAxMC45ODIgMTUuODUyIDE3LjQxOSAzLjIzOSA2Ljc5IDMuMTUyIDUuODIgMy4xNTIgMzUuMTgxdjI2bC0uOTMxIDEuODkxYy0uNTEzIDEuMDQtMS44MDMgMi42NzUtMi44NjggMy42MzItMS43NzggMS41OTgtMy4xMjYgMi4yODctMTAuNDAxIDUuMzEyLTE5Ljc3MiA4LjIyMi0zMS45OTEgMTYuMTM2LTM1LjIyMyAyMi44MTMtMi40ODEgNS4xMjUuMzcyIDEzLjE3OCA1Ljc5NSAxNi4zNTZsMS43MjEgMS4wMDkgNDUuMTU0LS4xMDZMMjQ1IDMwM2wxLjgzNy0xLjA4YzQuNzM5LTIuNzg2IDcuMjQzLTkuNjExIDUuMzkyLTE0LjY5NS0yLjMxOC02LjM2Ni0xMi4xMDktMTMuMjM1LTMxLjIyOS0yMS45MS0xMy43OTYtNi4yNTktMTUuMjg2LTcuMjExLTE3LjMxNi0xMS4wNkwyMDIuNiAyNTIuMnYtMjUuOGMwLTM2LjUxLjI2Ni0zNy4yNTkgMTguNjU4LTUyLjYwMSAxNy4yMzktMTQuMzc5IDMwLjM0Mi0zMC40NjUgMzAuMzQyLTM3LjI0OCAwLTIuMTk2LTEzLjk4MS03LjA2Mi0yNi40LTkuMTg5LTUuOTc5LTEuMDIzLTI1LjA2LTEuNzQ1LTI5LjQtMS4xMTFtLjQgMy4xNzJjLS4yMi4wODktMS45OTguNjItMy45NTEgMS4xODItOC41MjggMi40NTItMjMuNTEgMTAuMDkzLTI0LjQxNSAxMi40NTEtLjEzOS4zNjEuODg0IDIuMTYgMi41NjQgNC41MTQgNC4yNjYgNS45NzYgNC45NjggOC43MTYgMi42MjYgMTAuMjUxLTEuMzA0Ljg1NC0yLjUzNi40NDMtNC45MjEtMS42NDMtMS43ODEtMS41NTgtNi4xMDMtNi44NzktNi4xMDMtNy41MTMgMC0uMTMxLS43Mi0xLjM1Mi0xLjYtMi43MTQtMi4wMTktMy4xMjMtMi4xMDctMi43NyAxLjMtNS4xOTIgNS4zMjUtMy43ODcgMTIuMDg3LTYuNTU4IDIyLjM3Mi05LjE3IDYuMDg4LTEuNTQ2IDE0LjE5My0yLjk5MyAxMi4xMjgtMi4xNjZtLTUuMjI3IDE2LjIzOGMxLjgxOS44MjggMS42NSAzLjU2LS4yNTcgNC4xNjYtMi4xNjUuNjg3LTMuNzA1LTIuNjg5LTEuODI3LTQuMDA0IDEuMDYtLjc0My44NDctLjcyNiAyLjA4NC0uMTYybS05LjA1MyAxNS4yMTljLjY2NC42NjQuNjAzIDIuOTItLjA5NiAzLjUtLjk0MS43ODEtMi43MzEuMzQxLTMuMzg4LS44MzQtMS4xNDYtMi4wNTEgMS44MjUtNC4zMjUgMy40ODQtMi42NjZtNzkuODggMTQuNDJjNy40MDYgMTYuMTc1IDcuMTkzIDM1LjU2Ny0uNTczIDUyLjEzOS0xLjg0MSAzLjkyOC0xLjY5NSAzLjkyOS01LjIyNy0uMDUzLTMuMDE3LTMuNDAzLTExLjcwMS0xMS41Mi0xOC42LTE3LjM4Ni01LjkxOS01LjAzMy04LjYtNy42MTQtOC42LTguMjc4IDAtLjI4IDEuOTI5LTIuMDg3IDQuMjg3LTQuMDE1IDEwLjI3NS04LjQwNiAyMC42ODEtMTguMzU2IDI0LjQ4LTIzLjQwNyAyLjIzNC0yLjk3MiAyLjQzNi0yLjkyNCA0LjIzMyAxbS0xMTguNy40YzQuMjk5IDUuMDkxIDEyLjQwNyAxMi44NjkgMTkuOSAxOS4wODkgMy43NCAzLjEwNCA3LjA2MSA2LjAxOCA3LjM4IDYuNDc1LjY4Ni45ODIgMS41NDguMTIxLTExLjM5MiAxMS4zOS04LjAzMyA2Ljk5Ny0xMy4wNTIgMTEuODI0LTE2LjUxNCAxNS44OC0xLjYyMiAxLjkwMS0xLjc4OCAxLjc4Ny00LjA1NC0yLjc4Ny03LjM3NC0xNC44ODEtNy40NTItMzQuMTA2LS4yMDEtNDkuNjQ3IDIuMDctNC40MzcgMS41MTItNC4zOTEgNC44ODEtLjRtLTI0LjQ0MSA2LjAwOGMtMi4yMTMgOC44MTktMi41OTkgMjMuMDA0LS44ODggMzIuNjkyLjI5MSAxLjY1LjQ4NyAzLjA1LjQzNSAzLjExMS0uMzAzLjM1Ni0zMy40MzYtNC44MzgtMzUuMjQxLTUuNTI0LTIuMTk4LS44MzYtMi43OTYtMjIuNzcyLS42NzYtMjQuODI2LjI5Ni0uMjg4IDIuNzY3LS43NjUgMTguMzExLTMuNTM1IDE4LjE0Ni0zLjIzNCAxOC4zOTYtMy4yNiAxOC4wNTktMS45MThtMTY2LjUwMS0uNTE2YzEuMTM4LjIxNiA2LjA2OCAxLjAzMSAxMC45NTUgMS44MTEgOC41MjMgMS4zNjEgMTcuNjk0IDMuMDU0IDIwLjcxNSAzLjgyNSAzLjg0Ni45ODIgMy43NDEgMjQuNjkzLS4xMTIgMjUuMzU2LTEyLjY1OCAyLjE3OS0zNC4zODggNS40MjItMzQuNjczIDUuMTc0LS4wODUtLjA3My4xNTMtMS45NzkuNTI5LTQuMjMzIDEuNzQyLTEwLjQ1OCAxLjM5LTIzLjk1Ni0uODI2LTMxLjYyNS0uMjM5LS44MjcuMzc5LS44ODMgMy40MTItLjMwOE0yMDQgMjY0YzAgLjIyLS40MTkuNC0uOTMuNC0yLjExMyAwLTkuNjM2IDIuNjI0LTE0Ljk1NiA1LjIxNi0xMy43NjEgNi43MDctMjEuNDg1IDEzLjY3MS0yNi4yNjMgMjMuNjgxLTIuNTA0IDUuMjQ3LTYuNDA2IDUuOTAzLTguNjc0IDEuNDU4LTQuMDM4LTcuOTE1IDkuMjQ0LTIwLjA3IDMwLjAyMy0yNy40NzcgMy40ODItMS4yNDEgMTIuMjA3LTIuOTY0IDE2LjU4OS0zLjI3NWw0LjExMS0uMzQ0Yy4wNTUtLjAzMi4xLjEyMS4xLjM0MW0tMTIuNCAyMi40YzEuNzMzIDEuNzMzLjM1MiA1LjItMi4wNzIgNS4yLTEuMTU3IDAtMi43MjgtMS43ODktMi43MjgtMy4xMDYgMC0yLjQ4NCAzLjA3MS0zLjgyMyA0LjgtMi4wOTRtLTE3LjgyOSAzLjQyOWMxLjgwOSAxLjgwOC0uNjggNC41OTctMi45OTcgMy4zNTctLjg4Ny0uNDc1LTEuMDc2LTIuNzI0LS4yOTQtMy41MDYuNjgtLjY4IDIuNTQ4LS41OTUgMy4yOTEuMTQ5TTEzMi44IDMxNC44NWMyNC4xNSAyMi42NCA4NC42ODkgMjcuNDMyIDEyMC40MjEgOS41MzQgNS40NDUtMi43MjggMTQuOTExLTkuNTg4IDE1Ljk3Ni0xMS41NzlsLjQzMS0uODA1LTY5LjkxNC4wMTktNjkuOTE0LjAxOXoiIGZpbGw9IiMxNzMyNDEiLz48L3N2Zz4=",
html_favicon_url = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxjaXJjbGUgY3k9IjE5Ny41IiBjeD0iMjAwLjUiIHN0cm9rZT0iIzAwMCIgZmlsbD0iI2ZmZiIgcj0iMTUyLjUiLz48cGF0aCBkPSJNMTkxLjI0NyAzLjYyNmMtMTAuMDIuNjEtMTAuMDg1LjcxLTEyLjgzOSAxOS40NzYtMS41NDEgMTAuNDk2LTIuMTE2IDExLjU2Ni02LjczMiAxMi41MjMtMTIuNzIyIDIuNjM3LTIwLjg2MyA0Ljg0OS0yOS45ODcgOC4xNDgtMTEuNDUyIDQuMTQtMTkuOTcyIDguMjA5LTMwLjU3IDE0LjU5OS03LjIxMyA0LjM0OS01LjgzOCA0Ljc5Ny0xOC45MDgtNi4xNTgtOS4wODQtNy42MTMtMTAuMDA3LTguMDc3LTEzLjkxNi02Ljk5Mi00LjMyNSAxLjIwMS0yMi42NzUgMTguNDU5LTI1LjAwMyAyMy41MTUtMS43MjUgMy43NDQtMS40MTcgNC40MjggNy4xNDEgMTUuODYzIDguMjQzIDExLjAxNSA4LjEwMSAxMC42MjMgNS4yMzkgMTQuNDEtMTQuMzY2IDE5LjAwNy0yNS4zNjYgNDMuNjAzLTMwLjA2NiA2Ny4yMjUtMS42MDggOC4wODQuNjI1IDYuOTI2LTIxLjEwOCAxMC45NDdDMy44MTIgMTc5LjE1OCAzLjgxNiAxNzkuMTUyIDMuODMzIDE5OGMuMDIgMjAuNDcxLTIuMDg1IDE4LjQ4MyAyMy45NjcgMjIuNjQ0IDYuNDggMS4wMzUgNi40NDMuOTkyIDcuODI1IDkuMTIgMy45OTMgMjMuNDcgMTQuMTU0IDQ4LjEwMiAyNy40ODMgNjYuNjIyIDQuMDk1IDUuNjkgNC43MzcgNy4xNzQgMy44NTMgOC45MDUtLjgyNCAxLjYxMy01LjY1NSA4LjY2Ni05Ljg0NCAxNC4zNzMtNS4xMTkgNi45NzQtNS43NjYgOS41OTItMy4yNjUgMTMuMjIgMS43NjYgMi41NjMgMTMuMDg4IDEzLjc3NiAxNy4zODQgMTcuMjE3IDkuMTcxIDcuMzQ2IDkuNTAxIDcuMjk3IDIyLjU2NC0zLjM0MiAxMS43NDQtOS41NjQgMTAuMzExLTkuMTk4IDE3Ljk4OC00LjU5MiAxNy4wNzQgMTAuMjQ0IDM1LjYzNyAxNy4yOTIgNTcuNTU0IDIxLjg1MiA3LjAyNSAxLjQ2MSA3LjAyMSAxLjQ1MyA5LjY1OSAxNi4wMzEgMi4zMjMgMTIuODM0IDMuMDI0IDE0LjQzNyA2Ljc5OSAxNS41NDIgMi4yMzUuNjU0IDE5Ljg0Ny45OTggMjQuODc0LjQ4NSA3LjgwNS0uNzk2IDcuODU4LS44NzIgMTAuNzMtMTUuNDQyIDIuOTc4LTE1LjExIDIuOTYzLTE1LjA4NyAxMC43MTYtMTYuNjEyIDE5LjMwNC0zLjc5OSAzOC4xNDctMTAuODMzIDU2Ljg3NS0yMS4yMjkgMy45NTgtMi4xOTcgNy41MDEtMy45OTQgNy44NzUtMy45OTQgMS4wMDIgMCA0LjY0OSAyLjcxNCAxMi4wOTEgOSAxMi4xMzggMTAuMjUzIDEzLjU0NiAxMC4wMjEgMjguNjAyLTQuNzIzIDEyLjQ4My0xMi4yMjUgMTMuMDA4LTE0LjE3OSA2LjI1Mi0yMy4yNzctMTEuODQyLTE1Ljk0Ny0xMS42MzMtMTUuNDY0LTguNTk0LTE5Ljg3IDE3LjQwMy0yNS4yMzMgMjUuNjY1LTQ0Ljk3MSAzMC41NTYtNzIuOTkzLjk3MS01LjU2Mi40MzgtNS4zMTUgMTcuMjIzLTcuOTgzIDkuNzk3LTEuNTU3IDExLjMyMi0yLjA3IDEyLjQwOC00LjE3IDIuMTMyLTQuMTIzIDIuMzctMjguMTEzLjMyOS0zMy4yMjMtLjk4NS0yLjQ2Ni0yLjE1Ny0yLjk4OC0xMC4xOTQtNC41MzktMjEuMDU3LTQuMDY1LTE4LjU5Ni0yLjU2OS0yMC43NTEtMTIuNjIyLTQuNzIzLTIyLjAyNy0xMy43NDEtNDIuNTUzLTI2Ljg4OC02MS4yLTYuMDA3LTguNTE5LTYuMDgxLTcuNjA5IDEuMzg0LTE3LjA1NyA4LjczMy0xMS4wNTQgOS42MzMtMTIuNzIyIDguNzEyLTE2LjE0Mi0xLjMyOS00LjkzOC0yMC44Mi0yMy40ODgtMjYuMDY3LTI0LjgwOS0zLjYzOC0uOTE2LTQuNDY4LS40MjgtMTUuNDc4IDkuMTEzLTkuODgyIDguNTYyLTkuMjA5IDguMzUzLTE1LjAxNSA0LjY2Ni0xNS44NDEtMTAuMDYtMzcuMDE4LTE4LjMyMy01OC43NDktMjIuOTI1LTguNzQ1LTEuODUxLTcuNjU2LjE4OS0xMi4wNDgtMjIuNTYxLTEuNDEyLTcuMzE1LTIuNDg2LTguOC02Ljg0OC05LjQ2My0zLjcxNy0uNTY1LTE2LjE3Ni0uNzg0LTIyLjU0OC0uMzk2TTIwOS40IDU1LjIxMWM5Ni4xMTQgNi4zODEgMTU5LjYzMSA5OS42NDIgMTI5LjY2NyAxOTAuMzg5LTMzLjk1NCAxMDIuODMzLTE2NC42NzcgMTMzLjQ1LTI0MS42OTIgNTYuNjA3LTQyLjMzNS00Mi4yNDEtNTQuNTAzLTk5LjE0Mi0zMy4yMzYtMTU1LjQyOSAyMS4yMy01Ni4xODYgODMuODI3LTk1LjY0NiAxNDUuMjYxLTkxLjU2N20tMjIuNiAxMC41ODdjLTI0LjcyNiAyLjI5My00NS4zMzEgMTAuODExLTU1LjI4MSAyMi44NTFsLTEuNjEzIDEuOTUxIDcwLjE0Ny4yIDcwLjI5MS4xMjNjLjg5Ni0uNDgtNy4xOTctNy44MjMtMTIuNTQ0LTExLjM3OS0xNi40NDctMTAuOTQtNDMuOTE3LTE2LjI1OC03MS0xMy43NDZtOTUuNjMxIDI4LjU2OGMzLjc5NCAxMS43OTYgNC4wOTMgMjYuNTc2Ljc1OCAzNy4zNzQtMS4wNTQgMy40MTUtMS43MzUgMy4yNjIgNi4yMDggMS4zOWw2Ljc5OC0xLjYwMiAxLjEzNCAxLjMzNmMzLjIgMy43NyAxMS4wNzEgMTcuNDkzIDExLjA3MSAxOS4zMDIgMCAuNzUyLTQuNDUgNC44NDgtMTQuNiAxMy40NDFsLTExLjA3MiA5LjUxM2MtMS42NTMgMS41NTktMi40ODkgMS41MDQtMi45MDEtLjE4OC0uNTI4LTIuMTcyLTUuMzgxLTExLjU2Mi03Ljk5NC0xNS40NjctMy4xMzUtNC42ODUtMy4wNDktMy41MDItLjY1Ni05LjA2NSA1LjMzMS0xMi4zOSA3LjU4NC0zMS44NjYgNS4zMjMtNDZsLS43MzYtNC42LTkuNTE1LjA2NmMtMTAuNDU2LjA3Mi0xMC4yOTIuMDQ0LTkuMTExIDEuNTQ2IDMuOTIzIDQuOTg4IDUuNTYzIDIwLjA2MyAzLjM0MSAzMC43MDQtMy43MzQgMTcuODcxLTEyLjk3MSAzMS41MjEtMzIuMTM2IDQ3LjQ4OC0xMy41MTIgMTEuMjU2LTE1LjkgMTQuNTU2LTE1LjkzMyAyMi4wMTItLjAzMSA3LjAzNSAyLjMxIDEwLjUzNiAxMy4xOSAxOS43MjkgMTUuMzEgMTIuOTM0IDIzLjEwOCAyMS45NDQgMjguODYxIDMzLjM0MiA3LjY1NiAxNS4xNzEgOS4yMDkgMzMuOTUxIDMuNzMzIDQ1LjE2OS0uNzY3IDEuNTctMS4zOTQgMi45NjUtMS4zOTQgMy4xczQuMTQ0LjI0NCA5LjIxLjI0NGg5LjIxbC4zNTUtLjkzNWMxLjI0MS0zLjI2MyAyLjIzMi0xOC4wMjQgMS42NTItMjQuNjA1LS45OTQtMTEuMjk0LTIuOTUtMTguODYzLTcuMzkxLTI4LjYwOGwtMS40MS0zLjA5NSAyLjQ0Ny0zLjYzNGMyLjg3My00LjI2NiA2LjUwNy0xMS40NDcgOC4zNjItMTYuNTIzLjcyMy0xLjk4IDEuNDQ2LTMuNzU2IDEuNjA2LTMuOTQ2czIuMTUxIDEuMzQ4IDQuNDI1IDMuNDE3YTQ0NyA0NDcgMCAwIDAgOC41MzQgNy41MjdjNy4wOTMgNi4wNjggMTIuNjM1IDExLjI3MyAxMy42NzIgMTIuODM5bC45NjUgMS40NTgtMi41NDYgNS4zNTNjLTIuNzczIDUuODI2LTYuNTU3IDEyLjMxLTguMjAyIDE0LjA1Mi0xLjMzMyAxLjQxMi0xLjUyOSAxLjQwMS05LjA3Ny0uNDk3LTcuMzg2LTEuODU3LTYuODI4LTEuOTU2LTUuOCAxLjAzMSAzLjM1MyA5Ljc0NCAzLjY5OSAyNy4xMTguNzU5IDM4LjA5NC0xLjMwNSA0Ljg3NS0uOTk0IDQuNzE1IDkuMTY1LTQuNyA2Mi45OTQtNTguMzc4IDU5LjMwMy0xNTUuNTQ1LTcuODc3LTIwNy4zNTktMy43OC0yLjkxNS0zLjc4Mi0yLjkxNC0yLjQyOCAxLjI5N00xMTUuNCA5My4wNDRjLTMuMTQ1IDIuMzU1LTguMTQ4IDYuOS0xMy42IDEyLjM1Ni01NS44MTEgNTUuODUtNTAuNSAxNTAuODAyIDExLjEyMyAxOTguODMxIDQuNTE2IDMuNTIgNC42MDMgMy41MjEgMy41MzUuMDY0LTMuMjg0LTEwLjYzNS0zLjIwNS0yNS42MjUuMTk0LTM2LjM4MiAxLjI0LTMuOTI2IDEuOTA2LTMuNzE3LTUuNzQzLTEuNzk5LTcuMzk3IDEuODU1LTYuODIyIDEuOTU4LTkuNDk1LTEuNzA3LTEuNzM2LTIuMzgtNy4wNTItMTIuMDAyLTguMjEtMTQuODYyLTEuNDkyLTMuNjgyLTIuNjM3LTIuMzMgMTYuMzMtMTkuMjg2bDYuMzY0LTUuNzI1YzMuMjE3LTIuOTExIDQuMTAyLTMuMjgyIDQuMTAyLTEuNzIxIDAgMi4yNTEgNC41NTEgMTEuNTUzIDguOTg1IDE4LjM2M2wyLjYyNSA0LjAzMy0xLjk5NiA0LjA5NWMtNi43MzUgMTMuODE5LTkuNDggMzQuOTQ2LTYuNTExIDUwLjA5NmwuNzA2IDMuNiA5LjE4Ny4xMDhjMTEuMDMuMTI5IDEwLjUzMS4yNTggOC44MjgtMi4yNzMtNS4xMTctNy42MDMtNS41OTktMjIuNjc4LTEuMTUyLTM2LjAzIDUuMTY3LTE1LjUxNSAxNS4zNjQtMjguOTI4IDMzLjQxLTQzLjk1MSA5LjAxNy03LjUwNiAxMS4zNjctMTAuNTM2IDEyLjYwOC0xNi4yNTQgMS43MjYtNy45NTYtLjk2OC0xMi44OTQtMTEuODItMjEuNjY1LTI0Ljk5NS0yMC4yMDItMzUuMTc3LTM1Ljk3Mi0zNi45NTUtNTcuMjM2LS44NjQtMTAuMzM4LjI2Ni0xNy41MjQgMy42NTgtMjMuMjYuOTEyLTEuNTQzIDEuMTQyLTIuMjQ0LjgwMi0yLjQ1NC0uNzI0LS40NDgtMTguMTMuMDQ2LTE4LjQzNC41MjItLjU1Ni44NzMtMS41MjkgOC43ODgtMS43ODEgMTQuNDkzLS41OTQgMTMuMzkyIDIuMDIxIDI3LjQ3IDcuMDIyIDM3LjgxMy44NzggMS44MTQgMS40ODIgMy40OTkgMS4zNDQgMy43NDNzLTEuMTkgMS44ODQtMi4zMzYgMy42NDRjLTIuODk1IDQuNDQ1LTYuMTUgMTAuOTktNy45MjcgMTUuOTMzLS4yOTguODMxLS45NjcuMzg1LTUuNjkxLTMuNzg4LTEuMzM1LTEuMTgtNC41NjgtMy45NDUtNy4xODYtNi4xNDUtMTAuNzcyLTkuMDU1LTE0Ljk4Ni0xMy4xMDMtMTQuOTg2LTE0LjM5NCAwLTIuMTg5IDcuMzY5LTE1LjEzMiAxMC41MzYtMTguNTA2IDEuNTI2LTEuNjI1IDIuMTY5LTEuNjM0IDguNjYxLS4xMjQgNS44NTcgMS4zNjIgNS40MDIgMS41MDcgNC42MzEtMS40Ny0zLjIzMy0xMi40NzUtMi44ODgtMjUuNTA2Ljk4My0zNy4xMzkgMS4xNTMtMy40NjQuOTc4LTMuNjExLTEuODExLTEuNTIzbTM4LjMyOSA3Ljc4NGMtNC45MTkgMi40MzUtOC45MTggMTAuMTcxLTYuNTUgMTIuNjcybC44NTIuOWgxMDMuNTUxbC42ODItMS4wNDJjMS42Ni0yLjUzMy0xLjI3MS04LjU3NS01LjYwNS0xMS41NTRsLTIuMzM0LTEuNjA0LTM5LjM2Mi0uMTA2Yy0yMS42NS0uMDU4LTM5LjM2My0uMDM0LTM5LjM2My4wNTVzLjI2OS42NzUuNTk4IDEuMzA1YzEuNzQ2IDMuMzUtLjUwNyA2Ljk0Ni00LjM1MyA2Ljk0Ni0zLjQ4NiAwLTUuODE2LTMuNTQ3LTQuNTExLTYuODY4bC42MDItMS41MzJoLTEuMjY4Yy0uNjk3IDAtMi4wMi4zNzMtMi45MzkuODI4bTQyLjA3MSAyNS40MjNjLTE2LjMxMSAyLjM4Mi0zMS40MDkgNy42MjgtNDEuMSAxNC4yODEtNC4wNzMgMi43OTYtMy44ODcgMi4yNzItMi4wMzQgNS43MzEgNC43NTkgOC44ODEgMTIuMjMzIDE3LjA3NyAyNC45MyAyNy4zMzcgMTAuNTMxIDguNTA5IDEyLjc4MSAxMC45ODIgMTUuODUyIDE3LjQxOSAzLjIzOSA2Ljc5IDMuMTUyIDUuODIgMy4xNTIgMzUuMTgxdjI2bC0uOTMxIDEuODkxYy0uNTEzIDEuMDQtMS44MDMgMi42NzUtMi44NjggMy42MzItMS43NzggMS41OTgtMy4xMjYgMi4yODctMTAuNDAxIDUuMzEyLTE5Ljc3MiA4LjIyMi0zMS45OTEgMTYuMTM2LTM1LjIyMyAyMi44MTMtMi40ODEgNS4xMjUuMzcyIDEzLjE3OCA1Ljc5NSAxNi4zNTZsMS43MjEgMS4wMDkgNDUuMTU0LS4xMDZMMjQ1IDMwM2wxLjgzNy0xLjA4YzQuNzM5LTIuNzg2IDcuMjQzLTkuNjExIDUuMzkyLTE0LjY5NS0yLjMxOC02LjM2Ni0xMi4xMDktMTMuMjM1LTMxLjIyOS0yMS45MS0xMy43OTYtNi4yNTktMTUuMjg2LTcuMjExLTE3LjMxNi0xMS4wNkwyMDIuNiAyNTIuMnYtMjUuOGMwLTM2LjUxLjI2Ni0zNy4yNTkgMTguNjU4LTUyLjYwMSAxNy4yMzktMTQuMzc5IDMwLjM0Mi0zMC40NjUgMzAuMzQyLTM3LjI0OCAwLTIuMTk2LTEzLjk4MS03LjA2Mi0yNi40LTkuMTg5LTUuOTc5LTEuMDIzLTI1LjA2LTEuNzQ1LTI5LjQtMS4xMTFtLjQgMy4xNzJjLS4yMi4wODktMS45OTguNjItMy45NTEgMS4xODItOC41MjggMi40NTItMjMuNTEgMTAuMDkzLTI0LjQxNSAxMi40NTEtLjEzOS4zNjEuODg0IDIuMTYgMi41NjQgNC41MTQgNC4yNjYgNS45NzYgNC45NjggOC43MTYgMi42MjYgMTAuMjUxLTEuMzA0Ljg1NC0yLjUzNi40NDMtNC45MjEtMS42NDMtMS43ODEtMS41NTgtNi4xMDMtNi44NzktNi4xMDMtNy41MTMgMC0uMTMxLS43Mi0xLjM1Mi0xLjYtMi43MTQtMi4wMTktMy4xMjMtMi4xMDctMi43NyAxLjMtNS4xOTIgNS4zMjUtMy43ODcgMTIuMDg3LTYuNTU4IDIyLjM3Mi05LjE3IDYuMDg4LTEuNTQ2IDE0LjE5My0yLjk5MyAxMi4xMjgtMi4xNjZtLTUuMjI3IDE2LjIzOGMxLjgxOS44MjggMS42NSAzLjU2LS4yNTcgNC4xNjYtMi4xNjUuNjg3LTMuNzA1LTIuNjg5LTEuODI3LTQuMDA0IDEuMDYtLjc0My44NDctLjcyNiAyLjA4NC0uMTYybS05LjA1MyAxNS4yMTljLjY2NC42NjQuNjAzIDIuOTItLjA5NiAzLjUtLjk0MS43ODEtMi43MzEuMzQxLTMuMzg4LS44MzQtMS4xNDYtMi4wNTEgMS44MjUtNC4zMjUgMy40ODQtMi42NjZtNzkuODggMTQuNDJjNy40MDYgMTYuMTc1IDcuMTkzIDM1LjU2Ny0uNTczIDUyLjEzOS0xLjg0MSAzLjkyOC0xLjY5NSAzLjkyOS01LjIyNy0uMDUzLTMuMDE3LTMuNDAzLTExLjcwMS0xMS41Mi0xOC42LTE3LjM4Ni01LjkxOS01LjAzMy04LjYtNy42MTQtOC42LTguMjc4IDAtLjI4IDEuOTI5LTIuMDg3IDQuMjg3LTQuMDE1IDEwLjI3NS04LjQwNiAyMC42ODEtMTguMzU2IDI0LjQ4LTIzLjQwNyAyLjIzNC0yLjk3MiAyLjQzNi0yLjkyNCA0LjIzMyAxbS0xMTguNy40YzQuMjk5IDUuMDkxIDEyLjQwNyAxMi44NjkgMTkuOSAxOS4wODkgMy43NCAzLjEwNCA3LjA2MSA2LjAxOCA3LjM4IDYuNDc1LjY4Ni45ODIgMS41NDguMTIxLTExLjM5MiAxMS4zOS04LjAzMyA2Ljk5Ny0xMy4wNTIgMTEuODI0LTE2LjUxNCAxNS44OC0xLjYyMiAxLjkwMS0xLjc4OCAxLjc4Ny00LjA1NC0yLjc4Ny03LjM3NC0xNC44ODEtNy40NTItMzQuMTA2LS4yMDEtNDkuNjQ3IDIuMDctNC40MzcgMS41MTItNC4zOTEgNC44ODEtLjRtLTI0LjQ0MSA2LjAwOGMtMi4yMTMgOC44MTktMi41OTkgMjMuMDA0LS44ODggMzIuNjkyLjI5MSAxLjY1LjQ4NyAzLjA1LjQzNSAzLjExMS0uMzAzLjM1Ni0zMy40MzYtNC44MzgtMzUuMjQxLTUuNTI0LTIuMTk4LS44MzYtMi43OTYtMjIuNzcyLS42NzYtMjQuODI2LjI5Ni0uMjg4IDIuNzY3LS43NjUgMTguMzExLTMuNTM1IDE4LjE0Ni0zLjIzNCAxOC4zOTYtMy4yNiAxOC4wNTktMS45MThtMTY2LjUwMS0uNTE2YzEuMTM4LjIxNiA2LjA2OCAxLjAzMSAxMC45NTUgMS44MTEgOC41MjMgMS4zNjEgMTcuNjk0IDMuMDU0IDIwLjcxNSAzLjgyNSAzLjg0Ni45ODIgMy43NDEgMjQuNjkzLS4xMTIgMjUuMzU2LTEyLjY1OCAyLjE3OS0zNC4zODggNS40MjItMzQuNjczIDUuMTc0LS4wODUtLjA3My4xNTMtMS45NzkuNTI5LTQuMjMzIDEuNzQyLTEwLjQ1OCAxLjM5LTIzLjk1Ni0uODI2LTMxLjYyNS0uMjM5LS44MjcuMzc5LS44ODMgMy40MTItLjMwOE0yMDQgMjY0YzAgLjIyLS40MTkuNC0uOTMuNC0yLjExMyAwLTkuNjM2IDIuNjI0LTE0Ljk1NiA1LjIxNi0xMy43NjEgNi43MDctMjEuNDg1IDEzLjY3MS0yNi4yNjMgMjMuNjgxLTIuNTA0IDUuMjQ3LTYuNDA2IDUuOTAzLTguNjc0IDEuNDU4LTQuMDM4LTcuOTE1IDkuMjQ0LTIwLjA3IDMwLjAyMy0yNy40NzcgMy40ODItMS4yNDEgMTIuMjA3LTIuOTY0IDE2LjU4OS0zLjI3NWw0LjExMS0uMzQ0Yy4wNTUtLjAzMi4xLjEyMS4xLjM0MW0tMTIuNCAyMi40YzEuNzMzIDEuNzMzLjM1MiA1LjItMi4wNzIgNS4yLTEuMTU3IDAtMi43MjgtMS43ODktMi43MjgtMy4xMDYgMC0yLjQ4NCAzLjA3MS0zLjgyMyA0LjgtMi4wOTRtLTE3LjgyOSAzLjQyOWMxLjgwOSAxLjgwOC0uNjggNC41OTctMi45OTcgMy4zNTctLjg4Ny0uNDc1LTEuMDc2LTIuNzI0LS4yOTQtMy41MDYuNjgtLjY4IDIuNTQ4LS41OTUgMy4yOTEuMTQ5TTEzMi44IDMxNC44NWMyNC4xNSAyMi42NCA4NC42ODkgMjcuNDMyIDEyMC40MjEgOS41MzQgNS40NDUtMi43MjggMTQuOTExLTkuNTg4IDE1Ljk3Ni0xMS41NzlsLjQzMS0uODA1LTY5LjkxNC4wMTktNjkuOTE0LjAxOXoiIGZpbGw9IiMxNzMyNDEiLz48L3N2Zz4="
)]
#![warn(missing_docs)]
#[cfg(doc)]
extern crate self as odem_rs;
// Re-export the dependencies under shorter names without overriding external
// crates of the same name.
pub use {odem_rs_core as core, odem_rs_sync as sync, odem_rs_util as util};
// Re-export the `main` proc-macro from the odem_rs_meta-crate.
pub use odem_rs_meta::sim_main as main;
// Re-export the external crates in the version used in odem-rs here,
// if the corresponding feature is active.
#[cfg(feature = "uom")]
#[cfg_attr(docsrs, doc(cfg(feature = "uom")))]
pub use uom;
#[cfg(feature = "tracing")]
#[cfg_attr(docsrs, doc(cfg(feature = "tracing")))]
pub use tracing;
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
pub use rayon;
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub use typed_arena;
#[cfg(feature = "rand_pcg")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand_pcg")))]
pub use rand_pcg;
#[cfg(feature = "rand_xoshiro")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand_xoshiro")))]
pub use rand_xoshiro;
pub use intrusive_collections;
pub use rand;
pub mod error;
/// A module for re-exports of simulation-library concepts that are essential
/// for most simulation models.
///
/// This module simplifies the configuration and use of odem-rs for building,
/// executing, and analyzing simulation models. It is recommended to import it
/// into new simulation projects via `use odem_rs::prelude::*` to cut down on
/// the number of imports.
pub mod prelude {
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub use crate::sync::channel::channel;
#[cfg(feature = "uom")]
#[cfg_attr(docsrs, doc(cfg(feature = "uom")))]
pub use crate::util::si::{
UnitExt as _,
time::{Time, day, hour, microsecond, millisecond, minute, nanosecond, second, year},
};
pub use crate::rand::RngExt;
pub use crate::{
core::{
Active, Puck,
agent::{Agent, Behavior},
config::{Config, Time as _},
job::Job,
model_time,
ops::{defer, sim, sleep},
simulator::{Sim, Simulator, simulation},
},
error::SimResult,
sync::{
Publisher,
channel::{Channel, ChannelExt as _},
control::Control,
fork::ForkExt as _,
until,
},
util::{pool::Pool, random::RngStream, random_variable::RandomVariable},
};
}