Olib 2.0.0.pre.rc.3 → 2.0.0.pre.rc.4

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
  SHA256:
3
- metadata.gz: 88c17ccdc2fc52aecad952d952a46005a5fbff7103a1b650d29d4d65f437a17a
4
- data.tar.gz: 187d49baaf0362d38b87805b5beb71e345ce95654588095020b4a8de0f190a8e
3
+ metadata.gz: 67b2a5fcaa0b1e8ea96d2326a9d74093e75f3f67545e63d269cd5e2834946545
4
+ data.tar.gz: f1d1e645ef5b63d23afe1f1dd632fdedb4e456b271dad2495a01aa7ce222e914
5
5
  SHA512:
6
- metadata.gz: 72af6ca80a60fa8527c7edbcab8697a8e8730989866d90a73f094dbdb5e550b4e1171e609c5fcc6ede53a8b9e4e4b8fd94e0a4cdf79d05d01f3ada904b2b543d
7
- data.tar.gz: c6a9e86b1b0c33355a30e1262fde92800b82edc50e13dee9bcf048fdfb942819c9db3484e90e2ce443331316baed64130d6ee2ee3a7d43515695d7e4e1ff898e
6
+ metadata.gz: b228aa4fd9ad54c9e8e7b2ff17da544020992e98d76538d786a4103022c78c43a7ce7513b0a3e5bf56e04efd8aaec7743223c0d1b928e63856381c5750d98c75
7
+ data.tar.gz: 9f650744fe4431345c990ecc0c7a895211a6f83a6ac8a890c66db73a4c8f4b3cb454c487a7ae4fce2e8af38ce19f209e7bf323e429efccb24120dd395456b0ef
@@ -1,258 +1,99 @@
1
1
  require "ostruct"
2
+ require "benchmark"
2
3
  require "Olib/character/disk"
3
4
 
4
5
  module Group
5
- class Members
6
- include Enumerable
7
- attr_accessor :leader, :members, :birth
8
- def initialize
9
- @birth = Time.now
10
- @members = []
11
- end
12
-
13
- def clear!
14
- @members = []
15
- @birth = Time.now
16
- @leader = nil
17
- end
18
-
19
- def size
20
- @members.size
21
- end
22
-
23
- def empty?
24
- @members.empty?
25
- end
26
-
27
- def add(pc, leader = false)
28
- member = Member.new pc, leader
29
- if leader
30
- @leader = member
31
- end
32
- @members << member
33
- self
34
- end
35
-
36
- def each(&block)
37
- @members.each do |char| yield char end
38
- self
39
- end
40
-
41
- def include?(pc)
42
- return true if pc.is_a?(String) and Char.name.eql?(pc)
43
- return true if pc.respond_to?(:noun) and Char.name.eql?(pc.noun)
44
- return true if pc.respond_to?(:name) and Char.name.eql?(pc.name)
45
- !find do |char|
46
- if pc.is_a?(String)
47
- char.noun.eql?(pc)
48
- else
49
- char.noun.eql?(pc.noun) || char.noun.eql?(pc.name)
50
- end
51
- end.nil?
52
- end
53
-
54
- def nonmembers
55
- ((GameObj.pcs || []) + Disk.all()).reject do |pc|
56
- include?(pc)
57
- end
58
- end
59
-
60
- def to_s
61
- "<Members: [#{@members.join(" ")}]>"
62
- end
63
- end
64
-
65
- class Member
66
- attr_reader :id, :leader, :name, :noun
67
- def initialize(pc, leader = false)
68
- @id = pc.id
69
- @leader = leader
70
- @name = pc.name
71
- @noun = pc.noun
72
- end
73
-
74
- def ref
75
- GameObj[@id]
76
- end
77
-
78
- def leader?
79
- @leader
80
- end
81
-
82
- def status
83
- (ref.status.split(" ") || []).map(&:to_sym)
84
- end
85
-
86
- def is(state)
87
- status =~ state
88
- end
89
-
90
- def ==(other)
91
- @id == other.id
92
- end
93
-
94
- def to_s
95
- "<#{name}: @leader=#{leader?} @status=#{status}>"
96
- end
97
- end
6
+ @@members ||= []
7
+ @@leader ||= nil
8
+ @@checked ||= false
9
+ @@status ||= :closed
98
10
 
