diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/postrunner.rb | 11 | ||||
-rw-r--r-- | lib/postrunner/ActivitiesDB.rb | 123 | ||||
-rw-r--r-- | lib/postrunner/Activity.rb | 17 | ||||
-rw-r--r-- | lib/postrunner/Main.rb | 116 | ||||
-rw-r--r-- | lib/postrunner/version.rb | 3 |
5 files changed, 270 insertions, 0 deletions
diff --git a/lib/postrunner.rb b/lib/postrunner.rb new file mode 100644 index 0000000..681c583 --- /dev/null +++ b/lib/postrunner.rb @@ -0,0 +1,11 @@ +$:.unshift(File.join(File.dirname(__FILE__), '..', '..', 'fit4ruby', 'lib')) +$:.unshift(File.dirname(__FILE__)) + +require 'postrunner/version' +require 'postrunner/Main' + +module PostRunner + + Main.new(ARGV) + +end diff --git a/lib/postrunner/ActivitiesDB.rb b/lib/postrunner/ActivitiesDB.rb new file mode 100644 index 0000000..df0c105 --- /dev/null +++ b/lib/postrunner/ActivitiesDB.rb @@ -0,0 +1,123 @@ +require 'fileutils' +require 'yaml' + +require 'fit4ruby' +require 'postrunner/Activity' + +module PostRunner + + class ActivitiesDB + + def initialize(db_dir) + @db_dir = db_dir + @fit_dir = File.join(@db_dir, 'fit') + @archive_file = File.join(@db_dir, 'archive.yml') + + if Dir.exists?(@db_dir) + begin + if File.exists?(@archive_file) + @activities = YAML.load_file(@archive_file) + else + @activities = [] + end + rescue + Log.fatal "Cannot load archive file #{@archive_file}: #{$!}" + end + else + create_directories + @activities = [] + 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" + return false + end + + begin + fit_activity = Fit4Ruby.read(fit_file) + rescue + Log.error "Cannot read #{fit_file}: #{$!}" + return false + end + + begin + FileUtils.cp(fit_file, @fit_dir) + rescue + Log.fatal "Cannot copy #{fit_file} into #{@fit_dir}: #{$!}" + end + + @activities << Activity.new(base_fit_file, fit_activity) + sync + Log.info "#{fit_file} successfully added to archive" + + true + end + + def map_to_files(query) + case query + when /\A-?\d+$\z/ + index = query.to_i + # The UI counts the activities from 1 to N. Ruby counts from 0 - + # (N-1). + index -= 1 if index > 0 + if (a = @activities[index]) + return [ File.join(@fit_dir, a.fit_file) ] + end + when /\A-?\d+--?\d+\z/ + idxs = query.match(/(?<sidx>-?\d+)-(?<eidx>-?[0-9]+)/) + sidx = idxs['sidx'].to_i + eidx = idxs['eidx'].to_i + # The UI counts the activities from 1 to N. Ruby counts from 0 - + # (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| + files << File.join(@fit_dir, a.fit_file) + end + return files + end + else + Log.error "Invalid activity query: #{query}" + end + + [] + end + + def list + i = 0 + @activities.each do |a| + i += 1 + puts "#{"%4d" % i} #{"%12s" % a.fit_file} #{a.start_time}" + end + end + + private + + def sync + File.open(@archive_file, 'w') { |f| f.write(@activities.to_yaml) } + end + + def create_directories + Log.info "Creating data directory #{@db_dir}" + begin + Dir.mkdir(@db_dir) + rescue + Log.fatal "Cannot create data directory #{@db_dir}: #{$!}" + end + begin + Dir.mkdir(@fit_dir) + rescue + Log.fatal "Cannot create fit directory #{@fit_dir}: #{$!}" + end + end + + end + +end + diff --git a/lib/postrunner/Activity.rb b/lib/postrunner/Activity.rb new file mode 100644 index 0000000..96c9887 --- /dev/null +++ b/lib/postrunner/Activity.rb @@ -0,0 +1,17 @@ +require 'fit4ruby' + +module PostRunner + + class Activity + + attr_reader :fit_file, :start_time + + def initialize(fit_file, fit_activity) + @fit_file = fit_file + @start_time = fit_activity.start_time + end + + end + +end + diff --git a/lib/postrunner/Main.rb b/lib/postrunner/Main.rb new file mode 100644 index 0000000..26e1005 --- /dev/null +++ b/lib/postrunner/Main.rb @@ -0,0 +1,116 @@ +require 'optparse' +require 'logger' +require 'fit4ruby' +require 'postrunner/ActivitiesDB' + +module PostRunner + + Log = Fit4Ruby::ILogger.new(STDOUT) + + class Main + + def initialize(args) + @filter = nil + @activities = ActivitiesDB.new(File.join(ENV['HOME'], '.postrunner')) + + execute_command(parse_options(args)) + end + + private + + def parse_options(args) + parser = OptionParser.new do |opts| + opts.banner = "Usage postrunner <command> [options]" + opts.separator "" + opts.separator "Options for the 'dump' command:" + + opts.on('--filter-msg N', Integer, + 'Only dump messages of type number N') do |n| + @filter = Fit4Ruby::FitFilter.new unless @filter + @filter.record_numbers = [] unless @filter.record_numbers + @filter.record_numbers << n.to_i + end + opts.on('--filter-msg-idx N', Integer, + 'Only dump the N-th message of the specified types') do |n| + @filter = Fit4Ruby::FitFilter.new unless @filter + @filter.record_indexes = [] unless @filter.record_indexes + @filter.record_indexes << n.to_i + end + opts.on('--filter-field name', String, + 'Only dump the field \'name\' of the selected messages') do |n| + @filter = Fit4Ruby::FitFilter.new unless @filter + @filter.field_names = [] unless @filter.field_names + @filter.field_names << n + end + end + + parser.parse!(args) + end + + def execute_command(args) + case args.shift + when 'check' + process_files(args, :check) + when 'dump' + @filter = Fit4Ruby::FitFilter.new unless @filter + process_files_or_activities(args, :dump) + when 'import' + process_files(args, :import) + when 'list' + @activities.list + when 'summary' + process_files(args, :summary) + else + Log.fatal("No command provided") + end + end + + def process_files_or_activities(files_or_activities, command) + files_or_activities.each do |foa| + if foa[0] == ':' + files = @activities.map_to_files(foa[1..-1]) + if files.empty? + Log.warn "No matching activities found for '#{foa}'" + return + end + + process_files(files, command) + else + process_files(foa, command) + 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") + end + + files_or_dirs.each do |fod| + if File.directory?(fod) + Dir.glob(File.join(fod, '*.FIT')).each do |file| + process_file(file, command) + end + else + process_file(fod, command) + end + end + end + + def process_file(file, command) + if command == :import + @activities.add(file) + else + begin + activity = Fit4Ruby::read(file, @filter) + #rescue + # Log.error("File '#{file}' is corrupted!: #{$!}") + end + puts activity.to_s if command == :summary + end + end + + end + +end + diff --git a/lib/postrunner/version.rb b/lib/postrunner/version.rb new file mode 100644 index 0000000..3861ec6 --- /dev/null +++ b/lib/postrunner/version.rb @@ -0,0 +1,3 @@ +module PostRunner + VERSION = "0.0.1" +end |