-
-
Save anonymous/57af48ac306dcdf55dba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
require 'sequel' | |
require 'bigdecimal' | |
require 'chronic' | |
Sequel.default_timezone = :utc | |
def usage(extra=nil) | |
puts extra.to_s + "\n" if extra | |
puts <<-EOF | |
usage: #{$0} <command> [args...] | |
#{$0} record <weight_spec> [weigh_time] | |
#{$0} output [start_time] [end_time] | |
#{$0} output-facts [start_time] [end_time] | |
#{$0} minmax [start_time] [end_time] | |
EOF | |
exit 1 | |
end | |
def setup_db!(connstring="") | |
db = Sequel.connect(:adapter => "postgres", :database => "lupine", :encoding => "utf8", :charset => "utf8") | |
[db, db[:weight]] | |
end | |
def record_weight(weight_spec, weighed_at=Time.now) | |
db, tbl = setup_db! | |
weight = interpret_weight_spec(weight_spec) | |
weighed_at = Chronic::parse(weighed_at) if weighed_at.is_a?(String) | |
STDOUT.print "#{format_g(weight)} at #{weighed_at.strftime("%F %T")} [N/y] ? " | |
STDOUT.flush | |
rsp = STDIN.readline | |
STDOUT.print "\n" | |
exit 2 unless %w|y Y yes|.include?(rsp.chomp) | |
tbl << {:weight_g => weight, :weighed_at => weighed_at } | |
puts "Recorded" | |
end | |
def output_weight(start_time=nil, end_time=nil, style="simple") | |
db, tbl = setup_db! | |
start_time = Chronic.parse(start_time) if start_time.is_a?(String) | |
end_time = Chronic.parse(end_time) if end_time.is_a?(String) | |
set = tbl.order(:weighed_at) | |
set.filter(:weighed_at > start_time) if start_time | |
set.filter(:weighed_at < end_time) if end_time | |
result = set.to_a | |
puts "Time,Weight(g)" | |
case style | |
when "simple" | |
result.each do |rec| | |
puts "#{rec[:weighed_at].strftime("%F %T")},#{rec[:weight_g]}" | |
end | |
when "json" | |
puts "[" | |
result.each do |rec| | |
puts %Q| {"fact":"number", "name":"weight", "number":#{rec[:weight_g]}, "unit":"g", "recorded":"#{rec[:weighed_at].strftime("%F %T")}" },| | |
end | |
puts "]" | |
else | |
raise "Unknown style: " + style | |
end | |
end | |
def minmax_weight(start_time=nil, end_time=nil) | |
db, tbl = setup_db! | |
start_time = Chronic.parse(start_time) if start_time.is_a?(String) | |
end_time = Chronic.parse(end_time) if end_time.is_a?(String) | |
set = tbl.order(:weight_g) | |
set.filter(:weighed_at > start_time) if start_time | |
set.filter(:weighed_at < end_time) if end_time | |
min = set.first | |
max = set.last | |
puts "min: #{format_g(min[:weight_g])} at #{min[:weighed_at].strftime("%F %T")}" | |
puts "max: #{format_g(max[:weight_g])} at #{max[:weighed_at].strftime("%F %T")}" | |
days = if min[:weighed_at] >= max[:weighed_at] | |
( min[:weighed_at] - max[:weighed_at] ).to_i / 86400 | |
else | |
( min[:weighed_at] - max[:weighed_at] ).to_i / 86400 | |
end | |
diff = max[:weight_g] - min[:weight_g] | |
puts "diff: #{format_g( diff )} over #{days} days - or #{ format_g( diff / days )} per day" | |
end | |
# Takes a string specifying a weight and attempts to parse it into a number of grams. | |
# Valid examples: "10st 4lb", "185.45kg", etc. | |
NUM_MATCHER = "([0-9]*\.[0-9]+|[0-9]+)" | |
def interpret_weight_spec(spec) | |
total = spec.split(" ").collect {|part| | |
amount, multiplier = case part | |
when /#{NUM_MATCHER}kg\Z/mi then [ $1, "1000.0" ] | |
when /#{NUM_MATCHER}g\Z/mi then [ $1, "1.0" ] | |
when /#{NUM_MATCHER}st\Z/mi then [ $1, "6350.29318" ] | |
when /#{NUM_MATCHER}lb\Z/mi then [ $1, "453.59237" ] | |
else | |
raise ArgumentError.new("Couldn't work out units for #{part.inspect} in #{spec.inspect}") | |
end | |
amount, multiplier = [ BigDecimal(amount), BigDecimal(multiplier) ] | |
(amount * multiplier).to_i | |
}.inject(0) {|tot,x| tot + x } | |
end | |
def format_g(grams) | |
grams.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,") + "g" | |
end | |
if __FILE__ == $0 | |
COMMAND = ARGV.shift | |
case COMMAND | |
when "record" then record_weight(*ARGV) | |
when "output" then output_weight(*ARGV) | |
when "minmax" then minmax_weight(*ARGV) | |
else | |
usage("Unknown command: #{COMMAND}") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment