natour 0.3.0 → 0.7.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 +4 -4
- data/CHANGELOG.adoc +51 -0
- data/README.adoc +1 -1
- data/bin/natour +10 -4
- data/lib/natour/asciinurse.rb +38 -29
- data/lib/natour/config.rb +1 -1
- data/lib/natour/convert.rb +42 -16
- data/lib/natour/create.rb +2 -1
- data/lib/natour/gps_track.rb +4 -0
- data/lib/natour/gpx_file.rb +16 -13
- data/lib/natour/image.rb +36 -11
- data/lib/natour/report.rb +9 -5
- data/lib/natour/species_list.rb +18 -11
- data/lib/natour/utils/botanical_name_utils.rb +12 -0
- data/lib/natour/{helpers/date_parser.rb → utils/date_utils.rb} +1 -1
- data/lib/natour/utils/stdout_utils.rb +16 -0
- data/lib/natour.rb +3 -2
- metadata +29 -14
- data/lib/natour/helpers/suppress_output.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c649407352883c9e93ab6d6470413127d54803bb35dc72beb83292c9e521626
|
4
|
+
data.tar.gz: dbeb8f8ae4a412d7832c07ab66d717d40bb5e2ecd096fb076655ef65a6840b53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5a810b2ea0220c9eded025e0f00f8e4f782a42b54128f71a2929a84a535e75f45bb3ddff0cf72f7dad08e047c1aaef3b88800e778901405357efd11336b5db0
|
7
|
+
data.tar.gz: a928d426c1840cb57fb7ab58064850572fc2a7e14aeda6086b2c9560c8b2d7e3e8253c268a9070bef91e4c7fb2c0f26daf2e5664a043f29b595d192a0299137f
|
data/CHANGELOG.adoc
CHANGED
@@ -6,6 +6,57 @@ The format is based on https://keepachangelog.com/en/1.0.0/[Keep a Changelog^],
|
|
6
6
|
|
7
7
|
== Unreleased
|
8
8
|
|
9
|
+
== 0.7.0 - 2022-02-14
|
10
|
+
|
11
|
+
=== Added
|
12
|
+
|
13
|
+
- Add support for Ruby 3.0 and 3.1
|
14
|
+
- Support species lists from Vogelführer Birdlife Schweiz
|
15
|
+
|
16
|
+
=== Changed
|
17
|
+
|
18
|
+
- Return the filenames from `create` and `convert`
|
19
|
+
|
20
|
+
=== Removed
|
21
|
+
|
22
|
+
- Drop support for Ruby 2.5
|
23
|
+
|
24
|
+
=== Fixed
|
25
|
+
|
26
|
+
- Add revision date to the AsciiDoc output regardless of the author
|
27
|
+
- Prevent conversion from being aborted if a built-in date/time attribute is missing
|
28
|
+
|
29
|
+
== 0.6.0 - 2021-11-20
|
30
|
+
|
31
|
+
=== Fixed
|
32
|
+
|
33
|
+
- Support GPX files containing only mandatory elements (i.e. no extensions)
|
34
|
+
- Consider also the image dimensions to determine the orientation, even if the tag is present
|
35
|
+
|
36
|
+
== 0.5.0 - 2021-08-16
|
37
|
+
|
38
|
+
=== Added
|
39
|
+
|
40
|
+
- Reflect the date of the last update in the revision date
|
41
|
+
- Add captions to species lists in the AsciiDoc output
|
42
|
+
- Group species lists by taxonomic groups in the AsciiDoc output
|
43
|
+
|
44
|
+
=== Fixed
|
45
|
+
|
46
|
+
- Support species lists of Flora Helvetica exported from Favoriten
|
47
|
+
- Consider botanical names with the authority name preceding the subspecies
|
48
|
+
|
49
|
+
== 0.4.0 - 2021-05-02
|
50
|
+
|
51
|
+
=== Added
|
52
|
+
|
53
|
+
- Show date/time of images in draft output
|
54
|
+
- Support preferred conversion backend for draft output
|
55
|
+
|
56
|
+
=== Changed
|
57
|
+
|
58
|
+
- Remove redundant method `Image.portrait?`
|
59
|
+
|
9
60
|
== 0.3.0 - 2021-03-07
|
10
61
|
|
11
62
|
=== Changed
|
data/README.adoc
CHANGED
data/bin/natour
CHANGED
@@ -17,6 +17,7 @@ config = Natour::Config.load_file(
|
|
17
17
|
'adoc-author' => nil,
|
18
18
|
'backend' => 'pdf',
|
19
19
|
'draft' => false,
|
20
|
+
'draft-backend' => nil,
|
20
21
|
'image-maxdim' => 1800
|
21
22
|
}
|
22
23
|
)
|
@@ -27,10 +28,11 @@ option_parser = OptionParser.new do |opts|
|
|
27
28
|
opts.separator(WordWrap.ww(
|
28
29
|
'If PATH refers to a directory, one or more reports are created in ' \
|
29
30
|
'AsciiDoc format. GPS tracks, images and species lists (Kosmos ' \
|
30
|
-
'Vogelführer, ornitho.ch, Flora Helvetica,
|
31
|
-
'are included. Images of the map section
|
32
|
-
'also created and included. If PATH refers
|
33
|
-
'converted to PDF (or any other supported
|
31
|
+
'Vogelführer, Vogelführer Birdlife Schweiz, ornitho.ch, Flora Helvetica,' \
|
32
|
+
' Info Flora Online-Feldbuch) are included. Images of the map section ' \
|
33
|
+
'covered by the GPS tracks are also created and included. If PATH refers' \
|
34
|
+
' to an AsciiDoc file, it is converted to PDF (or any other supported ' \
|
35
|
+
'format).'
|
34
36
|
))
|
35
37
|
opts.separator('')
|
36
38
|
opts.separator('General:')
|
@@ -69,6 +71,9 @@ option_parser = OptionParser.new do |opts|
|
|
69
71
|
opts.on('--[no-]draft', 'Show additional information (e.g. image paths)') do |value|
|
70
72
|
config['draft'] = value
|
71
73
|
end
|
74
|
+
opts.on('--draft-backend BACKEND', 'Preferred conversion backend for draft (pdf, html5 ...)') do |value|
|
75
|
+
config['draft-backend'] = value
|
76
|
+
end
|
72
77
|
opts.on('--image-maxdim DIM', 'Shrink oversized images (PDF only)') do |value|
|
73
78
|
config['image-maxdim'] = value.to_i
|
74
79
|
end
|
@@ -106,6 +111,7 @@ else
|
|
106
111
|
overwrite: config['overwrite'],
|
107
112
|
backend: config['backend'],
|
108
113
|
draft: config['draft'],
|
114
|
+
draft_backend: config['draft-backend'],
|
109
115
|
image_maxdim: config['image-maxdim']
|
110
116
|
)
|
111
117
|
end
|
data/lib/natour/asciinurse.rb
CHANGED
@@ -28,11 +28,10 @@ module Natour
|
|
28
28
|
|
29
29
|
doc = []
|
30
30
|
doc << "= #{title}"
|
31
|
-
if author
|
32
|
-
|
33
|
-
doc << Date.today.strftime('%d.%m.%Y')
|
34
|
-
end
|
31
|
+
doc << author if author
|
32
|
+
doc << ':revdate: {docdate}'
|
35
33
|
doc << ':figure-caption!:'
|
34
|
+
doc << ':table-caption!:'
|
36
35
|
doc << ':pdf-page-mode: none'
|
37
36
|
doc << ':title-page:'
|
38
37
|
if title_image
|
@@ -77,10 +76,10 @@ module Natour
|
|
77
76
|
doc << '== Bilder'
|
78
77
|
doc << ''
|
79
78
|
images.each do |image|
|
80
|
-
width = if image.
|
81
|
-
'40%'
|
82
|
-
else
|
79
|
+
width = if image.landscape?
|
83
80
|
'80%'
|
81
|
+
else
|
82
|
+
'40%'
|
84
83
|
end
|
85
84
|
doc << '.Abbildung {counter:image}'
|
86
85
|
doc << "image::#{Pathname(doc_root).join(image.path)}[width=#{width}]"
|
@@ -88,35 +87,45 @@ module Natour
|
|
88
87
|
end
|
89
88
|
end
|
90
89
|
unless species_lists.empty?
|
91
|
-
birds_info = OpenStruct.new(
|
92
|
-
title: 'Vogelarten',
|
93
|
-
headers: %w[Deutscher\ Name Wissenschaftlicher\ Name],
|
94
|
-
columns: %i[name_de name]
|
95
|
-
)
|
96
|
-
plants_info = OpenStruct.new(
|
97
|
-
title: 'Pflanzenarten',
|
98
|
-
headers: %w[Wissenschaftlicher\ Name Deutscher\ Name],
|
99
|
-
columns: %i[name name_de]
|
100
|
-
)
|
101
90
|
doc << '<<<'
|
102
91
|
doc << ''
|
103
92
|
doc << '== Artenlisten'
|
104
93
|
doc << ''
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
94
|
+
index = 1
|
95
|
+
groups = species_lists.group_by(&:group)
|
96
|
+
[
|
97
|
+
OpenStruct.new(
|
98
|
+
group: :plants,
|
99
|
+
title: 'Pflanzenarten',
|
100
|
+
headers: ['Wissenschaftlicher Name', 'Deutscher Name'],
|
101
|
+
columns: %i[name name_de]
|
102
|
+
),
|
103
|
+
OpenStruct.new(
|
104
|
+
group: :birds,
|
105
|
+
title: 'Vogelarten',
|
106
|
+
headers: ['Deutscher Name', 'Wissenschaftlicher Name'],
|
107
|
+
columns: %i[name_de name]
|
108
|
+
)
|
109
|
+
].each do |info|
|
110
|
+
group = groups.fetch(info.group, [])
|
111
|
+
next if group.empty?
|
112
|
+
|
110
113
|
doc << "=== #{info.title}"
|
111
114
|
doc << ''
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
doc << "
|
115
|
+
group.each do |species_list|
|
116
|
+
caption = '.Tabelle {counter:species_lists}'
|
117
|
+
caption << ": #{species_list.description}" if species_list.description
|
118
|
+
doc << caption
|
119
|
+
doc << '[cols="1,5,5",options=header]'
|
120
|
+
doc << '|==='
|
121
|
+
doc << "|Nr.|#{info.headers.join('|')}"
|
122
|
+
species_list.each do |species|
|
123
|
+
doc << "|{counter:species_list#{index}}|#{info.columns.map { |method| species.send(method) }.join('|')}"
|
124
|
+
end
|
125
|
+
doc << '|==='
|
126
|
+
doc << ''
|
127
|
+
index += 1
|
117
128
|
end
|
118
|
-
doc << '|==='
|
119
|
-
doc << ''
|
120
129
|
end
|
121
130
|
end
|
122
131
|
doc.join("\n")
|
data/lib/natour/config.rb
CHANGED
data/lib/natour/convert.rb
CHANGED
@@ -3,12 +3,19 @@ require 'pathname'
|
|
3
3
|
require 'asciidoctor'
|
4
4
|
require 'asciidoctor-pdf'
|
5
5
|
require 'vips'
|
6
|
+
require 'time'
|
6
7
|
|
7
8
|
module Natour
|
8
9
|
module_function
|
9
10
|
|
10
11
|
def convert(filename, out_dir: nil, out_file: nil, overwrite: false,
|
11
|
-
backend: 'pdf', draft: false, image_maxdim: 16000)
|
12
|
+
backend: 'pdf', draft: false, draft_backend: nil, image_maxdim: 16000)
|
13
|
+
backend = if draft
|
14
|
+
draft_backend || backend
|
15
|
+
else
|
16
|
+
backend
|
17
|
+
end
|
18
|
+
|
12
19
|
doc = Asciidoctor.load_file(
|
13
20
|
filename,
|
14
21
|
backend: backend,
|
@@ -26,10 +33,35 @@ module Natour
|
|
26
33
|
out_file = Pathname(
|
27
34
|
out_file || "#{doc.attr('docname')}#{doc.attr('outfilesuffix')}"
|
28
35
|
)
|
36
|
+
filename = out_dir.join(out_file)
|
29
37
|
|
30
38
|
if draft
|
31
39
|
doc.find_by(context: :image).each do |node|
|
32
|
-
|
40
|
+
target = node.attr('target')
|
41
|
+
image = Image.load_file(dir.join(target).to_s)
|
42
|
+
node.title = "#{node.title} [#{[target, image.date_time].compact.join('|')}]"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
%w[
|
47
|
+
revdate
|
48
|
+
docdate
|
49
|
+
doctime
|
50
|
+
docdatetime
|
51
|
+
localdate
|
52
|
+
localtime
|
53
|
+
localdatetime
|
54
|
+
].each do |attr_name|
|
55
|
+
attr_value = doc.attr(attr_name)
|
56
|
+
next unless attr_value
|
57
|
+
|
58
|
+
date_time = Time.parse(attr_value)
|
59
|
+
if attr_name.end_with?('datetime')
|
60
|
+
doc.set_attr(attr_name, date_time.strftime('%d.%m.%Y %H:%M:%S'))
|
61
|
+
elsif attr_name.end_with?('date')
|
62
|
+
doc.set_attr(attr_name, date_time.strftime('%d.%m.%Y'))
|
63
|
+
elsif attr_name.end_with?('time')
|
64
|
+
doc.set_attr(attr_name, date_time.strftime('%H:%M:%S'))
|
33
65
|
end
|
34
66
|
end
|
35
67
|
|
@@ -40,32 +72,24 @@ module Natour
|
|
40
72
|
title_logo_image = doc.attr('title-logo-image')
|
41
73
|
if title_logo_image
|
42
74
|
target = title_logo_image[/^image:{1,2}(.*?)\[(.*?)\]$/, 1]
|
43
|
-
|
44
|
-
options[:autorotate] = true if target =~ /\.jpe?g$/i
|
45
|
-
image = Vips::Image.new_from_file(dir.join(target).to_s, options)
|
46
|
-
scale = image_maxdim / image.size.max.to_f
|
47
|
-
image = image.resize(scale) if scale < 1.0
|
75
|
+
image = Image.load_file(dir.join(target).to_s).autorotate.shrink_to(image_maxdim)
|
48
76
|
new_target = tmp_dir.join("title_logo_image_#{Pathname(target).basename}").to_s
|
49
|
-
|
77
|
+
image.save_as(new_target)
|
50
78
|
doc.set_attr('title-logo-image', title_logo_image.gsub(target, new_target))
|
51
79
|
end
|
52
80
|
|
53
81
|
doc.find_by(context: :image).each.with_index do |node, index|
|
54
82
|
target = node.attr('target')
|
55
|
-
|
56
|
-
options[:autorotate] = true if target =~ /\.jpe?g$/i
|
57
|
-
image = Vips::Image.new_from_file(dir.join(target).to_s, options)
|
58
|
-
scale = image_maxdim / image.size.max.to_f
|
59
|
-
image = image.resize(scale) if scale < 1.0
|
83
|
+
image = Image.load_file(dir.join(target).to_s).autorotate.shrink_to(image_maxdim)
|
60
84
|
new_target = tmp_dir.join("image#{index}_#{Pathname(target).basename}").to_s
|
61
|
-
|
85
|
+
image.save_as(new_target)
|
62
86
|
node.set_attr('target', new_target)
|
63
87
|
end
|
64
88
|
|
65
89
|
FileUtils.mkdir_p(out_dir)
|
66
90
|
mode = File::WRONLY | File::CREAT | File::TRUNC | File::BINARY
|
67
91
|
mode |= File::EXCL unless overwrite
|
68
|
-
File.open(
|
92
|
+
File.open(filename, mode) do |file|
|
69
93
|
doc.write(doc.convert, file)
|
70
94
|
end
|
71
95
|
end
|
@@ -73,9 +97,11 @@ module Natour
|
|
73
97
|
FileUtils.mkdir_p(out_dir)
|
74
98
|
mode = File::WRONLY | File::CREAT | File::TRUNC
|
75
99
|
mode |= File::EXCL unless overwrite
|
76
|
-
File.open(
|
100
|
+
File.open(filename, mode) do |file|
|
77
101
|
doc.write(doc.convert, file)
|
78
102
|
end
|
79
103
|
end
|
104
|
+
|
105
|
+
filename.to_s
|
80
106
|
end
|
81
107
|
end
|
data/lib/natour/create.rb
CHANGED
@@ -8,13 +8,14 @@ module Natour
|
|
8
8
|
reports = Report.load_directory(
|
9
9
|
dir, track_formats: track_formats, create_map: create_map, map_layers: map_layers
|
10
10
|
)
|
11
|
-
reports.
|
11
|
+
reports.map.with_index(1) do |report, index|
|
12
12
|
filename = if index < 2
|
13
13
|
out_dir.join(out_file)
|
14
14
|
else
|
15
15
|
out_dir.join("#{out_file.basename('.*')} (#{index})#{out_file.extname}")
|
16
16
|
end
|
17
17
|
report.save_adoc(filename, overwrite: overwrite, author: adoc_author)
|
18
|
+
filename.to_s
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
data/lib/natour/gps_track.rb
CHANGED
@@ -71,10 +71,14 @@ module Natour
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def round_duration(duration, hours: 0, minutes: 0, seconds: 0)
|
74
|
+
return unless duration
|
75
|
+
|
74
76
|
Duration.new(round_multiple_of(duration.to_i, (hours * 60 + minutes) * 60 + seconds))
|
75
77
|
end
|
76
78
|
|
77
79
|
def round_time(time, hours: 0, minutes: 0, seconds: 0)
|
80
|
+
return unless time
|
81
|
+
|
78
82
|
Time.at(round_multiple_of(time.to_i, (hours * 60 + minutes) * 60 + seconds))
|
79
83
|
end
|
80
84
|
end
|
data/lib/natour/gpx_file.rb
CHANGED
@@ -1,26 +1,29 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
require 'duration'
|
3
|
-
require '
|
4
|
-
require 'time'
|
3
|
+
require 'timeliness'
|
5
4
|
|
6
5
|
module Natour
|
7
6
|
class GPXFile < GPSTrack
|
7
|
+
GPX_XMLNS = {
|
8
|
+
'xmlns' => 'http://www.topografix.com/GPX/1/1',
|
9
|
+
'xmlns:gpxtrkx' => 'http://www.garmin.com/xmlschemas/TrackStatsExtension/v1'
|
10
|
+
}.freeze
|
11
|
+
|
8
12
|
def initialize(filename)
|
9
13
|
@doc = Nokogiri.XML(File.read(filename, mode: 'r:utf-8'))
|
10
14
|
|
11
|
-
|
12
|
-
stats = @doc.at('/xmlns:gpx/xmlns:trk/xmlns:extensions/gpxtrkx:TrackStatsExtension')
|
15
|
+
stats = @doc.at('/xmlns:gpx/xmlns:trk/xmlns:extensions/gpxtrkx:TrackStatsExtension', GPX_XMLNS)
|
13
16
|
if stats
|
14
|
-
ascent = stats.at('./gpxtrkx:Ascent').text.to_i
|
15
|
-
descent = stats.at('./gpxtrkx:Descent').text.to_i
|
16
|
-
distance = stats.at('./gpxtrkx:Distance').text.to_i
|
17
|
-
duration = Duration.new(stats.at('./gpxtrkx:TotalElapsedTime').text.to_i)
|
17
|
+
ascent = stats.at('./gpxtrkx:Ascent', GPX_XMLNS).text.to_i
|
18
|
+
descent = stats.at('./gpxtrkx:Descent', GPX_XMLNS).text.to_i
|
19
|
+
distance = stats.at('./gpxtrkx:Distance', GPX_XMLNS).text.to_i
|
20
|
+
duration = Duration.new(stats.at('./gpxtrkx:TotalElapsedTime', GPX_XMLNS).text.to_i)
|
18
21
|
end
|
19
22
|
|
20
|
-
start_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[1]/xmlns:trkpt[1]'))
|
21
|
-
end_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[last()]/xmlns:trkpt[last()]'))
|
23
|
+
start_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[1]/xmlns:trkpt[1]', GPX_XMLNS))
|
24
|
+
end_point = to_track_point(@doc.at('/xmlns:gpx/xmlns:trk/xmlns:trkseg[last()]/xmlns:trkpt[last()]', GPX_XMLNS))
|
22
25
|
|
23
|
-
super(filename,
|
26
|
+
super(filename, start_point.time&.to_date, ascent, descent, distance, duration, start_point, end_point)
|
24
27
|
end
|
25
28
|
|
26
29
|
def to_gpx
|
@@ -33,8 +36,8 @@ module Natour
|
|
33
36
|
GPSTrackPoint.new(
|
34
37
|
trkpt['lat'].to_f,
|
35
38
|
trkpt['lon'].to_f,
|
36
|
-
trkpt.at('./xmlns:ele')
|
37
|
-
|
39
|
+
trkpt.at('./xmlns:ele')&.text&.to_f,
|
40
|
+
Timeliness.parse(trkpt.at('./xmlns:time')&.text)
|
38
41
|
)
|
39
42
|
end
|
40
43
|
end
|
data/lib/natour/image.rb
CHANGED
@@ -1,29 +1,54 @@
|
|
1
1
|
require 'vips'
|
2
2
|
require 'timeliness'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
3
5
|
|
4
6
|
module Natour
|
5
7
|
class Image
|
6
8
|
attr_reader :path
|
7
9
|
attr_reader :date_time
|
8
10
|
|
9
|
-
def initialize(path)
|
11
|
+
def initialize(path, image)
|
10
12
|
@path = path
|
11
|
-
image =
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@portrait = orientation[/^(\d) \(/, 1].to_i.between?(5, 8) if orientation
|
17
|
-
date_time = get_field.call('exif-ifd0-DateTime')
|
13
|
+
@image = image
|
14
|
+
@landscape = image.width >= image.height
|
15
|
+
orientation = get_field('exif-ifd0-Orientation')
|
16
|
+
@landscape = !@landscape if orientation && orientation[/^(\d) \(/, 1].to_i.between?(5, 8)
|
17
|
+
date_time = get_field('exif-ifd0-DateTime')
|
18
18
|
@date_time = Timeliness.parse(date_time[/^(.*?) \(/, 1], format: 'yyyy:mm:dd hh:nn:ss') if date_time
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
21
|
+
def self.load_file(filename)
|
22
|
+
Image.new(filename, Vips::Image.new_from_file(filename))
|
23
23
|
end
|
24
24
|
|
25
25
|
def landscape?
|
26
|
-
|
26
|
+
@landscape
|
27
|
+
end
|
28
|
+
|
29
|
+
def autorotate
|
30
|
+
Image.new(@path, @image.autorot)
|
31
|
+
end
|
32
|
+
|
33
|
+
def shrink_to(maxdim)
|
34
|
+
scale = maxdim / @image.size.max.to_f
|
35
|
+
image = if scale < 1.0
|
36
|
+
@image.resize(scale)
|
37
|
+
else
|
38
|
+
@image.copy
|
39
|
+
end
|
40
|
+
Image.new(@path, image)
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_as(filename)
|
44
|
+
FileUtils.mkdir_p(Pathname(filename).dirname)
|
45
|
+
StdoutUtils.suppress_output { @image.write_to_file(filename) }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def get_field(name)
|
51
|
+
@image.get(name) if @image.get_fields.include?(name)
|
27
52
|
end
|
28
53
|
end
|
29
54
|
end
|
data/lib/natour/report.rb
CHANGED
@@ -34,18 +34,22 @@ module Natour
|
|
34
34
|
path = Pathname(dir)
|
35
35
|
title = Pathname.pwd.basename.to_s.encode('utf-8')
|
36
36
|
.gsub(/^\d{4}-\d{2}-\d{2}( |_|-)?/, '')
|
37
|
-
images = Pathname.glob('**/*.{
|
38
|
-
.map { |filename| Image.
|
37
|
+
images = Pathname.glob('**/*.{[j|J][p|P][g|G],[j|J][p|P][e|E][g|G]}')
|
38
|
+
.map { |filename| Image.load_file(filename.to_s) }
|
39
39
|
.sort_by { |image| [image.date_time ? 0 : 1, image.date_time, image.path] }
|
40
40
|
species_lists =
|
41
|
-
Pathname.glob('**/*.{
|
41
|
+
Pathname.glob('**/*.{[c|C][s|S][v|V],[k|K][m|M][l|L]}')
|
42
42
|
.map { |filename| SpeciesList.load_file(filename.to_s) }
|
43
43
|
.flatten
|
44
44
|
.sort_by { |species_list| [species_list.type, species_list.date ? 0 : 1, species_list.date] }
|
45
45
|
gps_tracks = if track_formats.empty?
|
46
46
|
[]
|
47
47
|
else
|
48
|
-
|
48
|
+
track_patterns = { gpx: '[g|G][p|P][x|X]', fit: '[f|F][i|I][t|T]' }
|
49
|
+
track_pattern = track_formats.map { |track_format| track_patterns[track_format] }
|
50
|
+
.compact
|
51
|
+
.join(',')
|
52
|
+
Pathname.glob("**/*.{#{track_pattern}}")
|
49
53
|
.map { |filename| GPSTrack.load_file(filename.to_s) }
|
50
54
|
.sort_by { |gps_track| [gps_track.date, gps_track.path] }
|
51
55
|
end
|
@@ -58,7 +62,7 @@ module Natour
|
|
58
62
|
gps_track.save_gpx(track, overwrite: true)
|
59
63
|
filename = Pathname(gps_track.path).sub_ext('.jpg')
|
60
64
|
map.save_image(filename, tracks: [track], layers: map_layers)
|
61
|
-
Image.
|
65
|
+
Image.load_file(filename.to_s)
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
data/lib/natour/species_list.rb
CHANGED
@@ -24,9 +24,9 @@ module Natour
|
|
24
24
|
def self.load_file(filename)
|
25
25
|
block = IO.binread(filename, 128)
|
26
26
|
header = if block.unpack('CC') == [0xff, 0xfe]
|
27
|
-
block[2
|
27
|
+
block[2..].force_encoding('utf-16le').encode('utf-8')
|
28
28
|
elsif block.unpack('CCC') == [0xef, 0xbb, 0xbf]
|
29
|
-
block[3
|
29
|
+
block[3..].force_encoding('utf-8')
|
30
30
|
else
|
31
31
|
block
|
32
32
|
end
|
@@ -34,13 +34,20 @@ module Natour
|
|
34
34
|
case header
|
35
35
|
when /^Primary/
|
36
36
|
CSV.open(filename, 'r:windows-1252:utf-8', headers: true, liberal_parsing: true) do |csv|
|
37
|
-
date =
|
37
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
38
38
|
items = csv.map { |row| Species.new(row[1], row[0]) }
|
39
39
|
.sort_by(&:name_de).uniq
|
40
40
|
[SpeciesList.new(filename, date, :kosmos_vogelfuehrer, :birds, nil, nil, items)]
|
41
41
|
end
|
42
|
+
when /^Name/
|
43
|
+
CSV.open(filename, 'r:bom|utf-8', headers: true) do |csv|
|
44
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
45
|
+
items = csv.map { |row| Species.new(row[1], row[0]) }
|
46
|
+
.sort_by(&:name_de).uniq
|
47
|
+
[SpeciesList.new(filename, date, :birdlife_vogelfuehrer, :birds, nil, nil, items)]
|
48
|
+
end
|
42
49
|
when /^<\?xml.*?www\.ornitho\.ch/m
|
43
|
-
date =
|
50
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
44
51
|
doc = Nokogiri.XML(File.read(filename, mode: 'r:utf-8'))
|
45
52
|
folder = doc.at('/xmlns:kml/xmlns:Document/xmlns:Folder/xmlns:Folder/xmlns:Folder')
|
46
53
|
name = folder.at('./xmlns:name').text
|
@@ -49,16 +56,16 @@ module Natour
|
|
49
56
|
.map { |description| Species.new(*description.scan(/>([^&(]+)</).flatten.reverse) }
|
50
57
|
.sort_by(&:name_de).uniq
|
51
58
|
[SpeciesList.new(filename, date, :ornitho_ch, :birds, name, nil, items)]
|
52
|
-
when /^Favoriten/
|
59
|
+
when /^(Favoriten|NUMMER_FLORA)/
|
53
60
|
CSV.open(filename, 'r:bom|utf-8', col_sep: ';', skip_blanks: true) do |csv|
|
54
|
-
chunks = csv.reject { |row| row.count == 1
|
55
|
-
.
|
61
|
+
chunks = csv.reject { |row| row.count == 1 }
|
62
|
+
.map { |row| row[0] == 'NUMMER_FLORA' ? ['Favoriten'] : row }
|
56
63
|
.slice_before { |row| row.count == 1 || row.count == 3 }
|
57
64
|
.reject { |rows| rows.count == 1 }
|
58
65
|
chunks.map do |rows|
|
59
66
|
name, description = rows.shift
|
60
|
-
date =
|
61
|
-
items = rows.map { |row| Species.new(row[1]
|
67
|
+
date = DateUtils.parse(name, Pathname(filename).basename).compact.first
|
68
|
+
items = rows.map { |row| Species.new(BotanicalNameUtils.parse(row[1]), row[2]) }
|
62
69
|
.sort_by(&:name).uniq
|
63
70
|
SpeciesList.new(
|
64
71
|
filename,
|
@@ -73,9 +80,9 @@ module Natour
|
|
73
80
|
end
|
74
81
|
when /^obs_id/
|
75
82
|
CSV.open(filename, 'r:bom|utf-16le:utf-8', col_sep: "\t", headers: true) do |csv|
|
76
|
-
date =
|
83
|
+
date = DateUtils.parse(Pathname(filename).basename).compact.first
|
77
84
|
items = csv.select { |row| row[0] }
|
78
|
-
.map { |row| Species.new(row[11]
|
85
|
+
.map { |row| Species.new(BotanicalNameUtils.parse(row[11]), nil) }
|
79
86
|
.sort_by(&:name).uniq
|
80
87
|
[SpeciesList.new(filename, date, :info_flora, :plants, nil, nil, items)]
|
81
88
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Natour
|
2
|
+
module StdoutUtils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def suppress_output
|
6
|
+
orig_stdout = $stdout.clone
|
7
|
+
orig_stderr = $stderr.clone
|
8
|
+
$stdout.reopen(File.new(File::NULL, 'w'))
|
9
|
+
$stderr.reopen(File.new(File::NULL, 'w'))
|
10
|
+
yield
|
11
|
+
ensure
|
12
|
+
$stdout.reopen(orig_stdout)
|
13
|
+
$stderr.reopen(orig_stderr)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/natour.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
require 'natour/
|
2
|
-
require 'natour/
|
1
|
+
require 'natour/utils/botanical_name_utils'
|
2
|
+
require 'natour/utils/date_utils'
|
3
|
+
require 'natour/utils/stdout_utils'
|
3
4
|
require 'natour/convert'
|
4
5
|
require 'natour/create'
|
5
6
|
require 'natour/asciinurse'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: natour
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Gysi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: fit4ruby
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3.
|
75
|
+
version: '3.9'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3.
|
82
|
+
version: '3.9'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: nokogiri
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0.4'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: webrick
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.7'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.7'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: word_wrap
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -154,16 +168,16 @@ dependencies:
|
|
154
168
|
name: rubocop
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
|
-
- -
|
171
|
+
- - '='
|
158
172
|
- !ruby/object:Gem::Version
|
159
|
-
version: '1.
|
173
|
+
version: '1.25'
|
160
174
|
type: :development
|
161
175
|
prerelease: false
|
162
176
|
version_requirements: !ruby/object:Gem::Requirement
|
163
177
|
requirements:
|
164
|
-
- -
|
178
|
+
- - '='
|
165
179
|
- !ruby/object:Gem::Version
|
166
|
-
version: '1.
|
180
|
+
version: '1.25'
|
167
181
|
description:
|
168
182
|
email: simon.gysi@gmail.com
|
169
183
|
executables:
|
@@ -192,8 +206,6 @@ files:
|
|
192
206
|
- lib/natour/gps_track.rb
|
193
207
|
- lib/natour/gps_track_point.rb
|
194
208
|
- lib/natour/gpx_file.rb
|
195
|
-
- lib/natour/helpers/date_parser.rb
|
196
|
-
- lib/natour/helpers/suppress_output.rb
|
197
209
|
- lib/natour/image.rb
|
198
210
|
- lib/natour/map_geo_admin.rb
|
199
211
|
- lib/natour/public_transport.rb
|
@@ -201,7 +213,10 @@ files:
|
|
201
213
|
- lib/natour/species.rb
|
202
214
|
- lib/natour/species_list.rb
|
203
215
|
- lib/natour/station.rb
|
204
|
-
|
216
|
+
- lib/natour/utils/botanical_name_utils.rb
|
217
|
+
- lib/natour/utils/date_utils.rb
|
218
|
+
- lib/natour/utils/stdout_utils.rb
|
219
|
+
homepage: https://github.com/simongysi/natour
|
205
220
|
licenses:
|
206
221
|
- MIT
|
207
222
|
metadata:
|
@@ -216,7 +231,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
216
231
|
requirements:
|
217
232
|
- - ">="
|
218
233
|
- !ruby/object:Gem::Version
|
219
|
-
version: '2.
|
234
|
+
version: '2.6'
|
220
235
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
221
236
|
requirements:
|
222
237
|
- - ">="
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Natour
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def suppress_output
|
5
|
-
orig_stdout = $stdout.clone
|
6
|
-
orig_stderr = $stderr.clone
|
7
|
-
$stdout.reopen(File.new(File::NULL, 'w'))
|
8
|
-
$stderr.reopen(File.new(File::NULL, 'w'))
|
9
|
-
yield
|
10
|
-
ensure
|
11
|
-
$stdout.reopen(orig_stdout)
|
12
|
-
$stderr.reopen(orig_stderr)
|
13
|
-
end
|
14
|
-
end
|