summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/postrunner/FitFileStore.rb23
-rw-r--r--lib/postrunner/Main.rb21
-rw-r--r--lib/postrunner/SleepStatistics.rb48
3 files changed, 89 insertions, 3 deletions
diff --git a/lib/postrunner/FitFileStore.rb b/lib/postrunner/FitFileStore.rb
index 75bd104..07a1335 100644
--- a/lib/postrunner/FitFileStore.rb
+++ b/lib/postrunner/FitFileStore.rb
@@ -341,6 +341,29 @@ module PostRunner
puts SleepStatistics.new(monitoring_files).daily(day)
end
+ def monthly_report(day)
+ monitorings = []
+ # 'day' specifies the current month. It must be in the form of
+ # YYYY-MM-01. But we don't know what timezone the watch was set to for a
+ # given date. The files are always named after the moment of finishing
+ # the recording expressed as GMT time. Each file contains information
+ # about the time zone for the specific file. Recording is always flipped
+ # to a new file at midnight GMT but there are usually multiple files per
+ # GMT day.
+ day_as_time = Time.parse(day).gmtime
+ @store['devices'].each do |id, device|
+ # We are looking for all files that potentially overlap with our
+ # localtime day.
+ monitorings += device.monitorings(day_as_time - 36 * 60 * 60,
+ day_as_time + 33 * 24 * 60 * 60)
+ end
+ monitoring_files = monitorings.map do |m|
+ read_fit_file(File.join(fit_file_dir(m.fit_file_name, m.device.long_uid,
+ 'monitor'), m.fit_file_name))
+ end
+ puts SleepStatistics.new(monitoring_files).monthly(day)
+ end
+
private
def read_fit_file(fit_file_name)
diff --git a/lib/postrunner/Main.rb b/lib/postrunner/Main.rb
index 652dd49..6754582 100644
--- a/lib/postrunner/Main.rb
+++ b/lib/postrunner/Main.rb
@@ -193,6 +193,10 @@ delete <ref>
list
List all FIT files stored in the data base.
+monthly [ <date> ]
+ Print a table with various statistics for each day of the specified
+ month.
+
records
List all personal records.
@@ -302,9 +306,11 @@ EOT
when 'daily'
# Get the date of requested day in 'YY-MM-DD' format. If no argument
# is given, use the current date.
- day = (args.empty? ? Time.now : Time.parse(args[0])).
- localtime.strftime('%Y-%m-%d')
- @ffs.daily_report(day)
+ @ffs.daily_report(day_in_localtime(args, '%Y-%m-%d'))
+ when 'monthly'
+ # Get the date of requested day in 'YY-MM-DD' format. If no argument
+ # is given, use the current date.
+ @ffs.monthly_report(day_in_localtime(args, '%Y-%m-01'))
when 'delete'
process_activities(args, :delete)
when 'dump'
@@ -548,6 +554,15 @@ EOT
end
end
+ def day_in_localtime(args, format)
+ begin
+ (args.empty? ? Time.now : Time.parse(args[0])).
+ localtime.strftime(format)
+ rescue ArgumentError
+ Log.abort("#{args[0]} is not a valid date. Use YYYY-MM-DD format.")
+ end
+ end
+
def handle_version_update
if @db['config']['version'] != VERSION
Log.warn "PostRunner version upgrade detected."
diff --git a/lib/postrunner/SleepStatistics.rb b/lib/postrunner/SleepStatistics.rb
index 514733b..0825ab9 100644
--- a/lib/postrunner/SleepStatistics.rb
+++ b/lib/postrunner/SleepStatistics.rb
@@ -63,6 +63,54 @@ module PostRunner
"Sleep Statistics for #{day}\n\n#{ti}\n#{tt}"
end
+ def monthly(day)
+ day_as_time = Time.parse(day)
+ year = day_as_time.year
+ month = day_as_time.month
+ last_day_of_month = Date.new(year, month, -1).day
+
+ t = FlexiTable.new
+ left = { :halign => :left }
+ right = { :halign => :right }
+ t.set_column_attributes([ left, right, right, right ])
+ t.head
+ t.row([ 'Date', 'Total Sleep', 'Deep Sleep', 'Light Sleep' ])
+ t.body
+ totals = Hash.new(0)
+ counted_days = 0
+
+ 1.upto(last_day_of_month).each do |dom|
+ day_str = Time.new(year, month, dom).strftime('%Y-%m-%d')
+ t.cell(day_str)
+
+ analyzer = DailySleepAnalyzer.new(@monitoring_files, day_str)
+
+ if analyzer.sleep_intervals.empty?
+ t.cell('-')
+ t.cell('-')
+ t.cell('-')
+ else
+ totals[:total_sleep] += analyzer.total_sleep
+ totals[:deep_sleep] += analyzer.deep_sleep
+ totals[:light_sleep] += analyzer.light_sleep
+ counted_days += 1
+
+ t.cell(secsToHM(analyzer.total_sleep))
+ t.cell(secsToHM(analyzer.deep_sleep))
+ t.cell(secsToHM(analyzer.light_sleep))
+ end
+ t.new_row
+ end
+ t.foot
+ t.cell('Averages')
+ t.cell(secsToHM(totals[:total_sleep] / counted_days))
+ t.cell(secsToHM(totals[:deep_sleep] / counted_days))
+ t.cell(secsToHM(totals[:light_sleep] / counted_days))
+ t.new_row
+
+ "Sleep Statistics for #{day_as_time.strftime('%B')} #{year}\n\n#{t}"
+ end
+
end
end