diff options
author | Chris Schlaeger <chris@linux.com> | 2014-08-29 22:45:11 +0200 |
---|---|---|
committer | Chris Schlaeger <chris@linux.com> | 2014-08-29 22:45:11 +0200 |
commit | 033c7916e8cb05b4d65ad5c7c9d6179efa0a0e29 (patch) | |
tree | f6ca1b8c7c2f92a67cce56e393eae6206bded909 | |
parent | 3c32e378c9ffc01c1ed994483571193127a4e6a4 (diff) | |
download | postrunner-033c7916e8cb05b4d65ad5c7c9d6179efa0a0e29.zip |
Adding device info and user profile to HTML view
-rw-r--r-- | lib/postrunner/ActivityView.rb | 6 | ||||
-rw-r--r-- | lib/postrunner/DeviceList.rb | 104 | ||||
-rw-r--r-- | lib/postrunner/FlexiTable.rb | 10 | ||||
-rw-r--r-- | lib/postrunner/UserProfileView.rb | 70 | ||||
-rw-r--r-- | spec/ActivitySummary_spec.rb | 2 | ||||
-rw-r--r-- | spec/spec_helper.rb | 10 |
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', |