summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChris Schlaeger <chris@linux.com>2014-07-20 21:47:39 +0200
committerChris Schlaeger <chris@linux.com>2014-07-20 21:47:39 +0200
commit06fd275a92cee58de4fcb2ca5e8f255f655d4ba5 (patch)
tree8eff1d8252ff14e7367d8aa68781d01d9e267f57 /lib
parentcc72a9807699b95363d0ae58aa5237d982946470 (diff)
downloadpostrunner-06fd275a92cee58de4fcb2ca5e8f255f655d4ba5.zip
Lots of cleanup work
Diffstat (limited to 'lib')
-rw-r--r--lib/postrunner/ActivitiesDB.rb35
-rw-r--r--lib/postrunner/Activity.rb53
-rw-r--r--lib/postrunner/Main.rb43
-rw-r--r--lib/postrunner/RuntimeConfig.rb20
4 files changed, 139 insertions, 12 deletions
diff --git a/lib/postrunner/ActivitiesDB.rb b/lib/postrunner/ActivitiesDB.rb
index df0c105..c8785fb 100644
--- a/lib/postrunner/ActivitiesDB.rb
+++ b/lib/postrunner/ActivitiesDB.rb
@@ -8,6 +8,8 @@ module PostRunner
class ActivitiesDB
+ include Fit4Ruby::Converters
+
def initialize(db_dir)
@db_dir = db_dir
@fit_dir = File.join(@db_dir, 'fit')
@@ -21,24 +23,28 @@ module PostRunner
@activities = []
end
rescue
- Log.fatal "Cannot load archive file #{@archive_file}: #{$!}"
+ Log.fatal "Cannot load archive file '#{@archive_file}': #{$!}"
end
else
create_directories
@activities = []
end
+
+ unless @activities.is_a?(Array)
+ Log.fatal "The archive file '#{@archive_file}' is corrupted"
+ end
end
def add(fit_file)
base_fit_file = File.basename(fit_file)
if @activities.find { |a| a.fit_file == base_fit_file }
- Log.warn "Activity #{fit_file} is already included in the archive"
+ Log.debug "Activity #{fit_file} is already included in the archive"
return false
end
begin
fit_activity = Fit4Ruby.read(fit_file)
- rescue
+ rescue Fit4Ruby::Error
Log.error "Cannot read #{fit_file}: #{$!}"
return false
end
@@ -50,12 +56,27 @@ module PostRunner
end
@activities << Activity.new(base_fit_file, fit_activity)
+ @activities.sort! do |a1, a2|
+ a2.start_time <=> a1.start_time
+ end
sync
Log.info "#{fit_file} successfully added to archive"
true
end
+
+ def rename(fit_file, name)
+ base_fit_file = File.basename(fit_file)
+ @activities.each do |a|
+ if a.fit_file == base_fit_file
+ a.name = name
+ sync
+ break
+ end
+ end
+ end
+
def map_to_files(query)
case query
when /\A-?\d+$\z/
@@ -74,7 +95,6 @@ module PostRunner
# (N-1).
sidx -= 1 if sidx > 0
eidx -= 1 if eidx > 0
- puts "iv: #{sidx} - #{eidx}"
unless (as = @activities[sidx..eidx]).empty?
files = []
as.each do |a|
@@ -93,7 +113,12 @@ module PostRunner
i = 0
@activities.each do |a|
i += 1
- puts "#{"%4d" % i} #{"%12s" % a.fit_file} #{a.start_time}"
+ puts "#{'%4d' % i} " +
+ "#{'%-20s' % a.name[0..19]} " +
+ "#{'%22s' % a.start_time.strftime("%a, %Y %b %d %H:%M")} " +
+ "#{'%7.2f' % (a.distance / 1000)} " +
+ "#{'%8s' % secsToHMS(a.duration)} " +
+ "#{'%5s' % speedToPace(a.avg_speed)} "
end
end
diff --git a/lib/postrunner/Activity.rb b/lib/postrunner/Activity.rb
index 96c9887..964a702 100644
--- a/lib/postrunner/Activity.rb
+++ b/lib/postrunner/Activity.rb
@@ -1,14 +1,61 @@
require 'fit4ruby'
+require 'postrunner/RuntimeConfig'
module PostRunner
class Activity
- attr_reader :fit_file, :start_time
+ attr_reader :fit_file
+ attr_accessor :name
- def initialize(fit_file, fit_activity)
+ # This is a list of variables that provide data from the fit file. To
+ # speed up access to it, we cache the data in the activity database.
+ @@CachedVariables = %w( start_time distance duration avg_speed )
+
+ def initialize(fit_file, fit_activity, name = nil)
@fit_file = fit_file
- @start_time = fit_activity.start_time
+ @fit_activity = fit_activity
+ @name = name || fit_file
+
+ @@CachedVariables.each do |v|
+ v_str = "@#{v}"
+ instance_variable_set(v_str, fit_activity.send(v))
+ self.class.send(:attr_reader, v.to_sym)
+ end
+ end
+
+ def yaml_initialize(tag, value)
+ # Create attr_readers for cached variables.
+ @@CachedVariables.each { |v| self.class.send(:attr_reader, v.to_sym) }
+
+ # Load all attributes and assign them to instance variables.
+ value.each do |a, v|
+ instance_variable_set("@" + a, v)
+ end
+ # Use the FIT file name as activity name if none has been set yet.
+ @name = @fit_file unless @name
+ end
+
+ def encode_with(coder)
+ attr_ignore = %w( @fit_activity )
+
+ instance_variables.each do |v|
+ v = v.to_s
+ next if attr_ignore.include?(v)
+
+ coder[v[1..-1]] = instance_variable_get(v)
+ end
+ end
+
+ def method_missing(method_name, *args, &block)
+ fit_file = File.join(Config['fit_dir'], @fit_file)
+ begin
+ @fit_activity = Fit4Ruby.read(fit_file) unless @fit_activity
+ rescue Fit4Ruby::Error
+ Log.error "Cannot read #{fit_file}: #{$!}"
+ return false
+ end
+ @fit_activity.send(method_name, *args, &block)
end
end
diff --git a/lib/postrunner/Main.rb b/lib/postrunner/Main.rb
index 26e1005..4e2f020 100644
--- a/lib/postrunner/Main.rb
+++ b/lib/postrunner/Main.rb
@@ -1,6 +1,7 @@
require 'optparse'
require 'logger'
require 'fit4ruby'
+require 'postrunner/RuntimeConfig'
require 'postrunner/ActivitiesDB'
module PostRunner
@@ -11,6 +12,7 @@ module PostRunner
def initialize(args)
@filter = nil
+ @name = nil
@activities = ActivitiesDB.new(File.join(ENV['HOME'], '.postrunner'))
execute_command(parse_options(args))
@@ -42,6 +44,18 @@ module PostRunner
@filter.field_names = [] unless @filter.field_names
@filter.field_names << n
end
+ opts.on('--filter-undef',
+ "Don't show fields with undefined values") do
+ @filter = Fit4Ruby::FitFilter.new unless @filter
+ @filter.ignore_undef = true
+ end
+
+ opts.separator "Options for the 'import' and 'rename' command:"
+
+ opts.on('--name name', String,
+ 'Name or rename the activity to the specified name') do |n|
+ @name = n
+ end
end
parser.parse!(args)
@@ -50,7 +64,7 @@ module PostRunner
def execute_command(args)
case args.shift
when 'check'
- process_files(args, :check)
+ process_files_or_activities(args, :check)
when 'dump'
@filter = Fit4Ruby::FitFilter.new unless @filter
process_files_or_activities(args, :dump)
@@ -58,8 +72,10 @@ module PostRunner
process_files(args, :import)
when 'list'
@activities.list
+ when 'rename'
+ process_activities(args, :rename)
when 'summary'
- process_files(args, :summary)
+ process_files_or_activities(args, :summary)
else
Log.fatal("No command provided")
end
@@ -76,11 +92,27 @@ module PostRunner
process_files(files, command)
else
- process_files(foa, command)
+ process_files([ foa ], command)
end
end
end
+ def process_activities(activity_files, command)
+ activity_files.each do |a|
+ if a[0] == ':'
+ files = @activities.map_to_files(a[1..-1])
+ if files.empty?
+ Log.warn "No matching activities found for '#{a}'"
+ return
+ end
+ process_files(files, command)
+ else
+ Log.fatal "Activity references must start with ':': #{a}"
+ end
+ end
+
+ end
+
def process_files(files_or_dirs, command)
if files_or_dirs.empty?
Log.fatal("You must provide at least one .FIT file name")
@@ -98,8 +130,11 @@ module PostRunner
end
def process_file(file, command)
- if command == :import
+ case command
+ when :import
@activities.add(file)
+ when :rename
+ @activities.rename(file, @name)
else
begin
activity = Fit4Ruby::read(file, @filter)
diff --git a/lib/postrunner/RuntimeConfig.rb b/lib/postrunner/RuntimeConfig.rb
new file mode 100644
index 0000000..2d5dccb
--- /dev/null
+++ b/lib/postrunner/RuntimeConfig.rb
@@ -0,0 +1,20 @@
+module PostRunner
+
+ class RuntimeConfig
+
+ def initialize
+ @settings = {}
+ @settings['data_dir'] = File.join(ENV['HOME'], '.postrunner')
+ @settings['fit_dir'] = File.join(@settings['data_dir'], 'fit')
+ end
+
+ def [](key)
+ @settings[key]
+ end
+
+ end
+
+ Config = RuntimeConfig.new
+
+end
+