99
- MEMBERS = Members.new
100
- OPEN = :open
101
- CLOSED = :closed
102
- CHECK_HOOK = self.name.to_s
103
- NO_GROUP = /You are not currently in a group/
104
- MEMBER = /<a exist="(?<id>.*?)" noun="(?<name>.*?)">(.*?)<\/a> is (?<type>(the leader|also a member) of your group|following you)\./
105
- STATE = /^Your group status is currently (?<state>open|closed)\./
106
- END_GROUP = /list of other options\./
107
-
108
- PARSER = Proc.new do |line|
109
- if line.strip.empty? || line =~ NO_GROUP
110
- nil
111
- elsif line =~ STATE
112
- nil
113
- elsif line =~ END_GROUP
114
- Group.checked!
115
- DownstreamHook.remove(CHECK_HOOK)
116
- nil
117
- elsif line =~ MEMBER
118
- begin
119
- pc = line.match(MEMBER).to_struct
120
- Group::MEMBERS.add GameObj[pc.name], (line =~ /leader/ ? true : false)
121
- if line =~ /following/
122
- Group::MEMBERS.leader = OpenStruct.new(name: Char.name, leader: true)
123
- end
124
- nil
125
- rescue Exception => e
126
- respond e
127
- respond e.backtrace
128
- end
129
- else
130
- line
131
- end
11
+ def self.clear()
12
+ @@members = []
13
+ @@checked = false
132
14
  end
133
15
 
134
- @@checked = false
135
-
136
- def Group.checked?
16
+ def self.checked?
137
17
  @@checked
138
18
  end
139
19
 
140
- def Group.checked!
141
- @@checked = true
142
- self
20
+ def self.push(*members)
21
+ members.each do |member|
22
+ @@members.push(member) unless include?(member)
23
+ end
143
24
  end
144
25
 
145
- def Group.empty?
146
- MEMBERS.empty?
26
+ def self.delete(*members)
27
+ gone = members.map(&:id)
28
+ @@members.reject! do |m| gone.include?(m.id) end
147
29
  end
148
30
 
149
- def Group.exists?
150
- !empty?
31
+ def self.members
32
+ maybe_check
33
+ @@members.dup
151
34
  end
152
35
 
153
- def Group.members
154
- maybe_check
155
- MEMBERS
36
+ def self._members
37
+ @@members
156
38
  end
157
39
 
158
- def Group.disks
40
+ def self.disks
159
41
  return [Disk.find_by_name(Char.name)].compact unless Group.leader?
160
- members.map(&:name).map do |name| Disk.find_by_name(name) end.compact
42
+ members.map(&:noun).map do |noun| Disk.find_by_name(noun) end.compact
161
43
  end
162
44
 
163
- def Group.to_s
164
- MEMBERS.to_s
45
+ def self.to_s
46
+ @@members.to_s
165
47
  end
166
48
 
167
- # ran at the initialization of a script
168
- def Group.check
169
- Group.unobserve()
170
- @@checked = false
171
- MEMBERS.clear!
172
- DownstreamHook.add(CHECK_HOOK, PARSER)
173
- Game._puts "<c>group\r\n"
174
- wait_until { Group.checked? }
175
- Group.observe()
176
- MEMBERS
49
+ def self.checked=(flag)
50
+ @@checked = flag
177
51
  end
178
52
 
179
- def Group.maybe_check
180
- Group.check unless checked?
53
+ def self.status=(state)
54
+ @@status = state
181
55
  end
182
56
 
183
- def Group.nonmembers
184
- members.nonmembers
57
+ def self.status()
58
+ @@status
185
59
  end
186
60
 
187
- def Group.leader
188
- members.leader
61
+ def self.open?
62
+ maybe_check
63
+ @@status.eql?(:open)
189
64
  end
190
65
 
191
- def Group.leader?
192
- leader && leader.name == Char.name
66
+ def self.closed?
67
+ not open?
193
68
  end
