osm 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## Version 0.6.0
2
+
3
+ * Badge::Data
4
+ * completed attribute is now a Fixnum not Boolean (fixes staged badges)
5
+ * Add awarded attribute (the last level awarded)
6
+ * Add due? method to tell if the badge is due
7
+ * Add started? method to tell if the badge has been started
8
+ * Add started method to tell which stage has been started
9
+ * Add first\_name and last\_name attributes
10
+ * Add mark\_awarded method
11
+ * Add mark\_due method
12
+ * Badge
13
+ * Make get\_badge\_data\_for\_section an instance not class method (called get\_data\_for\_section)
14
+ * Add get\_summary\_for\_section(api, section, term=nil, options={}) method
15
+ * Add optional section\_type parameter to get\_badges\_for\_section method
16
+
1
17
  ## Version 0.5.0
2
18
 
3
19
  * Code breaking changes to DueBadges:
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  ##Build State
6
6
  This project uses continuous integration to help ensure that a quality product is delivered.
7
7
  Travis CI monitors two branches (versions) of the code - Master (which is what gets released)
8
- and Staging (which is what is currently being debugged ready for moving to master).
8
+ and Staging (which is what is currently being developed ready for moving to master).
9
9
 
10
10
  Master [![Build Status](https://secure.travis-ci.org/robertgauld/osm.png?branch=master)](http://travis-ci.org/robertgauld/osm)
11
11
 
@@ -32,7 +32,7 @@ Use the [Online Scout Manager](https://www.onlinescoutmanager.co.uk) API.
32
32
  Add to your Gemfile and run the `bundle` command to install it.
33
33
 
34
34
  ```ruby
35
- gem 'osm', '~> 0.5.0'
35
+ gem 'osm', '~> 0.6.0'
36
36
  ```
37
37
 
38
38
  Configure the gem during the initalization of the app (e.g. if using rails then config/initializers/osm.rb would look like):
data/lib/osm/badge.rb CHANGED
@@ -7,7 +7,7 @@ module Osm
7
7
  # @return [String] the name of the badge
8
8
  # @!attribute [rw] requirement_notes
9
9
  # @return [String] a description of the badge
10
- # @!attribute [rw] key
10
+ # @!attribute [rw] osm_key
11
11
  # @return [String] the key for the badge in OSM
12
12
  # @!attribute [rw] sections_needed
13
13
  # @return [Fixnum]
@@ -45,13 +45,15 @@ module Osm
45
45
  # Get badges
46
46
  # @param [Osm::Api] api The api to use to make the request
47
47
  # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the due badges for
48
+ # @param [Symbol] section_type The type of section to get badges for (if nil uses the type of the section param)
48
49
  # @!macro options_get
49
50
  # @return [Array<Osm::Badge>]
50
- def self.get_badges_for_section(api, section, options={})
51
- raise Error, 'This method must be called on one of the subclasses (CoreBadge, ChallengeBadge, StagedBadge or ActivityBadge)' if badge_type.nil?
51
+ def self.get_badges_for_section(api, section, section_type=nil, options={})
52
+ raise Error, 'This method must be called on one of the subclasses (CoreBadge, ChallengeBadge, StagedBadge or ActivityBadge)' if type.nil?
52
53
  require_ability_to(api, :read, :badge, section, options)
53
54
  section = Osm::Section.get(api, section, options) unless section.is_a?(Osm::Section)
54
- cache_key = ['badges', section.type, badge_type]
55
+ section_type ||= section.type
56
+ cache_key = ['badges', section_type, type]
55
57
 
56
58
  if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key)
57
59
  return cache_read(api, cache_key)
@@ -60,7 +62,7 @@ module Osm
60
62
  term_id = Osm::Term.get_current_term_for_section(api, section, options).to_i
61
63
  badges = []
62
64
 
63
- data = api.perform_query("challenges.php?action=getInitialBadges&type=#{badge_type}&sectionid=#{section.id}&section=#{section.type}&termid=#{term_id}")
65
+ data = api.perform_query("challenges.php?action=getInitialBadges&type=#{type}&sectionid=#{section.id}&section=#{section_type}&termid=#{term_id}")
64
66
  badge_order = data["badgeOrder"].to_s.split(',')
65
67
  structures = data["structure"] || {}
66
68
  details = data["details"] || {}
@@ -97,34 +99,70 @@ module Osm
97
99
  return badges
98
100
  end
99
101
 
102
+ # Get a summary of badges earnt by members
103
+ # @param [Osm::Api] api The api to use to make the request
104
+ # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the due badges for
105
+ # @param [Osm::Term, Fixnum, #to_i, nil] term The term (or its ID) to get the due badges for, passing nil causes the current term to be used
106
+ # @!macro options_get
107
+ # @return [Array<Hash>]
108
+ def self.get_summary_for_section(api, section, term=nil, options={})
109
+ raise Error, 'This method must be called on one of the subclasses (CoreBadge, ChallengeBadge, StagedBadge or ActivityBadge)' if type.nil?
110
+ require_ability_to(api, :read, :badge, section, options)
111
+ section = Osm::Section.get(api, section, options) unless section.is_a?(Osm::Section)
112
+ term_id = (term.nil? ? Osm::Term.get_current_term_for_section(api, section, options) : term).to_i
113
+ cache_key = ['badge-summary', section.id, term_id, type]
114
+
115
+ if !options[:no_cache] && Osm::Model.cache_exist?(api, cache_key)
116
+ return cache_read(api, cache_key)
117
+ end
118
+
119
+ summary = []
120
+ data = api.perform_query("challenges.php?action=summary&section=#{section.type}&sectionid=#{section.id}&termid=#{term_id}&type=#{type}")
121
+ data['items'].each do |item|
122
+ new_item = {
123
+ :first_name => item['firstname'],
124
+ :last_name => item['lastname'],
125
+ }
126
+ (item.keys - ['firstname', 'lastname']).each do |key|
127
+ new_item[key] = item[key]
128
+ end
129
+ summary.push new_item
130
+ end
131
+
132
+ cache_write(api, cache_key, summary)
133
+ return summary
134
+ end
135
+
100
136
  # Get a list of badge requirements met by members
101
137
  # @param [Osm::Api] api The api to use to make the request
102
138
  # @param [Osm::Section, Fixnum, #to_i] section The section (or its ID) to get the due badges for
103
- # @param [Osm::Badge] badge The badge to get data for
104
139
  # @param [Osm::Term, Fixnum, #to_i, nil] term The term (or its ID) to get the due badges for, passing nil causes the current term to be used
105
140
  # @!macro options_get
106
141
  # @return [Array<Osm::Badge::Data>]
107
- def self.get_badge_data_for_section(api, section, badge, term=nil, options={})
108
- raise Error, 'This method must be called on one of the subclasses (CoreBadge, ChallengeBadge, StagedBadge or ActivityBadge)' if badge_type.nil?
142
+ def get_data_for_section(api, section, term=nil, options={})
143
+ raise Error, 'This method must be called on one of the subclasses (CoreBadge, ChallengeBadge, StagedBadge or ActivityBadge)' if type.nil?
109
144
  Osm::Model.require_ability_to(api, :read, :badge, section, options)
110
145
  section = Osm::Section.get(api, section, options) unless section.is_a?(Osm::Section)
111
146
  term_id = (term.nil? ? Osm::Term.get_current_term_for_section(api, section, options) : term).to_i
112
- cache_key = ['badge_data', section.id, term_id, badge.osm_key]
147
+ cache_key = ['badge_data', section.id, term_id, osm_key]
113
148
 
114
149
  if !options[:no_cache] && cache_exist?(api, cache_key)
115
150
  return cache_read(api, cache_key)
116
151
  end
117
152
 
118
153
  datas = []
119
- data = api.perform_query("challenges.php?termid=#{term_id}&type=#{badge_type}&section=#{section.type}&c=#{badge.osm_key}&sectionid=#{section.id}")
154
+ data = api.perform_query("challenges.php?termid=#{term_id}&type=#{type}&section=#{section.type}&c=#{osm_key}&sectionid=#{section.id}")
120
155
  data['items'].each do |d|
121
156
  datas.push Osm::Badge::Data.new(
122
157
  :member_id => d['scoutid'],
123
- :completed => d['completed'].eql?('1'),
158
+ :first_name => d['firstname'],
159
+ :last_name => d['lastname'],
160
+ :completed => d['completed'].to_i,
161
+ :awarded => d['awarded'].to_i,
124
162
  :awarded_date => Osm.parse_date(d['awardeddate']),
125
163
  :requirements => d.select{ |k,v| k.include?('_') },
126
164
  :section_id => section.id,
127
- :badge => badge,
165
+ :badge => self,
128
166
  )
129
167
  end
130
168
 
@@ -140,13 +178,20 @@ module Osm
140
178
  end
141
179
 
142
180
 
143
- private
144
- def self.badge_type
181
+ def self.type
145
182
  nil
146
183
  end
184
+ def type
185
+ self.class.type
186
+ end
187
+
188
+ private
147
189
  def self.subscription_required
148
190
  :bronze
149
191
  end
192
+ def subscription_required
193
+ self.class.subscription_required
194
+ end
150
195
 
151
196
 
152
197
  class Requirement
@@ -196,14 +241,17 @@ module Osm
196
241
  end # Class Requirement
197
242
 
198
243
 
199
- class Data
200
- include ::ActiveAttr::MassAssignmentSecurity
201
- include ::ActiveAttr::Model
202
-
244
+ class Data < Osm::Model
203
245
  # @!attribute [rw] member_id
204
246
  # @return [Fixnum] ID of the member this data relates to
247
+ # @!attribute [rw] first_name
248
+ # @return [Fixnum] the member's first name
249
+ # @!attribute [rw] last_name
250
+ # @return [Fixnum] Ithe member's last name
205
251
  # @!attribute [rw] completed
206
- # @return [Boolean] whether this badge has been completed (i.e. it is due?)
252
+ # @return [Fixnum] whether this badge has been completed (i.e. it is due?), number indicates stage if appropriate
253
+ # @!attribute [rw] awarded
254
+ # @return [Date] the last stage awarded
207
255
  # @!attribute [rw] awarded_date
208
256
  # @return [Date] when the badge was awarded
209
257
  # @!attribute [rw] requirements
@@ -214,16 +262,22 @@ module Osm
214
262
  # @return [Osm::Badge] the badge that the data belongs to
215
263
 
216
264
  attribute :member_id, :type => Integer
217
- attribute :completed, :type => Boolean
218
- attribute :awarded_date, :type => Date
265
+ attribute :first_name, :type => String
266
+ attribute :last_name, :type => String
267
+ attribute :completed, :type => Integer, :default => 0
268
+ attribute :awarded, :type => Integer, :default => 0
269
+ attribute :awarded_date, :type => Date, :default => nil
219
270
  attribute :requirements, :type => Object, :default => DirtyHashy.new
220
271
  attribute :section_id, :type => Integer
221
272
  attribute :badge, :type => Object
222
273
 
223
- attr_accessible :member_id, :completed, :awarded_date, :requirements, :section_id, :badge
274
+ attr_accessible :member_id, :first_name, :last_name, :completed, :awarded, :awarded_date, :requirements, :section_id, :badge
224
275
 
225
276
  validates_presence_of :badge
226
- validates_inclusion_of :completed, :in => [true, false]
277
+ validates_presence_of :first_name
278
+ validates_presence_of :last_name
279
+ validates_numericality_of :completed, :only_integer=>true, :greater_than_or_equal_to=>0
280
+ validates_numericality_of :awarded, :only_integer=>true, :greater_than_or_equal_to=>0
227
281
  validates_numericality_of :member_id, :only_integer=>true, :greater_than=>0
228
282
  validates_numericality_of :section_id, :only_integer=>true, :greater_than=>0
229
283
  validates :requirements, :hash => {:key_type => String, :value_type => String}
@@ -246,7 +300,7 @@ module Osm
246
300
  def total_gained
247
301
  count = 0
248
302
  requirements.each do |field, data|
249
- next if data.blank? || data.downcase[0].eql?('x')
303
+ next if data.blank? || data[0].downcase.eql?('x')
250
304
  count += 1
251
305
  end
252
306
  return count
@@ -273,12 +327,110 @@ module Osm
273
327
  requirements.each do |field, data|
274
328
  field = field.split('_')[0]
275
329
  count[field] ||= 0
276
- next if data.blank? || data.downcase[0].eql?('x')
330
+ next if data.blank? || data[0].downcase.eql?('x')
277
331
  count[field] += 1
278
332
  end
279
333
  return count
280
334
  end
281
335
 
336
+ # Check if this badge is due
337
+ # @return [Boolean] whether the badge is due to the member
338
+ def due?
339
+ completed > awarded
340
+ end
341
+
342
+ # Check if this badge has been started
343
+ # @return [Boolean] whether the badge has been started by the member (always false if the badge has been completed)
344
+ def started?
345
+ unless badge.type == :staged
346
+ return false if completed?
347
+ requirements.each do |key, value|
348
+ return true unless value.blank? || value[0].downcase.eql?('x')
349
+ end
350
+ else
351
+ # Staged badge
352
+ return (started > completed)
353
+ end
354
+ return false
355
+ end
356
+
357
+ # Get which stage has been started
358
+ # @return [Fixnum] which stage of the badge has been started by the member (lowest)
359
+ def started
360
+ unless badge.type == :staged
361
+ return started? ? 1 : 0
362
+ else
363
+ # Staged badge
364
+ if ['nightsaway', 'hikes'].include?(badge.osm_key) # Special staged badges
365
+ stages = [1, 5, 10, 20, 35, 50, 75, 100, 125, 150, 175, 200] if badge.osm_key.eql?('nightsaway')
366
+ stages = [1, 5, 10, 20, 35, 50] if badge.osm_key.eql?('hikes')
367
+ done = requirements['y_01'].to_i
368
+ return 0 if done < stages[0] # Not started the first stage
369
+ return 0 if done >= stages[stages.size - 1] # No more stages can be started
370
+ (1..stages.size-1).reverse_each do |index|
371
+ if (done < stages[index]) && (done > stages[index-1])
372
+ return stages[index]
373
+ end
374
+ end
375
+ else
376
+ start_group = 'abcde'[completed] # Requirements use the group letter to denote stage
377
+ started = 'z'
378
+ requirements.each do |key, value|
379
+ next if key[0] < start_group # This stage is marked as completed
380
+ next if key[0] > started # This stage is after the stage currently started
381
+ started = key[0] unless value.blank? || value[0].downcase.eql?('x')
382
+ end
383
+ return started.eql?('z') ? 0 : 'abcde'.index(started)+1
384
+ end
385
+ return 0
386
+ end
387
+ end
388
+
389
+ # Mark the badge as awarded in OSM
390
+ # @param [Osm::Api] api The api to use to make the request
391
+ # @param [Date] date The date to mark the badge as awarded
392
+ # @param [Fixnum] level The level of the badge to award (1 for non-staged badges)
393
+ # @param [Symbol] mark_as :awarded or :due
394
+ # @return [Boolean] whether the data was updated in OSM
395
+ def mark_awarded(api, date=Date.today, level=completed, mark_as=:awarded)
396
+ raise ArgumentError, 'date is not a Date' unless date.is_a?(Date)
397
+ raise ArgumentError, 'mark_as is not an allowed value, use :awarded or :du' unless [:awarded, :due].include?(mark_as)
398
+ raise ArgumentError, 'level can not be negative' if level < 0
399
+ section = Osm::Section.get(api, section_id)
400
+ require_ability_to(api, :write, :badge, section)
401
+
402
+ date_formatted = date.strftime(Osm::OSM_DATE_FORMAT)
403
+
404
+ result = api.perform_query("challenges.php?action=award", {
405
+ 'dateAwarded' => date_formatted,
406
+ 'sectionid' => section_id,
407
+ 'section' => section.type,
408
+ 'chal' => badge.osm_key,
409
+ 'type' => badge.type,
410
+ 'stagedLevel' => level,
411
+ 'due' => mark_as,
412
+ })
413
+ updated = result.is_a?(Array) &&
414
+ result[0].is_a?(Hash) &&
415
+ (result[0]['sid'].to_i == member_id) &&
416
+ (result[0]['awarded'].to_i == level) &&
417
+ (result[0]['awardeddate'] == date_formatted)
418
+
419
+ if updated
420
+ awarded = level
421
+ awarded_date = date
422
+ end
423
+ return updated
424
+ end
425
+
426
+ # Mark the badge as due in OSM
427
+ # @param [Osm::Api] api The api to use to make the request
428
+ # @param [Fixnum] level The level of the badge to mark as due (1 for non-staged badges)
429
+ # @return [Boolean] whether the data was updated in OSM
430
+ def mark_due(api, level)
431
+ mark_awarded(api, Date.today, level, :due)
432
+ end
433
+
282
434
  # Update data in OSM
283
435
  # @param [Osm::Api] api The api to use to make the request
284
436
  # @return [Boolean] whether the data was updated in OSM
@@ -286,13 +438,13 @@ module Osm
286
438
  def update(api)
287
439
  raise Osm::ObjectIsInvalid, 'data is invalid' unless valid?
288
440
  section = Osm::Section.get(api, section_id)
289
- Osm::Model.require_ability_to(api, :write, :badge, section)
441
+ require_ability_to(api, :write, :badge, section)
290
442
 
291
443
  updated = true
292
444
  editable_fields = badge.requirements.select{ |r| r.editable }.map{ |r| r.field}
293
445
  requirements.changes.each do |field, (was,now)|
294
446
  if editable_fields.include?(field)
295
- result = api.perform_query("challenges.php?type=#{badge.class.badge_type}&section=#{section.type}", {
447
+ result = api.perform_query("challenges.php?type=#{badge.class.type}&section=#{section.type}", {
296
448
  'action' => 'updatesingle',
297
449
  'id' => member_id,
298
450
  'col' => field,
@@ -306,11 +458,18 @@ module Osm
306
458
  end
307
459
  end
308
460
 
309
-
310
461
  if updated
311
462
  requirements.clean_up!
312
463
  end
313
464
 
465
+ if changed_attributes.include?('awarded') || changed_attributes.include?('awarded_date')
466
+ if mark_awarded(api, awarded_date, awarded)
467
+ reset_changed_attributes
468
+ else
469
+ updated = false
470
+ end
471
+ end
472
+
314
473
  return updated
315
474
  end
316
475
 
@@ -333,28 +492,28 @@ module Osm
333
492
 
334
493
  class CoreBadge < Osm::Badge
335
494
  private
336
- def self.badge_type
495
+ def self.type
337
496
  :core
338
497
  end
339
498
  end # Class CoreBadge
340
499
 
341
500
  class ChallengeBadge < Osm::Badge
342
501
  private
343
- def self.badge_type
502
+ def self.type
344
503
  :challenge
345
504
  end
346
505
  end # Class ChallengeBadge
347
506
 
348
507
  class StagedBadge < Osm::Badge
349
508
  private
350
- def self.badge_type
509
+ def self.type
351
510
  :staged
352
511
  end
353
512
  end # Class StagedBadge
354
513
 
355
514
  class ActivityBadge < Osm::Badge
356
515
  private
357
- def self.badge_type
516
+ def self.type
358
517
  :activity
359
518
  end
360
519
  def self.subscription_required
data/lib/osm/register.rb CHANGED
@@ -56,7 +56,9 @@ module Osm
56
56
  end
57
57
 
58
58
  data = api.perform_query("users.php?action=register&sectionid=#{section_id}&termid=#{term_id}")
59
- dates = get_structure(api, section, term, options).map{ |f| f.id }.select{ |f| f.match(Osm::OSM_DATE_REGEX) }
59
+ dates_s = get_structure(api, section, term, options)
60
+ dates_s = dates_s.map{ |f| f.id }.select{ |f| f.match(Osm::OSM_DATE_REGEX) }
61
+ dates_d = dates_s.map{ |d| Osm::parse_date(d) }
60
62
 
61
63
  to_return = []
62
64
  if data.is_a?(Hash) && data['items'].is_a?(Array)
@@ -65,9 +67,8 @@ module Osm
65
67
  if item.is_a?(Hash)
66
68
  unless item['scoutid'].to_i < 0 # It's a total row
67
69
  attendance = {}
68
- dates.each do |date|
69
- item_attendance = item[date]
70
- date = Date.strptime(date, Osm::OSM_DATE_FORMAT)
70
+ dates_d.each_with_index do |date, index|
71
+ item_attendance = item[dates_s[index]]
71
72
  attendance[date] = :unadvised_absent
72
73
  attendance[date] = :yes if item_attendance.eql?('Yes')
73
74
  attendance[date] = :advised_absent if item_attendance.eql?('No')
@@ -44,7 +44,10 @@ describe "Badge" do
44
44
  it "Create Data" do
45
45
  data = Osm::Badge::Data.new(
46
46
  :member_id => 1,
47
- :completed => true,
47
+ :first_name => 'First',
48
+ :last_name => 'Last',
49
+ :completed => 4,
50
+ :awarded => 3,
48
51
  :awarded_date => Date.new(2000, 1, 2),
49
52
  :requirements => {},
50
53
  :section_id => 2,
@@ -52,7 +55,10 @@ describe "Badge" do
52
55
  )
53
56
 
54
57
  data.member_id.should == 1
55
- data.completed.should == true
58
+ data.first_name.should == 'First'
59
+ data.last_name.should == 'Last'
60
+ data.completed.should == 4
61
+ data.awarded.should == 3
56
62
  data.awarded_date.should == Date.new(2000, 1, 2)
57
63
  data.requirements.should == {}
58
64
  data.section_id.should == 2
@@ -128,6 +134,64 @@ describe "Badge" do
128
134
  data.sections_gained.should == 1
129
135
  end
130
136
 
137
+ it "Works out if the badge is due" do
138
+ Osm::Badge::Data.new(:completed => 0, :awarded => 0).due?.should be_false
139
+ Osm::Badge::Data.new(:completed => 1, :awarded => 0).due?.should be_true
140
+ Osm::Badge::Data.new(:completed => 2, :awarded => 2).due?.should be_false
141
+ Osm::Badge::Data.new(:completed => 2, :awarded => 1).due?.should be_true
142
+ end
143
+
144
+ it "Works out if the badge has been started" do
145
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => 'Yes', 'a_02' => ''}).started?.should be_true
146
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => 'Yes', 'a_02' => ''}, :completed => 1).started?.should be_false
147
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => 'xNo', 'a_02' => ''}).started?.should be_false
148
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => '', 'a_02' => ''}).started?.should be_false
149
+ # Staged Badge
150
+ Osm::Badge::Data.new(
151
+ :badge => Osm::StagedBadge.new,
152
+ :requirements => {'a_01' => 'Yes', 'b_01' => 'Yes', 'b_02' => ''},
153
+ :completed => 1,
154
+ ).started?.should be_true
155
+ Osm::Badge::Data.new(
156
+ :badge => Osm::StagedBadge.new(:osm_key => 'nightsaway'),
157
+ :requirements => {'a_01' => 5, 'y_01' => '5', 'custom_26695' => ''},
158
+ :completed => 5,
159
+ ).started?.should be_false
160
+ Osm::Badge::Data.new(
161
+ :badge => Osm::StagedBadge.new(:osm_key => 'hikes'),
162
+ :requirements => {'a_01' => 2, 'y_01' => '2', 'custom_26695' => ''},
163
+ :completed => 1,
164
+ ).started?.should be_true
165
+ end
166
+
167
+ it "Works out what stage of the badge has been started" do
168
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => 'Yes', 'a_02' => ''}).started.should == 1
169
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => 'Yes', 'a_02' => ''}, :completed => 1).started.should == 0
170
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => 'xNo', 'a_02' => ''}).started.should == 0
171
+ Osm::Badge::Data.new(:badge => Osm::CoreBadge.new, :requirements => {'a_01' => '', 'a_02' => ''}).started.should == 0
172
+
173
+ # Staged Badge
174
+ Osm::Badge::Data.new(
175
+ :badge => Osm::StagedBadge.new(:osm_key => 'test'),
176
+ :requirements => {'a_01' => 'Yes', 'b_01' => 'Yes', 'b_02' => ''},
177
+ :completed => 1,
178
+ ).started.should == 2
179
+ Osm::Badge::Data.new(
180
+ :badge => Osm::StagedBadge.new(:osm_key => 'test'),
181
+ :requirements => {'a_01' => 'Yes', 'b_01' => 'Yes', 'b_02' => '', 'c_01' => 'Yes', 'c_02' => ''},
182
+ :completed => 1,
183
+ ).started.should == 2
184
+ Osm::Badge::Data.new(
185
+ :badge => Osm::StagedBadge.new(:osm_key => 'nightsaway'),
186
+ :requirements => {'a_01' => 7, 'y_01' => '7', 'custom_26695' => ''},
187
+ :completed => 5,
188
+ ).started.should == 10
189
+ Osm::Badge::Data.new(
190
+ :badge => Osm::StagedBadge.new(:osm_key => 'hikes'),
191
+ :requirements => {'a_01' => 2, 'y_01' => '2', 'custom_26695' => ''},
192
+ :completed => 1,
193
+ ).started.should == 5
194
+ end
131
195
 
