gooby 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. data/README +200 -35
  2. data/bin/code_scan.rb +1 -3
  3. data/bin/gooby_been_there.rb +12 -14
  4. data/bin/gooby_config.rb +11 -3
  5. data/bin/gooby_csv_validation.rb +50 -0
  6. data/bin/gooby_first_trackpoints_as_poi.rb +31 -0
  7. data/bin/gooby_gen_gmap.rb +7 -3
  8. data/bin/gooby_parser.rb +7 -5
  9. data/bin/gooby_splitter.rb +7 -4
  10. data/bin/gooby_version.rb +7 -3
  11. data/bin/run_all.sh +12 -2
  12. data/bin/run_been_there.sh +4 -1
  13. data/bin/run_config.sh +12 -0
  14. data/bin/run_csv_validation.sh +15 -0
  15. data/bin/run_db_gen.sh +1 -1
  16. data/bin/run_db_load.sh +1 -1
  17. data/bin/run_first_trackpoints_as_poi.sh +16 -0
  18. data/bin/run_gen_gmaps.sh +7 -6
  19. data/bin/run_parse_full.sh +45 -0
  20. data/bin/run_parse_samples.sh +21 -0
  21. data/bin/run_split.sh +5 -4
  22. data/bin/run_version.sh +12 -0
  23. data/config/gooby_config.yaml +130 -131
  24. data/data/20050305_corporate_cup_hm.csv +251 -251
  25. data/data/20050430_nashville_marathon_km.csv +1208 -0
  26. data/data/20060115_phoenix_marathon.csv +1280 -1280
  27. data/data/20070101_davidson_11m.csv +251 -0
  28. data/data/{davidson_11m_20070101.xml → 20070101_davidson_11m.xml} +0 -0
  29. data/data/{davidson_5K_20070505.xml → 20070505_davidson_5k.xml} +0 -0
  30. data/data/20070505_davidson_5k_km.csv +286 -0
  31. data/data/hrm1.csv +5 -0
  32. data/lib/gooby.rb +27 -3144
  33. data/lib/gooby_code_scanner.rb +288 -0
  34. data/lib/gooby_command.rb +210 -0
  35. data/lib/gooby_configuration.rb +123 -0
  36. data/lib/gooby_counter_hash.rb +95 -0
  37. data/lib/gooby_course.rb +117 -0
  38. data/lib/gooby_csv_point.rb +71 -0
  39. data/lib/gooby_csv_reader.rb +71 -0
  40. data/lib/gooby_csv_run.rb +28 -0
  41. data/lib/gooby_delim_line.rb +42 -0
  42. data/lib/gooby_dttm.rb +87 -0
  43. data/lib/gooby_duration.rb +86 -0
  44. data/lib/gooby_forerunner_xml_parser.rb +191 -0
  45. data/lib/gooby_forerunner_xml_splitter.rb +115 -0
  46. data/lib/gooby_google_map_generator.rb +385 -0
  47. data/lib/gooby_history.rb +41 -0
  48. data/lib/gooby_kernel.rb +163 -0
  49. data/lib/gooby_lap.rb +30 -0
  50. data/lib/gooby_line.rb +80 -0
  51. data/lib/gooby_object.rb +22 -0
  52. data/lib/gooby_point.rb +172 -0
  53. data/lib/gooby_run.rb +213 -0
  54. data/lib/gooby_simple_xml_parser.rb +50 -0
  55. data/lib/gooby_test_helper.rb +23 -0
  56. data/lib/gooby_track.rb +47 -0
  57. data/lib/gooby_track_point.rb +229 -0
  58. data/lib/gooby_training_center_xml_parser.rb +224 -0
  59. data/lib/gooby_training_center_xml_splitter.rb +116 -0
  60. data/lib/split_code.sh +29 -0
  61. data/samples/20050305_corporate_cup_hm.html +269 -269
  62. data/samples/20050430_nashville_marathon.html +1410 -1266
  63. data/samples/20060115_phoenix_marathon.html +1311 -1311
  64. data/samples/{davidson_11m_20070101.html → 20070101_davidson_11m.html} +267 -267
  65. data/samples/20070505_davidson_5k.html +413 -0
  66. data/samples/been_there.txt +52 -704
  67. data/samples/hrm1.html +87 -0
  68. data/sql/gooby.ddl +20 -16
  69. data/sql/gooby_load.dml +36 -9
  70. metadata +48 -14
  71. data/bin/example_usage.txt +0 -55
  72. data/bin/run_parse.sh +0 -43
  73. data/bin/run_parse_named.sh +0 -19
  74. data/data/20050430_nashville_marathon.csv +0 -1208
  75. data/data/davidson_11m_20070101.csv +0 -251
  76. data/data/davidson_5K_20070505.csv +0 -286
  77. data/data/test1.txt +0 -4
  78. data/samples/davidson_5K_20070505.html +0 -395