194
69
 
70
+ # ran at the initialization of a script
71
+ def self.check
72
+ Group.clear()
73
+ ttl = Time.now + 3
74
+ Game._puts "<c>group\r\n"
75
+ wait_until { Group.checked? or Time.now > ttl }
76
+ @@members.dup
77
+ end
195
78
 
196
- module Term
197
- # <a exist="-10467645" noun="Oreh">Oreh</a> leaves your group
198
- # <a exist="-10467645" noun="Oreh">Oreh</a> joins your group.
199
- # You add <a exist="-10467645" noun="Oreh">Oreh</a> to your group.
200
- # You remove <a exist="-10467645" noun="Oreh">Oreh</a> from the group.
201
- # You disband your group.
202
- JOIN = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> joins your group.$}
203
- LEAVE = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> leaves your group.$}
204
- ADD = %r{^You add <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> to your group.$}
205
- REMOVE = %r{^You remove <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> from the group.$}
206
- NOOP = %r{^But <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> is already a member of your group!$}
207
- EXIST = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a>}
208
- DISBAND = %r{^You disband your group}
209
- ANY = Regexp.union(JOIN, LEAVE, ADD, REMOVE, NOOP)
79
+ def self.maybe_check
80
+ Group.check unless checked?
210
81
  end
211
82
 
212
- GROUP_OBSERVER = -> line {
213
- begin
214
- return line if DownstreamHook.list.include?(CHECK_HOOK)
215
- Group.consume(line.strip)
216
- rescue => exception
217
- respond exception
218
- respond exception.backtrace
219
- end
220
- line
221
- }
83
+ def self.nonmembers
84
+ GameObj.pcs.to_a.reject {|pc| ids.include?(pc.id) }
85
+ end
222
86
 
223
- def self.observe()
224
- wait_while do DownstreamHook.list.include?(CHECK_HOOK) end
225
- DownstreamHook.add("__group_observer", GROUP_OBSERVER)
87
+ def self.leader=(char)
88
+ @@leader = char
226
89
  end
227
90
 
228
- def self.unobserve()
229
- DownstreamHook.remove("__group_observer")
91
+ def self.leader
92
+ @@leader
230
93
  end
231
94
 
232
- Group.observe()
233
-
234
- def self.consume(line)
235
- return unless line.match(Group::Term::ANY)
236
- person = GameObj[Term::EXIST.match(line)[:id]]
237
- case line
238
- when Term::JOIN
239
- Group.members.add(person) unless Group.members.include?(person)
240
- when Term::ADD
241
- Group.members.add(person) unless Group.members.include?(person)
242
- when Term::NOOP
243
- Group.members.add(person) unless Group.members.include?(person)
244
- when Term::LEAVE
245
- Group.members.members.delete(Group.members.find do |member|
246
- member.id.eql?(person.id)
247
- end)
248
- when Term::REMOVE
249
- Group.members.members.delete(Group.members.find do |member|
250
- member.id.eql?(person.id)
251
- end)
252
- else
253
- # silence is golden
254
- end
255
- Group.persist()
95
+ def self.leader?
96
+ @@leader.eql?(:self)
256
97
  end
257
98
 
258
99
  def self.add(*members)
@@ -260,34 +101,201 @@ module Group
260
101
  if member.is_a?(Array)
261
102
  Group.add(*member)
262
103
  else
