batchbook 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,10 @@
1
+ === 1.0.0 / 2009-01-02
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
7
+ === 1.0.2 / 2009-01-08
8
+
9
+ * allow label/name param to request a specific location/supertag
10
+ * search people/companies by passing :name or :email param to find(:all , :params {:name => 'will'})
data/Manifest.txt ADDED
@@ -0,0 +1,5 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/batchbook.rb
data/README.txt ADDED
@@ -0,0 +1,128 @@
1
+ = batchbook
2
+
3
+ http://github.com/batchblue/batchbook
4
+
5
+ == DESCRIPTION:
6
+
7
+ Wrapper for BatchBook XML API
8
+
9
+ == API
10
+
11
+ API : http://developer.batchblue.com/
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ Basic CRUD features for the data in your account: People, Companies, Communications, To-Dos, Deals. Also custom methods for adding/removing Tags & SuperTags from a record, as well as updating SuperTag data for a particular record.
16
+
17
+ == TODO:
18
+
19
+ * Fix supertag creation + deletion
20
+ * Delete location methods for 'Person' & 'Company'
21
+
22
+ == SYNOPSIS:
23
+
24
+ require 'batchbook'
25
+ BatchBook.account = 'devo'
26
+ BatchBook.token = 'xyZ'
27
+
28
+ #In development to test the urls being used:
29
+ ActiveResource::Base.logger = Logger.new(STDOUT)
30
+
31
+ #also work for company
32
+ search_by_name = BatchBook::Person.find(:all, :params => {:name => 'will larson'} )
33
+ search_by_email = BatchBook::Person.find(:all, :params => {:email => will@batchblue.com})
34
+
35
+ #Deal requests
36
+ deal_by_email = BatchBook::Deal.find(:all, :params => {:assigned_to => 'eekrause@batchblue.com'})
37
+ deal_by_status = BatchBook::Deal.find(:all, :params => {:status => 'lost'})
38
+
39
+ #To add/remove a tag
40
+ deal = BatchBook::Deal.find(1)
41
+ deal.add_tag 'some tag'
42
+ deal.remove_tag 'some tag'
43
+
44
+ #To add/remove a comment
45
+ comment = BatchBook::Comment.new :comment => "It's a lovely day"
46
+ comment.deal = deal
47
+ comment.save
48
+ deal.comments.first.destroy
49
+
50
+ person = BatchBook::Person.find(5)
51
+ => #<BatchBook::Person:0x1822c3c @attributes={"company"=>"BatchBlue Software", "title"=>"Software Developer", "id"=>5, "notes"=>nil, "first_name"=>"Will", "last_name"=>"Larson"}, @prefix_options={}>
52
+
53
+ person.tags
54
+ => [#<BatchBook::Tag:0x1816f18 @attributes={"name"=>"batchblue", "id"=>2}, @prefix_options={}>]
55
+
56
+ person.locations
57
+ => [#<BatchBook::Location:0x17cb7e8 @attributes={"city"=>"Seattle", "postal_code"=>"98101", "cell"=>"123-456-7890", "street_1"=>"123 Main Street", "street_2"=>nil, "country"=>"United States", "id"=>5, "website"=>"www.batchblue.com", "fax"=>nil, "phone"=>nil, "label"=>"work", "state"=>"WA", "email"=>"wlarson@batchblue.com"}, @prefix_options={}>]
58
+
59
+ person.location 'work'
60
+ => #<BatchBook::Location:0x17cb7e8 @attributes={"city"=>"Seattle", "postal_code"=>"98101", "cell"=>"123-456-7890", "street_1"=>"123 Main Street", "street_2"=>nil, "country"=>"United States", "id"=>5, "website"=>"www.batchblue.com", "fax"=>nil, "phone"=>nil, "label"=>"work", "state"=>"WA", "email"=>"wlarson@batchblue.com"}, @prefix_options={}>
61
+
62
+ person.supertags
63
+ => [#<BatchBook::SuperTag:0x17e5170 @attributes={"name"=>"reference", "id"=>5149}, @prefix_options={}>, #<BatchBook::SuperTag:0x17e515c @attributes={"name"=>"work schedule", "tuesday"=>"8-4", "wednesday"=>"9-5 PST", "thursday"=>"9-5 PST", "id"=>1948, "monday"=>"9-5 PST", "friday"=>"9-5 PST"}, @prefix_options={}>]
64
+
65
+ person.supertag 'work schedule'
66
+ => #<BatchBook::SuperTag:0x17c7ea4 @attributes={"name"=>"work schedule", "tuesday"=>"8-4", "wednesday"=>"9-5 PST", "thursday"=>"9-5 PST", "id"=>1948, "monday"=>"9-5 PST", "friday"=>"9-5 PST"}, @prefix_options={}>
67
+
68
+ company = BatchBook::Company.find(:all, :params =>{:name => 'BatchBlue'}).first
69
+ => #<BatchBook::Company:0x1762fcc @attributes={"name"=>"BatchBlue Software", "id"=>2, "notes"=>nil}, @prefix_options={}>
70
+
71
+ company.tags
72
+ => []
73
+
74
+ company.supertags
75
+ => []
76
+
77
+ company.locations
78
+ => [#<BatchBook::Location:0x1737cb4 @attributes={"city"=>"Barrington", "postal_code"=>"02806", "cell"=>nil, "street_1"=>"18 Maple Ave.", "street_2"=>"Suite #300", "country"=>"United States", "id"=>622, "website"=>"http://batchblue.com", "fax"=>"(401) 633-6526", "phone"=>"(888) 402-2824", "label"=>"main", "email"=>"info@batchblue.com", "state"=>"RI"}, @prefix_options={}>]
79
+
80
+ company.location 'main'
81
+ => #<BatchBook::Location:0x17225bc @attributes={"city"=>"Barrington", "postal_code"=>"02806", "cell"=>nil, "street_1"=>"18 Maple Ave.", "street_2"=>"Suite #300", "country"=>"United States", "id"=>622, "website"=>"http://batchblue.com", "fax"=>"(401) 633-6526", "phone"=>"(888) 402-2824", "label"=>"main", "email"=>"info@batchblue.com", "state"=>"RI"}, @prefix_options={}>
82
+
83
+ == ADDITIONAL EXAMPLES
84
+
85
+ person = BatchBook::Person.new(:first_name => 'Test', :last_name => 'Name', :notes => "Created via batchbook API")
86
+ person.save
87
+
88
+ person.add_tag('some tag name')
89
+ person.remove_tag('some tag name')
90
+
91
+ person.add_supertag('some tag name', "some field" => "some value")
92
+
93
+ person.add_location( :email => 'test@here.com.au', :phone => '1234 1234', :cell => '2345 2345', :fax => '5678 5678',
94
+ :street_1 => 'Test Street 1', :street_2 => 'Test Street 2', :city => 'Test City', :state => 'VIC',
95
+ :postal_code => '1234', :country => 'Australia')
96
+
97
+ == REQUIREMENTS:
98
+
99
+ activeresource
100
+
101
+ == INSTALL:
102
+
103
+ git clone git://github.com/batchblue/batchbook.git
104
+
105
+ == LICENSE:
106
+
107
+ (The MIT License)
108
+
109
+ Copyright (c) 2009 BatchBlue Software
110
+
111
+ Permission is hereby granted, free of charge, to any person obtaining
112
+ a copy of this software and associated documentation files (the
113
+ 'Software'), to deal in the Software without restriction, including
114
+ without limitation the rights to use, copy, modify, merge, publish,
115
+ distribute, sublicense, and/or sell copies of the Software, and to
116
+ permit persons to whom the Software is furnished to do so, subject to
117
+ the following conditions:
118
+
119
+ The above copyright notice and this permission notice shall be
120
+ included in all copies or substantial portions of the Software.
121
+
122
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
123
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
124
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
125
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
126
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
127
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
128
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/batchbook.rb'
6
+
7
+ Hoe.new('batchbook', BatchBook::VERSION) do |p|
8
+ p.developer('Will Larson', 'technical@batchblue.com')
9
+
10
+ p.extra_deps << ['activeresource', '2.1.0']
11
+ end
12
+
13
+ # vim: syntax=Ruby
data/lib/batchbook.rb ADDED
@@ -0,0 +1,413 @@
1
+ require 'rubygems'
2
+ require 'active_resource'
3
+
4
+ # Ruby lib for working with the BatchBook's API's XML interface. Set the account
5
+ # name and authentication token, using the BatchBook API Key found in your
6
+ # account settings, and you're ready to roll.
7
+ #
8
+ # http://demo.batchbook.com
9
+ # BatchBook.account = 'demo'
10
+ # BatchBook.token = 'XYZ'
11
+ #
12
+ #
13
+ module BatchBook
14
+ VERSION = '1.0.4'
15
+
16
+ class Error < StandardError; end
17
+ class << self
18
+ attr_accessor :host_format, :site_format, :domain_format, :protocol, :path
19
+ attr_reader :account, :token
20
+
21
+ # Sets the account name, and updates all the resources with the new domain.
22
+ def account=(name)
23
+ resources.each do |r|
24
+ r.site = r.site_format % (host_format % [protocol, domain_format % name, path])
25
+ end
26
+ @account = name
27
+ end
28
+
29
+ # Sets the BatchBook API Key for all resources.
30
+ def token=(value)
31
+ resources.each do |r|
32
+ r.user = value
33
+ end
34
+ end
35
+
36
+ def site=(value)
37
+ resources.each do |r|
38
+ r.site = value
39
+ end
40
+ end
41
+
42
+ def resources
43
+ @resources ||= []
44
+ end
45
+ end
46
+
47
+ self.host_format = '%s://%s/%s'
48
+ self.domain_format = '%s.batchbook.com'
49
+ self.path = 'service'
50
+ self.protocol = 'https'
51
+
52
+ class Base < ActiveResource::Base
53
+ @proxy = ''
54
+ @timeout = 15
55
+
56
+ def self.inherited(base)
57
+ BatchBook.resources << base
58
+ class << base
59
+ attr_accessor :site_format
60
+ end
61
+ base.site_format = '%s'
62
+ super
63
+ end
64
+ end
65
+
66
+ class Activities < Base
67
+
68
+ def self.recent
69
+ self.find(:all, :from => :recent)
70
+ end
71
+
72
+ end
73
+
74
+ class Affiliation < Base
75
+
76
+ end
77
+
78
+ class Person < Base
79
+ #http://developer.batchblue.com/people.html
80
+ def tags
81
+ Tag.find(:all, :params => {:contact_id => id})
82
+ end
83
+
84
+ def locations
85
+ self.get('locations')
86
+ end
87
+
88
+ def location label
89
+ raise Error, "Location label not specified. Usage: person.location('label_name')" unless label
90
+ self.get('locations', :label => label)
91
+ end
92
+
93
+ # Add a Location to a Person
94
+ # POST https://test.batchbook.com/service/people/#{id}/locations.xml
95
+ # Field Description
96
+ # location[label] Location Name ('work', 'home', etc.) - REQUIRED
97
+ # location[email] Email Address
98
+ # location[website] Website URL
99
+ # location[phone] Phone Number
100
+ # location[cell] Cell Phone Number
101
+ # location[fax] Fax Number
102
+ # location[street_1] Street Address
103
+ # location[street_2] Street Address 2
104
+ # location[city] City
105
+ # location[state] State
106
+ # location[postal_code] Postal Code
107
+ # location[country] Country
108
+ def add_location(params = {})
109
+ params.update(:label => 'home') unless params[:label].present?
110
+ self.post(:locations, :location => params)
111
+ end
112
+
113
+ def supertags
114
+ self.get('super_tags')
115
+ end
116
+
117
+ def supertag name
118
+ raise Error, "SuperTag name not specified. Usage: person.supertag('tag_name')" unless name
119
+ self.get('super_tags', :name => name)
120
+ end
121
+
122
+ #TODO : Fix supertags
123
+ # Add a SuperTag to a Person
124
+ #
125
+ # Add a SuperTag to a Person the same way you add a regular tag to it, via PUT https://test.batchbook.com/service/people/#{id}/add_tag/#{super_tag_name}.xml.
126
+ # Remove a SuperTag from a Person
127
+ # DELETE https://test.batchbook.com/service/people/#{id}/super_tags/#{super_tag_name}.xml
128
+
129
+ def add_supertag name, params = {}
130
+ raise Error, "Tag name not specified. Usage: person.add_supertag('tag_name')" unless name
131
+
132
+ self.put(:add_tag, :tag => name)
133
+ unless params.empty?
134
+ self.put("super_tags/#{name.gsub(/ /, '_')}", :super_tag => params)
135
+ end
136
+ end
137
+
138
+ def add_tag name
139
+ raise Error, "Tag name not specified. Usage: person.add_tag('tag_name')" unless name
140
+ self.put(:add_tag, :tag => name)
141
+ end
142
+
143
+ def remove_tag name
144
+ raise Error, "Tag name not specified. Usage: person.remove_tag('tag_name')" unless name
145
+ self.delete(:remove_tag, :tag => name)
146
+ end
147
+
148
+ def comments(scope = :all)
149
+ Comment.find(scope, :params => {:person_id => self.id})
150
+ end
151
+
152
+ def comment(id)
153
+ comments(id)
154
+ end
155
+
156
+ def affiliations
157
+ Affiliation.find(:all, :params => {:person_id => self.id})
158
+ end
159
+
160
+ def communications
161
+ Communication.find(:all, :params => {:person_id => self.id})
162
+ end
163
+
164
+ def todos
165
+ Todo.find(:all, :params => {:person_id => self.id})
166
+ end
167
+ end
168
+
169
+ class Company < Base
170
+ def tags
171
+ Tag.find(:all, :params => {:contact_id => id})
172
+ end
173
+
174
+ def locations
175
+ self.get('locations')
176
+ end
177
+
178
+ def location label
179
+ raise Error, "Location label not specified. Usage: person.location('label_name')" unless label
180
+ self.get('locations', :label => label)
181
+ end
182
+
183
+ def supertags
184
+ self.get('super_tags')
185
+ end
186
+
187
+ def supertag name
188
+ raise Error, "SuperTag name not specified. Usage: person.supertag('tag_name')" unless name
189
+ self.get('super_tags', :name => name)
190
+ end
191
+
192
+ def add_tag name
193
+ raise Error, "Tag name not specified. Usage: person.add_tag('tag_name')" unless name
194
+ self.put(:add_tag, :tag => name)
195
+ end
196
+
197
+ def remove_tag name
198
+ raise Error, "Tag name not specified. Usage: person.remove_tag('tag_name')" unless name
199
+ self.delete(:remove_tag, :tag => name)
200
+ end
201
+
202
+ def comments(scope = :all)
203
+ Comment.find(scope, :params => {:company_id => self.id})
204
+ end
205
+
206
+ def comment(id)
207
+ comments(id)
208
+ end
209
+
210
+ def people
211
+ Person.find(:all, :params => {:company_id => self.id})
212
+ # self.get(:people)
213
+ end
214
+
215
+ def affiliations
216
+ Affiliation.find(:all, :params => {:company_id => self.id})
217
+ end
218
+
219
+ def communications
220
+ Communication.find(:all, :params => {:company_id => self.id})
221
+ end
222
+
223
+ def todos
224
+ Todo.find(:all, :params => {:company_id => self.id})
225
+ end
226
+ end
227
+
228
+ class Todo < Base
229
+ def tags
230
+ Tag.find(:all, :params => {:todo_id => id})
231
+ end
232
+
233
+ def add_tag name
234
+ raise Error, "Tag name not specified. Usage: todo.add_tag('tag_name')" unless name
235
+ self.put(:add_tag, :tag => name)
236
+ end
237
+
238
+ def remove_tag name
239
+ raise Error, "Tag name not specified. Usage: todo.remove_tag('tag_name')" unless name
240
+ self.delete(:remove_tag, :tag => name)
241
+ end
242
+
243
+ def comments(scope = :all)
244
+ Comment.find(scope, :params => {:todo_id => self.id})
245
+ end
246
+
247
+ def comment(id)
248
+ comments(id)
249
+ end
250
+ end
251
+
252
+ class Deal < Base
253
+ def tags
254
+ Tag.find(:all, :params => {:deal_id => id})
255
+ end
256
+
257
+ def add_tag name
258
+ raise Error, "Tag name not specified. Usage: deal.add_tag('tag_name')" unless name
259
+ self.put(:add_tag, :tag => name)
260
+ end
261
+
262
+ def remove_tag name
263
+ raise Error, "Tag name not specified. Usage: deal.remove_tag('tag_name')" unless name
264
+ self.delete(:remove_tag, :tag => name)
265
+ end
266
+
267
+ def comments(scope = :all)
268
+ Comment.find(scope, :params => {:deal_id => self.id})
269
+ end
270
+
271
+ def comment(id)
272
+ comments(id)
273
+ end
274
+
275
+ def contacts
276
+ Person.find(:all, :params => {:deal_id => self.id})
277
+ end
278
+
279
+ def add_related_contact(contact_id)
280
+ raise Error, "Contact not specified. Usage: deal.add_contact(50)" unless contact_id
281
+ self.put(:add_related_contact, :contact_id => contact_id)
282
+ end
283
+
284
+ def remove_related_contact(contact_id)
285
+ raise Error, "Contact not specified. Usage: deal.add_contact(50)" unless contact_id
286
+ self.delete(:remove_related_contact, :contact_id => contact_id)
287
+ end
288
+ end
289
+
290
+ class Communication < Base
291
+ def tags
292
+ Tag.find(:all, :params => {:communication_id => id})
293
+ end
294
+
295
+ def add_tag name
296
+ raise Error, "Tag name not specified. Usage: communication.add_tag('tag_name')" unless name
297
+ self.put(:add_tag, :tag => name)
298
+ end
299
+
300
+ def remove_tag name
301
+ raise Error, "Tag name not specified. Usage: communication.remove_tag('tag_name')" unless name
302
+ self.delete(:remove_tag, :tag => name)
303
+ end
304
+
305
+ def comments(scope = :all)
306
+ Comment.find(scope, :params => {:communication_id => self.id})
307
+ end
308
+
309
+ def comment(id)
310
+ comments(id)
311
+ end
312
+ end
313
+
314
+ class Comment < Base
315
+
316
+ def communication
317
+ Communication.find(self.prefix_options[:communication_id])
318
+ end
319
+
320
+ def communication=(communication)
321
+ self.prefix_options[:communication_id] = communication.id
322
+ end
323
+
324
+ def company
325
+ Company.find(self.prefix_options[:company_id])
326
+ end
327
+
328
+ def company=(company)
329
+ self.prefix_options[:company_id] = company.id
330
+ end
331
+
332
+ def deal
333
+ Deal.find(self.prefix_options[:deal_id])
334
+ end
335
+
336
+ def deal=(deal)
337
+ self.prefix_options[:deal_id] = deal.id
338
+ end
339
+
340
+ def list
341
+ List.find(self.prefix_options[:list_id])
342
+ end
343
+
344
+ def list=(list)
345
+ self.prefix_options[:list_id] = list.id
346
+ end
347
+
348
+ def person
349
+ Person.find(self.prefix_options[:person_id])
350
+ end
351
+
352
+ def person=(person)
353
+ self.prefix_options[:person_id] = person.id
354
+ end
355
+
356
+ def todo
357
+ Todo.find(self.prefix_options[:todo_id])
358
+ end
359
+
360
+ def todo=(todo)
361
+ self.prefix_options[:todo_id] = todo.id
362
+ end
363
+
364
+ end
365
+
366
+ class List < Base
367
+ def comments(scope = :all)
368
+ Comment.find(scope, :params => {:list_id => self.id})
369
+ end
370
+
371
+ def comment(id)
372
+ comments(id)
373
+ end
374
+ end
375
+
376
+ class Tag < Base
377
+ end
378
+
379
+ class Location < Base
380
+ end
381
+
382
+ class SuperTag < Base
383
+ end
384
+
385
+ class Record < Base
386
+ end
387
+
388
+ end
389
+
390
+ __END__
391
+
392
+ require 'batchbook'
393
+ BatchBook.account = 'devo'
394
+ BatchBook.token = 'xyZ'
395
+
396
+ search_by_name = BatchBook::Person.find(:all, :params => {:name => 'will'} )
397
+ search_by_email = BatchBook::Person.find(:all, :params => {:email => will@batchblue.com})
398
+
399
+ person = BatchBook::Person.find 1937
400
+ person.last_name = 'new last name'
401
+ person.save
402
+
403
+ new_person = BatchBook::Person.new :first_name => 'will', :last_name => 'larson', :title => 'dev'
404
+ new_person.save
405
+ new_person_comment = BatchBook.Comment.new :comment => 'Best comment ever'
406
+ new_person_comment.person = new_person
407
+ new_person_comment.save
408
+ assert new_person.comments.include? new_person_comment
409
+
410
+
411
+
412
+
413
+
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: batchbook
3
+ version: !ruby/object:Gem::Version
4
+ hash: 17
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 3
10
+ version: 1.0.3
11
+ platform: ruby
12
+ authors:
13
+ - Will Larson
14
+ - Eric Krause
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-07-14 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: activeresource
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - "="
29
+ - !ruby/object:Gem::Version
30
+ hash: 9
31
+ segments:
32
+ - 2
33
+ - 3
34
+ - 5
35
+ version: 2.3.5
36
+ type: :runtime
37
+ version_requirements: *id001
38
+ description: Wrapper for BatchBook XML API
39
+ email:
40
+ - technical@batchblue.com
41
+ executables: []
42
+
43
+ extensions: []
44
+
45
+ extra_rdoc_files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - README.txt
49
+ files:
50
+ - History.txt
51
+ - Manifest.txt
52
+ - README.txt
53
+ - Rakefile
54
+ - lib/batchbook.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/batchblue/batchbook
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - README.txt
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.7
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Wrapper for BatchBook XML API
90
+ test_files: []
91
+
metadata.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ )�bnL0}�쌅=�k�|��^~7�z�tm�� Th �x#"��!׸'4>�(@���q�qe#��`�������hZ��5��S2���U��q�>��"+� a9��<��+9�#U˻Fx�,VY��p#`��������̿�C
2
+ pBk�ɛ�&6۟���DЙӀv�SFG�_�=]����*H���IrhkB����kt�޴H����B�b���6���?� ��]��$�G�ͦpO:'̨��$ t�խ