postrunner 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +74 -11
- data/Rakefile +10 -0
- data/lib/postrunner/ActivitiesDB.rb +120 -32
- data/lib/postrunner/Activity.rb +34 -11
- data/lib/postrunner/ActivityListView.rb +195 -0
- data/lib/postrunner/ActivitySummary.rb +141 -0
- data/lib/postrunner/ActivityView.rb +41 -71
- data/lib/postrunner/ChartView.rb +72 -33
- data/lib/postrunner/DeviceList.rb +104 -0
- data/lib/postrunner/FlexiTable.rb +42 -7
- data/lib/postrunner/HTMLBuilder.rb +12 -0
- data/lib/postrunner/Main.rb +68 -9
- data/lib/postrunner/PersonalRecords.rb +12 -0
- data/lib/postrunner/RuntimeConfig.rb +80 -0
- data/lib/postrunner/TrackView.rb +25 -8
- data/lib/postrunner/UserProfileView.rb +70 -0
- data/lib/postrunner/ViewWidgets.rb +107 -0
- data/lib/postrunner/version.rb +13 -1
- data/lib/postrunner.rb +12 -0
- data/misc/icons/back.png +0 -0
- data/misc/icons/back.svg +68 -0
- data/misc/icons/first.png +0 -0
- data/misc/icons/first.svg +64 -0
- data/misc/icons/forward.png +0 -0
- data/misc/icons/forward.svg +64 -0
- data/misc/icons/home.png +0 -0
- data/misc/icons/home.svg +64 -0
- data/misc/icons/last.png +0 -0
- data/misc/icons/last.svg +64 -0
- data/misc/icons/lgpl-3.0.txt +165 -0
- data/postrunner.gemspec +1 -1
- data/spec/ActivitySummary_spec.rb +28 -0
- data/spec/FlexiTable_spec.rb +19 -1
- data/spec/PostRunner_spec.rb +25 -21
- data/spec/spec_helper.rb +62 -0
- metadata +26 -8
- data/LICENSE.txt +0 -22
- data/lib/postrunner/ActivityReport.rb +0 -102
@@ -1,3 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = FlexiTable.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
require 'postrunner/HTMLBuilder'
|
2
14
|
|
3
15
|
module PostRunner
|
@@ -11,6 +23,7 @@ module PostRunner
|
|
11
23
|
def initialize(attrs = {})
|
12
24
|
@min_terminal_width = nil
|
13
25
|
@halign = nil
|
26
|
+
@width = nil
|
14
27
|
|
15
28
|
attrs.each do |name, value|
|
16
29
|
ivar_name = '@' + name.to_s
|
@@ -70,8 +83,18 @@ module PostRunner
|
|
70
83
|
end
|
71
84
|
|
72
85
|
def to_html(doc)
|
73
|
-
|
74
|
-
|
86
|
+
text_align = get_attribute(:halign)
|
87
|
+
attrs = { :class => 'ft_cell' }
|
88
|
+
width = get_attribute(:width)
|
89
|
+
attrs[:width] = width if width
|
90
|
+
attrs[:style] = "text-align: #{text_align.to_s}" if text_align
|
91
|
+
if @content.respond_to?('to_html')
|
92
|
+
doc.td(attrs) {
|
93
|
+
@content.to_html(doc)
|
94
|
+
}
|
95
|
+
else
|
96
|
+
doc.td(@content.to_s, attrs)
|
97
|
+
end
|
75
98
|
end
|
76
99
|
|
77
100
|
private
|
@@ -79,7 +102,8 @@ module PostRunner
|
|
79
102
|
def get_attribute(name)
|
80
103
|
@attributes[name] ||
|
81
104
|
@row.attributes[name] ||
|
82
|
-
@table.column_attributes[@column_index]
|
105
|
+
(@table.column_attributes[@column_index] ?
|
106
|
+
@table.column_attributes[@column_index][name] : nil)
|
83
107
|
end
|
84
108
|
|
85
109
|
end
|
@@ -88,8 +112,9 @@ module PostRunner
|
|
88
112
|
|
89
113
|
attr_reader :attributes
|
90
114
|
|
91
|
-
def initialize(table)
|
115
|
+
def initialize(table, section)
|
92
116
|
@table = table
|
117
|
+
@section = section
|
93
118
|
@attributes = Attributes.new
|
94
119
|
super()
|
95
120
|
end
|
@@ -101,6 +126,7 @@ module PostRunner
|
|
101
126
|
end
|
102
127
|
|
103
128
|
def set_indicies(col_idx, row_idx)
|
129
|
+
@index = row_idx
|
104
130
|
self[col_idx].set_indicies(col_idx, row_idx)
|
105
131
|
end
|
106
132
|
|
@@ -120,7 +146,9 @@ module PostRunner
|
|
120
146
|
end
|
121
147
|
|
122
148
|
def to_html(doc)
|
123
|
-
|
149
|
+
css_class = @section == :head ? 'ft_head_row' :
|
150
|
+
@index % 2 == 0 ? 'ft_even_row' : 'ft_odd_row'
|
151
|
+
doc.tr({ :class => css_class }) {
|
124
152
|
each { |c| c.to_html(doc) }
|
125
153
|
}
|
126
154
|
end
|
@@ -139,12 +167,17 @@ module PostRunner
|
|
139
167
|
@current_row = nil
|
140
168
|
|
141
169
|
@frame = true
|
170
|
+
@html_attrs = { :class => 'flexitable' }
|
142
171
|
|
143
172
|
@column_attributes = []
|
144
173
|
|
145
174
|
instance_eval(&block) if block_given?
|
146
175
|
end
|
147
176
|
|
177
|
+
def set_html_attrs(name, value)
|
178
|
+
@html_attrs[name] = value
|
179
|
+
end
|
180
|
+
|
148
181
|
def head
|
149
182
|
@current_section = :head
|
150
183
|
end
|
@@ -172,7 +205,7 @@ module PostRunner
|
|
172
205
|
@foot_rows
|
173
206
|
else
|
174
207
|
raise "Unknown section #{@current_section}"
|
175
|
-
end << (@current_row = Row.new(self))
|
208
|
+
end << (@current_row = Row.new(self, @current_section))
|
176
209
|
end
|
177
210
|
@current_row.cell(content, attributes)
|
178
211
|
end
|
@@ -217,7 +250,9 @@ module PostRunner
|
|
217
250
|
end
|
218
251
|
|
219
252
|
def to_html(doc)
|
220
|
-
|
253
|
+
index_table
|
254
|
+
|
255
|
+
doc.table(@html_attrs) {
|
221
256
|
@head_rows.each { |r| r.to_html(doc) }
|
222
257
|
@body_rows.each { |r| r.to_html(doc) }
|
223
258
|
@foot_rows.each { |r| r.to_html(doc) }
|
@@ -1,3 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = HTMLBuilder.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
require 'nokogiri'
|
2
14
|
|
3
15
|
module PostRunner
|
data/lib/postrunner/Main.rb
CHANGED
@@ -1,8 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = Main.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
require 'optparse'
|
2
14
|
require 'logger'
|
3
15
|
require 'fit4ruby'
|
4
16
|
|
5
17
|
require 'postrunner/version'
|
18
|
+
require 'postrunner/RuntimeConfig'
|
6
19
|
require 'postrunner/ActivitiesDB'
|
7
20
|
|
8
21
|
module PostRunner
|
@@ -24,6 +37,7 @@ module PostRunner
|
|
24
37
|
|
25
38
|
return if (args = parse_options(args)).nil?
|
26
39
|
|
40
|
+
@cfg = RuntimeConfig.new(@db_dir)
|
27
41
|
execute_command(args)
|
28
42
|
end
|
29
43
|
|
@@ -105,8 +119,10 @@ check [ <fit file> | <ref> ... ]
|
|
105
119
|
dump <fit file> | <ref>
|
106
120
|
Dump the content of the FIT file.
|
107
121
|
|
108
|
-
import <fit file> | <directory>
|
109
|
-
Import the provided FIT file(s) into the postrunner database.
|
122
|
+
import [ <fit file> | <directory> ]
|
123
|
+
Import the provided FIT file(s) into the postrunner database. If no
|
124
|
+
file or directory is provided, the directory that was used for the
|
125
|
+
previous import is being used.
|
110
126
|
|
111
127
|
delete <ref>
|
112
128
|
Delete the activity from the archive.
|
@@ -121,11 +137,23 @@ rename <ref>
|
|
121
137
|
Replace the FIT file name with a more meaningful name that describes
|
122
138
|
the activity.
|
123
139
|
|
124
|
-
show <ref>
|
125
|
-
Show the FIT activity in a web browser.
|
140
|
+
show [ <ref> ]
|
141
|
+
Show the referenced FIT activity in a web browser. If no reference
|
142
|
+
is provided show the list of activities in the database.
|
126
143
|
|
127
144
|
summary <ref>
|
128
145
|
Display the summary information for the FIT file.
|
146
|
+
|
147
|
+
units metric | statute
|
148
|
+
Change the unit system.
|
149
|
+
|
150
|
+
|
151
|
+
<fit file> An absolute or relative name of a .FIT file.
|
152
|
+
|
153
|
+
<ref> The index or a range of indexes to activities in the database.
|
154
|
+
:1 is the newest imported activity
|
155
|
+
:-1 is the oldest imported activity
|
156
|
+
:1-2 refers to the first and second activity in the database
|
129
157
|
EOT
|
130
158
|
|
131
159
|
end
|
@@ -134,7 +162,7 @@ EOT
|
|
134
162
|
end
|
135
163
|
|
136
164
|
def execute_command(args)
|
137
|
-
@activities = ActivitiesDB.new(@db_dir)
|
165
|
+
@activities = ActivitiesDB.new(@db_dir, @cfg)
|
138
166
|
|
139
167
|
case (cmd = args.shift)
|
140
168
|
when 'check'
|
@@ -149,7 +177,18 @@ EOT
|
|
149
177
|
@filter = Fit4Ruby::FitFilter.new unless @filter
|
150
178
|
process_files_or_activities(args, :dump)
|
151
179
|
when 'import'
|
152
|
-
|
180
|
+
if args.empty?
|
181
|
+
# If we have no file or directory for the import command, we get the
|
182
|
+
# most recently used directory from the runtime config.
|
183
|
+
process_files([ @cfg.get_option(:import_dir) ], :import)
|
184
|
+
else
|
185
|
+
process_files(args, :import)
|
186
|
+
if args.length == 1 && Dir.exists?(args[0])
|
187
|
+
# If only one directory was specified as argument we store the
|
188
|
+
# directory for future use.
|
189
|
+
@cfg.set_option(:import_dir, args[0])
|
190
|
+
end
|
191
|
+
end
|
153
192
|
when 'list'
|
154
193
|
@activities.list
|
155
194
|
when 'records'
|
@@ -157,9 +196,15 @@ EOT
|
|
157
196
|
when 'rename'
|
158
197
|
process_activities(args, :rename)
|
159
198
|
when 'show'
|
160
|
-
|
199
|
+
if args.empty?
|
200
|
+
@activities.show_list_in_browser
|
201
|
+
else
|
202
|
+
process_activities(args, :show)
|
203
|
+
end
|
161
204
|
when 'summary'
|
162
205
|
process_activities(args, :summary)
|
206
|
+
when 'units'
|
207
|
+
change_unit_system(args)
|
163
208
|
when nil
|
164
209
|
Log.fatal("No command provided. " +
|
165
210
|
"See 'postrunner -h' for more information.")
|
@@ -180,6 +225,10 @@ EOT
|
|
180
225
|
end
|
181
226
|
|
182
227
|
def process_activities(activity_refs, command)
|
228
|
+
if activity_refs.empty?
|
229
|
+
Log.fatal("You must provide at least one activity reference.")
|
230
|
+
end
|
231
|
+
|
183
232
|
activity_refs.each do |a_ref|
|
184
233
|
if a_ref[0] == ':'
|
185
234
|
activities = @activities.find(a_ref[1..-1])
|
@@ -192,12 +241,11 @@ EOT
|
|
192
241
|
Log.fatal "Activity references must start with ':': #{a_ref}"
|
193
242
|
end
|
194
243
|
end
|
195
|
-
|
196
244
|
end
|
197
245
|
|
198
246
|
def process_files(files_or_dirs, command)
|
199
247
|
if files_or_dirs.empty?
|
200
|
-
Log.fatal("You must provide at least one .FIT file name")
|
248
|
+
Log.fatal("You must provide at least one .FIT file name.")
|
201
249
|
end
|
202
250
|
|
203
251
|
files_or_dirs.each do |fod|
|
@@ -249,6 +297,17 @@ EOT
|
|
249
297
|
end
|
250
298
|
end
|
251
299
|
|
300
|
+
def change_unit_system(args)
|
301
|
+
if args.length != 1 || !%w( metric statute ).include?(args[0])
|
302
|
+
Log.fatal("You must specify 'metric' or 'statute' as unit system.")
|
303
|
+
end
|
304
|
+
|
305
|
+
if @cfg[:unit_system].to_s != args[0]
|
306
|
+
@cfg.set_option(:unit_system, args[0].to_sym)
|
307
|
+
@activities.generate_all_html_reports
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
252
311
|
end
|
253
312
|
|
254
313
|
end
|
@@ -1,3 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = PersonalRecords.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
require 'fileutils'
|
2
14
|
require 'yaml'
|
3
15
|
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = ActivitiesDB.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'yaml'
|
14
|
+
require 'fit4ruby'
|
15
|
+
|
16
|
+
module PostRunner
|
17
|
+
|
18
|
+
# Simple class to manage runtime configuration options which are persisted
|
19
|
+
# in a YAML file.
|
20
|
+
class RuntimeConfig
|
21
|
+
|
22
|
+
# Create a new RC object.
|
23
|
+
# @param dir [String] the directory to hold the config.yml file.
|
24
|
+
def initialize(dir)
|
25
|
+
@options = {
|
26
|
+
:unit_system => :metric,
|
27
|
+
:import_dir => nil
|
28
|
+
}
|
29
|
+
@config_file = File.join(dir, 'config.yml')
|
30
|
+
|
31
|
+
load_options if File.exist?(@config_file)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Shortcut for get_option.
|
35
|
+
# @param name [Symbol] the name of the config option.
|
36
|
+
# @return [Object] the value of the config option.
|
37
|
+
def [](name)
|
38
|
+
get_option(name)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Get a config option value.
|
42
|
+
# @param name [Symbol] the name of the config option.
|
43
|
+
# @return [Object] the value of the config option.
|
44
|
+
def get_option(name)
|
45
|
+
@options[name]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set a config option and update the RC file.
|
49
|
+
# @param name [Symbol] The name of the config option.
|
50
|
+
# @param value [Object] The value of the config option.
|
51
|
+
def set_option(name, value)
|
52
|
+
@options[name] = value
|
53
|
+
save_options
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def load_options
|
59
|
+
begin
|
60
|
+
opts = YAML::load_file(@config_file)
|
61
|
+
rescue IOError
|
62
|
+
Log.error "Cannot load config file '#{@config_file}': #{$!}"
|
63
|
+
end
|
64
|
+
# Merge the loaded options into the @options hash.
|
65
|
+
opts.each { |key, value| @options[key] = value }
|
66
|
+
end
|
67
|
+
|
68
|
+
def save_options
|
69
|
+
begin
|
70
|
+
File.write(@config_file, @options.to_yaml)
|
71
|
+
Log.info "Runtime config file '#{@config_file}' written"
|
72
|
+
rescue
|
73
|
+
Log.error "Cannot write config file '#{@config_file}': #{$!}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
data/lib/postrunner/TrackView.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = TrackView.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
require 'fit4ruby'
|
2
14
|
|
3
15
|
require 'postrunner/ViewWidgets'
|
@@ -10,9 +22,13 @@ module PostRunner
|
|
10
22
|
|
11
23
|
def initialize(activity)
|
12
24
|
@activity = activity
|
25
|
+
@session = @activity.fit_activity.sessions[0]
|
26
|
+
@has_geo_data = @session.has_geo_data?
|
13
27
|
end
|
14
28
|
|
15
29
|
def head(doc)
|
30
|
+
return unless @has_geo_data
|
31
|
+
|
16
32
|
doc.link({ 'rel' => 'stylesheet',
|
17
33
|
'href' => 'openlayers/theme/default/style.css',
|
18
34
|
'type' => 'text/css' })
|
@@ -22,6 +38,8 @@ module PostRunner
|
|
22
38
|
end
|
23
39
|
|
24
40
|
def div(doc)
|
41
|
+
return unless @has_geo_data
|
42
|
+
|
25
43
|
frame(doc, 'Map') {
|
26
44
|
doc.div({ 'id' => 'map', 'class' => 'trackmap' })
|
27
45
|
}
|
@@ -36,7 +54,7 @@ module PostRunner
|
|
36
54
|
}
|
37
55
|
|
38
56
|
.trackmap {
|
39
|
-
width:
|
57
|
+
width: 565px;
|
40
58
|
height: 400px;
|
41
59
|
border: 2px solid #545454;
|
42
60
|
}
|
@@ -52,11 +70,10 @@ function init() {
|
|
52
70
|
var geographic = new OpenLayers.Projection("EPSG:4326");
|
53
71
|
EOT
|
54
72
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
(session.nec_lat - session.swc_lat) / 2.0
|
73
|
+
center_long = @session.swc_long +
|
74
|
+
(@session.nec_long - @session.swc_long) / 2.0
|
75
|
+
center_lat = @session.swc_lat +
|
76
|
+
(@session.nec_lat - @session.swc_lat) / 2.0
|
60
77
|
last_lap = @activity.fit_activity.laps[-1]
|
61
78
|
|
62
79
|
js << <<EOT
|
@@ -84,8 +101,8 @@ EOT
|
|
84
101
|
var size = new OpenLayers.Size(21,25);
|
85
102
|
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
|
86
103
|
EOT
|
87
|
-
set_marker(js, 'marker-green', session.start_position_long,
|
88
|
-
session.start_position_lat)
|
104
|
+
set_marker(js, 'marker-green', @session.start_position_long,
|
105
|
+
@session.start_position_lat)
|
89
106
|
@activity.fit_activity.laps[0..-2].each do |lap|
|
90
107
|
set_marker(js, 'marker-blue',
|
91
108
|
lap.end_position_long, lap.end_position_lat)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = UserProfileView.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'fit4ruby'
|
14
|
+
|
15
|
+
require 'postrunner/ViewWidgets'
|
16
|
+
|
17
|
+
module PostRunner
|
18
|
+
|
19
|
+
class UserProfileView
|
20
|
+
|
21
|
+
include ViewWidgets
|
22
|
+
|
23
|
+
def initialize(fit_activity, unit_system)
|
24
|
+
@fit_activity = fit_activity
|
25
|
+
@unit_system = unit_system
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_html(doc)
|
29
|
+
return nil if @fit_activity.user_profiles.empty?
|
30
|
+
|
31
|
+
frame(doc, 'User Profile') {
|
32
|
+
profile.to_html(doc)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
return '' if @fit_activity.user_profiles.empty?
|
38
|
+
profile.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def profile
|
44
|
+
t = FlexiTable.new
|
45
|
+
profile = @fit_activity.user_profiles.first
|
46
|
+
if profile.height
|
47
|
+
unit = { :metric => 'm', :statute => 'ft' }[@unit_system]
|
48
|
+
height = profile.get_as('height', unit)
|
49
|
+
t.cell('Height:', { :width => '40%' })
|
50
|
+
t.cell("#{'%.1f' % height} #{unit}", { :width => '60%' })
|
51
|
+
t.new_row
|
52
|
+
end
|
53
|
+
if profile.weight
|
54
|
+
unit = { :metric => 'kg', :statute => 'lbs' }[@unit_system]
|
55
|
+
weight = profile.get_as('weight', unit)
|
56
|
+
t.row([ 'Weight:', "#{'%.1f' % weight} #{unit}" ])
|
57
|
+
end
|
58
|
+
t.row([ 'Gender:', profile.gender ]) if profile.gender
|
59
|
+
t.row([ 'Age:', "#{profile.age} years" ]) if profile.age
|
60
|
+
t.row([ 'Max. Heart Rate:', "#{profile.max_hr} bpm" ]) if profile.max_hr
|
61
|
+
if profile.activity_class
|
62
|
+
t.row([ 'Activity Class:', profile.activity_class ])
|
63
|
+
end
|
64
|
+
t
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
@@ -1,9 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = ViewWidgets.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
module PostRunner
|
2
14
|
|
3
15
|
module ViewWidgets
|
4
16
|
|
5
17
|
def view_widgets_style(doc)
|
6
18
|
doc.style(<<EOT
|
19
|
+
.titlebar {
|
20
|
+
width: 100%;
|
21
|
+
height: 50px;
|
22
|
+
margin: 0px;
|
23
|
+
background: linear-gradient(#7FA1FF 0, #002EAC 50px);
|
24
|
+
}
|
25
|
+
.title {
|
26
|
+
float: left;
|
27
|
+
font-size: 24pt;
|
28
|
+
font-style: italic;
|
29
|
+
font-weight: bold;
|
30
|
+
color: #F8F8F8;
|
31
|
+
text-shadow: -1px -1px 0 #5C5C5C,
|
32
|
+
1px -1px 0 #5C5C5C,
|
33
|
+
-1px 1px 0 #5C5C5C,
|
34
|
+
1px 1px 0 #5C5C5C;
|
35
|
+
padding: 3px 30px;
|
36
|
+
}
|
37
|
+
.navigator {
|
38
|
+
float: right;
|
39
|
+
padding: 3px 30px;
|
40
|
+
}
|
41
|
+
.active_button {
|
42
|
+
padding: 5px;
|
43
|
+
}
|
44
|
+
.inactive_button {
|
45
|
+
padding: 5px;
|
46
|
+
opacity: 0.4;
|
47
|
+
}
|
7
48
|
.widget_frame {
|
8
49
|
box-sizing: border-box;
|
9
50
|
width: 600px;
|
@@ -23,7 +64,36 @@ module PostRunner
|
|
23
64
|
-webkit-box-shadow: 0 3px 10px rgba(0,0,0,0.1);
|
24
65
|
}
|
25
66
|
.widget_frame_title {
|
67
|
+
font-size:13pt;
|
26
68
|
padding-bottom: 5px;
|
69
|
+
text-align: left;
|
70
|
+
}
|
71
|
+
.flexitable {
|
72
|
+
width: 100%;
|
73
|
+
border: 2px solid #545454;
|
74
|
+
border-collapse: collapse;
|
75
|
+
font-size:11pt;
|
76
|
+
}
|
77
|
+
.ft_head_row {
|
78
|
+
background-color: #DEDEDE
|
79
|
+
}
|
80
|
+
.ft_even_row {
|
81
|
+
background-color: #FCFCFC
|
82
|
+
}
|
83
|
+
.ft_odd_row {
|
84
|
+
background-color: #F1F1F1
|
85
|
+
}
|
86
|
+
.ft_cell {
|
87
|
+
border: 1px solid #CCCCCC;
|
88
|
+
padding: 1px 3px;
|
89
|
+
}
|
90
|
+
.footer {
|
91
|
+
clear: both;
|
92
|
+
width: 100%;
|
93
|
+
height: 30px;
|
94
|
+
padding: 15px;
|
95
|
+
text-align: center;
|
96
|
+
font-size: 9pt;
|
27
97
|
}
|
28
98
|
EOT
|
29
99
|
)
|
@@ -40,6 +110,43 @@ EOT
|
|
40
110
|
}
|
41
111
|
end
|
42
112
|
|
113
|
+
def titlebar(doc, first_page = nil, prev_page = nil, home_page = nil,
|
114
|
+
next_page = nil, last_page = nil)
|
115
|
+
# The top title bar.
|
116
|
+
doc.div({ :class => 'titlebar' }) {
|
117
|
+
doc.div('PostRunner', { :class => 'title' })
|
118
|
+
doc.div({ :class => 'navigator' }) {
|
119
|
+
button(doc, first_page, 'first.png')
|
120
|
+
button(doc, prev_page, 'back.png')
|
121
|
+
button(doc, home_page, 'home.png')
|
122
|
+
button(doc, next_page, 'forward.png')
|
123
|
+
button(doc, last_page, 'last.png')
|
124
|
+
}
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
def button(doc, link, icon)
|
129
|
+
if link
|
130
|
+
doc.a({ :href => link }) {
|
131
|
+
doc.img({ :src => "icons/#{icon}", :class => 'active_button' })
|
132
|
+
}
|
133
|
+
else
|
134
|
+
doc.img({ :src => "icons/#{icon}", :class => 'inactive_button' })
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def footer(doc)
|
139
|
+
doc.div({ :class => 'footer' }){
|
140
|
+
doc.hr
|
141
|
+
doc.div({ :class => 'copyright' }) {
|
142
|
+
doc.text("Generated by ")
|
143
|
+
doc.a('PostRunner',
|
144
|
+
{ :href => 'https://github.com/scrapper/postrunner' })
|
145
|
+
doc.text(" #{VERSION} on #{Time.now}")
|
146
|
+
}
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
43
150
|
end
|
44
151
|
|
45
152
|
end
|
data/lib/postrunner/version.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = version.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
module PostRunner
|
2
|
-
VERSION = "0.0.
|
14
|
+
VERSION = "0.0.5"
|
3
15
|
end
|
data/lib/postrunner.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = postrunner.rb -- PostRunner - Manage the data from your Garmin sport devices.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
1
13
|
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', 'fit4ruby', 'lib'))
|
2
14
|
$:.unshift(File.dirname(__FILE__))
|
3
15
|
|
data/misc/icons/back.png
ADDED
Binary file
|