reflekt 1.0.5 → 1.0.10
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 +4 -4
- data/lib/accessor.rb +45 -0
- data/lib/action.rb +127 -0
- data/lib/action_stack.rb +44 -0
- data/lib/{Clone.rb → clone.rb} +11 -11
- data/lib/config.rb +48 -0
- data/lib/control.rb +81 -0
- data/lib/experiment.rb +99 -0
- data/lib/meta.rb +75 -0
- data/lib/meta/array_meta.rb +32 -0
- data/lib/meta/boolean_meta.rb +26 -0
- data/lib/meta/float_meta.rb +26 -0
- data/lib/meta/integer_meta.rb +26 -0
- data/lib/meta/{NullMeta.rb → null_meta.rb} +21 -19
- data/lib/meta/object_meta.rb +35 -0
- data/lib/meta/string_meta.rb +26 -0
- data/lib/meta_builder.rb +100 -0
- data/lib/reflection.rb +123 -0
- data/lib/reflekt.rb +277 -0
- data/lib/renderer.rb +38 -0
- data/lib/rule.rb +54 -0
- data/lib/rule_set.rb +110 -0
- data/lib/rule_set_aggregator.rb +260 -0
- data/lib/rules/array_rule.rb +94 -0
- data/lib/rules/boolean_rule.rb +43 -0
- data/lib/rules/float_rule.rb +55 -0
- data/lib/rules/integer_rule.rb +55 -0
- data/lib/rules/null_rule.rb +35 -0
- data/lib/rules/object_rule.rb +42 -0
- data/lib/rules/string_rule.rb +75 -0
- data/lib/web/index.html +3 -4
- metadata +46 -29
- data/lib/Accessor.rb +0 -37
- data/lib/Action.rb +0 -88
- data/lib/ActionStack.rb +0 -44
- data/lib/Aggregator.rb +0 -260
- data/lib/Config.rb +0 -42
- data/lib/Control.rb +0 -83
- data/lib/Meta.rb +0 -71
- data/lib/MetaBuilder.rb +0 -84
- data/lib/Reflection.rb +0 -195
- data/lib/Reflekt.rb +0 -243
- data/lib/Renderer.rb +0 -39
- data/lib/Rule.rb +0 -52
- data/lib/RuleSet.rb +0 -109
- data/lib/meta/ArrayMeta.rb +0 -34
- data/lib/meta/BooleanMeta.rb +0 -26
- data/lib/meta/FloatMeta.rb +0 -26
- data/lib/meta/IntegerMeta.rb +0 -26
- data/lib/meta/StringMeta.rb +0 -26
- data/lib/rules/ArrayRule.rb +0 -88
- data/lib/rules/BooleanRule.rb +0 -47
- data/lib/rules/FloatRule.rb +0 -57
- data/lib/rules/IntegerRule.rb +0 -57
- data/lib/rules/NullRule.rb +0 -33
- data/lib/rules/StringRule.rb +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e5af4cf8808efaeb9b41e29c925aee883139afaea6fef303f060a91566a101b
|
4
|
+
data.tar.gz: cb877b7821ed829907c52387b5fc04ff3c986f05646170dceb3307cc14a4d648
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6200d9280ccdf2cd5cb1788d80e6795813e5dc7ca398ebca75e507aba2fc8e3bf116ec851f3d103c92eaa1e1a79fd0a6c3f14dc1f59cee74117a8a1f74f60e66
|
7
|
+
data.tar.gz: 9b28f16baeafa725c606c0ea458742f86d0b87cda0e95180658b66598a8a08a0efa46f706214d8e00e98eecfc766eadfafeeb47697cf297f62beef95e2ed452d
|
data/lib/accessor.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Access variables via one object to avoid polluting the caller's scope.
|
3
|
+
#
|
4
|
+
# @pattern Singleton
|
5
|
+
#
|
6
|
+
# @note Variables not accessed via Accessor:
|
7
|
+
# - @reflekt_counts on the instance
|
8
|
+
# - @@reflekt_skipped_methods on the instance's singleton class
|
9
|
+
################################################################################
|
10
|
+
|
11
|
+
module Reflekt
|
12
|
+
class Accessor
|
13
|
+
|
14
|
+
attr_accessor :initialized
|
15
|
+
attr_accessor :counts
|
16
|
+
attr_accessor :error
|
17
|
+
|
18
|
+
attr_accessor :config
|
19
|
+
attr_accessor :db
|
20
|
+
attr_accessor :stack
|
21
|
+
attr_accessor :aggregator
|
22
|
+
attr_accessor :renderer
|
23
|
+
|
24
|
+
attr_accessor :package_path
|
25
|
+
attr_accessor :project_path
|
26
|
+
attr_accessor :output_path
|
27
|
+
|
28
|
+
def initialize()
|
29
|
+
@initialized = false
|
30
|
+
@counts = {}
|
31
|
+
@error = nil
|
32
|
+
|
33
|
+
@config = nil
|
34
|
+
@db = nil
|
35
|
+
@stack = nil
|
36
|
+
@aggregator = nil
|
37
|
+
@renderer = nil
|
38
|
+
|
39
|
+
@package_path = nil
|
40
|
+
@project_path = nil
|
41
|
+
@output_path = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/action.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
################################################################################
|
2
|
+
# A shadow action.
|
3
|
+
#
|
4
|
+
# @hierachy
|
5
|
+
# 1. Action <- YOU ARE HERE
|
6
|
+
# 2. Reflection
|
7
|
+
# 3. Meta
|
8
|
+
################################################################################
|
9
|
+
|
10
|
+
module Reflekt
|
11
|
+
class Action
|
12
|
+
include LitCLI
|
13
|
+
|
14
|
+
attr_accessor :unique_id
|
15
|
+
attr_accessor :caller_object
|
16
|
+
attr_accessor :caller_id
|
17
|
+
attr_accessor :caller_class
|
18
|
+
attr_accessor :klass
|
19
|
+
attr_accessor :method
|
20
|
+
attr_accessor :base
|
21
|
+
attr_accessor :parent
|
22
|
+
attr_accessor :child
|
23
|
+
attr_accessor :control
|
24
|
+
attr_accessor :experiments
|
25
|
+
attr_accessor :is_actioned
|
26
|
+
attr_accessor :is_reflecting
|
27
|
+
attr_accessor :is_base
|
28
|
+
|
29
|
+
##
|
30
|
+
# Create Action.
|
31
|
+
#
|
32
|
+
# @param object [Object] The calling object.
|
33
|
+
# @param method [Symbol] The calling method.
|
34
|
+
# @param reflect_amount [Integer] The number of experiments to create per action.
|
35
|
+
# @param stack [ActionStack] The shadow action call stack.
|
36
|
+
##
|
37
|
+
def initialize(caller_object, method, config, db, stack, aggregator)
|
38
|
+
@time = Time.now.to_i
|
39
|
+
@unique_id = @time + rand(1..99999)
|
40
|
+
@base = nil
|
41
|
+
@child = nil
|
42
|
+
@parent = nil
|
43
|
+
|
44
|
+
# Dependencies.
|
45
|
+
@db = db
|
46
|
+
@stack = stack
|
47
|
+
@aggregator = aggregator
|
48
|
+
|
49
|
+
# Caller.
|
50
|
+
@caller_object = caller_object
|
51
|
+
@caller_class = caller_object.class
|
52
|
+
@caller_id = caller_object.object_id
|
53
|
+
@klass = @caller_class.to_s.to_sym
|
54
|
+
@method = method
|
55
|
+
|
56
|
+
# Reflections.
|
57
|
+
@control = nil
|
58
|
+
@experiments = Array.new(config.reflect_amount)
|
59
|
+
|
60
|
+
# State.
|
61
|
+
@is_reflecting = false
|
62
|
+
if @stack.peek() == nil
|
63
|
+
@is_base = true
|
64
|
+
else
|
65
|
+
@is_base = false
|
66
|
+
@base = @stack.base()
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def reflect(*args)
|
71
|
+
|
72
|
+
🔥"^ Create control for #{@method}()", :info, :control, @klass
|
73
|
+
@control = Control.new(self, 0, @aggregator)
|
74
|
+
|
75
|
+
@control.reflect(*args)
|
76
|
+
🔥"> Reflected control for #{@method}(): #{args}", @control.status, :result, @klass
|
77
|
+
|
78
|
+
# Stop reflecting when control fails to execute.
|
79
|
+
unless @control.status == :error
|
80
|
+
|
81
|
+
# Save control.
|
82
|
+
@db.get("controls").push(@control.serialize())
|
83
|
+
@db.get("reflections").push(@control.serialize())
|
84
|
+
|
85
|
+
# Multiple experiments per action.
|
86
|
+
@experiments.each_with_index do |value, index|
|
87
|
+
|
88
|
+
🔥"^ Create experiment ##{index + 1} for #{@method}()", :info, :experiment, @klass
|
89
|
+
experiment = Experiment.new(self, index + 1, @aggregator)
|
90
|
+
@experiments[index] = experiment
|
91
|
+
|
92
|
+
# Reflect experiment.
|
93
|
+
experiment.reflect(*args)
|
94
|
+
Reflekt.increase_count(@caller_object, @method)
|
95
|
+
🔥"> Reflected experiment ##{index + 1} for #{@method}()", experiment.status, :result, @klass
|
96
|
+
|
97
|
+
# Save experiment.
|
98
|
+
@db.get("reflections").push(experiment.serialize())
|
99
|
+
end
|
100
|
+
|
101
|
+
# Save results.
|
102
|
+
@db.write()
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def is_actioned?
|
107
|
+
@is_actioned
|
108
|
+
end
|
109
|
+
|
110
|
+
# Is the action currently reflecting methods?
|
111
|
+
def is_reflecting?
|
112
|
+
@is_reflecting
|
113
|
+
end
|
114
|
+
|
115
|
+
def has_empty_experiments?
|
116
|
+
@experiments.include? nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def has_finished_loop?
|
120
|
+
return false if is_actioned? == false
|
121
|
+
return false if is_reflecting?
|
122
|
+
return false if has_empty_experiments?
|
123
|
+
|
124
|
+
true
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/action_stack.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Track the actions in a shadow call stack.
|
3
|
+
#
|
4
|
+
# @pattern Stack
|
5
|
+
################################################################################
|
6
|
+
|
7
|
+
module Reflekt
|
8
|
+
class ActionStack
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@bottom = nil
|
12
|
+
@top = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def peek()
|
16
|
+
@top
|
17
|
+
end
|
18
|
+
|
19
|
+
def base()
|
20
|
+
@bottom
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Place Action at the top of stack.
|
25
|
+
#
|
26
|
+
# @param action [Action] The action to place.
|
27
|
+
# @return [Action] The placed action.
|
28
|
+
##
|
29
|
+
def push(action)
|
30
|
+
# First time? Place action at bottom of stack.
|
31
|
+
if @bottom.nil?
|
32
|
+
@bottom = action
|
33
|
+
# Connect subsequent actions to each other.
|
34
|
+
else
|
35
|
+
@top.parent = action
|
36
|
+
action.child = @top
|
37
|
+
end
|
38
|
+
|
39
|
+
# Place action at top of stack.
|
40
|
+
@top = action
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/{Clone.rb → clone.rb}
RENAMED
@@ -12,20 +12,20 @@
|
|
12
12
|
# 3. Clone <- YOU ARE HERE
|
13
13
|
################################################################################
|
14
14
|
|
15
|
-
|
15
|
+
module Reflekt
|
16
|
+
class Clone
|
16
17
|
|
17
|
-
|
18
|
+
def initialize(action)
|
19
|
+
# Clone the action's calling object.
|
20
|
+
@caller_object_clone = action.caller_object.clone
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
# TODO: Clone any other instances that this clone references.
|
23
|
+
# TODO: Replace clone's references to these new instances.
|
24
|
+
end
|
21
25
|
|
22
|
-
|
23
|
-
|
26
|
+
def action(method, *new_args)
|
27
|
+
@caller_object_clone.send(method, *new_args)
|
28
|
+
end
|
24
29
|
|
25
30
|
end
|
26
|
-
|
27
|
-
def action(method, *new_args)
|
28
|
-
@caller_object_clone.send(method, *new_args)
|
29
|
-
end
|
30
|
-
|
31
31
|
end
|
data/lib/config.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Reflekt
|
2
|
+
class Config
|
3
|
+
|
4
|
+
attr_accessor :enabled
|
5
|
+
attr_accessor :reflect_amount
|
6
|
+
attr_accessor :reflect_limit
|
7
|
+
attr_accessor :meta_map
|
8
|
+
attr_accessor :project_path
|
9
|
+
attr_accessor :output_directory
|
10
|
+
|
11
|
+
def initialize()
|
12
|
+
|
13
|
+
# Reflekt is enabled by default and should be disabled on production.
|
14
|
+
@enabled = true
|
15
|
+
|
16
|
+
# Reflekt is untracked in git by default.
|
17
|
+
@git_ignore = true
|
18
|
+
|
19
|
+
# The amount of reflections to create per method call.
|
20
|
+
# A control reflection is created in addition to this.
|
21
|
+
@reflect_amount = 5
|
22
|
+
|
23
|
+
# The maximum amount of reflections that can be created per instance per method.
|
24
|
+
# A method called thousands of times doesn't need that many reflections.
|
25
|
+
@reflect_limit = 10
|
26
|
+
|
27
|
+
# The rules that apply to meta types.
|
28
|
+
@meta_map = {
|
29
|
+
:array => [ArrayRule],
|
30
|
+
:bool => [BooleanRule],
|
31
|
+
:int => [IntegerRule],
|
32
|
+
:float => [FloatRule],
|
33
|
+
:null => [NullRule],
|
34
|
+
:object => [ObjectRule],
|
35
|
+
:string => [StringRule]
|
36
|
+
}
|
37
|
+
|
38
|
+
# An absolute path to the project root directory.
|
39
|
+
# Defaults to current execution path.
|
40
|
+
@project_path = Dir.pwd
|
41
|
+
|
42
|
+
# Name of output directory.
|
43
|
+
@output_directory = "reflections"
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/control.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
################################################################################
|
2
|
+
# A shapshot of real data.
|
3
|
+
#
|
4
|
+
# @note
|
5
|
+
# A control's @number will always be 0.
|
6
|
+
#
|
7
|
+
# @nomenclature
|
8
|
+
# args, inputs/output and meta represent different stages of a value.
|
9
|
+
#
|
10
|
+
# @hierachy
|
11
|
+
# 1. Action
|
12
|
+
# 2. Control <- YOU ARE HERE
|
13
|
+
# 3. Meta
|
14
|
+
#
|
15
|
+
# @status
|
16
|
+
# - :pass [Symbol] The reflection passes the rules.
|
17
|
+
# - :fail [Symbol] The reflection fails the rules or produces a system error.
|
18
|
+
# - :error [Symbol] The control reflection produces a system error.
|
19
|
+
################################################################################
|
20
|
+
|
21
|
+
require_relative 'reflection'
|
22
|
+
require_relative 'meta_builder'
|
23
|
+
|
24
|
+
module Reflekt
|
25
|
+
class Control < Reflection
|
26
|
+
|
27
|
+
##
|
28
|
+
# Reflect on a method.
|
29
|
+
#
|
30
|
+
# Create a shadow action.
|
31
|
+
# @param *args [Dynamic] The method's arguments.
|
32
|
+
##
|
33
|
+
def reflect(*args)
|
34
|
+
# Get trained rule sets.
|
35
|
+
input_rule_sets = @aggregator.get_input_rule_sets(@klass, @method)
|
36
|
+
output_rule_set = @aggregator.get_output_rule_set(@klass, @method)
|
37
|
+
|
38
|
+
# Fail when no trained rule sets.
|
39
|
+
if input_rule_sets.nil?
|
40
|
+
@status = :fail
|
41
|
+
🔥"> No trained rule sets", :fail, :reflect
|
42
|
+
end
|
43
|
+
|
44
|
+
# When arguments exist.
|
45
|
+
unless args.size == 0
|
46
|
+
# Validate arguments against trained rule sets.
|
47
|
+
unless input_rule_sets.nil?
|
48
|
+
unless @aggregator.test_inputs(args, input_rule_sets)
|
49
|
+
@status = :fail
|
50
|
+
🔥"> Invalid inputs", @status, :reflect
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
🔥"> Create meta for #{@method}(): #{args}", :info, :meta, @klass
|
55
|
+
# TODO: Create metadata for other inputs such as instance variables.
|
56
|
+
@inputs = MetaBuilder.create_many(args)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Action method with real arguments.
|
60
|
+
begin
|
61
|
+
# Run reflection.
|
62
|
+
output = @clone.send(@method, *args)
|
63
|
+
@output = MetaBuilder.create(output)
|
64
|
+
|
65
|
+
# Validate output with aggregated control rule sets.
|
66
|
+
unless @aggregator.test_output(output, output_rule_set)
|
67
|
+
@status = :fail
|
68
|
+
🔥"> Invalid output", @status, :reflect
|
69
|
+
end
|
70
|
+
|
71
|
+
# When a system error occurs.
|
72
|
+
rescue StandardError => message
|
73
|
+
@status = :error
|
74
|
+
@message = message
|
75
|
+
|
76
|
+
# TODO: Write log entry to /reflections/errors.txt
|
77
|
+
🔥"#{@method}() not reflected", :error, :control, @klass.class
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/experiment.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
################################################################################
|
2
|
+
# A snapshot of random data.
|
3
|
+
#
|
4
|
+
# @note
|
5
|
+
# A reflection's random values are generated from aggregated control rule sets.
|
6
|
+
#
|
7
|
+
# @nomenclature
|
8
|
+
# args, inputs/output and meta represent different stages of a value.
|
9
|
+
#
|
10
|
+
# @hierachy
|
11
|
+
# 1. Action
|
12
|
+
# 2. Experiment <- YOU ARE HERE
|
13
|
+
# 3. Meta
|
14
|
+
#
|
15
|
+
# @status
|
16
|
+
# - :pass [Symbol] The reflection passes the rules.
|
17
|
+
# - :fail [Symbol] The reflection fails the rules or produces a system error.
|
18
|
+
# - :error [Symbol] The control reflection produces a system error.
|
19
|
+
################################################################################
|
20
|
+
|
21
|
+
require_relative 'reflection'
|
22
|
+
require_relative 'meta_builder'
|
23
|
+
|
24
|
+
module Reflekt
|
25
|
+
class Experiment < Reflection
|
26
|
+
|
27
|
+
##
|
28
|
+
# Reflect on a method.
|
29
|
+
#
|
30
|
+
# Create a shadow action.
|
31
|
+
# @param *args [Dynamic] The method's arguments.
|
32
|
+
##
|
33
|
+
def reflect(*args)
|
34
|
+
# Get aggregated rule sets.
|
35
|
+
input_rule_sets = @aggregator.get_input_rule_sets(@klass, @method)
|
36
|
+
output_rule_set = @aggregator.get_output_rule_set(@klass, @method)
|
37
|
+
|
38
|
+
# Fail when no trained rule sets.
|
39
|
+
if input_rule_sets.nil?
|
40
|
+
@status = :fail
|
41
|
+
end
|
42
|
+
|
43
|
+
# When arguments exist.
|
44
|
+
unless args.size == 0
|
45
|
+
# Create random arguments from aggregated rule sets.
|
46
|
+
unless input_rule_sets.nil?
|
47
|
+
args = randomize(args, input_rule_sets)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create metadata for each argument.
|
51
|
+
# TODO: Create metadata for other inputs such as instance variables.
|
52
|
+
🔥"> Create meta for #{@method}(): #{args}", :info, :meta, @klass
|
53
|
+
@inputs = MetaBuilder.create_many(args)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Action method with random arguments.
|
57
|
+
begin
|
58
|
+
# Run reflection.
|
59
|
+
output = @clone.send(@method, *args)
|
60
|
+
@output = MetaBuilder.create(output)
|
61
|
+
|
62
|
+
# Validate output against aggregated control rule sets.
|
63
|
+
unless output_rule_set.nil?
|
64
|
+
unless @aggregator.test_output(output, output_rule_set)
|
65
|
+
@status = :fail
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# When a system error occurs.
|
70
|
+
rescue StandardError => message
|
71
|
+
@status = :fail
|
72
|
+
@message = message
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Create random values for each argument from control reflections.
|
78
|
+
#
|
79
|
+
# @param args [Dynamic] The arguments to mirror random values for.
|
80
|
+
# @param input_rule_sets [Array] Aggregated rule sets for each argument.
|
81
|
+
#
|
82
|
+
# @return [Dynamic] Random arguments.
|
83
|
+
##
|
84
|
+
def randomize(args, input_rule_sets)
|
85
|
+
random_args = []
|
86
|
+
|
87
|
+
args.each_with_index do |arg, arg_num|
|
88
|
+
# Get a random rule in the rule set.
|
89
|
+
rules = input_rule_sets[arg_num].rules
|
90
|
+
agg_rule = rules[rules.keys.sample]
|
91
|
+
|
92
|
+
# Create a random value that follows that rule.
|
93
|
+
random_args << agg_rule.random()
|
94
|
+
end
|
95
|
+
|
96
|
+
return random_args
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|