MonkeyEngine 1.0.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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.idea/.name +1 -0
  4. data/.idea/.rakeTasks +7 -0
  5. data/.idea/MonkeyEngine.iml +133 -0
  6. data/.idea/codeStyleSettings.xml +13 -0
  7. data/.idea/encodings.xml +5 -0
  8. data/.idea/misc.xml +5 -0
  9. data/.idea/modules.xml +9 -0
  10. data/.idea/runConfigurations/All_specs_in_test__MonkeyEngine.xml +38 -0
  11. data/.idea/runConfigurations/IRB_console.xml +25 -0
  12. data/.idea/runConfigurations/Start_Yard_Server.xml +26 -0
  13. data/.idea/runConfigurations/monkey_run.xml +26 -0
  14. data/.idea/scopes/scope_settings.xml +5 -0
  15. data/.idea/vcs.xml +7 -0
  16. data/.idea/workspace.xml +886 -0
  17. data/.ruby-version +1 -0
  18. data/Gemfile +4 -0
  19. data/LICENSE.txt +22 -0
  20. data/README.md +29 -0
  21. data/Rakefile +3 -0
  22. data/lib/Action/action.rb +29 -0
  23. data/lib/Monkey.rb +1 -0
  24. data/lib/Monkey/monkey.rb +108 -0
  25. data/lib/MonkeyAction/monkey_action.rb +14 -0
  26. data/lib/MonkeyAction/monkey_action_dead.rb +26 -0
  27. data/lib/MonkeyAction/monkey_action_eat.rb +31 -0
  28. data/lib/MonkeyAction/monkey_action_pause.rb +32 -0
  29. data/lib/MonkeyAction/monkey_action_sleep.rb +31 -0
  30. data/lib/MonkeyAction/monkey_action_type.rb +40 -0
  31. data/lib/MonkeyAction/monkey_action_wake.rb +26 -0
  32. data/lib/MonkeyAction/monkey_timed_action.rb +27 -0
  33. data/lib/MonkeyActions.rb +6 -0
  34. data/lib/MonkeyEngine.rb +1 -0
  35. data/lib/MonkeyEngine/action_rules.rb +111 -0
  36. data/lib/MonkeyEngine/exceptions.rb +21 -0
  37. data/lib/MonkeyEngine/monkey_engine.rb +53 -0
  38. data/lib/MonkeyEngine/version.rb +3 -0
  39. data/lib/MonkeyFactory.rb +1 -0
  40. data/lib/MonkeyFactory/monkey_factory.rb +14 -0
  41. data/lib/MonkeyKeyboard/keyboard_char.rb +10 -0
  42. data/lib/MonkeyKeyboard/keyboard_input.rb +14 -0
  43. data/lib/MonkeyKeyboard/keyboard_key.rb +26 -0
  44. data/lib/MonkeyKeyboard/keyboard_key_evaluator.rb +25 -0
  45. data/lib/MonkeyKeyboard/monkey_keyboard_en_us.rb +137 -0
  46. data/lib/MonkeyKeyboardEnUs.rb +1 -0
  47. data/lib/MonkeyManager.rb +1 -0
  48. data/lib/MonkeyManager/monkey_manager.rb +162 -0
  49. data/lib/MonkeyService.rb +1 -0
  50. data/lib/MonkeyService/monkey_service.rb +137 -0
  51. data/lib/tasks/engine.rb +91 -0
  52. data/monkeyengine.gemspec +32 -0
  53. data/spec/action_rules_spec.rb +59 -0
  54. data/spec/engine_spec.rb +56 -0
  55. data/spec/keyboard_char_spec.rb +12 -0
  56. data/spec/keyboard_key_spec.rb +15 -0
  57. data/spec/monkey_action_eat_spec.rb +86 -0
  58. data/spec/monkey_action_pause_spec.rb +91 -0
  59. data/spec/monkey_action_sleep_spec.rb +90 -0
  60. data/spec/monkey_action_type_spec.rb +94 -0
  61. data/spec/monkey_action_wake_spec.rb +58 -0
  62. data/spec/monkey_factory_spec.rb +23 -0
  63. data/spec/monkey_keyboard_en_us_spec.rb +42 -0
  64. data/spec/monkey_manager_spec.rb +8 -0
  65. data/spec/monkey_service_spec.rb +96 -0
  66. data/spec/monkey_spec.rb +8 -0
  67. data/spec/spec_helpers.rb +20 -0
  68. data/spec/support/shared_examples.rb +41 -0
  69. metadata +258 -0
