gooby 1.2.0 → 2.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.
Files changed (257) hide show
  1. data/README +133 -341
  2. data/config/ballantyne.yaml +11 -0
  3. data/config/big_sur_marathon.yaml +11 -0
  4. data/config/crowders_mtn_hike.yaml +11 -0
  5. data/config/davidson1.yaml +16 -0
  6. data/config/gooby_config.yaml +28 -135
  7. data/cucumber.yml +1 -0
  8. data/features/build_gem.feature +88 -0
  9. data/features/gooby.feature +300 -0
  10. data/features/install.feature +78 -0
  11. data/features/steps/gooby_steps.rb +245 -0
  12. data/features/support/env.rb +4 -0
  13. data/lib/gooby.rb +24 -30
  14. data/lib/gooby_activity.rb +63 -0
  15. data/lib/gooby_base_object.rb +46 -0
  16. data/lib/gooby_base_sax_parser.rb +95 -0
  17. data/lib/gooby_configuration.rb +33 -115
  18. data/lib/gooby_counter_hash.rb +28 -87
  19. data/lib/gooby_dttm.rb +88 -66
  20. data/lib/gooby_environment.rb +48 -0
  21. data/lib/gooby_garmin_tcx_parser.rb +92 -0
  22. data/lib/gooby_google_kml_generator.rb +168 -0
  23. data/lib/gooby_google_map_generator.rb +284 -349
  24. data/lib/gooby_gpx_parser.rb +97 -0
  25. data/lib/gooby_help_producer.rb +40 -0
  26. data/lib/gooby_introspection.rb +25 -0
  27. data/lib/gooby_io.rb +30 -0
  28. data/lib/gooby_lap.rb +27 -18
  29. data/lib/gooby_process.rb +281 -0
  30. data/lib/gooby_sax_path_parser.rb +43 -0
  31. data/lib/gooby_tcx_extractor.rb +71 -0
  32. data/lib/gooby_track_log_parser.rb +114 -0
  33. data/lib/gooby_trackpoint.rb +276 -0
  34. data/lib/gooby_xml_object.rb +40 -0
  35. data/{img/gicons → out/images}/blank.png +0 -0
  36. data/{img/gicons → out/images}/dd-end.png +0 -0
  37. data/{img/gicons → out/images}/dd-start.png +0 -0
  38. data/{img/gicons → out/images}/marker.png +0 -0
  39. data/{img/gicons → out/images}/marker0.png +0 -0
  40. data/{img/gicons → out/images}/marker00.png +0 -0
  41. data/{img/gicons → out/images}/marker01.png +0 -0
  42. data/{img/gicons → out/images}/marker02.png +0 -0
  43. data/{img/gicons → out/images}/marker03.png +0 -0
  44. data/{img/gicons → out/images}/marker04.png +0 -0
  45. data/{img/gicons → out/images}/marker05.png +0 -0
  46. data/{img/gicons → out/images}/marker06.png +0 -0
  47. data/{img/gicons → out/images}/marker07.png +0 -0
  48. data/{img/gicons → out/images}/marker08.png +0 -0
  49. data/{img/gicons → out/images}/marker09.png +0 -0
  50. data/{img/gicons → out/images}/marker1.png +0 -0
  51. data/{img/gicons → out/images}/marker10.png +0 -0
  52. data/{img/gicons → out/images}/marker11.png +0 -0
  53. data/{img/gicons → out/images}/marker12.png +0 -0
  54. data/{img/gicons → out/images}/marker13.png +0 -0
  55. data/{img/gicons → out/images}/marker14.png +0 -0
  56. data/{img/gicons → out/images}/marker15.png +0 -0
  57. data/{img/gicons → out/images}/marker16.png +0 -0
  58. data/{img/gicons → out/images}/marker17.png +0 -0
  59. data/{img/gicons → out/images}/marker18.png +0 -0
  60. data/{img/gicons → out/images}/marker19.png +0 -0
  61. data/{img/gicons → out/images}/marker2.png +0 -0
  62. data/{img/gicons → out/images}/marker20.png +0 -0
  63. data/{img/gicons → out/images}/marker21.png +0 -0
  64. data/{img/gicons → out/images}/marker22.png +0 -0
  65. data/{img/gicons → out/images}/marker23.png +0 -0
  66. data/{img/gicons → out/images}/marker24.png +0 -0
  67. data/{img/gicons → out/images}/marker25.png +0 -0
  68. data/{img/gicons → out/images}/marker26.png +0 -0
  69. data/{img/gicons → out/images}/marker27.png +0 -0
  70. data/{img/gicons → out/images}/marker28.png +0 -0
  71. data/{img/gicons → out/images}/marker29.png +0 -0
  72. data/{img/gicons → out/images}/marker3.png +0 -0
  73. data/{img/gicons → out/images}/marker30.png +0 -0
  74. data/{img/gicons → out/images}/marker31.png +0 -0
  75. data/{img/gicons → out/images}/marker32.png +0 -0
  76. data/{img/gicons → out/images}/marker33.png +0 -0
  77. data/{img/gicons → out/images}/marker34.png +0 -0
  78. data/{img/gicons → out/images}/marker35.png +0 -0
  79. data/{img/gicons → out/images}/marker36.png +0 -0
  80. data/{img/gicons → out/images}/marker37.png +0 -0
  81. data/{img/gicons → out/images}/marker38.png +0 -0
  82. data/{img/gicons → out/images}/marker39.png +0 -0
  83. data/{img/gicons → out/images}/marker4.png +0 -0
  84. data/{img/gicons → out/images}/marker40.png +0 -0
  85. data/{img/gicons → out/images}/marker41.png +0 -0
  86. data/{img/gicons → out/images}/marker42.png +0 -0
  87. data/{img/gicons → out/images}/marker43.png +0 -0
  88. data/{img/gicons → out/images}/marker44.png +0 -0
  89. data/{img/gicons → out/images}/marker45.png +0 -0
  90. data/{img/gicons → out/images}/marker46.png +0 -0
  91. data/{img/gicons → out/images}/marker47.png +0 -0
  92. data/{img/gicons → out/images}/marker48.png +0 -0
  93. data/{img/gicons → out/images}/marker49.png +0 -0
  94. data/{img/gicons → out/images}/marker5.png +0 -0
  95. data/{img/gicons → out/images}/marker50.png +0 -0
  96. data/{img/gicons → out/images}/marker51.png +0 -0
  97. data/{img/gicons → out/images}/marker52.png +0 -0
  98. data/{img/gicons → out/images}/marker53.png +0 -0
  99. data/{img/gicons → out/images}/marker54.png +0 -0
  100. data/{img/gicons → out/images}/marker55.png +0 -0
  101. data/{img/gicons → out/images}/marker56.png +0 -0
  102. data/{img/gicons → out/images}/marker57.png +0 -0
  103. data/{img/gicons → out/images}/marker58.png +0 -0
  104. data/{img/gicons → out/images}/marker59.png +0 -0
  105. data/{img/gicons → out/images}/marker6.png +0 -0
  106. data/{img/gicons → out/images}/marker60.png +0 -0
  107. data/{img/gicons → out/images}/marker61.png +0 -0
  108. data/{img/gicons → out/images}/marker62.png +0 -0
  109. data/{img/gicons → out/images}/marker63.png +0 -0
  110. data/{img/gicons → out/images}/marker64.png +0 -0
  111. data/{img/gicons → out/images}/marker65.png +0 -0
  112. data/{img/gicons → out/images}/marker66.png +0 -0
  113. data/{img/gicons → out/images}/marker67.png +0 -0
  114. data/{img/gicons → out/images}/marker68.png +0 -0
  115. data/{img/gicons → out/images}/marker69.png +0 -0
  116. data/{img/gicons → out/images}/marker7.png +0 -0
  117. data/{img/gicons → out/images}/marker70.png +0 -0
  118. data/{img/gicons → out/images}/marker71.png +0 -0
  119. data/{img/gicons → out/images}/marker72.png +0 -0
  120. data/{img/gicons → out/images}/marker73.png +0 -0
  121. data/{img/gicons → out/images}/marker74.png +0 -0
  122. data/{img/gicons → out/images}/marker75.png +0 -0
  123. data/{img/gicons → out/images}/marker76.png +0 -0
  124. data/{img/gicons → out/images}/marker77.png +0 -0
  125. data/{img/gicons → out/images}/marker78.png +0 -0
  126. data/{img/gicons → out/images}/marker79.png +0 -0
  127. data/{img/gicons → out/images}/marker8.png +0 -0
  128. data/{img/gicons → out/images}/marker80.png +0 -0
  129. data/{img/gicons → out/images}/marker81.png +0 -0
  130. data/{img/gicons → out/images}/marker82.png +0 -0
  131. data/{img/gicons → out/images}/marker83.png +0 -0
  132. data/{img/gicons → out/images}/marker84.png +0 -0
  133. data/{img/gicons → out/images}/marker85.png +0 -0
  134. data/{img/gicons → out/images}/marker86.png +0 -0
  135. data/{img/gicons → out/images}/marker87.png +0 -0
  136. data/{img/gicons → out/images}/marker88.png +0 -0
  137. data/{img/gicons → out/images}/marker89.png +0 -0
  138. data/{img/gicons → out/images}/marker9.png +0 -0
  139. data/{img/gicons → out/images}/marker90.png +0 -0
  140. data/{img/gicons → out/images}/marker91.png +0 -0
  141. data/{img/gicons → out/images}/marker92.png +0 -0
  142. data/{img/gicons → out/images}/marker93.png +0 -0
  143. data/{img/gicons → out/images}/marker94.png +0 -0
  144. data/{img/gicons → out/images}/marker95.png +0 -0
  145. data/{img/gicons → out/images}/marker96.png +0 -0
  146. data/{img/gicons → out/images}/marker97.png +0 -0
  147. data/{img/gicons → out/images}/marker98.png +0 -0
  148. data/{img/gicons → out/images}/marker99.png +0 -0
  149. data/{img/gicons → out/images}/markerA.png +0 -0
  150. data/{img/gicons → out/images}/markerB.png +0 -0
  151. data/{img/gicons → out/images}/markerC.png +0 -0
  152. data/{img/gicons → out/images}/markerD.png +0 -0
  153. data/{img/gicons → out/images}/markerE.png +0 -0
  154. data/{img/gicons → out/images}/markerF.png +0 -0
  155. data/{img/gicons → out/images}/markerG.png +0 -0
  156. data/{img/gicons → out/images}/markerH.png +0 -0
  157. data/{img/gicons → out/images}/markerI.png +0 -0
  158. data/{img/gicons → out/images}/markerJ.png +0 -0
  159. data/{img/gicons → out/images}/mm_20_red.png +0 -0
  160. data/{img/gicons → out/images}/mm_20_shadow.png +0 -0
  161. data/{img/gicons → out/images}/shadow50.png +0 -0
  162. data/rakefile.rb +79 -0
  163. data/samples.sh +21 -0
  164. data/samples/2008_04_27_13_49_50_tcx.csv +2449 -0
  165. data/samples/2008_04_27_13_49_50_tcx.xml +24560 -0
  166. data/samples/2009_01_01_14_45_00_tcx.xml +10630 -0
  167. data/samples/ballantyne.csv +27 -0
  168. data/samples/ballantyne.gpx +117 -0
  169. data/samples/ballantyne.kml +91 -0
  170. data/samples/big_sur_marathon.html +2766 -0
  171. data/samples/big_sur_marathon.kml +685 -0
  172. data/samples/build_gem_test_results.txt +6 -0
  173. data/samples/crowders_mtn_hike.csv +1065 -0
  174. data/samples/crowders_mtn_hike.html +1283 -0
  175. data/samples/crowders_mtn_hike.log +1 -0
  176. data/samples/cucumber_test_results.txt +302 -0
  177. data/samples/davidson1.csv +1 -0
  178. data/samples/davidson1.html +75 -0
  179. data/samples/davidson_1_point_tcx.csv +0 -0
  180. data/samples/doc.kml +49 -0
  181. data/samples/gps_track_log_asheville_mt_pisgah.txt +1 -0
  182. data/samples/gps_track_logs.txt +1 -0
  183. data/samples/install_test_results.txt +81 -0
  184. data/samples/mt_pisgah.txt +1 -0
  185. data/samples/rspec_test_results.txt +5 -0
  186. data/setup.rb +66 -0
  187. data/spec/gooby_base_object_spec.rb +116 -0
  188. data/spec/gooby_counter_hash_spec.rb +34 -0
  189. data/spec/gooby_dttm_spec.rb +40 -0
  190. data/spec/gooby_spec_helper.rb +9 -0
  191. data/spec/gooby_xml_object_spec.rb +32 -0
  192. metadata +225 -226
  193. data/bin/code_scan.rb +0 -16
  194. data/bin/gooby_been_there.rb +0 -33
  195. data/bin/gooby_config.rb +0 -24
  196. data/bin/gooby_csv_validation.rb +0 -50
  197. data/bin/gooby_first_trackpoints_as_poi.rb +0 -31
  198. data/bin/gooby_gen_gmap.rb +0 -20
  199. data/bin/gooby_parser.rb +0 -21
  200. data/bin/gooby_splitter.rb +0 -21
  201. data/bin/gooby_version.rb +0 -20
  202. data/bin/run_all.sh +0 -33
  203. data/bin/run_been_there.sh +0 -19
  204. data/bin/run_config.sh +0 -12
  205. data/bin/run_csv_validation.sh +0 -15
  206. data/bin/run_db_gen.sh +0 -11
  207. data/bin/run_db_load.sh +0 -11
  208. data/bin/run_first_trackpoints_as_poi.sh +0 -16
  209. data/bin/run_gen_gmaps.sh +0 -21
  210. data/bin/run_parse_full.sh +0 -45
  211. data/bin/run_parse_samples.sh +0 -21
  212. data/bin/run_split.sh +0 -24
  213. data/bin/run_version.sh +0 -12
  214. data/data/20050305_corporate_cup_hm.csv +0 -251
  215. data/data/20050305_corporate_cup_hm.xml +0 -2208
  216. data/data/20050430_nashville_marathon.xml +0 -10043
  217. data/data/20050430_nashville_marathon_km.csv +0 -1208
  218. data/data/20060115_phoenix_marathon.csv +0 -1280
  219. data/data/20060115_phoenix_marathon.xml +0 -10620
  220. data/data/20070101_davidson_11m.csv +0 -251
  221. data/data/20070101_davidson_11m.xml +0 -2020
  222. data/data/20070505_davidson_5k.xml +0 -2875
  223. data/data/20070505_davidson_5k_km.csv +0 -286
  224. data/data/hrm1.csv +0 -5
  225. data/img/gicons/readme.txt +0 -14
  226. data/lib/gooby_code_scanner.rb +0 -288
  227. data/lib/gooby_command.rb +0 -210
  228. data/lib/gooby_course.rb +0 -117
  229. data/lib/gooby_csv_point.rb +0 -71
  230. data/lib/gooby_csv_reader.rb +0 -71
  231. data/lib/gooby_csv_run.rb +0 -28
  232. data/lib/gooby_delim_line.rb +0 -42
  233. data/lib/gooby_duration.rb +0 -86
  234. data/lib/gooby_forerunner_xml_parser.rb +0 -191
  235. data/lib/gooby_forerunner_xml_splitter.rb +0 -115
  236. data/lib/gooby_history.rb +0 -41
  237. data/lib/gooby_kernel.rb +0 -163
  238. data/lib/gooby_line.rb +0 -80
  239. data/lib/gooby_object.rb +0 -22
  240. data/lib/gooby_point.rb +0 -172
  241. data/lib/gooby_run.rb +0 -213
  242. data/lib/gooby_simple_xml_parser.rb +0 -50
  243. data/lib/gooby_test_helper.rb +0 -23
  244. data/lib/gooby_track.rb +0 -47
  245. data/lib/gooby_track_point.rb +0 -229
  246. data/lib/gooby_training_center_xml_parser.rb +0 -224
  247. data/lib/gooby_training_center_xml_splitter.rb +0 -116
  248. data/lib/split_code.sh +0 -29
  249. data/samples/20050305_corporate_cup_hm.html +0 -450
  250. data/samples/20050430_nashville_marathon.html +0 -1668
  251. data/samples/20060115_phoenix_marathon.html +0 -1596
  252. data/samples/20070101_davidson_11m.html +0 -432
  253. data/samples/20070505_davidson_5k.html +0 -413
  254. data/samples/been_there.txt +0 -92
  255. data/samples/hrm1.html +0 -87
  256. data/sql/gooby.ddl +0 -60
  257. 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