by_star 2.2.1 → 3.0.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 +5 -13
- data/.gitignore +5 -5
- data/.travis.yml +61 -35
- data/CHANGELOG.md +44 -35
- data/Gemfile +18 -25
- data/MIT-LICENSE +20 -20
- data/README.md +577 -540
- data/Rakefile +18 -18
- data/UPGRADING +6 -12
- data/by_star.gemspec +34 -32
- data/cleaner.rb +24 -24
- data/lib/by_star.rb +17 -16
- data/lib/by_star/base.rb +68 -70
- data/lib/by_star/between.rb +156 -120
- data/lib/by_star/directional.rb +37 -33
- data/lib/by_star/kernel/date.rb +50 -19
- data/lib/by_star/kernel/time.rb +41 -41
- data/lib/by_star/normalization.rb +127 -118
- data/lib/by_star/orm/active_record/by_star.rb +61 -69
- data/lib/by_star/orm/mongoid/by_star.rb +76 -73
- data/lib/by_star/orm/mongoid/reorder.rb +23 -0
- data/lib/by_star/version.rb +3 -3
- data/spec/database.yml +15 -15
- data/spec/fixtures/active_record/models.rb +12 -10
- data/spec/fixtures/active_record/schema.rb +19 -19
- data/spec/fixtures/mongoid/models.rb +31 -29
- data/spec/fixtures/shared/seeds.rb +26 -26
- data/spec/gemfiles/Gemfile.master +6 -0
- data/spec/gemfiles/Gemfile.rails40 +7 -0
- data/spec/gemfiles/Gemfile.rails41 +7 -0
- data/spec/gemfiles/Gemfile.rails42 +7 -0
- data/spec/gemfiles/Gemfile.rails50 +10 -0
- data/spec/gemfiles/Gemfile.rails51 +10 -0
- data/spec/integration/active_record/active_record_spec.rb +38 -53
- data/spec/integration/mongoid/mongoid_spec.rb +37 -46
- data/spec/integration/shared/between_times.rb +82 -0
- data/spec/integration/shared/by_calendar_month.rb +55 -55
- data/spec/integration/shared/by_cweek.rb +54 -0
- data/spec/integration/shared/by_day.rb +96 -108
- data/spec/integration/shared/by_direction.rb +172 -153
- data/spec/integration/shared/by_fortnight.rb +48 -48
- data/spec/integration/shared/by_month.rb +50 -50
- data/spec/integration/shared/by_quarter.rb +49 -49
- data/spec/integration/shared/by_week.rb +54 -54
- data/spec/integration/shared/by_weekend.rb +49 -49
- data/spec/integration/shared/by_year.rb +48 -48
- data/spec/integration/shared/offset_parameter.rb +32 -31
- data/spec/integration/shared/order_parameter.rb +36 -0
- data/spec/integration/shared/relative.rb +174 -174
- data/spec/integration/shared/scope_parameter.rb +73 -72
- data/spec/spec_helper.rb +29 -29
- data/spec/unit/kernel_date_spec.rb +113 -60
- data/spec/unit/kernel_time_spec.rb +57 -57
- data/spec/unit/normalization_spec.rb +305 -255
- metadata +61 -62
@@ -1,255 +1,305 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ByStar::Normalization do
|
4
|
-
|
5
|
-
let(:options){ {} }
|
6
|
-
|
7
|
-
shared_examples_for 'time normalization from string' do
|
8
|
-
|
9
|
-
context 'when Chronic is defined' do
|
10
|
-
|
11
|
-
context 'date String' do
|
12
|
-
let(:input){ '2014-01-01' }
|
13
|
-
it { should eq Time.zone.parse('2014-01-01 12:00:00') }
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'time String' do
|
17
|
-
let(:input){ '2014-01-01 15:00:00' }
|
18
|
-
it { should eq Time.zone.parse('2014-01-01 15:00:00') }
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'natural language String' do
|
22
|
-
let(:input){ 'tomorrow at 3:30 pm' }
|
23
|
-
it { should eq Time.zone.parse('2014-01-02 15:30:00') }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'when Chronic is not defined' do
|
28
|
-
|
29
|
-
before { hide_const('Chronic') }
|
30
|
-
|
31
|
-
context 'date String' do
|
32
|
-
let(:input){ '2014-01-01' }
|
33
|
-
it { should eq Time.zone.parse('2014-01-01 00:00:00') }
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'time String' do
|
37
|
-
let(:input){ '2014-01-01 15:00:00' }
|
38
|
-
it { should eq Time.zone.parse('2014-01-01 15:00:00') }
|
39
|
-
end
|
40
|
-
|
41
|
-
context 'natural language String' do
|
42
|
-
let(:input){ 'tomorrow at noon' }
|
43
|
-
it {
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
shared_examples_for 'time normalization from date/time' do
|
49
|
-
context 'Date' do
|
50
|
-
let(:input){ Date.parse('2014-01-01') }
|
51
|
-
it {
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'DateTime' do
|
55
|
-
let(:input){ Time.zone.parse('2014-01-01 15:00:00').to_datetime }
|
56
|
-
it {
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'Time' do
|
60
|
-
let(:input){ Time.zone.parse('2014-01-01 15:00:00') }
|
61
|
-
it {
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe '#time' do
|
66
|
-
subject { ByStar::Normalization.time(input) }
|
67
|
-
it_behaves_like 'time normalization from string'
|
68
|
-
it_behaves_like 'time normalization from date/time'
|
69
|
-
end
|
70
|
-
|
71
|
-
describe '#week' do
|
72
|
-
subject { ByStar::Normalization.week(input, options) }
|
73
|
-
it_behaves_like 'time normalization from string'
|
74
|
-
it_behaves_like 'time normalization from date/time'
|
75
|
-
|
76
|
-
context '
|
77
|
-
let(:input){
|
78
|
-
it {
|
79
|
-
end
|
80
|
-
|
81
|
-
context '
|
82
|
-
let(:input){
|
83
|
-
it {
|
84
|
-
end
|
85
|
-
|
86
|
-
context '
|
87
|
-
let(:
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
context '
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
context '
|
122
|
-
let(:
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
context '
|
191
|
-
let(:input){
|
192
|
-
it {
|
193
|
-
end
|
194
|
-
|
195
|
-
context '
|
196
|
-
let(:input){
|
197
|
-
it {
|
198
|
-
end
|
199
|
-
|
200
|
-
context '
|
201
|
-
let(:input){
|
202
|
-
it {
|
203
|
-
end
|
204
|
-
|
205
|
-
context '
|
206
|
-
let(:
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
context '
|
236
|
-
let(:input){ 1 }
|
237
|
-
it {
|
238
|
-
end
|
239
|
-
|
240
|
-
context '
|
241
|
-
let(:input){
|
242
|
-
it {
|
243
|
-
end
|
244
|
-
|
245
|
-
context '
|
246
|
-
let(:input){
|
247
|
-
it {
|
248
|
-
end
|
249
|
-
|
250
|
-
context '
|
251
|
-
let(:input){
|
252
|
-
it {
|
253
|
-
end
|
254
|
-
|
255
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ByStar::Normalization do
|
4
|
+
|
5
|
+
let(:options){ {} }
|
6
|
+
|
7
|
+
shared_examples_for 'time normalization from string' do
|
8
|
+
|
9
|
+
context 'when Chronic is defined' do
|
10
|
+
|
11
|
+
context 'date String' do
|
12
|
+
let(:input){ '2014-01-01' }
|
13
|
+
it { should eq Time.zone.parse('2014-01-01 12:00:00') }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'time String' do
|
17
|
+
let(:input){ '2014-01-01 15:00:00' }
|
18
|
+
it { should eq Time.zone.parse('2014-01-01 15:00:00') }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'natural language String' do
|
22
|
+
let(:input){ 'tomorrow at 3:30 pm' }
|
23
|
+
it { should eq Time.zone.parse('2014-01-02 15:30:00') }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when Chronic is not defined' do
|
28
|
+
|
29
|
+
before { hide_const('Chronic') }
|
30
|
+
|
31
|
+
context 'date String' do
|
32
|
+
let(:input){ '2014-01-01' }
|
33
|
+
it { should eq Time.zone.parse('2014-01-01 00:00:00') }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'time String' do
|
37
|
+
let(:input){ '2014-01-01 15:00:00' }
|
38
|
+
it { should eq Time.zone.parse('2014-01-01 15:00:00') }
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'natural language String' do
|
42
|
+
let(:input){ 'tomorrow at noon' }
|
43
|
+
it { expect{ subject }.to raise_error(ByStar::ParseError, "Cannot parse String #{input.inspect}") }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
shared_examples_for 'time normalization from date/time' do
|
49
|
+
context 'Date' do
|
50
|
+
let(:input){ Date.parse('2014-01-01') }
|
51
|
+
it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'DateTime' do
|
55
|
+
let(:input){ Time.zone.parse('2014-01-01 15:00:00').to_datetime }
|
56
|
+
it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'Time' do
|
60
|
+
let(:input){ Time.zone.parse('2014-01-01 15:00:00') }
|
61
|
+
it { expect eq Time.zone.parse('2014-01-01 15:00:00') }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#time' do
|
66
|
+
subject { ByStar::Normalization.time(input) }
|
67
|
+
it_behaves_like 'time normalization from string'
|
68
|
+
it_behaves_like 'time normalization from date/time'
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#week' do
|
72
|
+
subject { ByStar::Normalization.week(input, options) }
|
73
|
+
it_behaves_like 'time normalization from string'
|
74
|
+
it_behaves_like 'time normalization from date/time'
|
75
|
+
|
76
|
+
context 'Integer -1' do
|
77
|
+
let(:input){ -1 }
|
78
|
+
it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'Integer 0' do
|
82
|
+
let(:input){ 0 }
|
83
|
+
it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'Integer 20' do
|
87
|
+
let(:input){ 20 }
|
88
|
+
it { expect eq Time.zone.parse('2014-05-21 00:00:00') }
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'Integer 53' do
|
92
|
+
let(:input){ 53 }
|
93
|
+
it { expect{subject}.to raise_error(ByStar::ParseError, 'Week number must be between 0 and 52') }
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'with year option' do
|
97
|
+
let(:options){ { year: 2011 } }
|
98
|
+
|
99
|
+
context 'Integer 0' do
|
100
|
+
let(:input){ 0 }
|
101
|
+
it { expect eq Time.zone.parse('2011-01-01 00:00:00') }
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'Integer 20' do
|
105
|
+
let(:input){ 20 }
|
106
|
+
it { expect eq Time.zone.parse('2011-05-21 00:00:00') }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#cweek' do
|
112
|
+
subject { ByStar::Normalization.cweek(input, options) }
|
113
|
+
it_behaves_like 'time normalization from string'
|
114
|
+
it_behaves_like 'time normalization from date/time'
|
115
|
+
|
116
|
+
context 'Integer 9' do
|
117
|
+
let(:input){ 0 }
|
118
|
+
it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'Integer 1' do
|
122
|
+
let(:input){ 1 }
|
123
|
+
it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'Integer 21' do
|
127
|
+
let(:input){ 21 }
|
128
|
+
it { expect eq Time.zone.parse('2014-05-21 00:00:00') }
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'Integer 54' do
|
132
|
+
let(:input){ 54 }
|
133
|
+
it { expect{subject}.to raise_error(ByStar::ParseError, 'cweek number must be between 1 and 53') }
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'with year option' do
|
137
|
+
let(:options){ { year: 2011 } }
|
138
|
+
|
139
|
+
context 'Integer 1' do
|
140
|
+
let(:input){ 1 }
|
141
|
+
it { expect eq Time.zone.parse('2011-01-01 00:00:00') }
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'Integer 21' do
|
145
|
+
let(:input){ 21 }
|
146
|
+
it { expect eq Time.zone.parse('2011-05-21 00:00:00') }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#fortnight' do
|
152
|
+
subject { ByStar::Normalization.fortnight(input, options) }
|
153
|
+
it_behaves_like 'time normalization from string'
|
154
|
+
it_behaves_like 'time normalization from date/time'
|
155
|
+
|
156
|
+
context 'Integer 0' do
|
157
|
+
let(:input){ 0 }
|
158
|
+
it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'Integer 26' do
|
162
|
+
let(:input){ 26 }
|
163
|
+
it { expect eq Time.zone.parse('2014-12-31 00:00:00') }
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'out of range' do
|
167
|
+
specify { expect{ ByStar::Normalization.fortnight(-1) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
|
168
|
+
specify { expect{ ByStar::Normalization.fortnight(27) }.to raise_error(ByStar::ParseError, 'Fortnight number must be between 0 and 26') }
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'with year option' do
|
172
|
+
let(:options){ { year: 2011 } }
|
173
|
+
|
174
|
+
context 'Integer 0' do
|
175
|
+
let(:input){ 0 }
|
176
|
+
it { expect eq Time.zone.parse('2011-01-01 00:00:00') }
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'Integer 26' do
|
180
|
+
let(:input){ 26 }
|
181
|
+
it { expect eq Time.zone.parse('2011-12-31 00:00:00') }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe '#month' do
|
187
|
+
subject { ByStar::Normalization.month(input, options) }
|
188
|
+
it_behaves_like 'time normalization from date/time'
|
189
|
+
|
190
|
+
context 'month abbr String' do
|
191
|
+
let(:input){ 'Feb' }
|
192
|
+
it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'month full String' do
|
196
|
+
let(:input){ 'February' }
|
197
|
+
it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'number String' do
|
201
|
+
let(:input){ '2' }
|
202
|
+
it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'Integer' do
|
206
|
+
let(:input){ 2 }
|
207
|
+
it { expect eq Time.zone.parse('2014-02-01 00:00:00') }
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'out of range' do
|
211
|
+
specify { expect{ ByStar::Normalization.month(0) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
|
212
|
+
specify { expect{ ByStar::Normalization.month(13) }.to raise_error(ByStar::ParseError, 'Month must be a number between 1 and 12 or a month name') }
|
213
|
+
end
|
214
|
+
|
215
|
+
context 'with year option' do
|
216
|
+
let(:options){ { year: 2011 } }
|
217
|
+
|
218
|
+
context 'month abbr String' do
|
219
|
+
let(:input){ 'Dec' }
|
220
|
+
it { expect eq Time.zone.parse('2011-12-01 00:00:00') }
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'Integer 12' do
|
224
|
+
let(:input){ 10 }
|
225
|
+
it { expect eq Time.zone.parse('2011-10-01 00:00:00') }
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe '#quarter' do
|
231
|
+
subject { ByStar::Normalization.quarter(input, options) }
|
232
|
+
it_behaves_like 'time normalization from string'
|
233
|
+
it_behaves_like 'time normalization from date/time'
|
234
|
+
|
235
|
+
context 'Integer 1' do
|
236
|
+
let(:input){ 1 }
|
237
|
+
it { expect eq Time.zone.parse('2014-01-01 00:00:00') }
|
238
|
+
end
|
239
|
+
|
240
|
+
context 'Integer 2' do
|
241
|
+
let(:input){ 2 }
|
242
|
+
it { expect eq Time.zone.parse('2014-04-01 00:00:00') }
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'Integer 3' do
|
246
|
+
let(:input){ 3 }
|
247
|
+
it { expect eq Time.zone.parse('2014-07-01 00:00:00') }
|
248
|
+
end
|
249
|
+
|
250
|
+
context 'Integer 4' do
|
251
|
+
let(:input){ 4 }
|
252
|
+
it { expect eq Time.zone.parse('2014-10-01 00:00:00') }
|
253
|
+
end
|
254
|
+
|
255
|
+
context 'with year option' do
|
256
|
+
let(:options){ { year: 2011 } }
|
257
|
+
|
258
|
+
context 'Integer 3' do
|
259
|
+
let(:input){ 3 }
|
260
|
+
it { expect eq Time.zone.parse('2011-07-01 00:00:00') }
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'out of range' do
|
265
|
+
specify { expect{ ByStar::Normalization.quarter(0) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
|
266
|
+
specify { expect{ ByStar::Normalization.quarter(5) }.to raise_error(ByStar::ParseError, 'Quarter number must be between 1 and 4') }
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe '#year' do
|
271
|
+
subject { ByStar::Normalization.year(input, options) }
|
272
|
+
it_behaves_like 'time normalization from string'
|
273
|
+
it_behaves_like 'time normalization from date/time'
|
274
|
+
|
275
|
+
context 'Integer 69' do
|
276
|
+
let(:input){ 69 }
|
277
|
+
it { expect eq Time.zone.parse('2069-01-01 00:00:00') }
|
278
|
+
end
|
279
|
+
|
280
|
+
context 'Integer 99' do
|
281
|
+
let(:input){ 99 }
|
282
|
+
it { expect eq Time.zone.parse('1999-01-01 00:00:00') }
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'Integer 2001' do
|
286
|
+
let(:input){ 1 }
|
287
|
+
it { expect eq Time.zone.parse('2001-01-01 00:00:00') }
|
288
|
+
end
|
289
|
+
|
290
|
+
context 'String 01' do
|
291
|
+
let(:input){ '01' }
|
292
|
+
it { expect eq Time.zone.parse('2001-01-01 00:00:00') }
|
293
|
+
end
|
294
|
+
|
295
|
+
context 'String 70' do
|
296
|
+
let(:input){ '70' }
|
297
|
+
it { expect eq Time.zone.parse('1970-01-01 00:00:00') }
|
298
|
+
end
|
299
|
+
|
300
|
+
context 'String 2001' do
|
301
|
+
let(:input){ '2001' }
|
302
|
+
it { expect eq Time.zone.parse('2001-01-01 00:00:00') }
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|