gooby 0.9.4 → 0.9.5

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 (91) hide show
  1. data/README +48 -67
  2. data/bin/20050305_corporate_cup_hm_to_csv.rb +9 -0
  3. data/bin/20050430_nashville_marathon_to_csv.rb +9 -0
  4. data/bin/20060115_phoenix_marathon_to_csv.rb +9 -0
  5. data/bin/activity_2007_03_10_13_02_32.xml_to_csv.rb +9 -0
  6. data/bin/{tests_gen.rb → code_scan.rb} +6 -4
  7. data/bin/example_usage.rb +2 -3
  8. data/bin/example_usage.sh +52 -0
  9. data/bin/gen_gap_phx.rb +10 -0
  10. data/bin/gen_gmap_cc_2005.rb +10 -0
  11. data/bin/gen_gmap_cc_2007.rb +10 -0
  12. data/bin/gen_gmap_nashville.rb +10 -0
  13. data/bin/gen_gmap_phx.rb +10 -0
  14. data/bin/phx_to_csv.rb +47 -0
  15. data/bin/split_forerunner_logbook_2007.rb +10 -0
  16. data/bin/split_training_center_2007.rb +8 -0
  17. data/data/{2007_03_04.tcx → 2007_03_10.tcx} +11694 -0
  18. data/data/activity_2007_03_10_13_02_32.csv +1168 -0
  19. data/data/activity_2007_03_10_13_02_32.xml +11695 -0
  20. data/data/forerunner_2007.xml +0 -227142
  21. data/img/gicons/readme.txt +3 -0
  22. data/lib/gooby.rb +625 -552
  23. data/samples/20050305_corporate_cup_hm.html +271 -269
  24. data/samples/20050430_nashville_marathon.html +1240 -246
  25. data/samples/20060115_phoenix_marathon.html +1596 -0
  26. data/samples/20070310_corporate_cup_hm.html +1367 -0
  27. data/samples/phoenix_marathon.html +1312 -258
  28. data/tests/ts_gooby.rb +423 -551
  29. data/tests/ts_gooby_min.rb +550 -0
  30. metadata +25 -67
  31. data/bin/tcx_ex.rb +0 -35
  32. data/data/20051124_hyatt_turkey_trot_8K.csv +0 -321
  33. data/data/20051124_hyatt_turkey_trot_8K.xml +0 -2651
  34. data/data/2007_03_03.tcx +0 -6207
  35. data/data/activity_2007_03_04_15_22_36.xml +0 -10545
  36. data/data/run_2007_01_01_16_38_27.xml +0 -2020
  37. data/data/run_2007_02_24_15_01_35.csv +0 -484
  38. data/data/run_2007_02_24_15_01_35.xml +0 -3884
  39. data/lib/gooby/cls_counter_hash.rb +0 -78
  40. data/lib/gooby/cls_delim_line.rb +0 -35
  41. data/lib/gooby/cls_dttm.rb +0 -79
  42. data/lib/gooby/cls_duration.rb +0 -79
  43. data/lib/gooby/cls_forerunner_xml_parser.rb +0 -178
  44. data/lib/gooby/cls_forerunner_xml_splitter.rb +0 -109
  45. data/lib/gooby/cls_geo_data.rb +0 -181
  46. data/lib/gooby/cls_gooby_command.rb +0 -46
  47. data/lib/gooby/cls_gooby_object.rb +0 -18
  48. data/lib/gooby/cls_google_map_generator.rb +0 -363
  49. data/lib/gooby/cls_history.rb +0 -33
  50. data/lib/gooby/cls_lap.rb +0 -22
  51. data/lib/gooby/cls_line.rb +0 -75
  52. data/lib/gooby/cls_options.rb +0 -67
  53. data/lib/gooby/cls_position.rb +0 -44
  54. data/lib/gooby/cls_run.rb +0 -194
  55. data/lib/gooby/cls_simple_xml_parser.rb +0 -41
  56. data/lib/gooby/cls_test_regen.rb +0 -182
  57. data/lib/gooby/cls_track.rb +0 -47
  58. data/lib/gooby/cls_trackpoint.rb +0 -200
  59. data/lib/gooby/cls_training_center_parser.rb +0 -183
  60. data/lib/gooby/cls_training_center_splitter.rb +0 -109
  61. data/lib/gooby/mod_introspect.rb +0 -26
  62. data/lib/gooby/mod_io.rb +0 -58
  63. data/lib/gooby/mod_project_info.rb +0 -80
  64. data/lib/gooby/mod_string.rb +0 -19
  65. data/lib/gooby/mod_test_helper.rb +0 -15
  66. data/samples/20041113_richmond_marathon.html +0 -532
  67. data/samples/run_2007_01_10_22_44_54.html +0 -201
  68. data/samples/run_2007_02_24_15_01_35.html +0 -298
  69. data/tests/tc_cls_counter_hash.rb +0 -107
  70. data/tests/tc_cls_delim_line.rb +0 -74
  71. data/tests/tc_cls_dttm.rb +0 -131
  72. data/tests/tc_cls_duration.rb +0 -51
  73. data/tests/tc_cls_forerunner_xml_parser.rb +0 -70
  74. data/tests/tc_cls_geo_data.xxx +0 -71
  75. data/tests/tc_cls_gooby_object.rb +0 -26
  76. data/tests/tc_cls_google_map_generator.rb +0 -109
  77. data/tests/tc_cls_history.rb +0 -46
  78. data/tests/tc_cls_lap.rb +0 -38
  79. data/tests/tc_cls_line.rb +0 -110
  80. data/tests/tc_cls_options.rb +0 -79
  81. data/tests/tc_cls_position.rb +0 -66
  82. data/tests/tc_cls_run.rb +0 -142
  83. data/tests/tc_cls_simple_xml_parser.rb +0 -50
  84. data/tests/tc_cls_track.rb +0 -70
  85. data/tests/tc_cls_trackpoint.rb +0 -145
  86. data/tests/tc_mod_introspect.rb +0 -32
  87. data/tests/tc_mod_io.rb +0 -53
  88. data/tests/tc_mod_project_info.rb +0 -79
  89. data/tests/tc_mod_string.rb +0 -58
  90. /data/data/{phx.csv → 20060115_phoenix_marathon.csv} +0 -0
  91. /data/data/{phx.xml → 20060115_phoenix_marathon.xml} +0 -0
data/lib/gooby.rb CHANGED
@@ -1,15 +1,41 @@
1
- # Packaged on Fri Mar 09 06:03:09 EST 2007
2
-
3
1
  =begin
4
2
 
5
- This file contains the classes and modules for the Gooby project.
6
3
  Gooby = Google APIs + Ruby
4
+ This file contains the classes and modules for the Gooby project.
7
5
 
8
6
  See file 'tests/ts_gooby.rb' for the regression test suite.
9
7
 
8
+ Index of Modules and Classes in this file:
9
+ line type Module or Class name
10
+ ---- ------ ---------------------------
11
+ 51 module Gooby
12
+ 58 module GoobyKernel
13
+ 185 module TestHelper
14
+ 203 class GoobyObject
15
+ 216 class CounterHash
16
+ 299 class DelimLine
17
+ 334 class DtTm
18
+ 411 class Duration
19
+ 490 class ForerunnerXmlParser
20
+ 661 class ForerunnerXmlSplitter
21
+ 771 class TrainingCenterXmlParser
22
+ 948 class TrainingCenterXmlSplitter
23
+ 1053 class GeoData
24
+ 1236 class GoogleMapGenerator
25
+ 1608 class History
26
+ 1639 class Lap
27
+ 1654 class Line
28
+ 1724 class Options
29
+ 1799 class Position
30
+ 1843 class Run
31
+ 2032 class SimpleXmlParser
32
+ 2072 class Track
33
+ 2119 class Trackpoint
34
+ 2308 class CodeScanner
35
+ 2600 class GoobyCommand
36
+
10
37
  Gooby - Copyright 2007 by Chris Joakim.
11
38
  Gooby is available under GNU General Public License (GPL) license.
12
-
13
39
  =end
14
40
 
15
41
  require 'date'
@@ -20,28 +46,37 @@ require 'rexml/streamlistener'
20
46
  require 'time'
21
47
  require 'yaml'
22
48
 
49
+ # =============================================================================
50
+
23
51
  module Gooby
24
52
 
25
53
  =begin rdoc
26
54
  This module is used to embed information about the Gooby project and
27
55
  version into the codebase.
28
-
29
- Gooby - Copyright 2007 by Chris Joakim.
30
- Gooby is available under GNU General Public License (GPL) license.
31
56
  =end
32
57
 
33
- module GoobyProjectInfo
58
+ module GoobyKernel
34
59
 
35
60
  # Return a String version number, like '1.0.0'.
61
+
62
+ def project_name
63
+ 'Gooby'
64
+ end
65
+
36
66
  def project_version_number
37
- '0.9.4'
67
+ '0.9.5'
38
68
  end
39
69
 
40
- # Return a String date, like '2007/02/25'.
70
+ # Return a String date, like '2007/03/15'.
41
71
  def project_date
42
- '2007/03/03'
72
+ '2007/03/15'
43
73
  end
44
-
74
+
75
+ # Return a String containing the project author name.
76
+ def project_author
77
+ 'Chris Joakim'
78
+ end
79
+
45
80
  # Return a String year, like '2007'.
46
81
  def project_year
47
82
  project_date[0...4] # start, length
@@ -51,115 +86,15 @@ module Gooby
51
86
  def project_copyright
52
87
  "Copyright (C) #{project_year} #{project_author}"
53
88
  end