132
196
  describe "Using the OSM API" do
133
197
 
@@ -261,6 +325,14 @@ describe "Badge" do
261
325
  requirement.badge.osm_key.should == 'badge'
262
326
  end
263
327
 
328
+ it "For a different section type" do
329
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=getInitialBadges&type=activity&sectionid=1&section=cubs&termid=2", :body => @data)
330
+ Osm::Term.stub(:get_current_term_for_section){ Osm::Term.new(:id => 2) }
331
+
332
+ badges = Osm::ActivityBadge.get_badges_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), :cubs)
333
+ badges.size.should == 1
334
+ end
335
+
264
336
  end
265
337
 
266
338
 
@@ -274,8 +346,8 @@ describe "Badge" do
274
346
  'firstname' => 'fn',
275
347
  'lastname' => 'ln',
276
348
  'sid' => '',
277
- 'completed' => '1',
278
- 'awarded' => '',
349
+ 'completed' => '2',
350
+ 'awarded' => '1',
279
351
  'awardeddate' => '2000-01-02',
280
352
  'patrolid' => 4,
281
353
  'a_1' => 'd',
@@ -286,11 +358,14 @@ describe "Badge" do
286
358
 
287
359
  it "Core badge" do
288
360
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?termid=2&type=core&section=beavers&c=badge&sectionid=1", :body => @data)
289
- datas = Osm::CoreBadge.get_badge_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), Osm::Badge.new(:osm_key => 'badge'), 2)
361
+ datas = Osm::CoreBadge.new(:osm_key => 'badge').get_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
290
362
  datas.size.should == 1
