tasci_merger 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +22 -22
- data/README.md +77 -77
- data/bin/merge_tasci +10 -8
- data/lib/labtime.rb +110 -110
- data/lib/man_merger.rb +344 -344
- data/lib/tasci_merger.rb +333 -324
- data/tasci_merger.gemspec +21 -21
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f64b8313d03c5d06c1bab7f649ba5f45fc73581
|
4
|
+
data.tar.gz: 1c792759d7a686ccc2b9170f59da9d045f29021f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5834a433021d04e75c0ee2e073232730104fd564a3b1cb5c5b7db0e235396a6daf3833092540b530309e60f40c1efd532b45c071202e0f1a17afef555a0ee164
|
7
|
+
data.tar.gz: b379b0ad91e13bc723180962161e20dd50f35e44eaca43b59c8e7d05ee50425fdf2802788eadd0366885857c18d006623817869d0416715504818906a51bf2dc
|
data/LICENSE
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2015 Piotr Mankowski
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|
22
|
-
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Piotr Mankowski
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
CHANGED
@@ -1,77 +1,77 @@
|
|
1
|
-
# Instructions for Tasci File Merger
|
2
|
-
|
3
|
-
## Installation
|
4
|
-
1. Install Ruby.
|
5
|
-
- [http://rubyinstaller.org/](http://rubyinstaller.org/)
|
6
|
-
- Download Ruby 2.1.5 (x64) installer.
|
7
|
-
- Install to desired *RUBY_DIRECTORY*
|
8
|
-
- Choose option to add ruby to *PATH*
|
9
|
-
- Choose option to associate *.rb files with Ruby
|
10
|
-
|
11
|
-
2. Verify ruby installation.
|
12
|
-
- Go into command line.
|
13
|
-
- Enter `ruby -v`
|
14
|
-
- Ouput should look like `ruby 2.1.5p273...`
|
15
|
-
- Enter `gem -v`
|
16
|
-
- Output should look like `2.2.2`
|
17
|
-
|
18
|
-
3. Fix potential RubyGems certificate bug, as documented on [this page](https://gist.github.com/luislavena/f064211759ee0f806c88)
|
19
|
-
- Try running `gem install activesupport --no-ri --no-rdoc`
|
20
|
-
- Click `Allow access` if prompted by Windows Firewall message, choosing option for *Private networks*
|
21
|
-
- If installation fails with an `SSL_error`, follow the following steps:
|
22
|
-
- Save certificate file from [this website](https://raw.githubusercontent.com/rubygems/rubygems/master/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem) to the Downloads directory.
|
23
|
-
- **Make sure file is saved with the *.pem extension**
|
24
|
-
- Find rubygems folder location by typing `gem which rubygems` into the console. You should get output like `C:/Ruby21/lib/ruby/2.1.0/rubygems.rb`
|
25
|
-
- Locate the directory and open it in an explorer window. For the above path, the directory would be `C:\Ruby21\lib\ruby\2.1.0\rubygems`
|
26
|
-
- Open the `ssl_certs` directory, and copy the previously-downloaded `*.pem` file into this directory.
|
27
|
-
- Close and re-open a console window.
|
28
|
-
|
29
|
-
4. Install required gem.
|
30
|
-
- Run:
|
31
|
-
|
32
|
-
```
|
33
|
-
gem install tasci_merger
|
34
|
-
```
|
35
|
-
|
36
|
-
## Usage in IRB
|
37
|
-
|
38
|
-
1. Open console and run `irb` to open interactive ruby console.
|
39
|
-
|
40
|
-
2. Run `require 'tasci_merger'`
|
41
|
-
|
42
|
-
3. Create tasci merger object:
|
43
|
-
|
44
|
-
```ruby
|
45
|
-
tm = TasciMerger.new("SUBJECT_CODE", "TASCI_DIRECTORY", "OUTPUT_DIRECTORY")
|
46
|
-
```
|
47
|
-
|
48
|
-
4. Create master file:
|
49
|
-
|
50
|
-
```ruby
|
51
|
-
tm.create_master_list
|
52
|
-
```
|
53
|
-
|
54
|
-
5. Create merged
|
55
|
-
|
56
|
-
```ruby
|
57
|
-
tm.merge_files
|
58
|
-
```
|
59
|
-
|
60
|
-
## Command-line Usage
|
61
|
-
|
62
|
-
The ruby gem makes the `tasci_merger` command available.
|
63
|
-
|
64
|
-
The command takes the following parameters:
|
65
|
-
- SUBJECT_CODE
|
66
|
-
- TASCI_DIRECTORY
|
67
|
-
- OUTPUT_DIRECTORY
|
68
|
-
|
69
|
-
The command creates a master file and merged
|
70
|
-
|
71
|
-
**Example Usage:**
|
72
|
-
|
73
|
-
```
|
74
|
-
merge_tasci 3441GX X:/TasciFilesFor3441GX C:/Circadian
|
75
|
-
```
|
76
|
-
|
77
|
-
This command would create the 2 files in the `C:/Circadian` directory.
|
1
|
+
# Instructions for Tasci File Merger
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
1. Install Ruby.
|
5
|
+
- [http://rubyinstaller.org/](http://rubyinstaller.org/)
|
6
|
+
- Download Ruby 2.1.5 (x64) installer.
|
7
|
+
- Install to desired *RUBY_DIRECTORY*
|
8
|
+
- Choose option to add ruby to *PATH*
|
9
|
+
- Choose option to associate *.rb files with Ruby
|
10
|
+
|
11
|
+
2. Verify ruby installation.
|
12
|
+
- Go into command line.
|
13
|
+
- Enter `ruby -v`
|
14
|
+
- Ouput should look like `ruby 2.1.5p273...`
|
15
|
+
- Enter `gem -v`
|
16
|
+
- Output should look like `2.2.2`
|
17
|
+
|
18
|
+
3. Fix potential RubyGems certificate bug, as documented on [this page](https://gist.github.com/luislavena/f064211759ee0f806c88)
|
19
|
+
- Try running `gem install activesupport --no-ri --no-rdoc`
|
20
|
+
- Click `Allow access` if prompted by Windows Firewall message, choosing option for *Private networks*
|
21
|
+
- If installation fails with an `SSL_error`, follow the following steps:
|
22
|
+
- Save certificate file from [this website](https://raw.githubusercontent.com/rubygems/rubygems/master/lib/rubygems/ssl_certs/AddTrustExternalCARoot-2048.pem) to the Downloads directory.
|
23
|
+
- **Make sure file is saved with the *.pem extension**
|
24
|
+
- Find rubygems folder location by typing `gem which rubygems` into the console. You should get output like `C:/Ruby21/lib/ruby/2.1.0/rubygems.rb`
|
25
|
+
- Locate the directory and open it in an explorer window. For the above path, the directory would be `C:\Ruby21\lib\ruby\2.1.0\rubygems`
|
26
|
+
- Open the `ssl_certs` directory, and copy the previously-downloaded `*.pem` file into this directory.
|
27
|
+
- Close and re-open a console window.
|
28
|
+
|
29
|
+
4. Install required gem.
|
30
|
+
- Run:
|
31
|
+
|
32
|
+
```
|
33
|
+
gem install tasci_merger
|
34
|
+
```
|
35
|
+
|
36
|
+
## Usage in IRB
|
37
|
+
|
38
|
+
1. Open console and run `irb` to open interactive ruby console.
|
39
|
+
|
40
|
+
2. Run `require 'tasci_merger'`
|
41
|
+
|
42
|
+
3. Create tasci merger object:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
tm = TasciMerger.new("SUBJECT_CODE", "TASCI_DIRECTORY", "OUTPUT_DIRECTORY")
|
46
|
+
```
|
47
|
+
|
48
|
+
4. Create master file:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
tm.create_master_list
|
52
|
+
```
|
53
|
+
|
54
|
+
5. Create 2 merged files:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
tm.merge_files
|
58
|
+
```
|
59
|
+
|
60
|
+
## Command-line Usage
|
61
|
+
|
62
|
+
The ruby gem makes the `tasci_merger` command available.
|
63
|
+
|
64
|
+
The command takes the following parameters:
|
65
|
+
- SUBJECT_CODE
|
66
|
+
- TASCI_DIRECTORY
|
67
|
+
- OUTPUT_DIRECTORY
|
68
|
+
|
69
|
+
The command creates a master file and two merged files in the output directory.
|
70
|
+
|
71
|
+
**Example Usage:**
|
72
|
+
|
73
|
+
```
|
74
|
+
merge_tasci 3441GX X:/TasciFilesFor3441GX C:/Circadian
|
75
|
+
```
|
76
|
+
|
77
|
+
This command would create the 2 files in the `C:/Circadian` directory.
|
data/bin/merge_tasci
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'tasci_merger'
|
4
|
-
|
5
|
-
# SUBJECT_CODE, TASCI_DIR
|
6
|
-
tm = TasciMerger.new(ARGV[0], ARGV[1], ARGV[2])
|
7
|
-
tm.create_master_list
|
8
|
-
tm.merge_files
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'tasci_merger'
|
4
|
+
|
5
|
+
# SUBJECT_CODE, TASCI_DIR
|
6
|
+
tm = TasciMerger.new(ARGV[0], ARGV[1], ARGV[2])
|
7
|
+
tm.create_master_list
|
8
|
+
tm.merge_files
|
9
|
+
|
10
|
+
# tm = TasciMerger.new("3241gx63", "C:/Partners/Tasci/Scored", "C:/Partners/Tasci/Output")
|
data/lib/labtime.rb
CHANGED
@@ -1,111 +1,111 @@
|
|
1
|
-
require('active_support/values/time_zone')
|
2
|
-
require('active_support/time_with_zone')
|
3
|
-
require 'active_support/core_ext/time/zones'
|
4
|
-
require 'active_support/core_ext/time'
|
5
|
-
require 'active_support/core_ext/numeric/time'
|
6
|
-
|
7
|
-
class Labtime
|
8
|
-
include Comparable
|
9
|
-
|
10
|
-
attr_accessor :year, :hour, :min, :sec, :time_zone
|
11
|
-
DEFAULT_TIME_ZONE = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
|
12
|
-
|
13
|
-
def self.parse(realtime)
|
14
|
-
# Return nil if nil parameter
|
15
|
-
return nil if realtime.nil?
|
16
|
-
|
17
|
-
# Make sure datetime is an ActiveSupport:TimeWithZone object
|
18
|
-
raise ArgumentError, "realtime class #{realtime.class} is not ActiveSupport::TimeWithZone" unless realtime.is_a?(ActiveSupport::TimeWithZone)
|
19
|
-
|
20
|
-
# year is easy
|
21
|
-
year = realtime.year
|
22
|
-
|
23
|
-
# Reference fo labtime is start of year
|
24
|
-
Time.zone = realtime.time_zone
|
25
|
-
reference_time = Time.zone.local(year)
|
26
|
-
|
27
|
-
# find difference between reference and
|
28
|
-
second_difference = realtime.to_i - reference_time.to_i
|
29
|
-
|
30
|
-
# convert second difference to labtime
|
31
|
-
hour = second_difference / 3600
|
32
|
-
min = (second_difference - (hour * 3600)) / 60
|
33
|
-
sec = (second_difference - (hour * 3600) - (min * 60))
|
34
|
-
|
35
|
-
self.new(year, hour, min, sec, realtime.time_zone)
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.from_decimal(decimal_labtime, year, time_zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)"))
|
39
|
-
raise ArguementError, "No year supplied!" if year.blank?
|
40
|
-
|
41
|
-
hour = decimal_labtime.to_i
|
42
|
-
remainder = decimal_labtime - hour.to_f
|
43
|
-
min_labtime = 60.0 * remainder
|
44
|
-
min = min_labtime.to_i
|
45
|
-
remainder = min_labtime - min.to_f
|
46
|
-
sec = (60 * remainder).round.to_i
|
47
|
-
|
48
|
-
self.new(year, hour, min, sec, time_zone)
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.from_seconds(sec_time, year, time_zone = DEFAULT_TIME_ZONE)
|
52
|
-
hour = (sec_time / 3600.0).to_i
|
53
|
-
sec_time = sec_time - (hour * 3600)
|
54
|
-
min = (sec_time / 60.0).to_i
|
55
|
-
sec_time = sec_time - (min * 60)
|
56
|
-
sec = sec_time
|
57
|
-
|
58
|
-
self.new(year, hour, min, sec, time_zone)
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.from_s(str, time_params = {}, time_zone = DEFAULT_TIME_ZONE)
|
62
|
-
time_captures = /(\d+)\:(\d{1,2})(\:(\d{1,2}))?(\s(\d\d\d\d))?\z/.match(str).captures
|
63
|
-
|
64
|
-
time_params[:hour] ||= time_captures[0]
|
65
|
-
time_params[:min] ||= time_captures[1]
|
66
|
-
time_params[:sec] ||= time_captures[3]
|
67
|
-
time_params[:year] ||= time_captures[5]
|
68
|
-
|
69
|
-
self.new(time_params[:year], time_params[:hour], time_params[:min], time_params[:sec], time_zone)
|
70
|
-
end
|
71
|
-
|
72
|
-
def initialize(year, hour, min, sec, time_zone = nil)
|
73
|
-
@year = year.to_i
|
74
|
-
@hour = hour.to_i
|
75
|
-
@min = min.to_i
|
76
|
-
@sec = sec.to_i
|
77
|
-
@time_zone = time_zone || DEFAULT_TIME_ZONE
|
78
|
-
end
|
79
|
-
|
80
|
-
def to_time
|
81
|
-
reference_time = time_zone.local(year)
|
82
|
-
reference_time + time_in_seconds
|
83
|
-
end
|
84
|
-
|
85
|
-
def <=>(other)
|
86
|
-
to_time <=> other.to_time
|
87
|
-
end
|
88
|
-
|
89
|
-
def to_s
|
90
|
-
"#{year} #{hour}:#{min}:#{sec} #{time_zone.to_s}"
|
91
|
-
end
|
92
|
-
|
93
|
-
def to_short_s
|
94
|
-
"#{hour}:#{min}:#{sec}"
|
95
|
-
end
|
96
|
-
|
97
|
-
def time_in_seconds
|
98
|
-
hour * 3600 + min * 60 + sec
|
99
|
-
end
|
100
|
-
|
101
|
-
def add_seconds(sec)
|
102
|
-
self.class.from_seconds(self.time_in_seconds + sec, self.year, self.time_zone)
|
103
|
-
end
|
104
|
-
|
105
|
-
def to_decimal
|
106
|
-
hour.to_f + (min.to_f/60.0) + (sec.to_f/3600.0)
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
|
1
|
+
require('active_support/values/time_zone')
|
2
|
+
require('active_support/time_with_zone')
|
3
|
+
require 'active_support/core_ext/time/zones'
|
4
|
+
require 'active_support/core_ext/time'
|
5
|
+
require 'active_support/core_ext/numeric/time'
|
6
|
+
|
7
|
+
class Labtime
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
attr_accessor :year, :hour, :min, :sec, :time_zone
|
11
|
+
DEFAULT_TIME_ZONE = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
|
12
|
+
|
13
|
+
def self.parse(realtime)
|
14
|
+
# Return nil if nil parameter
|
15
|
+
return nil if realtime.nil?
|
16
|
+
|
17
|
+
# Make sure datetime is an ActiveSupport:TimeWithZone object
|
18
|
+
raise ArgumentError, "realtime class #{realtime.class} is not ActiveSupport::TimeWithZone" unless realtime.is_a?(ActiveSupport::TimeWithZone)
|
19
|
+
|
20
|
+
# year is easy
|
21
|
+
year = realtime.year
|
22
|
+
|
23
|
+
# Reference fo labtime is start of year
|
24
|
+
Time.zone = realtime.time_zone
|
25
|
+
reference_time = Time.zone.local(year)
|
26
|
+
|
27
|
+
# find difference between reference and
|
28
|
+
second_difference = realtime.to_i - reference_time.to_i
|
29
|
+
|
30
|
+
# convert second difference to labtime
|
31
|
+
hour = second_difference / 3600
|
32
|
+
min = (second_difference - (hour * 3600)) / 60
|
33
|
+
sec = (second_difference - (hour * 3600) - (min * 60))
|
34
|
+
|
35
|
+
self.new(year, hour, min, sec, realtime.time_zone)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.from_decimal(decimal_labtime, year, time_zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)"))
|
39
|
+
raise ArguementError, "No year supplied!" if year.blank?
|
40
|
+
|
41
|
+
hour = decimal_labtime.to_i
|
42
|
+
remainder = decimal_labtime - hour.to_f
|
43
|
+
min_labtime = 60.0 * remainder
|
44
|
+
min = min_labtime.to_i
|
45
|
+
remainder = min_labtime - min.to_f
|
46
|
+
sec = (60 * remainder).round.to_i
|
47
|
+
|
48
|
+
self.new(year, hour, min, sec, time_zone)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.from_seconds(sec_time, year, time_zone = DEFAULT_TIME_ZONE)
|
52
|
+
hour = (sec_time / 3600.0).to_i
|
53
|
+
sec_time = sec_time - (hour * 3600)
|
54
|
+
min = (sec_time / 60.0).to_i
|
55
|
+
sec_time = sec_time - (min * 60)
|
56
|
+
sec = sec_time
|
57
|
+
|
58
|
+
self.new(year, hour, min, sec, time_zone)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.from_s(str, time_params = {}, time_zone = DEFAULT_TIME_ZONE)
|
62
|
+
time_captures = /(\d+)\:(\d{1,2})(\:(\d{1,2}))?(\s(\d\d\d\d))?\z/.match(str).captures
|
63
|
+
|
64
|
+
time_params[:hour] ||= time_captures[0]
|
65
|
+
time_params[:min] ||= time_captures[1]
|
66
|
+
time_params[:sec] ||= time_captures[3]
|
67
|
+
time_params[:year] ||= time_captures[5]
|
68
|
+
|
69
|
+
self.new(time_params[:year], time_params[:hour], time_params[:min], time_params[:sec], time_zone)
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(year, hour, min, sec, time_zone = nil)
|
73
|
+
@year = year.to_i
|
74
|
+
@hour = hour.to_i
|
75
|
+
@min = min.to_i
|
76
|
+
@sec = sec.to_i
|
77
|
+
@time_zone = time_zone || DEFAULT_TIME_ZONE
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_time
|
81
|
+
reference_time = time_zone.local(year)
|
82
|
+
reference_time + time_in_seconds
|
83
|
+
end
|
84
|
+
|
85
|
+
def <=>(other)
|
86
|
+
to_time <=> other.to_time
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
"#{year} #{hour}:#{min}:#{sec} #{time_zone.to_s}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_short_s
|
94
|
+
"#{hour}:#{min}:#{sec}"
|
95
|
+
end
|
96
|
+
|
97
|
+
def time_in_seconds
|
98
|
+
hour * 3600 + min * 60 + sec
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_seconds(sec)
|
102
|
+
self.class.from_seconds(self.time_in_seconds + sec, self.year, self.time_zone)
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_decimal
|
106
|
+
hour.to_f + (min.to_f/60.0) + (sec.to_f/3600.0)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
111
|
end
|