54
-
55
- # Return a String containing GNU/GPL, and the gpl.html URL.
56
- def project_license
57
- 'GNU General Public License (GPL). See http://www.gnu.org/copyleft/gpl.html'
58
- end
59
-
60
- # Return a String containing the project author name.
61
- def project_author
62
- 'Chris Joakim'
63
- end
64
-
65
- def google_maps_api_level
66
- '2'
67
- end
68
-
69
- def some_new_thing
70
- '2'
71
- end
72
-
73
- def tested_files
74
- array = Array.new
75
- array << 'cls_counter_hash.rb'
76
- array << 'cls_delim_line.rb'
77
- array << 'cls_dttm.rb'
78
- array << 'cls_duration.rb'
79
- array << 'cls_forerunner_xml_parser.rb'
80
- array << 'cls_geo_data.rb'
81
- array << 'cls_gooby_object.rb'
82
- array << 'cls_google_map_generator.rb'
83
- array << 'cls_history.rb'
84
- array << 'cls_lap.rb'
85
- array << 'cls_line.rb'
86
- array << 'cls_options.rb'
87
- array << 'cls_position.rb'
88
- array << 'cls_run.rb'
89
- array << 'cls_simple_xml_parser.rb'
90
- array << 'cls_track.rb'
91
- array << 'cls_trackpoint.rb'
92
- array << 'mod_constants.rb'
93
- array << 'mod_introspect.rb'
94
- array << 'mod_io.rb'
95
- array << 'mod_project_info.rb'
96
- array << 'mod_string.rb'
97
- array
98
- end
99
-
100
- end
101
-
102
-
103
- module Con
104
-
105
- public
106
-
107
- def default_delimiter
108
- return '|'
109
- end
110
89
 
111
- def invalid_distance
112
- return -99999999
113
- end
114
-
115
- def invalid_minutes
116
- return -99999999
117
- end
118
-
119
- def invalid_time
120
- return -99999999
121
- end
122
-
123
- def invalid_latitude
124
- return -1
125
- end
126
-
127
- def invalid_longitude
128
- return -1
129
- end
130
-
131
- def invalid_altitude
132
- return -1
90
+ def project_embedded_comment
91
+ "#{project_name} #{project_version_number}"
133
92
  end
134
93
 
135
- end
136
-
137
-
138
- module Introspect
139
-
140
- # Return a String w/instance variable and method info.
141
- def introspect
142
- c = self.class
143
- s = "Class: #{c} "
144
- iv = self.instance_variables.sort
145
- s << " ivc=#{iv.size}"
146
- iv.each { |v| s << " #{v}" }
147
- meth = self.methods.sort
148
- s << " mc=#{meth.size}"
149
- meth.each { |m| s << " #{m}" }
150
- s << ""
151
- s
152
- end
153
-
154
- # Return 'self.instance_variables'.
155
- def to_yaml_properties
156
- self.instance_variables
94
+ # Return a String containing GNU/GPL, and the gpl.html URL.
95
+ def project_license
96
+ 'GNU General Public License (GPL). See http://www.gnu.org/copyleft/gpl.html'
157
97
  end
158
-
159
- end
160
-
161
-
162
- module GoobyIO
163
98
 
164
99
  # Return an Array of lines in file, optionally stripped.
165
100
  def read_lines(filename, strip=false)
@@ -211,13 +146,8 @@ module Gooby
211
146
  end
212
147
  return newArray
213
148
  end
214
-
215
- end
216
149
 
217
-
218
- module GoobyString
219
-
220
- def tokenize(string, delim, strip=false)
150
+ def tokenize(string, delim=nil, strip=false)
221
151
  if string
222
152
  tokens = string.split(delim)
223
153
  if strip
@@ -228,10 +158,30 @@ module Gooby
228
158
  Array.new
229
159
  end
230
160
  end
231
-
232
- end
161
+
162
+ def default_delimiter
163
+ return '|'
164
+ end
165
+
166
+ def invalid_time
167
+ return -99999999
168
+ end
233
169
 
170
+ def invalid_latitude
171
+ return -1
172
+ end
234
173
 
174
+ def invalid_longitude
175
+ return -1
176
+ end
177
+
178
+ def invalid_altitude
179
+ return -1
180
+ end
181
+ end
182
+
183
+ # =============================================================================
184
+
235
185
  module TestHelper
236
186
 
237
187
  def setup
@@ -241,9 +191,9 @@ module Gooby
241
191
  def teardown
242
192
  @debug = false
243
193
  end
244
-
245
194
  end
246
-
195
+
196
+ # =============================================================================
247
197
 
248
198
  =begin rdoc
249
199
  This is the abstract superclass of several Gooby classes.
@@ -252,14 +202,10 @@ module Gooby
252
202
 
253
203
  class GoobyObject
254
204
 
255
- include Gooby::GoobyIO
256
- include Gooby::GoobyString
257
- include Gooby::Introspect
258
- include Gooby::GoobyProjectInfo
259
- include Gooby::Con
260
-
205
+ include Gooby::GoobyKernel
261
206
  end
262
-
207
+
208
+ # =============================================================================
263
209
 
264
210
  =begin rdoc
265
211
  This class wrappers a Hash object and provides increment/decrement functionality
@@ -272,6 +218,10 @@ module Gooby
272
218
  def initialize
273
219
  @hash = Hash.new(0)
274
220
  end
221
+
222
+ def size
223
+ @hash.size
224
+ end
275
225
 
276
226
  # Return the Integer count for the given key; zero default.
277
227
  def value(key)
@@ -290,6 +240,11 @@ module Gooby
290
240
  @hash[key] = 1
291
241
  end
292
242
  end
243
+
244
+ def increment_tokens(text)
245
+ tokens = tokenize(text)
246
+ tokens.each { |token| increment(token) }
247
+ end
293
248
 
294
249
  # Decrement the count for the given key.
295
250
  def decrement(key)
@@ -314,7 +269,7 @@ module Gooby
314
269
  s = "CHash:"
315
270
  sorted_keys.each { |key|
316
271
  val = @hash[key]
317
- s << " key: [#{key}] val: [#{val}]"
272
+ s << " key: [#{key}] val: [#{val}]\n"
318
273
  }
319
274
  s
320
275
  end
@@ -333,9 +288,9 @@ module Gooby
333
288
  s << " </CHash>"
334
289
  s
335
290
  end
336
-
337
291
  end
338
-
292
+
293
+ # =============================================================================
339
294
 
340
295
  =begin rdoc
341
296
  Instances of this class represent a delimited line of text, such as csv.
@@ -346,9 +301,9 @@ module Gooby
346
301
  attr_reader :line, :trim, :delim, :tokens
347
302
 
348
303
  def initialize(line, trim=true, delim=default_delimiter)
349
- @line = line
350
- @trim = trim
351
- @delim = delim
304
+ @line = line
305
+ @trim = trim
306
+ @delim = delim
352
307
  @tokens = @line.split(@delim)
353
308
  if trim
354
309
  @tokens.each { | token | token.strip! }
@@ -366,10 +321,10 @@ module Gooby
366
321
  def to_s
367
322
  "DelimLine: length: #{@line.size} trim: #{@trim} delim: #{@delim} tokens: #{@tokens.size}"
368
323
  end
369
-
370
324
  end
371
325
 
372
-
326
+ # =============================================================================
327
+
373
328
  =begin rdoc
374
329
  Instances of this class represent a Date and Time as parsed from a value
375
330
  such as '2006-01-15T13:41:40Z' in an XML file produced by a GPS device.
@@ -385,8 +340,8 @@ module Gooby
385
340
  if raw
386
341
  @rawdata = raw.strip
387
342
  if @rawdata.size > 18
388
- @dateTime = DateTime.parse(@rawdata[0..18])
389
- @time = Time.parse(@dateTime.to_s)
343
+ @date_time = DateTime.parse(@rawdata[0..18])
344
+ @time = Time.parse(@date_time.to_s)
390
345
  @valid = true
391
346
  else
392
347
  @valid = false
@@ -443,9 +398,9 @@ module Gooby
443
398
  def print_string
444
399
  "DtTm: #{yyyy_mm_dd_hh_mm_ss} #{to_i} #{@rawdata}"
445
400
  end
446
-
447
401
  end
448
-
402
+
403
+ # =============================================================================
449
404
 
450
405
  =begin rdoc
451
406
  Instances of this class represent the contents of a Forerunner extract
@@ -460,7 +415,7 @@ module Gooby
460
415
  # Constructor; arg is a String like 'PT507.870S'.
461
416
  def initialize(raw)
462
417
  if raw
463
- @rawdata = scrub(raw)
418
+ @rawdata = scrub("#{raw}")
464
419
  @seconds = @rawdata.to_f
465
420
  @minutes = @seconds / 60
466
421
  @base_min = @minutes.floor
@@ -519,9 +474,9 @@ module Gooby
519
474
  def print_string
520
475
  "Duration: #{@rawdata} sec: #{@seconds} min: #{@minutes} mmss: #{@mmss} bm: #{@base_min} fm: #{@frac_min} fs: #{@frac_sec}"
521
476
  end
522
-
523
477
  end
524
-
478
+
479
+ # =============================================================================
525
480
 
526
481
  =begin rdoc
527
482
  Instances of this class are used to parse a Forerunner XML file in a SAX-like
@@ -541,121 +496,120 @@ module Gooby
541
496
  attr_reader :history, :cvHash, :tagCount
542
497
 
543
498
  def initialize
544
- @cvHash = Hash.new("")
545
- @tagCount = 0
546
- @runCount = 0
547
- @lapCount = 0
548
- @trackCount = 0
549
- @trackpoint_count = 0
550
- @currText = "";
551
- @history = History.new
552
- @currRun = nil
553
- @currLap = nil
554
- @currTrack = nil
555
- @currBeginPosition = nil
556
- @currEndPosition = nil
499
+ @cv_hash = Hash.new("")
500
+ @tag_count = 0
501
+ @run_count = 0
502
+ @lap_count = 0
503
+ @track_count = 0
504
+ @trackpoint_count = 0
505
+ @curr_text = "";
506
+ @history = History.new
507
+ @curr_run = nil
508
+ @curr_lap = nil
509
+ @curr_track = nil
510
+ @curr_begin_position = nil
511
+ @@curr_end_position = nil
557
512
  end
558
513
 
559
514
  public
560
515
 
561
516
  # SAX API method; handles 'Run', 'Lap', 'Track'.
562
517
  def tag_start(tagname, attrs)
563
- @tagCount += 1
518
+ @tag_count += 1
564
519
  @currTag = tagname
565
- @cvHash[tagname] = ''
520
+ @cv_hash[tagname] = ''
566
521
 
567
522
  if detail_tag?(tagname)
568
523
  @inDetail = true
569
524
  end
570
525
 
571
526
  if is_tag?('Run', tagname)
572
- @runCount = @runCount + 1
573
- @lapCount = 0
574
- @trackCount = 0
575
- @currRun = Run.new(@runCount)
576
- @history.add_run(@currRun)
577
- @cvHash['Notes'] = ''
527
+ @run_count = @run_count + 1
528
+ @lap_count = 0
529
+ @track_count = 0
530
+ @curr_run = Run.new(@run_count)
531
+ @history.add_run(@curr_run)
532
+ @cv_hash['Notes'] = ''
578
533
  return
