lex-agentic-affect 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-affect.gemspec +30 -0
- data/lib/legion/extensions/agentic/affect/appraisal/client.rb +20 -0
- data/lib/legion/extensions/agentic/affect/appraisal/helpers/appraisal.rb +112 -0
- data/lib/legion/extensions/agentic/affect/appraisal/helpers/appraisal_engine.rb +129 -0
- data/lib/legion/extensions/agentic/affect/appraisal/helpers/constants.rb +43 -0
- data/lib/legion/extensions/agentic/affect/appraisal/runners/appraisal.rb +105 -0
- data/lib/legion/extensions/agentic/affect/appraisal/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/appraisal.rb +19 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/client.rb +19 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/helpers/constants.rb +37 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/helpers/empathy_engine.rb +151 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/helpers/perspective.rb +92 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/runners/cognitive_empathy.rb +93 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy.rb +20 -0
- data/lib/legion/extensions/agentic/affect/contagion/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/contagion/helpers/constants.rb +34 -0
- data/lib/legion/extensions/agentic/affect/contagion/helpers/contagion_engine.rb +184 -0
- data/lib/legion/extensions/agentic/affect/contagion/helpers/meme.rb +97 -0
- data/lib/legion/extensions/agentic/affect/contagion/runners/cognitive_contagion.rb +125 -0
- data/lib/legion/extensions/agentic/affect/contagion/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/contagion.rb +19 -0
- data/lib/legion/extensions/agentic/affect/defusion/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/defusion/helpers/constants.rb +64 -0
- data/lib/legion/extensions/agentic/affect/defusion/helpers/defusion_engine.rb +167 -0
- data/lib/legion/extensions/agentic/affect/defusion/helpers/thought.rb +92 -0
- data/lib/legion/extensions/agentic/affect/defusion/runners/cognitive_defusion.rb +127 -0
- data/lib/legion/extensions/agentic/affect/defusion/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/defusion.rb +19 -0
- data/lib/legion/extensions/agentic/affect/emotion/actors/momentum_decay.rb +45 -0
- data/lib/legion/extensions/agentic/affect/emotion/client.rb +36 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/baseline.rb +52 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/momentum.rb +52 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/valence.rb +92 -0
- data/lib/legion/extensions/agentic/affect/emotion/runners/gut.rb +102 -0
- data/lib/legion/extensions/agentic/affect/emotion/runners/valence.rb +120 -0
- data/lib/legion/extensions/agentic/affect/emotion/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/emotion.rb +20 -0
- data/lib/legion/extensions/agentic/affect/empathy/client.rb +21 -0
- data/lib/legion/extensions/agentic/affect/empathy/helpers/constants.rb +54 -0
- data/lib/legion/extensions/agentic/affect/empathy/helpers/mental_model.rb +185 -0
- data/lib/legion/extensions/agentic/affect/empathy/helpers/model_store.rb +88 -0
- data/lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb +173 -0
- data/lib/legion/extensions/agentic/affect/empathy/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/empathy.rb +20 -0
- data/lib/legion/extensions/agentic/affect/fatigue/client.rb +26 -0
- data/lib/legion/extensions/agentic/affect/fatigue/helpers/constants.rb +54 -0
- data/lib/legion/extensions/agentic/affect/fatigue/helpers/energy_model.rb +181 -0
- data/lib/legion/extensions/agentic/affect/fatigue/helpers/fatigue_store.rb +146 -0
- data/lib/legion/extensions/agentic/affect/fatigue/runners/fatigue.rb +89 -0
- data/lib/legion/extensions/agentic/affect/fatigue/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/fatigue.rb +19 -0
- data/lib/legion/extensions/agentic/affect/flow/client.rb +25 -0
- data/lib/legion/extensions/agentic/affect/flow/helpers/constants.rb +84 -0
- data/lib/legion/extensions/agentic/affect/flow/helpers/flow_detector.rb +166 -0
- data/lib/legion/extensions/agentic/affect/flow/runners/flow.rb +129 -0
- data/lib/legion/extensions/agentic/affect/flow/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/flow.rb +18 -0
- data/lib/legion/extensions/agentic/affect/interoception/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/affect/interoception/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/interoception/helpers/body_budget.rb +152 -0
- data/lib/legion/extensions/agentic/affect/interoception/helpers/constants.rb +68 -0
- data/lib/legion/extensions/agentic/affect/interoception/helpers/somatic_marker.rb +75 -0
- data/lib/legion/extensions/agentic/affect/interoception/runners/interoception.rb +101 -0
- data/lib/legion/extensions/agentic/affect/interoception/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/interoception.rb +20 -0
- data/lib/legion/extensions/agentic/affect/mood/client.rb +21 -0
- data/lib/legion/extensions/agentic/affect/mood/helpers/constants.rb +78 -0
- data/lib/legion/extensions/agentic/affect/mood/helpers/mood_state.rb +154 -0
- data/lib/legion/extensions/agentic/affect/mood/runners/mood.rb +122 -0
- data/lib/legion/extensions/agentic/affect/mood/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/mood.rb +18 -0
- data/lib/legion/extensions/agentic/affect/motivation/client.rb +26 -0
- data/lib/legion/extensions/agentic/affect/motivation/helpers/constants.rb +48 -0
- data/lib/legion/extensions/agentic/affect/motivation/helpers/drive_state.rb +98 -0
- data/lib/legion/extensions/agentic/affect/motivation/helpers/motivation_store.rb +106 -0
- data/lib/legion/extensions/agentic/affect/motivation/runners/motivation.rb +165 -0
- data/lib/legion/extensions/agentic/affect/motivation/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/motivation.rb +19 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/actors/auto_regulate.rb +45 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/constants.rb +82 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/emotional_event.rb +98 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/llm_enhancer.rb +88 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/reappraisal_engine.rb +153 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/runners/cognitive_reappraisal.rb +164 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/reappraisal.rb +20 -0
- data/lib/legion/extensions/agentic/affect/regulation/client.rb +25 -0
- data/lib/legion/extensions/agentic/affect/regulation/helpers/constants.rb +71 -0
- data/lib/legion/extensions/agentic/affect/regulation/helpers/regulation_model.rb +175 -0
- data/lib/legion/extensions/agentic/affect/regulation/runners/emotional_regulation.rb +127 -0
- data/lib/legion/extensions/agentic/affect/regulation/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/regulation.rb +18 -0
- data/lib/legion/extensions/agentic/affect/resilience/client.rb +27 -0
- data/lib/legion/extensions/agentic/affect/resilience/helpers/adversity_tracker.rb +130 -0
- data/lib/legion/extensions/agentic/affect/resilience/helpers/constants.rb +79 -0
- data/lib/legion/extensions/agentic/affect/resilience/helpers/resilience_model.rb +165 -0
- data/lib/legion/extensions/agentic/affect/resilience/runners/resilience.rb +150 -0
- data/lib/legion/extensions/agentic/affect/resilience/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/resilience.rb +19 -0
- data/lib/legion/extensions/agentic/affect/resonance/client.rb +24 -0
- data/lib/legion/extensions/agentic/affect/resonance/helpers/category.rb +75 -0
- data/lib/legion/extensions/agentic/affect/resonance/helpers/constants.rb +47 -0
- data/lib/legion/extensions/agentic/affect/resonance/helpers/resonance_engine.rb +115 -0
- data/lib/legion/extensions/agentic/affect/resonance/runners/cognitive_resonance.rb +94 -0
- data/lib/legion/extensions/agentic/affect/resonance/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/resonance.rb +19 -0
- data/lib/legion/extensions/agentic/affect/reward/client.rb +26 -0
- data/lib/legion/extensions/agentic/affect/reward/helpers/constants.rb +67 -0
- data/lib/legion/extensions/agentic/affect/reward/helpers/reward_signal.rb +178 -0
- data/lib/legion/extensions/agentic/affect/reward/helpers/reward_store.rb +142 -0
- data/lib/legion/extensions/agentic/affect/reward/runners/reward.rb +92 -0
- data/lib/legion/extensions/agentic/affect/reward/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/reward.rb +19 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/client.rb +29 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/body_state.rb +69 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/constants.rb +43 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/marker_store.rb +160 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/somatic_marker.rb +74 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/runners/somatic_marker.rb +132 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker.rb +20 -0
- data/lib/legion/extensions/agentic/affect/version.rb +11 -0
- data/lib/legion/extensions/agentic/affect.rb +34 -0
- data/spec/legion/extensions/agentic/affect/appraisal/client_spec.rb +52 -0
- data/spec/legion/extensions/agentic/affect/appraisal/helpers/appraisal_engine_spec.rb +161 -0
- data/spec/legion/extensions/agentic/affect/appraisal/helpers/appraisal_spec.rb +175 -0
- data/spec/legion/extensions/agentic/affect/appraisal/helpers/constants_spec.rb +49 -0
- data/spec/legion/extensions/agentic/affect/appraisal/runners/appraisal_spec.rb +116 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/client_spec.rb +62 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/helpers/empathy_engine_spec.rb +316 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/helpers/perspective_spec.rb +132 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/runners/cognitive_empathy_spec.rb +200 -0
- data/spec/legion/extensions/agentic/affect/contagion/client_spec.rb +63 -0
- data/spec/legion/extensions/agentic/affect/contagion/helpers/constants_spec.rb +86 -0
- data/spec/legion/extensions/agentic/affect/contagion/helpers/contagion_engine_spec.rb +241 -0
- data/spec/legion/extensions/agentic/affect/contagion/helpers/meme_spec.rb +160 -0
- data/spec/legion/extensions/agentic/affect/contagion/runners/cognitive_contagion_spec.rb +211 -0
- data/spec/legion/extensions/agentic/affect/defusion/client_spec.rb +80 -0
- data/spec/legion/extensions/agentic/affect/defusion/helpers/constants_spec.rb +84 -0
- data/spec/legion/extensions/agentic/affect/defusion/helpers/defusion_engine_spec.rb +250 -0
- data/spec/legion/extensions/agentic/affect/defusion/helpers/thought_spec.rb +178 -0
- data/spec/legion/extensions/agentic/affect/defusion/runners/cognitive_defusion_spec.rb +185 -0
- data/spec/legion/extensions/agentic/affect/emotion/actors/momentum_decay_spec.rb +46 -0
- data/spec/legion/extensions/agentic/affect/emotion/client_spec.rb +46 -0
- data/spec/legion/extensions/agentic/affect/emotion/helpers/baseline_spec.rb +48 -0
- data/spec/legion/extensions/agentic/affect/emotion/helpers/momentum_spec.rb +45 -0
- data/spec/legion/extensions/agentic/affect/emotion/helpers/valence_spec.rb +91 -0
- data/spec/legion/extensions/agentic/affect/emotion/runners/gut_spec.rb +73 -0
- data/spec/legion/extensions/agentic/affect/emotion/runners/valence_spec.rb +67 -0
- data/spec/legion/extensions/agentic/affect/empathy/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/affect/empathy/helpers/constants_spec.rb +23 -0
- data/spec/legion/extensions/agentic/affect/empathy/helpers/mental_model_spec.rb +150 -0
- data/spec/legion/extensions/agentic/affect/empathy/helpers/model_store_spec.rb +94 -0
- data/spec/legion/extensions/agentic/affect/empathy/runners/empathy_spec.rb +127 -0
- data/spec/legion/extensions/agentic/affect/fatigue/client_spec.rb +66 -0
- data/spec/legion/extensions/agentic/affect/fatigue/helpers/constants_spec.rb +130 -0
- data/spec/legion/extensions/agentic/affect/fatigue/helpers/energy_model_spec.rb +281 -0
- data/spec/legion/extensions/agentic/affect/fatigue/helpers/fatigue_store_spec.rb +157 -0
- data/spec/legion/extensions/agentic/affect/fatigue/runners/fatigue_spec.rb +127 -0
- data/spec/legion/extensions/agentic/affect/flow/client_spec.rb +58 -0
- data/spec/legion/extensions/agentic/affect/flow/helpers/constants_spec.rb +112 -0
- data/spec/legion/extensions/agentic/affect/flow/helpers/flow_detector_spec.rb +268 -0
- data/spec/legion/extensions/agentic/affect/flow/runners/flow_spec.rb +222 -0
- data/spec/legion/extensions/agentic/affect/interoception/client_spec.rb +52 -0
- data/spec/legion/extensions/agentic/affect/interoception/helpers/body_budget_spec.rb +178 -0
- data/spec/legion/extensions/agentic/affect/interoception/helpers/somatic_marker_spec.rb +120 -0
- data/spec/legion/extensions/agentic/affect/interoception/runners/interoception_spec.rb +108 -0
- data/spec/legion/extensions/agentic/affect/mood/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/affect/mood/helpers/constants_spec.rb +29 -0
- data/spec/legion/extensions/agentic/affect/mood/helpers/mood_state_spec.rb +94 -0
- data/spec/legion/extensions/agentic/affect/mood/runners/mood_spec.rb +71 -0
- data/spec/legion/extensions/agentic/affect/motivation/client_spec.rb +35 -0
- data/spec/legion/extensions/agentic/affect/motivation/helpers/constants_spec.rb +111 -0
- data/spec/legion/extensions/agentic/affect/motivation/helpers/drive_state_spec.rb +183 -0
- data/spec/legion/extensions/agentic/affect/motivation/helpers/motivation_store_spec.rb +185 -0
- data/spec/legion/extensions/agentic/affect/motivation/runners/motivation_spec.rb +248 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/actors/auto_regulate_spec.rb +46 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/client_spec.rb +64 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/constants_spec.rb +102 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/emotional_event_spec.rb +177 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/llm_enhancer_spec.rb +161 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/reappraisal_engine_spec.rb +211 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/runners/cognitive_reappraisal_spec.rb +312 -0
- data/spec/legion/extensions/agentic/affect/regulation/client_spec.rb +61 -0
- data/spec/legion/extensions/agentic/affect/regulation/helpers/constants_spec.rb +108 -0
- data/spec/legion/extensions/agentic/affect/regulation/helpers/regulation_model_spec.rb +200 -0
- data/spec/legion/extensions/agentic/affect/regulation/runners/emotional_regulation_spec.rb +190 -0
- data/spec/legion/extensions/agentic/affect/resilience/client_spec.rb +36 -0
- data/spec/legion/extensions/agentic/affect/resilience/helpers/adversity_tracker_spec.rb +164 -0
- data/spec/legion/extensions/agentic/affect/resilience/helpers/constants_spec.rb +78 -0
- data/spec/legion/extensions/agentic/affect/resilience/helpers/resilience_model_spec.rb +133 -0
- data/spec/legion/extensions/agentic/affect/resilience/runners/resilience_spec.rb +150 -0
- data/spec/legion/extensions/agentic/affect/resonance/client_spec.rb +66 -0
- data/spec/legion/extensions/agentic/affect/resonance/cognitive_resonance_spec.rb +27 -0
- data/spec/legion/extensions/agentic/affect/resonance/helpers/category_spec.rb +146 -0
- data/spec/legion/extensions/agentic/affect/resonance/helpers/constants_spec.rb +104 -0
- data/spec/legion/extensions/agentic/affect/resonance/helpers/resonance_engine_spec.rb +189 -0
- data/spec/legion/extensions/agentic/affect/resonance/runners/cognitive_resonance_spec.rb +197 -0
- data/spec/legion/extensions/agentic/affect/reward/client_spec.rb +42 -0
- data/spec/legion/extensions/agentic/affect/reward/helpers/constants_spec.rb +91 -0
- data/spec/legion/extensions/agentic/affect/reward/helpers/reward_signal_spec.rb +296 -0
- data/spec/legion/extensions/agentic/affect/reward/helpers/reward_store_spec.rb +167 -0
- data/spec/legion/extensions/agentic/affect/reward/runners/reward_spec.rb +149 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/client_spec.rb +83 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/helpers/body_state_spec.rb +155 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/helpers/marker_store_spec.rb +233 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/helpers/somatic_marker_spec.rb +172 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/runners/somatic_marker_spec.rb +181 -0
- data/spec/spec_helper.rb +46 -0
- metadata +302 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Motivation
|
|
8
|
+
module Helpers
|
|
9
|
+
class DriveState
|
|
10
|
+
attr_reader :drives
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@drives = Constants::DRIVE_TYPES.to_h do |type|
|
|
14
|
+
[type, { level: 0.5, satisfied: false, last_signal: nil }]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def update_drive(type, signal)
|
|
19
|
+
return unless Constants::DRIVE_TYPES.include?(type)
|
|
20
|
+
|
|
21
|
+
clamped = signal.clamp(0.0, 1.0)
|
|
22
|
+
current = @drives[type][:level]
|
|
23
|
+
@drives[type][:level] = ema(current, clamped, Constants::DRIVE_ALPHA)
|
|
24
|
+
@drives[type][:satisfied] = @drives[type][:level] >= 0.6
|
|
25
|
+
@drives[type][:last_signal] = Time.now.utc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def drive_level(type)
|
|
29
|
+
return 0.0 unless Constants::DRIVE_TYPES.include?(type)
|
|
30
|
+
|
|
31
|
+
@drives[type][:level]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def satisfied?(type)
|
|
35
|
+
return false unless Constants::DRIVE_TYPES.include?(type)
|
|
36
|
+
|
|
37
|
+
@drives[type][:satisfied]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def intrinsic_average
|
|
41
|
+
levels = Constants::INTRINSIC_DRIVES.map { |d| @drives[d][:level] }
|
|
42
|
+
mean(levels)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def extrinsic_average
|
|
46
|
+
levels = Constants::EXTRINSIC_DRIVES.map { |d| @drives[d][:level] }
|
|
47
|
+
mean(levels)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def overall_level
|
|
51
|
+
all_levels = @drives.values.map { |d| d[:level] }
|
|
52
|
+
mean(all_levels)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def current_mode
|
|
56
|
+
level = overall_level
|
|
57
|
+
if level >= Constants::APPROACH_THRESHOLD
|
|
58
|
+
:approach
|
|
59
|
+
elsif level <= Constants::BURNOUT_THRESHOLD
|
|
60
|
+
:dormant
|
|
61
|
+
elsif level <= Constants::AVOIDANCE_THRESHOLD
|
|
62
|
+
:avoidance
|
|
63
|
+
else
|
|
64
|
+
:maintenance
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def decay_all
|
|
69
|
+
@drives.each_key do |type|
|
|
70
|
+
current = @drives[type][:level]
|
|
71
|
+
decayed = [current - Constants::DRIVE_DECAY_RATE, 0.0].max
|
|
72
|
+
@drives[type][:level] = decayed
|
|
73
|
+
@drives[type][:satisfied] = decayed >= 0.6
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def amotivated?
|
|
78
|
+
@drives.values.all? { |d| d[:level] < Constants::AMOTIVATION_THRESHOLD }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def ema(current, observed, alpha)
|
|
84
|
+
(current * (1.0 - alpha)) + (observed * alpha)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def mean(values)
|
|
88
|
+
return 0.0 if values.empty?
|
|
89
|
+
|
|
90
|
+
values.sum / values.size.to_f
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Motivation
|
|
8
|
+
module Helpers
|
|
9
|
+
class MotivationStore
|
|
10
|
+
attr_reader :drive_state, :goal_motivations
|
|
11
|
+
|
|
12
|
+
def initialize(drive_state: nil)
|
|
13
|
+
@drive_state = drive_state || DriveState.new
|
|
14
|
+
@goal_motivations = {}
|
|
15
|
+
@low_motivation_ticks = 0
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def commit_goal(goal_id, drives)
|
|
19
|
+
valid_drives = Array(drives).select { |d| Constants::DRIVE_TYPES.include?(d) }
|
|
20
|
+
return false if valid_drives.empty?
|
|
21
|
+
|
|
22
|
+
trim_goals
|
|
23
|
+
@goal_motivations[goal_id] = {
|
|
24
|
+
drives: valid_drives,
|
|
25
|
+
energy: goal_energy_for(valid_drives),
|
|
26
|
+
committed: true,
|
|
27
|
+
committed_at: Time.now.utc
|
|
28
|
+
}
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def release_goal(goal_id)
|
|
33
|
+
@goal_motivations.delete(goal_id)
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def goal_energy(goal_id)
|
|
38
|
+
entry = @goal_motivations[goal_id]
|
|
39
|
+
return 0.0 unless entry
|
|
40
|
+
|
|
41
|
+
entry[:energy] = goal_energy_for(entry[:drives])
|
|
42
|
+
entry[:energy]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def most_motivated_goal
|
|
46
|
+
return nil if @goal_motivations.empty?
|
|
47
|
+
|
|
48
|
+
refreshed = @goal_motivations.transform_values do |entry|
|
|
49
|
+
entry.merge(energy: goal_energy_for(entry[:drives]))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
best_id, best_entry = refreshed.max_by { |_, v| v[:energy] }
|
|
53
|
+
return nil unless best_id
|
|
54
|
+
|
|
55
|
+
{ goal_id: best_id, energy: best_entry[:energy].round(4), drives: best_entry[:drives] }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def burnout_check
|
|
59
|
+
overall = @drive_state.overall_level
|
|
60
|
+
if overall < Constants::BURNOUT_THRESHOLD
|
|
61
|
+
@low_motivation_ticks += 1
|
|
62
|
+
else
|
|
63
|
+
@low_motivation_ticks = 0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
{
|
|
67
|
+
burnout: @low_motivation_ticks >= 10,
|
|
68
|
+
low_motivation_ticks: @low_motivation_ticks,
|
|
69
|
+
overall_level: overall.round(4)
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def stats
|
|
74
|
+
{
|
|
75
|
+
overall_level: @drive_state.overall_level.round(4),
|
|
76
|
+
current_mode: @drive_state.current_mode,
|
|
77
|
+
intrinsic_average: @drive_state.intrinsic_average.round(4),
|
|
78
|
+
extrinsic_average: @drive_state.extrinsic_average.round(4),
|
|
79
|
+
amotivated: @drive_state.amotivated?,
|
|
80
|
+
goal_count: @goal_motivations.size,
|
|
81
|
+
low_motivation_ticks: @low_motivation_ticks
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def goal_energy_for(drives)
|
|
88
|
+
return 0.0 if drives.empty?
|
|
89
|
+
|
|
90
|
+
total = drives.sum { |d| @drive_state.drive_level(d) }
|
|
91
|
+
(total / drives.size.to_f).clamp(0.0, 1.0)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def trim_goals
|
|
95
|
+
return unless @goal_motivations.size >= Constants::MAX_GOALS
|
|
96
|
+
|
|
97
|
+
oldest_key = @goal_motivations.min_by { |_, v| v[:committed_at] }&.first
|
|
98
|
+
@goal_motivations.delete(oldest_key) if oldest_key
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Motivation
|
|
8
|
+
module Runners
|
|
9
|
+
module Motivation
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def update_motivation(tick_results: {}, **)
|
|
14
|
+
extract_drive_signals(tick_results)
|
|
15
|
+
motivation_store.drive_state.decay_all
|
|
16
|
+
burnout = motivation_store.burnout_check
|
|
17
|
+
mode = motivation_store.drive_state.current_mode
|
|
18
|
+
|
|
19
|
+
Legion::Logging.debug "[motivation] mode=#{mode} " \
|
|
20
|
+
"overall=#{motivation_store.drive_state.overall_level.round(3)} " \
|
|
21
|
+
"amotivated=#{motivation_store.drive_state.amotivated?}"
|
|
22
|
+
|
|
23
|
+
{
|
|
24
|
+
mode: mode,
|
|
25
|
+
overall_level: motivation_store.drive_state.overall_level.round(4),
|
|
26
|
+
intrinsic_average: motivation_store.drive_state.intrinsic_average.round(4),
|
|
27
|
+
extrinsic_average: motivation_store.drive_state.extrinsic_average.round(4),
|
|
28
|
+
amotivated: motivation_store.drive_state.amotivated?,
|
|
29
|
+
burnout: burnout[:burnout]
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def signal_drive(drive:, signal:, **)
|
|
34
|
+
drive_sym = drive.to_sym
|
|
35
|
+
return { success: false, error: "unknown drive: #{drive}" } unless Helpers::Constants::DRIVE_TYPES.include?(drive_sym)
|
|
36
|
+
|
|
37
|
+
motivation_store.drive_state.update_drive(drive_sym, signal.to_f)
|
|
38
|
+
level = motivation_store.drive_state.drive_level(drive_sym)
|
|
39
|
+
|
|
40
|
+
Legion::Logging.debug "[motivation] drive signal: #{drive_sym}=#{level.round(3)}"
|
|
41
|
+
{ success: true, drive: drive_sym, level: level.round(4) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def commit_to_goal(goal_id:, drives:, **)
|
|
45
|
+
drive_syms = Array(drives).map(&:to_sym)
|
|
46
|
+
result = motivation_store.commit_goal(goal_id, drive_syms)
|
|
47
|
+
|
|
48
|
+
if result
|
|
49
|
+
energy = motivation_store.goal_energy(goal_id)
|
|
50
|
+
Legion::Logging.info "[motivation] committed goal=#{goal_id} energy=#{energy.round(3)}"
|
|
51
|
+
{ success: true, goal_id: goal_id, energy: energy.round(4) }
|
|
52
|
+
else
|
|
53
|
+
Legion::Logging.warn "[motivation] commit_goal rejected: no valid drives for #{goal_id}"
|
|
54
|
+
{ success: false, error: 'no valid drives provided' }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def release_goal(goal_id:, **)
|
|
59
|
+
motivation_store.release_goal(goal_id)
|
|
60
|
+
Legion::Logging.debug "[motivation] released goal=#{goal_id}"
|
|
61
|
+
{ success: true, goal_id: goal_id }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def motivation_for(goal_id:, **)
|
|
65
|
+
energy = motivation_store.goal_energy(goal_id)
|
|
66
|
+
Legion::Logging.debug "[motivation] motivation_for goal=#{goal_id} energy=#{energy.round(3)}"
|
|
67
|
+
{ goal_id: goal_id, energy: energy.round(4) }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def most_motivated_goal(**)
|
|
71
|
+
result = motivation_store.most_motivated_goal
|
|
72
|
+
Legion::Logging.debug "[motivation] most_motivated_goal=#{result&.fetch(:goal_id, nil)}"
|
|
73
|
+
result || { goal_id: nil, energy: 0.0, drives: [] }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def drive_status(**)
|
|
77
|
+
drives = motivation_store.drive_state.drives.transform_values do |d|
|
|
78
|
+
{ level: d[:level].round(4), satisfied: d[:satisfied] }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
Legion::Logging.debug '[motivation] drive_status'
|
|
82
|
+
{
|
|
83
|
+
drives: drives,
|
|
84
|
+
mode: motivation_store.drive_state.current_mode,
|
|
85
|
+
overall: motivation_store.drive_state.overall_level.round(4)
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def motivation_stats(**)
|
|
90
|
+
Legion::Logging.debug '[motivation] stats'
|
|
91
|
+
motivation_store.stats
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def motivation_store
|
|
97
|
+
@motivation_store ||= Helpers::MotivationStore.new
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def extract_drive_signals(tick_results)
|
|
101
|
+
extract_autonomy_signal(tick_results)
|
|
102
|
+
extract_competence_signal(tick_results)
|
|
103
|
+
extract_relatedness_signal(tick_results)
|
|
104
|
+
extract_novelty_signal(tick_results)
|
|
105
|
+
extract_obligation_signal(tick_results)
|
|
106
|
+
extract_survival_signal(tick_results)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def extract_autonomy_signal(tick_results)
|
|
110
|
+
consent_tier = tick_results.dig(:consent, :tier)
|
|
111
|
+
return unless consent_tier
|
|
112
|
+
|
|
113
|
+
signal = case consent_tier
|
|
114
|
+
when :autonomous then 1.0
|
|
115
|
+
when :collaborate then 0.7
|
|
116
|
+
when :consult then 0.4
|
|
117
|
+
else 0.1
|
|
118
|
+
end
|
|
119
|
+
motivation_store.drive_state.update_drive(:autonomy, signal)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def extract_competence_signal(tick_results)
|
|
123
|
+
accuracy = tick_results.dig(:prediction_engine, :accuracy)
|
|
124
|
+
return unless accuracy
|
|
125
|
+
|
|
126
|
+
motivation_store.drive_state.update_drive(:competence, accuracy.to_f)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def extract_relatedness_signal(tick_results)
|
|
130
|
+
trust_level = tick_results.dig(:trust, :overall_level)
|
|
131
|
+
return unless trust_level
|
|
132
|
+
|
|
133
|
+
motivation_store.drive_state.update_drive(:relatedness, trust_level.to_f)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def extract_novelty_signal(tick_results)
|
|
137
|
+
novel = tick_results.dig(:memory_retrieval, :novel_traces)
|
|
138
|
+
return unless novel
|
|
139
|
+
|
|
140
|
+
signal = novel.positive? ? [novel.to_f / 10.0, 1.0].min : 0.1
|
|
141
|
+
motivation_store.drive_state.update_drive(:novelty, signal)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def extract_obligation_signal(tick_results)
|
|
145
|
+
pending = tick_results.dig(:scheduler, :pending_tasks)
|
|
146
|
+
return unless pending
|
|
147
|
+
|
|
148
|
+
signal = pending.positive? ? [pending.to_f / 20.0, 1.0].min : 0.0
|
|
149
|
+
motivation_store.drive_state.update_drive(:obligation, signal)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def extract_survival_signal(tick_results)
|
|
153
|
+
extinction_level = tick_results.dig(:extinction, :level)
|
|
154
|
+
return unless extinction_level
|
|
155
|
+
|
|
156
|
+
signal = extinction_level.to_f / 4.0
|
|
157
|
+
motivation_store.drive_state.update_drive(:survival, signal)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/affect/motivation/version'
|
|
4
|
+
require 'legion/extensions/agentic/affect/motivation/helpers/constants'
|
|
5
|
+
require 'legion/extensions/agentic/affect/motivation/helpers/drive_state'
|
|
6
|
+
require 'legion/extensions/agentic/affect/motivation/helpers/motivation_store'
|
|
7
|
+
require 'legion/extensions/agentic/affect/motivation/runners/motivation'
|
|
8
|
+
require 'legion/extensions/agentic/affect/motivation/client'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module Agentic
|
|
13
|
+
module Affect
|
|
14
|
+
module Motivation
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/actors/every'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Affect
|
|
9
|
+
module Reappraisal
|
|
10
|
+
module Actor
|
|
11
|
+
class AutoRegulate < Legion::Extensions::Actors::Every
|
|
12
|
+
def runner_class
|
|
13
|
+
Legion::Extensions::Agentic::Affect::Reappraisal::Runners::CognitiveReappraisal
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def runner_function
|
|
17
|
+
'regulate_pending_events'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def time
|
|
21
|
+
300
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def run_now?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def use_runner?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def check_subtask?
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def generate_task?
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/constants'
|
|
4
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/emotional_event'
|
|
5
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/reappraisal_engine'
|
|
6
|
+
require 'legion/extensions/agentic/affect/reappraisal/runners/cognitive_reappraisal'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Agentic
|
|
11
|
+
module Affect
|
|
12
|
+
module Reappraisal
|
|
13
|
+
class Client
|
|
14
|
+
include Runners::CognitiveReappraisal
|
|
15
|
+
|
|
16
|
+
def initialize(engine: nil, **)
|
|
17
|
+
@reappraisal_engine = engine || Helpers::ReappraisalEngine.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
attr_reader :reappraisal_engine
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Reappraisal
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
MAX_EVENTS = 300
|
|
11
|
+
MAX_REAPPRAISALS = 500
|
|
12
|
+
|
|
13
|
+
STRATEGIES = %i[
|
|
14
|
+
reinterpretation
|
|
15
|
+
distancing
|
|
16
|
+
benefit_finding
|
|
17
|
+
normalizing
|
|
18
|
+
perspective_taking
|
|
19
|
+
temporal_distancing
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
STRATEGY_EFFECTIVENESS = {
|
|
23
|
+
reinterpretation: 0.25,
|
|
24
|
+
distancing: 0.15,
|
|
25
|
+
benefit_finding: 0.20,
|
|
26
|
+
normalizing: 0.12,
|
|
27
|
+
perspective_taking: 0.18,
|
|
28
|
+
temporal_distancing: 0.10
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
VALENCE_LABELS = {
|
|
32
|
+
(0.5..) => :positive,
|
|
33
|
+
(0.1...0.5) => :mildly_positive,
|
|
34
|
+
(-0.1...0.1) => :neutral,
|
|
35
|
+
(-0.5...-0.1) => :mildly_negative,
|
|
36
|
+
(..-0.5) => :negative
|
|
37
|
+
}.freeze
|
|
38
|
+
|
|
39
|
+
INTENSITY_LABELS = {
|
|
40
|
+
(0.8..) => :overwhelming,
|
|
41
|
+
(0.6...0.8) => :intense,
|
|
42
|
+
(0.4...0.6) => :moderate,
|
|
43
|
+
(0.2...0.4) => :mild,
|
|
44
|
+
(..0.2) => :faint
|
|
45
|
+
}.freeze
|
|
46
|
+
|
|
47
|
+
REGULATION_LABELS = {
|
|
48
|
+
(0.8..) => :excellent,
|
|
49
|
+
(0.6...0.8) => :good,
|
|
50
|
+
(0.4...0.6) => :moderate,
|
|
51
|
+
(0.2...0.4) => :poor,
|
|
52
|
+
(..0.2) => :minimal
|
|
53
|
+
}.freeze
|
|
54
|
+
|
|
55
|
+
NEGATIVE_VALENCE_THRESHOLD = -0.3
|
|
56
|
+
HIGH_INTENSITY_THRESHOLD = 0.7
|
|
57
|
+
REAPPRAISAL_DIFFICULTY_MULTIPLIER = 0.5
|
|
58
|
+
|
|
59
|
+
module_function
|
|
60
|
+
|
|
61
|
+
def label_for(value, label_map)
|
|
62
|
+
label_map.find { |range, _label| range.cover?(value) }&.last || :unknown
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def valid_strategy?(strategy)
|
|
66
|
+
STRATEGIES.include?(strategy)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def clamp(value, min = -1.0, max = 1.0)
|
|
70
|
+
value.clamp(min, max)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def clamp_intensity(value)
|
|
74
|
+
value.clamp(0.0, 1.0)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Affect
|
|
9
|
+
module Reappraisal
|
|
10
|
+
module Helpers
|
|
11
|
+
class EmotionalEvent
|
|
12
|
+
include Constants
|
|
13
|
+
|
|
14
|
+
attr_reader :id, :content, :initial_valence, :current_valence,
|
|
15
|
+
:initial_intensity, :current_intensity, :appraisal,
|
|
16
|
+
:reappraisal_count, :created_at
|
|
17
|
+
|
|
18
|
+
def initialize(content:, valence:, intensity:, appraisal:)
|
|
19
|
+
@id = SecureRandom.uuid
|
|
20
|
+
@content = content
|
|
21
|
+
@initial_valence = Constants.clamp(valence)
|
|
22
|
+
@current_valence = @initial_valence
|
|
23
|
+
@initial_intensity = Constants.clamp_intensity(intensity)
|
|
24
|
+
@current_intensity = @initial_intensity
|
|
25
|
+
@appraisal = appraisal
|
|
26
|
+
@reappraisal_count = 0
|
|
27
|
+
@created_at = Time.now.utc
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def reappraise!(strategy:, new_appraisal:)
|
|
31
|
+
return 0.0 unless Constants.valid_strategy?(strategy)
|
|
32
|
+
|
|
33
|
+
base_effectiveness = Constants::STRATEGY_EFFECTIVENESS[strategy]
|
|
34
|
+
difficulty = @current_intensity > Constants::HIGH_INTENSITY_THRESHOLD ? Constants::REAPPRAISAL_DIFFICULTY_MULTIPLIER : 1.0
|
|
35
|
+
effectiveness = (base_effectiveness * difficulty).round(10)
|
|
36
|
+
|
|
37
|
+
valence_shift = effectiveness
|
|
38
|
+
intensity_reduction = (effectiveness * 0.5).round(10)
|
|
39
|
+
|
|
40
|
+
old_valence = @current_valence
|
|
41
|
+
old_intensity = @current_intensity
|
|
42
|
+
|
|
43
|
+
@current_valence = Constants.clamp(@current_valence + valence_shift)
|
|
44
|
+
@current_intensity = Constants.clamp_intensity(@current_intensity - intensity_reduction)
|
|
45
|
+
@appraisal = new_appraisal
|
|
46
|
+
@reappraisal_count += 1
|
|
47
|
+
|
|
48
|
+
((@current_valence - old_valence).abs + (old_intensity - @current_intensity).abs).round(10)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def negative?
|
|
52
|
+
@current_valence < Constants::NEGATIVE_VALENCE_THRESHOLD
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def intense?
|
|
56
|
+
@current_intensity > Constants::HIGH_INTENSITY_THRESHOLD
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def regulation_amount
|
|
60
|
+
valence_change = (@current_valence - @initial_valence).abs
|
|
61
|
+
intensity_change = (@initial_intensity - @current_intensity).abs
|
|
62
|
+
raw = valence_change + intensity_change
|
|
63
|
+
Constants.clamp_intensity(raw / 2.0)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def valence_label
|
|
67
|
+
Constants.label_for(@current_valence, Constants::VALENCE_LABELS)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def intensity_label
|
|
71
|
+
Constants.label_for(@current_intensity, Constants::INTENSITY_LABELS)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_h
|
|
75
|
+
{
|
|
76
|
+
id: @id,
|
|
77
|
+
content: @content,
|
|
78
|
+
initial_valence: @initial_valence.round(10),
|
|
79
|
+
current_valence: @current_valence.round(10),
|
|
80
|
+
initial_intensity: @initial_intensity.round(10),
|
|
81
|
+
current_intensity: @current_intensity.round(10),
|
|
82
|
+
appraisal: @appraisal,
|
|
83
|
+
reappraisal_count: @reappraisal_count,
|
|
84
|
+
negative: negative?,
|
|
85
|
+
intense: intense?,
|
|
86
|
+
regulation_amount: regulation_amount.round(10),
|
|
87
|
+
valence_label: valence_label,
|
|
88
|
+
intensity_label: intensity_label,
|
|
89
|
+
created_at: @created_at
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|