behave_fun 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 935e48b4d598edb584ef80612774fec7028552597b1a6e56b4d2ec4b6283f616
4
- data.tar.gz: 9a51961b11ec757601e3912eee99918a4ec9b39b7913d7dc95aaae25218bc627
3
+ metadata.gz: a7a9e0845eb973be63f59ba48dcceaf4e7a98ba28b4c29c1b11db4e5c98cc505
4
+ data.tar.gz: f4eda02740d8e094cc7191651053e8ba34c289d01381f4cd3c9493679d574e62
5
5
  SHA512:
6
- metadata.gz: e2a1e6a8aa77715d47b2238920626da6b232e75e4fd92cc22b525c88d7de1036c54d1c704aa29dc5276fce1573876b164b48e6492102288a5168e0c1ccb3d41f
7
- data.tar.gz: 5592475d04f9fb7198f4d6222673a98ebe6dbeec7ecd80e22fcf580022f4a8b7ced2901dfda2e8da887b5ca432fd1a48164ebdc5b6f89914405e14d77da69fe0
6
+ metadata.gz: 23c14f5aee8434fc001ff9579e64454247ca46b4ae9cf84260bb47575b81a16e662611ba7a57d86ac75769d2d87f0bcee605c9f2ebd8137cf76855dcc8faf7ad
7
+ data.tar.gz: 8335771314c4fbb5e09c0cef08d77da21a114cbd5d0f1cb6707966ca530ffb2ac80c2517aff056fd4ad6c8e490347f6e672121ae7999398d804c3d7c87c6b376
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- behave_fun (0.1.2)
4
+ behave_fun (0.2.0)
5
5
  activesupport (~> 6.0.0)
6
6
  zeitwerk (~> 2.3.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (6.0.3)
11
+ activesupport (6.0.3.1)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 0.7, < 2)
14
14
  minitest (~> 5.1)
data/README.md CHANGED
@@ -13,36 +13,43 @@ Main features:
13
13
 
14
14
  Add this line to your application's Gemfile:
15
15
 
16
- ```ruby
16
+ ``` ruby
17
17
  gem 'behave_fun'
18
18
  ```
19
19
 
20
20
  And then execute:
21
21
 
22
+ ```
22
23
  $ bundle install
24
+ ```
23
25
 
24
26
  Or install it yourself as:
25
27
 
28
+ ```
26
29
  $ gem install behave_fun
30
+ ```
27
31
 
28
32
  ## Usage
29
33
 
30
34
  To build a behavior tree:
31
35
 
32
36
  ``` ruby
37
+ builder = BehaveFun.build_builder {
38
+ # add_task_type YourCustomTask
39
+ }
33
40
  # ruby dsl
34
- tree = BehaveFun.build_tree { success }
41
+ tree = builder.build_tree { success }
35
42
  # from hash
36
- tree = BehaveFun.build_tree_from_hash(type: :success)
43
+ tree = builder.build_tree_from_hash(type: :success)
37
44
  # from json
38
- tree = BehaveFun.build_tree_from_json(json_string)
45
+ tree = builder.build_tree_from_json(json_string)
39
46
  ```
40
47
 
41
48
  To build a complex behavior tree:
42
49
 
43
50
  ``` ruby
44
51
  # write_spec, write_code, run_spec, git_push and release_gem are customized tasks