579
534
  end
580
535
 
581
536
  if is_tag?('Lap', tagname)
582
- @lapCount = @lapCount + 1
583
- @currLap = Lap.new(@lapCount)
537
+ @lap_count = @lap_count + 1
538
+ @curr_lap = Lap.new(@lap_count)
584
539
  return
585
540
  end
586
541
 
587
542
  if is_tag?('Track', tagname)
588
- @trackCount = @trackCount + 1
589
- @currTrack = Track.new(@trackCount)
543
+ @track_count = @track_count + 1
544
+ @curr_track = Track.new(@track_count)
590
545
  @trackpoint_count = 0
591
546
  return
592
547
  end
593
-
594
548
  end
595
549
 
596
550
  # SAX API method; handles 'Position', 'Trackpoint', 'Track', 'Lap', 'Run'.
597
551
  def tag_end(tagname)
598
552
  if @inDetail
599
- @cvHash[tagname] = @currText
553
+ @cv_hash[tagname] = @curr_text
600
554
  else
601
555
  if is_tag?('Position', tagname)
602
- lat = @cvHash['Latitude']
603
- long = @cvHash['Longitude']
604
- @currBeginPosition = Position.new(lat.strip, long.strip, '')
605
- @currEndPosition = Position.new(lat.strip, long.strip, '')
556
+ lat = @cv_hash['Latitude']
557
+ long = @cv_hash['Longitude']
558
+ @curr_begin_position = Position.new(lat.strip, long.strip, '')
559
+ @@curr_end_position = Position.new(lat.strip, long.strip, '')
606
560
  end
607
561
 
608
562
  if is_tag?('BeginPosition', tagname)
609
- lat = @cvHash['Latitude']
610
- long = @cvHash['Longitude']
611
- @currBeginPosition = Position.new(lat.strip, long.strip, '')
563
+ lat = @cv_hash['Latitude']
564
+ long = @cv_hash['Longitude']
565
+ @curr_begin_position = Position.new(lat.strip, long.strip, '')
612
566
  end
613
567
 
614
568
  if is_tag?('EndPosition', tagname)
615
- lat = @cvHash['Latitude']
616
- long = @cvHash['Longitude']
617
- @currEndPosition = Position.new(lat.strip, long.strip, '')
569
+ lat = @cv_hash['Latitude']
570
+ long = @cv_hash['Longitude']
571
+ @@curr_end_position = Position.new(lat.strip, long.strip, '')
618
572
  end
619
573
 
620
574
  if is_tag?('Trackpoint', tagname)
621
575
  @trackpoint_count = @trackpoint_count + 1
622
- lat = @cvHash['Latitude']
623
- long = @cvHash['Longitude']
624
- alt = @cvHash['Altitude']
625
- time = @cvHash['Time']
576
+ lat = @cv_hash['Latitude']
577
+ long = @cv_hash['Longitude']
578
+ alt = @cv_hash['Altitude']
579
+ time = @cv_hash['Time']
626
580
  tp = Trackpoint.new(@trackpoint_count, lat, long, alt, time)
627
- @currTrack.add_trackpoint(tp)
581
+ @curr_track.add_trackpoint(tp)
628
582
  end
629
583
 
630
584
  if is_tag?('Track', tagname)
631
- if @currRun != nil
632
- @currRun.add_track(@currTrack)
585
+ if @curr_run != nil
586
+ @curr_run.add_track(@curr_track)
633
587
  end
634
588
  end
635
589
 
636
590
  if is_tag?('Lap', tagname)
637
- @currLap.startTime = @cvHash['StartTime']
638
- @currLap.duration = Duration.new(@cvHash['Duration'])
639
- @currLap.length = @cvHash['Length']
640
- @currLap.beginPosition = @currBeginPosition
641
- @currLap.endPosition = @currEndPosition
642
- @currRun.add_lap(@currLap)
591
+ @curr_lap.startTime = @cv_hash['StartTime']
592
+ @curr_lap.duration = Duration.new(@cv_hash['Duration'])
593
+ @curr_lap.length = @cv_hash['Length']
594
+ @curr_lap.begin_position = @curr_begin_position
595
+ @curr_lap.end_position = @@curr_end_position
596
+ @curr_run.add_lap(@curr_lap)
643
597
  end
644
598
 
645
599
  if is_tag?('Run', tagname)
646
- @currRun.notes = @cvHash['Notes']
600
+ @curr_run.notes = @cv_hash['Notes']
647
601
  end
648
602
  end
649
603
 
650
604
  @inDetail = false
651
- @currText = ""
605
+ @curr_text = ""
652
606
  @currTag = ""
653
607
  end
654
608
 
655
609
  # SAX API method.
656
610
  def text(txt)
657
611
  if @inDetail
658
- @currText = @currText + txt
612
+ @curr_text = @curr_text + txt
659
613
  end
660
614
  end
661
615
 
@@ -695,9 +649,9 @@ module Gooby
695
649
  }
696
650
  return false
697
651
  end
698
-
699
652
  end
700
653
 
654
+ # =============================================================================
701
655
 
702
656
  =begin rdoc
703
657
  Instances of this class are used to split a large ForerunnerLogbook
@@ -801,9 +755,9 @@ module Gooby
801
755
  }
802
756
  puts "output files written."
803
757
  end
804
-
805
758
  end
806
759
 
760
+ # =============================================================================
807
761
 
808
762
  =begin rdoc
809
763
  Instances of this class are used to parse a Garmin TrainingCenter XML file
@@ -825,53 +779,53 @@ module Gooby
825
779
  attr_reader :history, :cvHash, :tagCount
826
780
 
827
781
  def initialize
828
- @cvHash = Hash.new("")
829
- @tagCount = 0
830
- @runCount = 0
831
- @lapCount = 0
832
- @trackCount = 0
833
- @trackpoint_count = 0
834
- @currText = "";
835
- @history = History.new
836
- @currRun = nil
837
- @currLap = nil
838
- @currTrack = nil
839
- @currBeginPosition = nil
840
- @currEndPosition = nil
782
+ @cv_hash = Hash.new("")
783
+ @tag_count = 0
784
+ @run_count = 0
785
+ @lap_count = 0
786
+ @track_count = 0
787
+ @trackpoint_count = 0
788
+ @curr_text = "";
789
+ @history = History.new
790
+ @curr_run = nil
791
+ @curr_lap = nil
792
+ @curr_track = nil
793
+ @curr_begin_position = nil
794
+ @@curr_end_position = nil
841
795
  end
842
796
 
843
797
  public
844
798
 
845
799
  # SAX API method; handles 'Activity', 'Lap', 'Track'.
846
800
  def tag_start(tagname, attrs)
847
- @tagCount += 1
801
+ @tag_count += 1
848
802
  @currTag = tagname
849
- @cvHash[tagname] = ''
803
+ @cv_hash[tagname] = ''
850
804
 
851
805
  if detail_tag?(tagname)
852
806
  @inDetail = true
853
807
  end
854
808
 
855
809
  if is_tag?('Activity', tagname)
856
- @runCount = @runCount + 1
857
- @lapCount = 0
858
- @trackCount = 0
859
- @currRun = Run.new(@runCount)
860
- @history.add_run(@currRun)
861
- @cvHash['Notes'] = ''
810
+ @run_count = @run_count + 1
811
+ @lap_count = 0
812
+ @track_count = 0
813
+ @curr_run = Run.new(@run_count)
814
+ @history.add_run(@curr_run)
815
+ @cv_hash['Notes'] = ''
862
816
  return
863
817
  end
864
818
 
865
819
  if is_tag?('Lap', tagname)
866
- @lapCount = @lapCount + 1
867
- @currLap = Lap.new(@lapCount)
820
+ @lap_count = @lap_count + 1
821
+ @curr_lap = Lap.new(@lap_count)
868
822
  # TODO - capture value of 'StartTime' attribute.
869
823
  return
870
824
  end
871
825
 
872
826
  if is_tag?('Track', tagname)
873
- @trackCount = @trackCount + 1
874
- @currTrack = Track.new(@trackCount)
827
+ @track_count = @track_count + 1
828
+ @curr_track = Track.new(@track_count)
875
829
  @trackpoint_count = 0
876
830
  return
877
831
  end
@@ -881,68 +835,68 @@ module Gooby
881
835
  # SAX API method; handles 'Position', 'Trackpoint', 'Track', 'Lap', 'Run'.
882
836
  def tag_end(tagname)
883
837
  if @inDetail
884
- @cvHash[tagname] = @currText
838
+ @cv_hash[tagname] = @curr_text
885
839
  else
886
840
  if is_tag?('Position', tagname)
887
- lat = @cvHash['LatitudeDegrees']
888
- long = @cvHash['LongitudeDegrees']
889
- @currBeginPosition = Position.new(lat.strip, long.strip, '')
890
- @currEndPosition = Position.new(lat.strip, long.strip, '')
841
+ lat = @cv_hash['LatitudeDegrees']
842
+ long = @cv_hash['LongitudeDegrees']
843
+ @curr_begin_position = Position.new(lat.strip, long.strip, '')
844
+ @@curr_end_position = Position.new(lat.strip, long.strip, '')
891
845
  end
892
846
 
893
847
  if is_tag?('BeginPosition', tagname)
894
- lat = @cvHash['LatitudeDegrees']
895
- long = @cvHash['LongitudeDegrees']
896
- @currBeginPosition = Position.new(lat.strip, long.strip, '')
848
+ lat = @cv_hash['LatitudeDegrees']
849
+ long = @cv_hash['LongitudeDegrees']
850
+ @curr_begin_position = Position.new(lat.strip, long.strip, '')
897
851
  end
898
852
 
899
853
  if is_tag?('EndPosition', tagname)
900
- lat = @cvHash['LatitudeDegrees']
901
- long = @cvHash['LongitudeDegrees']
902
- @currEndPosition = Position.new(lat.strip, long.strip, '')
854
+ lat = @cv_hash['LatitudeDegrees']
855
+ long = @cv_hash['LongitudeDegrees']
856
+ @@curr_end_position = Position.new(lat.strip, long.strip, '')
903
857
  end
904
858
 
