gooby 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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