291
363
  data = datas[0]
292
364
  data.member_id.should == 3
293
- data.completed.should == true
365
+ data.first_name.should == 'fn'
366
+ data.last_name.should == 'ln'
367
+ data.completed.should == 2
368
+ data.awarded.should == 1
294
369
  data.awarded_date.should == Date.new(2000, 1, 2)
295
370
  data.requirements.should == {'a_1' => 'd'}
296
371
  data.section_id.should == 1
@@ -299,11 +374,14 @@ describe "Badge" do
299
374
 
300
375
  it "Challenge badge" do
301
376
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?termid=2&type=challenge&section=beavers&c=badge&sectionid=1", :body => @data)
302
- datas = Osm::ChallengeBadge.get_badge_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), Osm::Badge.new(:osm_key => 'badge'), 2)
377
+ datas = Osm::ChallengeBadge.new(:osm_key => 'badge').get_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
303
378
  datas.size.should == 1
304
379
  data = datas[0]
305
380
  data.member_id.should == 3
306
- data.completed.should == true
381
+ data.first_name.should == 'fn'
382
+ data.last_name.should == 'ln'
383
+ data.completed.should == 2
384
+ data.awarded.should == 1
307
385
  data.awarded_date.should == Date.new(2000, 1, 2)
308
386
  data.requirements.should == {'a_1' => 'd'}