905
859
  if is_tag?('Trackpoint', tagname)
906
860
  @trackpoint_count = @trackpoint_count + 1
907
- lat = @cvHash['LatitudeDegrees']
908
- long = @cvHash['LongitudeDegrees']
909
- alt = @cvHash['AltitudeMeters']
910
- time = @cvHash['Time']
861
+ lat = @cv_hash['LatitudeDegrees']
862
+ long = @cv_hash['LongitudeDegrees']
863
+ alt = @cv_hash['AltitudeMeters']
864
+ time = @cv_hash['Time']
911
865
  tp = Trackpoint.new(@trackpoint_count, lat, long, alt, time)
912
- @currTrack.add_trackpoint(tp)
866
+ @curr_track.add_trackpoint(tp)
913
867
  end
914
868
 
915
869
  if is_tag?('Track', tagname)
916
- if @currRun != nil
917
- @currRun.add_track(@currTrack)
870
+ if @curr_run != nil
871
+ @curr_run.add_track(@curr_track)
918
872
  end
919
873
  end
920
874
 
921
875
  if is_tag?('Lap', tagname)
922
876
  # TotalTimeSeconds DistanceMeters
923
877
  # TODO - rework tnd of Lap for tcx
924
- # @currLap.startTime = @cvHash['StartTime']
925
- # @currLap.duration = Duration.new(@cvHash['Duration'])
926
- # @currLap.length = @cvHash['Length']
927
- # @currLap.beginPosition = @currBeginPosition
928
- # @currLap.endPosition = @currEndPosition
929
- @currRun.add_lap(@currLap)
878
+ # @curr_lap.startTime = @cv_hash['StartTime']
879
+ # @curr_lap.duration = Duration.new(@cv_hash['Duration'])
880
+ # @curr_lap.length = @cv_hash['Length']
881
+ # @curr_lap.begin_position = @curr_begin_position
882
+ # @curr_lap.end_position = @@curr_end_position
883
+ @curr_run.add_lap(@curr_lap)
930
884
  end
931
885
 
932
886
  if is_tag?('Activity', tagname)
933
- @currRun.notes = @cvHash['Notes']
887
+ @curr_run.notes = @cv_hash['Notes']
934
888
  end
935
889
  end
936
890
 
937
891
  @inDetail = false
938
- @currText = ""
892
+ @curr_text = ""
939
893
  @currTag = ""
940
894
  end
941
895
 
942
896
  # SAX API method.
943
897
  def text(txt)
944
898
  if @inDetail
945
- @currText = @currText + txt
899
+ @curr_text = @curr_text + txt
946
900
  end
947
901
  end
948
902
 
@@ -982,9 +936,9 @@ module Gooby
982
936
  }
983
937
  return false
984
938
  end
985
-
986
939
  end
987
940
 
941
+ # =============================================================================
988
942
 
989
943
  =begin rdoc
990
944
  Instances of this class are used to split a large Garmin TrainingCenter
@@ -999,7 +953,7 @@ module Gooby
999
953
  @out_dir = out_dir
1000
954
  @training_center_files = Array.new
1001
955
  @training_center_files << tcx_file
1002
- @out_files_hash = Hash.new
956
+ @out_files_hash = Hash.new
1003
957
  end
1004
958
 
1005
959
  def split
@@ -1088,9 +1042,9 @@ module Gooby
1088
1042
  }
1089
1043
  puts "output files written."
1090
1044
  end
1091
-
1092
1045
  end
1093
1046
 
1047
+ # =============================================================================
1094
1048
 
1095
1049
  =begin rdoc
1096
1050
  Instances of this class represent a the set of Geographic data defined in file geo.txt
@@ -1267,9 +1221,9 @@ module Gooby
1267
1221
  puts "Route: '#{key}'"
1268
1222
  }
1269
1223
  end
1270
-
1271
1224
  end
1272
1225
 
1226
+ # =============================================================================
1273
1227
 
1274
1228
  =begin rdoc
1275
1229
  Instances of this class represent a <Run> aggregate object from a
@@ -1297,13 +1251,21 @@ module Gooby
1297
1251
  @lng_idx = lng_idx
1298
1252
  @alt_idx = alt_idx
1299
1253
  @cdist_idx = cdist_idx
1254
+
1255
+ # Override default csv value indices if specified in the options yaml file.
1300
1256
  @options = Gooby::Options.new(nil)
1257
+ @dttm_idx = @options.get('csv_dttm_idx') if @options.get('csv_dttm_idx')
1258
+ @num_idx = @options.get('csv_num_idx') if @options.get('csv_num_idx')
1259
+ @lat_idx = @options.get('csv_lat_idx') if @options.get('csv_lat_idx')
1260
+ @lng_idx = @options.get('csv_lng_idx') if @options.get('csv_lng_idx')
1261
+ @alt_idx = @options.get('csv_alt_idx') if @options.get('csv_alt_idx')
1262
+
1301
1263
  @content_hash = Hash.new('')
1302
1264
  @run = Gooby::Run.new(1)
1303
1265
  @track = Gooby::Track.new(1)
1304
1266
  @run.add_track(@track)
1305
1267
  @tkpts = Array.new
1306
-
1268
+ @icon_url_base = @options.get('gmap_icon_url_base')
1307
1269
  @csv_lines = read_as_ascii_lines(@csv_file, 10, true)
1308
1270
  @csv_lines.each { | line |
1309
1271
  dline = Gooby::DelimLine.new(line)
@@ -1327,7 +1289,8 @@ Returns a Hash with specific generated content at the following keys:
1327
1289
  @options = options
1328
1290
  end
1329
1291
  @content_hash['when_generated'] = Time.now
1330
- @content_hash['title'] = @options.get('gmap_title')
1292
+ @content_hash['title'] = @options.get('gmap_title')
1293
+ @icon_url_base = @options.get('gmap_icon_url_base')
1331
1294
  filter_trackpoints
1332
1295
  compute_center_point
1333
1296
  generate_key_js
@@ -1374,6 +1337,8 @@ s = <<HERE
1374
1337
  <html xmlns="http://www.w3.org/1999/xhtml">
1375
1338
  <head>
1376
1339
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
1340
+ <meta name="description" content="Google Map generated with #{project_embedded_comment}">
1341
+ <meta name="keywords" content="Google Map #{project_embedded_comment} GPS">
1377
1342
  <title> Google Map by Gooby </title>
1378
1343
  #{content_hash['key_js']}
1379
1344
  #{content_hash['main_js_start']}
@@ -1450,11 +1415,12 @@ HERE
1450
1415
  end
1451
1416
 
1452
1417
  def generate_main_js_start
1453
- id = @options.get('gmap_map_element_id')
1454
- size = @options.get('gmap_size_control')
1455
- type = @options.get('gmap_type')
1456
- zoom = @options.get('gmap_zoom_level')
1457
- title = @options.get('gmap_title')
1418
+ id = @options.get('gmap_map_element_id')
1419
+ size = @options.get('gmap_size_control')
1420
+ type = @options.get('gmap_type')
1421
+ zoom = @options.get('gmap_zoom_level')
1422
+ title = @options.get('gmap_title')
1423
+ zoom_tab = @options.get('gmap_zoom_tab')
1458
1424
  if size
1459
1425
  if size == 'smallmap'
1460
1426
  size = 'GSmallMapControl'
@@ -1502,7 +1468,7 @@ HERE
1502
1468
  # s << ');'
1503
1469
  s << "\n"
1504
1470
  end
1505
- s << " var centerPoint = new GLatLng(#{@center_latitude}, #{@center_longitude}); \n"
1471
+ s << " var centerPoint = new GLatLng(#{@center_latitude}, #{@center_longitude}); // #{project_embedded_comment} \n"
1506
1472
  s << " map.setCenter(centerPoint, #{zoom}); \n"
1507
1473
  s << "\n"
1508
1474
  @content_hash['main_js_start'] = s
@@ -1510,11 +1476,11 @@ HERE
1510
1476
  end
1511
1477
 
1512
1478
  def generate_main_js_route_overlay
1513
- tkpt_count = @tkpts.size.to_f
1514
- app_max = @options.get('gmap_approx_max_points').to_f
1515
- comments = @options.get('gmap_gen_comments')
1516
- ratio = tkpt_count / app_max
1517
- @start_dttm = nil
1479
+ tkpt_count = @tkpts.size.to_f
1480
+ app_max = @options.get('gmap_approx_max_points').to_f
1481
+ gen_comments = @options.get('gmap_gen_comments')
1482
+ ratio = tkpt_count / app_max
1483
+ @start_dttm = nil
1518
1484
  if ratio > 1.0
1519
1485
  increment = (tkpt_count / app_max).to_i
1520
1486
  else
@@ -1531,8 +1497,10 @@ HERE
1531
1497
  end
1532
1498
  if ((curr_idx == next_idx) || (curr_idx == last_idx) || (tkpt.is_split()))
1533
1499
  gpoint_count = gpoint_count + 1
1534
- s << tkpt.as_glatlng(comments, tkpt_count, curr_idx, gpoint_count, @start_dttm)
1500
+ s << tkpt.as_glatlng(false, gen_comments, tkpt_count, curr_idx, @start_dttm)
1535
1501
  next_idx = curr_idx + increment
1502
+ else
1503
+ s << tkpt.as_glatlng(true, gen_comments, tkpt_count, curr_idx, @start_dttm)
1536
1504
  end
1537
1505
  }
1538
1506
  s << "\n"
@@ -1544,16 +1512,16 @@ HERE
1544
1512
 
1545
1513
  def generate_main_js_checkpoint_overlays
1546
1514
  s = "\n // Create a base icon for all of our markers that specifies the "
