aladtec 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4559364e023c7c4a781ecc7463901b10256bf125
4
- data.tar.gz: fee96a2725c63d0b50b0251442e7be614e1b1791
3
+ metadata.gz: 5833472c1eeb7a7f359005a98ba355d114fb8223
4
+ data.tar.gz: 969f3e879943297a501a15253cece2cefbb7facb
5
5
  SHA512:
6
- metadata.gz: d7487b455740cf72952d88ac0da3998d5523e36caf86a9d5fd0dbc212ae6f6215ea1007d29c1d19fac8efb74611a53fa93780308117c05527411b064a628aa89
7
- data.tar.gz: 2d003cffb72914e92712dbc08990ae19d4a71f55155032aa3602296b4f1f4151cb7485264086596466d0049cd124698187d445a34ff6983c4f89f815ba29e426
6
+ metadata.gz: afdf0a35e2d5e5960a4958b41044ef0f5a7eb1c6484ccac93d8786ac7c7b6f2b910f3b8cf52f49e73b7d687de4c86b73522911748d000b3a1d2e767966385203
7
+ data.tar.gz: 648d57e16f2ded50b0d62f966a3c59464032cf3d93d6502699b476c99607ccb8639e9d6d45ff8bdef6d79e24605c59edb510fb91c5b22e28d12f65bffd3fba63
@@ -1,6 +1,4 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.1.0
5
- - 2.0.0
6
- - 1.9.3
4
+ - 2.3.1
@@ -0,0 +1,3 @@
1
+ # 0.2.0
2
+ - Removed dependencies on happy_mapper and rest_client.
3
+ - Removed RangeDenormalizer. ScheduledRanges will no longer include member and position attributes.
data/README.md CHANGED
@@ -29,13 +29,16 @@ Configure the gem with your credentials:
29
29
  end
30
30
 
31
31
  Get members
32
+
32
33
  client = Aladtec::Client.new
33
34
  client.members
34
35
 
35
36
  Get events
37
+
36
38
  client.events(begin_date: Date.today)
37
39
 
38
40
  Get schedules
41
+
39
42
  client.schedules
40
43
 
