summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Schlaeger <chris@linux.com>2014-08-29 22:45:11 +0200
committerChris Schlaeger <chris@linux.com>2014-08-29 22:45:11 +0200
commit033c7916e8cb05b4d65ad5c7c9d6179efa0a0e29 (patch)
treef6ca1b8c7c2f92a67cce56e393eae6206bded909
parent3c32e378c9ffc01c1ed994483571193127a4e6a4 (diff)
downloadpostrunner-033c7916e8cb05b4d65ad5c7c9d6179efa0a0e29.zip
Adding device info and user profile to HTML view
-rw-r--r--lib/postrunner/ActivityView.rb6
-rw-r--r--lib/postrunner/DeviceList.rb104
-rw-r--r--lib/postrunner/FlexiTable.rb10
-rw-r--r--lib/postrunner/UserProfileView.rb70
-rw-r--r--spec/ActivitySummary_spec.rb2
-rw-r--r--spec/spec_helper.rb10
6 files changed, 195 insertions, 7 deletions
diff --git a/lib/postrunner/ActivityView.rb b/lib/postrunner/ActivityView.rb
index bde8d42..790a0aa 100644
--- a/lib/postrunner/ActivityView.rb
+++ b/lib/postrunner/ActivityView.rb
@@ -14,6 +14,8 @@ require 'fit4ruby'
require 'postrunner/HTMLBuilder'
require 'postrunner/ActivitySummary'
+require 'postrunner/DeviceList'
+require 'postrunner/UserProfileView'
require 'postrunner/ViewWidgets'
require 'postrunner/TrackView'
require 'postrunner/ChartView'
@@ -42,6 +44,8 @@ module PostRunner
def generate_html(doc)
@report = ActivitySummary.new(@activity.fit_activity, @activity.name,
@unit_system)
+ @device_list = DeviceList.new(@activity.fit_activity)
+ @user_profile = UserProfileView.new(@activity.fit_activity, @unit_system)
@track_view = TrackView.new(@activity)
@chart_view = ChartView.new(@activity, @unit_system)
@@ -99,6 +103,8 @@ EOT
doc.div({ :class => 'left_col' }) {
@report.to_html(doc)
@track_view.div(doc)
+ @device_list.to_html(doc)
+ @user_profile.to_html(doc)
}
doc.div({ :class => 'right_col' }) {
@chart_view.div(doc)
diff --git a/lib/postrunner/DeviceList.rb b/lib/postrunner/DeviceList.rb
new file mode 100644
index 0000000..3316dde
--- /dev/null
+++ b/lib/postrunner/DeviceList.rb
@@ -0,0 +1,104 @@
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
+#
+# = DeviceList.rb -- PostRunner - Manage the data from your Garmin sport devices.
+#
+# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+
+require 'fit4ruby'
+
+require 'postrunner/ViewWidgets'
+
+module PostRunner
+
+ class DeviceList
+
+ include ViewWidgets
+
+ def initialize(fit_activity)
+ @fit_activity = fit_activity
+ end
+
+ def to_html(doc)
+ frame(doc, 'Devices') {
+ devices.each { |d| d.to_html(doc) }
+ }
+ end
+
+ def to_s
+ devices.map { |d| d.to_s }.join("\n")
+ end
+
+ private
+
+ def devices
+ tables = []
+ seen_indexes = []
+ @fit_activity.device_infos.reverse_each do |device|
+ next if seen_indexes.include?(device.device_index) ||
+ device.manufacturer.nil? ||
+ device.manufacturer == 'Undocumented value 0' ||
+ device.device_type == 'Undocumented value 0'
+
+ tables << (t = FlexiTable.new)
+ t.set_html_attrs(:style, 'margin-bottom: 15px') if tables.length != 1
+ t.body
+
+ t.cell('Manufacturer:', { :width => '40%' })
+ t.cell(device.manufacturer, { :width => '60%' })
+ t.new_row
+
+ if (product = device.product)
+ t.cell('Product:')
+ rename = { 'fr620' => 'FR620', 'sdm4' => 'SDM4',
+ 'hrm_run_single_byte_product_id' => 'HRM Run',
+ 'hrm_run' => 'HRM Run' }
+ product = rename[product] if rename.include?(product)
+ t.cell(product)
+ t.new_row
+ end
+ if (type = device.device_type)
+ rename = { 'heart_rate' => 'Heart Rate Sensor',
+ 'stride_speed_distance' => 'Footpod',
+ 'running_dynamics' => 'Running Dynamics' }
+ type = rename[type] if rename.include?(type)
+ t.cell('Device Type:')
+ t.cell(type)
+ t.new_row
+ end
+ if device.serial_number
+ t.cell('Serial Number:')
+ t.cell(device.serial_number)
+ t.new_row
+ end
+ if device.software_version
+ t.cell('Software Version:')
+ t.cell(device.software_version)
+ t.new_row
+ end
+ if (rx_ok = device.rx_packets_ok) && (rx_err = device.rx_packets_err)
+ t.cell('Packet Errors:')
+ t.cell('%d%%' % ((rx_err.to_f / (rx_ok + rx_err)) * 100).to_i)
+ t.new_row
+ end
+ if device.battery_status
+ t.cell('Battery Status:')
+ t.cell(device.battery_status)
+ t.new_row
+ end
+
+ seen_indexes << device.device_index
+ end
+
+ tables.reverse
+ end
+
+ end
+
+end
+
diff --git a/lib/postrunner/FlexiTable.rb b/lib/postrunner/FlexiTable.rb
index 0de737e..7385db7 100644
--- a/lib/postrunner/FlexiTable.rb
+++ b/lib/postrunner/FlexiTable.rb
@@ -23,6 +23,7 @@ module PostRunner
def initialize(attrs = {})
@min_terminal_width = nil
@halign = nil
+ @width = nil
attrs.each do |name, value|
ivar_name = '@' + name.to_s
@@ -84,6 +85,8 @@ module PostRunner
def to_html(doc)
text_align = get_attribute(:halign)
attrs = { :class => 'ft_cell' }
+ width = get_attribute(:width)
+ attrs[:width] = width if width
attrs[:style] = "text-align: #{text_align.to_s}" if text_align
if @content.respond_to?('to_html')
doc.td(attrs) {
@@ -164,12 +167,17 @@ module PostRunner
@current_row = nil
@frame = true
+ @html_attrs = { :class => 'flexitable' }
@column_attributes = []
instance_eval(&block) if block_given?
end
+ def set_html_attrs(name, value)
+ @html_attrs[name] = value
+ end
+
def head
@current_section = :head
end
@@ -244,7 +252,7 @@ module PostRunner
def to_html(doc)
index_table
- doc.table({ :class => 'flexitable' }) {
+ doc.table(@html_attrs) {
@head_rows.each { |r| r.to_html(doc) }
@body_rows.each { |r| r.to_html(doc) }
@foot_rows.each { |r| r.to_html(doc) }
diff --git a/lib/postrunner/UserProfileView.rb b/lib/postrunner/UserProfileView.rb
new file mode 100644
index 0000000..81cc5ad
--- /dev/null
+++ b/lib/postrunner/UserProfileView.rb
@@ -0,0 +1,70 @@
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
+#
+# = UserProfileView.rb -- PostRunner - Manage the data from your Garmin sport devices.
+#
+# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+
+require 'fit4ruby'
+
+require 'postrunner/ViewWidgets'
+
+module PostRunner
+
+ class UserProfileView
+
+ include ViewWidgets
+
+ def initialize(fit_activity, unit_system)
+ @fit_activity = fit_activity
+ @unit_system = unit_system
+ end
+
+ def to_html(doc)
+ return nil if @fit_activity.user_profiles.empty?
+
+ frame(doc, 'User Profile') {
+ profile.to_html(doc)
+ }
+ end
+
+ def to_s
+ return '' if @fit_activity.user_profiles.empty?
+ profile.to_s
+ end
+
+ private
+
+ def profile
+ t = FlexiTable.new
+ profile = @fit_activity.user_profiles.first
+ if profile.height
+ unit = { :metric => 'm', :statute => 'ft' }[@unit_system]
+ height = profile.get_as('height', unit)
+ t.cell('Height:', { :width => '40%' })
+ t.cell("#{'%.1f' % height} #{unit}", { :width => '60%' })
+ t.new_row
+ end
+ if profile.weight
+ unit = { :metric => 'kg', :statute => 'lbs' }[@unit_system]
+ weight = profile.get_as('weight', unit)
+ t.row([ 'Weight:', "#{'%.1f' % weight} #{unit}" ])
+ end
+ t.row([ 'Gender:', profile.gender ]) if profile.gender
+ t.row([ 'Age:', "#{profile.age} years" ]) if profile.age
+ t.row([ 'Max. Heart Rate:', "#{profile.max_hr} bpm" ]) if profile.max_hr
+ if profile.activity_class
+ t.row([ 'Activity Class:', profile.activity_class ])
+ end
+ t
+ end
+
+ end
+
+end
+
diff --git a/spec/ActivitySummary_spec.rb b/spec/ActivitySummary_spec.rb
index 4e92017..20bbd3d 100644
--- a/spec/ActivitySummary_spec.rb
+++ b/spec/ActivitySummary_spec.rb
@@ -21,7 +21,7 @@ describe PostRunner::ActivitySummary do
end
it 'should create a metric summary' do
- @as.to_s #TODO: Fix aggregation first
+ puts @as.to_s #TODO: Fix aggregation first
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index cd6fec4..1bd2c43 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -8,7 +8,7 @@ def create_fit_activity(date, duration_minutes)
a.total_timer_time = duration_minutes * 60
a.new_user_profile({ :timestamp => ts,
:age => 33, :height => 1.78, :weight => 73.0,
- :gender => 'male', :activity_class => 4.0,
+ :gender => 'male', :activity_class => 7.0,
:max_hr => 178 })
a.new_event({ :timestamp => ts, :event => 'timer',
@@ -22,9 +22,9 @@ def create_fit_activity(date, duration_minutes)
:position_lat => 51.5512 - mins * 0.0008,
:position_long => 11.647 + mins * 0.002,
:distance => 200.0 * mins,
- :altitude => 100 + mins * 0.5,
+ :altitude => 100 + mins * 3,
:speed => 3.1,
- :vertical_oscillation => 9 + mins * 0.02,
+ :vertical_oscillation => 90 + mins * 0.2,
:stance_time => 235.0 * mins * 0.01,
:stance_time_percent => 32.0,
:heart_rate => 140 + mins,
@@ -33,10 +33,10 @@ def create_fit_activity(date, duration_minutes)
:fractional_cadence => (mins % 2) / 2.0
})
- ts += 60
- if (mins + 1) % 5 == 0
+ if mins > 0 && mins % 5 == 0
a.new_lap({ :timestamp => ts })
end
+ ts += 60
end
a.new_session({ :timestamp => ts })
a.new_event({ :timestamp => ts, :event => 'recovery_time',