1547
- s << "\n // shadow, icon dimensions, etc."
1548
- s << "\n var baseIcon = new GIcon();"
1549
- s << "\n baseIcon.shadow = \"http://www.joakim-systems.com/gicons/shadow50.png\";"
1550
- s << "\n baseIcon.iconSize = new GSize(20, 34);"
1551
- s << "\n baseIcon.shadowSize = new GSize(37, 34);"
1552
- s << "\n baseIcon.iconAnchor = new GPoint(9, 34);"
1553
- s << "\n baseIcon.infoWindowAnchor = new GPoint(9, 2);"
1554
- s << "\n baseIcon.infoShadowAnchor = new GPoint(18, 25);"
1555
- s << "\n"
1556
-
1515
+ s << "\n // shadow, icon dimensions, etc."
1516
+ s << "\n var baseIcon = new GIcon();"
1517
+ s << "\n baseIcon.shadow = \"#{@icon_url_base}shadow50.png\";"
1518
+ s << "\n baseIcon.iconSize = new GSize(20, 34);"
1519
+ s << "\n baseIcon.shadowSize = new GSize(37, 34);"
1520
+ s << "\n baseIcon.iconAnchor = new GPoint(9, 34);"
1521
+ s << "\n baseIcon.infoWindowAnchor = new GPoint(9, 2);"
1522
+ s << "\n baseIcon.infoShadowAnchor = new GPoint(18, 25);"
1523
+ s << "\n"
1524
+
1557
1525
  curr_idx = -1
1558
1526
  last_idx = @tkpts.size - 1
1559
1527
  next_checkpoint = 0.0
@@ -1564,38 +1532,38 @@ HERE
1564
1532
  @start_dttm = tkpt.dttm
1565
1533
  info_window_html = tkpt.as_info_window_html('Start', @start_dttm)
1566
1534
  s << "\n var iconStart = new GIcon(baseIcon); "
1567
- s << "\n iconStart.image = \"http://www.joakim-systems.com/gicons/dd-start.png\";"
1535
+ s << "\n iconStart.image = \"#{@icon_url_base}dd-start.png\";"
1568
1536
  s << "\n var pStart = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
1569
1537
  s << "\n var mStart = new GMarker(pStart, iconStart);"
1570
1538
  s << "\n GEvent.addListener(mStart, \"click\", function() { "
1571
1539
  s << "\n mStart.openInfoWindowHtml(#{info_window_html});"
1572
- s << "\n }); "
1540
+ s << "\n }); "
1573
1541
  s << "\n map.addOverlay(mStart);"
1574
1542
  s << "\n "
1575
1543
  next_checkpoint = 1.0
1576
1544
  elsif curr_idx == last_idx
1577
1545
  info_window_html = tkpt.as_info_window_html('Finish', @start_dttm)
1578
1546
  s << "\n var iconFinish = new GIcon(baseIcon); "
1579
- s << "\n iconFinish.image = \"http://www.joakim-systems.com/gicons/dd-end.png\";"
1547
+ s << "\n iconFinish.image = \"#{@icon_url_base}dd-end.png\";"
1580
1548
  s << "\n var pFinish = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
1581
1549
  s << "\n var mFinish = new GMarker(pFinish, iconFinish);"
1582
1550
  s << "\n GEvent.addListener(mFinish, \"click\", function() { "
1583
1551
  s << "\n mFinish.openInfoWindowHtml(#{info_window_html});"
1584
- s << "\n }); "
1552
+ s << "\n }); "
1585
1553
  s << "\n map.addOverlay(mFinish);"
1586
1554
  s << "\n "
1587
1555
  next_checkpoint = 999999
1588
1556
  else
1589
- if (tkpt.cumulativeDistance >= next_checkpoint)
1557
+ if (tkpt.cumulative_distance >= next_checkpoint)
1590
1558
  integer = next_checkpoint.to_i
1591
1559
  info_window_html = tkpt.as_info_window_html("#{integer}", @start_dttm)
1592
1560
  s << "\n var icon#{integer} = new GIcon(baseIcon); "
1593
- s << "\n icon#{integer}.image = \"http://www.joakim-systems.com/gicons/marker#{integer}.png\";"
1561
+ s << "\n icon#{integer}.image = \"#{@icon_url_base}marker#{integer}.png\";"
1594
1562
  s << "\n var p#{integer} = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
1595
1563
  s << "\n var m#{integer} = new GMarker(p#{integer}, icon#{integer});"
1596
1564
  s << "\n GEvent.addListener(m#{integer}, \"click\", function() { "
1597
1565
  s << "\n m#{integer}.openInfoWindowHtml(#{info_window_html});"
1598
- s << "\n }); "
1566
+ s << "\n }); "
1599
1567
  s << "\n map.addOverlay(m#{integer});"
1600
1568
  s << "\n "
1601
1569
  next_checkpoint = next_checkpoint + 1.0
@@ -1628,9 +1596,9 @@ HERE
1628
1596
 
1629
1597
  @content_hash['main_js_end'] = s
1630
1598
  end
1631
-
1632
1599
  end
1633
-
1600
+
1601
+ # =============================================================================
1634
1602
 
1635
1603
  =begin rdoc
1636
1604
  Instances of this class represent a <History> aggregate object from a
@@ -1659,9 +1627,9 @@ HERE
1659
1627
  runs.each { | run | s << run.print_string }
1660
1628
  s
1661
1629
  end
1662
-
1663
1630
  end
1664
-
1631
+
1632
+ # =============================================================================
1665
1633
 
1666
1634
  =begin rdoc
1667
1635
  Instances of this class represent a <Lap> aggregate object from a
@@ -1670,22 +1638,18 @@ HERE
1670
1638
 
1671
1639
  class Lap < GoobyObject
1672
1640
 
1673
- attr_accessor :number, :startTime, :duration, :length, :beginPosition, :endPosition
1641
+ attr_accessor :number, :startTime, :duration, :length, :begin_position, :end_position
1674
1642
 
1675
1643
  def initialize(num)
1676
1644
  @number = num
1677
1645
  end
1678
1646
 
1679
1647
  def to_s
1680
- return "Lap: num: #{@number} start: #{@startTime} dur: #{@duration} len: #{@length} begin: #{@beginPosition.to_s} end: #{@endPosition.to_s}"
1648
+ return "Lap: num: #{@number} start: #{@startTime} dur: #{@duration} len: #{@length} begin: #{@begin_position.to_s} end: #{@end_position.to_s}"
1681
1649
  end
1682
-
1683
1650
  end
1684
1651
 
1685
-
1686
- =begin rdoc
1687
-
1688
- =end
1652
+ # =============================================================================
1689
1653
 
1690
1654
  class Line < GoobyObject
1691
1655
 
@@ -1755,21 +1719,20 @@ HERE
1755
1719
  end
1756
1720
  end
1757
1721
 
1758
-
1722
+ # =============================================================================
1723
+
1759
1724
  class Options < GoobyObject
1760
1725
 
1761
- attr_reader :yamlFilename, :options
1726
+ attr_reader :yaml_filename, :options
1762
1727
 
1763
1728
  def initialize(filename) # Constructor.
1764
- filename ? @yamlFilename = filename : @yamlFilename = 'gooby_options.yaml'
1729
+ filename ? @yaml_filename = filename : @yaml_filename = 'gooby_options.yaml'
1765
1730
  loadFile()
1766
1731
  end
1767
-
1768
- public
1769
1732
 
1770
- # Load the @yamlFilename
1733
+ # Load the @yaml_filename
1771
1734
  def loadFile
1772
- File.open("#{@yamlFilename}") { |fn|
1735
+ File.open("#{@yaml_filename}") { |fn|
1773
1736
  @options = YAML::load(fn)
1774
1737
  }
1775
1738
  end
@@ -1792,6 +1755,8 @@ HERE
1792
1755
  return 'map'
1793
1756
  elsif (name == 'gmap_height')
1794
1757
  return '600'
1758
+ elsif (name == 'gmap_icon_url_base')
1759
+ return 'http://www.your-web-site.com/gicons/'
1795
1760
  elsif (name == 'gmap_key')
1796
1761
  return 'enter your Google Map Key here'
1797
1762
  elsif (name == 'gmap_type_control')
@@ -1812,14 +1777,18 @@ HERE
1812
1777
  end
1813
1778
  s
1814
1779
  end
1780
+
1781
+ def size
1782
+ @options.size
1783
+ end
1815
1784
 
1816
1785
  # Return a String containing yaml filename and entry count.
1817
1786
  def to_s
1818
- return "Options: filename: #{@yamlFilename} entries: #{@options.size}"
1787
+ return "Options: filename: #{@yaml_filename} entries: #{@options.size}"
1819
1788
  end
1820
-
1821
1789
  end
1822
1790
 
1791
+ # =============================================================================
1823
1792
 
1824
1793
  =begin rdoc
1825
1794
  Instances of this class represent a <Position> aggregate object from a
@@ -1859,9 +1828,9 @@ HERE
1859
1828
  def altitude_as_float
1860
1829
  @altitude ? @altitude.to_f : invalid_altitude
1861
1830
  end
1862
-
1863
1831
  end
1864
1832
 
1833
+ # =============================================================================
1865
1834
 
1866
1835
  =begin rdoc
1867
1836
  Instances of this class represent a <Run> aggregate object from a
@@ -1896,7 +1865,7 @@ HERE
1896
1865
  unless @finished
1897
1866
  @tracks.each { |trk|
1898
1867
  trk.trackpoints().each { |tkpt|
1899
- tkpt.runNumber = @number
1868
+ tkpt.run_number = @number
1900
1869
  @tkpts.push(tkpt)
1901
1870
  }
1902
1871
  }
@@ -1922,7 +1891,7 @@ HERE
1922
1891
  @laps.push(lap)
1923
1892
  end
1924
1893
 
1925
- def lapCount()
1894
+ def lap_count()
1926
1895
  @laps.size
1927
1896
  end
1928
1897
 
@@ -1984,7 +1953,7 @@ HERE
1984
1953
  def to_s
1985
1954
  finish() unless @finished
1986
1955
  s = "Run: #{@number} date: #{start_yyyy_mm_dd} distance: #{distance} duration: #{duration} "
1987
- s << " tracks: #{@tracks.size} tkpts: #{trackpoint_count} laps: #{lapCount} "
1956
+ s << " tracks: #{@tracks.size} tkpts: #{trackpoint_count} laps: #{lap_count} "
1988
1957
  s << " notes: #{@notes} "
1989
1958
  s
1990
1959
  end
@@ -1996,13 +1965,13 @@ HERE
1996
1965
 
1997
1966
  def put_csv()
1998
1967
  finish() unless @finished
1999
- puts "#{@number}|#{}|#{start_yyyy_mm_dd()}|#{start_hh_mm_ss()}|#{end_hh_mm_ss}|#{duration()}|#{@distance}|#{@tracks.size}|#{trackpoint_count()}|#{lapCount}|#{@notes.strip}"
1968
+ puts "#{@number}|#{}|#{start_yyyy_mm_dd()}|#{start_hh_mm_ss()}|#{end_hh_mm_ss}|#{duration()}|#{@distance}|#{@tracks.size}|#{trackpoint_count()}|#{lap_count}|#{@notes.strip}"
2000
1969
  end
2001
1970
 
2002
1971
  def put_tkpt_csv(with_header_comment=false)
2003
1972
  finish() unless @finished
2004
1973
  if with_header_comment
2005
- puts "# Run: #{@number} date: #{start_yyyy_mm_dd} dist: #{distance} dur: #{duration} trks: #{@tracks.size} tkpts: #{trackpoint_count} laps: #{lapCount} "
1974
+ puts "# Run: #{@number} date: #{start_yyyy_mm_dd} dist: #{distance} dur: #{duration} trks: #{@tracks.size} tkpts: #{trackpoint_count} laps: #{lap_count} "
2006
1975
  end
2007
1976
  @tkpts.each { | tkpt | puts tkpt.to_csv }
2008
1977
  end
@@ -2033,14 +2002,14 @@ HERE
2033
2002
 
2034
2003
  def compute_splits
2035
2004
  nextSplitDist = 1.00
2036
- prevSplitTkpt = nil
2005
+ prev_splitTkpt = nil
2037
2006
  loop1Count = 0;
2038
2007
  @tkpts.each { |tkpt|
2039
2008
  loop1Count = loop1Count + 1
2040
- if tkpt.cumulativeDistance() >= nextSplitDist
2041
- tkpt.set_split(0 + nextSplitDist, prevSplitTkpt)
2009
+ if tkpt.cumulative_distance() >= nextSplitDist
2010
+ tkpt.set_split(0 + nextSplitDist, prev_splitTkpt)
2042
2011
  nextSplitDist = nextSplitDist + 1.00
2043
- prevSplitTkpt = tkpt
2012
+ prev_splitTkpt = tkpt
2044
2013
  end
2045
2014
  }
2046
2015
  # set first and last booleans
@@ -2051,12 +2020,13 @@ HERE
2051
2020
  tkpt.last = true if count == loop1Count
2052
2021
  }
