cdss-ruby 0.1.0

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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +86 -0
  3. data/CHANGELOG.md +5 -0
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/README.md +101 -0
  6. data/Rakefile +26 -0
  7. data/docs/Cdss/AdminCalls.html +399 -0
  8. data/docs/Cdss/Analysis.html +972 -0
  9. data/docs/Cdss/Client.html +581 -0
  10. data/docs/Cdss/Climate.html +1257 -0
  11. data/docs/Cdss/Concerns/LogReadingAttributes.html +406 -0
  12. data/docs/Cdss/Concerns/WellReadingAttributes.html +414 -0
  13. data/docs/Cdss/Concerns.html +117 -0
  14. data/docs/Cdss/GroundWater.html +945 -0
  15. data/docs/Cdss/Models/AdminCall.html +252 -0
  16. data/docs/Cdss/Models/Analysis.html +397 -0
  17. data/docs/Cdss/Models/CallAnalysis.html +140 -0
  18. data/docs/Cdss/Models/ClimateStation.html +249 -0
  19. data/docs/Cdss/Models/DiversionRecord.html +248 -0
  20. data/docs/Cdss/Models/Reading.html +301 -0
  21. data/docs/Cdss/Models/ReferenceTable.html +339 -0
  22. data/docs/Cdss/Models/RouteAnalysis.html +140 -0
  23. data/docs/Cdss/Models/SourceRoute.html +140 -0
  24. data/docs/Cdss/Models/Station.html +248 -0
  25. data/docs/Cdss/Models/Structure.html +259 -0
  26. data/docs/Cdss/Models/WaterClass.html +249 -0
  27. data/docs/Cdss/Models/WaterRight.html +255 -0
  28. data/docs/Cdss/Models/Well.html +251 -0
  29. data/docs/Cdss/Models.html +117 -0
  30. data/docs/Cdss/Parser.html +2155 -0
  31. data/docs/Cdss/Parsers/AdminCallsParser.html +201 -0
  32. data/docs/Cdss/Parsers/AnalysisParser.html +296 -0
  33. data/docs/Cdss/Parsers/BaseParser.html +207 -0
  34. data/docs/Cdss/Parsers/ClimateParser.html +253 -0
  35. data/docs/Cdss/Parsers/ReadingParser.html +201 -0
  36. data/docs/Cdss/Parsers/ReferenceTablesParser.html +201 -0
  37. data/docs/Cdss/Parsers/StationParser.html +201 -0
  38. data/docs/Cdss/Parsers/StructuresParser.html +305 -0
  39. data/docs/Cdss/Parsers/WaterRightsParser.html +219 -0
  40. data/docs/Cdss/Parsers/WellParser.html +357 -0
  41. data/docs/Cdss/Parsers.html +117 -0
  42. data/docs/Cdss/ReferenceTables.html +332 -0
  43. data/docs/Cdss/Structures.html +1132 -0
  44. data/docs/Cdss/SurfaceWater.html +798 -0
  45. data/docs/Cdss/Telemetry.html +763 -0
  46. data/docs/Cdss/Utils.html +1276 -0
  47. data/docs/Cdss/WaterRights.html +634 -0
  48. data/docs/Cdss.html +292 -0
  49. data/docs/_index.html +493 -0
  50. data/docs/class_list.html +54 -0
  51. data/docs/css/common.css +1 -0
  52. data/docs/css/full_list.css +58 -0
  53. data/docs/css/style.css +503 -0
  54. data/docs/file.README.html +108 -0
  55. data/docs/file_list.html +59 -0
  56. data/docs/frames.html +22 -0
  57. data/docs/index.html +108 -0
  58. data/docs/js/app.js +344 -0
  59. data/docs/js/full_list.js +242 -0
  60. data/docs/js/jquery.js +4 -0
  61. data/docs/method_list.html +790 -0
  62. data/docs/top-level-namespace.html +110 -0
  63. data/lib/cdss/admin_calls.rb +44 -0
  64. data/lib/cdss/analysis.rb +183 -0
  65. data/lib/cdss/client.rb +121 -0
  66. data/lib/cdss/climate.rb +155 -0
  67. data/lib/cdss/concerns/log_reading_attributes.rb +48 -0
  68. data/lib/cdss/concerns/well_reading_attributes.rb +56 -0
  69. data/lib/cdss/ground_water.rb +112 -0
  70. data/lib/cdss/models/admin_call.rb +45 -0
  71. data/lib/cdss/models/analysis.rb +77 -0
  72. data/lib/cdss/models/climate_station.rb +40 -0
  73. data/lib/cdss/models/reading.rb +54 -0
  74. data/lib/cdss/models/reference_table.rb +56 -0
  75. data/lib/cdss/models/station.rb +40 -0
  76. data/lib/cdss/models/structure.rb +101 -0
  77. data/lib/cdss/models/water_right.rb +47 -0
  78. data/lib/cdss/models/well.rb +43 -0
  79. data/lib/cdss/parser.rb +172 -0
  80. data/lib/cdss/parsers/admin_calls_parser.rb +47 -0
  81. data/lib/cdss/parsers/analysis_parser.rb +124 -0
  82. data/lib/cdss/parsers/base_parser.rb +18 -0
  83. data/lib/cdss/parsers/climate_parser.rb +86 -0
  84. data/lib/cdss/parsers/reading_parser.rb +90 -0
  85. data/lib/cdss/parsers/reference_tables_parser.rb +55 -0
  86. data/lib/cdss/parsers/station_parser.rb +42 -0
  87. data/lib/cdss/parsers/structures_parser.rb +96 -0
  88. data/lib/cdss/parsers/water_rights_parser.rb +77 -0
  89. data/lib/cdss/parsers/well_parser.rb +107 -0
  90. data/lib/cdss/reference_tables.rb +147 -0
  91. data/lib/cdss/structures.rb +235 -0
  92. data/lib/cdss/surface_water.rb +186 -0
  93. data/lib/cdss/telemetry.rb +98 -0
  94. data/lib/cdss/utils.rb +152 -0
  95. data/lib/cdss/version.rb +5 -0
  96. data/lib/cdss/water_rights.rb +95 -0
  97. data/lib/cdss.rb +27 -0
  98. data/sig/cdss/ruby.rbs +6 -0
  99. metadata +272 -0
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ # The Parser class handles parsing of response data from the CDSS API into domain objects.
5
+ # It delegates the actual parsing work to specialized parser modules for each data type.
6
+ class Parser
7
+ class << self
8
+ # Parses station data from the API response.
9
+ #
10
+ # @param response [Hash] The API response containing station data.
11
+ # @return [Array<Station>] Array of Station objects representing telemetry or surface water stations.
12
+ # @example Parse stations from API response
13
+ # stations = Parser.parse_stations(response_data)
14
+ def parse_stations(response)
15
+ Parsers::StationParser.parse_stations(response)
16
+ end
17
+
18
+ # Parses time series readings from the API response.
19
+ #
20
+ # @param response [Hash] The API response containing reading data.
21
+ # @param timescale [Symbol] The timescale of the readings (:day, :month, :year, :raw, :hour).
22
+ # @return [Array<Reading>] Array of Reading objects with time series data.
23
+ # @raise [ArgumentError] If an invalid timescale is provided.
24
+ # @example Parse daily readings
25
+ # readings = Parser.parse_readings(response_data, timescale: :day)
26
+ def parse_readings(response, timescale:)
27
+ Parsers::ReadingParser.parse_readings(response, timescale: timescale)
28
+ end
29
+
30
+ # Parses well data from the API response.
31
+ #
32
+ # @param response [Hash] The API response containing well data.
33
+ # @return [Array<Well>] Array of Well objects with basic well information.
34
+ # @example Parse wells from response
35
+ # wells = Parser.parse_wells(response_data)
36
+ def parse_wells(response)
37
+ Parsers::WellParser.parse_wells(response)
38
+ end
39
+
40
+ # Parses well measurement data from the API response.
41
+ #
42
+ # @param response [Hash] The API response containing well measurement data.
43
+ # @return [Array<Reading>] Array of Reading objects containing well measurements.
44
+ # @example Parse well measurements
45
+ # measurements = Parser.parse_well_measurements(response_data)
46
+ def parse_well_measurements(response)
47
+ Parsers::WellParser.parse_well_measurements(response)
48
+ end
49
+
50
+ # Parses geophysical well data from the API response.
51
+ #
52
+ # @param response [Hash] The API response containing geophysical well data.
53
+ # @return [Array<Well>] Array of Well objects with geophysical well information.
54
+ # @example Parse geophysical wells
55
+ # geo_wells = Parser.parse_geophysical_wells(response_data)
56
+ def parse_geophysical_wells(response)
57
+ Parsers::WellParser.parse_geophysical_wells(response)
58
+ end
59
+
60
+ # Parses geophysical log pick data from the API response.
61
+ #
62
+ # @param response [Hash] The API response containing log pick data.
63
+ # @return [Array<Reading>] Array of Reading objects containing log pick information.
64
+ # @example Parse log picks for a well
65
+ # picks = Parser.parse_log_picks(response_data)
66
+ def parse_log_picks(response)
67
+ Parsers::WellParser.parse_log_picks(response)
68
+ end
69
+
70
+ # Parses water rights data from the API response.
71
+ #
72
+ # @param response [Hash] The API response containing water rights data.
73
+ # @param type [Symbol] The type of water rights data to parse (:net_amount or :transaction).
74
+ # @return [Array<WaterRight>] Array of WaterRight objects.
75
+ # @raise [ArgumentError] If an invalid water rights type is provided.
76
+ # @example Parse net amounts
77
+ # rights = Parser.parse_water_rights(response_data, type: :net_amount)
78
+ # @example Parse transactions
79
+ # transactions = Parser.parse_water_rights(response_data, type: :transaction)
80
+ def parse_water_rights(response, type:)
81
+ Parsers::WaterRightsParser.parse_water_rights(response, type: type)
82
+ end
83
+
84
+ # Parses climate station data from the API response.
85
+ #
86
+ # @param response [Hash] The API response containing climate station data.
87
+ # @return [Array<ClimateStation>] Array of climate station objects.
88
+ def parse_climate_stations(response)
89
+ Parsers::ClimateParser.parse_climate_stations(response)
90
+ end
91
+
92
+ # Parses climate reading data from the API response.
93
+ #
94
+ # @param response [Hash] The API response containing climate readings.
95
+ # @param type [Symbol] The type of climate reading (:frost_dates, :daily, or :monthly).
96
+ # @return [Array<Reading>] Array of climate reading objects.
97
+ # @raise [ArgumentError] If an invalid reading type is provided.
98
+ def parse_climate_readings(response, type:)
99
+ Parsers::ClimateParser.parse_climate_readings(response, type: type)
100
+ end
101
+
102
+ # Parses administrative calls data from the API response.
103
+ #
104
+ # @param response [Hash] The API response containing administrative calls data.
105
+ # @return [Array<AdminCall>] Array of administrative call objects.
106
+ # @example Parse admin calls from response
107
+ # calls = Parser.parse_admin_calls(response_data)
108
+ def parse_admin_calls(response)
109
+ Parsers::AdminCallsParser.parse_admin_calls(response)
110
+ end
111
+
112
+ # Parses call analysis data from the API response.
113
+ #
114
+ # @param response [Hash] The API response containing call analysis data.
115
+ # @param type [Symbol] The type of analysis (:wdid or :gnis).
116
+ # @return [Array<CallAnalysis>] Array of call analysis objects.
117
+ # @raise [ArgumentError] If an invalid analysis type is provided.
118
+ def parse_call_analyses(response, type:)
119
+ Parsers::AnalysisParser.parse_call_analyses(response, type: type)
120
+ end
121
+
122
+ # Parses source route framework data from the API response.
123
+ #
124
+ # @param response [Hash] The API response containing source route data.
125
+ # @return [Array<SourceRoute>] Array of source route objects.
126
+ def parse_source_routes(response)
127
+ Parsers::AnalysisParser.parse_source_routes(response)
128
+ end
129
+
130
+ # Parses route analysis data from the API response.
131
+ #
132
+ # @param response [Hash] The API response containing route analysis data.
133
+ # @return [Array<RouteAnalysis>] Array of route analysis objects.
134
+ def parse_route_analyses(response)
135
+ Parsers::AnalysisParser.parse_route_analyses(response)
136
+ end
137
+
138
+ # Parses structure data from the API response.
139
+ #
140
+ # @param response [Hash] The API response containing structure data.
141
+ # @return [Array<Cdss::Models::Structure>] Array of structure objects.
142
+ def parse_structures(response)
143
+ Parsers::StructuresParser.parse_structures(response)
144
+ end
145
+
146
+ # Parses diversion record data from the API response.
147
+ #
148
+ # @param response [Hash] The API response containing diversion record data.
149
+ # @param type [Symbol] The type of record (:day, :month, :year, or :stage_volume).
150
+ # @return [Array<Cdss::Models::DiversionRecord>] Array of diversion record objects.
151
+ def parse_diversion_records(response, type:)
152
+ Parsers::StructuresParser.parse_diversion_records(response, type: type)
153
+ end
154
+
155
+ # Parses water class data from the API response.
156
+ #
157
+ # @param response [Hash] The API response containing water class data.
158
+ # @return [Array<Cdss::Models::WaterClass>] Array of water class objects.
159
+ def parse_water_classes(response)
160
+ Parsers::StructuresParser.parse_water_classes(response)
161
+ end
162
+
163
+ # Parses reference table data from the API response.
164
+ #
165
+ # @param response [Hash] The API response containing reference table data.
166
+ # @return [Array<Cdss::Models::ReferenceTable>] Array of reference table objects.
167
+ def parse_reference_table(response)
168
+ Parsers::ReferenceTablesParser.parse_reference_table(response)
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module AdminCallsParser
6
+ extend BaseParser
7
+ class << self
8
+ def parse_admin_calls(response)
9
+ parse_collection(response) { |data| build_call(data) }
10
+ end
11
+
12
+ private
13
+
14
+ def build_call(data)
15
+ Cdss::Models::AdminCall.new(
16
+ call_number: data["callNumber"]&.to_i,
17
+ call_type: data["callType"],
18
+ date_time_set: parse_timestamp(data["dateTimeSet"]),
19
+ date_time_released: parse_timestamp(data["dateTimeReleased"]),
20
+ water_source_name: data["waterSourceName"],
21
+ location_wdid: data["locationWdid"],
22
+ location_wdid_streammile: data["locationWdidStreammile"]&.to_f,
23
+ location_structure_name: data["locationStructureName"],
24
+ priority_wdid: data["priorityWdid"],
25
+ priority_structure_name: data["priorityStructureName"],
26
+ priority_admin_number: data["priorityAdminNumber"]&.to_f,
27
+ priority_order_number: data["priorityOrderNumber"]&.to_i,
28
+ priority_date: parse_timestamp(data["priorityDate"]),
29
+ priority_number: data["priorityNumber"]&.to_i,
30
+ bounding_wdid: data["boundingWdid"],
31
+ bounding_structure_name: data["boundingStructureName"],
32
+ set_comments: data["setComments"],
33
+ release_comment: data["releaseComment"],
34
+ division: data["division"]&.to_i,
35
+ location_structure_latitude: data["locationStructureLatitude"]&.to_f,
36
+ location_structure_longitude: data["locationStructureLongitude"]&.to_f,
37
+ bounding_structure_latitude: data["boundingStructureLatitude"]&.to_f,
38
+ bounding_structure_longitude: data["boundingStructureLongitude"]&.to_f,
39
+ modified: parse_timestamp(data["modified"]),
40
+ more_information: data["moreInformation"],
41
+ metadata: {}
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module AnalysisParser
6
+ class << self
7
+ def parse_call_analyses(response, type:)
8
+ parse_collection(response) do |data|
9
+ params = build_call_analysis_params(data, type)
10
+ Cdss::Models::CallAnalysis.new(**params)
11
+ end
12
+ end
13
+
14
+ def parse_source_routes(response)
15
+ parse_collection(response) do |data|
16
+ params = build_source_route_params(data)
17
+ Cdss::Models::SourceRoute.new(**params)
18
+ end
19
+ end
20
+
21
+ def parse_route_analyses(response)
22
+ parse_collection(response) do |data|
23
+ params = build_route_analysis_params(data)
24
+ Cdss::Models::RouteAnalysis.new(**params)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def parse_collection(response, &block)
31
+ return [] unless response && response["ResultList"]
32
+
33
+ response["ResultList"].map(&block)
34
+ end
35
+
36
+ def parse_timestamp(value)
37
+ return nil if value.nil? || value.to_s.empty?
38
+
39
+ DateTime.parse(value)
40
+ rescue StandardError
41
+ nil
42
+ end
43
+
44
+ def safe_float(value)
45
+ Float(value)
46
+ rescue StandardError
47
+ nil
48
+ end
49
+
50
+ def safe_integer(value)
51
+ Integer(value)
52
+ rescue StandardError
53
+ nil
54
+ end
55
+
56
+ def build_call_analysis_params(data, _type)
57
+ return {} unless data
58
+
59
+ {
60
+ analysis_date: parse_timestamp(data["analysisDate"]),
61
+ wdid: data["analysisWdid"],
62
+ admin_number: safe_float(data["analysisWrAdminNo"]),
63
+ percent_time_out_of_priority: safe_float(data["analysisOutOfPriorityPercentOfDay"]),
64
+ downstream_call_wdid: data["locationWdid"],
65
+ downstream_call_right: data["priorityStructure"],
66
+ downstream_call_stream_mile: safe_float(data["locationWdidStreamMile"]),
67
+ downstream_call_admin_number: safe_float(data["priorityAdminNo"]),
68
+ downstream_call_decreed_amount: nil,
69
+ downstream_call_decreed_unit: nil,
70
+ downstream_call_appropriation_date: parse_timestamp(data["priorityDate"]),
71
+ downstream_call_status: data["callType"],
72
+ modified: parse_timestamp(data["dateTimeSet"]),
73
+ metadata: {
74
+ division: safe_integer(data["division"]),
75
+ date_time_released: parse_timestamp(data["dateTimeReleased"]),
76
+ water_source_name: data["waterSourceName"],
77
+ location_structure: data["locationStructure"],
78
+ priority_order_no: safe_integer(data["priorityOrderNo"]),
79
+ priority_no: data["priorityNo"],
80
+ bounding_wdid: data["boundingWdid"],
81
+ bounding_structure_name: data["boundingStructureName"],
82
+ set_comments: data["setComments"],
83
+ release_comment: data["releaseComment"]
84
+ }
85
+ }.compact
86
+ end
87
+
88
+ def build_source_route_params(data)
89
+ return {} unless data
90
+
91
+ {
92
+ gnis_id: data["gnisId"],
93
+ gnis_name: data["gnisName"],
94
+ division: safe_integer(data["division"]),
95
+ water_district: safe_integer(data["waterDistrict"]),
96
+ stream_length: safe_float(data["streamLength"]),
97
+ tributary_to_level: safe_integer(data["tributaryToLevel"]),
98
+ tributary_to_gnis_id: data["TributaryToGnisId"],
99
+ tributary_gnis_name: data["tribGnisName"],
100
+ tributary_to_stream_mile: safe_float(data["tributaryToStreamMile"]),
101
+ metadata: {}
102
+ }.compact
103
+ end
104
+
105
+ def build_route_analysis_params(data)
106
+ return {} unless data
107
+
108
+ {
109
+ wdid: data["wdid"],
110
+ structure_name: data["structureName"],
111
+ stream_mile: safe_float(data["streamMile"]),
112
+ structure_type: data["structureType"],
113
+ decreed_amount: safe_float(data["decreedAmount"]),
114
+ decreed_unit: data["decreedUnit"],
115
+ appropriation_date: parse_timestamp(data["appropriationDate"]),
116
+ admin_number: safe_float(data["adminNo"]),
117
+ modified: parse_timestamp(data["modified"]),
118
+ metadata: {}
119
+ }.compact
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module BaseParser
6
+ include Utils
7
+ def parse_collection(response, &block)
8
+ return [] unless response["ResultList"]
9
+
10
+ if block_given?
11
+ response["ResultList"].map(&block)
12
+ else
13
+ response["ResultList"].map { |data| build_resource(data) }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module ClimateParser
6
+ extend BaseParser
7
+
8
+ class << self
9
+ def parse_climate_stations(response)
10
+ parse_collection(response) { |data| build_station(data) }
11
+ end
12
+
13
+ def parse_climate_readings(response, type:)
14
+ parse_collection(response) { |data| build_reading(data, type) }
15
+ end
16
+
17
+ private
18
+
19
+ def build_station(data)
20
+ Cdss::Models::ClimateStation.new(
21
+ station_number: data["stationNum"],
22
+ station_name: data["stationName"],
23
+ site_id: data["siteId"],
24
+ division: data["division"]&.to_i,
25
+ water_district: data["waterDistrict"]&.to_i,
26
+ county: data["county"],
27
+ state: data["state"],
28
+ latitude: data["latitude"]&.to_f,
29
+ longitude: data["longitude"]&.to_f,
30
+ utm_x: data["utmX"]&.to_f,
31
+ utm_y: data["utmY"]&.to_f,
32
+ elevation: data["elevation"]&.to_f,
33
+ data_source: data["dataSource"],
34
+ start_date: parse_timestamp(data["startDate"]),
35
+ end_date: parse_timestamp(data["endDate"]),
36
+ modified: parse_timestamp(data["modified"]),
37
+ more_information: data["moreInformation"],
38
+ parameter_types: data["parameterTypes"],
39
+ metadata: {}
40
+ )
41
+ end
42
+
43
+ def build_reading(data, type)
44
+ base_params = {
45
+ station_number: data["stationNum"],
46
+ site_id: data["siteId"],
47
+ parameter: data["measType"],
48
+ data_source: data["dataSource"],
49
+ modified: parse_timestamp(data["modified"]),
50
+ metadata: {}
51
+ }
52
+
53
+ case type
54
+ when :frost_dates
55
+ base_params.merge!(
56
+ cal_year: data["calYear"]&.to_i,
57
+ spring_frost_date: parse_timestamp(data["springFrostDate"]),
58
+ fall_frost_date: parse_timestamp(data["fallFrostDate"]),
59
+ frost_date_28f_spring: parse_timestamp(data["l28s"]),
60
+ frost_date_28f_fall: parse_timestamp(data["f28s"]),
61
+ frost_date_32f_spring: parse_timestamp(data["l32s"]),
62
+ frost_date_32f_fall: parse_timestamp(data["f32f"])
63
+ )
64
+ when :daily
65
+ base_params.merge!(
66
+ meas_date: parse_timestamp(data["measDate"]),
67
+ value: data["value"]&.to_f,
68
+ flag: data["flag"],
69
+ units: data["units"]
70
+ )
71
+ when :monthly
72
+ base_params.merge!(
73
+ cal_year: data["calYear"]&.to_i,
74
+ cal_month: data["calMonth"]&.to_i,
75
+ value: data["value"]&.to_f,
76
+ flag: data["flag"],
77
+ units: data["units"]
78
+ )
79
+ end
80
+
81
+ Cdss::Models::Reading.new(**base_params)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module ReadingParser
6
+ extend BaseParser
7
+
8
+ class << self
9
+ def parse_readings(response, timescale:)
10
+ parse_collection(response) { |data| build_reading(data, timescale) }
11
+ end
12
+
13
+ private
14
+
15
+ def build_reading(data, timescale)
16
+ params = build_base_params(data)
17
+ add_timescale_params(params, data, timescale)
18
+ Cdss::Models::Reading.new(**params)
19
+ end
20
+
21
+ def build_base_params(data)
22
+ {
23
+ station_num: data["stationNum"],
24
+ abbrev: data["abbrev"],
25
+ parameter: data["parameter"],
26
+ usgs_site_id: data["usgsSiteId"],
27
+ meas_type: data["measType"],
28
+ meas_unit: data["measUnit"],
29
+ meas_count: safe_integer(data["measCount"]),
30
+ meas_value: safe_float(data["measValue"]),
31
+ meas_date: parse_timestamp(data["measDate"]),
32
+ meas_date_time: parse_timestamp(data["measDateTime"]),
33
+ data_source: data["dataSource"],
34
+ modified: parse_timestamp(data["modified"]),
35
+ metadata: {}
36
+ }
37
+ end
38
+
39
+ def add_timescale_params(params, data, timescale)
40
+ case timescale
41
+ when :day then add_day_params(params, data)
42
+ when :month then add_month_params(params, data)
43
+ when :year, :water_year then add_year_params(params, data)
44
+ when :raw, :hour then add_raw_params(params, data)
45
+ else
46
+ raise ArgumentError, "Invalid timescale: #{timescale}"
47
+ end
48
+ end
49
+
50
+ def add_day_params(params, data)
51
+ params[:value] = safe_float(data["value"])
52
+ params[:flags] = {
53
+ flagA: data["flagA"],
54
+ flagB: data["flagB"],
55
+ flagC: data["flagC"],
56
+ flagD: data["flagD"]
57
+ }
58
+ end
59
+
60
+ def add_month_params(params, data)
61
+ params.merge!(
62
+ cal_year: safe_integer(data["calYear"]),
63
+ cal_month_num: safe_integer(data["calMonNum"]),
64
+ min_q_cfs: safe_float(data["minQCfs"]),
65
+ max_q_cfs: safe_float(data["maxQCfs"]),
66
+ avg_q_cfs: safe_float(data["avgQCfs"]),
67
+ total_q_af: safe_float(data["totalQAf"])
68
+ )
69
+ end
70
+
71
+ def add_year_params(params, data)
72
+ params.merge!(
73
+ water_year: safe_integer(data["waterYear"]),
74
+ min_q_cfs: safe_float(data["minQCfs"]),
75
+ max_q_cfs: safe_float(data["maxQCfs"]),
76
+ avg_q_cfs: safe_float(data["avgQCfs"]),
77
+ total_q_af: safe_float(data["totalQAf"])
78
+ )
79
+ end
80
+
81
+ def add_raw_params(params, data)
82
+ params[:flags] = {
83
+ flagA: data["flagA"],
84
+ flagB: data["flagB"]
85
+ }
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module ReferenceTablesParser
6
+ extend BaseParser
7
+
8
+ class << self
9
+ def parse_reference_table(response)
10
+ parse_collection(response) { |data| build_reference(data) }
11
+ end
12
+
13
+ private
14
+
15
+ def build_reference(data)
16
+ Models::ReferenceTable.new(
17
+ name: data["name"],
18
+ code: data["code"],
19
+ description: data["description"],
20
+ division: safe_integer(data["division"]),
21
+ water_district: safe_integer(data["waterDistrict"]),
22
+ water_district_name: data["waterDistrictName"],
23
+ division_name: data["divisionName"],
24
+ county: data["county"],
25
+ management_district: data["managementDistrict"],
26
+ management_district_name: data["managementDistrictName"],
27
+ designated_basin: data["designatedBasin"],
28
+ designated_basin_name: data["designatedBasinName"],
29
+ parameter: data["parameter"] || data["measType"],
30
+ flag: data["flag"],
31
+ flag_column: data["flagColumn"],
32
+ divrectype: data["divRecType"],
33
+ div_rec_type_long: data["divRecTypeLong"],
34
+ additional_info: data["additionalInfo"],
35
+ data_source: data["dataSource"],
36
+ publication_name: data["publicationName"],
37
+ action_name: data["actionName"],
38
+ action_descr: data["actionDescr"],
39
+ ciu_code: data["ciuCode"],
40
+ ciu_code_long: data["ciuCodeLong"],
41
+ obs_code: data["obsCode"],
42
+ obs_code_long: data["obsCodeLong"],
43
+ obs_descr: data["obsDescr"],
44
+ start_iyr: safe_integer(data["startIyr"]),
45
+ end_iyr: safe_integer(data["endIyr"]),
46
+ not_used_code: data["notUsedCode"],
47
+ not_used_code_descr: data["notUsedCodeDescr"],
48
+ submission_type: data["submissionType"],
49
+ metadata: {}
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cdss
4
+ module Parsers
5
+ module StationParser
6
+ extend BaseParser
7
+
8
+ class << self
9
+ def parse_stations(response)
10
+ parse_collection(response)
11
+ end
12
+
13
+ private
14
+
15
+ def build_resource(data)
16
+ Cdss::Models::Station.new(
17
+ station_num: data["stationNum"],
18
+ abbrev: data["abbrev"],
19
+ usgs_site_id: data["usgsSiteId"],
20
+ name: data["stationName"],
21
+ agency: data["dataSource"],
22
+ latitude: data["latitude"],
23
+ longitude: data["longitude"],
24
+ division: data["division"],
25
+ water_district: data["waterDistrict"],
26
+ county: data["county"],
27
+ state: data["state"],
28
+ utm_x: data["utmX"],
29
+ utm_y: data["utmY"],
30
+ location_accuracy: data["locationAccuracy"],
31
+ start_date: parse_timestamp(data["startDate"]),
32
+ end_date: parse_timestamp(data["endDate"]),
33
+ modified: parse_timestamp(data["modified"]),
34
+ more_information: data["moreInformation"],
35
+ meas_unit: data["measUnit"],
36
+ metadata: {}
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end