309
387
  data.section_id.should == 1
@@ -312,11 +390,14 @@ describe "Badge" do
312
390
 
313
391
  it "Staged badge" do
314
392
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?termid=2&type=staged&section=beavers&c=badge&sectionid=1", :body => @data)
315
- datas = Osm::StagedBadge.get_badge_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), Osm::Badge.new(:osm_key => 'badge'), 2)
393
+ datas = Osm::StagedBadge.new(:osm_key => 'badge').get_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
316
394
  datas.size.should == 1
317
395
  data = datas[0]
318
396
  data.member_id.should == 3
319
- data.completed.should == true
397
+ data.first_name.should == 'fn'
398
+ data.last_name.should == 'ln'
399
+ data.completed.should == 2
400
+ data.awarded.should == 1
320
401
  data.awarded_date.should == Date.new(2000, 1, 2)
321
402
  data.requirements.should == {'a_1' => 'd'}
322
403
  data.section_id.should == 1
@@ -325,11 +406,14 @@ describe "Badge" do
325
406
 
326
407
  it "Activity badge" do
327
408
  FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?termid=2&type=activity&section=beavers&c=badge&sectionid=1", :body => @data)
328
- datas = Osm::ActivityBadge.get_badge_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), Osm::Badge.new(:osm_key => 'badge'), 2)
409
+ datas = Osm::ActivityBadge.new(:osm_key => 'badge').get_data_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
329
410
  datas.size.should == 1
