lex-agentic-learning 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +13 -0
- data/lex-agentic-learning.gemspec +30 -0
- data/lib/legion/extensions/agentic/learning/anchoring/client.rb +26 -0
- data/lib/legion/extensions/agentic/learning/anchoring/helpers/anchor.rb +65 -0
- data/lib/legion/extensions/agentic/learning/anchoring/helpers/anchor_store.rb +132 -0
- data/lib/legion/extensions/agentic/learning/anchoring/helpers/constants.rb +31 -0
- data/lib/legion/extensions/agentic/learning/anchoring/runners/anchoring.rb +100 -0
- data/lib/legion/extensions/agentic/learning/anchoring/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/anchoring.rb +19 -0
- data/lib/legion/extensions/agentic/learning/catalyst/client.rb +15 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/catalyst.rb +87 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/catalyst_engine.rb +153 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/constants.rb +55 -0
- data/lib/legion/extensions/agentic/learning/catalyst/helpers/reaction.rb +87 -0
- data/lib/legion/extensions/agentic/learning/catalyst/runners/cognitive_catalyst.rb +103 -0
- data/lib/legion/extensions/agentic/learning/catalyst/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/catalyst.rb +22 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/client.rb +22 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis.rb +137 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/cocoon.rb +89 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/constants.rb +49 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/helpers/metamorphosis_engine.rb +157 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/runners/cognitive_chrysalis.rb +129 -0
- data/lib/legion/extensions/agentic/learning/chrysalis/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/chrysalis.rb +21 -0
- data/lib/legion/extensions/agentic/learning/curiosity/client.rb +28 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/constants.rb +30 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/gap_detector.rb +167 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/wonder.rb +73 -0
- data/lib/legion/extensions/agentic/learning/curiosity/helpers/wonder_store.rb +149 -0
- data/lib/legion/extensions/agentic/learning/curiosity/runners/curiosity.rb +163 -0
- data/lib/legion/extensions/agentic/learning/curiosity/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/curiosity.rb +21 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/client.rb +28 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/constants.rb +31 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/curiosity_engine.rb +122 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/helpers/knowledge_gap.rb +70 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/runners/epistemic_curiosity.rb +106 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/epistemic_curiosity.rb +19 -0
- data/lib/legion/extensions/agentic/learning/fermentation/client.rb +19 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/batch.rb +75 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/constants.rb +78 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/fermentation_engine.rb +147 -0
- data/lib/legion/extensions/agentic/learning/fermentation/helpers/substrate.rb +108 -0
- data/lib/legion/extensions/agentic/learning/fermentation/runners/cognitive_fermentation.rb +60 -0
- data/lib/legion/extensions/agentic/learning/fermentation/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/fermentation.rb +22 -0
- data/lib/legion/extensions/agentic/learning/habit/client.rb +26 -0
- data/lib/legion/extensions/agentic/learning/habit/helpers/action_sequence.rb +120 -0
- data/lib/legion/extensions/agentic/learning/habit/helpers/constants.rb +44 -0
- data/lib/legion/extensions/agentic/learning/habit/helpers/habit_store.rb +148 -0
- data/lib/legion/extensions/agentic/learning/habit/runners/habit.rb +86 -0
- data/lib/legion/extensions/agentic/learning/habit/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/habit.rb +19 -0
- data/lib/legion/extensions/agentic/learning/hebbian/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/learning/hebbian/client.rb +29 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/assembly.rb +82 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/assembly_network.rb +190 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/constants.rb +50 -0
- data/lib/legion/extensions/agentic/learning/hebbian/helpers/unit.rb +94 -0
- data/lib/legion/extensions/agentic/learning/hebbian/runners/hebbian_assembly.rb +94 -0
- data/lib/legion/extensions/agentic/learning/hebbian/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/hebbian.rb +20 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/client.rb +25 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/helpers/constants.rb +35 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/helpers/rate_model.rb +133 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/runners/learning_rate.rb +85 -0
- data/lib/legion/extensions/agentic/learning/learning_rate/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/learning_rate.rb +18 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/client.rb +27 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/constants.rb +46 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/learning_domain.rb +85 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine.rb +202 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/helpers/strategy.rb +62 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/runners/meta_learning.rb +118 -0
- data/lib/legion/extensions/agentic/learning/meta_learning/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/meta_learning.rb +20 -0
- data/lib/legion/extensions/agentic/learning/plasticity/client.rb +15 -0
- data/lib/legion/extensions/agentic/learning/plasticity/helpers/constants.rb +45 -0
- data/lib/legion/extensions/agentic/learning/plasticity/helpers/neural_pathway.rb +85 -0
- data/lib/legion/extensions/agentic/learning/plasticity/helpers/plasticity_engine.rb +130 -0
- data/lib/legion/extensions/agentic/learning/plasticity/runners/cognitive_plasticity.rb +85 -0
- data/lib/legion/extensions/agentic/learning/plasticity/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/plasticity.rb +19 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/client.rb +28 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/helpers/constants.rb +35 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/helpers/option.rb +78 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/helpers/preference_engine.rb +121 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/runners/preference_learning.rb +84 -0
- data/lib/legion/extensions/agentic/learning/preference_learning/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/preference_learning.rb +19 -0
- data/lib/legion/extensions/agentic/learning/procedural/client.rb +19 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/constants.rb +46 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/learning_engine.rb +160 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/production.rb +66 -0
- data/lib/legion/extensions/agentic/learning/procedural/helpers/skill.rb +101 -0
- data/lib/legion/extensions/agentic/learning/procedural/runners/procedural_learning.rb +96 -0
- data/lib/legion/extensions/agentic/learning/procedural/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/procedural.rb +20 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/client.rb +26 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/helpers/constants.rb +42 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/helpers/scaffold.rb +136 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine.rb +112 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding.rb +107 -0
- data/lib/legion/extensions/agentic/learning/scaffolding/version.rb +13 -0
- data/lib/legion/extensions/agentic/learning/scaffolding.rb +19 -0
- data/lib/legion/extensions/agentic/learning/version.rb +11 -0
- data/lib/legion/extensions/agentic/learning.rb +31 -0
- data/spec/legion/extensions/agentic/learning/anchoring/client_spec.rb +32 -0
- data/spec/legion/extensions/agentic/learning/anchoring/helpers/anchor_spec.rb +130 -0
- data/spec/legion/extensions/agentic/learning/anchoring/helpers/anchor_store_spec.rb +201 -0
- data/spec/legion/extensions/agentic/learning/anchoring/helpers/constants_spec.rb +63 -0
- data/spec/legion/extensions/agentic/learning/anchoring/runners/anchoring_spec.rb +199 -0
- data/spec/legion/extensions/agentic/learning/catalyst/client_spec.rb +58 -0
- data/spec/legion/extensions/agentic/learning/catalyst/cognitive_catalyst_spec.rb +49 -0
- data/spec/legion/extensions/agentic/learning/catalyst/helpers/catalyst_engine_spec.rb +263 -0
- data/spec/legion/extensions/agentic/learning/catalyst/helpers/catalyst_spec.rb +214 -0
- data/spec/legion/extensions/agentic/learning/catalyst/helpers/reaction_spec.rb +223 -0
- data/spec/legion/extensions/agentic/learning/catalyst/runners/cognitive_catalyst_spec.rb +217 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/client_spec.rb +83 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/cognitive_chrysalis_spec.rb +15 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis_engine_spec.rb +57 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/chrysalis_spec.rb +305 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/cocoon_spec.rb +206 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/constants_spec.rb +109 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/metamorphic_cycle_spec.rb +76 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/metamorphosis_engine_spec.rb +247 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/helpers/transformation_phase_spec.rb +98 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/runners/cognitive_chrysalis_spec.rb +180 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/runners/reporting_spec.rb +81 -0
- data/spec/legion/extensions/agentic/learning/chrysalis/runners/transformation_spec.rb +74 -0
- data/spec/legion/extensions/agentic/learning/curiosity/client_spec.rb +27 -0
- data/spec/legion/extensions/agentic/learning/curiosity/helpers/gap_detector_spec.rb +118 -0
- data/spec/legion/extensions/agentic/learning/curiosity/helpers/wonder_spec.rb +130 -0
- data/spec/legion/extensions/agentic/learning/curiosity/helpers/wonder_store_spec.rb +136 -0
- data/spec/legion/extensions/agentic/learning/curiosity/runners/curiosity_spec.rb +159 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/client_spec.rb +47 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/constants_spec.rb +45 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/curiosity_engine_spec.rb +229 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/helpers/knowledge_gap_spec.rb +188 -0
- data/spec/legion/extensions/agentic/learning/epistemic_curiosity/runners/epistemic_curiosity_spec.rb +175 -0
- data/spec/legion/extensions/agentic/learning/fermentation/client_spec.rb +36 -0
- data/spec/legion/extensions/agentic/learning/fermentation/helpers/batch_spec.rb +72 -0
- data/spec/legion/extensions/agentic/learning/fermentation/helpers/fermentation_engine_spec.rb +138 -0
- data/spec/legion/extensions/agentic/learning/fermentation/helpers/substrate_spec.rb +146 -0
- data/spec/legion/extensions/agentic/learning/habit/client_spec.rb +50 -0
- data/spec/legion/extensions/agentic/learning/habit/helpers/action_sequence_spec.rb +276 -0
- data/spec/legion/extensions/agentic/learning/habit/helpers/constants_spec.rb +115 -0
- data/spec/legion/extensions/agentic/learning/habit/helpers/habit_store_spec.rb +274 -0
- data/spec/legion/extensions/agentic/learning/habit/runners/habit_spec.rb +228 -0
- data/spec/legion/extensions/agentic/learning/hebbian/client_spec.rb +38 -0
- data/spec/legion/extensions/agentic/learning/hebbian/helpers/assembly_network_spec.rb +142 -0
- data/spec/legion/extensions/agentic/learning/hebbian/helpers/assembly_spec.rb +89 -0
- data/spec/legion/extensions/agentic/learning/hebbian/helpers/unit_spec.rb +119 -0
- data/spec/legion/extensions/agentic/learning/hebbian/runners/hebbian_assembly_spec.rb +109 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/client_spec.rb +51 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/helpers/constants_spec.rb +29 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/helpers/rate_model_spec.rb +151 -0
- data/spec/legion/extensions/agentic/learning/learning_rate/runners/learning_rate_spec.rb +92 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/client_spec.rb +27 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/constants_spec.rb +43 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/learning_domain_spec.rb +146 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/meta_learning_engine_spec.rb +309 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/helpers/strategy_spec.rb +82 -0
- data/spec/legion/extensions/agentic/learning/meta_learning/runners/meta_learning_spec.rb +185 -0
- data/spec/legion/extensions/agentic/learning/plasticity/helpers/constants_spec.rb +54 -0
- data/spec/legion/extensions/agentic/learning/plasticity/helpers/neural_pathway_spec.rb +136 -0
- data/spec/legion/extensions/agentic/learning/plasticity/helpers/plasticity_engine_spec.rb +157 -0
- data/spec/legion/extensions/agentic/learning/plasticity/runners/cognitive_plasticity_spec.rb +83 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/client_spec.rb +17 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/helpers/constants_spec.rb +67 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/helpers/option_spec.rb +104 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/helpers/preference_engine_spec.rb +151 -0
- data/spec/legion/extensions/agentic/learning/preference_learning/runners/preference_learning_spec.rb +86 -0
- data/spec/legion/extensions/agentic/learning/procedural/client_spec.rb +22 -0
- data/spec/legion/extensions/agentic/learning/procedural/helpers/learning_engine_spec.rb +135 -0
- data/spec/legion/extensions/agentic/learning/procedural/helpers/production_spec.rb +66 -0
- data/spec/legion/extensions/agentic/learning/procedural/helpers/skill_spec.rb +102 -0
- data/spec/legion/extensions/agentic/learning/procedural/runners/procedural_learning_spec.rb +94 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/helpers/constants_spec.rb +36 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/helpers/scaffold_spec.rb +187 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/helpers/scaffolding_engine_spec.rb +159 -0
- data/spec/legion/extensions/agentic/learning/scaffolding/runners/cognitive_scaffolding_spec.rb +163 -0
- data/spec/spec_helper.rb +46 -0
- metadata +277 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module Catalyst
|
|
8
|
+
module Helpers
|
|
9
|
+
class CatalystEngine
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@catalysts = {}
|
|
14
|
+
@reactions = {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_catalyst(catalyst_type:, domain:, potency: 0.5, specificity: 0.5, **)
|
|
18
|
+
unless CATALYST_TYPES.include?(catalyst_type.to_sym)
|
|
19
|
+
raise ArgumentError,
|
|
20
|
+
"invalid catalyst_type: #{catalyst_type}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
evict_oldest_catalyst if @catalysts.size >= MAX_CATALYSTS
|
|
24
|
+
catalyst = Catalyst.new(
|
|
25
|
+
catalyst_type: catalyst_type.to_sym,
|
|
26
|
+
domain: domain,
|
|
27
|
+
potency: potency,
|
|
28
|
+
specificity: specificity
|
|
29
|
+
)
|
|
30
|
+
@catalysts[catalyst.id] = catalyst
|
|
31
|
+
catalyst
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create_reaction(reaction_type:, reactants:, activation_energy: ACTIVATION_ENERGY, **)
|
|
35
|
+
unless REACTION_TYPES.include?(reaction_type.to_sym)
|
|
36
|
+
raise ArgumentError,
|
|
37
|
+
"invalid reaction_type: #{reaction_type}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
evict_oldest_reaction if @reactions.size >= MAX_REACTIONS
|
|
41
|
+
reaction = Reaction.new(
|
|
42
|
+
reaction_type: reaction_type.to_sym,
|
|
43
|
+
reactants: reactants,
|
|
44
|
+
activation_energy: activation_energy
|
|
45
|
+
)
|
|
46
|
+
@reactions[reaction.id] = reaction
|
|
47
|
+
reaction
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def apply_catalyst(catalyst_id:, reaction_id:)
|
|
51
|
+
catalyst = @catalysts[catalyst_id]
|
|
52
|
+
reaction = @reactions[reaction_id]
|
|
53
|
+
|
|
54
|
+
return { success: false, reason: :catalyst_not_found } unless catalyst
|
|
55
|
+
return { success: false, reason: :reaction_not_found } unless reaction
|
|
56
|
+
return { success: false, reason: :already_completed } if reaction.complete?
|
|
57
|
+
|
|
58
|
+
reaction.apply_catalyst!(catalyst)
|
|
59
|
+
{
|
|
60
|
+
success: true,
|
|
61
|
+
activation_energy: reaction.activation_energy,
|
|
62
|
+
catalyst_id: catalyst_id,
|
|
63
|
+
reaction_id: reaction_id
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def attempt_reaction(reaction_id:, energy_input:)
|
|
68
|
+
reaction = @reactions[reaction_id]
|
|
69
|
+
return { success: false, reason: :not_found } unless reaction
|
|
70
|
+
return { success: false, reason: :already_completed } if reaction.complete?
|
|
71
|
+
|
|
72
|
+
completed = reaction.attempt!(energy_input)
|
|
73
|
+
{
|
|
74
|
+
success: true,
|
|
75
|
+
completed: completed,
|
|
76
|
+
yield_value: reaction.yield_value,
|
|
77
|
+
yield_label: reaction.yield_label,
|
|
78
|
+
catalyzed: reaction.catalyzed?,
|
|
79
|
+
activation_energy: reaction.activation_energy
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def degrade_all!
|
|
84
|
+
@catalysts.each_value(&:degrade!)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def recharge_catalyst(catalyst_id:, amount:)
|
|
88
|
+
catalyst = @catalysts[catalyst_id]
|
|
89
|
+
return { success: false, reason: :not_found } unless catalyst
|
|
90
|
+
|
|
91
|
+
catalyst.recharge!(amount)
|
|
92
|
+
{ success: true, potency: catalyst.potency, potency_label: catalyst.potency_label }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def all_catalysts
|
|
96
|
+
@catalysts.values
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def all_reactions
|
|
100
|
+
@reactions.values
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def completed_reactions
|
|
104
|
+
@reactions.values.select(&:complete?)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def catalyzed_rate
|
|
108
|
+
completed = completed_reactions
|
|
109
|
+
return 0.0 if completed.empty?
|
|
110
|
+
|
|
111
|
+
catalyzed_count = completed.count(&:catalyzed?)
|
|
112
|
+
(catalyzed_count.to_f / completed.size).round(10)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def catalyst_report
|
|
116
|
+
completed = completed_reactions
|
|
117
|
+
catalyzed_cnt = completed.count(&:catalyzed?)
|
|
118
|
+
avg_potency = if @catalysts.empty?
|
|
119
|
+
0.0
|
|
120
|
+
else
|
|
121
|
+
(@catalysts.values.sum(&:potency) / @catalysts.size).round(10)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
{
|
|
125
|
+
total_catalysts: @catalysts.size,
|
|
126
|
+
total_reactions: @reactions.size,
|
|
127
|
+
completed: completed.size,
|
|
128
|
+
catalyzed_count: catalyzed_cnt,
|
|
129
|
+
catalyzed_rate: catalyzed_rate,
|
|
130
|
+
avg_potency: avg_potency,
|
|
131
|
+
powerful_count: @catalysts.values.count(&:powerful?),
|
|
132
|
+
inert_count: @catalysts.values.count(&:inert?)
|
|
133
|
+
}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def evict_oldest_catalyst
|
|
139
|
+
oldest_id = @catalysts.min_by { |_id, c| c.created_at }&.first
|
|
140
|
+
@catalysts.delete(oldest_id) if oldest_id
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def evict_oldest_reaction
|
|
144
|
+
oldest_id = @reactions.min_by { |_id, r| r.created_at }&.first
|
|
145
|
+
@reactions.delete(oldest_id) if oldest_id
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module Catalyst
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
# Catalyst types — categories of experiences/insights that accelerate reactions
|
|
11
|
+
CATALYST_TYPES = %i[experience insight analogy pattern emotion].freeze
|
|
12
|
+
|
|
13
|
+
# Reaction types — categories of cognitive transformations
|
|
14
|
+
REACTION_TYPES = %i[synthesis decomposition exchange neutralization precipitation].freeze
|
|
15
|
+
|
|
16
|
+
# Storage limits
|
|
17
|
+
MAX_CATALYSTS = 500
|
|
18
|
+
MAX_REACTIONS = 200
|
|
19
|
+
|
|
20
|
+
# Activation energy — minimum energy to complete a reaction without a catalyst
|
|
21
|
+
ACTIVATION_ENERGY = 0.6
|
|
22
|
+
|
|
23
|
+
# How much a catalyst lowers the activation energy threshold
|
|
24
|
+
CATALYST_REDUCTION = 0.3
|
|
25
|
+
|
|
26
|
+
# Potency degradation rate from environmental wear (not from use)
|
|
27
|
+
POTENCY_DECAY = 0.02
|
|
28
|
+
|
|
29
|
+
# Bonus added when catalyst specificity matches reaction domain
|
|
30
|
+
SPECIFICITY_BONUS = 0.15
|
|
31
|
+
|
|
32
|
+
# Potency labels — range-based classification of catalyst strength
|
|
33
|
+
POTENCY_LABELS = {
|
|
34
|
+
(0.8..) => :powerful,
|
|
35
|
+
(0.6...0.8) => :strong,
|
|
36
|
+
(0.4...0.6) => :moderate,
|
|
37
|
+
(0.2...0.4) => :weak,
|
|
38
|
+
(..0.2) => :inert
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
# Yield labels — range-based classification of reaction output quality
|
|
42
|
+
YIELD_LABELS = {
|
|
43
|
+
(0.8..) => :excellent,
|
|
44
|
+
(0.6...0.8) => :good,
|
|
45
|
+
(0.4...0.6) => :fair,
|
|
46
|
+
(0.2...0.4) => :poor,
|
|
47
|
+
(..0.2) => :negligible
|
|
48
|
+
}.freeze
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Learning
|
|
9
|
+
module Catalyst
|
|
10
|
+
module Helpers
|
|
11
|
+
class Reaction
|
|
12
|
+
include Constants
|
|
13
|
+
|
|
14
|
+
attr_reader :id, :reaction_type, :reactants, :activation_energy,
|
|
15
|
+
:yield_value, :catalyzed, :catalyst_id, :completed, :created_at
|
|
16
|
+
|
|
17
|
+
def initialize(reaction_type:, reactants:, activation_energy: ACTIVATION_ENERGY)
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@reaction_type = reaction_type
|
|
20
|
+
@reactants = Array(reactants)
|
|
21
|
+
@activation_energy = activation_energy.clamp(0.0, 1.0)
|
|
22
|
+
@yield_value = 0.0
|
|
23
|
+
@catalyzed = false
|
|
24
|
+
@catalyst_id = nil
|
|
25
|
+
@completed = false
|
|
26
|
+
@created_at = Time.now.utc
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Apply a catalyst to lower the activation energy threshold
|
|
30
|
+
def apply_catalyst!(catalyst)
|
|
31
|
+
reduction = catalyst.catalyze!(@reaction_type)
|
|
32
|
+
@activation_energy = (@activation_energy - reduction).clamp(0.0, 1.0).round(10)
|
|
33
|
+
@catalyzed = true
|
|
34
|
+
@catalyst_id = catalyst.id
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Attempt to complete the reaction with given energy input
|
|
38
|
+
# Completes if energy_input >= activation_energy; yield based on energy surplus
|
|
39
|
+
def attempt!(energy_input)
|
|
40
|
+
return false if @completed
|
|
41
|
+
return false if energy_input < @activation_energy
|
|
42
|
+
|
|
43
|
+
@completed = true
|
|
44
|
+
surplus = (energy_input - @activation_energy).clamp(0.0, 1.0)
|
|
45
|
+
@yield_value = (0.5 + (surplus * 0.5)).clamp(0.0, 1.0).round(10)
|
|
46
|
+
true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def complete?
|
|
50
|
+
@completed
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def catalyzed?
|
|
54
|
+
@catalyzed
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Completed spontaneously — without a catalyst
|
|
58
|
+
def spontaneous?
|
|
59
|
+
@completed && !@catalyzed
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def yield_label
|
|
63
|
+
YIELD_LABELS.find { |range, _| range.cover?(@yield_value) }&.last || :negligible
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def to_h
|
|
67
|
+
{
|
|
68
|
+
id: @id,
|
|
69
|
+
reaction_type: @reaction_type,
|
|
70
|
+
reactants: @reactants,
|
|
71
|
+
activation_energy: @activation_energy,
|
|
72
|
+
yield_value: @yield_value,
|
|
73
|
+
yield_label: yield_label,
|
|
74
|
+
catalyzed: @catalyzed,
|
|
75
|
+
catalyst_id: @catalyst_id,
|
|
76
|
+
completed: @completed,
|
|
77
|
+
spontaneous: spontaneous?,
|
|
78
|
+
created_at: @created_at
|
|
79
|
+
}
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module Catalyst
|
|
8
|
+
module Runners
|
|
9
|
+
module CognitiveCatalyst
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def create_catalyst(catalyst_type:, domain:, potency: nil, specificity: nil, engine: nil, **)
|
|
14
|
+
e = engine || default_engine
|
|
15
|
+
raise ArgumentError, "invalid catalyst_type: #{catalyst_type}" unless Helpers::Constants::CATALYST_TYPES.include?(catalyst_type.to_sym)
|
|
16
|
+
|
|
17
|
+
opts = {
|
|
18
|
+
catalyst_type: catalyst_type.to_sym,
|
|
19
|
+
domain: domain
|
|
20
|
+
}
|
|
21
|
+
opts[:potency] = potency unless potency.nil?
|
|
22
|
+
opts[:specificity] = specificity unless specificity.nil?
|
|
23
|
+
|
|
24
|
+
catalyst = e.create_catalyst(**opts)
|
|
25
|
+
Legion::Logging.debug "[cognitive_catalyst] create_catalyst id=#{catalyst.id[0..7]} " \
|
|
26
|
+
"type=#{catalyst_type} domain=#{domain} potency=#{catalyst.potency.round(2)}"
|
|
27
|
+
{ success: true, catalyst: catalyst.to_h }
|
|
28
|
+
rescue ArgumentError => e
|
|
29
|
+
Legion::Logging.warn "[cognitive_catalyst] create_catalyst failed: #{e.message}"
|
|
30
|
+
{ success: false, reason: e.message }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def create_reaction(reaction_type:, reactants:, activation_energy: nil, engine: nil, **)
|
|
34
|
+
e = engine || default_engine
|
|
35
|
+
raise ArgumentError, "invalid reaction_type: #{reaction_type}" unless Helpers::Constants::REACTION_TYPES.include?(reaction_type.to_sym)
|
|
36
|
+
|
|
37
|
+
opts = {
|
|
38
|
+
reaction_type: reaction_type.to_sym,
|
|
39
|
+
reactants: Array(reactants)
|
|
40
|
+
}
|
|
41
|
+
opts[:activation_energy] = activation_energy unless activation_energy.nil?
|
|
42
|
+
|
|
43
|
+
reaction = e.create_reaction(**opts)
|
|
44
|
+
Legion::Logging.debug "[cognitive_catalyst] create_reaction id=#{reaction.id[0..7]} " \
|
|
45
|
+
"type=#{reaction_type} reactants=#{reaction.reactants.size}"
|
|
46
|
+
{ success: true, reaction: reaction.to_h }
|
|
47
|
+
rescue ArgumentError => e
|
|
48
|
+
Legion::Logging.warn "[cognitive_catalyst] create_reaction failed: #{e.message}"
|
|
49
|
+
{ success: false, reason: e.message }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def apply_catalyst(catalyst_id:, reaction_id:, engine: nil, **)
|
|
53
|
+
e = engine || default_engine
|
|
54
|
+
result = e.apply_catalyst(catalyst_id: catalyst_id, reaction_id: reaction_id)
|
|
55
|
+
Legion::Logging.debug '[cognitive_catalyst] apply_catalyst ' \
|
|
56
|
+
"catalyst=#{catalyst_id[0..7]} reaction=#{reaction_id[0..7]} " \
|
|
57
|
+
"success=#{result[:success]}"
|
|
58
|
+
result
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def attempt_reaction(reaction_id:, energy_input:, engine: nil, **)
|
|
62
|
+
e = engine || default_engine
|
|
63
|
+
result = e.attempt_reaction(reaction_id: reaction_id, energy_input: energy_input)
|
|
64
|
+
Legion::Logging.debug "[cognitive_catalyst] attempt_reaction id=#{reaction_id[0..7]} " \
|
|
65
|
+
"energy=#{energy_input} completed=#{result[:completed]}"
|
|
66
|
+
result
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def recharge(catalyst_id:, amount:, engine: nil, **)
|
|
70
|
+
e = engine || default_engine
|
|
71
|
+
result = e.recharge_catalyst(catalyst_id: catalyst_id, amount: amount)
|
|
72
|
+
Legion::Logging.debug "[cognitive_catalyst] recharge id=#{catalyst_id[0..7]} " \
|
|
73
|
+
"amount=#{amount} potency=#{result[:potency]&.round(2)}"
|
|
74
|
+
result
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def list_catalysts(engine: nil, **)
|
|
78
|
+
e = engine || default_engine
|
|
79
|
+
catalysts = e.all_catalysts
|
|
80
|
+
Legion::Logging.debug "[cognitive_catalyst] list_catalysts count=#{catalysts.size}"
|
|
81
|
+
{ success: true, catalysts: catalysts.map(&:to_h), count: catalysts.size }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def catalyst_status(engine: nil, **)
|
|
85
|
+
e = engine || default_engine
|
|
86
|
+
report = e.catalyst_report
|
|
87
|
+
Legion::Logging.debug "[cognitive_catalyst] catalyst_status total=#{report[:total_catalysts]} " \
|
|
88
|
+
"reactions=#{report[:total_reactions]} rate=#{report[:catalyzed_rate].round(2)}"
|
|
89
|
+
{ success: true }.merge(report)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def default_engine
|
|
95
|
+
@default_engine ||= Helpers::CatalystEngine.new
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
require_relative 'catalyst/version'
|
|
6
|
+
require_relative 'catalyst/helpers/constants'
|
|
7
|
+
require_relative 'catalyst/helpers/catalyst'
|
|
8
|
+
require_relative 'catalyst/helpers/reaction'
|
|
9
|
+
require_relative 'catalyst/helpers/catalyst_engine'
|
|
10
|
+
require_relative 'catalyst/runners/cognitive_catalyst'
|
|
11
|
+
require_relative 'catalyst/client'
|
|
12
|
+
|
|
13
|
+
module Legion
|
|
14
|
+
module Extensions
|
|
15
|
+
module Agentic
|
|
16
|
+
module Learning
|
|
17
|
+
module Catalyst
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Learning
|
|
7
|
+
module Chrysalis
|
|
8
|
+
class Client
|
|
9
|
+
include Runners::CognitiveChrysalis
|
|
10
|
+
|
|
11
|
+
attr_reader :engine
|
|
12
|
+
|
|
13
|
+
def initialize(**)
|
|
14
|
+
@engine = Helpers::MetamorphosisEngine.new
|
|
15
|
+
@default_engine = @engine
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Learning
|
|
9
|
+
module Chrysalis
|
|
10
|
+
module Helpers
|
|
11
|
+
class Chrysalis
|
|
12
|
+
attr_reader :id, :chrysalis_type, :content, :stage,
|
|
13
|
+
:transformation_progress, :protection, :beauty, :created_at
|
|
14
|
+
|
|
15
|
+
def initialize(chrysalis_type:, content:, **)
|
|
16
|
+
@id = SecureRandom.uuid
|
|
17
|
+
@chrysalis_type = chrysalis_type.to_sym
|
|
18
|
+
@content = content.to_s
|
|
19
|
+
@stage = :larva
|
|
20
|
+
@transformation_progress = 0.0
|
|
21
|
+
@protection = 0.8
|
|
22
|
+
@beauty = 0.0
|
|
23
|
+
@created_at = Time.now.utc
|
|
24
|
+
@premature = false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def spin!
|
|
28
|
+
raise ArgumentError, "must be :larva to spin, currently #{@stage}" unless @stage == :larva
|
|
29
|
+
|
|
30
|
+
@stage = :spinning
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def cocoon!
|
|
35
|
+
raise ArgumentError, "must be :spinning to cocoon, currently #{@stage}" unless @stage == :spinning
|
|
36
|
+
|
|
37
|
+
@stage = :cocooned
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def transform!(rate = Helpers::Constants::TRANSFORMATION_RATE)
|
|
42
|
+
return false if @stage == :butterfly
|
|
43
|
+
|
|
44
|
+
@transformation_progress = (@transformation_progress + rate).clamp(0.0, 1.0).round(10)
|
|
45
|
+
@beauty = (@transformation_progress * 0.9).clamp(0.0, 1.0).round(10)
|
|
46
|
+
update_stage_from_progress!
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def emerge!(force: false)
|
|
51
|
+
if @transformation_progress >= Helpers::Constants::EMERGENCE_THRESHOLD
|
|
52
|
+
@stage = :butterfly
|
|
53
|
+
@beauty = 1.0
|
|
54
|
+
elsif force
|
|
55
|
+
@premature = true
|
|
56
|
+
@stage = :butterfly
|
|
57
|
+
@beauty = (@beauty - Helpers::Constants::PREMATURE_PENALTY).clamp(0.0, 1.0).round(10)
|
|
58
|
+
else
|
|
59
|
+
return false
|
|
60
|
+
end
|
|
61
|
+
true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def decay_protection!
|
|
65
|
+
@protection = (@protection - Helpers::Constants::PROTECTION_DECAY).clamp(0.0, 1.0).round(10)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def disturb!(force)
|
|
69
|
+
@protection = (@protection - force.to_f).clamp(0.0, 1.0).round(10)
|
|
70
|
+
emerge!(force: true) if @protection <= 0 && %i[cocooned transforming].include?(@stage)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def butterfly?
|
|
74
|
+
@stage == :butterfly
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def cocooned?
|
|
78
|
+
@stage == :cocooned
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def transforming?
|
|
82
|
+
@stage == :transforming
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def premature?
|
|
86
|
+
butterfly? && @beauty < 0.5
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def stage_label
|
|
90
|
+
Helpers::Constants.label_for(Helpers::Constants::STAGE_LABELS, @transformation_progress)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def beauty_label
|
|
94
|
+
Helpers::Constants.label_for(Helpers::Constants::BEAUTY_LABELS, @beauty)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_h
|
|
98
|
+
{
|
|
99
|
+
id: @id,
|
|
100
|
+
chrysalis_type: @chrysalis_type,
|
|
101
|
+
content: @content,
|
|
102
|
+
stage: @stage,
|
|
103
|
+
transformation_progress: @transformation_progress,
|
|
104
|
+
protection: @protection,
|
|
105
|
+
beauty: @beauty,
|
|
106
|
+
stage_label: stage_label,
|
|
107
|
+
beauty_label: beauty_label,
|
|
108
|
+
premature: @premature,
|
|
109
|
+
created_at: @created_at
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def update_stage_from_progress!
|
|
116
|
+
progress_stage = if @transformation_progress >= 0.8
|
|
117
|
+
:emerging
|
|
118
|
+
elsif @transformation_progress >= 0.6
|
|
119
|
+
:transforming
|
|
120
|
+
elsif @transformation_progress >= 0.4
|
|
121
|
+
:cocooned
|
|
122
|
+
elsif @transformation_progress >= 0.2
|
|
123
|
+
:spinning
|
|
124
|
+
else
|
|
125
|
+
:larva
|
|
126
|
+
end
|
|
127
|
+
current_rank = Helpers::Constants::LIFE_STAGES.index(@stage) || 0
|
|
128
|
+
progress_rank = Helpers::Constants::LIFE_STAGES.index(progress_stage) || 0
|
|
129
|
+
@stage = Helpers::Constants::LIFE_STAGES[[current_rank, progress_rank].max]
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Learning
|
|
9
|
+
module Chrysalis
|
|
10
|
+
module Helpers
|
|
11
|
+
class Cocoon
|
|
12
|
+
attr_reader :id, :environment, :temperature, :humidity, :chrysalis_ids, :created_at
|
|
13
|
+
|
|
14
|
+
TEMP_ADJUST = 0.05
|
|
15
|
+
HUMID_ADJUST = 0.05
|
|
16
|
+
|
|
17
|
+
def initialize(environment:, temperature: 0.5, humidity: 0.5, **)
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@environment = environment.to_s
|
|
20
|
+
@temperature = temperature.to_f.clamp(0.0, 1.0)
|
|
21
|
+
@humidity = humidity.to_f.clamp(0.0, 1.0)
|
|
22
|
+
@chrysalis_ids = []
|
|
23
|
+
@created_at = Time.now.utc
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def shelter(chrysalis_id)
|
|
27
|
+
@chrysalis_ids << chrysalis_id unless @chrysalis_ids.include?(chrysalis_id)
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def expose(chrysalis_id)
|
|
32
|
+
@chrysalis_ids.delete(chrysalis_id)
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def warm!
|
|
37
|
+
@temperature = (@temperature + TEMP_ADJUST).clamp(0.0, 1.0).round(10)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def cool!
|
|
41
|
+
@temperature = (@temperature - TEMP_ADJUST).clamp(0.0, 1.0).round(10)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def moisten!
|
|
45
|
+
@humidity = (@humidity + HUMID_ADJUST).clamp(0.0, 1.0).round(10)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def dry!
|
|
49
|
+
@humidity = (@humidity - HUMID_ADJUST).clamp(0.0, 1.0).round(10)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def ideal?
|
|
53
|
+
@temperature.between?(0.4, 0.7) && @humidity.between?(0.4, 0.7)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def hostile?
|
|
57
|
+
@temperature > 0.9 || @humidity < 0.1
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def growth_modifier
|
|
61
|
+
if ideal?
|
|
62
|
+
0.1
|
|
63
|
+
elsif hostile?
|
|
64
|
+
-0.05
|
|
65
|
+
else
|
|
66
|
+
0.0
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_h
|
|
71
|
+
{
|
|
72
|
+
id: @id,
|
|
73
|
+
environment: @environment,
|
|
74
|
+
temperature: @temperature,
|
|
75
|
+
humidity: @humidity,
|
|
76
|
+
chrysalis_ids: @chrysalis_ids.dup,
|
|
77
|
+
ideal: ideal?,
|
|
78
|
+
hostile: hostile?,
|
|
79
|
+
growth_modifier: growth_modifier,
|
|
80
|
+
created_at: @created_at
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|