Class: Legion::Extensions::Agentic::Homeostasis::Tectonics::Helpers::TectonicEngine

Inherits:
Object
  • Object
show all
Includes:
Constants, TectonicBoundaries
Defined in:
lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb

Constant Summary

Constants included from Constants

Constants::AFTERSHOCK_DECAY, Constants::BOUNDARY_TYPES, Constants::COLLISION_THRESHOLD, Constants::MAGNITUDE_LABELS, Constants::MAX_DRIFT_RATE, Constants::MAX_PLATES, Constants::MAX_QUAKES, Constants::MIN_DRIFT_RATE, Constants::PLATE_STATES, Constants::STRESS_QUAKE_TRIGGER, Constants::SUBDUCTION_RATIO

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Constants

#label_for

Constructor Details

#initializeTectonicEngine

Returns a new instance of TectonicEngine.



97
98
99
100
101
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 97

def initialize
  @plates          = {}
  @seismic_history = []
  @active_faults   = []
end

Instance Attribute Details

#active_faultsObject (readonly)

Returns the value of attribute active_faults.



95
96
97
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 95

def active_faults
  @active_faults
end

#platesObject (readonly)

Returns the value of attribute plates.



95
96
97
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 95

def plates
  @plates
end

#seismic_historyObject (readonly)

Returns the value of attribute seismic_history.



95
96
97
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 95

def seismic_history
  @seismic_history
end

Instance Method Details

#aftershock_cascade(event_id:) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 177

def aftershock_cascade(event_id:, **)
  parent = @seismic_history.find { |e| e.id == event_id }
  raise ArgumentError, "event not found: #{event_id}" unless parent

  decayed_magnitude = (parent.magnitude * (1.0 - Constants::AFTERSHOCK_DECAY)).round(10)
  return { success: true, aftershocks: [], reason: :magnitude_too_low } if decayed_magnitude < 0.1

  aftershock = SeismicEvent.new(type: :aftershock, magnitude: decayed_magnitude,
                                epicenter_plate_id: parent.epicenter_plate_id,
                                affected_plate_ids: parent.affected_plate_ids,
                                parent_event_id: event_id)
  record_seismic_event(aftershock)
  { success: true, aftershocks: [aftershock.to_h] }
rescue ArgumentError => e
  { success: false, error: e.message }
end

#all_platesObject



194
195
196
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 194

def all_plates
  @plates.values.map(&:to_h)
end

#create_plate(domain:, content:, mass: 0.5, drift_vector: nil, position: nil) ⇒ Object



103
104
105
106
107
108
109
110
111
112
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 103

def create_plate(domain:, content:, mass: 0.5, drift_vector: nil, position: nil, **)
  raise ArgumentError, 'plate limit reached' if @plates.size >= Constants::MAX_PLATES

  plate = BeliefPlate.new(domain: domain, content: content,
                          mass: mass, drift_vector: drift_vector, position: position)
  @plates[plate.id] = plate
  { success: true, plate_id: plate.id, plate: plate.to_h }
rescue ArgumentError => e
  { success: false, error: e.message }
end

#detect_collisionsObject



126
127
128
129
130
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 126

def detect_collisions
  active = @plates.values.select(&:active?)
  pairs  = active.combination(2).select { |a, b| a.distance_to(b) < Constants::COLLISION_THRESHOLD }
  pairs.map { |a, b| { plate_a_id: a.id, plate_b_id: b.id, distance: a.distance_to(b) } }
end

#drift_tick!(delta_t = 1.0) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 114

def drift_tick!(delta_t = 1.0, **)
  moved = 0
  @plates.each_value do |plate|
    next unless plate.active?

    plate.drift!(delta_t)
    moved += 1
  end
  collisions = detect_collisions
  { success: true, plates_moved: moved, collisions_detected: collisions.size, collisions: collisions }
end

#resolve_collision(plate_a_id:, plate_b_id:, boundary_type:) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 132

def resolve_collision(plate_a_id:, plate_b_id:, boundary_type:, **)
  raise ArgumentError, "unknown boundary type: #{boundary_type}" unless Constants::BOUNDARY_TYPES.include?(boundary_type)

  plate_a = @plates[plate_a_id]
  plate_b = @plates[plate_b_id]
  raise ArgumentError, "plate not found: #{plate_a_id}" unless plate_a
  raise ArgumentError, "plate not found: #{plate_b_id}" unless plate_b

  result = send(:"resolve_#{boundary_type}", plate_a, plate_b)
  update_active_faults(plate_a_id, plate_b_id, boundary_type)
  result
rescue ArgumentError => e
  { success: false, error: e.message }
end

#subduct(weaker_plate_id:, stronger_plate_id:) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 147

def subduct(weaker_plate_id:, stronger_plate_id:, **)
  weaker   = @plates[weaker_plate_id]
  stronger = @plates[stronger_plate_id]
  raise ArgumentError, "plate not found: #{weaker_plate_id}"   unless weaker
  raise ArgumentError, "plate not found: #{stronger_plate_id}" unless stronger

  mass_absorbed = weaker.mass * 0.5
  stronger.mass = (stronger.mass + mass_absorbed).clamp(0.0, 1.0)
  weaker.subduct!
  remove_faults_for(weaker_plate_id)
  { success: true, subducted_plate_id: weaker_plate_id, mass_absorbed: mass_absorbed.round(10) }
rescue ArgumentError => e
  { success: false, error: e.message }
end

#tectonic_reportObject



198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 198

def tectonic_report
  active_plates, subducted_plates = @plates.values.partition(&:active?)
  high_stress = active_plates.select { |p| p.stress_accumulation > 0.5 }
  {
    total_plates:      @plates.size,
    active_plates:     active_plates.size,
    subducted_plates:  subducted_plates.size,
    high_stress_count: high_stress.size,
    seismic_events:    @seismic_history.size,
    active_faults:     @active_faults.size,
    avg_mass:          avg_mass(active_plates),
    recent_quakes:     recent_earthquakes(5)
  }
end

#trigger_earthquake(plate_id:, magnitude:) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/legion/extensions/agentic/homeostasis/tectonics/helpers/tectonic_engine.rb', line 162

def trigger_earthquake(plate_id:, magnitude:, **)
  plate = @plates[plate_id]
  raise ArgumentError, "plate not found: #{plate_id}" unless plate

  nearby = nearby_plates(plate, exclude_id: plate_id)
  event  = SeismicEvent.new(type: :earthquake, magnitude: magnitude,
                            epicenter_plate_id: plate_id, affected_plate_ids: nearby.map(&:id))
  record_seismic_event(event)
  plate.release_stress!
  nearby.each { |p| p.accumulate_stress!(magnitude * 0.3) }
  { success: true, event_id: event.id, event: event.to_h }
rescue ArgumentError => e
  { success: false, error: e.message }
end