@@ -231,6 +231,33 @@ pub fn conversion_efficiency(energy_input: f32, energy_output: f32) -> f32 {
231231 }
232232}
233233
234+ /// Optional resource to monitor energy drift over time (diagnostic only, not enforced)
235+ #[ derive( Resource , Debug ) ]
236+ pub struct EnergyDriftMonitor {
237+ pub initial_energy : f32 ,
238+ pub tolerance : f32 ,
239+ }
240+
241+ impl EnergyDriftMonitor {
242+ pub fn new ( initial_energy : f32 , tolerance : f32 ) -> Self {
243+ Self {
244+ initial_energy,
245+ tolerance,
246+ }
247+ }
248+
249+ /// Check if current energy has drifted beyond tolerance
250+ /// Returns Some(drift) if drift exceeds tolerance, None otherwise
251+ pub fn check_drift ( & self , current_energy : f32 ) -> Option < f32 > {
252+ let drift = ( current_energy - self . initial_energy ) . abs ( ) ;
253+ if drift > self . tolerance {
254+ Some ( drift)
255+ } else {
256+ None
257+ }
258+ }
259+ }
260+
234261/// Plugin to manage energy conservation systems
235262pub struct EnergyConservationPlugin ;
236263
@@ -249,3 +276,92 @@ impl Plugin for EnergyConservationPlugin {
249276 . add_message :: < EnergyTransferEvent > ( ) ;
250277 }
251278}
279+
280+ #[ cfg( test) ]
281+ mod tests {
282+ use super :: * ;
283+
284+ #[ test]
285+ fn test_ledger_arithmetic ( ) {
286+ // Test that net_energy_change = total_input - total_output
287+ let mut ledger = EnergyAccountingLedger :: default ( ) ;
288+
289+ ledger. record_transaction ( EnergyTransaction {
290+ transaction_type : TransactionType :: Input ,
291+ amount : 100.0 ,
292+ source : None ,
293+ destination : None ,
294+ timestamp : 0.0 ,
295+ transfer_rate : 0.0 ,
296+ duration : 0.0 ,
297+ } ) ;
298+
299+ ledger. record_transaction ( EnergyTransaction {
300+ transaction_type : TransactionType :: Output ,
301+ amount : 30.0 ,
302+ source : None ,
303+ destination : None ,
304+ timestamp : 0.0 ,
305+ transfer_rate : 0.0 ,
306+ duration : 0.0 ,
307+ } ) ;
308+
309+ ledger. record_transaction ( EnergyTransaction {
310+ transaction_type : TransactionType :: Input ,
311+ amount : 50.0 ,
312+ source : None ,
313+ destination : None ,
314+ timestamp : 0.0 ,
315+ transfer_rate : 0.0 ,
316+ duration : 0.0 ,
317+ } ) ;
318+
319+ assert_eq ! ( ledger. total_input, 150.0 ) ;
320+ assert_eq ! ( ledger. total_output, 30.0 ) ;
321+ assert_eq ! ( ledger. net_energy_change( ) , 120.0 ) ;
322+ }
323+
324+ #[ test]
325+ fn test_current_flux_sums_active_rates ( ) {
326+ // Test that current_flux sums transfer rates correctly
327+ let mut ledger = EnergyAccountingLedger :: default ( ) ;
328+
329+ let current_time = 10.0 ;
330+
331+ // Add active transfer (within time window)
332+ ledger. record_transaction ( EnergyTransaction {
333+ transaction_type : TransactionType :: Input ,
334+ amount : 50.0 ,
335+ source : None ,
336+ destination : None ,
337+ timestamp : 9.5 ,
338+ transfer_rate : 10.0 , // W
339+ duration : 1.0 ,
340+ } ) ;
341+
342+ // Add another active transfer
343+ ledger. record_transaction ( EnergyTransaction {
344+ transaction_type : TransactionType :: Input ,
345+ amount : 30.0 ,
346+ source : None ,
347+ destination : None ,
348+ timestamp : 9.8 ,
349+ transfer_rate : 5.0 , // W
350+ duration : 0.5 ,
351+ } ) ;
352+
353+ // Add old transfer (outside time window)
354+ ledger. record_transaction ( EnergyTransaction {
355+ transaction_type : TransactionType :: Input ,
356+ amount : 100.0 ,
357+ source : None ,
358+ destination : None ,
359+ timestamp : 5.0 ,
360+ transfer_rate : 20.0 , // W
361+ duration : 2.0 ,
362+ } ) ;
363+
364+ let flux = ledger. current_flux ( current_time, 1.0 ) ;
365+ assert_eq ! ( flux, 15.0 , "Expected sum of active rates: 10.0 + 5.0" ) ;
366+ }
367+ }
0 commit comments