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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41529c0e59bef04bb41b1732e50ef7f75ec94b0f
4
- data.tar.gz: 6df39185e8e284a7beb7985adecbbae2741e8edc
3
+ metadata.gz: d6b8db18d440d61ddaf291c7db149e5fa35f8a98
4
+ data.tar.gz: 393a37a546f63d71e2132374c927f0571d475c4b
5
5
  SHA512:
6
- metadata.gz: 18d325950bf55638c7f88ca8c24008affbea3f1fc123f2e24d2dca9fd193b20ef5d247113fbf3abe8b3598b887e063373f2ac92e50bf24213397d3498d55757a
7
- data.tar.gz: 044aecb2e1e1c830c6ed1fb450be14fe7ebc76b338312a63c0616dcf8a651ec85d205b57a5c5da626287d2da7d022aac342e095c9a70decf32c25534262b61e0
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 create_attribute_methods_with_define_method attr, default = nil
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
- if arg.nil?
14
- unless attributes.has_key? attr
15
- if default.respond_to? :call
16
- if default.arity == 0
17
- attributes[attr] = default.call # todo: is this the same as ? ... instance_eval &default
18
- else
19
- attributes[attr] = default.call(self)
20
- end
21
- else
22
- attributes[attr] = default
23
- end
24
- end
25
- attributes[attr]
26
- else
27
- attributes[attr] = arg
28
- end
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
- create_attribute_methods_with_define_method attr_sym, default_value
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 << attr
43
- create_attribute_methods_with_define_method attr
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
- end
94
+ def attribute *attrs
95
+ self.attributes *attrs
96
+ end
97
+
98
+ def groups
99
+ @groups ||= {}
100
+ end
49
101
 
50
- def self.included(base)
51
- base.extend(ClassMethods)
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
+
@@ -1,3 +1,3 @@
1
1
  module Woyo
2
- WORLD_VERSION = "0.0.5"
2
+ WORLD_VERSION = "0.0.6"
3
3
  end
@@ -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 world
14
- from ? from.world : nil
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
- def to arg=nil
33
- if arg.nil?
34
- @to
35
- else
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