bpl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +140 -0
- data/Rakefile +15 -0
- data/bin/bpl +110 -0
- data/bpl.gemspec +31 -0
- data/config/database.yml +3 -0
- data/lib/bpl/version.rb +3 -0
- data/lib/bpl.rb +112 -0
- data/lib/create_blood.rb +27 -0
- data/lib/lib_trollop.rb +782 -0
- data/lib/models/blood_pressure.rb +30 -0
- data/spec/bpl_spec.rb +57 -0
- data/spec/spec_helper.rb +14 -0
- metadata +208 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Florin T.PATRASCU
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
### Blood Pressure Logger (BPL)
|
2
|
+
|
3
|
+
A very simple gem to help you track your [blood pressure](http://en.wikipedia.org/wiki/Blood_pressure) values over time. With BPL you can also:
|
4
|
+
|
5
|
+
- export your data to other applications; Numbers, Excel, etc.
|
6
|
+
- view history for a given period of time
|
7
|
+
- and more
|
8
|
+
|
9
|
+
Your privacy is very important, this is why the BPL application is open source and it is using only local resources such as the small database stored on your computer. A basic guarantee that your data is safe and completely under your own control.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Install the BP gem:
|
14
|
+
|
15
|
+
$ gem install bpl
|
16
|
+
|
17
|
+
Create a new folder `.bp` in your home directory:
|
18
|
+
|
19
|
+
$ mkdir ~/.bp
|
20
|
+
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
You'll have to initialize the database first, this is a one-time command:
|
25
|
+
|
26
|
+
$ bpl init
|
27
|
+
|
28
|
+
After that you can start recording your BP measurements as needed. Examples:
|
29
|
+
|
30
|
+
$ bpl 145/81/67/L/87 -d 2012/12/10 -t 16:30 -m notes
|
31
|
+
$ bpl 136/60/66
|
32
|
+
$ bpl 136/60/66/r
|
33
|
+
$ bpl 125/71/67/L/87 -d 2012/12/11 -m "some notes"
|
34
|
+
$ bpl 136/60/66/l/85
|
35
|
+
$ bpl 120/64/67/L/87 -D "2012/12/10 16:30"
|
36
|
+
|
37
|
+
BPL expects you to enter the following values:
|
38
|
+
|
39
|
+
SYS/DIA/HR/ARM/WEIGHT
|
40
|
+
|
41
|
+
Where:
|
42
|
+
|
43
|
+
SYS: systolic pressure.
|
44
|
+
DIA: diastolic pressure.
|
45
|
+
HR: heart rate
|
46
|
+
ARM: 'l' or 'r'. Left or right. It is optional; LEFT arm, if not specified.
|
47
|
+
WEIGHT: weight (optional, see note below)
|
48
|
+
|
49
|
+
You can also specify the date, date and time, and an optional comment, as seen in the previous set of examples.
|
50
|
+
|
51
|
+
A special **note** to remember when you log your data. Your weight is important but you're not required to specify it every time you add a new measurement. Specify your weight at least once or very time it is changing. The last weight value will be reused when not specified explicitly in the measurement.
|
52
|
+
|
53
|
+
### Other useful commands
|
54
|
+
A handful of command lines and switches are provided for your convenience.
|
55
|
+
|
56
|
+
**View**
|
57
|
+
- display a page with the most recent records, or recorded at a specified date/time. Example:
|
58
|
+
|
59
|
+
$ bpl view
|
60
|
+
$ bpl view -d 2012/08/01
|
61
|
+
$ bpl view -d 08/14 -t 09:31:10
|
62
|
+
|
63
|
+
**Remove**
|
64
|
+
delete a record by record id. The record id can be observed with the **view** command. Example:
|
65
|
+
|
66
|
+
$ bpl view -d 08/14 -t 09:31:10
|
67
|
+
+--+-------------------+---+---+--+-----+------+-----+
|
68
|
+
|Id| Date |Sys|Dia|Hr| Arm |Weight|Notes|
|
69
|
+
+--+-------------------+---+---+--+-----+------+-----+
|
70
|
+
|2 |2012-09-25 09:31:11|120|80 |67|LEFT |90 | |
|
71
|
+
|1 |2012-09-25 09:30:30|1 |2 |3 |RIGHT|90 | |
|
72
|
+
+--+-------------------+---+---+--+-----+------+-----+
|
73
|
+
|
74
|
+
$ bpl remove 1
|
75
|
+
record: #1, was removed.
|
76
|
+
|
77
|
+
**Export to CSV**
|
78
|
+
export your data to a file that can be imported by other applications, including Numbers or Excel.
|
79
|
+
|
80
|
+
Here is an example exporting the data to the screen:
|
81
|
+
|
82
|
+
$ bpl export -d 9/14
|
83
|
+
ID,DATE,SYS,DIA,HR,ARM,WEIGHT,NOTES
|
84
|
+
2,'2012-09-25 09:31:11',120,80,67,'LEFT',90,''
|
85
|
+
|
86
|
+
And to a specified file:
|
87
|
+
|
88
|
+
$ bpl export -d 2012/08/01 -f > my_bp.csv
|
89
|
+
$
|
90
|
+
|
91
|
+
**Init**
|
92
|
+
use init with `-f` if you want to wipe out clean your local database. Warning, your data cannot be restored after this point in time. Example:
|
93
|
+
|
94
|
+
$ bpl init -f
|
95
|
+
|
96
|
+
**Help**
|
97
|
+
|
98
|
+
$ bpl -h
|
99
|
+
|
100
|
+
Simple blood pressure logger
|
101
|
+
|
102
|
+
Available commands: history, series, delete, view, init, plot
|
103
|
+
|
104
|
+
Examples:
|
105
|
+
|
106
|
+
$ bpl 145/81/67/L/87 -d 2012/12/10 -t 16:30 -m notes
|
107
|
+
$ bpl 136/60/66
|
108
|
+
$ bpl 136/60/66/r
|
109
|
+
$ bpl 125/71/67/L/87 -d 2012/12/11 -m "some notes"
|
110
|
+
$ bpl 136/60/66/l/85
|
111
|
+
$ bpl 120/64/67/L/87 -D "2012/12/10 16:30"
|
112
|
+
$ bpl export -d 2012/08/01 -f > my_bp.csv
|
113
|
+
|
114
|
+
The following options apply:
|
115
|
+
--date, -d <s>: Date (default: 2012/10/31)
|
116
|
+
--time, -t <s>: Time (default: 11:01:31)
|
117
|
+
--datetime, -D <s>: Specify the date and the time, surrounded with quotes ";
|
118
|
+
--message, -m <s>: Notes, comments
|
119
|
+
--force, -f: Force database initialization, all the data will be lost
|
120
|
+
--raw, -r: used to view the data without formatting
|
121
|
+
--page, -p <i>: total number of records to view (default: 15)
|
122
|
+
--all, -a: export the entire dataset, all the records
|
123
|
+
--quiet, -q: no echoing to console
|
124
|
+
--help, -h: Show this message
|
125
|
+
|
126
|
+
|
127
|
+
### TODO
|
128
|
+
|
129
|
+
- plot the data for simple visualizations
|
130
|
+
|
131
|
+
## Contributing
|
132
|
+
|
133
|
+
1. Fork it
|
134
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
135
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
136
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
137
|
+
5. Create new Pull Request
|
138
|
+
|
139
|
+
## License
|
140
|
+
MIT, please see the attached LICENSE.txt for more details.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
Bundler::GemHelper.install_tasks
|
7
|
+
|
8
|
+
desc 'Default: run tests.'
|
9
|
+
task :default => [:spec]
|
10
|
+
|
11
|
+
task :spec do
|
12
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
13
|
+
t.pattern = './spec/**/*_spec.rb'
|
14
|
+
end
|
15
|
+
end
|
data/bin/bpl
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
+
|
5
|
+
require "date"
|
6
|
+
require "bundler/setup"
|
7
|
+
require 'yajl'
|
8
|
+
require 'active_record'
|
9
|
+
require "lib_trollop"
|
10
|
+
require "bpl"
|
11
|
+
require "bpl/version"
|
12
|
+
require "models/blood_pressure"
|
13
|
+
require "create_blood"
|
14
|
+
require 'tablizer'
|
15
|
+
require "chronic"
|
16
|
+
|
17
|
+
# Simple Blood Pressure logger
|
18
|
+
#
|
19
|
+
# Florin, 2012.10.15
|
20
|
+
|
21
|
+
|
22
|
+
SUB_COMMANDS = %w(history series delete view init plot)
|
23
|
+
|
24
|
+
# db_config = YAML::load(File.open(File.join(File.dirname(__FILE__),
|
25
|
+
# '../config','database.yml'))) [ENV['ENV'] ? ENV['ENV'] : 'development']
|
26
|
+
# ActiveRecord::Base.establish_connection(db_config)
|
27
|
+
|
28
|
+
ActiveRecord::Base.establish_connection :adapter => "sqlite3",
|
29
|
+
:database => File.expand_path("~/.bp/blood.sqlite3")
|
30
|
+
opts = Trollop::options do
|
31
|
+
banner <<-BANNER
|
32
|
+
Simple blood pressure logger
|
33
|
+
|
34
|
+
Available commands: #{SUB_COMMANDS.join(", ")}
|
35
|
+
|
36
|
+
Examples:
|
37
|
+
|
38
|
+
$ bpl 145/81/67/L/87 -d 2012/12/10 -t 16:30 -m notes
|
39
|
+
$ bpl 136/60/66
|
40
|
+
$ bpl 136/60/66/r
|
41
|
+
$ bpl view --all
|
42
|
+
$ bpl 125/71/67/L/87 -d 2012/12/11 -m "some notes"
|
43
|
+
$ bpl 136/60/66/l/85
|
44
|
+
$ bpl 120/64/67/L/87 -D "2012/12/10 16:30"
|
45
|
+
$ bpl export -r -a
|
46
|
+
$ bpl export -d 2012/08/01 -f > my_bp.csv
|
47
|
+
|
48
|
+
The following options apply:
|
49
|
+
BANNER
|
50
|
+
|
51
|
+
now = Time.now
|
52
|
+
|
53
|
+
opt :date, "Date", :short => "-d", :default => now.strftime("%Y/%m/%d"), :type => String
|
54
|
+
opt :time, "Time", :short => "-t", :default => now.strftime("%H:%M:%S"), :type => String
|
55
|
+
opt :datetime, "Specify the date and the time, surrounded with quotes \";", :short => "-D", :type => String
|
56
|
+
opt :message, "Notes, comments", :short => "-m", :type => String
|
57
|
+
opt :force, "Force database initialization, all the data will be lost", :short => "-f"
|
58
|
+
opt :raw, "used to view the data without formatting", :short => "-r", :default => false
|
59
|
+
opt :page, "total number of records to view", :short => "-p", :default => 15, :type => Integer
|
60
|
+
opt :all, "export the entire dataset, all the records", :short => "-a", :default => false
|
61
|
+
opt :quiet, "no echoing to console", :short => "-q", :default => false
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
include Bpl
|
66
|
+
Bpl.options opts
|
67
|
+
|
68
|
+
# Check the command line parameters
|
69
|
+
cmd = ARGV.shift # get the subcommand
|
70
|
+
|
71
|
+
# optimize the two regex and build a clever one to rule them all :)
|
72
|
+
# use http://rubular.com, to validate
|
73
|
+
# hints: http://strugglingwithruby.blogspot.ca/2009/05/regular-expressions-in-ruby.html
|
74
|
+
case cmd
|
75
|
+
when /^(\d+)\/(\d+)\/(\d+)(?:\/([lr]))(?:\/(\d+))$/i, /^(\d+)\/(\d+)\/(\d+)(?:\/([lr]))?$/i
|
76
|
+
begin
|
77
|
+
Bpl.add($1, $2, $3, $4, $5)
|
78
|
+
rescue => e
|
79
|
+
puts "Exception in BPL: #{e} at #{e.backtrace.join("\n")}"
|
80
|
+
end
|
81
|
+
|
82
|
+
when "history", "view"
|
83
|
+
Bpl.view
|
84
|
+
|
85
|
+
when "export"
|
86
|
+
puts Bpl.export
|
87
|
+
|
88
|
+
when "delete", "remove"
|
89
|
+
Bpl.remove ARGV[0]
|
90
|
+
|
91
|
+
when "init"
|
92
|
+
puts "Initializing the blood database ..."
|
93
|
+
begin
|
94
|
+
CreateBlood.up
|
95
|
+
rescue => e
|
96
|
+
if opts[:force]
|
97
|
+
# ActiveRecord::Base.connection.drop_database db_config["database"] rescue nil
|
98
|
+
CreateBlood.down
|
99
|
+
CreateBlood.up
|
100
|
+
puts " - done."
|
101
|
+
else
|
102
|
+
puts "error: #{e.message}"
|
103
|
+
puts "use -f, to force the process and overwrite the data. All your previous data will be lost!"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
else
|
108
|
+
Trollop::die "unknown command #{cmd.inspect}"
|
109
|
+
end
|
110
|
+
|
data/bpl.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/bpl/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "bpl"
|
6
|
+
gem.version = Bpl::VERSION
|
7
|
+
gem.authors = ["Florin T.PATRASCU"]
|
8
|
+
gem.email = ["florin.patrascu@gmail.com"]
|
9
|
+
gem.description = %q{BPL is a gem to help you track your blood pressure and view your records over time}
|
10
|
+
gem.summary = %q{Blood pressure logger}
|
11
|
+
gem.homepage = ""
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
|
18
|
+
# Gem dependencies for run-time
|
19
|
+
gem.add_runtime_dependency "yajl-ruby"
|
20
|
+
gem.add_runtime_dependency 'sqlite3'
|
21
|
+
gem.add_runtime_dependency 'yajl-ruby'
|
22
|
+
gem.add_runtime_dependency 'chronic'
|
23
|
+
gem.add_runtime_dependency 'activerecord-sqlserver-adapter'
|
24
|
+
gem.add_runtime_dependency 'activerecord'
|
25
|
+
gem.add_runtime_dependency 'time_of_day'
|
26
|
+
gem.add_runtime_dependency 'tablizer'
|
27
|
+
|
28
|
+
# Gem dependencies for development
|
29
|
+
gem.add_development_dependency "rspec"
|
30
|
+
|
31
|
+
end
|
data/config/database.yml
ADDED
data/lib/bpl/version.rb
ADDED
data/lib/bpl.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require "bpl/version"
|
2
|
+
require 'yajl'
|
3
|
+
require "models/blood_pressure"
|
4
|
+
require "csv"
|
5
|
+
|
6
|
+
module Bpl
|
7
|
+
def options(opts={})
|
8
|
+
@opts=opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.add(sys, dia, hr, arm='l', weight=nil)
|
12
|
+
@sys = sys.to_i
|
13
|
+
@dia = dia.to_i
|
14
|
+
@hr = hr.to_i
|
15
|
+
@arm = arm
|
16
|
+
@weight = weight
|
17
|
+
|
18
|
+
if weight.nil?
|
19
|
+
begin
|
20
|
+
@weight = BloodPressure.most_recent.weight
|
21
|
+
rescue => e
|
22
|
+
puts "Problems: #{e.message}"
|
23
|
+
puts "You should add your weight next time. It is: 0, now."
|
24
|
+
@weight = 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if @opts[:datetime]
|
29
|
+
@created_at = Chronic.parse @opts[:datetime]
|
30
|
+
else
|
31
|
+
@created_at = Chronic.parse "#{@opts[:date]} #{@opts[:time]}"
|
32
|
+
end
|
33
|
+
|
34
|
+
bp = BloodPressure.new(:sys => @sys, :dia => @dia, :hr => @hr,
|
35
|
+
:arm => arm(@arm), :weight => @weight,
|
36
|
+
:created_at => @created_at,
|
37
|
+
:notes => @opts[:message])
|
38
|
+
bp.save
|
39
|
+
Bpl.echo unless @opts[:quiet]
|
40
|
+
bp
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.remove(id)
|
44
|
+
begin
|
45
|
+
BloodPressure.find(id).delete unless id.nil?
|
46
|
+
puts "record: \##{id}, was removed."
|
47
|
+
rescue => e
|
48
|
+
puts e.message
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.view(silent=false)
|
54
|
+
table = [['ID', 'DATE', 'SYS', 'DIA', 'HR', 'ARM', 'WEIGHT', 'NOTES']]
|
55
|
+
records = []
|
56
|
+
|
57
|
+
if @opts[:all]
|
58
|
+
records = BloodPressure.all_records
|
59
|
+
else
|
60
|
+
records = BloodPressure.records_since(Chronic.parse(@opts[:date]), @opts[:page])
|
61
|
+
end
|
62
|
+
|
63
|
+
if records.empty?
|
64
|
+
puts "the database has no records."
|
65
|
+
else
|
66
|
+
records.each do |r|
|
67
|
+
table << [r.id ,"#{r.date_collected} #{r.time_collected.time_of_day}", r.sys, r.dia, r.hr, r.arm, r.weight, r.notes.nil? ? '' : r.notes]
|
68
|
+
end
|
69
|
+
|
70
|
+
if @opts[:raw]
|
71
|
+
table.shift
|
72
|
+
puts table.inspect
|
73
|
+
else
|
74
|
+
puts Tablizer::Table.new(table, header: true) # can add align: 'ansi_rjust'
|
75
|
+
end unless silent
|
76
|
+
end
|
77
|
+
|
78
|
+
table
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.echo
|
82
|
+
puts "[#{@created_at.inspect}] Sys: #{@sys}, DIA: #{@dia}, HR: #{@hr}, arm: #{arm(@arm)}, W: #{@weight}; Notes: #{@opts[:message]}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.export
|
86
|
+
begin
|
87
|
+
table = Bpl.view true
|
88
|
+
csv_string = CSV.generate do |csv|
|
89
|
+
csv << table[0]
|
90
|
+
table.shift
|
91
|
+
table.each do |r|
|
92
|
+
csv << [r[0], "'#{r[1]}'", r[2], r[3], r[4], "'#{r[5]}'", r[6], "'#{r[7]}'"]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
csv_string
|
97
|
+
rescue => e
|
98
|
+
# puts e.inspect
|
99
|
+
# puts e.backtrace
|
100
|
+
# or:
|
101
|
+
puts caller
|
102
|
+
puts "Error while exporting the data: #{e.message}"
|
103
|
+
''
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
protected
|
108
|
+
def arm(which_one)
|
109
|
+
which_one =~ /[rR]/ ? 'RIGHT' : 'LEFT'
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
data/lib/create_blood.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
class CreateBlood < ActiveRecord::Migration
|
4
|
+
def self.up
|
5
|
+
create_table :blood_pressures do |t|
|
6
|
+
t.column :sys, :integer
|
7
|
+
t.column :dia, :integer
|
8
|
+
t.column :hr, :integer
|
9
|
+
t.column :arm, :string
|
10
|
+
t.column :weight, :integer
|
11
|
+
t.column :notes, :text
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
add_index :blood_pressures, [:created_at]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.down
|
18
|
+
drop_table :blood_pressures
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# other methods:
|
23
|
+
# def init_db
|
24
|
+
# ActiveRecord::Schema.define do
|
25
|
+
# .....
|
26
|
+
# end
|
27
|
+
# end
|