pueri 0.7.0
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.
- checksums.yaml +7 -0
- data/.gitattributes +194 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/ISSUE_TEMPLATE/user_question.md +14 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- data/.github/config.yml +49 -0
- data/.gitignore +252 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +22 -0
- data/CHANGELOG.md +26 -0
- data/CODE-OF-CONDUCT.md +78 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +82 -0
- data/LICENSE.md +13 -0
- data/README.md +43 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/docs/Pueri.html +231 -0
- data/docs/Pueri/Age.html +600 -0
- data/docs/Pueri/Neuro.html +660 -0
- data/docs/Pueri/Vax.html +698 -0
- data/docs/_index.html +152 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +116 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +116 -0
- data/docs/js/app.js +303 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +211 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/pueri.rb +15 -0
- data/lib/pueri/age.rb +161 -0
- data/lib/pueri/neuro.rb +144 -0
- data/lib/pueri/vax.rb +121 -0
- data/lib/pueri/version.rb +17 -0
- data/package.json +16 -0
- data/pueri.gemspec +45 -0
- metadata +163 -0
data/lib/pueri.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pueri/age'
|
4
|
+
require 'pueri/neuro'
|
5
|
+
require 'pueri/vax'
|
6
|
+
require 'pueri/version'
|
7
|
+
|
8
|
+
require 'pastel'
|
9
|
+
require 'tty-table'
|
10
|
+
|
11
|
+
# This module is a support for physicians and nurses who work on Primary Care
|
12
|
+
# with children age 12 and younger. It calculates the child's age and outputs
|
13
|
+
# an optimal vaccination scheme for such age, based on Brazil's National Program
|
14
|
+
# of Immunization (PNI), using the 2019 uptade.
|
15
|
+
module Pueri; end
|
data/lib/pueri/age.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pueri
|
4
|
+
# Parses a given date string into and Array of age. The array contains the
|
5
|
+
# years, months and days of life of the one who was/would be born on the given
|
6
|
+
# day.
|
7
|
+
class Age
|
8
|
+
attr_reader :days_month, :age
|
9
|
+
|
10
|
+
# Creates an Age instance.
|
11
|
+
#
|
12
|
+
# @param date [String] A date current or on the past - NOT on the future.
|
13
|
+
def initialize(date)
|
14
|
+
@days_month = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
15
|
+
@age = parse_age(date)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Retrieves the age on a readable format.
|
19
|
+
#
|
20
|
+
# @param short [Booleann] Whether to output a short-format age or not.
|
21
|
+
# Defaults to long format.
|
22
|
+
# @return [String] The age in a readable format, either short or long.
|
23
|
+
def to_s(short = false)
|
24
|
+
if short
|
25
|
+
short_string
|
26
|
+
else
|
27
|
+
long_string
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Retrieves the age in days.
|
32
|
+
#
|
33
|
+
# @return [Float] The age in days, rounded to the second decimal place.
|
34
|
+
def to_f
|
35
|
+
a = age[0].to_f * 365.25
|
36
|
+
a += age[1].to_f * 30.0
|
37
|
+
a += age[2].to_f
|
38
|
+
a.round(2)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def short_string
|
44
|
+
p = Pastel.new
|
45
|
+
"#{p.bold(age[0])}a#{p.bold(age[1])}m#{p.bold(age[2])}d"
|
46
|
+
end
|
47
|
+
|
48
|
+
def long_string
|
49
|
+
p = Pastel.new
|
50
|
+
"Idade: #{p.cyan(age[0])} anos, #{p.cyan(age[1])} meses, "\
|
51
|
+
"#{p.cyan(age[2])} dias."
|
52
|
+
end
|
53
|
+
|
54
|
+
# This method takes a date in the string format "DD/MM/YYYY" and returns
|
55
|
+
# a Time object.
|
56
|
+
def birthday_timestamp_time(date_read)
|
57
|
+
date = date_read.chomp
|
58
|
+
if date =~ %r{/}
|
59
|
+
birthday = date.split('/')
|
60
|
+
birthday[2] = year(birthday[2])
|
61
|
+
else
|
62
|
+
birthday = parse_numonly_date(date)
|
63
|
+
end
|
64
|
+
Time.new(birthday[2], birthday[1], birthday[0])
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_numonly_date(date)
|
68
|
+
if date.size == 6
|
69
|
+
[date[0..1], date[2..3], year(date[4..5])]
|
70
|
+
else
|
71
|
+
[date[0..1], date[2..3], date[4..7]]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def year(year)
|
76
|
+
if year.chomp.size == 2
|
77
|
+
if year.to_i < 30
|
78
|
+
year.prepend('20')
|
79
|
+
else
|
80
|
+
year.prepend('19')
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
year
|
85
|
+
end
|
86
|
+
|
87
|
+
def future_day?(day, month, birth_date, current_date, borrowed_month)
|
88
|
+
if day.negative?
|
89
|
+
# subtract month, get positive # for day
|
90
|
+
day = @days_month[birth_date.month] - birth_date.day + current_date.day
|
91
|
+
month -= 1
|
92
|
+
borrowed_month = true
|
93
|
+
end
|
94
|
+
|
95
|
+
[day, month, borrowed_month]
|
96
|
+
end
|
97
|
+
|
98
|
+
def future_month?(month, year, birth_date, current_date, borrowed_month)
|
99
|
+
if month.negative?
|
100
|
+
# subtract year, get positive # for month
|
101
|
+
month = 12 - birth_date.month + current_date.month
|
102
|
+
month -= 1 if borrowed_month == true
|
103
|
+
year -= 1
|
104
|
+
end
|
105
|
+
|
106
|
+
[month, year]
|
107
|
+
end
|
108
|
+
|
109
|
+
def future_year?(year, month, day)
|
110
|
+
# Error-handling for future date
|
111
|
+
if year.negative?
|
112
|
+
year = 0
|
113
|
+
month = 0
|
114
|
+
day = 0
|
115
|
+
end
|
116
|
+
|
117
|
+
[year, month, day]
|
118
|
+
end
|
119
|
+
|
120
|
+
def check_future(day, month, year, dates, borrowed_month)
|
121
|
+
birth_date, current_date = dates
|
122
|
+
day, month, borrowed_month = future_day?(
|
123
|
+
day, month, birth_date, current_date, borrowed_month
|
124
|
+
)
|
125
|
+
month, year = future_month?(
|
126
|
+
month, year, birth_date, current_date, borrowed_month
|
127
|
+
)
|
128
|
+
year, month, day = future_year?(year, month, day)
|
129
|
+
|
130
|
+
[day, month, year]
|
131
|
+
end
|
132
|
+
|
133
|
+
def check_present(current_date, birth_date)
|
134
|
+
day = current_date.day - birth_date.day
|
135
|
+
month = current_date.month - birth_date.month
|
136
|
+
year = current_date.year - birth_date.year
|
137
|
+
|
138
|
+
[day, month, year]
|
139
|
+
end
|
140
|
+
|
141
|
+
# This method takes a birthday in the string format "DD/MM/YYYY" and returns
|
142
|
+
# the person's age.
|
143
|
+
def parse_age(date)
|
144
|
+
borrowed_month = false
|
145
|
+
|
146
|
+
current_date = Time.new
|
147
|
+
birth_date = birthday_timestamp_time(date)
|
148
|
+
|
149
|
+
# Get days for this year
|
150
|
+
@days_month[2] = 29 if current_date.to_date.leap?
|
151
|
+
|
152
|
+
day, month, year = check_present(current_date, birth_date)
|
153
|
+
|
154
|
+
day, month, year = check_future(
|
155
|
+
day, month, year, [birth_date, current_date], borrowed_month
|
156
|
+
)
|
157
|
+
|
158
|
+
[year, month, day]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/pueri/neuro.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pueri
|
4
|
+
# Class description here
|
5
|
+
class Neuro
|
6
|
+
attr_reader :range, :header, :social, :motor, :lang, :table
|
7
|
+
|
8
|
+
def initialize(norm_age)
|
9
|
+
@range = calc_range(norm_age)
|
10
|
+
init_tables
|
11
|
+
mount_table
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def mount_table
|
17
|
+
adjust_length
|
18
|
+
table_obj = TTY::Table.new @header, make_lines
|
19
|
+
@table = table_obj.render :unicode
|
20
|
+
end
|
21
|
+
|
22
|
+
def adjust_length
|
23
|
+
max_length = num_lines
|
24
|
+
adjust_length_social(max_length)
|
25
|
+
adjust_length_motor(max_length)
|
26
|
+
adjust_length_lang(max_length)
|
27
|
+
end
|
28
|
+
|
29
|
+
def adjust_length_social(max_length)
|
30
|
+
return unless @social.size < max_length
|
31
|
+
|
32
|
+
(max_length - @social.size).times do
|
33
|
+
@social.append ''
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def adjust_length_motor(max_length)
|
38
|
+
return unless @motor.size < max_length
|
39
|
+
|
40
|
+
(max_length - @motor.size).times do
|
41
|
+
@motor.append ''
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def adjust_length_lang(max_length)
|
46
|
+
return unless @lang.size < max_length
|
47
|
+
|
48
|
+
(max_length - @lang.size).times do
|
49
|
+
@lang.append ''
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def make_lines
|
54
|
+
[@social, @motor, @lang].transpose
|
55
|
+
end
|
56
|
+
|
57
|
+
def num_lines
|
58
|
+
n = @social.size
|
59
|
+
n = @motor.size if @motor.size > n
|
60
|
+
n = @lang.size if @lang.size > n
|
61
|
+
n
|
62
|
+
end
|
63
|
+
|
64
|
+
def init_tables
|
65
|
+
init_header
|
66
|
+
init_social
|
67
|
+
init_motor
|
68
|
+
init_lang
|
69
|
+
end
|
70
|
+
|
71
|
+
def init_header
|
72
|
+
@header = %w[
|
73
|
+
Social
|
74
|
+
Motor
|
75
|
+
Linguagem
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
79
|
+
def init_social
|
80
|
+
social = [
|
81
|
+
'Mamar, evacuar e dormir.',
|
82
|
+
'Fixa o olhar com o examinador',
|
83
|
+
'Sorriso social',
|
84
|
+
'Leva a mão a objetos', '', '',
|
85
|
+
'Estranhamento social', '',
|
86
|
+
'Dá tchau e bate palma',
|
87
|
+
'Imita atividades da casa', '', ''
|
88
|
+
]
|
89
|
+
@social = social[0..@range].reject(&:empty?)
|
90
|
+
end
|
91
|
+
|
92
|
+
def init_motor
|
93
|
+
motor = [
|
94
|
+
'', '', '',
|
95
|
+
'Fixa polo cefálico',
|
96
|
+
'Senta com apoio',
|
97
|
+
'Senta sem apoio, pinça superior',
|
98
|
+
'Fica em pé com ajuda', '', '',
|
99
|
+
'Primeiros passos', '', ''
|
100
|
+
]
|
101
|
+
@motor = motor[0..@range].reject(&:empty?)
|
102
|
+
end
|
103
|
+
|
104
|
+
def init_lang
|
105
|
+
lang = [
|
106
|
+
'', '', '', '',
|
107
|
+
'Lalação', '', '',
|
108
|
+
'Primeiras palavras', '',
|
109
|
+
'Palavra frase',
|
110
|
+
'Junta duas palavras',
|
111
|
+
'Fases gramaticais'
|
112
|
+
]
|
113
|
+
@lang = lang[0..@range].reject(&:empty?)
|
114
|
+
end
|
115
|
+
|
116
|
+
def out_of_range
|
117
|
+
m = 'The given age is out of reality bounds'
|
118
|
+
raise ArgumentError, m
|
119
|
+
end
|
120
|
+
|
121
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
122
|
+
# Disabled rubocop for this method for breaking this switch apart will make
|
123
|
+
# it less readable than keeping it as a whole logic.
|
124
|
+
def calc_range(age)
|
125
|
+
r = case age
|
126
|
+
when 0.01..59.99 then 0
|
127
|
+
when 60.0..89.99 then 1
|
128
|
+
when 90.0..119.99 then 2
|
129
|
+
when 120.0..179.99 then 3
|
130
|
+
when 180.0..269.99 then 4
|
131
|
+
when 270.0..299.99 then 5
|
132
|
+
when 300.0..365.24 then 6
|
133
|
+
when 365.25..455.24 then 7
|
134
|
+
when 455.25..545.24 then 8
|
135
|
+
when 545.25..730.49 then 9
|
136
|
+
when 730.5..1095.74 then 10
|
137
|
+
when 1095.75..50_000.0 then 11
|
138
|
+
else out_of_range
|
139
|
+
end
|
140
|
+
r
|
141
|
+
end
|
142
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
143
|
+
end
|
144
|
+
end
|
data/lib/pueri/vax.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pueri
|
4
|
+
# Gets input from child vaccination calendar for children (PNI) and an age in
|
5
|
+
# days. With this, process which vaccines are due by that age.
|
6
|
+
class Vax
|
7
|
+
attr_reader :header, :calendar, :notes
|
8
|
+
attr_reader :range, :table
|
9
|
+
|
10
|
+
def initialize(norm_age)
|
11
|
+
init_base
|
12
|
+
@range = calc_range(norm_age)
|
13
|
+
parse_calendar
|
14
|
+
end
|
15
|
+
|
16
|
+
# Retrieves the notes for the vaccination calendar, prettified.
|
17
|
+
#
|
18
|
+
# @return [String] The notes for the vaccines' calendar.
|
19
|
+
def parse_notes
|
20
|
+
r = ''
|
21
|
+
max = @notes.size
|
22
|
+
p = Pastel.new
|
23
|
+
|
24
|
+
@notes.each_with_index do |line, k|
|
25
|
+
pre = ' ' * (max - (k + 1))
|
26
|
+
pre += '*' * (k.to_i + 1)
|
27
|
+
r += "\n#{p.cyan(pre)} #{line}"
|
28
|
+
end
|
29
|
+
|
30
|
+
r
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def init_base
|
36
|
+
init_header
|
37
|
+
init_calendar
|
38
|
+
init_notes
|
39
|
+
end
|
40
|
+
|
41
|
+
def init_header
|
42
|
+
@header = ['BCB', 'HepB', 'Penta', 'Polio', 'Pneumo 10V', 'Rota',
|
43
|
+
'MeningoC', 'FA', 'HepA', 'SCR', 'Tetra*', 'Varicela',
|
44
|
+
'HPV', 'Influenza']
|
45
|
+
end
|
46
|
+
|
47
|
+
def init_calendar
|
48
|
+
part1 = init_calendar1
|
49
|
+
part2 = init_calendar2
|
50
|
+
@calendar = part1.concat part2
|
51
|
+
end
|
52
|
+
|
53
|
+
def init_calendar1
|
54
|
+
[
|
55
|
+
['DU', '1ª', '', '', '', '', '', '', '', '', '', '', '', ''],
|
56
|
+
['', '', '1ª', '1ª VIP', '1ª', '1ª', '', '', '', '', '', '', '', ''],
|
57
|
+
['', '', '', '', '', '', '1ª', '', '', '', '', '', '', ''],
|
58
|
+
['', '', '2ª', '2ª VIP', '2ª', '2ª', '', '', '', '', '', '', '', ''],
|
59
|
+
['', '', '', '', '', '', '2ª', '', '', '', '', '', '', ''],
|
60
|
+
['', '', '3ª', '3ª VIP', '', '', '', '', '', '', '', '', '', '**']
|
61
|
+
]
|
62
|
+
end
|
63
|
+
|
64
|
+
def init_calendar2
|
65
|
+
[
|
66
|
+
['', '', '', '', '', '', '', 'DU', '', '', '', '', '', '**'],
|
67
|
+
['', '', '', '', 'Ref', '', 'Ref', '', '', '1ª', '', '', '', '**'],
|
68
|
+
['', '', 'DTP', '1ª VOP', '', '', '', '', 'DU', '', 'DU', '', '', '**'],
|
69
|
+
['', '', 'DTP', '2ª VOP', '', '', '', '', '', '', '', 'DU', '', '**'],
|
70
|
+
['', '', '', '', '', '', '', '', '', '', '', '', '***', '']
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def init_notes
|
75
|
+
@notes = [
|
76
|
+
'A vacina tetra viral corresponde à segunda dose de SCR e a uma dose '\
|
77
|
+
'de Varicela.',
|
78
|
+
'A partir dos 6 meses aos 6 anos incompletos, uma dose por ano, exceto'\
|
79
|
+
' no primeiro ano de vida, quase se oferta duas doses.',
|
80
|
+
'Meninas de 9 a 14 anos. Meninos de 11 a 14 anos. Duas doses com '\
|
81
|
+
'intervalo de 6 meses.'
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_calendar
|
86
|
+
table_obj = TTY::Table.new(header: @header) do |table_line|
|
87
|
+
@calendar[0..@range].each do |line|
|
88
|
+
table_line << line
|
89
|
+
end
|
90
|
+
end
|
91
|
+
@table = table_obj.render(:unicode, alignment: :center)
|
92
|
+
end
|
93
|
+
|
94
|
+
def out_of_range
|
95
|
+
m = 'The given age is out of reality bounds'
|
96
|
+
raise ArgumentError, m
|
97
|
+
end
|
98
|
+
|
99
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
100
|
+
# Disabled rubocop for this method for breaking this switch apart will make
|
101
|
+
# it less readable than keeping it as a whole logic.
|
102
|
+
def calc_range(norm_age)
|
103
|
+
r = case norm_age
|
104
|
+
when 0.01..59.99 then 0
|
105
|
+
when 60.0..89.99 then 1
|
106
|
+
when 90.0..119.99 then 2
|
107
|
+
when 120.0..149.99 then 3
|
108
|
+
when 150.0..179.99 then 4
|
109
|
+
when 180.0..269.99 then 5
|
110
|
+
when 270.0..365.24 then 6
|
111
|
+
when 365.25..455.24 then 7
|
112
|
+
when 455.25..1460.99 then 8
|
113
|
+
when 1461.0..3287.24 then 9
|
114
|
+
when 3287.25..50_000.0 then 10
|
115
|
+
else out_of_range
|
116
|
+
end
|
117
|
+
r
|
118
|
+
end
|
119
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module is a support for physicians and nurses who work on Primary Care
|
4
|
+
# with children age 12 and younger. It calculates the child's age and outputs
|
5
|
+
# an optimal vaccination scheme for such age, based on Brazil's National Program
|
6
|
+
# of Immunization (PNI), using the 2019 uptade.
|
7
|
+
module Pueri
|
8
|
+
# Sets the current version of the gem
|
9
|
+
@version = '0.7.0'
|
10
|
+
|
11
|
+
# Returns the Gem's current version.
|
12
|
+
#
|
13
|
+
# @return [String] The Gem's current version.
|
14
|
+
def self.version
|
15
|
+
@version
|
16
|
+
end
|
17
|
+
end
|