MonkeyEngine 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.idea/.name +1 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/MonkeyEngine.iml +133 -0
- data/.idea/codeStyleSettings.xml +13 -0
- data/.idea/encodings.xml +5 -0
- data/.idea/misc.xml +5 -0
- data/.idea/modules.xml +9 -0
- data/.idea/runConfigurations/All_specs_in_test__MonkeyEngine.xml +38 -0
- data/.idea/runConfigurations/IRB_console.xml +25 -0
- data/.idea/runConfigurations/Start_Yard_Server.xml +26 -0
- data/.idea/runConfigurations/monkey_run.xml +26 -0
- data/.idea/scopes/scope_settings.xml +5 -0
- data/.idea/vcs.xml +7 -0
- data/.idea/workspace.xml +886 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +3 -0
- data/lib/Action/action.rb +29 -0
- data/lib/Monkey.rb +1 -0
- data/lib/Monkey/monkey.rb +108 -0
- data/lib/MonkeyAction/monkey_action.rb +14 -0
- data/lib/MonkeyAction/monkey_action_dead.rb +26 -0
- data/lib/MonkeyAction/monkey_action_eat.rb +31 -0
- data/lib/MonkeyAction/monkey_action_pause.rb +32 -0
- data/lib/MonkeyAction/monkey_action_sleep.rb +31 -0
- data/lib/MonkeyAction/monkey_action_type.rb +40 -0
- data/lib/MonkeyAction/monkey_action_wake.rb +26 -0
- data/lib/MonkeyAction/monkey_timed_action.rb +27 -0
- data/lib/MonkeyActions.rb +6 -0
- data/lib/MonkeyEngine.rb +1 -0
- data/lib/MonkeyEngine/action_rules.rb +111 -0
- data/lib/MonkeyEngine/exceptions.rb +21 -0
- data/lib/MonkeyEngine/monkey_engine.rb +53 -0
- data/lib/MonkeyEngine/version.rb +3 -0
- data/lib/MonkeyFactory.rb +1 -0
- data/lib/MonkeyFactory/monkey_factory.rb +14 -0
- data/lib/MonkeyKeyboard/keyboard_char.rb +10 -0
- data/lib/MonkeyKeyboard/keyboard_input.rb +14 -0
- data/lib/MonkeyKeyboard/keyboard_key.rb +26 -0
- data/lib/MonkeyKeyboard/keyboard_key_evaluator.rb +25 -0
- data/lib/MonkeyKeyboard/monkey_keyboard_en_us.rb +137 -0
- data/lib/MonkeyKeyboardEnUs.rb +1 -0
- data/lib/MonkeyManager.rb +1 -0
- data/lib/MonkeyManager/monkey_manager.rb +162 -0
- data/lib/MonkeyService.rb +1 -0
- data/lib/MonkeyService/monkey_service.rb +137 -0
- data/lib/tasks/engine.rb +91 -0
- data/monkeyengine.gemspec +32 -0
- data/spec/action_rules_spec.rb +59 -0
- data/spec/engine_spec.rb +56 -0
- data/spec/keyboard_char_spec.rb +12 -0
- data/spec/keyboard_key_spec.rb +15 -0
- data/spec/monkey_action_eat_spec.rb +86 -0
- data/spec/monkey_action_pause_spec.rb +91 -0
- data/spec/monkey_action_sleep_spec.rb +90 -0
- data/spec/monkey_action_type_spec.rb +94 -0
- data/spec/monkey_action_wake_spec.rb +58 -0
- data/spec/monkey_factory_spec.rb +23 -0
- data/spec/monkey_keyboard_en_us_spec.rb +42 -0
- data/spec/monkey_manager_spec.rb +8 -0
- data/spec/monkey_service_spec.rb +96 -0
- data/spec/monkey_spec.rb +8 -0
- data/spec/spec_helpers.rb +20 -0
- data/spec/support/shared_examples.rb +41 -0
- 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'
|
data/lib/MonkeyEngine.rb
ADDED
@@ -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 @@
|
|
1
|
+
require_relative 'MonkeyFactory/monkey_factory'
|
@@ -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'
|