gooby 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +133 -341
- data/config/ballantyne.yaml +11 -0
- data/config/big_sur_marathon.yaml +11 -0
- data/config/crowders_mtn_hike.yaml +11 -0
- data/config/davidson1.yaml +16 -0
- data/config/gooby_config.yaml +28 -135
- data/cucumber.yml +1 -0
- data/features/build_gem.feature +88 -0
- data/features/gooby.feature +300 -0
- data/features/install.feature +78 -0
- data/features/steps/gooby_steps.rb +245 -0
- data/features/support/env.rb +4 -0
- data/lib/gooby.rb +24 -30
- data/lib/gooby_activity.rb +63 -0
- data/lib/gooby_base_object.rb +46 -0
- data/lib/gooby_base_sax_parser.rb +95 -0
- data/lib/gooby_configuration.rb +33 -115
- data/lib/gooby_counter_hash.rb +28 -87
- data/lib/gooby_dttm.rb +88 -66
- data/lib/gooby_environment.rb +48 -0
- data/lib/gooby_garmin_tcx_parser.rb +92 -0
- data/lib/gooby_google_kml_generator.rb +168 -0
- data/lib/gooby_google_map_generator.rb +284 -349
- data/lib/gooby_gpx_parser.rb +97 -0
- data/lib/gooby_help_producer.rb +40 -0
- data/lib/gooby_introspection.rb +25 -0
- data/lib/gooby_io.rb +30 -0
- data/lib/gooby_lap.rb +27 -18
- data/lib/gooby_process.rb +281 -0
- data/lib/gooby_sax_path_parser.rb +43 -0
- data/lib/gooby_tcx_extractor.rb +71 -0
- data/lib/gooby_track_log_parser.rb +114 -0
- data/lib/gooby_trackpoint.rb +276 -0
- data/lib/gooby_xml_object.rb +40 -0
- data/{img/gicons → out/images}/blank.png +0 -0
- data/{img/gicons → out/images}/dd-end.png +0 -0
- data/{img/gicons → out/images}/dd-start.png +0 -0
- data/{img/gicons → out/images}/marker.png +0 -0
- data/{img/gicons → out/images}/marker0.png +0 -0
- data/{img/gicons → out/images}/marker00.png +0 -0
- data/{img/gicons → out/images}/marker01.png +0 -0
- data/{img/gicons → out/images}/marker02.png +0 -0
- data/{img/gicons → out/images}/marker03.png +0 -0
- data/{img/gicons → out/images}/marker04.png +0 -0
- data/{img/gicons → out/images}/marker05.png +0 -0
- data/{img/gicons → out/images}/marker06.png +0 -0
- data/{img/gicons → out/images}/marker07.png +0 -0
- data/{img/gicons → out/images}/marker08.png +0 -0
- data/{img/gicons → out/images}/marker09.png +0 -0
- data/{img/gicons → out/images}/marker1.png +0 -0
- data/{img/gicons → out/images}/marker10.png +0 -0
- data/{img/gicons → out/images}/marker11.png +0 -0
- data/{img/gicons → out/images}/marker12.png +0 -0
- data/{img/gicons → out/images}/marker13.png +0 -0
- data/{img/gicons → out/images}/marker14.png +0 -0
- data/{img/gicons → out/images}/marker15.png +0 -0
- data/{img/gicons → out/images}/marker16.png +0 -0
- data/{img/gicons → out/images}/marker17.png +0 -0
- data/{img/gicons → out/images}/marker18.png +0 -0
- data/{img/gicons → out/images}/marker19.png +0 -0
- data/{img/gicons → out/images}/marker2.png +0 -0
- data/{img/gicons → out/images}/marker20.png +0 -0
- data/{img/gicons → out/images}/marker21.png +0 -0
- data/{img/gicons → out/images}/marker22.png +0 -0
- data/{img/gicons → out/images}/marker23.png +0 -0
- data/{img/gicons → out/images}/marker24.png +0 -0
- data/{img/gicons → out/images}/marker25.png +0 -0
- data/{img/gicons → out/images}/marker26.png +0 -0
- data/{img/gicons → out/images}/marker27.png +0 -0
- data/{img/gicons → out/images}/marker28.png +0 -0
- data/{img/gicons → out/images}/marker29.png +0 -0
- data/{img/gicons → out/images}/marker3.png +0 -0
- data/{img/gicons → out/images}/marker30.png +0 -0
- data/{img/gicons → out/images}/marker31.png +0 -0
- data/{img/gicons → out/images}/marker32.png +0 -0
- data/{img/gicons → out/images}/marker33.png +0 -0
- data/{img/gicons → out/images}/marker34.png +0 -0
- data/{img/gicons → out/images}/marker35.png +0 -0
- data/{img/gicons → out/images}/marker36.png +0 -0
- data/{img/gicons → out/images}/marker37.png +0 -0
- data/{img/gicons → out/images}/marker38.png +0 -0
- data/{img/gicons → out/images}/marker39.png +0 -0
- data/{img/gicons → out/images}/marker4.png +0 -0
- data/{img/gicons → out/images}/marker40.png +0 -0
- data/{img/gicons → out/images}/marker41.png +0 -0
- data/{img/gicons → out/images}/marker42.png +0 -0
- data/{img/gicons → out/images}/marker43.png +0 -0
- data/{img/gicons → out/images}/marker44.png +0 -0
- data/{img/gicons → out/images}/marker45.png +0 -0
- data/{img/gicons → out/images}/marker46.png +0 -0
- data/{img/gicons → out/images}/marker47.png +0 -0
- data/{img/gicons → out/images}/marker48.png +0 -0
- data/{img/gicons → out/images}/marker49.png +0 -0
- data/{img/gicons → out/images}/marker5.png +0 -0
- data/{img/gicons → out/images}/marker50.png +0 -0
- data/{img/gicons → out/images}/marker51.png +0 -0
- data/{img/gicons → out/images}/marker52.png +0 -0
- data/{img/gicons → out/images}/marker53.png +0 -0
- data/{img/gicons → out/images}/marker54.png +0 -0
- data/{img/gicons → out/images}/marker55.png +0 -0
- data/{img/gicons → out/images}/marker56.png +0 -0
- data/{img/gicons → out/images}/marker57.png +0 -0
- data/{img/gicons → out/images}/marker58.png +0 -0
- data/{img/gicons → out/images}/marker59.png +0 -0
- data/{img/gicons → out/images}/marker6.png +0 -0
- data/{img/gicons → out/images}/marker60.png +0 -0
- data/{img/gicons → out/images}/marker61.png +0 -0
- data/{img/gicons → out/images}/marker62.png +0 -0
- data/{img/gicons → out/images}/marker63.png +0 -0
- data/{img/gicons → out/images}/marker64.png +0 -0
- data/{img/gicons → out/images}/marker65.png +0 -0
- data/{img/gicons → out/images}/marker66.png +0 -0
- data/{img/gicons → out/images}/marker67.png +0 -0
- data/{img/gicons → out/images}/marker68.png +0 -0
- data/{img/gicons → out/images}/marker69.png +0 -0
- data/{img/gicons → out/images}/marker7.png +0 -0
- data/{img/gicons → out/images}/marker70.png +0 -0
- data/{img/gicons → out/images}/marker71.png +0 -0
- data/{img/gicons → out/images}/marker72.png +0 -0
- data/{img/gicons → out/images}/marker73.png +0 -0
- data/{img/gicons → out/images}/marker74.png +0 -0
- data/{img/gicons → out/images}/marker75.png +0 -0
- data/{img/gicons → out/images}/marker76.png +0 -0
- data/{img/gicons → out/images}/marker77.png +0 -0
- data/{img/gicons → out/images}/marker78.png +0 -0
- data/{img/gicons → out/images}/marker79.png +0 -0
- data/{img/gicons → out/images}/marker8.png +0 -0
- data/{img/gicons → out/images}/marker80.png +0 -0
- data/{img/gicons → out/images}/marker81.png +0 -0
- data/{img/gicons → out/images}/marker82.png +0 -0
- data/{img/gicons → out/images}/marker83.png +0 -0
- data/{img/gicons → out/images}/marker84.png +0 -0
- data/{img/gicons → out/images}/marker85.png +0 -0
- data/{img/gicons → out/images}/marker86.png +0 -0
- data/{img/gicons → out/images}/marker87.png +0 -0
- data/{img/gicons → out/images}/marker88.png +0 -0
- data/{img/gicons → out/images}/marker89.png +0 -0
- data/{img/gicons → out/images}/marker9.png +0 -0
- data/{img/gicons → out/images}/marker90.png +0 -0
- data/{img/gicons → out/images}/marker91.png +0 -0
- data/{img/gicons → out/images}/marker92.png +0 -0
- data/{img/gicons → out/images}/marker93.png +0 -0
- data/{img/gicons → out/images}/marker94.png +0 -0
- data/{img/gicons → out/images}/marker95.png +0 -0
- data/{img/gicons → out/images}/marker96.png +0 -0
- data/{img/gicons → out/images}/marker97.png +0 -0
- data/{img/gicons → out/images}/marker98.png +0 -0
- data/{img/gicons → out/images}/marker99.png +0 -0
- data/{img/gicons → out/images}/markerA.png +0 -0
- data/{img/gicons → out/images}/markerB.png +0 -0
- data/{img/gicons → out/images}/markerC.png +0 -0
- data/{img/gicons → out/images}/markerD.png +0 -0
- data/{img/gicons → out/images}/markerE.png +0 -0
- data/{img/gicons → out/images}/markerF.png +0 -0
- data/{img/gicons → out/images}/markerG.png +0 -0
- data/{img/gicons → out/images}/markerH.png +0 -0
- data/{img/gicons → out/images}/markerI.png +0 -0
- data/{img/gicons → out/images}/markerJ.png +0 -0
- data/{img/gicons → out/images}/mm_20_red.png +0 -0
- data/{img/gicons → out/images}/mm_20_shadow.png +0 -0
- data/{img/gicons → out/images}/shadow50.png +0 -0
- data/rakefile.rb +79 -0
- data/samples.sh +21 -0
- data/samples/2008_04_27_13_49_50_tcx.csv +2449 -0
- data/samples/2008_04_27_13_49_50_tcx.xml +24560 -0
- data/samples/2009_01_01_14_45_00_tcx.xml +10630 -0
- data/samples/ballantyne.csv +27 -0
- data/samples/ballantyne.gpx +117 -0
- data/samples/ballantyne.kml +91 -0
- data/samples/big_sur_marathon.html +2766 -0
- data/samples/big_sur_marathon.kml +685 -0
- data/samples/build_gem_test_results.txt +6 -0
- data/samples/crowders_mtn_hike.csv +1065 -0
- data/samples/crowders_mtn_hike.html +1283 -0
- data/samples/crowders_mtn_hike.log +1 -0
- data/samples/cucumber_test_results.txt +302 -0
- data/samples/davidson1.csv +1 -0
- data/samples/davidson1.html +75 -0
- data/samples/davidson_1_point_tcx.csv +0 -0
- data/samples/doc.kml +49 -0
- data/samples/gps_track_log_asheville_mt_pisgah.txt +1 -0
- data/samples/gps_track_logs.txt +1 -0
- data/samples/install_test_results.txt +81 -0
- data/samples/mt_pisgah.txt +1 -0
- data/samples/rspec_test_results.txt +5 -0
- data/setup.rb +66 -0
- data/spec/gooby_base_object_spec.rb +116 -0
- data/spec/gooby_counter_hash_spec.rb +34 -0
- data/spec/gooby_dttm_spec.rb +40 -0
- data/spec/gooby_spec_helper.rb +9 -0
- data/spec/gooby_xml_object_spec.rb +32 -0
- metadata +225 -226
- data/bin/code_scan.rb +0 -16
- data/bin/gooby_been_there.rb +0 -33
- data/bin/gooby_config.rb +0 -24
- data/bin/gooby_csv_validation.rb +0 -50
- data/bin/gooby_first_trackpoints_as_poi.rb +0 -31
- data/bin/gooby_gen_gmap.rb +0 -20
- data/bin/gooby_parser.rb +0 -21
- data/bin/gooby_splitter.rb +0 -21
- data/bin/gooby_version.rb +0 -20
- data/bin/run_all.sh +0 -33
- data/bin/run_been_there.sh +0 -19
- data/bin/run_config.sh +0 -12
- data/bin/run_csv_validation.sh +0 -15
- data/bin/run_db_gen.sh +0 -11
- data/bin/run_db_load.sh +0 -11
- data/bin/run_first_trackpoints_as_poi.sh +0 -16
- data/bin/run_gen_gmaps.sh +0 -21
- data/bin/run_parse_full.sh +0 -45
- data/bin/run_parse_samples.sh +0 -21
- data/bin/run_split.sh +0 -24
- data/bin/run_version.sh +0 -12
- data/data/20050305_corporate_cup_hm.csv +0 -251
- data/data/20050305_corporate_cup_hm.xml +0 -2208
- data/data/20050430_nashville_marathon.xml +0 -10043
- data/data/20050430_nashville_marathon_km.csv +0 -1208
- data/data/20060115_phoenix_marathon.csv +0 -1280
- data/data/20060115_phoenix_marathon.xml +0 -10620
- data/data/20070101_davidson_11m.csv +0 -251
- data/data/20070101_davidson_11m.xml +0 -2020
- data/data/20070505_davidson_5k.xml +0 -2875
- data/data/20070505_davidson_5k_km.csv +0 -286
- data/data/hrm1.csv +0 -5
- data/img/gicons/readme.txt +0 -14
- data/lib/gooby_code_scanner.rb +0 -288
- data/lib/gooby_command.rb +0 -210
- data/lib/gooby_course.rb +0 -117
- data/lib/gooby_csv_point.rb +0 -71
- data/lib/gooby_csv_reader.rb +0 -71
- data/lib/gooby_csv_run.rb +0 -28
- data/lib/gooby_delim_line.rb +0 -42
- data/lib/gooby_duration.rb +0 -86
- data/lib/gooby_forerunner_xml_parser.rb +0 -191
- data/lib/gooby_forerunner_xml_splitter.rb +0 -115
- data/lib/gooby_history.rb +0 -41
- data/lib/gooby_kernel.rb +0 -163
- data/lib/gooby_line.rb +0 -80
- data/lib/gooby_object.rb +0 -22
- data/lib/gooby_point.rb +0 -172
- data/lib/gooby_run.rb +0 -213
- data/lib/gooby_simple_xml_parser.rb +0 -50
- data/lib/gooby_test_helper.rb +0 -23
- data/lib/gooby_track.rb +0 -47
- data/lib/gooby_track_point.rb +0 -229
- data/lib/gooby_training_center_xml_parser.rb +0 -224
- data/lib/gooby_training_center_xml_splitter.rb +0 -116
- data/lib/split_code.sh +0 -29
- data/samples/20050305_corporate_cup_hm.html +0 -450
- data/samples/20050430_nashville_marathon.html +0 -1668
- data/samples/20060115_phoenix_marathon.html +0 -1596
- data/samples/20070101_davidson_11m.html +0 -432
- data/samples/20070505_davidson_5k.html +0 -413
- data/samples/been_there.txt +0 -92
- data/samples/hrm1.html +0 -87
- data/sql/gooby.ddl +0 -60
- data/sql/gooby_load.dml +0 -62
@@ -0,0 +1,43 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Gooby = Google APIs + Ruby. Copyright 2009 by Chris Joakim.
|
4
|
+
Gooby is available under GNU General Public License (GPL) license.
|
5
|
+
|
6
|
+
---
|
7
|
+
|
8
|
+
This class is used to explore the structure of large xml files which are
|
9
|
+
too large and deep to visually comprehend, such Garmin xml/tcx files.
|
10
|
+
|
11
|
+
=end
|
12
|
+
|
13
|
+
class GoobySaxPathParser < GoobyBaseSaxParser
|
14
|
+
|
15
|
+
attr_reader :counter
|
16
|
+
|
17
|
+
def subclass_initialize
|
18
|
+
@tags, @mappings, @counter = [], {}, GoobyCounterHash.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_start_element(name, attributes, prefix=nil, uri=nil, namespaces=nil)
|
22
|
+
@tags.push(name)
|
23
|
+
@counter.increment('on_start_element')
|
24
|
+
@counter.increment(current_path)
|
25
|
+
attributes.keys.each { | key | @counter.increment("#{current_path}@#{key}") }
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_end_element(name, prefix=nil, uri=nil)
|
29
|
+
@tags.pop
|
30
|
+
end
|
31
|
+
|
32
|
+
def current_path
|
33
|
+
@tags.join('|')
|
34
|
+
end
|
35
|
+
|
36
|
+
def display_structure
|
37
|
+
@counter.sorted_keys.each { | key |
|
38
|
+
count = @counter.value(key)
|
39
|
+
puts sprintf("%-9d %-100s", count, key)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Gooby = Google APIs + Ruby. Copyright 2009 by Chris Joakim.
|
4
|
+
Gooby is available under GNU General Public License (GPL) license.
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
class GoobyTcxExtractor < GoobyBaseObject
|
9
|
+
|
10
|
+
attr_reader :file, :out_dir, :lines, :files_written, :files_extracted_info
|
11
|
+
|
12
|
+
def extract(file, out_dir)
|
13
|
+
@file, @out_dir, @files_written, @files_extracted_info = file, out_dir, 0, {}
|
14
|
+
|
15
|
+
puts "GoobyTcxExtractor - file: #{@file} out_dir: #{@out_dir}"
|
16
|
+
@lines = read_file_as_lines(@file)
|
17
|
+
puts "file has been read; line count: #{lines_read}"
|
18
|
+
current_activity_start_index, current_activity_lines, current_id = 0, [], ''
|
19
|
+
|
20
|
+
@lines.each_with_index { | line, index |
|
21
|
+
if line.match('<Activity')
|
22
|
+
current_activity_start_index = index
|
23
|
+
current_activity_lines, current_id = [], ''
|
24
|
+
current_activity_lines << xml_prolog_line
|
25
|
+
current_activity_lines << root_xml_tag
|
26
|
+
current_activity_lines << ' <Activities>'
|
27
|
+
current_activity_lines << ' <!-- comment placeholder -->'
|
28
|
+
end
|
29
|
+
current_activity_lines << line.rstrip
|
30
|
+
if line.match('<Id') && (index == (current_activity_start_index + 1))
|
31
|
+
current_id = scrub_id(line.strip)
|
32
|
+
end
|
33
|
+
if line.match('</Activity')
|
34
|
+
current_activity_lines << ' </Activities>'
|
35
|
+
current_activity_lines << '</TrainingCenterDatabase>'
|
36
|
+
write_activity_file(current_activity_lines, current_id, current_activity_start_index)
|
37
|
+
current_activity_lines = []
|
38
|
+
ObjectSpace.garbage_collect
|
39
|
+
end
|
40
|
+
}
|
41
|
+
puts "files written: #{@files_written}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def lines_read
|
45
|
+
@lines.size
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def write_activity_file(lines, id, start_idx)
|
51
|
+
filename = "#{@out_dir}/#{id}_tcx.xml"
|
52
|
+
lines[3] = " <!-- Activity Id: #{id} Extracted by Gooby on #{Time.now} from Garmin tcx file #{@file} -->"
|
53
|
+
write_lines(filename, lines)
|
54
|
+
@files_written = @files_written + 1
|
55
|
+
@files_extracted_info[filename] = "lines: #{lines.size} start_idx: #{start_idx}"
|
56
|
+
puts sprintf("file written: %-50s lines: %-7d start_index: %d", filename, lines.size, start_idx)
|
57
|
+
end
|
58
|
+
|
59
|
+
def scrub_id(id)
|
60
|
+
id.tr('-:TZ<>','___ ').strip.split[1].strip # 2007-03-03T15:58:57Z
|
61
|
+
end
|
62
|
+
|
63
|
+
def xml_prolog_line
|
64
|
+
'<?xml version="1.0" encoding="UTF-8" standalone="no" ?>'
|
65
|
+
end
|
66
|
+
|
67
|
+
def root_xml_tag
|
68
|
+
'<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd">'
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Gooby = Google APIs + Ruby. Copyright 2009 by Chris Joakim.
|
4
|
+
Gooby is available under GNU General Public License (GPL) license.
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
class GoobyTracksLogParser < GoobyBaseObject
|
9
|
+
|
10
|
+
attr_reader :logs_file, :trackpoints
|
11
|
+
|
12
|
+
def parse(logs_file)
|
13
|
+
@logs_file, @trackpoints = logs_file, []
|
14
|
+
@log_lines = IO.readlines(@logs_file, "\r") # funky line ends on this file; not \n
|
15
|
+
puts "#{@log_lines.size} lines read from file #{@logs_file}"
|
16
|
+
parse_trackpoints
|
17
|
+
post_process_trackpoints
|
18
|
+
# @current_trackpoint = GoobyTrackpoint.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_trackpoints
|
22
|
+
|
23
|
+
# The input file looks like the following:
|
24
|
+
# Format: DDD M/D/Y H:M:S -5.00 hrs Datum[116]: WGS 84
|
25
|
+
# ID Date Time Latitude Longitude Altitude
|
26
|
+
# L ACTIVE LOG
|
27
|
+
# T 11/16/2008 08:43:06.000 35.21357 -81.29359 262.6
|
28
|
+
# T 11/16/2008 08:44:13.000 35.21363 -81.29353 265.0
|
29
|
+
# T 11/16/2008 08:44:16.000 35.21366 -81.29349 262.6
|
30
|
+
|
31
|
+
sequence = 0
|
32
|
+
@log_lines.each { | line |
|
33
|
+
tokens = line.split
|
34
|
+
if (tokens.size > 5) && (tokens[0] == 'T')
|
35
|
+
sequence = sequence + 1
|
36
|
+
mmddccyy = tokens[1].strip
|
37
|
+
time = tokens[2].strip
|
38
|
+
latitude = tokens[3].strip
|
39
|
+
longitude = tokens[4].strip
|
40
|
+
altitude = tokens[5].strip
|
41
|
+
tkpt = GoobyTrackpoint.new
|
42
|
+
tkpt.set('ActivityId', '')
|
43
|
+
tkpt.set('LapStartTime', '')
|
44
|
+
tkpt.set('LapSeq', '1')
|
45
|
+
tkpt.set('Seq', sequence)
|
46
|
+
tkpt.set('Time', reformatDateTime(mmddccyy, time))
|
47
|
+
tkpt.set('ElapsedTime', '')
|
48
|
+
tkpt.set('LatitudeDegrees', latitude)
|
49
|
+
tkpt.set('LongitudeDegrees', longitude)
|
50
|
+
tkpt.set('AltitudeMeters', altitude.to_f / METERS_PER_FOOT)
|
51
|
+
tkpt.set('Distance', '')
|
52
|
+
tkpt.set('Pace', '')
|
53
|
+
tkpt.set('MPH', '')
|
54
|
+
@trackpoints << tkpt
|
55
|
+
end
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def reformatDate(mmddccyy)
|
60
|
+
date_tokens = mmddccyy.split('/')
|
61
|
+
"#{date_tokens[2]}-#{date_tokens[0]}-#{date_tokens[1]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return a String value in this format: 2007-03-03T15:58:57Z
|
65
|
+
def reformatDateTime(mmddccyy, time)
|
66
|
+
time_tokens = time.split('.')
|
67
|
+
"#{reformatDate(mmddccyy)}T#{time_tokens[0]}Z"
|
68
|
+
end
|
69
|
+
|
70
|
+
def post_process_trackpoints
|
71
|
+
# Trackpoint,"","","","",2008-11-16T08:43:06Z,"",35.21357,-81.29359,262.6,0.0,"",""
|
72
|
+
# set('ActivityId', row[1])
|
73
|
+
# set('LapStartTime', row[2])
|
74
|
+
# set('LapSeq', row[3])
|
75
|
+
# set('Seq', row[4])
|
76
|
+
# set('Time', row[5])
|
77
|
+
# set('ElapsedTime', row[6])
|
78
|
+
# set('LatitudeDegrees', row[7])
|
79
|
+
# set('LongitudeDegrees', row[8])
|
80
|
+
# set('AltitudeMeters', row[9])
|
81
|
+
# set('Distance', row[10])
|
82
|
+
# set('Pace', row[11])
|
83
|
+
# set('MPH', row[12])
|
84
|
+
|
85
|
+
cumulative_distance, first_tkpt_dttm, prev_tkpt = 0.0, nil, nil
|
86
|
+
if @trackpoints.size > 0
|
87
|
+
activity_id = @trackpoints[0].time
|
88
|
+
else
|
89
|
+
return
|
90
|
+
end
|
91
|
+
@trackpoints.each { | tkpt |
|
92
|
+
tkpt.set('ActivityId', activity_id)
|
93
|
+
tkpt.set('LapStartTime', activity_id)
|
94
|
+
if prev_tkpt
|
95
|
+
incremental_distance = tkpt.proximity(prev_tkpt)
|
96
|
+
cumulative_distance = cumulative_distance + incremental_distance
|
97
|
+
tkpt.set('Distance', cumulative_distance)
|
98
|
+
else
|
99
|
+
first_tkpt_dttm = tkpt.dttm
|
100
|
+
tkpt.set('Distance', 0.0)
|
101
|
+
end
|
102
|
+
tkpt.compute_elapsed_time(first_tkpt_dttm)
|
103
|
+
tkpt.compute_cumulative_pace_and_mph(first_tkpt_dttm)
|
104
|
+
prev_tkpt = tkpt
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def trackpoints_to_csv
|
109
|
+
lines = []
|
110
|
+
@trackpoints.each { | trackpoint | lines << trackpoint.to_csv }
|
111
|
+
lines
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Gooby = Google APIs + Ruby. Copyright 2009 by Chris Joakim.
|
4
|
+
Gooby is available under GNU General Public License (GPL) license.
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
class GoobyTrackpoint < GoobyXmlObject
|
9
|
+
|
10
|
+
def time
|
11
|
+
get('Time')
|
12
|
+
end
|
13
|
+
|
14
|
+
def dttm
|
15
|
+
GoobyDtTm.new(time)
|
16
|
+
end
|
17
|
+
|
18
|
+
def latitude
|
19
|
+
get('LatitudeDegrees').to_f
|
20
|
+
end
|
21
|
+
|
22
|
+
def longitude
|
23
|
+
get('LongitudeDegrees').to_f
|
24
|
+
end
|
25
|
+
|
26
|
+
def altitude
|
27
|
+
altitude_meters * METERS_PER_FOOT
|
28
|
+
end
|
29
|
+
|
30
|
+
def altitude_rounded
|
31
|
+
sprintf("%5.1f", altitude)
|
32
|
+
end
|
33
|
+
|
34
|
+
def altitude_meters
|
35
|
+
get('AltitudeMeters').to_f
|
36
|
+
end
|
37
|
+
|
38
|
+
def dump
|
39
|
+
puts to_csv
|
40
|
+
end
|
41
|
+
|
42
|
+
def activity_id
|
43
|
+
get('ActivityId')
|
44
|
+
end
|
45
|
+
|
46
|
+
def lap_seq
|
47
|
+
get('LapSeq')
|
48
|
+
end
|
49
|
+
|
50
|
+
def lap_start_time
|
51
|
+
get('LapStartTime')
|
52
|
+
end
|
53
|
+
|
54
|
+
def distance
|
55
|
+
get('Distance').to_f
|
56
|
+
end
|
57
|
+
|
58
|
+
def distance_rounded
|
59
|
+
sprintf("%3.3f", distance)
|
60
|
+
end
|
61
|
+
|
62
|
+
def pace
|
63
|
+
get('Pace')
|
64
|
+
end
|
65
|
+
|
66
|
+
def mph
|
67
|
+
get('MPH')
|
68
|
+
end
|
69
|
+
|
70
|
+
def elapsed_time
|
71
|
+
get('ElapsedTime')
|
72
|
+
end
|
73
|
+
|
74
|
+
def degrees_diff(another_tkpt)
|
75
|
+
if another_tkpt
|
76
|
+
lat_diff = latitude - another_tkpt.latitude
|
77
|
+
lng_diff = longitude - another_tkpt.longitude
|
78
|
+
lat_diff.abs + lng_diff.abs
|
79
|
+
else
|
80
|
+
360
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def same_location?(another_tkpt)
|
85
|
+
if another_tkpt
|
86
|
+
return false if latitude != another_tkpt.latitude
|
87
|
+
return false if longitude != another_tkpt.longitude
|
88
|
+
true
|
89
|
+
else
|
90
|
+
false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def proximity(another_tkpt, uom='m')
|
95
|
+
if same_location?(another_tkpt)
|
96
|
+
return 0.0
|
97
|
+
end
|
98
|
+
if another_tkpt
|
99
|
+
arg1 = latitude
|
100
|
+
arg2 = another_tkpt.latitude
|
101
|
+
arg3 = latitude
|
102
|
+
arg4 = another_tkpt.latitude
|
103
|
+
theta = longitude - another_tkpt.longitude
|
104
|
+
res1 = Math.sin(deg2rad(arg1))
|
105
|
+
res2 = Math.sin(deg2rad(arg2))
|
106
|
+
res3 = Math.cos(deg2rad(arg3))
|
107
|
+
res4 = Math.cos(deg2rad(arg4))
|
108
|
+
res5 = Math.cos(deg2rad(theta.to_f))
|
109
|
+
dist = ((res1 * res2) + (res3 * res4 * res5)).to_f
|
110
|
+
# puts "proximity #{another_tkpt.sequence} a1: #{arg1} a2: #{arg2} a3: #{arg3} a4: #{arg4} t: #{theta} r1: #{res1} r2: #{res2} r3: #{res3} r4: #{res4} r5: #{res5} #{dist}"
|
111
|
+
if !dist.nan?
|
112
|
+
dist = Math.acos(dist.to_f)
|
113
|
+
if (!dist.nan?)
|
114
|
+
dist = rad2deg(dist)
|
115
|
+
if !dist.nan?
|
116
|
+
dist = dist * 60.0 * 1.1515;
|
117
|
+
if !dist.nan?
|
118
|
+
if uom == "km"
|
119
|
+
dist = dist * 1.609344;
|
120
|
+
elsif uom == "n"
|
121
|
+
dist = dist * 0.8684;
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
return dist.to_f
|
127
|
+
else
|
128
|
+
return 0.0
|
129
|
+
end
|
130
|
+
else
|
131
|
+
return 0.0
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def deg2rad(degrees)
|
136
|
+
(((0.0 + degrees.to_f) * Math::PI) / 180.0)
|
137
|
+
end
|
138
|
+
|
139
|
+
def rad2deg(radians)
|
140
|
+
(((0.0 + radians.to_f) * 180.0) / Math::PI)
|
141
|
+
end
|
142
|
+
|
143
|
+
def compute_elapsed_time(first_tkpt_dttm)
|
144
|
+
set('ElapsedTime', dttm.hhmmss_diff(first_tkpt_dttm))
|
145
|
+
end
|
146
|
+
|
147
|
+
def compute_cumulative_pace_and_mph(first_tkpt_dttm)
|
148
|
+
if distance > 0.0
|
149
|
+
secs_diff = dttm.seconds_diff(first_tkpt_dttm)
|
150
|
+
secs_mile = ((secs_diff.to_f) / distance)
|
151
|
+
mins_mile = (secs_mile / 60.0)
|
152
|
+
whole_mins = mins_mile.floor
|
153
|
+
fract_mins = mins_mile - (whole_mins.to_f)
|
154
|
+
fract_secs = fract_mins * 60.0
|
155
|
+
if fract_secs < 10
|
156
|
+
pace = sprintf("%d:0%2.2f", whole_mins, fract_secs)
|
157
|
+
else
|
158
|
+
pace = sprintf("%d:%2.2f", whole_mins, fract_secs)
|
159
|
+
end
|
160
|
+
set('Pace', pace)
|
161
|
+
hours = secs_diff / 3600.0
|
162
|
+
mph = sprintf("%5.3f", distance / hours)
|
163
|
+
set('MPH', sprintf("%5.3f", mph))
|
164
|
+
else
|
165
|
+
set('Pace', '0:00')
|
166
|
+
set('MPH', '0.00')
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def from_csv(row)
|
171
|
+
if row && row.size > 12
|
172
|
+
set('ActivityId', row[1])
|
173
|
+
set('LapStartTime', row[2])
|
174
|
+
set('LapSeq', row[3])
|
175
|
+
set('Seq', row[4])
|
176
|
+
set('Time', row[5])
|
177
|
+
set('ElapsedTime', row[6])
|
178
|
+
set('LatitudeDegrees', row[7])
|
179
|
+
set('LongitudeDegrees', row[8])
|
180
|
+
set('AltitudeMeters', row[9])
|
181
|
+
set('Distance', row[10])
|
182
|
+
set('Pace', row[11])
|
183
|
+
set('MPH', row[12])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def to_csv
|
188
|
+
csv_string = FasterCSV.generate do | csv |
|
189
|
+
csv << ['Trackpoint', activity_id, lap_start_time, lap_seq, sequence, time, elapsed_time, latitude, longitude, altitude, distance, pace, mph ]
|
190
|
+
end
|
191
|
+
csv_string.strip
|
192
|
+
end
|
193
|
+
|
194
|
+
def as_glatlng(comment_out, gen_comments, tkpt_count, curr_idx, start_dttm)
|
195
|
+
comment_out ? comment = '// ' : comment = ''
|
196
|
+
"\n #{comment}points.push(new GLatLng(#{latitude},#{longitude})); "
|
197
|
+
end
|
198
|
+
|
199
|
+
def split_info(a_dttm)
|
200
|
+
# if split?
|
201
|
+
# hhmmss = ''
|
202
|
+
# if @prev_split
|
203
|
+
# return "#{@split} #{dttm.hhmmss_diff(@prev_split.dttm())}"
|
204
|
+
# else
|
205
|
+
# return "#{@split} #{dttm.hhmmss_diff(a_dttm)}"
|
206
|
+
# end
|
207
|
+
# else
|
208
|
+
# ""
|
209
|
+
# end
|
210
|
+
''
|
211
|
+
end
|
212
|
+
|
213
|
+
def split?
|
214
|
+
false
|
215
|
+
end
|
216
|
+
|
217
|
+
def as_one_point_info_window_html(label=nil)
|
218
|
+
td_style="style='padding-left:12px;padding-right:1px;'"
|
219
|
+
s = "\"<table align='left'>"
|
220
|
+
s << "<tr><td colspan='2'><b>#{label}</b></td></tr>" if label
|
221
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_latutude')
|
222
|
+
s << "<tr><td>Latitude: </td><td #{td_style}>#{latitude}</td></tr>"
|
223
|
+
end
|
224
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_longitude')
|
225
|
+
s << "<tr><td>Longitude: </td><td #{td_style}>#{longitude}</td></tr>"
|
226
|
+
end
|
227
|
+
s << "</table>\""
|
228
|
+
s
|
229
|
+
end
|
230
|
+
|
231
|
+
def as_quoted_info_window_html(checkpoint, start_dttm)
|
232
|
+
"\"#{as_info_window_html(checkpoint, start_dttm)}\""
|
233
|
+
end
|
234
|
+
|
235
|
+
def as_info_window_html(checkpoint, start_dttm)
|
236
|
+
s = "<table align='left'>"
|
237
|
+
if checkpoint
|
238
|
+
secs_diff = dttm.seconds_diff(start_dttm)
|
239
|
+
fmt_time = dttm.hhmmss_diff(start_dttm)
|
240
|
+
td_style="style='padding-left:12px;padding-right:1px;'"
|
241
|
+
if checkpoint.to_i == 0
|
242
|
+
s << "<tr><td colspan='2'><b>Start!</b></td></tr>"
|
243
|
+
elsif checkpoint.to_i == 999999
|
244
|
+
s << "<tr><td colspan='2'><b>Finish!</b></td></tr>"
|
245
|
+
else
|
246
|
+
s << "<tr><td colspan='2'><b>Mile #{checkpoint}</b></td></tr>"
|
247
|
+
end
|
248
|
+
|
249
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_distance')
|
250
|
+
s << "<tr><td>Distance: </td><td #{td_style}>#{distance_rounded}</td></tr>"
|
251
|
+
end
|
252
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_elapsed_time')
|
253
|
+
s << "<tr><td>Elapsed Time: </td><td #{td_style}>#{elapsed_time}</td></tr>"
|
254
|
+
end
|
255
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_average_pace')
|
256
|
+
s << "<tr><td>Average Pace: </td><td #{td_style}>#{pace}</td></tr>"
|
257
|
+
end
|
258
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_average_mph')
|
259
|
+
s << "<tr><td>Average MPH: </td><td #{td_style}>#{mph}</td></tr>"
|
260
|
+
end
|
261
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_latutude')
|
262
|
+
s << "<tr><td>Latitude: </td><td #{td_style}>#{latitude}</td></tr>"
|
263
|
+
end
|
264
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_longitude')
|
265
|
+
s << "<tr><td>Longitude: </td><td #{td_style}>#{longitude}</td></tr>"
|
266
|
+
end
|
267
|
+
if GoobyBaseObject.boolean_config_value('gmap_info_window_altitude')
|
268
|
+
s << "<tr><td>Altitude: </td><td #{td_style}>#{altitude_rounded}</td></tr>"
|
269
|
+
end
|
270
|
+
s
|
271
|
+
end
|
272
|
+
s << "</table>"
|
273
|
+
s
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|