2053
2022
  end
2054
-
2055
2023
  end
2056
-
2024
+
2025
+ # =============================================================================
2057
2026
 
2058
2027
  =begin rdoc
2059
2028
  Sample implementation of a REXML::StreamListener SAX parser.
2029
+ This class isn't actually used in Gooby, but is retained for future use.
2060
2030
  =end
2061
2031
 
2062
2032
  class SimpleXmlParser
@@ -2090,189 +2060,9 @@ HERE
2090
2060
  def dump
2091
2061
  puts @counter_hash.to_s
2092
2062
  end
2093
-
2094
- end
2095
-
2096
-
2097
- =begin rdoc
2098
- This class is used to generate, on an ongoing basis, the various Gooby test
2099
- classes. Regeneration retains the current test methods, and adds stubs for
2100
- new test methods. All methods, old and new, appear in the merged output in
2101
- propper sort sequence.
2102
- =end
2103
-
2104
- class TestGenerator < GoobyObject
2105
-
2106
- def initialize
2107
- tested_files.each { | base_rb_file |
2108
- test_file = "tc_#{base_rb_file}"
2109
- if true
2110
- @codeLines = read_lines("lib/#{base_rb_file}")
2111
- @testLines = read_lines("tests/#{test_file}")
2112
- @codeHash = Hash.new
2113
- @testHash = Hash.new
2114
- @mergedHash = Hash.new
2115
- @excludeClasses = %w( TestHelper TestGenerator )
2116
- puts "current codeLines = #{@codeLines.size}"
2117
- puts "current testLines = #{@testLines.size}"
2118
- parse_code_lines
2119
- parse_test_lines
2120
- merge_keys
2121
- regenerate(test_file)
2122
- end
2123
- }
2124
- end
2125
-
2126
- private
2127
-
2128
- # Produce a Hash with keys and values like the following:
2129
- # test|class|Trackpoint|deg2rad Trackpoint|deg2rad(degrees)
2130
-
2131
- def parse_code_lines
2132
- type = ''
2133
- type_name = ''
2134
- meth_name = ''
2135
- @codeLines.each { | line |
2136
- line.strip!
2137
- if (line.match(/^module /))
2138
- type = 'module'
2139
- tokens = line.split
2140
- type_name = tokens[1]
2141
- elsif (line.match(/^class /))
2142
- type = 'class'
2143
- tokens = line.split
2144
- type_name = tokens[1]
2145
- elsif (line.match(/^def /))
2146
- signature = line[4...999]
2147
- short_method = parse_meth_name("#{signature}")
2148
- @codeHash["test_#{type}_#{type_name}"] = "#{type_name}"
2149
- @codeHash["test_#{type}_#{type_name}_#{short_method}"] = "#{type_name}|#{signature}"
2150
- end
2151
- }
2152
- end
2153
-
2154
- def parse_meth_name(string)
2155
- string.gsub!('(', ' ')
2156
- string.gsub!(')', ' ')
2157
- tokens = string.split
2158
- tokens[0]
2159
- end
2160
-
2161
- def parse_test_lines
2162
- in_method = true
2163
- method_name = 'a_start'
2164
- method_lines = Array.new
2165
- line_num = 0
2166
-
2167
- @testLines.each { | line |
2168
- line_num = line_num + 1
2169
- line.chomp!
2170
- prefix = line[0...5] # ' def'
2171
- prefix21 = line[0...21] # ' ### Start of tests.'
2172
-
2173
- if ((prefix == ' def') || (prefix == "\tdef"))
2174
- in_method = true
2175
- tokens = line.split
2176
- method_name = tokens[1]
2177
- method_lines = Array.new
2178
- end
2179
- if in_method
2180
- method_lines << "#{line}"
2181
- end
2182
- if prefix21 == ' ### Start of tests.'
2183
- in_method = false
2184
- @testHash["#{method_name}"] = method_lines
2185
- end
2186
- if ((prefix == ' end') || (prefix == "\tend"))
2187
- in_method = false
2188
- @testHash["#{method_name}"] = method_lines
2189
- end
2190
- }
2191
- end
2192
-
2193
- def merge_keys
2194
- @codeHash.keys.sort.each { |key| @mergedHash["#{key}"] = "code" }
2195
- @testHash.keys.sort.each { |key| @mergedHash["#{key}"] = "test" }
2196
- end
2197
-
2198
- def regenerate(test_file)
2199
- code = ''
2200
- @mergedHash.keys.sort.each { |key|
2201
-
2202
- tokens = key.split('_')
2203
- type, name, meth = tokens[1], tokens[2], tokens[3]
2204
-
2205
- processThisKey = true
2206
- @excludeClasses.each { |xc|
2207
- if xc == name
2208
- processThisKey = false
2209
- end
2210
- }
2211
-
2212
- next if !processThisKey
2213
-
2214
- if @testHash.has_key?(key)
2215
- # We already have a test method written in the test class,
2216
- # so keep this currently existing test code!
2217
-
2218
- if @codeHash.has_key?(key)
2219
- comment = nil
2220
- else
2221
- if key != 'a_start'
2222
- comment = "# Warning: possible obsolete test method - #{key}"
2223
- end
2224
- end
2225
-
2226
- code << "\n"
2227
- if comment != nil
2228
- code << "\n#{comment}"
2229
- code << "\n"
2230
- end
2231
- array = @testHash["#{key}"]
2232
- array.each { |line| code << "\n#{line}" }
2233
- else
2234
- # We don't have this test method in the current test class,
2235
- # so generate a test method stub.
2236
-
2237
- code << "\n"
2238
- code << "\n def #{key}"
2239
- code << "\n"
2240
-
2241
- if @gen_impl_stub
2242
- if type = 'class'
2243
- code << "\n #obj = #{type}.new"
2244
- code << "\n #result = obj.#{meth}"
2245
- code << "\n #expected = ''"
2246
- s = "\n"
2247
- s << ' #assert_equal(expected, actual, "'
2248
- s << "#{type}.#{meth} "
2249
- s << 'values are not as expected; #{result} vs #{expected}")'
2250
- code << s
2251
- else
2252
- code << "\n #result = #{type}.#{meth}"
2253
- code << "\n #expected = ''"
2254
- s = "\n"
2255
- s << ' #assert_equal(expected, actual, "'
2256
- s << "#{type}.#{meth} "
2257
- s << 'values are not as expected; #{result} vs #{expected}")'
2258
- code << s
2259
- end
2260
- end
2261
- code << "\n end"
2262
- end
2263
- }
2264
- code << "\nend" # end of class
2265
- code << "\n"
2266
- fn = "tests/#{test_file}"
2267
- out = File.new fn, "w+"
2268
- out.write code
2269
- out.flush
2270
- out.close
2271
- puts "file written: #{fn}"
2272
- end
2273
-
2274
2063
  end
2275
2064
 
2065
+ # =============================================================================
2276
2066
 
2277
2067
  =begin rdoc
2278
2068
  Instances of this class represent a <Track> aggregate object from a Forerunner
@@ -2298,14 +2088,6 @@ HERE
2298
2088
  def size
2299
2089
  @trackpoints.size
2300
2090
  end
2301
-
2302
- def first_tkpt
2303
- @trackpoints.size > 0 ? @trackpoints[0] : nil
2304
- end
2305
-
2306
- def last_tkpt
2307
- @trackpoints.size > 0 ? @trackpoints[-1] : nil
2308
- end
2309
2091
 
2310
2092
  def to_s
2311
2093
  return "Trk: #{@descr} tkpts: #{size}"
@@ -2315,9 +2097,9 @@ HERE
2315
2097
  puts "Track: '#{@descr}' tkpts: #{size}"
2316
2098
  @trackpoints.each { |tkpt| puts tkpt.to_csv } # to_geo_s
2317
2099
  end
2318
-
2319
2100
  end
2320
2101
 
2102
+ # =============================================================================
2321
2103
 
2322
2104
  =begin rdoc
2323
2105
  Instances of this class represent a <Trackpoint> aggregate from a Forerunner
@@ -2336,13 +2118,13 @@ HERE
2336
2118
 
2337
2119
  class Trackpoint < Position
2338
2120
 