330
411
  data = datas[0]
331
412
  data.member_id.should == 3
332
- data.completed.should == true
413
+ data.first_name.should == 'fn'
414
+ data.last_name.should == 'ln'
415
+ data.completed.should == 2
416
+ data.awarded.should == 1
333
417
  data.awarded_date.should == Date.new(2000, 1, 2)
334
418
  data.requirements.should == {'a_1' => 'd'}
335
419
  data.section_id.should == 1
@@ -341,7 +425,7 @@ describe "Badge" do
341
425
  describe "Update badge data for a section/member" do
342
426
 
343
427
  before :each do
344
- @post_data = {
428
+ @update_post_data = {
345
429
  'apiid' => @CONFIGURATION[:api][:osm][:id],
346
430
  'token' => @CONFIGURATION[:api][:osm][:token],
347
431
  'userid' => 'user_id',
@@ -353,13 +437,29 @@ describe "Badge" do
353
437
  'chal' => 'badge',
354
438
  'sectionid' => 2,
355
439
  }
440
+ @update_body_data = {'sid' => '1', 'a' => '2', 'b' => '2'}
356
441
 
357
- @body_data = {'sid' => '1', 'a' => '2', 'b' => '2'}
442
+ @awarded_post_data = {
443
+ 'apiid' => @CONFIGURATION[:api][:osm][:id],
444
+ 'token' => @CONFIGURATION[:api][:osm][:token],
445
+ 'userid' => 'user_id',
446
+ 'secret' => 'secret',
447
+ 'dateAwarded' => '2000-01-02',
448
+ 'sectionid' => 2,
449
+ 'section' => :beavers,
450
+ 'chal' => 'badge',
451
+ 'stagedLevel' => 1,
452
+ 'due' => :awarded,
453
+ }
454
+ @awarded_body_data = [{'sid'=>'1', 'awarded'=>'1', 'awardeddate'=>'2000-01-02'}]
455
+ @awarded_url = "https://www.onlinescoutmanager.co.uk/challenges.php?action=award"
358
456
  end
359
457
 
360
458
  it "Core badge" do
361
459
  data = Osm::Badge::Data.new(
362
460
  :member_id => 1,
461
+ :first_name => 'fn',
462
+ :last_name => 'ln',
363
463
  :section_id => 2,
364
464
  :requirements => {'a' => '1', 'b' => '2'},
365
465
  :badge => Osm::CoreBadge.new(
@@ -368,20 +468,25 @@ describe "Badge" do
368
468
  Osm::Badge::Requirement.new(:field => 'a', :editable => true),
369
469
  Osm::Badge::Requirement.new(:field => 'b', :editable => true),
370
470
  ]),
371
- :completed => false,
471
+ :completed => 0,
372
472
  )
