///|
/// CLI demonstration runner for moonbit-granular discrete element engine.
fn main {
  println("=========================================================")
  println(" moonbit-granular: Discrete Element Method (DEM) Engine ")
  println("=========================================================")

  // Demonstration 1: Direct Shear Box Simulation
  println("\n--- [Demo 1] Direct Shear Box Simulation ---")
  let shear_box = @app.DirectShearBoxApp::new(0.05, 0.05, 0.05, 20, 5.0e4, 0.01)
  for step = 0; step < 20; step = step + 1 {
    shear_box.step()
  }
  println(
    "Shear Displacement: " + shear_box.shear_displacement().to_string() + " m",
  )
  println(
    "Measured Shear Stress: " +
    shear_box.measured_shear_stress().to_string() +
    " Pa",
  )

  // Demonstration 2: Granular Hopper Discharge & Beverloo Law
  println("\n--- [Demo 2] Granular Hopper Discharge ---")
  let hopper = @app.GranularHopperApp::new(0.06, 0.08, 0.025, 25)
  for step = 0; step < 25; step = step + 1 {
    hopper.step()
  }
  println("Discharged Particle Count: " + hopper.discharged_count().to_string())
  println("Discharged Mass: " + hopper.discharged_mass().to_string() + " kg")

  // Demonstration 3: Micro-Macro Granular Statistics & Love-Weber Stress Tensor
  println("\n--- [Demo 3] Granular Micro-Macro Statistics ---")
  let world = shear_box.world()
  let pstats = @stats.compute_packing_stats(world.particles(), 0.000125)
  println("Packing Density (Phi): " + pstats.packing_density().to_string())
  println("Void Ratio (e): " + pstats.void_ratio().to_string())

  let cstats = @stats.compute_coordination_stats(world)
  println(
    "Average Coordination Number (Z): " +
    cstats.average_coordination().to_string(),
  )

  let fnet = @stats.compute_force_network_stats(world)
  println("Mean Contact Force: " + fnet.mean_normal_force().to_string() + " N")
  println("Strong Force Fraction: " + fnet.strong_force_fraction().to_string())

  let stress = @stats.compute_love_weber_stress(world, 0.000125)
  println(
    "Love-Weber Hydrostatic Stress p: " +
    stress.hydrostatic_mean().to_string() +
    " Pa",
  )

  let fab = @stats.compute_fabric_stats(world)
  println("Fabric Anisotropy Index: " + fab.anisotropy_index().to_string())

  println("\n=========================================================")
  println(" DEM Simulation complete! All statistical metrics verified. ")
  println("=========================================================")
}