Class: Legion::Extensions::Agentic::Homeostasis::Tide::Helpers::TideEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTideEngine

Returns a new instance of TideEngine.



12
13
14
15
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 12

def initialize
  @oscillators = []
  @pools       = []
end

Instance Attribute Details

#oscillatorsObject (readonly)

Returns the value of attribute oscillators.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 10

def oscillators
  @oscillators
end

#poolsObject (readonly)

Returns the value of attribute pools.



10
11
12
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 10

def pools
  @pools
end

Instance Method Details

#add_oscillator(oscillator_type:, period:, amplitude: 1.0, phase_offset: 0.0) ⇒ Object

Add an oscillator; returns the new Oscillator instance



18
19
20
21
22
23
24
25
26
27
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 18

def add_oscillator(oscillator_type:, period:, amplitude: 1.0, phase_offset: 0.0)
  osc = Oscillator.new(
    oscillator_type: oscillator_type,
    period:          period,
    amplitude:       amplitude,
    phase_offset:    phase_offset
  )
  @oscillators << osc
  osc
end

#composite_tide_levelObject

Composite tide level: clamped sum of all oscillator current values, normalized to [0, 1]



30
31
32
33
34
35
36
37
38
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 30

def composite_tide_level
  return 0.0 if @oscillators.empty?

  raw = @oscillators.sum(&:current_value)
  max = @oscillators.sum(&:amplitude)
  return 0.0 if max.zero?

  (raw / max).clamp(0.0, 1.0).round(10)
end

#create_pool(domain:, capacity: 20) ⇒ Object

Create a new tidal pool for a domain; respects MAX_POOLS limit



57
58
59
60
61
62
63
64
65
66
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 57

def create_pool(domain:, capacity: 20)
  return nil if @pools.size >= Constants::MAX_POOLS

  existing = find_pool(domain)
  return existing if existing

  pool = TidalPool.new(domain: domain, capacity: capacity)
  @pools << pool
  pool
end

#current_phaseObject

Determine phase based on comparison of current and recent tide level



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 41

def current_phase
  level = composite_tide_level
  previous = previous_level

  if level >= 0.65
    :high_tide
  elsif level <= 0.35
    :low_tide
  elsif level > previous
    :rising
  else
    :falling
  end
end

#deposit_to_pool(domain:, item:, capacity: 20) ⇒ Object

Deposit an item into a domain pool (creates the pool if needed)



69
70
71
72
73
74
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 69

def deposit_to_pool(domain:, item:, capacity: 20)
  pool = find_pool(domain) || create_pool(domain: domain, capacity: capacity)
  return false unless pool

  pool.deposit(item)
end

#evaporate_all!(rate = Constants::POOL_EVAPORATION_RATE) ⇒ Object

Apply evaporation to all pools



91
92
93
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 91

def evaporate_all!(rate = Constants::POOL_EVAPORATION_RATE)
  @pools.sum { |pool| pool.evaporate!(rate) }
end

#harvest_pools(min_depth: 0.0) ⇒ Object

Harvest pools only when tide is rising; returns hash of domain => items



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 77

def harvest_pools(min_depth: 0.0)
  return {} unless rising?

  result = {}
  @pools.each do |pool|
    next if pool.depth < min_depth
    next if pool.empty?

    result[pool.domain] = pool.harvest!
  end
  result
end

#high_tide?Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 109

def high_tide?
  composite_tide_level >= 0.65
end

#low_tide?Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 113

def low_tide?
  composite_tide_level <= 0.35
end

#rising?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 117

def rising?
  current_phase == :rising
end

#tide_forecast(duration) ⇒ Object

Forecast tide level at regular intervals over a duration (seconds)



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 96

def tide_forecast(duration)
  return [] if @oscillators.empty?

  steps = (duration.to_f / Constants::FORECAST_RESOLUTION).ceil
  now   = Time.now.utc

  (0...steps).map do |step|
    t     = now + (step * Constants::FORECAST_RESOLUTION)
    level = forecast_level_at(t)
    { time: t, level: level, label: tide_label(level) }
  end
end

#tide_reportObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/legion/extensions/agentic/homeostasis/tide/helpers/tide_engine.rb', line 121

def tide_report
  level = composite_tide_level
  {
    level:            level,
    phase:            current_phase,
    label:            tide_label(level),
    oscillator_count: @oscillators.size,
    pool_count:       @pools.size,
    high_tide:        high_tide?,
    low_tide:         low_tide?,
    pools:            @pools.map(&:to_h),
    oscillators:      @oscillators.map(&:to_h)
  }
end