diff options
-rw-r--r-- | lib/postrunner/Activity.rb | 21 | ||||
-rw-r--r-- | lib/postrunner/ActivityView.rb | 3 | ||||
-rw-r--r-- | lib/postrunner/DataSources.rb | 15 | ||||
-rw-r--r-- | lib/postrunner/EventList.rb | 149 | ||||
-rw-r--r-- | lib/postrunner/Main.rb | 7 | ||||
-rw-r--r-- | spec/PostRunner_spec.rb | 8 |
6 files changed, 189 insertions, 14 deletions
diff --git a/lib/postrunner/Activity.rb b/lib/postrunner/Activity.rb index 13f2cd9..07dd999 100644 --- a/lib/postrunner/Activity.rb +++ b/lib/postrunner/Activity.rb @@ -14,6 +14,7 @@ require 'fit4ruby' require 'postrunner/ActivitySummary' require 'postrunner/DataSources' +require 'postrunner/EventList' require 'postrunner/ActivityView' require 'postrunner/Schema' require 'postrunner/QueryResult' @@ -196,6 +197,11 @@ module PostRunner QueryResult.new(value, schema) end + def events + @fit_activity = load_fit_file unless @fit_activity + puts EventList.new(self, @db.cfg[:unit_system]).to_s + end + def show generate_html_view #unless File.exists?(@html_file) @@ -374,6 +380,21 @@ module PostRunner ActivitySubTypes[@sub_sport] || 'Undefined' end + def distance(timestamp, unit_system) + @fit_activity = load_fit_file unless @fit_activity + + @fit_activity.records.each do |record| + if record.timestamp >= timestamp + unit = { :metric => 'km', :statute => 'mi'}[unit_system] + value = record.get_as('distance', unit) + return '-' unless value + return "#{'%.2f %s' % [value, unit]}" + end + end + + '-' + end + private def load_fit_file(filter = nil) diff --git a/lib/postrunner/ActivityView.rb b/lib/postrunner/ActivityView.rb index a1bbc3b..9474089 100644 --- a/lib/postrunner/ActivityView.rb +++ b/lib/postrunner/ActivityView.rb @@ -14,7 +14,9 @@ require 'fit4ruby' require 'postrunner/View' require 'postrunner/ActivitySummary' +require 'postrunner/EventList' require 'postrunner/DeviceList' +require 'postrunner/DataSources' require 'postrunner/UserProfileView' require 'postrunner/TrackView' require 'postrunner/ChartView' @@ -73,6 +75,7 @@ module PostRunner } doc.div({ :class => 'right_col' }) { ChartView.new(@activity, @unit_system).to_html(doc) + EventList.new(@activity, @unit_system).to_html(doc) } } doc.div({ :class => 'two_col' }) { diff --git a/lib/postrunner/DataSources.rb b/lib/postrunner/DataSources.rb index 01ed9a8..c90a405 100644 --- a/lib/postrunner/DataSources.rb +++ b/lib/postrunner/DataSources.rb @@ -55,7 +55,7 @@ module PostRunner start_time = session.start_time @fit_activity.data_sources.each do |source| t.cell(secsToHMS(source.timestamp - start_time)) - t.cell(distance(source.timestamp)) + t.cell(@activity.distance(source.timestamp, @unit_system)) t.cell(source.mode) t.cell(device_name(source.distance)) t.cell(device_name(source.speed)) @@ -81,19 +81,6 @@ module PostRunner '' end - def distance(timestamp) - @fit_activity.records.each do |record| - if record.timestamp >= timestamp - unit = { :metric => 'km', :statute => 'mi'}[@unit_system] - value = record.get_as('distance', unit) - return '-' unless value - return "#{'%.2f %s' % [value, unit]}" - end - end - - '-' - end - end end diff --git a/lib/postrunner/EventList.rb b/lib/postrunner/EventList.rb new file mode 100644 index 0000000..d248001 --- /dev/null +++ b/lib/postrunner/EventList.rb @@ -0,0 +1,149 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = EventList.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 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/FlexiTable' +require 'postrunner/ViewFrame' +require 'postrunner/DeviceList' + +module PostRunner + + # The EventList objects can generate a table that lists all the recorded + # FIT file events in chronological order. + class EventList + + include Fit4Ruby::Converters + + # Create a DataSources object. + # @param activity [Activity] The activity to analyze. + # @param unit_system [Symbol] The unit system to use (:metric or + # :imperial ) + def initialize(activity, unit_system) + @activity = activity + @fit_activity = activity.fit_activity + @unit_system = unit_system + end + + # Return the list as ASCII table + def to_s + list.to_s + end + + # Add the list as HTML table to the specified doc. + # @param doc [HTMLBuilder] HTML document + def to_html(doc) + ViewFrame.new("Events", 600, list).to_html(doc) + end + + private + + def list + session = @fit_activity.sessions[0] + + t = FlexiTable.new + t.enable_frame(false) + t.body + t.row([ 'Time', 'Distance', 'Description', 'Value' ]) + t.set_column_attributes([ + { :halign => :right }, + { :halign => :right }, + { :halign => :left }, + { :halign => :right } + ]) + start_time = session.start_time + @fit_activity.events.each do |event| + t.cell(secsToHMS(event.timestamp - start_time)) + t.cell(@activity.distance(event.timestamp, @unit_system)) + event_name_and_value(t, event) + t.new_row + end + + t + end + + def event_name_and_value(table, event) + case event.event + when 'timer' + name = "Timer (#{event.event_type.gsub(/_/, ' ')})" + value = event.timer_trigger + when 'course_point' + name = 'Course Point' + value = event.message_index + when 'battery' + name = 'Battery Level' + value = event.battery_level + when 'hr_high_alert' + name = 'HR high alert' + value = event.hr_high_alert + when 'hr_low_alert' + name = 'HR low alert' + value = event.hr_low_alert + when 'speed_high_alert' + name = 'Speed high alert' + value = event.speed_high_alert + when 'speed_low_alert' + name = 'Speed low alert' + value = event.speed_low_alert + when 'cad_high_alert' + name = 'Cadence high alert' + value = event.cad_high_alert + when 'cad_low_alert' + name = 'Cadence low alert' + value = event.cad_low_alert + when 'power_high_alert' + name = 'Power high alert' + value = event.power_high_alert + when 'power_low_alert' + name = 'Power low alert' + value = event.power_low_alert + when 'time_duration_alert' + name 'Time duration alert' + value = event.time_duration_alert + when 'calorie_duration_alert' + name = 'Calorie duration alert' + value = event.calorie_duration_alert + when 'fitness_equipment' + name = 'Fitness equipment state' + value = event.fitness_equipment_state + when 'rider_position' + name 'Rider position changed' + value = event.rider_position + when 'comm_timeout' + name 'Communication timeout' + value = event.comm_timeout + when 'recovery_hr' + name = 'Recovery heart rate' + value = "#{event.recovery_hr} bpm" + when 'recovery_time' + name = 'Recovery time' + value = "#{secsToDHMS(event.recovery_time * 60)}" + when 'recovery_info' + name = 'Recovery info' + mins = event.recovery_info + value = "#{secsToDHMS(mins * 60)} (#{mins < 24 * 60 ? 'Good' : 'Poor'})" + when 'vo2max' + name = 'VO2Max' + value = event.vo2max + else + name = event.event + value = event.data + end + + table.cell(name) + table.cell(value) + end + + end + +end + diff --git a/lib/postrunner/Main.rb b/lib/postrunner/Main.rb index 7dbb6be..c388910 100644 --- a/lib/postrunner/Main.rb +++ b/lib/postrunner/Main.rb @@ -119,6 +119,9 @@ check [ <fit file> | <ref> ... ] dump <fit file> | <ref> Dump the content of the FIT file. +events [ <ref> ] + List all the events of the specified activies. + import [ <fit file> | <directory> ] Import the provided FIT file(s) into the postrunner database. If no file or directory is provided, the directory that was used for the @@ -205,6 +208,8 @@ EOT when 'dump' @filter = Fit4Ruby::FitFilter.new unless @filter process_files_or_activities(args, :dump) + when 'events' + process_files_or_activities(args, :events) when 'import' if args.empty? # If we have no file or directory for the import command, we get the @@ -351,6 +356,8 @@ EOT @activities.delete(activity) when :dump activity.dump(@filter) + when :events + activity.events when :rename @activities.rename(activity, @name) when :set diff --git a/spec/PostRunner_spec.rb b/spec/PostRunner_spec.rb index 59c5d0e..f4dd33b 100644 --- a/spec/PostRunner_spec.rb +++ b/spec/PostRunner_spec.rb @@ -131,6 +131,14 @@ describe PostRunner::Main do list.index('Cycling').should be_a(Fixnum) end + it 'should list the events of an activity' do + postrunner(%w( events :1 )) + end + + it 'should list the data sources of an activity' do + postrunner(%w( sources :1 )) + end + it 'should fail when setting bad activity type' do lambda { postrunner(%w( set type foobar :1)) }.should raise_error Fit4Ruby::Error end |