2339
- attr_reader :first, :last, :number, :runNumber, :dttm, :prevTkpt, :descr
2340
- attr_reader :cumulativeDistance, :cumulativePace, :incrementalDistance, :split, :prevSplit
2341
- attr_writer :first, :last, :runNumber
2121
+ attr_reader :first, :last, :number, :run_number, :dttm, :prev_tkpt, :descr
2122
+ attr_reader :cumulative_distance, :cumulative_pace, :incremental_distance, :split, :prev_split
2123
+ attr_writer :first, :last, :run_number
2342
2124
 
2343
2125
  def initialize(num, lat, lng, alt, time_string, descr='')
2344
2126
  @number = num
2345
- @runNumber = 0
2127
+ @run_number = 0
2346
2128
 
2347
2129
  # initialize superclass variables:
2348
2130
  @latitude = lat.to_s
@@ -2352,9 +2134,9 @@ HERE
2352
2134
  @dttm = DtTm.new(time_string)
2353
2135
  @first = false
2354
2136
  @last = false
2355
- @prevTkpt = nil
2356
- @cumulativeDistance, @split = 0.0, 0.0
2357
- @cumulativePace = ""
2137
+ @prev_tkpt = nil
2138
+ @cumulative_distance, @split = 0.0, 0.0
2139
+ @cumulative_pace = ""
2358
2140
  @descr = descr
2359
2141
  end
2360
2142
 
@@ -2365,12 +2147,12 @@ HERE
2365
2147
  end
2366
2148
 
2367
2149
  def to_s
2368
- "Tkpt: #{@number} #{super.to_s} date: #{@dttm.to_s} cdist: #{@cumulativeDistance}"
2150
+ "Tkpt: #{@number} #{super.to_s} date: #{@dttm.to_s} cdist: #{@cumulative_distance}"
2369
2151
  end
2370
2152
 
2371
2153
  def to_csv
2372
2154
  ss = position.to_csv
2373
- "#{@runNumber} | #{@dttm.to_s} | #{@number} | #{ss} | #{@cumulativeDistance} "
2155
+ "#{@run_number} | #{@dttm.to_s} | #{@number} | #{ss} | #{@cumulative_distance} "
2374
2156
  end
2375
2157
 
2376
2158
  def to_geo_s
@@ -2380,7 +2162,7 @@ HERE
2380
2162
 
2381
2163
  def compute_distance_and_pace(curr_index, start_dttm, prev_cumulative_dist, prev_trackpoint, units)
2382
2164
  @prev_tkpt = prev_trackpoint
2383
- @cumulativeDistance = prev_cumulative_dist.to_f
2165
+ @cumulative_distance = prev_cumulative_dist.to_f
2384
2166
 
2385
2167
  if @prev_tkpt
2386
2168
  arg1 = latitude().to_f
@@ -2410,54 +2192,46 @@ HERE
2410
2192
  if units == "N"
2411
2193
  incremental_distance = incremental_distance * 0.8684;
2412
2194
  end
2413
- @cumulativeDistance = @cumulativeDistance + incremental_distance.to_f
2195
+ @cumulative_distance = @cumulative_distance + incremental_distance.to_f
2414
2196
  end
2415
2197
  end
2416
2198
  end
2417
2199
  end
2418
2200
  compute_cumulative_pace(start_dttm)
2419
- @cumulativeDistance
2201
+ @cumulative_distance
2420
2202
  else
2421
2203
  0
2422
2204
  end
2423
2205
  end
2424
2206
 
2425
2207
  def compute_cumulative_pace(start_dttm)
2426
- if @cumulativeDistance > 0
2208
+ if @cumulative_distance > 0
2427
2209
  secsDiff = @dttm.seconds_diff(start_dttm)
2428
- secsMile = ((secsDiff.to_f) / (@cumulativeDistance.to_f))
2210
+ secsMile = ((secsDiff.to_f) / (@cumulative_distance.to_f))
2429
2211
  minsMile = (secsMile / 60)
2430
2212
  wholeMins = minsMile.floor
2431
2213
  secsBal = secsMile - (wholeMins * 60)
2432
- s1 = "#{secsDiff} #{secsMile} #{minsMile} #{wholeMins} #{secsBal} #{@cumulativeDistance} | "
2214
+ s1 = "#{secsDiff} #{secsMile} #{minsMile} #{wholeMins} #{secsBal} #{@cumulative_distance} | "
2433
2215
  s2 = sprintf("%d:%2.1f", minsMile, secsBal)
2434
- @cumulativePace = "#{s2}"
2216
+ @cumulative_pace = "#{s2}"
2435
2217
  else
2436
- @cumulativePace = ""
2218
+ @cumulative_pace = ""
2437
2219
  end
2438
2220
  end
2439
2221
 
2440
2222
  def set_split(n, tkpt)
2441
- @split, @prevSplit = n, tkpt
2223
+ @split, @prev_split = n, tkpt
2442
2224
  end
2443
2225
 
2444
2226
  def is_split()
2445
2227
  (@split >= 1)
2446
2228
  end
2447
2229
 
2448
- def is_first()
2449
- @first
2450
- end
2451
-
2452
- def is_last()
2453
- @last
2454
- end
2455
-
2456
2230
  def split_info(dtTm)
2457
2231
  if is_split
2458
2232
  hhmmss = ''
2459
- if @prevSplit
2460
- return "#{@split} #{@dttm.hhmmss_diff(@prevSplit.dttm())}"
2233
+ if @prev_split
2234
+ return "#{@split} #{@dttm.hhmmss_diff(@prev_split.dttm())}"
2461
2235
  else
2462
2236
  return "#{@split} #{@dttm.hhmmss_diff(dtTm)}"
2463
2237
  end
@@ -2478,14 +2252,15 @@ HERE
2478
2252
 
2479
2253
  public
2480
2254
 
2481
- def as_glatlng(comments, tkpt_count, curr_idx, gpoint_count, start_dttm)
2482
- if comments
2255
+ def as_glatlng(comment_out, gen_comments, tkpt_count, curr_idx, start_dttm)
2256
+ comment_out ? comment = '// ' : comment = ''
2257
+ if gen_comments
2483
2258
  secs_diff = @dttm.seconds_diff(start_dttm)
2484
2259
  fmt_time = @dttm.hhmmss_diff(start_dttm)
2485
- "\n points.push(new GLatLng(#{latitude_as_float},#{longitude_as_float})); " +
2486
- "// #{gpoint_count} (#{curr_idx + 1} of #{tkpt_count}) #{@dttm.to_s} #{secs_diff} #{fmt_time} #{@cumulativeDistance} #{split_info(start_dttm)} "
2260
+ "\n #{comment}points.push(new GLatLng(#{latitude_as_float},#{longitude_as_float})); " +
2261
+ "// (#{curr_idx + 1} of #{tkpt_count}) #{@dttm.to_s} #{secs_diff} #{fmt_time} #{@cumulative_distance} #{split_info(start_dttm)} #{project_embedded_comment} "
2487
2262
  else
2488
- "\n points.push(new GLatLng(#{latitude_as_float},#{longitude_as_float})); "
2263
+ "\n #{comment}points.push(new GLatLng(#{latitude_as_float},#{longitude_as_float})); // #{project_embedded_comment} "
2489
2264
  end
2490
2265
  end
2491
2266
 
@@ -2502,10 +2277,10 @@ HERE
2502
2277
  else
2503
2278
  s << "<tr><td colspan='2'><b>Checkpoint #{checkpoint}</b></td></tr>"
2504
2279
  end
2505
- s << "<tr><td>Distance: </td><td>#{@cumulativeDistance}</td></tr>"
2280
+ s << "<tr><td>Distance: </td><td>#{@cumulative_distance}</td></tr>"
2506
2281
  s << "<tr><td>Time of Day: </td><td>#{@dttm.to_s} </td></tr>"
2507
2282
  s << "<tr><td>Elapsed Time: </td><td>#{fmt_time} </td></tr>"
2508
- s << "<tr><td>Average Pace: </td><td>#{@cumulativePace} </td></tr>"
2283
+ s << "<tr><td>Average Pace: </td><td>#{@cumulative_pace} </td></tr>"
2509
2284
  s << "<tr><td>Lat/Lng: </td><td>#{latitude_as_float} , #{longitude_as_float} </td></tr>"
2510
2285
  s << "<tr><td>Altitude: </td><td>#{altitude_as_float}m </td></tr>"
2511
2286
  s
@@ -2513,13 +2288,313 @@ HERE
2513
2288
  s << "</table>\""
2514
2289
  s
2515
2290
  end
2516
-
2517
2291
  end
2518
2292
 
