MonkeyEngine 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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'