373
473
 
374
- url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=core&section=beavers"
375
- HTTParty.should_receive(:post).with(url, {:body => @post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@body_data.to_json}) }
474
+ update_url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=core&section=beavers"
475
+ HTTParty.should_receive(:post).with(update_url, {:body => @update_post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@update_body_data.to_json}) }
476
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :core})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
376
477
  Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
377
478
 
378
479
  data.requirements['a'] = '2'
480
+ data.awarded = 1
481
+ data.awarded_date = Date.new(2000, 1, 2)
379
482
  data.update(@api).should be_true
380
483
  end
381
484
 
382
485
  it "Challenge badge" do
383
486
  data = Osm::Badge::Data.new(
384
487
  :member_id => 1,
488
+ :first_name => 'fn',
489
+ :last_name => 'ln',
385
490
  :section_id => 2,
386
491
  :requirements => {'a' => '1', 'b' => '2'},
387
492
  :badge => Osm::ChallengeBadge.new(
@@ -390,20 +495,25 @@ describe "Badge" do
390
495
  Osm::Badge::Requirement.new(:field => 'a', :editable => true),
391
496
  Osm::Badge::Requirement.new(:field => 'b', :editable => true),
392
497
  ]),
393
- :completed => false,
498
+ :completed => 0,
394
499
  )