104
+ member = GameObj.pcs.find {|pc| pc.noun.eql?(member)} if member.is_a?(String)
105
+
106
+ return if member.nil?
107
+
263
108
  result = dothistimeout("group ##{member.id}", 3, Regexp.union(
264
109
  %r{You add #{member.noun} to your group},
265
110
  %r{#{member.noun}'s group status is closed},
266
111
  %r{But #{member.noun} is already a member of your group}))
267
112
 
268
113
  case result
269
- when %r{You add}
270
- Group.members.add(member)
271
- [:ok, member]
272
- when %r{already a member}
273
- [:noop, member]
114
+ when %r{You add}, %r{already a member}
115
+ Group.push(member)
116
+ {ok: member}
274
117
  when %r{closed}
275
- [:err, member]
118
+ Group.delete(member)
119
+ {err: member}
276
120
  else
277
121
  end
278
122
  end
279
123
  end
280
124
  end
281
125
 
282
- def self.persist()
283
- return
126
+ def self.ids
127
+ @@members.map(&:id)
128
+ end
129
+
130
+ def self.include?(*members)
131
+ members.all? { |m| ids.include?(m.id) }
284
132
  end
285
133
 
286
134
  def self.broken?
287
135
  if Group.leader?
288
- (GameObj.pcs.map(&:noun) & Group.members.map(&:noun)).size < Group.members.size
136
+ (GameObj.pcs.map(&:noun) & @@members.map(&:noun)).size < @@members.size
289
137
  else
290
138
  GameObj.pcs.find do |pc| pc.noun.eql?(Group.leader.noun) end.nil?
291
139
  end
292
140
  end
293
- end
141
+
142
+ def self.method_missing(method, *args, &block)
143
+ @@members.send(method, *args, &block)
144
+ end
145
+ end
146
+
147
+ module Group
148
+ module Observer
149
+ module Term
150
+ ##
151
+ ## passive messages
152
+ ##
153
+ # <a exist="-10467645" noun="Oreh">Oreh</a> joins your group.
154
+ JOIN = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> joins your group.$}
155
+ # <a exist="-10467645" noun="Oreh">Oreh</a> leaves your group
156
+ LEAVE = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> leaves your group.$}
157
+ # You add <a exist="-10467645" noun="Oreh">Oreh</a> to your group.
158
+ ADD = %r{^You add <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> to your group.$}
159
+ # You remove <a exist="-10467645" noun="Oreh">Oreh</a> from the group.
160
+ REMOVE = %r{^You remove <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> from the group.$}
161
+ NOOP = %r{^But <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> is already a member of your group!$}
162
+ # <a exist="-10488845" noun="Etanamir">Etanamir</a> designates you as the new leader of the group.
163
+ HAS_LEADER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> designates you as the new leader of the group\.$}
164
+ SWAP_LEADER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> designates <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> as the new leader of the group.}
165
+
166
+ # You designate <a exist="-10778599" noun="Ondreian">Ondreian</a> as the new leader of the group.
167
+ GAVE_LEADER_AWAY = %r{You designate <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> as the new leader of the group\.$}
168
+ # You disband your group.
169
+ DISBAND = %r{^You disband your group}
170
+ # <a exist="-10488845" noun="Etanamir">Etanamir</a> adds you to <a exist="-10488845" noun="Etanamir">his</a> group.
171
+ ADDED_TO_NEW_GROUP = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> adds you to <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> group.}
172
+ # You join <a exist="-10488845" noun="Etanamir">Etanamir</a>.
173
+ JOINED_NEW_GROUP = %r{You join <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a>\.$}
174
+ # <a exist="-10488845" noun="Etanamir">Etanamir</a> adds <a exist="-10974229" noun="Szan">Szan</a> to <a exist="-10488845" noun="Etanamir">his</a> group.
175
+ LEADER_ADDED_MEMBER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> adds <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> to <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> group\.$}
176
+ # <a exist="-10488845" noun="Etanamir">Etanamir</a> removes <a exist="-10974229" noun="Szan">Szan</a> from the group.
177
+ LEADER_REMOVED_MEMBER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> removes <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> from the group\.$}
178
+ ##
179
+ ## active messages
180
+ ##
181
+ NO_GROUP = /You are not currently in a group/
182
+ MEMBER = /<a exist="(?<id>.*?)" noun="(?<name>.*?)">(.*?)<\/a> is (?<type>(the leader|also a member) of your group|following you)\./
183
+ STATUS = /^Your group status is currently (?<status>open|closed)\./
184
+
185
+ GROUP_EMPTIED = %[<indicator id='IconJOINED' visible='n'/>]
186
+ GROUP_EXISTS = %[<indicator id='IconJOINED' visible='y'/>]
187
+ GIVEN_LEADERSHIP = %[designates you as the new leader of the group.]
188
+
189
+ ANY = Regexp.union(
190
+ JOIN,
191
+ LEAVE,
192
+ ADD,
193
+ REMOVE,
194
+ DISBAND,
195
+ NOOP,
196
+ STATUS,
197
+ NO_GROUP,
198
+ MEMBER,
199
+
200
+ HAS_LEADER,
201
+ SWAP_LEADER,
202
+
203
+ LEADER_ADDED_MEMBER,
204
+ LEADER_REMOVED_MEMBER,
205
+
206
+ ADDED_TO_NEW_GROUP,
207
+ JOINED_NEW_GROUP,
208
+ GAVE_LEADER_AWAY,
209
+ )
210
+
211
+ EXIST = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a>}
212
+ end
213
+
214
+ CALLBACK = -> line {
215
+ begin
216
+ # fast first-pass
217
+ if line.include?("group") or line.include?("following you") or line.include?("IconJOINED")
218
+ # more detailed pass
219
+ if match_data = Observer.wants?(line)
220
+ Observer.consume(line.strip, match_data)
221
+ end
222
+ end
223
+ rescue => exception
224
+ respond(exception)
225
+ respond(exception.backtrace)
226
+ ensure
227
+ return line
228
+ end
229
+ }
230
+
231
+ def self.exist(xml)
232
+ xml.scan(Group::Observer::Term::EXIST).map { |id, noun, name| GameObj[id] }
233
+ end
234
+
235
+ def self.wants?(line)
236
+ line.strip.match(Term::ANY) or
237
+ line.include?(Term::GROUP_EMPTIED)
238
+ end
239
+
240
+ def self.consume(line, match_data)
241
+ if line.include?(Term::GIVEN_LEADERSHIP)
242
+ return Group.leader = :self
243
+ end
244
+
245
+ ## Group indicator changed!
246
+ if line.include?(Term::GROUP_EMPTIED)
247
+ Group.leader = :self
248
+ return Group._members.clear
249
+ end
250
+
251
+ people = exist(line)
252
+
253
+ if line.include?("is following you")
254
+ Group.leader = :self
255
+ elsif line.include?("is the leader of your group")
256
+ Group.leader = people.first
257
+ end
258
+
259
+ case line
260
+ when Term::NO_GROUP, Term::DISBAND
261
+ Group.leader = :self
262
+ return Group._members.clear
263
+ when Term::STATUS
264
+ Group.status = match_data[:status].to_sym
265
+ return Group.checked = true
266
+ when Term::GAVE_LEADER_AWAY
267
+ Group.push(people.first)
268
+ return Group.leader = people.first
269
+ when Term::ADDED_TO_NEW_GROUP, Term::JOINED_NEW_GROUP
270
+ Group.push(people.first)
271
+ return Group.leader = people.first
272
+ when Term::SWAP_LEADER
273
+ (old_leader, new_leader) = people
274
+ Group.push(*people) if Group.include?(old_leader) or Group.include?(new_leader)
275
+ return Group.leader = new_leader
276
+ when Term::LEADER_ADDED_MEMBER
277
+ (leader, added) = people
278
+ Group.push(added) if Group.include?(leader)
279
+ when Term::LEADER_REMOVED_MEMBER
280
+ (leader, removed) = people
281
+ return Group.delete(removed) if Group.include?(leader)
282
+ when Term::JOIN, Term::ADD, Term::NOOP, Term::MEMBER
283
+ return Group.push(*people)
284
+ when Term::LEAVE, Term::REMOVE
285
+ return Group.delete(*people)
286
+ end
287
+ end
288
+
289
+
290
+ def self.attach()
291
+ remove() if DownstreamHook.list.include?(self.name)
292
+ DownstreamHook.add(self.name, CALLBACK)
293
+ end
294
+
295
+ def self.remove()
296
+ DownstreamHook.remove(self.name)
297
+ end
298
+ end
299
+
300
+ Observer.attach()
301
+ end
@@ -1,3 +1,3 @@
1
1
  module Olib
2
- VERSION = "2.0.0-rc.3"
2
+ VERSION = "2.0.0-rc.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Olib
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.rc.3
4
+ version: 2.0.0.pre.rc.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ondreian Shamsiel