Scriptable Verification ======================= NavalToolbox includes a powerful scripting engine based on `Rhai `_ that allows you to define and verify custom stability criteria without recompiling the library. Overview -------- The verification process involves three steps: 1. **Calculate Stability**: Perform standard stability analysis (GZ curve, etc.). 2. **Create Context**: Wrap the result into a ``CriteriaContext``. 3. **Run Script**: Execute a Rhai script using ``ScriptEngine``. Basic Example ------------- .. code-block:: python from navaltoolbox import CriteriaContext, ScriptEngine, StabilityCalculator # 1. Calculate stability calc = StabilityCalculator(vessel) result = calc.complete_stability(...) # 2. Create context ctx = CriteriaContext.from_result(result, "MV Example", "Departure") # 3. Run script engine = ScriptEngine() criteria = engine.run_script_file("rules/is_code_2008_general.rhai", ctx) # Check results if criteria.overall_pass: print("Vessel Compliant") else: print(f"Failed {criteria.fail_count} criteria") for c in criteria.criteria: print(f"{c.name}: {c.status} (Actual: {c.actual_value} {c.unit})") Writing Custom Scripts ---------------------- Scripts are written in Rhai. You have access to the ``ctx`` object which provides helper methods. .. code-block:: rust // Custom criterion script fn check(ctx) { // 1. Get data let area_30 = ctx.area_under_curve(0.0, 30.0); let gz_30 = ctx.gz_at_angle(30.0); let results = []; // 2. Define criteria // The criterion() function optionally takes a 6th argument for the comparison operator. // Supported operators: "<=", ">=", "<", ">", "==" // If omitted, it defaults to ">=" (actual >= required). results.push(criterion( "Area 0-30", "Minimum area under GZ curve up to 30 deg", 0.055, // Required area_30, // Actual "m.rad" // Unit // Implicitly uses ">=" )); results.push(criterion( "GZ at 30", "Minimum GZ at 30 deg", 0.20, gz_30, "m", ">=" // Explicit operator )); // Example for a maximum allowed value (e.g., wind heel angle) // results.push(criterion("Equilibrium", "Steady wind heel <= 16 deg", 16.0, heel, "deg", "<=")); // 3. Define Plot (Optional) let plot = #{ id: "main_plot", title: "GZ Curve", x_label: "Heel (deg)", y_label: "GZ (m)", elements: [ #{ type: "Curve", name: "GZ", x: ctx.get_heels(), y: ctx.get_gz_values(), color: "blue" } ] }; // Link criteria to plot for r in results { r.plot_id = "main_plot"; } // 4. Return result map let fail_count = 0; for r in results { if r.status == "FAIL" { fail_count += 1; } } #{ regulation_name: "My Custom Rules", regulation_reference: "CUSTOM-01", vessel_name: ctx.get_vessel_name(), loading_condition: ctx.get_loading_condition(), displacement: ctx.get_displacement(), overall_pass: fail_count == 0, criteria: results, plots: [plot], notes: "" } } Plotting Results ---------------- You can visualize the verification results using the built-in plotting utility (requires Matplotlib). .. code-block:: python from navaltoolbox import plotting # Display interactively plotting.plot_criteria_result(criteria) # Save to file plotting.plot_criteria_result(criteria, show=False, save_to="report.png") This generates a graph showing the GZ curve along with visual indications of the criteria (threshold lines, areas, etc.).