41
44
  Refer to the [documentation](http://www.rubydoc.info/github/travisdahlke/aladtec) for more detailed usage.
@@ -24,6 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "webmock"
25
25
  spec.add_development_dependency "pry"
26
26
 
27
- spec.add_dependency "rest-client", "~> 1.6.7"
28
- spec.add_dependency "happymapper", "~> 0.4.1"
27
+ spec.add_dependency "multi_xml"
29
28
  end
@@ -1,14 +1,13 @@
1
- require 'happymapper'
2
-
3
1
  module Aladtec
4
2
  class Authentication
5
- include HappyMapper
3
+ attr_accessor :code, :retry, :message, :member
6
4
 
7
- tag 'authentication'
8
- attribute :code, Integer
9
- attribute :retry, Integer
10
- element :message, String
11
- has_one :member, Member
5
+ def initialize(args = {})
6
+ @code = args["code"].to_i
7
+ @retry = args["retry"]
8
+ @message = args["message"]
9
+ @member = args["member"]
10
+ end
12
11
 
13
12
  def success?
14
13
  self.code == 0
@@ -1,15 +1,16 @@
1
- require 'kconv'
2
- require 'rest-client'
1
+ require 'net/http'
2
+ require 'multi_xml'
3
3
  require 'aladtec/event'
4
4
  require 'aladtec/member'
5
5
  require 'aladtec/authentication'
6
6
  require 'aladtec/range'
7
7
  require 'aladtec/schedule'
8
- require 'aladtec/range_denormalizer'
8
+ require 'aladtec/exceptions'
9
9
 
10
10
  module Aladtec
11
11
  class Client
12
12
 
13
+
13
14
  attr_accessor *Configuration::VALID_CONFIG_KEYS
14
15
 
15
16
  def initialize(options={})
@@ -26,43 +27,41 @@ module Aladtec
26
27
  # :begin_date - The begin date to return events for (required).
27
28
  # :end_date - The end date to return events for (optional).
28
29
  def events(options = {})
29
- bd = options.fetch(:begin_date) { raise "You must supply a :begin_date option!"}
30
+ bd = options.fetch(:begin_date) { raise ArgumentError, "You must supply a :begin_date option!"}
30
31
  ed = options.fetch(:end_date, nil)
31
32
  bd = bd.is_a?(Date) ? bd.iso8601 : Date.parse(bd).iso8601
32
33
  if ed
33
34
  ed = ed.is_a?(Date) ? ed.iso8601 : Date.parse(ed).iso8601
34
35
  end
35
- response = request(:getEvents, bd: bd, ed: ed)
36
- Event.parse(response.body)
37
- rescue LibXML::XML::Error
38
- Event.parse(Kconv.toutf8(response.body))
36
+ body = request(:getEvents, bd: bd, ed: ed)
37
+ fetch_map(body, "events", "event", Event)
39
38
  end
40
39
 
41
40
  # Public: Get a list of members
42
41
  #
43
42
  def members
44
- response = request(:getMembers, ia: 'all')
45
- Member.parse(response.body)
43
+ body = request(:getMembers, ia: 'all')
44
+ fetch_map(body, "members", "member", Member)
46
45
  end
47
46
 
48
47
  # Public: Authenticate member
49
48
  #
50
49
  def auth(username, password)
51
- response = request(:authenticateMember, memun: username, mempw: password)
52
- Authentication.parse(response.body)
50
+ body = request(:authenticateMember, memun: username, mempw: password)
51
+ Authentication.new(body["results"]["authentication"])
53
52
  end
54
53
 
55
54
  # Public: Get a list of schedules
56
55
  #
57
56
  def schedules
58
- response = request(:getSchedules, isp: 1)
59
- Schedule.parse(response.body)
57
+ body = request(:getSchedules, isp: 1)
58
+ fetch_map(body, "schedules", "schedule", Schedule)
60
59
  end
61
60
 
62
61
  # Public: Get list of members scheduled now
63
- def scheduled_now
64
- response = request(:getScheduledTimeNow, isp: 1)
65
- Schedule.parse(response.body)
62
+ def scheduled_now(options = {})
63
+ body = request(:getScheduledTimeNow, {isp: 1}.merge(options))
64
+ fetch_map(body, "schedules", "schedule", Schedule)
66
65
  end
67
66
 
68
67
  # Public: Get list of members scheduled in a time range
@@ -70,18 +69,25 @@ module Aladtec
70
69
  # options - The Hash options used to refine the selection (default: {}):
71
70
  # :begin_time - The begin time to return events for (required).
72
71
  # :end_time - The end time to return events for (required).
72
+ # :sch - Array of schedule ids to fetch
73
73
  def scheduled_range(options = {})
74
- bt = options.fetch(:begin_time) { raise "You must supply a :begin_time!"}
75
- et = options.fetch(:end_time) { raise "You must supply an :end_time!"}
74
+ bt = options.fetch(:begin_time) { raise ArgumentError, "You must supply a :begin_time!"}
75
+ et = options.fetch(:end_time) { raise ArgumentError, "You must supply an :end_time!"}
76
+ sch = Array(options.fetch(:sch, "all")).join(",")
76
77
  bt = bt.is_a?(Time) ? bt.clone.utc.iso8601 : Time.parse(bt).utc.iso8601
77
78
  et = et.is_a?(Time) ? et.clone.utc.iso8601 : Time.parse(et).utc.iso8601
78
- response = request(:getScheduledTimeRanges, bt: bt, et: et, isp: 1)
79
- denormalize_ranges(Range.parse(response.body))
79
+ body = request(:getScheduledTimeRanges, bt: bt, et: et, isp: 1, sch: sch)
80
+ fetch_map(body, "ranges", "range", Range)
80
81
  end
81
82
 
82
- def denormalize_ranges(ranges, klass = RangeDenormalizer)
83
- klass.new(schedules: schedules, members: members).denormalize(ranges)
83
+ def fetch_map(body, collection, key, klass)
84
+ results = body["results"][collection][key] if body["results"][collection]
85
+ return [] unless results
86
+ # Array.wrap
87
+ results = results.respond_to?(:to_ary) ? results.to_ary : [results]
88
+ results.map{|r| klass.new(r)}
84
89
  end
90
+ private :fetch_map
85
91
 
86
92
  def auth_params
87
93
  {accid: acc_id, acckey: acc_key}
@@ -90,9 +96,34 @@ module Aladtec
90
96
 
91
97
  def request(cmd, options = {})
92
98
  post_params = options.merge(cmd: cmd)
93
- RestClient.post(endpoint, auth_params.merge(post_params), user_agent: user_agent, accept: :xml)
99
+ req = Net::HTTP::Post.new(uri)
100
+ req.set_form_data(auth_params.merge(post_params))
101
+ req['User-Agent'] = user_agent
102
+ req['Accept'] = 'application/xml'
103
+
104
+ res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
105
+ http.use_ssl = true
106
+ http.request(req)
107
+ end
108
+
109
+ case res
110
+ when Net::HTTPSuccess, Net::HTTPRedirection
111
+ body = MultiXml.parse(res.body)
112
+ if body["results"]["errors"]
113
+ raise Aladtec::Error, body["results"]["errors"]["error"]["__content__"]
114
+ else
115
+ return body
116
+ end
117
+ else
118
+ raise Aladtec::Error, res.msg
119
+ end
94
120
  end
95
121
  private :request
96
122
 
123
+ def uri
124
+ @uri ||= URI(endpoint)
125
+ end
126
+ private :uri
127
+
97
128
  end
98
129
  end
@@ -4,7 +4,7 @@ module Aladtec
4
4
  VALID_OPTIONS_KEYS = [:acc_id, :acc_key].freeze
5
5
  VALID_CONFIG_KEYS = VALID_CONNECTION_KEYS + VALID_OPTIONS_KEYS
6
6
 
7
- DEFAULT_ENDPOINT = 'https://secure.emsmanager.net/api/index.php'
7
+ DEFAULT_ENDPOINT = "https://secure.emsmanager.net/api/index.php".freeze
8
8
  DEFAULT_METHOD = :post
9
9
  DEFAULT_USER_AGENT = "Aladtec API Ruby Gem #{Aladtec::VERSION}".freeze
10
10
 
@@ -1,14 +1,13 @@
1
- require 'happymapper'
2
-
3
1
  module Aladtec
4
2
  class Event
5
- include HappyMapper
3
+ attr_accessor :title, :description, :location, :begin, :end
6
4
 
7
- tag 'event'
8
- element :title, String
9
- element :description, String
10
- element :location, String
11
- element :begin, Time
12
- element :end, Time
5
+ def initialize(args = {})
6
+ @title = args["title"]
7
+ @description = args["description"]
8
+ @location = args["location"]
9
+ @begin = Time.parse(args["begin"]) if args["begin"]
10
+ @end = Time.parse(args["end"]) if args["end"]
11
+ end
13
12
  end
14
13
  end
@@ -0,0 +1,3 @@
1
+ module Aladtec
2
+ class Error < StandardError; end
3
+ end
@@ -1,11 +1,10 @@
1
- require 'happymapper'
2
-
3
1
  module Aladtec
4
2
  class Member
5
- include HappyMapper
3
+ attr_accessor :id, :name
6
4
 
7
- tag 'member'
8
- attribute :id, Integer
9
- element :name, String
5
+ def initialize(args = {})
6
+ @id = args["id"].to_i
7
+ @name = args["name"]
8
+ end
10
9
  end
11
10
  end
@@ -1,13 +1,13 @@
1
- require 'happymapper'
2
1
  require 'aladtec/member'
3
2
 
4
3
  module Aladtec
5
4
  class Position
6
- include HappyMapper
5
+ attr_accessor :id, :name, :member
7
6
 
8
- tag 'position'
9
- element :name, String
10
- attribute :id, Integer
11
- has_one :member, Member
7
+ def initialize(args = {})
8
+ @id = args["id"].to_i
9
+ @name = args["name"]
10
+ @member = Member.new(args["member"]) if args["member"]
11
+ end
12
12
  end
13
13
  end
@@ -1,17 +1,18 @@
1
- require 'happymapper'
2
1
  require 'aladtec/schedule'
3
2
  require 'aladtec/position'
4
3
  require 'aladtec/member'
5
4
 
6
5
  module Aladtec
7
6
  class Range
8
- include HappyMapper
7
+ attr_accessor :schedule, :position, :member, :begin, :end
8
+
9
+ def initialize(args = {})
10
+ @member = Member.new(args["member"])
11
+ @position = Position.new(args["position"])
12
+ @schedule = Schedule.new(args["schedule"])
13
+ @begin = Time.parse(args["begin"]) if args["begin"]
14
+ @end = Time.parse(args["end"]) if args["end"]
15
+ end
9
16
 
10
- tag 'range'
11
- has_one :schedule, Schedule
12
- has_one :position, Position
13
- has_one :member, Member
14
- element :begin, Time
15
- element :end, Time
16
17
  end
17
18
  end
@@ -1,13 +1,22 @@
1
- require 'happymapper'
2
1
  require 'aladtec/position'
3
2
 
4
3
  module Aladtec
5
4
  class Schedule
6
- include HappyMapper
5
+ attr_accessor :id, :name, :positions
6
+
7
+ def initialize(args = {})
8
+ @id = args["id"].to_i
9
+ @name = args["name"]
10
+ @positions = parse_positions(args["positions"]["position"]) if args["positions"]
11
+ end
12
+
13
+ private
14
+
15
+ def parse_positions(positions)
16
+ return [] unless positions
17
+ return [Position.new(positions)] if positions.include? "id"
18
+ positions.map{|p| Position.new(p)}
19
+ end
7
20
 
8
- tag 'schedule'
9
- has_many :positions, Position
10
- element :name, String
11
- attribute :id, Integer
12
21
  end
13
22
  end
@@ -1,3 +1,3 @@
1
1
  module Aladtec
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -5,6 +5,20 @@ describe Aladtec::Client do
5
5
  Aladtec::Configuration::VALID_CONFIG_KEYS
6
6
  end
7
7
 
8
+ describe "#auth" do
9
+ let(:auth) { subject.auth("user", "pass") }
10
+ before(:each) do
11
+ stub_request(:post, "https://secure.emsmanager.net/api/index.php").
12
+ with(body: hash_including({cmd: "authenticateMember"})).
13
+ to_return(body: fixture('authenticate_member.xml'))
14
+ end
15
+
16
+ it "returns an authentication object" do
17
+ expect(auth).to be_success
18
+ end
19
+
20
+ end
21
+
8
22
  describe "#members" do
9
23
  let(:members) { subject.members }
10
24
  before(:each) do
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <results version="3.5.1" accessTime="2016­03­03T15:52:01Z">
3
+ <authentication code="0">
4
+ <member id="8"/>
5
+ </authentication>
6
+ </results>
@@ -1 +1,57 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
1
  <schedules>
3
2
  <schedule id="5">
4
3
  <name>Sample BLS - 24/48</name>
5
4
  </schedule>
6
5
  <schedule id="6">
7
6
  <name>Medic 5</name>
8
7
  </schedule>
9
8
  <schedule id="7">
10
9
  <name>Wheelchair Van 12</name>
11
10
  </schedule>
12
11
  <schedule id="8">
13
12
  <name>Air Crew</name>
14
13
  </schedule>
15
14
  <schedule id="9">
16
15
  <name>Dispatch</name>
17
16
  </schedule>
18
17
  </schedules>
18
+ <?xml version="1.0" encoding="UTF-8"?>
19
+ <results version="3.5.1" accessTime="2016­03­03T15:52:01Z">
20
+ <schedules>
21
+ <schedule id="5">
22
+ <name>Sample BLS - 24/48</name>
23
+ <positions>
24
+ <position id="1">
25
+ <name>EMT</name>
26
+ </position>
27
+ <position id="2">
28
+ <name>Driver</name>
29
+ </position>
30
+ </positions>
31
+ </schedule>
32
+ <schedule id="6">
33
+ <name>Medic 5</name>
34
+ <positions>
35
+ <position id="9">
36
+ <name>Medic</name>
37
+ </position>
38
+ <position id="8">
39
+ <name>EMT</name>
40
+ </position>
41
+ </positions>
42
+ </schedule>
43
+ <schedule id="7">
44
+ <name>Wheelchair Van 12</name>
45
+ <positions>
46
+ <position id="14">
47
+ <name>Driver</name>
48
+ </position>
49
+ </positions>
50
+ </schedule>
51
+ <schedule id="8">
52
+ <name>Air Crew</name>
53
+ <positions>
54
+ <position id="10">
55
+ <name>Medic</name>
56
+ </position>
57
+ <position id="11">
58
+ <name>EMT</name>
59
+ </position>
60
+ <position id="12">
61
+ <name>Pilot</name>
62
+ </position>
63
+ </positions>
64
+ </schedule>
65
+ <schedule id="9">
66
+ <name>Dispatch</name>
67
+ <positions>
68
+ <position id="4">
69
+ <name>Dispatcher</name>
70
+ </position>
71
+ </positions>
72
+ </schedule>
73
+ </schedules>
74
+ </results>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aladtec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Travis Dahlke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-30 00:00:00.000000000 Z
11
+ date: 2016-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,33 +81,19 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rest-client
84
+ name: multi_xml
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 1.6.7
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 1.6.7
97
- - !ruby/object:Gem::Dependency
98
- name: happymapper
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
87
+ - - ">="
102
88
  - !ruby/object:Gem::Version
103
- version: 0.4.1
89
+ version: '0'
104
90
  type: :runtime
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
- - - "~>"
94
+ - - ">="
109
95
  - !ruby/object:Gem::Version
110
- version: 0.4.1
96
+ version: '0'
111
97
  description: Retrieve schedules and events from the Aladtec API. Works with EMS Manager,
112
98
  Fire Manager, Zanager.
113
99
  email:
@@ -118,6 +104,7 @@ extra_rdoc_files: []
118
104
  files:
119
105
  - ".gitignore"
120
106
  - ".travis.yml"
107
+ - CHANGELOG.md
121
108
  - Gemfile
122
109
  - LICENSE.txt
123
110
  - README.md
@@ -128,16 +115,16 @@ files:
128
115
  - lib/aladtec/client.rb
129
116
  - lib/aladtec/configuration.rb
130
117
  - lib/aladtec/event.rb
118
+ - lib/aladtec/exceptions.rb
131
119
  - lib/aladtec/member.rb
132
120
  - lib/aladtec/position.rb
133
121
  - lib/aladtec/range.rb
134
- - lib/aladtec/range_denormalizer.rb
135
122
  - lib/aladtec/schedule.rb
136
123
  - lib/aladtec/version.rb
137
124
  - spec/aladtec/aladtec_spec.rb
138
125
  - spec/aladtec/client_spec.rb
139
126
  - spec/aladtec/configuration_spec.rb
140
- - spec/aladtec/range_denormalizer_spec.rb
127
+ - spec/fixtures/authenticate_member.xml
141
128
  - spec/fixtures/get_events.xml
142
129
  - spec/fixtures/get_members.xml
143
130
  - spec/fixtures/get_scheduled_time_now.xml
@@ -164,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
151
  version: '0'
165
152
  requirements: []
166
153
  rubyforge_project:
167
- rubygems_version: 2.4.5.1
154
+ rubygems_version: 2.5.1
168
155
  signing_key:
169
156
  specification_version: 4
170
157
  summary: Client library for the Aladtec API
@@ -172,7 +159,7 @@ test_files:
172
159
  - spec/aladtec/aladtec_spec.rb
173
160
  - spec/aladtec/client_spec.rb
174
161
  - spec/aladtec/configuration_spec.rb
175
- - spec/aladtec/range_denormalizer_spec.rb
162
+ - spec/fixtures/authenticate_member.xml
176
163
  - spec/fixtures/get_events.xml
177
164
  - spec/fixtures/get_members.xml
178
165
  - spec/fixtures/get_scheduled_time_now.xml
@@ -1,50 +0,0 @@
1
- module Aladtec
2
- class RangeDenormalizer
3
- attr_reader :members, :schedules
4
-
5
- def initialize(attrs = {})
6
- @members = attrs.fetch(:members) { raise "You must provide the members" }
7
- @schedules = attrs.fetch(:schedules) { raise "You must provide the schedules" }
8
- end
9
-
10
- def denormalize(ranges)
11
- ranges.each do |range|
12
- find_member(range)
13
- find_schedule(range)
14
- find_position(range)
15
- range.position = positions_by_id[range.position.id] || range.position
16
- end
17
- end
18
-
19
- def find_member(range)
20
- member = members_by_id[range.member.id]
21
- range.member = member if member
22
- end
23
-
24
- def find_schedule(range)
25
- schedule = schedules_by_id[range.schedule.id]
26
- range.schedule = schedule if schedule
27
- end
28
-
29
- def find_position(range)
30
- position = positions_by_id[range.position.id]
31
- range.position = position if position
32
- end
33
-
34
- def members_by_id
35
- @members_by_id ||= members.reduce({}) {|h, member| h[member.id] = member; h}
36
- end
37
-
38
- def schedules_by_id
39
- @schedules_by_id ||= schedules.reduce({}) do |h, schedule|
40
- h[schedule.id] = schedule
41
- schedule.positions.each {|position| positions_by_id[position.id] ||= position}
42
- h
43
- end
44
- end
45
-
46
- def positions_by_id
47
- @positions_by_id ||= {}
48
- end
49
- end
50
- end
@@ -1,26 +0,0 @@
1
- require_relative File.join('..','spec_helper')
2
- require 'ostruct'
3
-
4
- describe Aladtec::RangeDenormalizer do
5
- let(:members) {[OpenStruct.new(id: 1, name: "Joe Schmoe"), OpenStruct.new(id: 2, name: "Ann Perkins")]}
6
- let(:schedules) {
7
- [OpenStruct.new(id: 1, name: "Daytime", positions: [OpenStruct.new(id: 3, name: "Firefighter")]),
8
- OpenStruct.new(id: 2, name: "Nighttime", positions: [OpenStruct.new(id: 3, name: "Firefighter")])]
9
- }
10
- subject { Aladtec::RangeDenormalizer.new(members: members, schedules: schedules) }
11
-
12
- describe "#denormalize" do
13
- let(:ranges) {[OpenStruct.new(member: OpenStruct.new(id: 1), schedule: OpenStruct.new(id: 2), position: OpenStruct.new(id: 3))]}
14
- it "should map members to ranges" do
15
- expect(subject.denormalize(ranges).first.member.name).to eq("Joe Schmoe")
16
- end
17
-
18
- it "should map schedules to ranges" do
19
- expect(subject.denormalize(ranges).first.schedule.name).to eq("Nighttime")
20
- end
21
-
22
- it "should map positions to ranges" do
23
- expect(subject.denormalize(ranges).first.position.name).to eq("Firefighter")
24
- end
25
- end
26
- end