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.
- checksums.yaml +7 -0
- data/.rubocop.yml +86 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/README.md +101 -0
- data/Rakefile +26 -0
- data/docs/Cdss/AdminCalls.html +399 -0
- data/docs/Cdss/Analysis.html +972 -0
- data/docs/Cdss/Client.html +581 -0
- data/docs/Cdss/Climate.html +1257 -0
- data/docs/Cdss/Concerns/LogReadingAttributes.html +406 -0
- data/docs/Cdss/Concerns/WellReadingAttributes.html +414 -0
- data/docs/Cdss/Concerns.html +117 -0
- data/docs/Cdss/GroundWater.html +945 -0
- data/docs/Cdss/Models/AdminCall.html +252 -0
- data/docs/Cdss/Models/Analysis.html +397 -0
- data/docs/Cdss/Models/CallAnalysis.html +140 -0
- data/docs/Cdss/Models/ClimateStation.html +249 -0
- data/docs/Cdss/Models/DiversionRecord.html +248 -0
- data/docs/Cdss/Models/Reading.html +301 -0
- data/docs/Cdss/Models/ReferenceTable.html +339 -0
- data/docs/Cdss/Models/RouteAnalysis.html +140 -0
- data/docs/Cdss/Models/SourceRoute.html +140 -0
- data/docs/Cdss/Models/Station.html +248 -0
- data/docs/Cdss/Models/Structure.html +259 -0
- data/docs/Cdss/Models/WaterClass.html +249 -0
- data/docs/Cdss/Models/WaterRight.html +255 -0
- data/docs/Cdss/Models/Well.html +251 -0
- data/docs/Cdss/Models.html +117 -0
- data/docs/Cdss/Parser.html +2155 -0
- data/docs/Cdss/Parsers/AdminCallsParser.html +201 -0
- data/docs/Cdss/Parsers/AnalysisParser.html +296 -0
- data/docs/Cdss/Parsers/BaseParser.html +207 -0
- data/docs/Cdss/Parsers/ClimateParser.html +253 -0
- data/docs/Cdss/Parsers/ReadingParser.html +201 -0
- data/docs/Cdss/Parsers/ReferenceTablesParser.html +201 -0
- data/docs/Cdss/Parsers/StationParser.html +201 -0
- data/docs/Cdss/Parsers/StructuresParser.html +305 -0
- data/docs/Cdss/Parsers/WaterRightsParser.html +219 -0
- data/docs/Cdss/Parsers/WellParser.html +357 -0
- data/docs/Cdss/Parsers.html +117 -0
- data/docs/Cdss/ReferenceTables.html +332 -0
- data/docs/Cdss/Structures.html +1132 -0
- data/docs/Cdss/SurfaceWater.html +798 -0
- data/docs/Cdss/Telemetry.html +763 -0
- data/docs/Cdss/Utils.html +1276 -0
- data/docs/Cdss/WaterRights.html +634 -0
- data/docs/Cdss.html +292 -0
- data/docs/_index.html +493 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +503 -0
- data/docs/file.README.html +108 -0
- data/docs/file_list.html +59 -0
- data/docs/frames.html +22 -0
- data/docs/index.html +108 -0
- data/docs/js/app.js +344 -0
- data/docs/js/full_list.js +242 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +790 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/cdss/admin_calls.rb +44 -0
- data/lib/cdss/analysis.rb +183 -0
- data/lib/cdss/client.rb +121 -0
- data/lib/cdss/climate.rb +155 -0
- data/lib/cdss/concerns/log_reading_attributes.rb +48 -0
- data/lib/cdss/concerns/well_reading_attributes.rb +56 -0
- data/lib/cdss/ground_water.rb +112 -0
- data/lib/cdss/models/admin_call.rb +45 -0
- data/lib/cdss/models/analysis.rb +77 -0
- data/lib/cdss/models/climate_station.rb +40 -0
- data/lib/cdss/models/reading.rb +54 -0
- data/lib/cdss/models/reference_table.rb +56 -0
- data/lib/cdss/models/station.rb +40 -0
- data/lib/cdss/models/structure.rb +101 -0
- data/lib/cdss/models/water_right.rb +47 -0
- data/lib/cdss/models/well.rb +43 -0
- data/lib/cdss/parser.rb +172 -0
- data/lib/cdss/parsers/admin_calls_parser.rb +47 -0
- data/lib/cdss/parsers/analysis_parser.rb +124 -0
- data/lib/cdss/parsers/base_parser.rb +18 -0
- data/lib/cdss/parsers/climate_parser.rb +86 -0
- data/lib/cdss/parsers/reading_parser.rb +90 -0
- data/lib/cdss/parsers/reference_tables_parser.rb +55 -0
- data/lib/cdss/parsers/station_parser.rb +42 -0
- data/lib/cdss/parsers/structures_parser.rb +96 -0
- data/lib/cdss/parsers/water_rights_parser.rb +77 -0
- data/lib/cdss/parsers/well_parser.rb +107 -0
- data/lib/cdss/reference_tables.rb +147 -0
- data/lib/cdss/structures.rb +235 -0
- data/lib/cdss/surface_water.rb +186 -0
- data/lib/cdss/telemetry.rb +98 -0
- data/lib/cdss/utils.rb +152 -0
- data/lib/cdss/version.rb +5 -0
- data/lib/cdss/water_rights.rb +95 -0
- data/lib/cdss.rb +27 -0
- data/sig/cdss/ruby.rbs +6 -0
- metadata +272 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.37
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
|
+
|
17
|
+
<script type="text/javascript">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div id="content"><h1>Top Level Namespace
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
</h1>
|
67
|
+
<div class="box_info">
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<h2>Defined Under Namespace</h2>
|
82
|
+
<p class="children">
|
83
|
+
|
84
|
+
|
85
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Cdss.html" title="Cdss (module)">Cdss</a></span>
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
</p>
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<div id="footer">
|
103
|
+
Generated on Thu Feb 20 21:19:08 2025 by
|
104
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
|
+
0.9.37 (ruby-3.2.2).
|
106
|
+
</div>
|
107
|
+
|
108
|
+
</div>
|
109
|
+
</body>
|
110
|
+
</html>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cdss
|
4
|
+
# Provides methods for accessing administrative calls data from the CDSS API.
|
5
|
+
#
|
6
|
+
# This module includes functionality for retrieving active and historical administrative
|
7
|
+
# calls based on various criteria such as division, location, and date ranges.
|
8
|
+
module AdminCalls
|
9
|
+
include Utils
|
10
|
+
|
11
|
+
# Fetches administrative calls based on various filtering criteria.
|
12
|
+
#
|
13
|
+
# @param [Integer, nil] division Water division to filter calls.
|
14
|
+
# @param [String, nil] location_wdid WDID of the call location structure.
|
15
|
+
# @param [Integer, nil] call_number Unique call identifier to query.
|
16
|
+
# @param [Date, nil] start_date Start date for calls data.
|
17
|
+
# @param [Date, nil] end_date End date for calls data.
|
18
|
+
# @param [Boolean] active Whether to fetch active (true) or historical (false) calls. Defaults to true.
|
19
|
+
# @return [Array<AdminCall>] Array of matching administrative call objects.
|
20
|
+
# @example Fetch active calls for a division
|
21
|
+
# get_admin_calls(division: 1, active: true)
|
22
|
+
def get_admin_calls(division: nil, location_wdid: nil, call_number: nil, start_date: nil, end_date: nil,
|
23
|
+
active: true)
|
24
|
+
query = build_query(
|
25
|
+
{
|
26
|
+
dateFormat: "spaceSepToSeconds",
|
27
|
+
division: division,
|
28
|
+
callNumber: call_number,
|
29
|
+
"min-dateTimeSet": format_date(start_date),
|
30
|
+
"max-dateTimeSet": format_date(end_date),
|
31
|
+
locationWdid: location_wdid
|
32
|
+
},
|
33
|
+
encode: true
|
34
|
+
)
|
35
|
+
|
36
|
+
endpoint = active ? "administrativecalls/active/" : "administrativecalls/historical/"
|
37
|
+
|
38
|
+
fetch_paginated_data(
|
39
|
+
endpoint: "/#{endpoint}",
|
40
|
+
query: query
|
41
|
+
) { |data| Parser.parse_admin_calls(data) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cdss
|
4
|
+
# Provides methods for accessing analysis services from the CDSS API including
|
5
|
+
# call analysis and water source route frameworks.
|
6
|
+
module Analysis
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
# Performs call analysis by WDID, showing daily priority percentages.
|
10
|
+
#
|
11
|
+
# @param [String] wdid DWR WDID unique structure identifier code.
|
12
|
+
# @param [String, Integer] admin_no Water Right Administration Number.
|
13
|
+
# @param [Date, nil] start_date Start date for analysis data.
|
14
|
+
# @param [Date, nil] end_date End date for analysis data.
|
15
|
+
# @param [Boolean] batch Whether to break date range into yearly batches. Defaults to false.
|
16
|
+
# @return [Array<CallAnalysis>] Array of call analysis records.
|
17
|
+
# @example Analyze calls for a specific WDID
|
18
|
+
# get_call_analysis_wdid(wdid: "0301234", admin_no: "12345.00000")
|
19
|
+
def get_call_analysis_wdid(wdid:, admin_no:, start_date: nil, end_date: nil, batch: false)
|
20
|
+
admin_no = admin_no.to_s
|
21
|
+
|
22
|
+
if batch
|
23
|
+
results = []
|
24
|
+
date_ranges = batch_dates(start_date, end_date)
|
25
|
+
|
26
|
+
date_ranges.each_with_index do |range, _index|
|
27
|
+
results.concat(
|
28
|
+
fetch_call_analysis_wdid(
|
29
|
+
wdid: wdid,
|
30
|
+
admin_no: admin_no,
|
31
|
+
start_date: range[0],
|
32
|
+
end_date: range[1]
|
33
|
+
)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
results
|
38
|
+
else
|
39
|
+
fetch_call_analysis_wdid(
|
40
|
+
wdid: wdid,
|
41
|
+
admin_no: admin_no,
|
42
|
+
start_date: start_date,
|
43
|
+
end_date: end_date
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Performs call analysis by GNIS ID, showing daily priority percentages.
|
49
|
+
#
|
50
|
+
# @param [String] gnis_id GNIS ID to analyze.
|
51
|
+
# @param [String, Integer] admin_no Water Right Administration Number.
|
52
|
+
# @param [Float] stream_mile Stream mile for the analysis point.
|
53
|
+
# @param [Date, nil] start_date Start date for analysis data.
|
54
|
+
# @param [Date, nil] end_date End date for analysis data.
|
55
|
+
# @param [Boolean] batch Whether to break date range into yearly batches. Defaults to false.
|
56
|
+
# @return [Array<CallAnalysis>] Array of call analysis records.
|
57
|
+
def get_call_analysis_gnisid(gnis_id:, admin_no:, stream_mile:, start_date: nil, end_date: nil, batch: false)
|
58
|
+
admin_no = admin_no.to_s
|
59
|
+
|
60
|
+
if batch
|
61
|
+
results = []
|
62
|
+
date_ranges = batch_dates(start_date, end_date)
|
63
|
+
|
64
|
+
date_ranges.each_with_index do |range, _index|
|
65
|
+
results.concat(
|
66
|
+
fetch_call_analysis_gnisid(
|
67
|
+
gnis_id: gnis_id,
|
68
|
+
admin_no: admin_no,
|
69
|
+
stream_mile: stream_mile,
|
70
|
+
start_date: range[0],
|
71
|
+
end_date: range[1]
|
72
|
+
)
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
results
|
77
|
+
else
|
78
|
+
fetch_call_analysis_gnisid(
|
79
|
+
gnis_id: gnis_id,
|
80
|
+
admin_no: admin_no,
|
81
|
+
stream_mile: stream_mile,
|
82
|
+
start_date: start_date,
|
83
|
+
end_date: end_date
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Retrieves the DWR source route framework reference data.
|
89
|
+
#
|
90
|
+
# @param [Integer, nil] division Water division to filter by.
|
91
|
+
# @param [String, nil] gnis_name GNIS Name to filter by.
|
92
|
+
# @param [Integer, nil] water_district Water district to filter by.
|
93
|
+
# @return [Array<SourceRoute>] Array of source route framework records.
|
94
|
+
def get_source_route_framework(division: nil, gnis_name: nil, water_district: nil)
|
95
|
+
query = build_query(
|
96
|
+
{
|
97
|
+
dateFormat: "spaceSepToSeconds",
|
98
|
+
division: division,
|
99
|
+
gnisName: gnis_name,
|
100
|
+
waterDistrict: water_district
|
101
|
+
}
|
102
|
+
)
|
103
|
+
|
104
|
+
fetch_paginated_data(
|
105
|
+
endpoint: "/analysisservices/watersourcerouteframework/",
|
106
|
+
query: query
|
107
|
+
) { |data| Parser.parse_source_routes(data) }
|
108
|
+
end
|
109
|
+
|
110
|
+
# Analyzes water source routes between two points.
|
111
|
+
#
|
112
|
+
# @param [String] lt_gnis_id Lower terminus GNIS ID.
|
113
|
+
# @param [Float] lt_stream_mile Lower terminus stream mile.
|
114
|
+
# @param [String] ut_gnis_id Upper terminus GNIS ID.
|
115
|
+
# @param [Float] ut_stream_mile Upper terminus stream mile.
|
116
|
+
# @return [Array<RouteAnalysis>] Array of route analysis records.
|
117
|
+
def get_source_route_analysis(lt_gnis_id:, lt_stream_mile:, ut_gnis_id:, ut_stream_mile:)
|
118
|
+
query = build_query(
|
119
|
+
{
|
120
|
+
ltGnisId: lt_gnis_id,
|
121
|
+
ltStreamMile: lt_stream_mile,
|
122
|
+
utGnisId: ut_gnis_id,
|
123
|
+
utStreamMile: ut_stream_mile
|
124
|
+
}
|
125
|
+
)
|
126
|
+
|
127
|
+
fetch_paginated_data(
|
128
|
+
endpoint: "/analysisservices/watersourcerouteanalysis/",
|
129
|
+
query: query
|
130
|
+
) { |data| Parser.parse_route_analyses(data) }
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
# Fetches call analysis data for a specific WDID.
|
136
|
+
#
|
137
|
+
# @param [String] wdid WDID to analyze
|
138
|
+
# @param [String] admin_no Water Right Administration Number
|
139
|
+
# @param [Date, nil] start_date Start date for analysis data
|
140
|
+
# @param [Date, nil] end_date End date for analysis data
|
141
|
+
# @return [Array<CallAnalysis>] Array of call analysis records
|
142
|
+
def fetch_call_analysis_wdid(wdid:, admin_no:, start_date:, end_date:)
|
143
|
+
query = build_query(
|
144
|
+
{
|
145
|
+
wdid: wdid,
|
146
|
+
adminNo: admin_no,
|
147
|
+
startDate: format_date(start_date),
|
148
|
+
endDate: format_date(end_date)
|
149
|
+
}
|
150
|
+
)
|
151
|
+
|
152
|
+
fetch_paginated_data(
|
153
|
+
endpoint: "/analysisservices/callanalysisbywdid/",
|
154
|
+
query: query
|
155
|
+
) { |data| Parser.parse_call_analyses(data, type: :wdid) }
|
156
|
+
end
|
157
|
+
|
158
|
+
# Fetches call analysis data for a specific GNIS ID and stream mile.
|
159
|
+
#
|
160
|
+
# @param [String] gnis_id GNIS ID to analyze
|
161
|
+
# @param [String] admin_no Water Right Administration Number
|
162
|
+
# @param [Float] stream_mile Stream mile for the analysis point
|
163
|
+
# @param [Date, nil] start_date Start date for analysis data
|
164
|
+
# @param [Date, nil] end_date End date for analysis data
|
165
|
+
# @return [Array<CallAnalysis>] Array of call analysis records
|
166
|
+
def fetch_call_analysis_gnisid(gnis_id:, admin_no:, stream_mile:, start_date:, end_date:)
|
167
|
+
query = build_query(
|
168
|
+
{
|
169
|
+
gnisId: gnis_id,
|
170
|
+
adminNo: admin_no,
|
171
|
+
streamMile: stream_mile,
|
172
|
+
startDate: format_date(start_date),
|
173
|
+
endDate: format_date(end_date)
|
174
|
+
}
|
175
|
+
)
|
176
|
+
|
177
|
+
fetch_paginated_data(
|
178
|
+
endpoint: "/analysisservices/callanalysisbygnisid/",
|
179
|
+
query: query
|
180
|
+
) { |data| Parser.parse_call_analyses(data, type: :gnis) }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/lib/cdss/client.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cdss
|
4
|
+
# Main client class for interacting with the CDSS API.
|
5
|
+
#
|
6
|
+
# The Client class provides access to all CDSS API endpoints and handles authentication,
|
7
|
+
# request configuration, and response processing.
|
8
|
+
#
|
9
|
+
# @example Create a new client
|
10
|
+
# client = Cdss::Client.new(api_key: "your-api-key")
|
11
|
+
# client.get_climate_stations(county: "Denver")
|
12
|
+
class Client
|
13
|
+
include HTTParty
|
14
|
+
base_uri Cdss.config.base_url
|
15
|
+
|
16
|
+
include AdminCalls
|
17
|
+
include Analysis
|
18
|
+
include Climate
|
19
|
+
include GroundWater
|
20
|
+
include Structures
|
21
|
+
include SurfaceWater
|
22
|
+
include Telemetry
|
23
|
+
include WaterRights
|
24
|
+
include ReferenceTables
|
25
|
+
|
26
|
+
# @return [Hash] Additional options passed to the client
|
27
|
+
attr_reader :options
|
28
|
+
|
29
|
+
# @return [String, nil] API key for authentication
|
30
|
+
attr_reader :api_key
|
31
|
+
|
32
|
+
# Initialize a new CDSS API client.
|
33
|
+
#
|
34
|
+
# @param [String, nil] api_key API key for authentication
|
35
|
+
# @param [Hash] options Additional options for configuring the client
|
36
|
+
# @return [Client] New client instance
|
37
|
+
def initialize(api_key: nil, **options)
|
38
|
+
@options = options
|
39
|
+
@api_key = api_key
|
40
|
+
setup_client
|
41
|
+
end
|
42
|
+
|
43
|
+
# Update the client's API key.
|
44
|
+
#
|
45
|
+
# @param [String] key New API key
|
46
|
+
# @return [String] The new API key
|
47
|
+
def api_key=(key)
|
48
|
+
@api_key = key
|
49
|
+
setup_client
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Configures the HTTP client with timeout and authorization headers.
|
55
|
+
# Sets the User-Agent and API token if provided.
|
56
|
+
#
|
57
|
+
# @return [void]
|
58
|
+
def setup_client
|
59
|
+
self.class.default_timeout(Cdss.config.timeout)
|
60
|
+
self.class.headers({
|
61
|
+
"User-Agent" => Cdss.config.user_agent,
|
62
|
+
"Token" => api_key
|
63
|
+
}.compact)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Processes API responses and handles error conditions.
|
67
|
+
#
|
68
|
+
# @param [HTTParty::Response] response The raw API response
|
69
|
+
# @return [Hash] Parsed JSON response body
|
70
|
+
# @raise [RuntimeError] When the API request fails
|
71
|
+
def handle_response(response)
|
72
|
+
return JSON.parse(response.body) if response.success?
|
73
|
+
|
74
|
+
raise "API request failed with status #{response.code}: #{response.message}"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Makes GET requests with debug logging support.
|
78
|
+
#
|
79
|
+
# @param [Array] args The request arguments including path and options
|
80
|
+
# @return [HTTParty::Response] The API response
|
81
|
+
def self.get(*args)
|
82
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
83
|
+
debug_request(args.first, options)
|
84
|
+
super(*args, options)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Makes authenticated GET requests to the API.
|
88
|
+
#
|
89
|
+
# @param [String] path The API endpoint path
|
90
|
+
# @param [Hash] options Request options including query parameters
|
91
|
+
# @return [HTTParty::Response] The API response
|
92
|
+
def get(path, options = {})
|
93
|
+
options[:query] ||= {}
|
94
|
+
options[:query][:apiKey] = api_key if api_key
|
95
|
+
self.class.get(path, options)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Logs detailed request information when debug mode is enabled.
|
99
|
+
#
|
100
|
+
# @param [String] endpoint The API endpoint being called
|
101
|
+
# @param [Hash] options Request options including query parameters and headers
|
102
|
+
# @return [void]
|
103
|
+
def self.debug_request(endpoint, options)
|
104
|
+
return unless Cdss.config.debug
|
105
|
+
|
106
|
+
query_string = options[:query]&.map { |k, v| "#{k}=#{v}" }&.join("&")
|
107
|
+
full_url = [base_uri, endpoint].join
|
108
|
+
full_url += "?#{query_string}" if query_string
|
109
|
+
|
110
|
+
puts "\n=== CDSS API Request ==="
|
111
|
+
puts "URL: #{full_url}"
|
112
|
+
puts "\nHeaders:"
|
113
|
+
headers = default_options[:headers] || {}
|
114
|
+
headers.merge!(options[:headers] || {})
|
115
|
+
headers.each do |key, value|
|
116
|
+
puts " #{key}: #{value}"
|
117
|
+
end
|
118
|
+
puts "=====================\n"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/cdss/climate.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cdss
|
4
|
+
# Provides methods for accessing climate data from the CDSS API.
|
5
|
+
#
|
6
|
+
# This module includes functionality for retrieving climate stations,
|
7
|
+
# frost dates, and time series data at various time scales.
|
8
|
+
module Climate
|
9
|
+
include Utils
|
10
|
+
|
11
|
+
# Fetches climate stations based on various filtering criteria.
|
12
|
+
#
|
13
|
+
# @param [Hash, Array, nil] aoi Area of interest for spatial searches. If hash, must contain :latitude and :longitude keys.
|
14
|
+
# If array, must contain [longitude, latitude].
|
15
|
+
# @param [Integer, nil] radius Radius in miles for spatial search around aoi. Defaults to 20 if aoi is provided.
|
16
|
+
# @param [String, nil] county County name to filter stations.
|
17
|
+
# @param [Integer, nil] division Water division number to filter stations.
|
18
|
+
# @param [String, nil] station_name Name of the station to filter by.
|
19
|
+
# @param [String, nil] site_id Station site ID to filter by.
|
20
|
+
# @param [Integer, nil] water_district Water district number to filter stations.
|
21
|
+
# @return [Array<Station>] Array of matching climate station objects.
|
22
|
+
# @raise [ArgumentError] If aoi parameter is provided but invalid.
|
23
|
+
# @example Fetch stations in Denver county
|
24
|
+
# get_climate_stations(county: 'Denver')
|
25
|
+
def get_climate_stations(aoi: nil, radius: nil, county: nil, division: nil, station_name: nil, site_id: nil,
|
26
|
+
water_district: nil)
|
27
|
+
query_params = {
|
28
|
+
dateFormat: "spaceSepToSeconds",
|
29
|
+
units: "miles",
|
30
|
+
county: county,
|
31
|
+
division: division,
|
32
|
+
stationName: station_name,
|
33
|
+
siteId: site_id,
|
34
|
+
waterDistrict: water_district
|
35
|
+
}
|
36
|
+
|
37
|
+
if aoi
|
38
|
+
if aoi.is_a?(Hash) && aoi[:latitude] && aoi[:longitude]
|
39
|
+
query_params.merge!(longitude: aoi[:longitude], latitude: aoi[:latitude])
|
40
|
+
elsif aoi.is_a?(Array) && aoi.count == 2
|
41
|
+
query_params.merge!(longitude: aoi[0], latitude: aoi[1])
|
42
|
+
else
|
43
|
+
raise ArgumentError, "Invalid 'aoi' parameter"
|
44
|
+
end
|
45
|
+
query_params[:radius] = radius || 20
|
46
|
+
end
|
47
|
+
|
48
|
+
fetch_paginated_data(
|
49
|
+
endpoint: "/climatedata/climatestations/",
|
50
|
+
query: query_params
|
51
|
+
) { |data| Parser.parse_climate_stations(data) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Fetches frost dates for a specific climate station.
|
55
|
+
#
|
56
|
+
# @param [String] station_number Station number to fetch frost dates for.
|
57
|
+
# @param [Date, nil] start_date Start date for frost dates data.
|
58
|
+
# @param [Date, nil] end_date End date for frost dates data.
|
59
|
+
# @return [Array<Reading>] Array of frost date readings.
|
60
|
+
def get_climate_frost_dates(station_number:, start_date: nil, end_date: nil)
|
61
|
+
query_params = {
|
62
|
+
dateFormat: "spaceSepToSeconds",
|
63
|
+
stationNum: station_number
|
64
|
+
}
|
65
|
+
|
66
|
+
query_params[:"min-calYear"] = start_date.strftime("%Y") if start_date
|
67
|
+
query_params[:"max-calYear"] = end_date.strftime("%Y") if end_date
|
68
|
+
|
69
|
+
fetch_paginated_data(
|
70
|
+
endpoint: "/climatedata/climatestationfrostdates/",
|
71
|
+
query: query_params
|
72
|
+
) { |data| Parser.parse_climate_readings(data, type: :frost_dates) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Fetches daily climate time series data.
|
76
|
+
#
|
77
|
+
# @param [String] param Climate parameter type to retrieve
|
78
|
+
# @param [String, nil] station_number Station number
|
79
|
+
# @param [String, nil] site_id Site ID
|
80
|
+
# @param [Date, nil] start_date Start date for time series data
|
81
|
+
# @param [Date, nil] end_date End date for time series data
|
82
|
+
# @return [Array<Reading>] Array of daily climate readings
|
83
|
+
def get_climate_ts_day(param:, station_number: nil, site_id: nil, start_date: nil, end_date: nil)
|
84
|
+
query_params = {
|
85
|
+
dateFormat: "spaceSepToSeconds",
|
86
|
+
measType: param,
|
87
|
+
stationNum: station_number,
|
88
|
+
siteId: site_id
|
89
|
+
}
|
90
|
+
|
91
|
+
query_params[:"min-measDate"] = start_date.strftime("%m-%d-%Y") if start_date
|
92
|
+
query_params[:"max-measDate"] = end_date.strftime("%m-%d-%Y") if end_date
|
93
|
+
|
94
|
+
fetch_paginated_data(
|
95
|
+
endpoint: "/climatedata/climatestationtsday/",
|
96
|
+
query: query_params
|
97
|
+
) { |data| Parser.parse_climate_readings(data, type: :daily) }
|
98
|
+
end
|
99
|
+
|
100
|
+
# Fetches monthly climate time series data.
|
101
|
+
#
|
102
|
+
# @param [String] param Climate parameter type to retrieve
|
103
|
+
# @param [String, nil] station_number Station number
|
104
|
+
# @param [String, nil] site_id Site ID
|
105
|
+
# @param [Date, nil] start_date Start date for time series data
|
106
|
+
# @param [Date, nil] end_date End date for time series data
|
107
|
+
# @return [Array<Reading>] Array of monthly climate readings
|
108
|
+
def get_climate_ts_month(param:, station_number: nil, site_id: nil, start_date: nil, end_date: nil)
|
109
|
+
query_params = {
|
110
|
+
dateFormat: "spaceSepToSeconds",
|
111
|
+
measType: param,
|
112
|
+
stationNum: station_number,
|
113
|
+
siteId: site_id
|
114
|
+
}
|
115
|
+
|
116
|
+
query_params[:"min-calYear"] = start_date.strftime("%Y") if start_date
|
117
|
+
query_params[:"max-calYear"] = end_date.strftime("%Y") if end_date
|
118
|
+
|
119
|
+
fetch_paginated_data(
|
120
|
+
endpoint: "/climatedata/climatestationtsmonth/",
|
121
|
+
query: query_params
|
122
|
+
) { |data| Parser.parse_climate_readings(data, type: :monthly) }
|
123
|
+
end
|
124
|
+
|
125
|
+
# Fetches climate time series data for specified stations.
|
126
|
+
#
|
127
|
+
# @param [String, nil] station_number Station number
|
128
|
+
# @param [String, nil] site_id Site ID
|
129
|
+
# @param [String] param Climate parameter to retrieve (Evap, FrostDate, MaxTemp, etc.)
|
130
|
+
# @param [Date, nil] start_date Start date for time series data
|
131
|
+
# @param [Date, nil] end_date End date for time series data
|
132
|
+
# @param [String] timescale Time interval for data aggregation ('day' or 'month'). Defaults to 'day'
|
133
|
+
# @return [Array<Reading>] Array of time series reading objects
|
134
|
+
# @raise [ArgumentError] If an invalid parameter or timescale is provided
|
135
|
+
def get_climate_ts(station_number: nil, site_id: nil, param: nil, start_date: nil, end_date: nil, timescale: "day")
|
136
|
+
valid_params = %w[Evap FrostDate MaxTemp MeanTemp MinTemp Precip Snow SnowDepth SnowSWE Solar VP Wind]
|
137
|
+
raise ArgumentError, "Invalid parameter: '#{param}'. Valid values are: #{valid_params.join(', ')}" unless valid_params.include?(param)
|
138
|
+
|
139
|
+
day_formats = %w[day days daily d]
|
140
|
+
month_formats = %w[month months monthly mon m]
|
141
|
+
timescale = timescale.to_s.downcase
|
142
|
+
|
143
|
+
case timescale
|
144
|
+
when *day_formats
|
145
|
+
get_climate_ts_day(station_number: station_number, site_id: site_id, param: param,
|
146
|
+
start_date: start_date, end_date: end_date)
|
147
|
+
when *month_formats
|
148
|
+
get_climate_ts_month(station_number: station_number, site_id: site_id, param: param,
|
149
|
+
start_date: start_date, end_date: end_date)
|
150
|
+
else
|
151
|
+
raise ArgumentError, "Invalid timescale: '#{timescale}'. Use 'day' or 'month'."
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cdss
|
4
|
+
module Concerns
|
5
|
+
# A concern module that adds log reading-related attributes to classes.
|
6
|
+
#
|
7
|
+
# This module provides a set of standardized attributes for log reading data,
|
8
|
+
# including aquifer information, depth measurements, elevation, and comments.
|
9
|
+
# When included in a class, it dynamically adds accessor methods for these attributes.
|
10
|
+
#
|
11
|
+
# @example Adding log reading attributes to a class
|
12
|
+
# class WellLog
|
13
|
+
# include Cdss::Concerns::LogReadingAttributes
|
14
|
+
# end
|
15
|
+
module LogReadingAttributes
|
16
|
+
# Predefined list of log reading attributes
|
17
|
+
#
|
18
|
+
# @return [Array<Symbol>] List of attributes related to log readings
|
19
|
+
LOG_ATTRIBUTES = %i[
|
20
|
+
aquifer
|
21
|
+
g_log_top_depth
|
22
|
+
g_log_base_depth
|
23
|
+
g_log_top_elev
|
24
|
+
g_log_base_elev
|
25
|
+
g_log_thickness
|
26
|
+
comment
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
# Dynamically adds accessor methods when the module is included in a class
|
30
|
+
#
|
31
|
+
# @param [Class] base The class including this module
|
32
|
+
def self.included(base)
|
33
|
+
base.class_eval do
|
34
|
+
attr_accessor(*LOG_ATTRIBUTES)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Checks if the instance has log reading data
|
39
|
+
#
|
40
|
+
# @return [Boolean] true if aquifer or log thickness is present, false otherwise
|
41
|
+
# @example Check if a well log has reading data
|
42
|
+
# well_log.log_reading? # => true or false
|
43
|
+
def log_reading?
|
44
|
+
!aquifer.nil? || !g_log_thickness.nil?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|