woyo-world 0.0.5 → 0.0.6
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.
- checksums.yaml +4 -4
- data/lib/woyo/world/attributes.rb +170 -26
- data/lib/woyo/world/group.rb +101 -0
- data/lib/woyo/world/version.rb +1 -1
- data/lib/woyo/world/way.rb +23 -8
- data/lib/woyo/world/world_object.rb +2 -0
- data/spec/woyo/world/attributes_spec.rb +358 -4
- data/spec/woyo/world/group_spec.rb +162 -0
- data/spec/woyo/world/language_spec.rb +157 -113
- data/spec/woyo/world/way_spec.rb +120 -1
- data/todo.txt +79 -37
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6b8db18d440d61ddaf291c7db149e5fa35f8a98
|
4
|
+
data.tar.gz: 393a37a546f63d71e2132374c927f0571d475c4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 465dab73ed8d398391a9e7ca63bac830b205a7622e895a5b1fc736ad36d7c2f36179a5713f7bece47aaf53ab6ecdb438937f9c8b026f730f5d3b9eff1e8f2f08
|
7
|
+
data.tar.gz: 033f7d8ddf1839495ead16bb0d65ae6e4e7df2469bb31ab7e5e7993483a41c7d8e4d1485d43eccd3844f2fd1ce0f6813fe02497ccd8bc9ca4e36bffe836dc076
|
@@ -1,31 +1,75 @@
|
|
1
|
+
require_relative 'group'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
alias_method :names, :keys
|
5
|
+
end
|
1
6
|
|
2
7
|
module Woyo
|
3
8
|
|
4
9
|
module Attributes
|
5
10
|
|
11
|
+
def self.included(base)
|
12
|
+
base.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.prepended(base)
|
16
|
+
base.singleton_class.prepend(ClassMethods) # base.extend(ClassMethods) also seems to work, what's the diff ?
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize *args
|
20
|
+
initialize_attributes
|
21
|
+
initialize_groups
|
22
|
+
initialize_boolean_groups
|
23
|
+
initialize_is_overrides
|
24
|
+
#super # we'll need this if we prepend Attributes again
|
25
|
+
end
|
26
|
+
|
6
27
|
module ClassMethods
|
7
28
|
|
8
|
-
def
|
29
|
+
def define_attr_methods attr, default = nil
|
30
|
+
define_attr_default attr, default
|
31
|
+
define_attr_equals attr
|
32
|
+
define_attr attr
|
33
|
+
if default == true || default == false # boolean convenience methods
|
34
|
+
define_attr? attr
|
35
|
+
define_attr! attr
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_attr_default attr, default
|
40
|
+
define_method "#{attr}_default" do
|
41
|
+
if default.respond_to? :call
|
42
|
+
return default.arity == 0 ? default.call : default.call(self)
|
43
|
+
end
|
44
|
+
default
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_attr_equals attr
|
9
49
|
define_method "#{attr}=" do |arg|
|
10
50
|
attributes[attr] = arg
|
11
51
|
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_attr attr
|
12
55
|
define_method attr do |arg = nil|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
56
|
+
return attributes[attr] = arg unless arg.nil?
|
57
|
+
return attributes[attr] unless attributes[attr].kind_of? Hash
|
58
|
+
true_attribute_match = attributes[attr].detect { |name,value| attributes[name] == true }
|
59
|
+
return true_attribute_match[1] if true_attribute_match
|
60
|
+
attributes[attr]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def define_attr? attr
|
65
|
+
define_method "#{attr}?" do
|
66
|
+
( send attr ) ? true : false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def define_attr! attr
|
71
|
+
define_method "#{attr}!" do
|
72
|
+
send "#{attr}=", true
|
29
73
|
end
|
30
74
|
end
|
31
75
|
|
@@ -35,24 +79,124 @@ module Attributes
|
|
35
79
|
attrs.each do |attr|
|
36
80
|
if attr.kind_of? Hash
|
37
81
|
attr.each do |attr_sym,default_value|
|
38
|
-
@attributes << attr_sym
|
39
|
-
|
82
|
+
@attributes << attr_sym unless @attributes.include? attr_sym
|
83
|
+
define_attr_methods attr_sym, default_value
|
40
84
|
end
|
41
85
|
else
|
42
|
-
@attributes
|
43
|
-
|
86
|
+
unless @attributes.include? attr
|
87
|
+
@attributes << attr
|
88
|
+
define_attr_methods attr
|
89
|
+
end
|
44
90
|
end
|
45
91
|
end
|
46
92
|
end
|
47
93
|
|
48
|
-
|
94
|
+
def attribute *attrs
|
95
|
+
self.attributes *attrs
|
96
|
+
end
|
97
|
+
|
98
|
+
def groups
|
99
|
+
@groups ||= {}
|
100
|
+
end
|
49
101
|
|
50
|
-
|
51
|
-
|
102
|
+
def group sym, *attrs
|
103
|
+
@groups ||= {}
|
104
|
+
group = @groups[sym] ? @groups[sym] : ( @groups[sym] = [] )
|
105
|
+
self.attributes *attrs
|
106
|
+
attrs.each do |attr|
|
107
|
+
if attr.kind_of? Hash
|
108
|
+
attr.each do |attr_sym,default_value|
|
109
|
+
group << attr_sym
|
110
|
+
end
|
111
|
+
else
|
112
|
+
group << attr
|
113
|
+
end
|
114
|
+
end
|
115
|
+
define_method sym do
|
116
|
+
groups[sym]
|
117
|
+
end
|
118
|
+
group
|
119
|
+
end
|
120
|
+
|
121
|
+
def boolean_groups
|
122
|
+
@boolean_groups ||={}
|
123
|
+
end
|
124
|
+
|
125
|
+
def group! sym, *attrs
|
126
|
+
@boolean_groups ||= {}
|
127
|
+
group = @boolean_groups[sym] ? @boolean_groups[sym] : ( @boolean_groups[sym] = [] )
|
128
|
+
self.attributes *attrs
|
129
|
+
attrs.each do |attr|
|
130
|
+
define_attr? attr
|
131
|
+
define_attr! attr
|
132
|
+
if attr.kind_of? Hash
|
133
|
+
attr.each do |attr_sym,default_value|
|
134
|
+
group << attr_sym
|
135
|
+
end
|
136
|
+
else
|
137
|
+
group << attr
|
138
|
+
end
|
139
|
+
end
|
140
|
+
define_method sym do
|
141
|
+
boolean_groups[sym]
|
142
|
+
end
|
143
|
+
group
|
144
|
+
end
|
145
|
+
|
146
|
+
def is *attrs
|
147
|
+
@is_overrides ||= []
|
148
|
+
attrs.each do |attr|
|
149
|
+
@is_overrides << attr unless @is_overrides.include? attr
|
150
|
+
self.attribute( { attr => true } )
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def is_overrides
|
155
|
+
@is_overrides ||= []
|
156
|
+
end
|
157
|
+
|
158
|
+
end # module ClassMethods
|
159
|
+
|
160
|
+
def initialize_attributes
|
161
|
+
@attributes = self.class.attributes.each_with_object(Woyo::Attributes::AttributesHash.new) do |attr,hash|
|
162
|
+
hash[attr] = send "#{attr}_default"
|
163
|
+
end
|
52
164
|
end
|
53
|
-
|
165
|
+
|
166
|
+
def initialize_groups
|
167
|
+
@groups = {}
|
168
|
+
self.class.groups.each { |sym,members| @groups[sym] = Woyo::Attributes::Group.new @attributes, *members }
|
169
|
+
@groups
|
170
|
+
end
|
171
|
+
|
172
|
+
def initialize_boolean_groups
|
173
|
+
@boolean_groups = {}
|
174
|
+
self.class.boolean_groups.each { |sym,members| @boolean_groups[sym] = Woyo::Attributes::BooleanGroup.new @attributes, *members }
|
175
|
+
@boolean_groups
|
176
|
+
end
|
177
|
+
|
178
|
+
def initialize_is_overrides
|
179
|
+
self.class.is_overrides.each { |attr| send "#{attr}!" }
|
180
|
+
end
|
181
|
+
|
54
182
|
def attributes
|
55
|
-
@attributes
|
183
|
+
@attributes
|
184
|
+
end
|
185
|
+
|
186
|
+
def groups
|
187
|
+
@groups
|
188
|
+
end
|
189
|
+
|
190
|
+
def boolean_groups
|
191
|
+
@boolean_groups
|
192
|
+
end
|
193
|
+
|
194
|
+
def is? attr
|
195
|
+
send "#{attr}?"
|
196
|
+
end
|
197
|
+
|
198
|
+
def is attr
|
199
|
+
send "#{attr}=", true
|
56
200
|
end
|
57
201
|
|
58
202
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Woyo
|
4
|
+
|
5
|
+
module Attributes
|
6
|
+
|
7
|
+
class AttributesHash < Hash
|
8
|
+
|
9
|
+
alias_method :names, :keys
|
10
|
+
alias_method :set, :[]=
|
11
|
+
|
12
|
+
attr_reader :listeners
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@listeners = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_attribute_listener attr, listener
|
19
|
+
@listeners[attr] = listener
|
20
|
+
end
|
21
|
+
|
22
|
+
def []= attr, value
|
23
|
+
old_value = self[attr]
|
24
|
+
super
|
25
|
+
if ( listener = @listeners[attr] ) && value != old_value
|
26
|
+
listener.notify attr, value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class Group
|
33
|
+
|
34
|
+
extend Forwardable
|
35
|
+
|
36
|
+
def_delegators :@members, :count
|
37
|
+
def_delegators :@attributes, :[], :[]=
|
38
|
+
|
39
|
+
attr_reader :members, :attributes
|
40
|
+
|
41
|
+
def initialize attributes, *members
|
42
|
+
@attributes = attributes
|
43
|
+
@members = members
|
44
|
+
end
|
45
|
+
|
46
|
+
def names
|
47
|
+
@members
|
48
|
+
end
|
49
|
+
|
50
|
+
def values
|
51
|
+
@attributes.values_at *@members
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class BooleanGroup < Group
|
57
|
+
|
58
|
+
attr_reader :default
|
59
|
+
|
60
|
+
def initialize attributes, *members
|
61
|
+
super
|
62
|
+
@default = @members.first
|
63
|
+
self[@default] = true
|
64
|
+
@members.each { |member| @attributes.add_attribute_listener member, self }
|
65
|
+
end
|
66
|
+
|
67
|
+
def []= this_member, value
|
68
|
+
raise '#{this_member} is not a member of this group' unless @members.include? this_member
|
69
|
+
super
|
70
|
+
if value #true
|
71
|
+
# sync group members via AttributesHash#set to prevent triggering notify
|
72
|
+
@members.each { |member| @attributes.set(member,false) unless member == this_member }
|
73
|
+
else #false
|
74
|
+
if self.count == 2 # binary group
|
75
|
+
@members.each { |member| @attributes.set member ,(member != this_member ) }
|
76
|
+
else
|
77
|
+
self[@default] = true # revert to default
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def notify this_member, value
|
83
|
+
# assuming value==true for now
|
84
|
+
# sync group members via AttributesHash#set to prevent re-triggering notify
|
85
|
+
@members.each { |member| @attributes.set(member,false) unless member == this_member }
|
86
|
+
end
|
87
|
+
|
88
|
+
def value
|
89
|
+
@members.detect { |member| @attributes[member] } # name of first member with true value
|
90
|
+
end
|
91
|
+
|
92
|
+
def default!
|
93
|
+
self[@default] = true
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
data/lib/woyo/world/version.rb
CHANGED
data/lib/woyo/world/way.rb
CHANGED
@@ -6,12 +6,26 @@ class Way < WorldObject
|
|
6
6
|
|
7
7
|
attributes :description, name: lambda { |this| this.id.to_s.capitalize }
|
8
8
|
|
9
|
+
group! :passable, :closed, :open # defaults to closed: true
|
10
|
+
|
11
|
+
def world
|
12
|
+
from ? from.world : nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def close!
|
16
|
+
closed!
|
17
|
+
end
|
18
|
+
|
9
19
|
def from
|
10
20
|
@from ||= context
|
11
21
|
end
|
12
22
|
|
13
|
-
def
|
14
|
-
|
23
|
+
def to arg=nil
|
24
|
+
if arg.nil?
|
25
|
+
@to
|
26
|
+
else
|
27
|
+
self.to = arg
|
28
|
+
end
|
15
29
|
end
|
16
30
|
|
17
31
|
def to= arg
|
@@ -26,15 +40,16 @@ class Way < WorldObject
|
|
26
40
|
else
|
27
41
|
@to = Location.new arg # create free-standing destination location
|
28
42
|
end
|
43
|
+
self.open!
|
44
|
+
else
|
45
|
+
raise "Symbol required, but #{arg.class} : '#{arg}' given."
|
29
46
|
end
|
30
47
|
end
|
31
48
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
self.to = arg
|
37
|
-
end
|
49
|
+
attribute :going
|
50
|
+
|
51
|
+
def go
|
52
|
+
{ go: open?, going: self.going }
|
38
53
|
end
|
39
54
|
|
40
55
|
end
|
@@ -6,6 +6,7 @@ module Woyo
|
|
6
6
|
|
7
7
|
class WorldObject
|
8
8
|
|
9
|
+
#prepend Attributes
|
9
10
|
include Attributes
|
10
11
|
include DSL
|
11
12
|
|
@@ -15,6 +16,7 @@ class WorldObject
|
|
15
16
|
def initialize id, context: nil, &block
|
16
17
|
@id = id.to_s.downcase.to_sym
|
17
18
|
@context = context
|
19
|
+
super # initializes attributes
|
18
20
|
evaluate &block
|
19
21
|
end
|
20
22
|
|