@@ -0,0 +1,385 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class represent a <Run> aggregate object from a
13
+ Forerunner XML file.
14
+
15
+ Additionally, there is distance, pace, and Google Map generation logic
16
+ in this class.
17
+ =end
18
+
19
+ class GoogleMapGenerator < GoobyObject
20
+
21
+ attr_reader :csv_file, :csv_lines, :dttm_idx, :num_idx, :lat_idx, :lng_idx, :alt_idx, :cdist_idx
22
+ attr_reader :run, :tkpts, :content_hash, :center_longitude, :center_latitude, :gpoint_array, :overlay_points, :notes
23
+ attr_reader :center_longitude, :center_latitude
24
+
25
+ # The default csv input file format is as follows:
26
+ # 1 | 2006-01-15T18:31:10Z | 1279 | 33.42601 | -111.92927 | 347.654 | 26.3514930151813
27
+ # 1 | 2004-11-13T13:05:20Z | 2 | 37.54318 | -77.43636 | -58.022 | 0.00297286231747969
28
+
29
+ def initialize(csv_file, dttm_idx=1, num_idx=4, lat_idx=5, lng_idx=6, alt_idx=7, cdist_idx=8)
30
+ @csv_file = csv_file
31
+ @dttm_idx = dttm_idx
32
+ @num_idx = num_idx
33
+ @lat_idx = lat_idx
34
+ @lng_idx = lng_idx
35
+ @alt_idx = alt_idx
36
+ @cdist_idx = cdist_idx
37
+
38
+ # Override default csv value indices if specified in the configuration yaml file.
39
+ @configuration = Gooby::Configuration.get_config
40
+ @dttm_idx = @configuration.get('csv_dttm_idx') if @configuration.get('csv_dttm_idx')
41
+ @num_idx = @configuration.get('csv_num_idx') if @configuration.get('csv_num_idx')
42
+ @lat_idx = @configuration.get('csv_lat_idx') if @configuration.get('csv_lat_idx')
43
+ @lng_idx = @configuration.get('csv_lng_idx') if @configuration.get('csv_lng_idx')
44
+ @alt_idx = @configuration.get('csv_alt_idx') if @configuration.get('csv_alt_idx')
45
+ @title = @configuration.get("#{@csv_file}")
46
+
47
+ @content_hash = Hash.new('')
48
+ @run = Gooby::Run.new(1)
49
+ @track = Gooby::Track.new(1)
50
+ @run.add_track(@track)
51
+ @tkpts = Array.new
52
+ @icon_url_base = @configuration.get('gmap_icon_url_base')
53
+
54
+ list = Array.new
55
+ list << @csv_file
56
+ @csv_reader = Gooby::CsvReader.new(list)
57
+ @csv_points = @csv_reader.read
58
+ @csv_points.each { |csv_point|
59
+ tkpt = csv_point.as_trackpoint
60
+ if tkpt
61
+ @track.add_trackpoint(tkpt)
62
+ end
63
+ }
64
+ @run.finish
65
+ end
66
+
67
+ =begin
68
+ Returns a Hash with specific generated content at the following keys:
69
+ =end
70
+ def generate(configuration)
71
+ if (configuration == nil)
72
+ @configuration = Gooby::Configuration.get_config
73
+ else
74
+ @configuration = configuration
75
+ end
76
+ @content_hash['when_generated'] = Time.now
77
+ @content_hash['title'] = @title
78
+ @icon_url_base = @configuration.get('gmap_icon_url_base')
79
+ filter_trackpoints
80
+ compute_center_point
81
+ generate_key_js
82
+ generate_map_div
83
+ generate_messages_div
84
+ generate_main_js_start
85
+ generate_main_js_route_overlay
86
+ generate_main_js_checkpoint_overlays
87
+ generate_main_js_map_clicked_listeners
88
+ generate_main_js_end
89
+ @content_hash
90
+ end
91
+
92
+ def filter_trackpoints
93
+ count, @tkpts = 0, Array.new
94
+ firstTkpt = @configuration.get('gmap_first_tkpt_number')
95
+ lastTkpt = @configuration.get('gmap_last_tkpt_number')
96
+ @run.tracks.each { |trk|
97
+ trk.trackpoints.each { |tkpt|
98
+ count = count + 1
99
+ if ((count >= firstTkpt) && (count <= lastTkpt))
100
+ @tkpts.push(tkpt)
101
+ end
102
+ }
103
+ }
104
+ end
105
+
106
+ =begin
107
+ Returns a Hash with specific generated content at the following keys:
108
+ =end
109
+ def generate_page(configuration)
110
+
111
+ # puts "generate_page #{@csv_file} #{@csv_lines.size}"
112
+ content_hash = generate(nil)
113
+ s = String.new(@csv_file)
114
+ s.gsub("/", " ")
115
+ tokens = tokenize(s, nil)
116
+ out_file = "#{tokens[-2]}.html"
117
+ #content_hash.keys.sort.each { | key | puts key }
118
+
119
+ s = <<HERE
120
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
121
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
122
+ <html xmlns="http://www.w3.org/1999/xhtml">
123
+ <head>
124
+ <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
125
+ <meta name="description" content="Google Map generated with #{project_embedded_comment}">
126
+ <meta name="keywords" content="Google Map #{project_embedded_comment} GPS">
127
+ <title> Google Map by Gooby </title>
128
+ #{content_hash['key_js']}
129
+ #{content_hash['main_js_start']}
130
+ #{content_hash['main_js_route_overlay']}
131
+ #{content_hash['main_js_checkpoint_overlays']}
132
+ #{content_hash['main_js_map_clicked_listeners']}
133
+ #{content_hash['main_js_end']}
134
+ </head>
135
+ <body onload="load()" onunload="GUnload()">
136
+ <center>
137
+ <h3> #{@title} </h3>
138
+ <h5> Generated by Gooby #{content_hash['when_generated']} <br> Gooby = Google APIs + Ruby </h5>
139
+ #{content_hash['map_div']}
140
+ #{content_hash['messages_div']}
141
+ </center>
142
+ </body>
143
+ </html>
144
+ HERE
145
+ puts s # Redirect output via shell.
146
+ end
147
+
148
+ private
149
+
150
+ def compute_center_point
151
+ highLat = -999.0
152
+ highLong = -999.0
153
+ lowLat = 999.0
154
+ lowLong = 999.0
155
+ @tkpts.each { |tkpt|
156
+ highLat = tkpt.latitude_as_float if tkpt.latitude_as_float > highLat
157
+ lowLat = tkpt.latitude_as_float if tkpt.latitude_as_float < lowLat
158
+ highLong = tkpt.longitude_as_float if tkpt.longitude_as_float > highLong
159
+ lowLong = tkpt.longitude_as_float if tkpt.longitude_as_float < lowLong
160
+ }
161
+ @center_longitude = (highLong + lowLong) / 2
162
+ @center_latitude = (highLat + lowLat) / 2
163
+ @content_hash['center_longitude'] = @center_longitude
164
+ @content_hash['center_latitude'] = @center_latitude
165
+ end
166
+
167
+ def generate_key_js
168
+ key = @configuration.get('gmap_key')
169
+ key.strip!
170
+ # <script src="http://maps.google.com/maps?file=api&v=2&key=<%= @gmap_key -%>" type="text/javascript"></script>
171
+ s = "<script src='http://maps.google.com/maps?file=api&v=2&key="
172
+ s << key
173
+ s << "' type='text/javascript'></script>"
174
+ @content_hash['key_js'] = s
175
+ end
176
+
177
+ def generate_map_div
178
+ width = @configuration.get('gmap_width')
179
+ height = @configuration.get('gmap_height')
180
+ id = @configuration.get('gmap_map_element_id')
181
+ s = '<div id="'
182
+ s << id
183
+ s << '" style="width: '
184
+ s << width
185
+ s << '; height: '
186
+ s << height
187
+ s << '"></div>'
188
+ @content_hash['map_width'] = width
189
+ @content_hash['map_height'] = height
190
+ @content_hash['map_div'] = s
191
+ end
192
+
193
+ def generate_messages_div
194
+ s = "<div id=\"messages\"></div>"
195
+ @content_hash['messages_div'] = s
196
+ end
197
+
198
+ def generate_main_js_start
199
+ id = @configuration.get('gmap_map_element_id')
200
+ size = @configuration.get('gmap_size_control')
201
+ type = @configuration.get('gmap_type')
202
+ zoom = @configuration.get('gmap_zoom_level')
203
+ title = @configuration.get("#{@csv_file}")
204
+ title = '' if title == nil
205
+ zoom_tab = @configuration.get('gmap_zoom_tab')
206
+ if size
207
+ if size == 'smallmap'
208
+ size = 'GSmallMapControl'
209
+ elsif size == 'smallzoom'
210
+ size = 'GSmallMapControl'
211
+ else
212
+ size = 'GLargeMapControl'
213
+ end
214
+ end
215
+
216
+ if type
217
+ if type == 'satellite'
218
+ type = 'G_SATELLITE_MAP'
219
+ elsif type == 'hybrid'
220
+ type = 'G_HYBRID_MAP'
221
+ else
222
+ type = 'G_NORMAL_MAP'
223
+ end
224
+ else
225
+ type = 'G_NORMAL_MAP'
226
+ end
227
+
228
+ s = '<script type="text/javascript">'
229
+ s << "\n"
230
+ s << "//<![CDATA[ \n"
231
+ s << " function load() { \n"
232
+ s << " if (GBrowserIsCompatible()) { \n"
233
+ s << ' var map = new GMap2(document.getElementById("'
234
+ s << id
235
+ s << '")); '
236
+ s << "\n"
237
+
238
+ if size
239
+ s << ' map.addControl(new '
240
+ s << size
241
+ s << '());'
242
+ s << "\n"
243
+ end
244
+
245
+ if type
246
+ s << ' map.addControl(new GMapTypeControl());'
247
+ s << "\n"
248
+ # s << ' map.setMapType('
249
+ # s << type
250
+ # s << ');'
251
+ s << "\n"
252
+ end
253
+ s << " var centerPoint = new GLatLng(#{@center_latitude}, #{@center_longitude}); // #{project_embedded_comment} \n"
254
+ s << " map.setCenter(centerPoint, #{zoom}); \n"
255
+ s << "\n"
256
+ @content_hash['main_js_start'] = s
257
+ @content_hash['title'] = title
258
+ end
259
+
260
+ def generate_main_js_route_overlay
261
+ tkpt_count = @tkpts.size.to_f
262
+ app_max = @configuration.get('gmap_approx_max_points').to_f
263
+ gen_comments = @configuration.get('gmap_gen_comments')
264
+ ratio = tkpt_count / app_max
265
+ @start_dttm = nil
266
+ if ratio > 1.0
267
+ increment = (tkpt_count / app_max).to_i
268
+ else
269
+ increment = 1
270
+ end
271
+ curr_idx, next_idx, gpoint_count, last_idx = -1, 0, 0, @tkpts.size - 1
272
+ s = " var points = new Array(); "
273
+ @tkpts.each { |tkpt|
274
+ curr_idx = curr_idx + 1
275
+ if curr_idx == 0
276
+ @start_dttm = tkpt.dttm
277
+ @start_pos = tkpt.point
278
+
279
+ time = Time.parse(@start_dttm.dateTime().to_s)
280
+ end
281
+ if ((curr_idx == next_idx) || (curr_idx == last_idx) || (tkpt.is_split()))
282
+ gpoint_count = gpoint_count + 1
283
+ s << tkpt.as_glatlng(false, gen_comments, tkpt_count, curr_idx, @start_dttm)
284
+ next_idx = curr_idx + increment
285
+ else
286
+ s << tkpt.as_glatlng(true, gen_comments, tkpt_count, curr_idx, @start_dttm)
287
+ end
288
+ }
289
+ s << "\n"
290
+ s << "\n var routePolyline = new GPolyline(points); "
291
+ s << "\n map.addOverlay(routePolyline); "
292
+ @content_hash['main_js_route_overlay'] = s
293
+ @content_hash['main_js_route_overlay_increment'] = increment
294
+ end
295
+
296
+ def generate_main_js_checkpoint_overlays
297
+ s = "\n // Create a base icon for all of our markers that specifies the "
298
+ s << "\n // shadow, icon dimensions, etc."
299
+ s << "\n var baseIcon = new GIcon();"
300
+ s << "\n baseIcon.shadow = \"#{@icon_url_base}shadow50.png\";"
301
+ s << "\n baseIcon.iconSize = new GSize(20, 34);"
302
+ s << "\n baseIcon.shadowSize = new GSize(37, 34);"
303
+ s << "\n baseIcon.iconAnchor = new GPoint(9, 34);"
304
+ s << "\n baseIcon.infoWindowAnchor = new GPoint(9, 2);"
305
+ s << "\n baseIcon.infoShadowAnchor = new GPoint(18, 25);"
306
+ s << "\n"
307
+
308
+ curr_idx = -1
309
+ last_idx = @tkpts.size - 1
310
+ next_checkpoint = 0.0
311
+ @start_dttm = nil
312
+ @tkpts.each { | tkpt |
313
+ curr_idx = curr_idx + 1
314
+ if curr_idx == 0
315
+ @start_dttm = tkpt.dttm
316
+ info_window_html = tkpt.as_info_window_html('Start', @start_dttm)
317
+ s << "\n var iconStart = new GIcon(baseIcon); "
318
+ s << "\n iconStart.image = \"#{@icon_url_base}dd-start.png\";"
319
+ s << "\n var pStart = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
320
+ s << "\n var mStart = new GMarker(pStart, iconStart);"
321
+ s << "\n GEvent.addListener(mStart, \"click\", function() { "
322
+ s << "\n mStart.openInfoWindowHtml(#{info_window_html});"
323
+ s << "\n }); "
324
+ s << "\n map.addOverlay(mStart);"
325
+ s << "\n "
326
+ next_checkpoint = 1.0
327
+ elsif curr_idx == last_idx
328
+ info_window_html = tkpt.as_info_window_html('Finish', @start_dttm)
329
+ s << "\n var iconFinish = new GIcon(baseIcon); "
330
+ s << "\n iconFinish.image = \"#{@icon_url_base}dd-end.png\";"
331
+ s << "\n var pFinish = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
332
+ s << "\n var mFinish = new GMarker(pFinish, iconFinish);"
333
+ s << "\n GEvent.addListener(mFinish, \"click\", function() { "
334
+ s << "\n mFinish.openInfoWindowHtml(#{info_window_html});"
335
+ s << "\n }); "
336
+ s << "\n map.addOverlay(mFinish);"
337
+ s << "\n "
338
+ next_checkpoint = 999999
339
+ else
340
+ if (tkpt.cumulative_distance >= next_checkpoint)
341
+ integer = next_checkpoint.to_i
342
+ info_window_html = tkpt.as_info_window_html("#{integer}", @start_dttm)
343
+ s << "\n var icon#{integer} = new GIcon(baseIcon); "
344
+ s << "\n icon#{integer}.image = \"#{@icon_url_base}marker#{integer}.png\";"
345
+ s << "\n var p#{integer} = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
346
+ s << "\n var m#{integer} = new GMarker(p#{integer}, icon#{integer});"
347
+ s << "\n GEvent.addListener(m#{integer}, \"click\", function() { "
348
+ s << "\n m#{integer}.openInfoWindowHtml(#{info_window_html});"
349
+ s << "\n }); "
350
+ s << "\n map.addOverlay(m#{integer});"
351
+ s << "\n "
352
+ next_checkpoint = next_checkpoint + 1.0
353
+ end
354
+ end
355
+ }
356
+ s << "\n"
357
+ @content_hash['main_js_checkpoint_overlays'] = s
358
+
359
+ end
360
+
361
+ def generate_main_js_map_clicked_listeners
362
+ s = "\n"
363
+ s << "\n GEvent.addListener(map, \"click\", function() { "
364
+ s << "\n var center = map.getCenter(); \n"
365
+ s << "\n document.getElementById(\"messages\").innerHTML = 'click: ' + center.toString(); "
366
+ s << "\n });"
367
+ s << "\n GEvent.addListener(map, \"moveend\", function() { "
368
+ s << "\n var center = map.getCenter(); \n"
369
+ s << "\n document.getElementById(\"messages\").innerHTML = 'moveend: ' + center.toString(); "
370
+ s << "\n });"
371
+ @content_hash['main_js_map_clicked_listeners'] = s
372
+ end
373
+
374
+ def generate_main_js_end
375
+ s = "\n } "
376
+ s << "\n } "
377
+ s << "\n//]]> \n"
378
+ s << "\n</script>"
379
+
380
+ @content_hash['main_js_end'] = s
381
+ end
382
+
383
+ end
384
+
385
+ end # end of module
@@ -0,0 +1,41 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class represent a <History> aggregate object from a
13
+ Forerunner XML file.
14
+ =end
15
+
16
+ class History < GoobyObject
17
+
18
+ attr_reader :runs
19
+
20
+ def initialize
21
+ @runs = Array.new
22
+ end
23
+
24
+ # Adds a Run during XML parsing.
25
+ def add_run(run)
26
+ @runs.push(run)
27
+ end
28
+
29
+ def to_s
30
+ return "Hist: runs: #{@runs.size}"
31
+ end
32
+
33
+ def print_string
34
+ s = "History: run count=#{@runs.size} \n"
35
+ runs.each { | run | s << run.print_string }
36
+ s
37
+ end
38
+
39
+ end
40
+
41
+ end # end of module
@@ -0,0 +1,163 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ This module is used to embed information about the Gooby project and
13
+ version into the codebase.
14
+ =end
15
+
16
+ module GoobyKernel
17
+
18
+ def project_name
19
+ 'Gooby'
20
+ end
21
+
22
+ def project_version_number
23
+ '1.2.0'
24
+ end
25
+
26
+ # Return a String date, like '2007/03/21'.
27
+ def project_date
28
+ '2007/07/22'
29
+ end
30
+
31
+ # Return a String containing the project author name.
32
+ def project_author
33
+ 'Chris Joakim'
34
+ end
35
+
36
+ # Return a String year, like '2007'.
37
+ def project_year
38
+ project_date[0...4] # start, length
39
+ end
40
+
41
+ # Return a String containing copyright, year, and author.
42
+ def project_copyright
43
+ "Copyright (C) #{project_year} #{project_author}"
44
+ end
45
+
46
+ def project_embedded_comment
47
+ "#{project_name} #{project_version_number}"
48
+ end
49
+
50
+ # Return a String containing GNU/GPL, and the gpl.html URL.
51
+ def project_license
52
+ 'GNU General Public License (GPL). See http://www.gnu.org/copyleft/gpl.html'
53
+ end
54
+
55
+ # Return an Array of lines in file, optionally stripped.
56
+ def read_lines(filename, strip=false)
57
+
58
+ array = IO.readlines(filename)
59
+ if strip
60
+ array = strip_lines(array)
61
+ end
62
+ return array
63
+ end
64
+
65
+ # Return an Array of lines in file per the given delimeter, optionally stripped.
66
+ def read_as_ascii_lines(filename, delim=10, strip=false)
67
+
68
+ array = Array.new
69
+ file = File.new(filename)
70
+ currLine = ''
71
+ bytesRead = 0
72
+ linesRead = 0
73
+
74
+ file.each_byte { |b|
75
+ bytesRead = bytesRead + 1
76
+ if (b == delim) # delim is 13 for quicken, 10 for address book xml
77
+ array << currLine
78
+ currLine = ''
79
+ linesRead = linesRead + 1
80
+ else
81
+ if (b < 127)
82
+ currLine << "#{b.chr}"
83
+ end
84
+ end
85
+ }
86
+
87
+ if currLine.size > 0
88
+ array << currLine
89
+ end
90
+ if strip
91
+ array = strip_lines(array)
92
+ end
93
+ return array
94
+ end
95
+
96
+ # Strip the lines/Strings; return a new Array.
97
+ def strip_lines(array)
98
+
99
+ newArray = Array.new
100
+ if (array != nil)
101
+ array.each { |line| line.strip! ; newArray << line }
102
+ end
103
+ return newArray
104
+ end
105
+
106
+ def tokenize(string, delim=nil, strip=false)
107
+ if string
108
+ tokens = string.split(delim)
109
+ if strip
110
+ tokens.each { |tok| tok.strip! }
111
+ end
112
+ tokens
113
+ else
114
+ Array.new
115
+ end
116
+ end
117
+
118
+ def character_align(character, number, left_length, right_length)
119
+ tokens = number.to_s.split("#{character}")
120
+ integer = tokens[0].to_s
121
+ fraction = tokens[1].to_s
122
+ lpad_size = left_length - integer.size
123
+ rpad_size = right_length - fraction.size
124
+ if lpad_size > 0
125
+ lpad_size.times do |i|
126
+ integer = " #{integer}"
127
+ end
128
+ end
129
+ if rpad_size > 0
130
+ rpad_size.times do |i|
131
+ fraction = "#{fraction} "
132
+ end
133
+ end
134
+ "#{integer}.#{fraction}"
135
+ end
136
+
137
+ def default_delimiter
138
+ return '|'
139
+ end
140
+
141
+ def invalid_time
142
+ return -99999999
143
+ end
144
+
145
+ def invalid_latitude
146
+ return -1
147
+ end
148
+
149
+ def invalid_longitude
150
+ return -1
151
+ end
152
+
153
+ def invalid_altitude
154
+ return -1
155
+ end
156
+
157
+ def invalid_heartbeat
158
+ return -1
159
+ end
160
+
161
+ end
162
+
163
+ end # end of module