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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/accessor.rb +45 -0
  3. data/lib/action.rb +127 -0
  4. data/lib/action_stack.rb +44 -0
  5. data/lib/{Clone.rb → clone.rb} +11 -11
  6. data/lib/config.rb +48 -0
  7. data/lib/control.rb +81 -0
  8. data/lib/experiment.rb +99 -0
  9. data/lib/meta.rb +75 -0
  10. data/lib/meta/array_meta.rb +32 -0
  11. data/lib/meta/boolean_meta.rb +26 -0
  12. data/lib/meta/float_meta.rb +26 -0
  13. data/lib/meta/integer_meta.rb +26 -0
  14. data/lib/meta/{NullMeta.rb → null_meta.rb} +21 -19
  15. data/lib/meta/object_meta.rb +35 -0
  16. data/lib/meta/string_meta.rb +26 -0
  17. data/lib/meta_builder.rb +100 -0
  18. data/lib/reflection.rb +123 -0
  19. data/lib/reflekt.rb +277 -0
  20. data/lib/renderer.rb +38 -0
  21. data/lib/rule.rb +54 -0
  22. data/lib/rule_set.rb +110 -0
  23. data/lib/rule_set_aggregator.rb +260 -0
  24. data/lib/rules/array_rule.rb +94 -0
  25. data/lib/rules/boolean_rule.rb +43 -0
  26. data/lib/rules/float_rule.rb +55 -0
  27. data/lib/rules/integer_rule.rb +55 -0
  28. data/lib/rules/null_rule.rb +35 -0
  29. data/lib/rules/object_rule.rb +42 -0
  30. data/lib/rules/string_rule.rb +75 -0
  31. data/lib/web/index.html +3 -4
  32. metadata +46 -29
  33. data/lib/Accessor.rb +0 -37
  34. data/lib/Action.rb +0 -88
  35. data/lib/ActionStack.rb +0 -44
  36. data/lib/Aggregator.rb +0 -260
  37. data/lib/Config.rb +0 -42
  38. data/lib/Control.rb +0 -83
  39. data/lib/Meta.rb +0 -71
  40. data/lib/MetaBuilder.rb +0 -84
  41. data/lib/Reflection.rb +0 -195
  42. data/lib/Reflekt.rb +0 -243
  43. data/lib/Renderer.rb +0 -39
  44. data/lib/Rule.rb +0 -52
  45. data/lib/RuleSet.rb +0 -109
  46. data/lib/meta/ArrayMeta.rb +0 -34
  47. data/lib/meta/BooleanMeta.rb +0 -26
  48. data/lib/meta/FloatMeta.rb +0 -26
  49. data/lib/meta/IntegerMeta.rb +0 -26
  50. data/lib/meta/StringMeta.rb +0 -26
  51. data/lib/rules/ArrayRule.rb +0 -88
  52. data/lib/rules/BooleanRule.rb +0 -47
  53. data/lib/rules/FloatRule.rb +0 -57
  54. data/lib/rules/IntegerRule.rb +0 -57
  55. data/lib/rules/NullRule.rb +0 -33
  56. data/lib/rules/StringRule.rb +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 457006f1c0a4fbe9a1ce47684aeeec980852cd966f29d07ac57751161f314d52
4
- data.tar.gz: ca01fd9306ece9e1698aab0dcb4945a848a5a910625f8b9394b4f26aa7819514
3
+ metadata.gz: 3e5af4cf8808efaeb9b41e29c925aee883139afaea6fef303f060a91566a101b
4
+ data.tar.gz: cb877b7821ed829907c52387b5fc04ff3c986f05646170dceb3307cc14a4d648
5
5
  SHA512:
6
- metadata.gz: 1de336f083b2e90230453d3ce07cfb36981998587de2e126c88948da75a618ee57a68b32b9869865fb9353b45e85fadc293d98afc2c4669afe8fadc9761fda93
7
- data.tar.gz: 0b00aa43ef7763bc11e93697446ca0e86114818f3e6238d28711d1038eef0c4bc58dc43b1f1f901ec58a4cdf6c9138493e63572a7d33a0363a591e908b38e751
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
@@ -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
@@ -12,20 +12,20 @@
12
12
  # 3. Clone <- YOU ARE HERE
13
13
  ################################################################################
14
14
 
15
- class Clone
15
+ module Reflekt
16
+ class Clone
16
17
 
17
- def initialize(action)
18
+ def initialize(action)
19
+ # Clone the action's calling object.
20
+ @caller_object_clone = action.caller_object.clone
18
21
 
19
- # Clone the action's calling object.
20
- @caller_object_clone = action.caller_object.clone
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
- # TODO: Clone any other instances that this clone references.
23
- # TODO: Replace clone's references to these new instances.
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