broutes 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,152 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formats::Tcx do
4
+ describe "#load" do
5
+ before(:all) do
6
+ @file = open_file('single_lap.tcx')
7
+ @target = Formats::Tcx.new
8
+ @route = GeoRoute.new
9
+
10
+ @target.load(@file, @route)
11
+ end
12
+
13
+ it "sets the start point lat" do
14
+ @route.start_point.lat.should eq(52.94124)
15
+ end
16
+ it "sets the start point lon" do
17
+ @route.start_point.lon.should eq(-1.26039)
18
+ end
19
+ it "sets the total distance" do
20
+ @route.total_distance.should eq(76037)
21
+ end
22
+ it "sets the total ascent" do
23
+ @route.total_ascent.round.should eq(1203)
24
+ end
25
+ it "sets the total descent" do
26
+ @route.total_descent.round.should eq(1204)
27
+ end
28
+ it "sets the total time" do
29
+ @route.total_time.round.should eq(10631)
30
+ end
31
+ it "sets the started_at" do
32
+ @route.started_at.to_i.should eq(Time.new(2012, 3, 15, 21, 20, 38).to_i)
33
+ end
34
+ it "sets the ended_at" do
35
+ @route.ended_at.to_i.should eq(Time.new(2012, 3, 16, 00, 17, 49).to_i)
36
+ end
37
+ it "can create hash" do
38
+ @route.to_hash
39
+ end
40
+ end
41
+
42
+ describe "#load Garmin Training Centre" do
43
+ before(:all) do
44
+ @file = open_file('garmin_training_center.tcx')
45
+ @target = Formats::Tcx.new
46
+ @route = GeoRoute.new
47
+
48
+ @target.load(@file, @route)
49
+ end
50
+
51
+ it "sets the start point lat" do
52
+ @route.start_point.lat.should eq(52.930873)
53
+ end
54
+ it "sets the start point lon" do
55
+ @route.start_point.lon.should eq(-1.2236503)
56
+ end
57
+ it "extracts the heart rate" do
58
+ @route.start_point.heart_rate.should eq(77)
59
+ end
60
+ it "extracts the cadence" do
61
+ @route.start_point.cadence.should eq(85)
62
+ end
63
+ it "extracts the speed" do
64
+ @route.start_point.speed.should eq(11.3190002)
65
+ end
66
+ it "extracts the power" do
67
+ @route.start_point.power.should eq(297)
68
+ end
69
+ it "sets the total distance" do
70
+ @route.total_distance.should eq(43892)
71
+ end
72
+ it "sets the total ascent" do
73
+ @route.total_ascent.round.should eq(416)
74
+ end
75
+ it "sets the total descent" do
76
+ @route.total_descent.round.should eq(404)
77
+ end
78
+ it "sets the total time" do
79
+ @route.total_time.round.should eq(6926)
80
+ end
81
+ it "can create hash" do
82
+ @route.to_hash
83
+ end
84
+ end
85
+
86
+ describe "file without GPS coordinates" do
87
+ before(:all) do
88
+ @file = open_file('no_gps_coordinates.tcx')
89
+ @target = Formats::Tcx.new
90
+ @route = GeoRoute.new
91
+
92
+ @target.load(@file, @route)
93
+ end
94
+
95
+ it "sets the total time" do
96
+ @route.total_time.should eq(653)
97
+ end
98
+ it "sets the start point lat" do
99
+ @route.start_point.lat.should be_nil
100
+ end
101
+ it "sets the start point lon" do
102
+ @route.start_point.lon.should be_nil
103
+ end
104
+ it "sets the total distance" do
105
+ @route.total_distance.should eq(0)
106
+ end
107
+ it "sets the total ascent" do
108
+ @route.total_ascent.should eq(2.403564500000016)
109
+ end
110
+ it "sets the total descent" do
111
+ @route.total_descent.should eq(2.8841553000000033)
112
+ end
113
+ it "can create hash" do
114
+ @route.to_hash
115
+ end
116
+ end
117
+
118
+ describe "file without points only summary" do
119
+ before(:all) do
120
+ @file = open_file('summary_no_points.tcx')
121
+ @target = Formats::Tcx.new
122
+ @route = GeoRoute.new
123
+
124
+ @target.load(@file, @route)
125
+ end
126
+
127
+ it "sets the total time" do
128
+ @route.total_time.should eq(2490)
129
+ end
130
+ it "start_point should be nil" do
131
+ @route.start_point.should be_nil
132
+ end
133
+ it "sets the total distance" do
134
+ @route.total_distance.should eq(21146)
135
+ end
136
+ it "sets the total ascent" do
137
+ @route.total_ascent.should eq(0)
138
+ end
139
+ it "sets the total descent" do
140
+ @route.total_descent.should eq(0)
141
+ end
142
+ it "can create hash" do
143
+ @route.to_hash
144
+ end
145
+ it "sets the started_at" do
146
+ @route.started_at.to_i.should eq(DateTime.parse("2012-09-05T18:55:11Z").to_time.to_i)
147
+ end
148
+ it "include the started at in the hash" do
149
+ @route.to_hash['started_at'].should_not be_nil
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeoPoint do
4
+ describe "#to_hash" do
5
+ before(:each) do
6
+ @point = GeoPoint.new(lat: random_lat, lon: random_lon)
7
+ end
8
+
9
+ subject { @point.to_hash }
10
+
11
+ it "contains lat" do
12
+ subject['lat'].should eq(@point.lat)
13
+ end
14
+ it "contains lon" do
15
+ subject['lon'].should eq(@point.lon)
16
+ end
17
+
18
+ context "when only lat lon set" do
19
+ it "should not contain distance" do
20
+ subject.keys.should_not include('distance')
21
+ end
22
+ it "should not contain elevation" do
23
+ subject.keys.should_not include('elevation')
24
+ end
25
+ end
26
+ context "when elevation set" do
27
+ before(:each) do
28
+ @point.elevation = random_elevation
29
+ end
30
+ it "should contain elevation" do
31
+ subject['elevation'].should eq(@point.elevation)
32
+ end
33
+ end
34
+ context "when distance set" do
35
+ before(:each) do
36
+ @point.distance = random_distance
37
+ end
38
+ it "should contain distance" do
39
+ subject['distance'].should eq(@point.distance)
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#time=" do
45
+ let(:point) { GeoPoint.new }
46
+
47
+ subject { point.time = @value }
48
+
49
+ context "when parseable string" do
50
+ before(:each) do
51
+ @value = "2013-01-12T08:33:11Z"
52
+ end
53
+ it "should eq the time" do
54
+ subject
55
+ point.time.to_i.should eq(Time.utc(2013, 1, 12, 8, 33, 11).to_i)
56
+ end
57
+ end
58
+ context "when is a time" do
59
+ before(:each) do
60
+ @value = Time.new(2013, 4, 12, 12, 34, 45)
61
+ end
62
+ it "should eq the time" do
63
+ subject
64
+ point.time.to_i.should eq(@value.to_i)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+
3
+ describe GeoRoute do
4
+ describe "#add_point" do
5
+ before(:each) do
6
+ @route = GeoRoute.new
7
+ @lat = random_lat
8
+ @lon = random_lon
9
+ @elevation = 35.6000000
10
+ @new_point = GeoPoint.new(lat: @lat, lon: @lon, elevation: @elevation, distance: 0)
11
+ end
12
+
13
+ subject { @route.add_point(lat: @lat, lon: @lon, elevation: @elevation) }
14
+
15
+ context "when route is empty" do
16
+
17
+ it "sets the start point to the new_point" do
18
+ subject
19
+ @route.start_point.should eq(@new_point)
20
+ end
21
+ it "should set the total distance to zero" do
22
+ subject
23
+ @route.total_distance.should eq(0)
24
+ end
25
+ it "should add the start point to the points list" do
26
+ subject
27
+ @route.points.first.should eq(@route.start_point)
28
+ end
29
+ end
30
+ context "when route already has a start point" do
31
+ before(:each) do
32
+ @start_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: random_elevation, distance: 0)
33
+ @route.add_point(lat: @start_point.lat, lon: @start_point.lon, elevation: @start_point.elevation)
34
+ end
35
+
36
+ it "should not change start_point" do
37
+ subject
38
+ @route.start_point.should eq(@start_point)
39
+ end
40
+ it "should set the total distance to be haversine distance between the start_point and the new point" do
41
+ subject
42
+ @route.total_distance.should eq(Maths.haversine_distance(@start_point, @new_point).round)
43
+ end
44
+ it "set the distance of the point to be the haverside_distance between the start_point" do
45
+ subject
46
+ last(@route.points).distance.should eq(Maths.haversine_distance(@start_point, @new_point))
47
+ end
48
+ end
49
+
50
+ context "when route already has at least two points" do
51
+ before(:each) do
52
+ @start_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: random_elevation)
53
+ @next_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: random_elevation)
54
+ @route.add_point(lat: @start_point.lat, lon: @start_point.lon, elevation: @start_point.elevation)
55
+ @route.add_point(lat: @next_point.lat, lon: @next_point.lon, elevation: @next_point.elevation)
56
+ end
57
+ it "should set the total distance to haversine distance along all points" do
58
+ subject
59
+ @route.total_distance.should be_within(1).of(
60
+ Maths.haversine_distance(@start_point, @next_point).round +
61
+ Maths.haversine_distance(@next_point, @new_point).round
62
+ )
63
+ end
64
+ it "set the distance of the point to haversine distance along all points" do
65
+ subject
66
+ last(@route.points).distance.should eq(
67
+ Maths.haversine_distance(@start_point, @next_point) +
68
+ Maths.haversine_distance(@next_point, @new_point)
69
+ )
70
+ end
71
+ end
72
+ end
73
+ describe "#process_elevation_delta" do
74
+ before(:each) do
75
+ @route = GeoRoute.new
76
+ @next_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: random_elevation)
77
+ end
78
+
79
+ subject { @route.process_elevation_delta(@last_point, @next_point) }
80
+
81
+ context "when last_point is nil" do
82
+ it "has an total_ascent of nil" do
83
+ subject
84
+ @route.total_ascent.should eq(0)
85
+ end
86
+ it "has an total_descent of nil" do
87
+ subject
88
+ @route.total_descent.should eq(0)
89
+ end
90
+ end
91
+ context "when last_point is same elevation as next point" do
92
+ before(:each) do
93
+ @last_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: @next_point.elevation)
94
+ end
95
+ it "has an total_ascent of zero" do
96
+ subject
97
+ @route.total_ascent.should eq(0)
98
+ end
99
+ it "has an total_descent of zero" do
100
+ subject
101
+ @route.total_descent.should eq(0)
102
+ end
103
+ end
104
+ context "when last_point is lower than the next point" do
105
+ before(:each) do
106
+ @delta = random_elevation
107
+ @last_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: @next_point.elevation - @delta)
108
+ end
109
+ it "the delta is added to the total_ascent" do
110
+ subject
111
+ round_to(@route.total_ascent, 3).should eq(@delta)
112
+ end
113
+ it "has an total_descent of zero" do
114
+ subject
115
+ @route.total_descent.should eq(0)
116
+ end
117
+ end
118
+ context "when last_point is higher than the next point" do
119
+ before(:each) do
120
+ @delta = random_elevation
121
+ @last_point = GeoPoint.new(lat: random_lat, lon: random_lon, elevation: @next_point.elevation + @delta)
122
+ end
123
+ it "has an total_ascent of zero" do
124
+ subject
125
+ @route.total_ascent.should eq(0)
126
+ end
127
+ it "the delta is added to the total_descent" do
128
+ subject
129
+ round_to(@route.total_descent, 3).should eq(@delta)
130
+ end
131
+ end
132
+ end
133
+ describe "#hilliness" do
134
+ before(:each) do
135
+ @route = GeoRoute.new
136
+ end
137
+
138
+ subject { @route.hilliness }
139
+
140
+ context "when 1000 m ascent in 100km" do
141
+ before(:each) do
142
+ @route.stub(:total_distance) { 100000 }
143
+ @route.stub(:total_ascent) { 1000 }
144
+ end
145
+ it "is 10" do
146
+ subject.should eq(10)
147
+ end
148
+ end
149
+ context "when 0 ascent in 100km" do
150
+ before(:each) do
151
+ @route.stub(:total_distance) { 100000 }
152
+ @route.stub(:total_ascent) { 0 }
153
+ end
154
+ it "is 0" do
155
+ subject.should eq(0)
156
+ end
157
+ end
158
+ context "when 1000 ascent in 0km" do
159
+ before(:each) do
160
+ @route.stub(:total_distance) { 0 }
161
+ @route.stub(:total_ascent) { 1000 }
162
+ end
163
+ it "is 0" do
164
+ subject.should eq(0)
165
+ end
166
+ end
167
+ end
168
+
169
+ describe ".from_hash" do
170
+ let(:started_at) { Time.now }
171
+ let(:points) {[
172
+ GeoPoint.new(lat: random_lat, lon: random_lon, time: started_at),
173
+ GeoPoint.new(lat: random_lat, lon: random_lon, time: started_at + 1),
174
+ GeoPoint.new(lat: random_lat, lon: random_lon, time: started_at + 2)
175
+ ]}
176
+ let(:hash) {{
177
+ 'started_at' => started_at,
178
+ 'points' => points.collect { |p| p.to_hash }
179
+ }}
180
+
181
+ subject { GeoRoute.from_hash hash }
182
+
183
+ it "set the started_at" do
184
+ subject.started_at.to_i.should eq(started_at.to_i)
185
+ end
186
+ it "has the requisite number of points" do
187
+ subject.points.count.should eq(points.count)
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Maths do
4
+ describe ".haversine_distance" do
5
+ before(:each) do
6
+ @p1 = GeoPoint.new(lat: 39.06546, lon: -104.88544)
7
+ @p2 = GeoPoint.new(lat: 39.06546, lon: -104.80)
8
+ end
9
+
10
+ subject { Maths.haversine_distance( @p1, @p2 ) }
11
+
12
+ it "equals 7376.435 to 3dp" do
13
+ round_to(subject, 3).should eq(7376.435)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Broutes do
4
+ describe ".from_file" do
5
+ before(:all) do
6
+ @file = open_file('single_lap_gpx_track.gpx')
7
+ @route = Broutes.from_file(@file, 'single_lap_gpx_track.gpx')
8
+ end
9
+
10
+ it "sets the start point lat" do
11
+ @route.start_point.lat.should eq(52.9552055)
12
+ end
13
+ it "sets the start point lon" do
14
+ @route.start_point.lon.should eq(-1.1558583)
15
+ end
16
+ it "sets the total distance" do
17
+ @route.total_distance.should eq(7088)
18
+ end
19
+ it "sets the total ascent" do
20
+ @route.total_ascent.round.should eq(34)
21
+ end
22
+ it "sets the total descent" do
23
+ @route.total_descent.round.should eq(37)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ require 'rake'
2
+ require 'rspec'
3
+ require "#{Rake.application.original_dir}/lib/broutes"
4
+
5
+ include Broutes
6
+ Broutes.logger.level = Logger::FATAL
7
+
8
+ def random_lat
9
+ rand + rand(180)
10
+ end
11
+
12
+ def random_lon
13
+ rand
14
+ end
15
+
16
+ def random_integer
17
+ rand(100000).to_i
18
+ end
19
+
20
+ def random_elevation
21
+ round_to(rand + rand(999), 3)
22
+ end
23
+
24
+ def random_distance
25
+ round_to(rand + rand(999), 3)
26
+ end
27
+
28
+ def random_string
29
+ (0...24).map{ ('a'..'z').to_a[rand(26)] }.join
30
+ end
31
+
32
+ def round_to(number, decimal_places)
33
+ if number
34
+ if decimal_places > 0
35
+ ((number * 10**decimal_places).round.to_f / 10**decimal_places)
36
+ else
37
+ number.round
38
+ end
39
+ end
40
+ end
41
+
42
+ def last(enum)
43
+ enum.collect{|item| item}.reverse.first
44
+ end
45
+
46
+ def open_file(name)
47
+ File.open("#{Rake.application.original_dir}/spec/support/#{name}")
48
+ end