@@ -0,0 +1,6 @@
1
+ require_relative 'MonkeyAction/monkey_action_dead'
2
+ require_relative 'MonkeyAction/monkey_action_eat'
3
+ require_relative 'MonkeyAction/monkey_action_pause'
4
+ require_relative 'MonkeyAction/monkey_action_sleep'
5
+ require_relative 'MonkeyAction/monkey_action_type'
6
+ require_relative 'MonkeyAction/monkey_action_wake'
@@ -0,0 +1 @@
1
+ require_relative 'MonkeyEngine/monkey_engine'
@@ -0,0 +1,111 @@
1
+ require 'time'
2
+ require 'singleton'
3
+
4
+ require 'MonkeyActions'
5
+ require 'MonkeyKeyboardEnUs'
6
+
7
+ # Handles monkey action rules.
8
+ class ActionRules
9
+ include Singleton
10
+
11
+ # Retrieves tne next action for the monkey
12
+ #
13
+ # @param [monkey] the monkey whose next action is to be retrieved
14
+ # @return [MonkeyAction] the next monkey action
15
+ def get_next_action(monkey)
16
+ raise MonkeyEngine::Exceptions::InvalidOperationException.new \
17
+ "The action [#{monkey.action.class.name}] for Monkey [#{monkey.monkey_symbol}] must be completed before calling get_next_action" \
18
+ unless monkey.action.nil? || monkey.action.action_completed?
19
+
20
+ # current_action = monkey.action
21
+
22
+ # If the monkey is sleeping, or first action, wake him up.
23
+ return MonkeyActionWake.new(monkey) if monkey.action.nil? || monkey.action.is_a?(MonkeyActionSleep)
24
+
25
+ return get_next_action_eval(monkey) unless nil
26
+
27
+ # Nothing else interesting, monkey takes a breather...
28
+ # MonkeyActionPause.new(monkey, Random.new.rand(MonkeyActionPause::VALID_VALUES))
29
+ MonkeyActionPause.new(monkey, 5)
30
+ end
31
+
32
+ def get_next_action_eval(monkey)
33
+ # TODO: Add logic to determine next logical action.
34
+
35
+ keyboard_input = MonkeyEngine::MonkeyKeyboardEnUs.instance.get_keyboard_input
36
+
37
+ return MonkeyActionType.new monkey, keyboard_input
38
+ end
39
+
40
+ # Evaluates an action and sets it to completed if the criteria for completion is met.
41
+ def action_eval!(action)
42
+ raise MonkeyEngine::Exceptions::NilArgumentException.new "The [action] to be evaluated cannot be nil" \
43
+ if action.nil?
44
+
45
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
46
+ unless action.is_a? Action
47
+
48
+ action_eval_eat(action) if action.is_a?(MonkeyActionEat)
49
+ action_eval_pause(action) if action.is_a?(MonkeyActionPause)
50
+ action_eval_sleep(action) if action.is_a?(MonkeyActionSleep)
51
+ action_eval_type(action) if action.is_a?(MonkeyActionType)
52
+ action_eval_wake(action) if action.is_a?(MonkeyActionWake)
53
+
54
+ # If we don't specifically handle the action, just let it pass through - Action#action_completed will
55
+ # be set elsewhere.
56
+ action.action_completed?
57
+ end
58
+
59
+ private
60
+
61
+ # Action evaluation methods
62
+
63
+ def action_eval_eat(action)
64
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
65
+ unless action.is_a? MonkeyActionEat
66
+
67
+ action_eval_timed_action action
68
+ end
69
+
70
+ def action_eval_pause(action)
71
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
72
+ unless action.is_a? MonkeyActionPause
73
+
74
+ action_eval_timed_action action
75
+ end
76
+
77
+ def action_eval_sleep(action)
78
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
79
+ unless action.is_a? MonkeyActionSleep
80
+
81
+ action_eval_timed_action action
82
+ end
83
+
84
+ def action_eval_type(action)
85
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
86
+ unless action.is_a? MonkeyActionType
87
+
88
+ # TODO: How do I evaluate this?
89
+
90
+ action
91
+ end
92
+
93
+ def action_eval_wake(action)
94
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
95
+ unless action.is_a? MonkeyActionWake
96
+
97
+ action.action_completed = true
98
+
99
+ action
100
+ end
101
+
102
+ def action_eval_timed_action(action)
103
+ raise MonkeyEngine::Exceptions::InvalidArgumentTypeException.new "The [action] is not the correct type" \
104
+ unless action.is_a? MonkeyTimedAction
105
+
106
+ action.action_completed = true if action.action_time_of_completion <= Time.now
107
+
108
+ action
109
+ end
110
+
111
+ end
@@ -0,0 +1,21 @@
1
+ require 'test/unit/assertions'
2
+
3
+ module MonkeyEngine
4
+ module Exceptions
5
+ class InvalidArgumentValueException < ArgumentError;
6
+ end
7
+
8
+ class InvalidArgumentTypeException < ArgumentError;
9
+ end
10
+
11
+ class NilArgumentException < ArgumentError;
12
+ end
13
+
14
+ # The object must be unique.
15
+ class UniqueObjectException < ArgumentError;
16
+ end
17
+
18
+ class InvalidOperationException < ArgumentError;
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,53 @@
1
+ require 'observer'
2
+ require 'singleton'
3
+ require 'time'
4
+
5
+ require 'MonkeyActions'
6
+ require_relative 'action_rules'
7
+
8
+ module MonkeyEngine
9
+
10
+ # Assigns, executes and evaluates actions.
11
+ class Engine
12
+ include Singleton
13
+ include Observable
14
+
15
+ private
16
+ def initialize
17
+ end
18
+
19
+ public
20
+
21
+ # Evaluates whether or not the action is completed.
22
+ def action_eval!(action)
23
+ ActionRules.instance.action_eval! action
24
+ end
25
+
26
+ def do_action(action)
27
+ raise MonkeyEngine::Exceptions::InvalidOperationException.new \
28
+ "The action [#{action.class.name}] for Monkey [#{action.monkey.monkey_symbol}] is already completed" if action.action_completed?
29
+
30
+ do_action_type(action) if action.is_a? MonkeyActionType
31
+
32
+ # TODO: Update database for monkey with action detail
33
+ # TODO: Call observer to notify of action update.
34
+ # TODO: Set action.action_completed to true if the action is completed.
35
+
36
+ action.action_completed?
37
+ end
38
+
39
+ def do_action_type(action)
40
+ action.action_completed = true
41
+ end
42
+
43
+ # Returns a new action.
44
+ def new_action(monkey)
45
+ raise MonkeyEngine::Exceptions::InvalidOperationException.new \
46
+ "The action [#{monkey.action.class.name}] for Monkey [#{monkey.monkey_symbol}] must be completed before calling new_action" \
47
+ unless monkey.action.nil? || monkey.action.action_completed?
48
+
49
+ return ActionRules.instance.get_next_action monkey
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module MonkeyEngine
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1 @@
1
+ require_relative 'MonkeyFactory/monkey_factory'
@@ -0,0 +1,14 @@
1
+ require 'Monkey'
2
+
3
+ module MonkeyFactory
4
+
5
+ class << self
6
+
7
+ public
8
+ def create(monkey_symbol)
9
+ # Call the protected constructor - monkeys can only be created
10
+ # via the MonkeyFactory.
11
+ Monkey.send(:new, monkey_symbol)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ # Represents a keyboard character.
2
+ class KeyboardChar
3
+
4
+ attr_reader :char
5
+
6
+ def initialize(char)
7
+ @char = char
8
+ self
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ # Represents keyboard input.
2
+ class KeyboardInput
3
+
4
+ attr_accessor :is_word, :input
5
+
6
+ def initialize
7
+ @is_word = false
8
+ @input = Array.new
9
+ end
10
+
11
+ def input_to_s
12
+ @input.join.to_s
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'keyboard_char'
2
+
3
+ # Represents a keyboard key.
4
+ class KeyboardKey
5
+ attr_reader :keyboard_char, :keyboard_shift_char, :keyboard_key_section, :keyboard_key_weight
6
+
7
+ def initialize(keyboard_char, keyboard_shift_char, keyboard_key_section, keyboard_key_weight)
8
+ # TODO: Check keyboard_char is_a? KeyboardChar
9
+ # TODO: Check keyboard_shift_char is_a? KeyboardChar
10
+ # TODO: Check keyboard_key_section is :left or :right
11
+
12
+ @keyboard_char = keyboard_char
13
+ @keyboard_shift_char = keyboard_shift_char
14
+ @keyboard_key_section = keyboard_key_section
15
+ @keyboard_key_weight = keyboard_key_weight
16
+ end
17
+
18
+ def self.make_key(char, shift_char, keyboard_key_section, keyboard_key_weight)
19
+ # TODO: Check keyboard_key_section is :left or :right
20
+
21
+ keyboard_char = KeyboardChar.new char
22
+ keyboard_shift_char = KeyboardChar.new shift_char
23
+
24
+ KeyboardKey.new keyboard_char, keyboard_shift_char, keyboard_key_section, keyboard_key_weight
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ class KeyboardKeyEvaluator
2
+ def initialize
3
+ @shift_on = false
4
+ @caps_on = false
5
+ end
6
+
7
+ def get_char(keyboard_key)
8
+ @shift_on = !@shift_on if keyboard_key.keyboard_char.char == :shift
9
+ @caps_on = !@shift_on if keyboard_key.keyboard_char.char == :caps
10
+
11
+ return nil if keyboard_key.keyboard_char.char.is_a? Symbol
12
+
13
+ if @shift_on
14
+ return keyboard_key.keyboard_shift_char.char
15
+ end
16
+
17
+ char = keyboard_key.keyboard_char.char
18
+
19
+ if @caps_on
20
+ return char.upcase
21
+ end
22
+
23
+ char
24
+ end
25
+ end
@@ -0,0 +1,137 @@
1
+ require 'singleton'
2
+ require 'LittleWeasel'
3
+
4
+ require_relative 'keyboard_char'
5
+ require_relative 'keyboard_key'
6
+ require_relative 'keyboard_input'
7
+ require_relative 'keyboard_key_evaluator'
8
+
9
+
10
+ module MonkeyEngine
11
+
12
+ class MonkeyKeyboardEnUs
13
+ include Singleton
14
+
15
+ attr_reader :keys, :left_keys, :right_keys
16
+
17
+ def initialize
18
+
19
+ @keys = [
20
+ # Row 1 of 5
21
+ KeyboardKey::make_key('`', '~', :left, 1),
22
+ KeyboardKey::make_key('1', '!', :left, 1),
23
+ KeyboardKey::make_key('2', '@', :left, 1),
24
+ KeyboardKey::make_key('3', '#', :left, 1),
25
+ KeyboardKey::make_key('4', '$', :left, 1),
26
+ KeyboardKey::make_key('5', '%', :left, 1),
27
+ KeyboardKey::make_key('6', '^', :left, 1),
28
+ KeyboardKey::make_key('7', '&', :right, 1),
29
+ KeyboardKey::make_key('8', '*', :right, 1),
30
+ KeyboardKey::make_key('9', '(', :right, 1),
31
+ KeyboardKey::make_key('0', ')', :right, 1),
32
+ KeyboardKey::make_key('-', '_', :right, 1),
33
+ KeyboardKey::make_key('=', '+', :right, 1),
34
+ KeyboardKey::make_key(:del, :del, :right, 1),
35
+
36
+ # Row 2 of 5
37
+ KeyboardKey::make_key(:tab, :tab, :left, 2),
38
+ KeyboardKey::make_key('q', 'Q', :left, 1),
39
+ KeyboardKey::make_key('w', 'W', :left, 1),
40
+ KeyboardKey::make_key('e', 'E', :left, 1),
41
+ KeyboardKey::make_key('r', 'R', :left, 1),
42
+ KeyboardKey::make_key('t', 'T', :left, 1),
43
+ KeyboardKey::make_key('y', 'Y', :left, 1),
44
+ KeyboardKey::make_key('u', 'U', :right, 1),
45
+ KeyboardKey::make_key('i', 'I', :right, 1),
46
+ KeyboardKey::make_key('o', 'O', :right, 1),
47
+ KeyboardKey::make_key('p', 'P', :right, 1),
48
+ KeyboardKey::make_key('', '{', :right, 1),
49
+ KeyboardKey::make_key('', '}', :right, 1),
50
+ KeyboardKey::make_key('\\', '|', :right, 1),
51
+
52
+ # Row 3 of 5
53
+ KeyboardKey::make_key(:caps, :caps, :left, 3),
54
+ KeyboardKey::make_key('a', 'A', :left, 1),
55
+ KeyboardKey::make_key('s', 'S', :left, 1),
56
+ KeyboardKey::make_key('d', 'D', :left, 1),
57
+ KeyboardKey::make_key('f', 'F', :left, 1),
58
+ KeyboardKey::make_key('g', 'G', :left, 1),
59
+ KeyboardKey::make_key('h', 'H', :right, 1),
60
+ KeyboardKey::make_key('j', 'J', :right, 1),
61
+ KeyboardKey::make_key('k', 'K', :right, 1),
62
+ KeyboardKey::make_key('l', 'L', :right, 1),
63
+ KeyboardKey::make_key(';', ':', :right, 1),
64
+ KeyboardKey::make_key('\'', '"', :right, 1),
65
+ KeyboardKey::make_key(:enter, :enter, :right, 2),
66
+
67
+ # Row 4 of 5
68
+ KeyboardKey::make_key(:shift, :shift, :left, 5),
69
+ KeyboardKey::make_key('z', 'Z', :left, 1),
70
+ KeyboardKey::make_key('x', 'X', :left, 1),
71
+ KeyboardKey::make_key('c', 'C', :left, 1),
72
+ KeyboardKey::make_key('v', 'V', :left, 1),
73
+ KeyboardKey::make_key('b', 'B', :left, 1),
74
+ KeyboardKey::make_key('n', 'N', :right, 1),
75
+ KeyboardKey::make_key('m', 'M', :right, 1),
76
+ KeyboardKey::make_key(',', '<', :right, 1),
77
+ KeyboardKey::make_key('.', '>', :right, 1),
78
+ KeyboardKey::make_key('/', '?', :right, 1),
79
+ KeyboardKey::make_key(:shift, :shift, :right, 5),
80
+
81
+ # Row 5 of 5
82
+ KeyboardKey::make_key(:space, :space, :left, 2),
83
+ KeyboardKey::make_key(:space, :space, :right, 2)
84
+ ]
85
+
86
+ @left_keys = []
87
+ @right_keys = []
88
+
89
+ @keys.each { |key|
90
+ # Separate the keys on the left side of the keyboard...
91
+ key.keyboard_key_weight.times do
92
+ left_keys.push(key)
93
+ end if key.keyboard_key_section == :left
94
+
95
+ # Separate the keys on the right side of the keyboard...
96
+ key.keyboard_key_weight.times do
97
+ right_keys.push(key)
98
+ end if key.keyboard_key_section == :right
99
+ }
100
+
101
+ @keys.freeze
102
+ @keys_left.freeze
103
+ @keys_right.freeze
104
+ end
105
+
106
+ def get_keyboard_input
107
+ keyboard_input = KeyboardInput.new
108
+
109
+ left_keys = @left_keys
110
+ right_keys = @right_keys
111
+
112
+ keys = left_keys.zip(right_keys).flatten.compact.shuffle
113
+
114
+ keyboard_key_evaluator = KeyboardKeyEvaluator.new
115
+
116
+ # Take the keys until we hit a key that terminates a word...
117
+ keyboard_input.input = keys.take_while { |key|
118
+ !keyboard_char_ends_word?(key.keyboard_char.char)
119
+ }.collect { |key| keyboard_key_evaluator.get_char(key) }.compact
120
+
121
+ # Keep going until we get something...
122
+ keyboard_input = get_keyboard_input if keyboard_input.input.empty?
123
+
124
+ keyboard_input.is_word = LittleWeasel::Checker.instance.exists?(keyboard_input.input_to_s,
125
+ exclude_alphabet: true, strip_whitespace: true, ignore_numeric: false, single_word_mode: true)
126
+
127
+ keyboard_input
128
+ end
129
+
130
+ # Returns true if the character causes a word termination.
131
+ def keyboard_char_ends_word?(char)
132
+ return char == :tab || char == :enter || char == :space || char == '.'
133
+ end
134
+
135
+ end
136
+
137
+ end
@@ -0,0 +1 @@
1
+ require_relative 'MonkeyKeyboard/monkey_keyboard_en_us'