gooby 0.9.4 → 0.9.5

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