use serde::{Deserialize, Serialize};
pub use kimiya::electrochemistry;
pub use kimiya::element;
pub use kimiya::gas;
pub use kimiya::kinetics;
pub use kimiya::molecule;
pub use kimiya::nuclear;
pub use kimiya::phase as chem_phase;
pub use kimiya::reaction;
pub use kimiya::solution;
pub use kimiya::spectroscopy;
pub use kimiya::stoichiometry;
pub use kimiya::thermochem;
pub use kimiya::KimiyaError;
pub use khanij::crystal;
pub use khanij::crystallography;
pub use khanij::dating;
pub use khanij::mineral;
pub use khanij::ore;
pub use khanij::rock;
pub use khanij::sediment;
pub use khanij::soil as geo_soil;
pub use khanij::stratigraphy;
pub use khanij::tectonics;
pub use khanij::timescale;
pub use khanij::volcanic;
pub use khanij::weathering;
pub use khanij::KhanijError;
pub use tanmatra::atomic;
pub use tanmatra::constants as atomic_constants;
pub use tanmatra::decay;
pub use tanmatra::nucleus;
pub use tanmatra::particle;
pub use tanmatra::reaction as nuclear_reaction;
pub use tanmatra::relativity;
pub use tanmatra::scattering as particle_scattering;
pub use tanmatra::prelude::TanmatraError;
pub use kana::circuit as quantum_circuit;
pub use kana::dynamics as quantum_dynamics;
pub use kana::entanglement;
pub use kana::operator;
pub use kana::state;
pub use kana::KanaError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChemicalBody {
pub formula: String,
pub temperature: f64,
pub concentration: f64,
pub ph: f64,
pub active: bool,
}
impl ChemicalBody {
pub fn new(formula: impl Into<String>, temperature: f64) -> Self {
let formula = formula.into();
tracing::trace!(%formula, temperature, "created chemical body");
Self {
formula,
temperature,
concentration: 0.0,
ph: 7.0,
active: true,
}
}
pub fn with_concentration(mut self, c: f64) -> Self {
self.concentration = c;
self
}
pub fn with_ph(mut self, ph: f64) -> Self {
self.ph = ph;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeologicalBody {
pub material_name: String,
pub hardness: f64,
pub density: f64,
pub weathering_rate: f64,
pub active: bool,
}
impl GeologicalBody {
pub fn new(material_name: impl Into<String>, hardness: f64, density: f64) -> Self {
Self {
material_name: material_name.into(),
hardness,
density,
weathering_rate: 0.0,
active: true,
}
}
pub fn with_weathering(mut self, rate: f64) -> Self {
self.weathering_rate = rate;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RadioactiveSource {
pub isotope: String,
pub half_life: f64,
pub activity: f64,
pub active: bool,
}
impl RadioactiveSource {
pub fn new(isotope: impl Into<String>, half_life: f64, activity: f64) -> Self {
let isotope = isotope.into();
tracing::trace!(%isotope, half_life, activity, "created radioactive source");
Self {
isotope,
half_life,
activity,
active: true,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chemical_body_builder() {
let c = ChemicalBody::new("NaCl", 298.0)
.with_concentration(0.1)
.with_ph(7.0);
assert_eq!(c.formula, "NaCl");
assert_eq!(c.concentration, 0.1);
}
#[test]
fn geological_body_builder() {
let g = GeologicalBody::new("Granite", 7.0, 2700.0).with_weathering(0.1);
assert_eq!(g.hardness, 7.0);
assert_eq!(g.weathering_rate, 0.1);
}
#[test]
fn radioactive_source() {
let r = RadioactiveSource::new("C-14", 5730.0 * 365.25 * 86400.0, 1e6);
assert_eq!(r.isotope, "C-14");
assert!(r.half_life > 0.0);
}
#[test]
fn chemical_as_component() {
let mut world = crate::World::new();
let e = world.spawn();
world
.insert_component(e, ChemicalBody::new("H2O", 373.0))
.unwrap();
assert!(world.has_component::<ChemicalBody>(e));
}
#[test]
fn geological_as_component() {
let mut world = crate::World::new();
let e = world.spawn();
world
.insert_component(e, GeologicalBody::new("Quartz", 7.0, 2650.0))
.unwrap();
let g = world.get_component::<GeologicalBody>(e).unwrap();
assert_eq!(g.material_name, "Quartz");
}
}