395
500
 
396
- url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=challenge&section=beavers"
397
- HTTParty.should_receive(:post).with(url, {:body => @post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@body_data.to_json}) }
501
+ update_url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=challenge&section=beavers"
502
+ HTTParty.should_receive(:post).with(update_url, {:body => @update_post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@update_body_data.to_json}) }
503
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :challenge})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
398
504
  Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
399
505
 
400
506
  data.requirements['a'] = '2'
507
+ data.awarded = 1
508
+ data.awarded_date = Date.new(2000, 1, 2)
401
509
  data.update(@api).should be_true
402
510
  end
403
511
 
404
512
  it "Staged badge" do
405
513
  data = Osm::Badge::Data.new(
406
514
  :member_id => 1,
515
+ :first_name => 'fn',
516
+ :last_name => 'ln',
407
517
  :section_id => 2,
408
518
  :requirements => {'a' => '1', 'b' => '2'},
409
519
  :badge => Osm::StagedBadge.new(
@@ -412,20 +522,25 @@ describe "Badge" do
412
522
  Osm::Badge::Requirement.new(:field => 'a', :editable => true),
413
523
  Osm::Badge::Requirement.new(:field => 'b', :editable => true),
414
524
  ]),
415
- :completed => false,
525
+ :completed => 0,
416
526
  )
417
527
 
418
- url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=staged&section=beavers"
419
- HTTParty.should_receive(:post).with(url, {:body => @post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@body_data.to_json}) }
528
+ update_url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=staged&section=beavers"
529
+ HTTParty.should_receive(:post).with(update_url, {:body => @update_post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@update_body_data.to_json}) }
530
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :staged})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
420
531
  Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
421
532
 
422
533
  data.requirements['a'] = '2'
534
+ data.awarded = 1
535
+ data.awarded_date = Date.new(2000, 1, 2)
423
536
  data.update(@api).should be_true
424
537
  end
425
538
 
426
539
  it "Activity badge" do
427
540
  data = Osm::Badge::Data.new(
428
541
  :member_id => 1,
542
+ :first_name => 'fn',
543
+ :last_name => 'ln',
429
544
  :section_id => 2,
430
545
  :requirements => {'a' => '1', 'b' => '2'},
431
546
  :badge => Osm::ActivityBadge.new(
@@ -434,19 +549,171 @@ describe "Badge" do
434
549
  Osm::Badge::Requirement.new(:field => 'a', :editable => true),
435
550
  Osm::Badge::Requirement.new(:field => 'b', :editable => true),
436
551
  ]),
437
- :completed => false,
552
+ :completed => 0,
438
553
  )
439
554
 
440
- url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=activity&section=beavers"
441
- HTTParty.should_receive(:post).with(url, {:body => @post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@body_data.to_json}) }
555
+ update_url = "https://www.onlinescoutmanager.co.uk/challenges.php?type=activity&section=beavers"
556
+ HTTParty.should_receive(:post).with(update_url, {:body => @update_post_data}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@update_body_data.to_json}) }
557
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :activity})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
442
558
  Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
443
559
 
444
560
  data.requirements['a'] = '2'
561
+ data.awarded = 1
562
+ data.awarded_date = Date.new(2000, 1, 2)
445
563
  data.update(@api).should be_true
446
564
  end
447
565
 
448
566
  end
449
567
 