45
- tree = BehaveFun.build_tree {
52
+ tree = builder.build_tree {
46
53
  sequence {
47
54
  until_success {
48
55
  sequence {
@@ -57,7 +64,7 @@ tree = BehaveFun.build_tree {
57
64
  }
58
65
  ```
59
66
 
60
- To create customized task, create a class that extends `BehaveFun::Task`. Don't forget call `running` `success` or `fail` in `#execute` method at the end.
67
+ To create customized task, create a class that extends `BehaveFun::Task` (or use a lambda if only need to overwrite `#execute` method). Don't forget call `running` `success` or `fail` in `#execute` method at the end.
61
68
 
62
69
  ``` ruby
63
70
  # a task that increase data by 1, always success
@@ -66,18 +73,17 @@ class Counter < BehaveFun::Task
66
73
  context[:counter] += 1
67
74
  success
68
75
  end
69
-
70
- add_to_task_builder
71
76
  end
72
77
 
73
78
  # a task that detect tree data is even or not
74
- class IsCounterEven < BehaveFun::Task
75
- def execute
76
- context[:counter].even? ? success : fail
77
- end
79
+ is_counter_even = -> { context[:counter].even? ? success : fail }
78
80
 
79
- add_to_task_builder
80
- end
81
+ # add these tasks to your builder
82
+ builder = BehaveFun.build_builder {
83
+ add_task_type Counter
84
+ add_lambda_task_type :is_counter_even, &is_counter_even
85
+ }
86
+ builder.build_tree { counter }
81
87
  ```
82
88
 
83
89
  To run a tree:
data/lib/behave_fun.rb CHANGED
@@ -9,35 +9,8 @@ loader.setup
9
9
  module BehaveFun
10
10
  module_function
11
11
 
12
- def build_task(&block)
13
- task = build_tree(&block).root
14
- task.control = nil
15
- task
16
- end
17
-
18
- def build_tree(&block)
19
- builder = TaskBuilder.new(Tree.new)
20
- builder.instance_eval(&block)
21
- builder.control
22
- end
23
-
24
- def build_tree_from_hash(hash)
25
- build_tree do
26
- build_from_hash(hash[:root])
27
- end
28
- end
29
-
30
- def build_tree_from_json(json)
31
- hash = ActiveSupport::JSON.decode(json).deep_symbolize_keys
32
- build_tree_from_hash(hash)
33
- end
34
-
35
- def as_json(tree)
36
- tree.as_json
37
- end
38
-
39
- def to_json(tree)
40
- ActiveSupport::JSON.encode(as_json(tree))
12
+ def build_builder(&block)
13
+ BehaveFun::TaskBuilderFactory.new(&block)
41
14
  end
42
15
 
43
16
  class Error < StandardError; end
@@ -26,7 +26,5 @@ module BehaveFun
26
26
  def child_fail
27
27
  fail
28
28
  end
29
-
30
- add_to_task_builder
31
29
  end
32
30
  end
@@ -16,7 +16,5 @@ module BehaveFun
16
16
  def serializable_status_fields
17
17
  [:current_child_idx, :order]
18
18
  end
19
-
20
- add_to_task_builder
21
19
  end
22
20
  end
@@ -16,7 +16,5 @@ module BehaveFun
16
16
  def serializable_status_fields
17
17
  [:current_child_idx, :order]
18
18
  end
19
-
20
- add_to_task_builder
21
19
  end
22
20
  end
@@ -31,7 +31,5 @@ module BehaveFun
31
31
  def serializable_status_fields
32
32
  [:current_child_idx]
33
33
  end
34
-
35
- add_to_task_builder
36
34
  end
37
35
  end
@@ -31,7 +31,5 @@ module BehaveFun
31
31
  def serializable_status_fields
32
32
  [:current_child_idx]
33
33
  end
34
-
35
- add_to_task_builder
36
34
  end
37
35
  end
@@ -3,7 +3,5 @@ module BehaveFun
3
3
  def child_success
4
4
  fail
5
5
  end
6
-
7
- add_to_task_builder
8
6
  end
9
7
  end
@@ -3,7 +3,5 @@ module BehaveFun
3
3
  def child_fail
4
4
  success
5
5
  end
6
-
7
- add_to_task_builder
8
6
  end
9
7
  end
@@ -7,7 +7,5 @@ module BehaveFun
7
7
  def child_success
8
8
  fail
9
9
  end
10
-
11
- add_to_task_builder
12
10
  end
13
11
  end
@@ -2,21 +2,16 @@ module BehaveFun
2
2
  class Decorators::Repeat < Decorator
3
3
  attr_accessor :counter
4
4
 
5
- def initialize(times: -1)
6
- super
7
- @times = times
8
- end
9
-
10
5
  def start
11
6
  super
12
7
  @counter = 0
13
8
  end
14
9
 
15
10
  def child_success
16
- return @children[0].reset if @times == -1
11
+ return @children[0].reset unless params[:times]
17
12
 
18
13
  @counter += 1
19
- if @counter < @times
14
+ if @counter < params[:times]
20
15
  @children[0].reset
21
16
  else
22
17
  success
@@ -30,7 +25,5 @@ module BehaveFun
30
25
  def serializable_status_fields
31
26
  [:counter]
32
27
  end
33
-
34
- add_to_task_builder
35
28
  end
36
29
  end
@@ -3,7 +3,5 @@ module BehaveFun
3
3
  def child_fail
4
4
  success
5
5
  end
6
-
7
- add_to_task_builder
8
6
  end
9
7
  end
@@ -3,7 +3,5 @@ module BehaveFun
3
3
  def child_success
4
4
  success
5
5
  end
6
-
7
- add_to_task_builder
8
6
  end
9
7
  end
@@ -3,7 +3,5 @@ module BehaveFun
3
3
  def execute
4
4
  fail
5
5
  end
6
-
7
- add_to_task_builder
8
6
  end
9
7
  end
@@ -3,7 +3,5 @@ module BehaveFun
3
3
  def execute
4
4
  success
5
5
  end
6
-
7
- add_to_task_builder
8
6
  end
9
7
  end
@@ -2,18 +2,13 @@ module BehaveFun
2
2
  class LeafTasks::Wait < Task
3
3
  attr_accessor :counter
4
4
 
5
- def initialize(duration: )
6
- super
7
- @duration = duration
8
- end
9
-
10
5
  def start
11
6
  super
12
7
  @counter = 0
13
8
  end
14
9
 
15
10
  def execute
16
- if @counter < @duration
11
+ if @counter < params[:duration]
17
12
  @counter += 1
18
13
  running
19
14
  else
@@ -24,7 +19,5 @@ module BehaveFun
24
19
  def serializable_status_fields
25
20
  [:counter]
26
21
  end
27
-
28
- add_to_task_builder
29
22
  end
30
23
  end
@@ -5,7 +5,7 @@ module BehaveFun
5
5
  attr_accessor :control, :guard
6
6
  attr_reader :context, :children, :params, :status
7
7
 
8
- def initialize(**params)
8
+ def initialize(params = {})
9
9
  @params = params
10
10
  @children = []
11
11
  @status = :fresh
@@ -15,10 +15,6 @@ module BehaveFun
15
15
  name.demodulize.underscore
16
16
  end
17
17
 
18
- def self.add_to_task_builder(name = task_name)
19
- BehaveFun::TaskBuilder.add_task_type(self, name: name)
20
- end
21
-
22
18
  def context=(context)
23
19
  @context = context
24
20
  children.each { _1.context = context }
@@ -119,5 +115,11 @@ module BehaveFun
119
115
  @status = :fresh
120
116
  children.each { |child| child.reset }
121
117
  end
118
+
119
+ def dup
120
+ cloned = self.class.new(params)
121
+ children.each { cloned.add_child(_1.dup) }
122
+ cloned
123
+ end
122
124
  end
123
125
  end
@@ -0,0 +1,130 @@
1
+ module BehaveFun
2
+ class TaskBuilderFactory
3
+ attr_reader :tasks
4
+
5
+ def initialize(&block)
6
+ @tasks = {}
7
+
8
+ add_task_type BehaveFun::LeafTasks::Success
9
+ add_task_type BehaveFun::LeafTasks::Failure
10
+ add_task_type BehaveFun::LeafTasks::Wait
11
+ add_task_type BehaveFun::Decorators::AlwaysSucceed
12
+ add_task_type BehaveFun::Decorators::AlwaysFail
13
+ add_task_type BehaveFun::Decorators::UntilSuccess
14
+ add_task_type BehaveFun::Decorators::UntilFail
15
+ add_task_type BehaveFun::Decorators::Invert
16
+ add_task_type BehaveFun::Decorators::Repeat
17
+ add_task_type BehaveFun::BranchTasks::Sequence
18
+ add_task_type BehaveFun::BranchTasks::Selector
19
+ add_task_type BehaveFun::BranchTasks::RandomSequence
20
+ add_task_type BehaveFun::BranchTasks::RandomSelector
21
+ add_task_type BehaveFun::BranchTasks::DynamicGuardSelector
22
+
23
+ instance_eval(&block) if block_given?
24
+ end
25
+
26
+ def add_task_type(type, name: type.task_name)
27
+ tasks[name.to_sym] = type
28
+ end
29
+
30
+ def add_lambda_task_type(task_name, &block)
31
+ type = Class.new(Task) do
32
+ def name
33
+ task_name
34
+ end
35
+
36
+ define_method(:execute, &block)
37
+ end
38
+ tasks[task_name.to_sym] = type
39
+ end
40
+
41
+ def build_task(&block)
42
+ task = build_tree(&block).root
43
+ task.control = nil
44
+ task
45
+ end
46
+
47
+ def build_tree(&block)
48
+ builder = Builder.new(self, Tree.new)
49
+ builder.instance_eval(&block)
50
+ builder.control
51
+ end
52
+
53
+ def build_task_from_hash(hash)
54
+ tree = build_tree do
55
+ build_from_hash(hash)
56
+ end
57
+ tree.root
58
+ end
59
+
60
+ def build_tree_from_hash(hash)
61
+ build_tree do
62
+ build_from_hash(hash[:root])
63
+ end
64
+ end
65
+
66
+ def build_tree_from_json(json)
67
+ hash = ActiveSupport::JSON.decode(json).deep_symbolize_keys
68
+ build_tree_from_hash(hash)
69
+ end
70
+
71
+ def as_json(tree)
72
+ tree.as_json
73
+ end
74
+
75
+ def to_json(tree)
76
+ ActiveSupport::JSON.encode(as_json(tree))
77
+ end
78
+
79
+ class Builder
80
+ attr_reader :factory, :control
81
+
82
+ def initialize(factory, control)
83
+ @factory = factory
84
+ @control = control
85
+ end
86
+
87
+ def add_task(type, params = {}, &block)
88
+ task = type.new(params)
89
+ @control.add_child(task)
90
+
91
+ if block
92
+ builder = Builder.new(factory, task)
93
+ builder.instance_eval(&block)
94
+ end
95
+ end
96
+
97
+ def guard_with(&block)
98
+ builder = Builder.new(factory, Tree.new)
99
+ builder.instance_eval(&block)
100
+ control.guard = builder.control.root
101
+ end
102
+
103
+ def include(task)
104
+ cloned_task = task.dup
105
+ @control.add_child(cloned_task)
106
+ end
107
+
108
+ def build_from_hash(task_hash)
109
+ type_name, params, guard_with, children =
110
+ task_hash.values_at(:type, :params, :guard_with, :children)
111
+ params ||= {}
112
+ children ||= []
113
+ type = factory.tasks[type_name.to_sym]
114
+ add_task type, **params do
115
+ guard_with { build_from_hash(guard_with) } if guard_with
116
+ children.each { build_from_hash(_1) }
117
+ end
118
+ end
119
+
120
+ def method_missing(name, *args, &block)
121
+ type = factory.tasks[name.to_sym]
122
+ if type
123
+ add_task(type, *args, &block)
124
+ else
125
+ super
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,3 +1,3 @@
1
1
  module BehaveFun
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: behave_fun
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ayaya zhao
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-17 00:00:00.000000000 Z
11
+ date: 2020-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -74,7 +74,7 @@ files:
74
74
  - lib/behave_fun/leaf_tasks/success.rb
75
75
  - lib/behave_fun/leaf_tasks/wait.rb
76
76
  - lib/behave_fun/task.rb
77
- - lib/behave_fun/task_builder.rb
77
+ - lib/behave_fun/task_builder_factory.rb
78
78
  - lib/behave_fun/task_serializer.rb
79
79
  - lib/behave_fun/tree.rb
80
80
  - lib/behave_fun/version.rb
@@ -1,53 +0,0 @@
1
- module BehaveFun
2
- class TaskBuilder
3
- attr_reader :control
4
-
5
- def initialize(control)
6
- @control = control
7
- end
8
-
9
- def add_task(type, **params, &block)
10
- task = type.new(**params)
11
- @control.add_child(task)
12
-
13
- if block
14
- builder = TaskBuilder.new(task)
15
- builder.instance_eval(&block)
16
- end
17
- end
18
-
19
- def guard_with(&block)
20
- builder = TaskBuilder.new(Tree.new)
21
- builder.instance_eval(&block)
22
- control.guard = builder.control.root
23
- end
24
-
25
- def include(task)
26
- cloned_task = BehaveFun.build_task { build_from_hash(task.as_json) }
27
- @control.add_child(cloned_task)
28
- end
29
-
30
- def build_from_hash(task_hash)
31
- type_name, params, guard_with, children =
32
- task_hash.values_at(:type, :params, :guard_with, :children)
33
- params ||= {}
34
- children ||= []
35
- type = self.class.tasks[type_name.to_sym]
36
- add_task type, **params do
37
- guard_with { build_from_hash(guard_with) } if guard_with
38
- children.each { build_from_hash(_1) }
39
- end
40
- end
41
-
42
- def self.tasks
43
- @tasks ||= {}
44
- end
45
-
46
- def self.add_task_type(type, name: type.task_name)
47
- tasks[name.to_sym] = type
48
- define_method name do |params = {}, &block|
49
- add_task(type, **params, &block)
50
- end
51
- end
52
- end
53
- end