oxiphysics_python/serialization/
functions_2.rs1#[allow(unused_imports)]
6use super::functions::*;
7
8use super::types::{SimulationCheckpoint, SimulationSnapshot};
9
10pub fn serialize_simulation_checkpoint(
14 snap: &SimulationSnapshot,
15 label: impl Into<String>,
16 step_count: u64,
17 timestamp: f64,
18) -> String {
19 let cp = SimulationCheckpoint::from_snapshot(snap, label, step_count, timestamp);
20 cp.to_json()
21}
22#[cfg(test)]
23mod json_checkpoint_tests {
24 use super::*;
25 use crate::serialization::BodyStateJson;
26 use crate::serialization::SimBodyState;
27 #[test]
28 fn test_serialize_body_state_json_roundtrip() {
29 let body = SimBodyState {
30 handle: 42,
31 position: [1.0, 2.0, 3.0],
32 velocity: [0.1, 0.2, 0.3],
33 orientation: [0.0, 0.0, 0.0, 1.0],
34 angular_velocity: [0.0; 3],
35 is_sleeping: false,
36 is_static: false,
37 tag: Some("ball".to_string()),
38 };
39 let json = serialize_body_state_json(&body);
40 let back = deserialize_body_state_json(&json).unwrap();
41 assert_eq!(back.handle, 42);
42 assert!((back.position[0] - 1.0).abs() < 1e-12);
43 assert_eq!(back.tag.as_deref(), Some("ball"));
44 }
45 #[test]
46 fn test_deserialize_body_state_json_invalid() {
47 let result = deserialize_body_state_json("not valid json");
48 assert!(result.is_err());
49 }
50 #[test]
51 fn test_body_state_json_schema_version() {
52 let body = SimBodyState::at_rest(0, [0.0; 3]);
53 let bsj = BodyStateJson::from_sim_body(&body);
54 assert_eq!(bsj.schema_version, "1.0.0");
55 }
56 #[test]
57 fn test_simulation_checkpoint_from_snapshot() {
58 let mut snap = SimulationSnapshot::empty();
59 snap.time = 5.0;
60 snap.bodies.push(SimBodyState::at_rest(0, [1.0, 2.0, 3.0]));
61 let cp = SimulationCheckpoint::from_snapshot(&snap, "test_checkpoint", 300, 12345.0);
62 assert_eq!(cp.label, "test_checkpoint");
63 assert!((cp.sim_time - 5.0).abs() < 1e-10);
64 assert_eq!(cp.step_count, 300);
65 assert_eq!(cp.body_count(), 1);
66 }
67 #[test]
68 fn test_simulation_checkpoint_json_roundtrip() {
69 let mut snap = SimulationSnapshot::empty();
70 snap.time = 2.5;
71 snap.gravity = [0.0, -9.81, 0.0];
72 snap.bodies.push(SimBodyState::at_rest(1, [0.0, 5.0, 0.0]));
73 let json = serialize_simulation_checkpoint(&snap, "save_1", 100, 0.0);
74 let cp = SimulationCheckpoint::from_json(&json).unwrap();
75 assert_eq!(cp.body_count(), 1);
76 assert!((cp.sim_time - 2.5).abs() < 1e-10);
77 let restored = cp.to_snapshot();
78 assert_eq!(restored.bodies.len(), 1);
79 assert!((restored.bodies[0].position[1] - 5.0).abs() < 1e-10);
80 }
81 #[test]
82 fn test_snapshot_diff_identical() {
83 let mut snap = SimulationSnapshot::empty();
84 snap.bodies.push(SimBodyState::at_rest(0, [1.0, 0.0, 0.0]));
85 snap.bodies.push(SimBodyState::at_rest(1, [2.0, 0.0, 0.0]));
86 let diff = snap.diff(&snap, 1e-6);
87 assert!(
88 diff.is_identical(),
89 "identical snapshots should yield empty diff"
90 );
91 assert!((diff.max_displacement).abs() < 1e-12);
92 }
93 #[test]
94 fn test_snapshot_diff_added_removed() {
95 let mut snap_a = SimulationSnapshot::empty();
96 snap_a.bodies.push(SimBodyState::at_rest(0, [0.0; 3]));
97 snap_a
98 .bodies
99 .push(SimBodyState::at_rest(1, [1.0, 0.0, 0.0]));
100 let mut snap_b = SimulationSnapshot::empty();
101 snap_b
102 .bodies
103 .push(SimBodyState::at_rest(1, [1.0, 0.0, 0.0]));
104 snap_b
105 .bodies
106 .push(SimBodyState::at_rest(2, [5.0, 0.0, 0.0]));
107 let diff = snap_a.diff(&snap_b, 1e-6);
108 assert_eq!(diff.removed.len(), 1);
109 assert!(diff.removed.contains(&0));
110 assert_eq!(diff.added.len(), 1);
111 assert!(diff.added.contains(&2));
112 }
113 #[test]
114 fn test_snapshot_diff_moved() {
115 let mut snap_a = SimulationSnapshot::empty();
116 snap_a.time = 0.0;
117 snap_a
118 .bodies
119 .push(SimBodyState::at_rest(0, [0.0, 0.0, 0.0]));
120 let mut snap_b = SimulationSnapshot::empty();
121 snap_b.time = 1.0;
122 let mut moved = SimBodyState::at_rest(0, [3.0, 4.0, 0.0]);
123 moved.velocity = [1.0, 0.0, 0.0];
124 snap_b.bodies.push(moved);
125 let diff = snap_a.diff(&snap_b, 1e-6);
126 assert_eq!(diff.moved.len(), 1);
127 assert_eq!(diff.moved[0], 0);
128 assert!(
129 (diff.max_displacement - 5.0).abs() < 1e-10,
130 "disp = {}",
131 diff.max_displacement
132 );
133 assert!((diff.time_delta - 1.0).abs() < 1e-10);
134 }
135 #[test]
136 fn test_snapshot_diff_change_count() {
137 let snap_a = SimulationSnapshot::empty();
138 let mut snap_b = SimulationSnapshot::empty();
139 snap_b.bodies.push(SimBodyState::at_rest(0, [0.0; 3]));
140 snap_b
141 .bodies
142 .push(SimBodyState::at_rest(1, [1.0, 0.0, 0.0]));
143 let diff = snap_a.diff(&snap_b, 1e-6);
144 assert_eq!(diff.change_count(), 2);
145 assert!(!diff.is_identical());
146 }
147 #[test]
148 fn test_checkpoint_empty() {
149 let cp = SimulationCheckpoint::empty("init");
150 assert_eq!(cp.body_count(), 0);
151 assert_eq!(cp.label, "init");
152 assert_eq!(cp.version, SimulationCheckpoint::FORMAT_VERSION);
153 }
154}