2293
+ # =============================================================================
2294
+
2295
+ =begin rdoc
2296
+ This class reads and scans the Gooby code for various purposes.
2297
+
2298
+ Primarily, it is used to regenerate, on an ongoing basis, the various
2299
+ regression tests in file 'ts_gooby.rb'. Regeneration retains the current
2300
+ test methods, adds stubs for new test methods, and flags obsolete methods.
2301
+
2302
+ It is also used to create a Gooby class, module, and method "quick reference"
2303
+ - somewhat similar to the TextMate symbol list.
2304
+
2305
+ TODO: Method indexing and where used" functionality.
2306
+ =end
2307
+
2308
+ class CodeScanner < GoobyObject
2309
+
2310
+ def initialize(argv)
2311
+
2312
+ function = 'outline'
2313
+ if (argv.size > 0)
2314
+ function = argv[0]
2315
+ end
2316
+
2317
+ @codebase_file = 'gooby.rb'
2318
+ @testbase_file = 'ts_gooby.rb'
2319
+ @code_lines = read_lines("lib/#{@codebase_file}")
2320
+ @test_lines = read_lines("tests/#{@testbase_file}")
2321
+
2322
+ puts "code lines = #{@code_lines.size}"
2323
+ puts "test lines = #{@test_lines.size}"
2324
+
2325
+ @tokens_hash = CounterHash.new
2326
+ @module_names_hash = CounterHash.new
2327
+ @class_names_hash = CounterHash.new
2328
+ @method_names_hash = CounterHash.new
2329
+ @mc_line_num_array = Array.new
2330
+ @type_names = Hash.new
2331
+ @code_hash = Hash.new
2332
+ @test_hash = Hash.new
2333
+ @api_hash = Hash.new
2334
+ @merged_hash = Hash.new
2335
+ @exclude_classes = Array.new
2336
+
2337
+ regenerate_test_suite if (function == 'regenerate_test_suite')
2338
+ regenerate_test_suite if (function == 'tests')
2339
+
2340
+ model_class_outline if (function == 'model_class_outline')
2341
+ model_class_outline if (function == 'outline')
2342
+
2343
+ quick_reference_guide if (function == 'quick_reference_guide')
2344
+ quick_reference_guide if (function == 'qrg')
2345
+
2346
+ mcm_references if (function == 'mcm_references')
2347
+ mcm_references if (function == 'mcm')
2348
+ end
2349
+
2350
+ private
2351
+
2352
+ def regenerate_test_suite
2353
+ @exclude_classes = %w( TestHelper CodeScanner )
2354
+ parse_code_lines
2355
+ parse_test_lines
2356
+ merge_keys
2357
+ regenerate(@testbase_file)
2358
+ end
2359
+
2360
+ def model_class_outline
2361
+ parse_code_lines
2362
+ @mc_line_num_array.each { |line|
2363
+ tokens = tokenize(line)
2364
+ type = tokens[0].ljust(6)
2365
+ name = tokens[1]
2366
+ count = tokens[2].rjust(6)
2367
+ puts " #{count} #{type} #{name}"
2368
+ }
2369
+ end
2370
+
2371
+ def quick_reference_guide
2372
+ parse_code_lines
2373
+ determine_longest_names
2374
+ quick_reference_guide_report('module')
2375
+ quick_reference_guide_report('class')
2376
+ end
2377
+
2378
+ def quick_reference_guide_report(obj_type)
2379
+ @api_hash.keys.sort.each { |key|
2380
+ val = @api_hash[key]
2381
+ tokens = tokenize(key, '|')
2382
+ if (tokens[0] == obj_type)
2383
+ s1 = tokens[0].ljust(6)
2384
+ s2 = tokens[1].ljust(@longest_classname + 1)
2385
+ s3 = tokens[2]
2386
+ # s = sprintf("%6s '%30s %s'", tokens[0], tokens[1], tokens[2])
2387
+ puts "#{s1} #{s2} #{s3}"
2388
+ end
2389
+ }
2390
+ end
2391
+
2392
+ def determine_longest_names
2393
+ @longest_classname = 0
2394
+ @api_hash.keys.sort.each { |key|
2395
+ tokens = tokenize(@api_hash[key], '|')
2396
+ @longest_classname = tokens[1].size if tokens[1].size > @longest_classname
2397
+ }
2398
+ end
2399
+
2400
+ def mcm_references
2401
+ parse_code_lines
2402
+ determine_longest_names
2403
+ @module_names_hash.sorted_keys.each { |name|
2404
+ count = @tokens_hash.value(name)
2405
+ puts "module: #{name} (#{count})"
2406
+ }
2407
+ @class_names_hash.sorted_keys.each { |name|
2408
+ count = @tokens_hash.value(name)
2409
+ puts "class: #{name} (#{count})"
2410
+ }
2411
+ @method_names_hash.sorted_keys.each { |name|
2412
+ count = @tokens_hash.value(name)
2413
+ puts "method: #{name} (#{count})"
2414
+ }
2415
+ # puts @tokens_hash.to_s
2416
+ # puts @tokens_hash.size
2417
+ end
2418
+
2419
+ def parse_code_lines
2420
+ type = ''
2421
+ type_name = ''
2422
+ meth_name = ''
2423
+ line_number = 0
2424
+ @code_lines.each { | line |
2425
+ line_number = line_number + 1
2426
+ line.strip!
2427
+ if (line.match(/^module /))
2428
+ type = 'module'
2429
+ tokens = line.split
2430
+ type_name = tokens[1]
2431
+ @module_names_hash.increment(type_name)
2432
+ @mc_line_num_array << "module #{type_name} #{line_number}"
2433
+ elsif (line.match(/^class /))
2434
+ type = 'class'
2435
+ tokens = line.split
2436
+ type_name = tokens[1]
2437
+ @class_names_hash.increment(type_name)
2438
+ @mc_line_num_array << "class #{type_name} #{line_number}"
2439
+ elsif (line.match(/^def /))
2440
+ signature = line[4...999]
2441
+ short_method = parse_meth_name("#{signature}")
2442
+ @code_hash["test_#{type}_#{type_name}"] = "#{type_name}"
2443
+ @code_hash["test_#{type}_#{type_name}_#{short_method}"] = "#{type_name}|#{signature}"
2444
+ @api_hash["#{type}|#{type_name}|#{signature}" ] = "#{type}|#{type_name}|#{signature}"
2445
+ @method_names_hash.increment(short_method)
2446
+ end
2447
+ increment_tokens(line)
2448
+ }
2449
+ end
2450
+
2451
+ def increment_tokens(line)
2452
+ # see http://www.asciitable.com/
2453
+ s = ''
2454
+ line.each_byte { |b|
2455
+ keep = false
2456
+ keep = true if ((b >= 65) && (b <= 90)) # A-Z
2457
+ keep = true if ((b >= 97) && (b <= 122)) # a-z
2458
+ keep = true if ((b >= 48) && (b <= 57)) # 0-9
2459
+ keep = true if (b == 95) # _
2460
+ keep = true if (b == 64) # @
2461
+ keep = true if (b == 63) # ?
2462
+ keep = true if (b == 33) # !
2463
+ if keep
2464
+ s << b.chr
2465
+ else
2466
+ s << ' '
2467
+ end
2468
+ }
2469
+ @tokens_hash.increment_tokens(s)
2470
+ end
2471
+
2472
+ def parse_meth_name(string)
2473
+ string.gsub!('(', ' ')
2474
+ string.gsub!(')', ' ')
2475
+ tokens = string.split
2476
+ tokens[0]
2477
+ end
2478
+
2479
+ def parse_test_lines
2480
+ in_zone = true
2481
+ method_name = 'a_start'
2482
+ method_lines = Array.new
2483
+ line_num = 0
2484
+
2485
+ @test_lines.each { | line |
2486
+ line_num = line_num + 1
2487
+ line.chomp!
2488
+ prefix = line[0...5] # ' def' or ' end'
2489
+ prefix42 = line [0..42]
2490
+
2491
+ if ((prefix == ' def') || (prefix == "\tdef"))
2492
+ in_zone = true
2493
+ tokens = line.split
2494
+ method_name = tokens[1]
2495
+ method_lines = Array.new
2496
+ end
2497
+
2498
+ if in_zone
2499
+ method_lines << "#{line}"
2500
+ end
2501
+ if (prefix42 == ' # beginning of tests - keep this marker')
2502
+ in_zone = false
2503
+ @test_hash["aaa"] = method_lines
2504
+ end
2505
+ if ((prefix == ' end') || (prefix == "\tend"))
2506
+ in_zone = false
2507
+ @test_hash["#{method_name}"] = method_lines
2508
+ end
2509
+ }
2510
+ end
2511
+
2512
+ def merge_keys
2513
+ @merged_hash = Hash.new
2514
+ @code_hash.keys.sort.each { |key| @merged_hash["#{key}"] = "code" }
2515
+ @test_hash.keys.sort.each { |key| @merged_hash["#{key}"] = "test" }
2516
+ end
2517
+
2518
+ def regenerate(test_file)
2519
+ code = ''
2520
+ @merged_hash.keys.sort.each { |key|
2521
+ tokens = key.split('_')
2522
+ type, name, meth = tokens[1], tokens[2], tokens[3]
2523
+
2524
+ processThisKey = true
2525
+ @exclude_classes.each { |xc|
2526
+ if xc == name
2527
+ processThisKey = false
2528
+ end
2529
+ }
2530
+
2531
+ next if !processThisKey
2532
+
2533
+ if @test_hash.has_key?(key)
2534
+ # We already have a test method written in the test class,
2535
+ # so keep this currently existing test code!
2536
+
2537
+ if @code_hash.has_key?(key)
2538
+ comment = nil
2539
+ else
2540
+ if key != 'a_start'
2541
+ comment = "# Warning: possible obsolete test method - #{key}"
2542
+ end
2543
+ end
2544
+
2545
+ code << "\n"
2546
+ if comment != nil
2547
+ code << "\n#{comment}"
2548
+ code << "\n"
2549
+ end
2550
+ array = @test_hash["#{key}"]
2551
+ array.each { |line| code << "\n#{line}" }
2552
+ else
2553
+ # We don't have this test method in the current test class,
2554
+ # so generate a test method stub.
2555
+ code << "\n"
2556
+ code << "\n def #{key}"
2557
+ code << "\n"
2558
+
2559
+ if @gen_impl_stub
2560
+ if type = 'class'
2561
+ code << "\n #obj = #{type}.new"
2562
+ code << "\n #result = obj.#{meth}"
2563
+ code << "\n #expected = ''"
2564
+ s = "\n"
2565
+ s << ' #assert_equal(expected, actual, "'
2566
+ s << "#{type}.#{meth} "
2567
+ s << 'values are not as expected; #{result} vs #{expected}")'
2568
+ code << s
2569
+ else
2570
+ code << "\n #result = #{type}.#{meth}"
2571
+ code << "\n #expected = ''"
2572
+ s = "\n"
2573
+ s << ' #assert_equal(expected, actual, "'
2574
+ s << "#{type}.#{meth} "
2575
+ s << 'values are not as expected; #{result} vs #{expected}")'
2576
+ code << s
2577
+ end
2578
+ end
2579
+ code << "\n end"
2580
+ end
2581
+ }
2582
+ code << "\nend" # end of class
2583
+ code << "\n"
2584
+ fn = "tests/#{test_file}"
2585
+ out = File.new fn, "w+"
2586
+ out.write code
2587
+ out.flush
2588
+ out.close
2589
+ puts "file written: #{fn}"
2590
+ end
2591
+ end
2592
+
2593
+ # =============================================================================
2519
2594
 
2520
2595
  =begin rdoc
2521
2596
  This class provides "user friendly DSL" functionality for the use
2522
- of Gooby.
2597
+ of Gooby. See 'bin/example_usage.rb' for examples using this class.
2523
2598
  =end
2524
2599
 
2525
2600
  class GoobyCommand < GoobyObject
@@ -2557,7 +2632,5 @@ HERE
2557
2632
  generator = Gooby::GoogleMapGenerator.new(csv_filename)
2558
2633
  generator.generate_page(options_obj)
2559
2634
  end
2560
-
2561
2635
  end
2562
-
2563
2636
  end # end of module