568
+
569
+ describe "Mark badge awarded" do
570
+
571
+ before :each do
572
+ @awarded_post_data = {
573
+ 'apiid' => @CONFIGURATION[:api][:osm][:id],
574
+ 'token' => @CONFIGURATION[:api][:osm][:token],
575
+ 'userid' => 'user_id',
576
+ 'secret' => 'secret',
577
+ 'dateAwarded' => '2000-01-02',
578
+ 'sectionid' => 2,
579
+ 'section' => :beavers,
580
+ 'chal' => 'badge',
581
+ 'stagedLevel' => 1,
582
+ 'due' => :awarded,
583
+ }
584
+ @awarded_body_data = [{'sid'=>'1', 'awarded'=>'1', 'awardeddate'=>'2000-01-02'}]
585
+ @awarded_url = "https://www.onlinescoutmanager.co.uk/challenges.php?action=award"
586
+ end
587
+
588
+ it "Core badge" do
589
+ data = Osm::Badge::Data.new(
590
+ :member_id => 1,
591
+ :section_id => 2,
592
+ :badge => Osm::CoreBadge.new(
593
+ :osm_key => 'badge',
594
+ )
595
+ )
596
+
597
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :core})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
598
+ Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
599
+
600
+ data.mark_awarded(@api, Date.new(2000, 1, 2), 1).should be_true
601
+ end
602
+
603
+ it "Challenge badge" do
604
+ data = Osm::Badge::Data.new(
605
+ :member_id => 1,
606
+ :section_id => 2,
607
+ :badge => Osm::ChallengeBadge.new(
608
+ :osm_key => 'badge',
609
+ )
610
+ )
611
+
612
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :challenge})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
613
+ Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
614
+
615
+ data.mark_awarded(@api, Date.new(2000, 1, 2), 1).should be_true
616
+ end
617
+
618
+ it "Staged badge" do
619
+ data = Osm::Badge::Data.new(
620
+ :member_id => 1,
621
+ :section_id => 2,
622
+ :badge => Osm::StagedBadge.new(
623
+ :osm_key => 'badge',
624
+ )
625
+ )
626
+
627
+ @awarded_body_data[0].merge!({'awarded' => '4'})
628
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :staged, 'stagedLevel' => 4})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
629
+ Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
630
+
631
+ data.mark_awarded(@api, Date.new(2000, 1, 2), 4).should be_true
632
+ end
633
+
634
+ it "Activity badge" do
635
+ data = Osm::Badge::Data.new(
636
+ :member_id => 1,
637
+ :section_id => 2,
638
+ :badge => Osm::ActivityBadge.new(
639
+ :osm_key => 'badge',
640
+ )
641
+ )
642
+
643
+ HTTParty.should_receive(:post).with(@awarded_url, {:body => @awarded_post_data.merge({'type' => :activity})}) { OsmTest::DummyHttpResult.new(:response=>{:code=>'200', :body=>@awarded_body_data.to_json}) }
644
+ Osm::Section.stub(:get) { Osm::Section.new(:id => 2, :type => :beavers) }
645
+
646
+ data.mark_awarded(@api, Date.new(2000, 1, 2), 1).should be_true
647
+ end
648
+
649
+ end
650
+
651
+
652
+ describe "Get summary data for a section" do
653
+
654
+ before :each do
655
+ @data = {
656
+ 'items' => [
657
+ {
658
+ 'firstname' => 'First',
659
+ 'lastname' => 'Last',
660
+ 'badge_none' => '',
661
+ 'badge_earnt' => '2000-01-02',
662
+ }
663
+ ]
664
+ }
665
+ @data = @data.to_json
666
+ end
667
+
668
+ it "Core badge" do
669
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=summary&section=beavers&sectionid=1&termid=2&type=core", :body => @data)
670
+ summary = Osm::CoreBadge.get_summary_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
671
+ summary.size.should == 1
672
+ summary[0].should == {
673
+ :first_name => 'First',
674
+ :last_name => 'Last',
675
+ 'badge_none' => '',
676
+ 'badge_earnt' => '2000-01-02',
677
+ }
678
+ end
679
+
680
+ it "Challenge badge" do
681
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=summary&section=beavers&sectionid=1&termid=2&type=challenge", :body => @data)
682
+ summary = Osm::ChallengeBadge.get_summary_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
683
+ summary.size.should == 1
684
+ summary[0].should == {
685
+ :first_name => 'First',
686
+ :last_name => 'Last',
687
+ 'badge_none' => '',
688
+ 'badge_earnt' => '2000-01-02',
689
+ }
690
+ end
691
+
692
+ it "Staged badge" do
693
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=summary&section=beavers&sectionid=1&termid=2&type=staged", :body => @data)
694
+ summary = Osm::StagedBadge.get_summary_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
695
+ summary.size.should == 1
696
+ summary[0].should == {
697
+ :first_name => 'First',
698
+ :last_name => 'Last',
699
+ 'badge_none' => '',
700
+ 'badge_earnt' => '2000-01-02',
701
+ }
702
+ end
703
+
704
+ it "Activity badge" do
705
+ FakeWeb.register_uri(:post, "https://www.onlinescoutmanager.co.uk/challenges.php?action=summary&section=beavers&sectionid=1&termid=2&type=activity", :body => @data)
706
+ summary = Osm::ActivityBadge.get_summary_for_section(@api, Osm::Section.new(:id => 1, :type => :beavers), 2)
707
+ summary.size.should == 1
708
+ summary[0].should == {
709
+ :first_name => 'First',
710
+ :last_name => 'Last',
711
+ 'badge_none' => '',
712
+ 'badge_earnt' => '2000-01-02',
713
+ }
714
+ end
715
+ end
716
+
450
717
  end
451
718
 
452
719
  end
data/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Osm
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-29 00:00:00.000000000 Z
12
+ date: 2013-04-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport