launchdarkly_api 9.0.0 → 9.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -9
- data/docs/AccountMembersApi.md +6 -6
- data/docs/EnvironmentsApi.md +1 -1
- data/docs/Experiment.md +36 -0
- data/docs/ExperimentCollectionRep.md +1 -1
- data/docs/ExperimentExpandableProperties.md +20 -0
- data/docs/ExperimentInfoRep.md +1 -1
- data/docs/ExperimentsBetaApi.md +12 -12
- data/docs/FeatureFlagsApi.md +1 -1
- data/docs/FeatureFlagsBetaApi.md +2 -2
- data/docs/IterationExpandableProperties.md +1 -1
- data/docs/IterationRep.md +4 -2
- data/docs/{ExperimentRep.md → LegacyExperimentRep.md} +2 -2
- data/docs/MetricRep.md +43 -3
- data/docs/MetricV2Rep.md +22 -0
- data/docs/OtherApi.md +1 -1
- data/docs/StatisticsRep.md +20 -0
- data/docs/TeamsBetaApi.md +9 -9
- data/docs/TreatmentRep.md +1 -1
- data/docs/UserRecord.md +1 -1
- data/docs/Users.md +1 -1
- data/docs/UsersApi.md +4 -4
- data/docs/UsersRep.md +22 -0
- data/lib/launchdarkly_api/api/account_members_api.rb +6 -6
- data/lib/launchdarkly_api/api/environments_api.rb +2 -2
- data/lib/launchdarkly_api/api/experiments_beta_api.rb +9 -9
- data/lib/launchdarkly_api/api/feature_flags_api.rb +2 -2
- data/lib/launchdarkly_api/api/feature_flags_beta_api.rb +4 -4
- data/lib/launchdarkly_api/api/other_api.rb +2 -2
- data/lib/launchdarkly_api/api/teams_beta_api.rb +12 -12
- data/lib/launchdarkly_api/api/users_api.rb +3 -3
- data/lib/launchdarkly_api/models/experiment.rb +328 -0
- data/lib/launchdarkly_api/models/experiment_collection_rep.rb +1 -1
- data/lib/launchdarkly_api/models/{decimal.rb → experiment_expandable_properties.rb} +18 -17
- data/lib/launchdarkly_api/models/experiment_info_rep.rb +1 -1
- data/lib/launchdarkly_api/models/iteration_expandable_properties.rb +1 -1
- data/lib/launchdarkly_api/models/iteration_rep.rb +12 -3
- data/lib/launchdarkly_api/models/{experiment_rep.rb → legacy_experiment_rep.rb} +3 -3
- data/lib/launchdarkly_api/models/metric_rep.rb +256 -4
- data/lib/launchdarkly_api/models/metric_v2_rep.rb +253 -0
- data/lib/launchdarkly_api/models/{null_decimal.rb → statistics_rep.rb} +20 -16
- data/lib/launchdarkly_api/models/treatment_rep.rb +1 -1
- data/lib/launchdarkly_api/models/users_rep.rb +250 -0
- data/lib/launchdarkly_api/version.rb +1 -1
- data/lib/launchdarkly_api.rb +6 -3
- data/spec/api/account_members_api_spec.rb +3 -3
- data/spec/api/environments_api_spec.rb +1 -1
- data/spec/api/experiments_beta_api_spec.rb +3 -3
- data/spec/api/feature_flags_api_spec.rb +1 -1
- data/spec/api/feature_flags_beta_api_spec.rb +2 -2
- data/spec/api/other_api_spec.rb +1 -1
- data/spec/api/teams_beta_api_spec.rb +6 -6
- data/spec/api/users_api_spec.rb +1 -1
- data/spec/models/{decimal_spec.rb → experiment_expandable_properties_spec.rb} +8 -8
- data/spec/models/experiment_spec.rb +88 -0
- data/spec/models/iteration_rep_spec.rb +6 -0
- data/spec/models/{experiment_rep_spec.rb → legacy_experiment_rep_spec.rb} +6 -6
- data/spec/models/metric_rep_spec.rb +128 -0
- data/spec/models/metric_v2_rep_spec.rb +46 -0
- data/spec/models/{null_decimal_spec.rb → statistics_rep_spec.rb} +8 -8
- data/spec/models/users_rep_spec.rb +46 -0
- metadata +26 -14
- data/docs/Decimal.md +0 -20
- data/docs/NullDecimal.md +0 -20
@@ -27,6 +27,8 @@ module LaunchDarklyApi
|
|
27
27
|
|
28
28
|
attr_accessor :winning_treatment_id
|
29
29
|
|
30
|
+
attr_accessor :winning_reason
|
31
|
+
|
30
32
|
attr_accessor :can_reshuffle_traffic
|
31
33
|
|
32
34
|
attr_accessor :flags
|
@@ -46,6 +48,7 @@ module LaunchDarklyApi
|
|
46
48
|
:'started_at' => :'startedAt',
|
47
49
|
:'ended_at' => :'endedAt',
|
48
50
|
:'winning_treatment_id' => :'winningTreatmentId',
|
51
|
+
:'winning_reason' => :'winningReason',
|
49
52
|
:'can_reshuffle_traffic' => :'canReshuffleTraffic',
|
50
53
|
:'flags' => :'flags',
|
51
54
|
:'primary_metric' => :'primaryMetric',
|
@@ -68,11 +71,12 @@ module LaunchDarklyApi
|
|
68
71
|
:'started_at' => :'Integer',
|
69
72
|
:'ended_at' => :'Integer',
|
70
73
|
:'winning_treatment_id' => :'String',
|
74
|
+
:'winning_reason' => :'String',
|
71
75
|
:'can_reshuffle_traffic' => :'Boolean',
|
72
76
|
:'flags' => :'Hash<String, FlagRep>',
|
73
|
-
:'primary_metric' => :'
|
77
|
+
:'primary_metric' => :'MetricV2Rep',
|
74
78
|
:'treatments' => :'Array<TreatmentRep>',
|
75
|
-
:'secondary_metrics' => :'Array<
|
79
|
+
:'secondary_metrics' => :'Array<MetricV2Rep>'
|
76
80
|
}
|
77
81
|
end
|
78
82
|
|
@@ -121,6 +125,10 @@ module LaunchDarklyApi
|
|
121
125
|
self.winning_treatment_id = attributes[:'winning_treatment_id']
|
122
126
|
end
|
123
127
|
|
128
|
+
if attributes.key?(:'winning_reason')
|
129
|
+
self.winning_reason = attributes[:'winning_reason']
|
130
|
+
end
|
131
|
+
|
124
132
|
if attributes.key?(:'can_reshuffle_traffic')
|
125
133
|
self.can_reshuffle_traffic = attributes[:'can_reshuffle_traffic']
|
126
134
|
end
|
@@ -182,6 +190,7 @@ module LaunchDarklyApi
|
|
182
190
|
started_at == o.started_at &&
|
183
191
|
ended_at == o.ended_at &&
|
184
192
|
winning_treatment_id == o.winning_treatment_id &&
|
193
|
+
winning_reason == o.winning_reason &&
|
185
194
|
can_reshuffle_traffic == o.can_reshuffle_traffic &&
|
186
195
|
flags == o.flags &&
|
187
196
|
primary_metric == o.primary_metric &&
|
@@ -198,7 +207,7 @@ module LaunchDarklyApi
|
|
198
207
|
# Calculates hash code according to all attributes.
|
199
208
|
# @return [Integer] Hash code
|
200
209
|
def hash
|
201
|
-
[_id, hypothesis, status, started_at, ended_at, winning_treatment_id, can_reshuffle_traffic, flags, primary_metric, treatments, secondary_metrics].hash
|
210
|
+
[_id, hypothesis, status, started_at, ended_at, winning_treatment_id, winning_reason, can_reshuffle_traffic, flags, primary_metric, treatments, secondary_metrics].hash
|
202
211
|
end
|
203
212
|
|
204
213
|
# Builds the object from hash
|
@@ -14,7 +14,7 @@ require 'date'
|
|
14
14
|
require 'time'
|
15
15
|
|
16
16
|
module LaunchDarklyApi
|
17
|
-
class
|
17
|
+
class LegacyExperimentRep
|
18
18
|
attr_accessor :metric_key
|
19
19
|
|
20
20
|
attr_accessor :_metric
|
@@ -58,13 +58,13 @@ module LaunchDarklyApi
|
|
58
58
|
# @param [Hash] attributes Model attributes in the form of hash
|
59
59
|
def initialize(attributes = {})
|
60
60
|
if (!attributes.is_a?(Hash))
|
61
|
-
fail ArgumentError, "The input argument (attributes) must be a hash in `LaunchDarklyApi::
|
61
|
+
fail ArgumentError, "The input argument (attributes) must be a hash in `LaunchDarklyApi::LegacyExperimentRep` initialize method"
|
62
62
|
end
|
63
63
|
|
64
64
|
# check to see if the attribute exists and convert string to symbol for hash key
|
65
65
|
attributes = attributes.each_with_object({}) { |(k, v), h|
|
66
66
|
if (!self.class.attribute_map.key?(k.to_sym))
|
67
|
-
fail ArgumentError, "`#{k}` is not a valid attribute in `LaunchDarklyApi::
|
67
|
+
fail ArgumentError, "`#{k}` is not a valid attribute in `LaunchDarklyApi::LegacyExperimentRep`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
|
68
68
|
end
|
69
69
|
h[k.to_sym] = v
|
70
70
|
}
|
@@ -15,18 +15,100 @@ require 'time'
|
|
15
15
|
|
16
16
|
module LaunchDarklyApi
|
17
17
|
class MetricRep
|
18
|
+
attr_accessor :_id
|
19
|
+
|
18
20
|
attr_accessor :key
|
19
21
|
|
20
22
|
attr_accessor :name
|
21
23
|
|
24
|
+
attr_accessor :kind
|
25
|
+
|
26
|
+
attr_accessor :_attached_flag_count
|
27
|
+
|
22
28
|
attr_accessor :_links
|
23
29
|
|
30
|
+
attr_accessor :_site
|
31
|
+
|
32
|
+
attr_accessor :_access
|
33
|
+
|
34
|
+
attr_accessor :tags
|
35
|
+
|
36
|
+
attr_accessor :_creation_date
|
37
|
+
|
38
|
+
attr_accessor :last_modified
|
39
|
+
|
40
|
+
attr_accessor :maintainer_id
|
41
|
+
|
42
|
+
attr_accessor :_maintainer
|
43
|
+
|
44
|
+
attr_accessor :description
|
45
|
+
|
46
|
+
attr_accessor :is_numeric
|
47
|
+
|
48
|
+
attr_accessor :success_criteria
|
49
|
+
|
50
|
+
attr_accessor :unit
|
51
|
+
|
52
|
+
attr_accessor :event_key
|
53
|
+
|
54
|
+
attr_accessor :is_active
|
55
|
+
|
56
|
+
attr_accessor :_attached_features
|
57
|
+
|
58
|
+
attr_accessor :_version
|
59
|
+
|
60
|
+
attr_accessor :selector
|
61
|
+
|
62
|
+
attr_accessor :urls
|
63
|
+
|
64
|
+
class EnumAttributeValidator
|
65
|
+
attr_reader :datatype
|
66
|
+
attr_reader :allowable_values
|
67
|
+
|
68
|
+
def initialize(datatype, allowable_values)
|
69
|
+
@allowable_values = allowable_values.map do |value|
|
70
|
+
case datatype.to_s
|
71
|
+
when /Integer/i
|
72
|
+
value.to_i
|
73
|
+
when /Float/i
|
74
|
+
value.to_f
|
75
|
+
else
|
76
|
+
value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def valid?(value)
|
82
|
+
!value || allowable_values.include?(value)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
24
86
|
# Attribute mapping from ruby-style variable name to JSON key.
|
25
87
|
def self.attribute_map
|
26
88
|
{
|
89
|
+
:'_id' => :'_id',
|
27
90
|
:'key' => :'key',
|
28
91
|
:'name' => :'name',
|
29
|
-
:'
|
92
|
+
:'kind' => :'kind',
|
93
|
+
:'_attached_flag_count' => :'_attachedFlagCount',
|
94
|
+
:'_links' => :'_links',
|
95
|
+
:'_site' => :'_site',
|
96
|
+
:'_access' => :'_access',
|
97
|
+
:'tags' => :'tags',
|
98
|
+
:'_creation_date' => :'_creationDate',
|
99
|
+
:'last_modified' => :'lastModified',
|
100
|
+
:'maintainer_id' => :'maintainerId',
|
101
|
+
:'_maintainer' => :'_maintainer',
|
102
|
+
:'description' => :'description',
|
103
|
+
:'is_numeric' => :'isNumeric',
|
104
|
+
:'success_criteria' => :'successCriteria',
|
105
|
+
:'unit' => :'unit',
|
106
|
+
:'event_key' => :'eventKey',
|
107
|
+
:'is_active' => :'isActive',
|
108
|
+
:'_attached_features' => :'_attachedFeatures',
|
109
|
+
:'_version' => :'_version',
|
110
|
+
:'selector' => :'selector',
|
111
|
+
:'urls' => :'urls'
|
30
112
|
}
|
31
113
|
end
|
32
114
|
|
@@ -38,9 +120,29 @@ module LaunchDarklyApi
|
|
38
120
|
# Attribute type mapping.
|
39
121
|
def self.openapi_types
|
40
122
|
{
|
123
|
+
:'_id' => :'String',
|
41
124
|
:'key' => :'String',
|
42
125
|
:'name' => :'String',
|
43
|
-
:'
|
126
|
+
:'kind' => :'String',
|
127
|
+
:'_attached_flag_count' => :'Integer',
|
128
|
+
:'_links' => :'Hash<String, Link>',
|
129
|
+
:'_site' => :'Link',
|
130
|
+
:'_access' => :'Access',
|
131
|
+
:'tags' => :'Array<String>',
|
132
|
+
:'_creation_date' => :'Integer',
|
133
|
+
:'last_modified' => :'Modification',
|
134
|
+
:'maintainer_id' => :'String',
|
135
|
+
:'_maintainer' => :'MemberSummary',
|
136
|
+
:'description' => :'String',
|
137
|
+
:'is_numeric' => :'Boolean',
|
138
|
+
:'success_criteria' => :'String',
|
139
|
+
:'unit' => :'String',
|
140
|
+
:'event_key' => :'String',
|
141
|
+
:'is_active' => :'Boolean',
|
142
|
+
:'_attached_features' => :'Array<FlagListingRep>',
|
143
|
+
:'_version' => :'Integer',
|
144
|
+
:'selector' => :'String',
|
145
|
+
:'urls' => :'Array<Object>'
|
44
146
|
}
|
45
147
|
end
|
46
148
|
|
@@ -65,6 +167,10 @@ module LaunchDarklyApi
|
|
65
167
|
h[k.to_sym] = v
|
66
168
|
}
|
67
169
|
|
170
|
+
if attributes.key?(:'_id')
|
171
|
+
self._id = attributes[:'_id']
|
172
|
+
end
|
173
|
+
|
68
174
|
if attributes.key?(:'key')
|
69
175
|
self.key = attributes[:'key']
|
70
176
|
end
|
@@ -73,17 +179,103 @@ module LaunchDarklyApi
|
|
73
179
|
self.name = attributes[:'name']
|
74
180
|
end
|
75
181
|
|
182
|
+
if attributes.key?(:'kind')
|
183
|
+
self.kind = attributes[:'kind']
|
184
|
+
end
|
185
|
+
|
186
|
+
if attributes.key?(:'_attached_flag_count')
|
187
|
+
self._attached_flag_count = attributes[:'_attached_flag_count']
|
188
|
+
end
|
189
|
+
|
76
190
|
if attributes.key?(:'_links')
|
77
191
|
if (value = attributes[:'_links']).is_a?(Hash)
|
78
192
|
self._links = value
|
79
193
|
end
|
80
194
|
end
|
195
|
+
|
196
|
+
if attributes.key?(:'_site')
|
197
|
+
self._site = attributes[:'_site']
|
198
|
+
end
|
199
|
+
|
200
|
+
if attributes.key?(:'_access')
|
201
|
+
self._access = attributes[:'_access']
|
202
|
+
end
|
203
|
+
|
204
|
+
if attributes.key?(:'tags')
|
205
|
+
if (value = attributes[:'tags']).is_a?(Array)
|
206
|
+
self.tags = value
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
if attributes.key?(:'_creation_date')
|
211
|
+
self._creation_date = attributes[:'_creation_date']
|
212
|
+
end
|
213
|
+
|
214
|
+
if attributes.key?(:'last_modified')
|
215
|
+
self.last_modified = attributes[:'last_modified']
|
216
|
+
end
|
217
|
+
|
218
|
+
if attributes.key?(:'maintainer_id')
|
219
|
+
self.maintainer_id = attributes[:'maintainer_id']
|
220
|
+
end
|
221
|
+
|
222
|
+
if attributes.key?(:'_maintainer')
|
223
|
+
self._maintainer = attributes[:'_maintainer']
|
224
|
+
end
|
225
|
+
|
226
|
+
if attributes.key?(:'description')
|
227
|
+
self.description = attributes[:'description']
|
228
|
+
end
|
229
|
+
|
230
|
+
if attributes.key?(:'is_numeric')
|
231
|
+
self.is_numeric = attributes[:'is_numeric']
|
232
|
+
end
|
233
|
+
|
234
|
+
if attributes.key?(:'success_criteria')
|
235
|
+
self.success_criteria = attributes[:'success_criteria']
|
236
|
+
end
|
237
|
+
|
238
|
+
if attributes.key?(:'unit')
|
239
|
+
self.unit = attributes[:'unit']
|
240
|
+
end
|
241
|
+
|
242
|
+
if attributes.key?(:'event_key')
|
243
|
+
self.event_key = attributes[:'event_key']
|
244
|
+
end
|
245
|
+
|
246
|
+
if attributes.key?(:'is_active')
|
247
|
+
self.is_active = attributes[:'is_active']
|
248
|
+
end
|
249
|
+
|
250
|
+
if attributes.key?(:'_attached_features')
|
251
|
+
if (value = attributes[:'_attached_features']).is_a?(Array)
|
252
|
+
self._attached_features = value
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
if attributes.key?(:'_version')
|
257
|
+
self._version = attributes[:'_version']
|
258
|
+
end
|
259
|
+
|
260
|
+
if attributes.key?(:'selector')
|
261
|
+
self.selector = attributes[:'selector']
|
262
|
+
end
|
263
|
+
|
264
|
+
if attributes.key?(:'urls')
|
265
|
+
if (value = attributes[:'urls']).is_a?(Array)
|
266
|
+
self.urls = value
|
267
|
+
end
|
268
|
+
end
|
81
269
|
end
|
82
270
|
|
83
271
|
# Show invalid properties with the reasons. Usually used together with valid?
|
84
272
|
# @return Array for valid properties with the reasons
|
85
273
|
def list_invalid_properties
|
86
274
|
invalid_properties = Array.new
|
275
|
+
if @_id.nil?
|
276
|
+
invalid_properties.push('invalid value for "_id", _id cannot be nil.')
|
277
|
+
end
|
278
|
+
|
87
279
|
if @key.nil?
|
88
280
|
invalid_properties.push('invalid value for "key", key cannot be nil.')
|
89
281
|
end
|
@@ -92,30 +284,90 @@ module LaunchDarklyApi
|
|
92
284
|
invalid_properties.push('invalid value for "name", name cannot be nil.')
|
93
285
|
end
|
94
286
|
|
287
|
+
if @kind.nil?
|
288
|
+
invalid_properties.push('invalid value for "kind", kind cannot be nil.')
|
289
|
+
end
|
290
|
+
|
95
291
|
if @_links.nil?
|
96
292
|
invalid_properties.push('invalid value for "_links", _links cannot be nil.')
|
97
293
|
end
|
98
294
|
|
295
|
+
if @tags.nil?
|
296
|
+
invalid_properties.push('invalid value for "tags", tags cannot be nil.')
|
297
|
+
end
|
298
|
+
|
299
|
+
if @_creation_date.nil?
|
300
|
+
invalid_properties.push('invalid value for "_creation_date", _creation_date cannot be nil.')
|
301
|
+
end
|
302
|
+
|
99
303
|
invalid_properties
|
100
304
|
end
|
101
305
|
|
102
306
|
# Check to see if the all the properties in the model are valid
|
103
307
|
# @return true if the model is valid
|
104
308
|
def valid?
|
309
|
+
return false if @_id.nil?
|
105
310
|
return false if @key.nil?
|
106
311
|
return false if @name.nil?
|
312
|
+
return false if @kind.nil?
|
313
|
+
kind_validator = EnumAttributeValidator.new('String', ["pageview", "click", "custom"])
|
314
|
+
return false unless kind_validator.valid?(@kind)
|
107
315
|
return false if @_links.nil?
|
316
|
+
return false if @tags.nil?
|
317
|
+
return false if @_creation_date.nil?
|
318
|
+
success_criteria_validator = EnumAttributeValidator.new('String', ["HigherThanBaseline", "LowerThanBaseline"])
|
319
|
+
return false unless success_criteria_validator.valid?(@success_criteria)
|
108
320
|
true
|
109
321
|
end
|
110
322
|
|
323
|
+
# Custom attribute writer method checking allowed values (enum).
|
324
|
+
# @param [Object] kind Object to be assigned
|
325
|
+
def kind=(kind)
|
326
|
+
validator = EnumAttributeValidator.new('String', ["pageview", "click", "custom"])
|
327
|
+
unless validator.valid?(kind)
|
328
|
+
fail ArgumentError, "invalid value for \"kind\", must be one of #{validator.allowable_values}."
|
329
|
+
end
|
330
|
+
@kind = kind
|
331
|
+
end
|
332
|
+
|
333
|
+
# Custom attribute writer method checking allowed values (enum).
|
334
|
+
# @param [Object] success_criteria Object to be assigned
|
335
|
+
def success_criteria=(success_criteria)
|
336
|
+
validator = EnumAttributeValidator.new('String', ["HigherThanBaseline", "LowerThanBaseline"])
|
337
|
+
unless validator.valid?(success_criteria)
|
338
|
+
fail ArgumentError, "invalid value for \"success_criteria\", must be one of #{validator.allowable_values}."
|
339
|
+
end
|
340
|
+
@success_criteria = success_criteria
|
341
|
+
end
|
342
|
+
|
111
343
|
# Checks equality by comparing each attribute.
|
112
344
|
# @param [Object] Object to be compared
|
113
345
|
def ==(o)
|
114
346
|
return true if self.equal?(o)
|
115
347
|
self.class == o.class &&
|
348
|
+
_id == o._id &&
|
116
349
|
key == o.key &&
|
117
350
|
name == o.name &&
|
118
|
-
|
351
|
+
kind == o.kind &&
|
352
|
+
_attached_flag_count == o._attached_flag_count &&
|
353
|
+
_links == o._links &&
|
354
|
+
_site == o._site &&
|
355
|
+
_access == o._access &&
|
356
|
+
tags == o.tags &&
|
357
|
+
_creation_date == o._creation_date &&
|
358
|
+
last_modified == o.last_modified &&
|
359
|
+
maintainer_id == o.maintainer_id &&
|
360
|
+
_maintainer == o._maintainer &&
|
361
|
+
description == o.description &&
|
362
|
+
is_numeric == o.is_numeric &&
|
363
|
+
success_criteria == o.success_criteria &&
|
364
|
+
unit == o.unit &&
|
365
|
+
event_key == o.event_key &&
|
366
|
+
is_active == o.is_active &&
|
367
|
+
_attached_features == o._attached_features &&
|
368
|
+
_version == o._version &&
|
369
|
+
selector == o.selector &&
|
370
|
+
urls == o.urls
|
119
371
|
end
|
120
372
|
|
121
373
|
# @see the `==` method
|
@@ -127,7 +379,7 @@ module LaunchDarklyApi
|
|
127
379
|
# Calculates hash code according to all attributes.
|
128
380
|
# @return [Integer] Hash code
|
129
381
|
def hash
|
130
|
-
[key, name, _links].hash
|
382
|
+
[_id, key, name, kind, _attached_flag_count, _links, _site, _access, tags, _creation_date, last_modified, maintainer_id, _maintainer, description, is_numeric, success_criteria, unit, event_key, is_active, _attached_features, _version, selector, urls].hash
|
131
383
|
end
|
132
384
|
|
133
385
|
# Builds the object from hash
|