hqmf2js 1.2.1 → 1.3.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 +15 -0
- data/.travis.yml +2 -5
- data/Gemfile +6 -4
- data/Gemfile.lock +83 -86
- data/Rakefile +9 -5
- data/app/assets/javascripts/hqmf_util.js.coffee +98 -23
- data/app/assets/javascripts/logging_utils.js.coffee +25 -16
- data/app/assets/javascripts/patient_api_extension.js.coffee +85 -0
- data/app/assets/javascripts/specifics.js.coffee +60 -14
- data/hqmf2js.gemspec +8 -8
- data/lib/assets/javascripts/libraries/map_reduce_utils.js +130 -0
- data/lib/generator/characteristic.js.erb +28 -17
- data/lib/generator/codes_to_json.rb +5 -5
- data/lib/generator/data_criteria.js.erb +5 -5
- data/lib/generator/execution.rb +144 -0
- data/lib/generator/js.rb +46 -21
- data/lib/generator/observation_criteria.js.erb +1 -1
- data/lib/generator/patient_data.js.erb +22 -19
- data/lib/generator/population_criteria.js.erb +6 -1
- data/lib/generator/precondition.js.erb +5 -7
- data/lib/hqmf2js.rb +1 -0
- data/test/fixtures/codes/codes.json +54 -0
- data/test/fixtures/json/0495.json +1014 -0
- data/test/fixtures/json/59New.json +148 -0
- data/test/fixtures/json/data_criteria/specific_occurrence.json +27 -0
- data/test/fixtures/json/data_criteria/temporals_with_anynonnull.json +27 -0
- data/test/fixtures/patients/larry_vanderman.json +4 -4
- data/test/simplecov.rb +19 -0
- data/test/test_helper.rb +1 -1
- data/test/unit/cmd_test.rb +92 -0
- data/test/unit/codes_to_json_test.rb +32 -0
- data/test/unit/erb_context_test.rb +64 -0
- data/test/unit/hqmf_from_json_javascript_test.rb +37 -2
- data/test/unit/hqmf_javascript_test.rb +18 -0
- data/test/unit/js_object_test.rb +27 -0
- data/test/unit/library_function_test.rb +22 -21
- data/test/unit/specifics_test.rb +7 -2
- metadata +16 -121
- data/lib/tasks/cover_me.rake +0 -8
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTFiZDJjMjNmZGViNTU3MGE1MzY2M2YwYzBhZDVmOTViMjRhNDk1Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZGRlMTYwNmRmODBlZjNkNmQwY2E1Yjg4NmY2YmMwZjIxMjNmYjNkZA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZWM3NDBhMzBmYzg5YjE0ODAyZmEzNDliMDgzODIyZmI0MGIxM2FlZDY3ZTBm
|
10
|
+
NDkwZjhhMjMyMGZkZWNjYzk1ZDI0OWFlYjdiYzFmMzU5YmU2MTM3YWMxMGQ5
|
11
|
+
ZDcyMmZiNTdlMTdmMGZhZWVjYmI0YWFiNmUwNzM2MzhlYzcyNjY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YTg5ZDhiZjZlOTYxNzY5ZTlkNjI3NDI2NGQzM2M4YzVkZDEwMTAxZDJmYjQ5
|
14
|
+
ZjJkNWFkZmY3N2UyZDZhYWI1NWY5ZjJkOWU2OGMzZjA4NjhjOTM5ZGM3MjRj
|
15
|
+
MDYzODYwMDAyODU2ZWNhMjhmMWIzMDJjNDAxN2ZmNzNkZjcxZDQ=
|
data/.travis.yml
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
language: ruby
|
2
|
-
|
3
2
|
rvm:
|
4
3
|
- 1.9.3
|
5
|
-
|
6
|
-
script: bundle exec rake
|
7
|
-
|
4
|
+
script: bundle exec rake test
|
8
5
|
notifications:
|
9
6
|
email:
|
10
7
|
recipients:
|
11
8
|
- healthcare-ci@googlegroups.com
|
12
9
|
on_failure: change
|
13
10
|
|
14
|
-
branches:
|
11
|
+
branches:
|
15
12
|
only:
|
16
13
|
- master
|
17
14
|
- develop
|
data/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem 'rails', '3.2.
|
3
|
+
gem 'rails', '3.2.14'
|
4
4
|
|
5
5
|
group :assets do
|
6
6
|
gem 'sass-rails'
|
@@ -8,10 +8,11 @@ group :assets do
|
|
8
8
|
gem 'uglifier'
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
gem 'hquery-patient-api', '1.0.4'
|
12
|
+
gem 'health-data-standards', :git => 'https://github.com/projectcypress/health-data-standards.git', :branch => 'master'
|
12
13
|
|
13
14
|
gem 'nokogiri'
|
14
|
-
gem 'sprockets'
|
15
|
+
gem 'sprockets'
|
15
16
|
gem 'coffee-script'
|
16
17
|
gem 'uglifier'
|
17
18
|
gem 'tilt'
|
@@ -19,9 +20,10 @@ gem 'rake'
|
|
19
20
|
gem 'pry'
|
20
21
|
|
21
22
|
group :test do
|
23
|
+
gem 'simplecov', :require => false
|
24
|
+
|
22
25
|
gem 'minitest'
|
23
26
|
gem 'turn', :require => false
|
24
|
-
gem 'cover_me', '~> 1.2.0'
|
25
27
|
gem 'awesome_print', :require => 'ap'
|
26
28
|
|
27
29
|
platforms :ruby do
|
data/Gemfile.lock
CHANGED
@@ -1,46 +1,53 @@
|
|
1
|
-
|
2
|
-
remote: .
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/projectcypress/health-data-standards.git
|
3
|
+
revision: 7a5673f90ab59b1350e22a71aefc1de5b569d98b
|
4
|
+
branch: master
|
3
5
|
specs:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
health-data-standards (3.4.3)
|
7
|
+
activesupport (~> 3.2.14)
|
8
|
+
builder (~> 3.0.0)
|
9
|
+
erubis (~> 2.7.0)
|
10
|
+
log4r (~> 1.1.10)
|
11
|
+
memoist (~> 0.9.1)
|
12
|
+
mongoid (~> 3.1.4)
|
13
|
+
mongoid-tree (~> 1.0.4)
|
14
|
+
nokogiri (= 1.6.0)
|
15
|
+
rest-client (~> 1.6.7)
|
16
|
+
rubyzip (= 0.9.9)
|
17
|
+
uuid (~> 2.3.7)
|
11
18
|
|
12
19
|
GEM
|
13
20
|
remote: http://rubygems.org/
|
14
21
|
specs:
|
15
|
-
actionmailer (3.2.
|
16
|
-
actionpack (= 3.2.
|
17
|
-
mail (~> 2.
|
18
|
-
actionpack (3.2.
|
19
|
-
activemodel (= 3.2.
|
20
|
-
activesupport (= 3.2.
|
22
|
+
actionmailer (3.2.14)
|
23
|
+
actionpack (= 3.2.14)
|
24
|
+
mail (~> 2.5.4)
|
25
|
+
actionpack (3.2.14)
|
26
|
+
activemodel (= 3.2.14)
|
27
|
+
activesupport (= 3.2.14)
|
21
28
|
builder (~> 3.0.0)
|
22
29
|
erubis (~> 2.7.0)
|
23
30
|
journey (~> 1.0.4)
|
24
|
-
rack (~> 1.4.
|
31
|
+
rack (~> 1.4.5)
|
25
32
|
rack-cache (~> 1.2)
|
26
33
|
rack-test (~> 0.6.1)
|
27
34
|
sprockets (~> 2.2.1)
|
28
|
-
activemodel (3.2.
|
29
|
-
activesupport (= 3.2.
|
35
|
+
activemodel (3.2.14)
|
36
|
+
activesupport (= 3.2.14)
|
30
37
|
builder (~> 3.0.0)
|
31
|
-
activerecord (3.2.
|
32
|
-
activemodel (= 3.2.
|
33
|
-
activesupport (= 3.2.
|
38
|
+
activerecord (3.2.14)
|
39
|
+
activemodel (= 3.2.14)
|
40
|
+
activesupport (= 3.2.14)
|
34
41
|
arel (~> 3.0.2)
|
35
42
|
tzinfo (~> 0.3.29)
|
36
|
-
activeresource (3.2.
|
37
|
-
activemodel (= 3.2.
|
38
|
-
activesupport (= 3.2.
|
39
|
-
activesupport (3.2.
|
40
|
-
i18n (~> 0.6)
|
43
|
+
activeresource (3.2.14)
|
44
|
+
activemodel (= 3.2.14)
|
45
|
+
activesupport (= 3.2.14)
|
46
|
+
activesupport (3.2.14)
|
47
|
+
i18n (~> 0.6, >= 0.6.4)
|
41
48
|
multi_json (~> 1.0)
|
42
49
|
ansi (1.4.3)
|
43
|
-
arel (3.0.
|
50
|
+
arel (3.0.3)
|
44
51
|
awesome_print (1.1.0)
|
45
52
|
builder (3.0.4)
|
46
53
|
coderay (1.0.8)
|
@@ -51,81 +58,67 @@ GEM
|
|
51
58
|
coffee-script-source
|
52
59
|
execjs
|
53
60
|
coffee-script-source (1.4.0)
|
54
|
-
configatron (2.9.1)
|
55
|
-
yamler (>= 0.1.0)
|
56
|
-
cover_me (1.2.0)
|
57
|
-
configatron
|
58
|
-
hashie
|
59
61
|
erubis (2.7.0)
|
60
62
|
execjs (1.4.0)
|
61
63
|
multi_json (~> 1.0)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
builder (~> 3.0.0)
|
66
|
-
erubis (~> 2.7.0)
|
67
|
-
log4r (~> 1.1.10)
|
68
|
-
memoist (~> 0.9.0)
|
69
|
-
mongoid (~> 3.1.0)
|
70
|
-
nokogiri (~> 1.5.5)
|
71
|
-
rest-client (~> 1.6.7)
|
72
|
-
rubyzip
|
73
|
-
uuid (~> 2.3.5)
|
74
|
-
hike (1.2.1)
|
75
|
-
hquery-patient-api (1.0.2)
|
76
|
-
i18n (0.6.1)
|
64
|
+
hike (1.2.3)
|
65
|
+
hquery-patient-api (1.0.4)
|
66
|
+
i18n (0.6.9)
|
77
67
|
journey (1.0.4)
|
78
|
-
json (1.
|
68
|
+
json (1.8.1)
|
79
69
|
libv8 (3.3.10.4)
|
80
70
|
log4r (1.1.10)
|
81
|
-
macaddr (1.6.
|
82
|
-
systemu (~> 2.
|
83
|
-
mail (2.
|
84
|
-
i18n (>= 0.4.0)
|
71
|
+
macaddr (1.6.7)
|
72
|
+
systemu (~> 2.6.2)
|
73
|
+
mail (2.5.4)
|
85
74
|
mime-types (~> 1.16)
|
86
75
|
treetop (~> 1.4.8)
|
87
|
-
memoist (0.9.
|
76
|
+
memoist (0.9.1)
|
88
77
|
method_source (0.8.1)
|
89
|
-
mime-types (1.
|
78
|
+
mime-types (1.25.1)
|
79
|
+
mini_portile (0.5.3)
|
90
80
|
minitest (4.3.2)
|
91
|
-
mongoid (3.1.
|
81
|
+
mongoid (3.1.6)
|
92
82
|
activemodel (~> 3.2)
|
93
|
-
moped (~> 1.4
|
83
|
+
moped (~> 1.4)
|
94
84
|
origin (~> 1.0)
|
95
|
-
tzinfo (~> 0.3.
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
85
|
+
tzinfo (~> 0.3.29)
|
86
|
+
mongoid-tree (1.0.4)
|
87
|
+
mongoid (>= 3.0, <= 4.0)
|
88
|
+
moped (1.5.2)
|
89
|
+
multi_json (1.9.2)
|
90
|
+
nokogiri (1.6.0)
|
91
|
+
mini_portile (~> 0.5.0)
|
92
|
+
origin (1.1.0)
|
93
|
+
polyglot (0.3.4)
|
101
94
|
pry (0.9.10)
|
102
95
|
coderay (~> 1.0.5)
|
103
96
|
method_source (~> 0.8)
|
104
97
|
slop (~> 3.3.1)
|
105
|
-
rack (1.4.
|
98
|
+
rack (1.4.5)
|
106
99
|
rack-cache (1.2)
|
107
100
|
rack (>= 0.4)
|
108
|
-
rack-ssl (1.3.
|
101
|
+
rack-ssl (1.3.4)
|
109
102
|
rack
|
110
103
|
rack-test (0.6.2)
|
111
104
|
rack (>= 1.0)
|
112
|
-
rails (3.2.
|
113
|
-
actionmailer (= 3.2.
|
114
|
-
actionpack (= 3.2.
|
115
|
-
activerecord (= 3.2.
|
116
|
-
activeresource (= 3.2.
|
117
|
-
activesupport (= 3.2.
|
105
|
+
rails (3.2.14)
|
106
|
+
actionmailer (= 3.2.14)
|
107
|
+
actionpack (= 3.2.14)
|
108
|
+
activerecord (= 3.2.14)
|
109
|
+
activeresource (= 3.2.14)
|
110
|
+
activesupport (= 3.2.14)
|
118
111
|
bundler (~> 1.0)
|
119
|
-
railties (= 3.2.
|
120
|
-
railties (3.2.
|
121
|
-
actionpack (= 3.2.
|
122
|
-
activesupport (= 3.2.
|
112
|
+
railties (= 3.2.14)
|
113
|
+
railties (3.2.14)
|
114
|
+
actionpack (= 3.2.14)
|
115
|
+
activesupport (= 3.2.14)
|
123
116
|
rack-ssl (~> 1.3.2)
|
124
117
|
rake (>= 0.8.7)
|
125
118
|
rdoc (~> 3.4)
|
126
119
|
thor (>= 0.14.6, < 2.0)
|
127
|
-
rake (10.0
|
128
|
-
rdoc (3.12)
|
120
|
+
rake (10.2.0)
|
121
|
+
rdoc (3.12.2)
|
129
122
|
json (~> 1.4)
|
130
123
|
rest-client (1.6.7)
|
131
124
|
mime-types (>= 1.16)
|
@@ -135,29 +128,32 @@ GEM
|
|
135
128
|
railties (~> 3.2.0)
|
136
129
|
sass (>= 3.1.10)
|
137
130
|
tilt (~> 1.3)
|
131
|
+
simplecov (0.7.1)
|
132
|
+
multi_json (~> 1.0)
|
133
|
+
simplecov-html (~> 0.7.1)
|
134
|
+
simplecov-html (0.7.1)
|
138
135
|
slop (3.3.3)
|
139
136
|
sprockets (2.2.2)
|
140
137
|
hike (~> 1.2)
|
141
138
|
multi_json (~> 1.0)
|
142
139
|
rack (~> 1.0)
|
143
140
|
tilt (~> 1.1, != 1.3.0)
|
144
|
-
systemu (2.
|
141
|
+
systemu (2.6.4)
|
145
142
|
therubyracer (0.10.2)
|
146
143
|
libv8 (~> 3.3.10)
|
147
|
-
thor (0.
|
148
|
-
tilt (1.
|
149
|
-
treetop (1.4.
|
144
|
+
thor (0.19.1)
|
145
|
+
tilt (1.4.1)
|
146
|
+
treetop (1.4.15)
|
150
147
|
polyglot
|
151
148
|
polyglot (>= 0.3.1)
|
152
149
|
turn (0.9.6)
|
153
150
|
ansi
|
154
|
-
tzinfo (0.3.
|
151
|
+
tzinfo (0.3.39)
|
155
152
|
uglifier (1.3.0)
|
156
153
|
execjs (>= 0.3.0)
|
157
154
|
multi_json (~> 1.0, >= 1.0.2)
|
158
155
|
uuid (2.3.7)
|
159
156
|
macaddr (~> 1.0)
|
160
|
-
yamler (0.1.0)
|
161
157
|
|
162
158
|
PLATFORMS
|
163
159
|
ruby
|
@@ -166,15 +162,16 @@ DEPENDENCIES
|
|
166
162
|
awesome_print
|
167
163
|
coffee-rails
|
168
164
|
coffee-script
|
169
|
-
|
170
|
-
|
165
|
+
health-data-standards!
|
166
|
+
hquery-patient-api (= 1.0.4)
|
171
167
|
minitest
|
172
168
|
nokogiri
|
173
169
|
pry
|
174
|
-
rails (= 3.2.
|
170
|
+
rails (= 3.2.14)
|
175
171
|
rake
|
176
172
|
sass-rails
|
177
|
-
|
173
|
+
simplecov
|
174
|
+
sprockets
|
178
175
|
therubyracer
|
179
176
|
therubyrhino
|
180
177
|
tilt
|
data/Rakefile
CHANGED
@@ -11,12 +11,16 @@ Dir['lib/tasks/*.rake'].sort.each do |ext|
|
|
11
11
|
load ext
|
12
12
|
end
|
13
13
|
|
14
|
-
$LOAD_PATH << File.expand_path("../test",__FILE__)
|
15
14
|
desc "Run basic tests"
|
16
|
-
Rake::TestTask.new(
|
17
|
-
t.
|
15
|
+
Rake::TestTask.new(:test_unit) do |t|
|
16
|
+
t.libs << "test"
|
17
|
+
t.test_files = FileList['test/**/*_test.rb']
|
18
18
|
t.verbose = true
|
19
19
|
t.warning = false
|
20
|
-
|
20
|
+
end
|
21
|
+
|
22
|
+
task :test => [:test_unit] do
|
23
|
+
system("open coverage/index.html")
|
24
|
+
end
|
21
25
|
|
22
|
-
task :default => [:
|
26
|
+
task :default => [:test]
|
@@ -52,6 +52,7 @@ class TS
|
|
52
52
|
else
|
53
53
|
earlier = @date
|
54
54
|
later = ts.asDate()
|
55
|
+
return Number.MAX_VALUE if !earlier? || !later?
|
55
56
|
if granularity=="a"
|
56
57
|
TS.yearsDifference(earlier,later)
|
57
58
|
else if granularity=="mo"
|
@@ -91,6 +92,9 @@ class TS
|
|
91
92
|
[a,b] = TS.dropSeconds(@date, other.date)
|
92
93
|
a.getTime() > b.getTime()
|
93
94
|
|
95
|
+
equals: (other) ->
|
96
|
+
(@date==null && other.date==null) || (@date.getTime()==other.date.getTime())
|
97
|
+
|
94
98
|
# Returns whether this TS is before or concurrent with the supplied TS ignoring seconds
|
95
99
|
beforeOrConcurrent: (other) ->
|
96
100
|
if @date==null || other.date==null
|
@@ -398,6 +402,10 @@ class IVL_TS
|
|
398
402
|
@low.asDate() && other.high.asDate() && @low.withinSameMinute(other.high)
|
399
403
|
else
|
400
404
|
false
|
405
|
+
|
406
|
+
equals: (other) ->
|
407
|
+
(@low==null && other.low==null) || (@low.equals(other.low)) && (@high==null && other.high==null) || (@high.equals(other.high))
|
408
|
+
|
401
409
|
@IVL_TS = IVL_TS
|
402
410
|
|
403
411
|
# Used to represent a value that will match any other value that is not null.
|
@@ -408,29 +416,80 @@ class ANYNonNull
|
|
408
416
|
val != null
|
409
417
|
@ANYNonNull = ANYNonNull
|
410
418
|
|
419
|
+
invokeOne = (patient, initialSpecificContext, fn) ->
|
420
|
+
if typeof(fn.isTrue)=='function' || typeof(fn)=='boolean'
|
421
|
+
fn
|
422
|
+
else
|
423
|
+
fn(patient, initialSpecificContext)
|
424
|
+
@invokeOne = invokeOne
|
425
|
+
|
426
|
+
evalUnlessShortCircuit = (fn) ->
|
427
|
+
# if we are short circuiting then return the function uncalled, if we are not then call the function and
|
428
|
+
# evaluate the tree. If uncalled, from here the function will only be called if required
|
429
|
+
if (Logger.short_circuit) then fn else fn()
|
430
|
+
@evalUnlessShortCircuit = evalUnlessShortCircuit
|
431
|
+
|
432
|
+
invokeAll = (patient, initialSpecificContext, fns) ->
|
433
|
+
(invokeOne(patient, initialSpecificContext, fn) for fn in fns)
|
434
|
+
@invokeAll = invokeAll
|
435
|
+
|
411
436
|
# Returns true if one or more of the supplied values is true
|
412
|
-
atLeastOneTrue = (precondition,
|
413
|
-
|
414
|
-
|
415
|
-
|
437
|
+
atLeastOneTrue = (precondition, patient, initialSpecificContext, valueFns...) ->
|
438
|
+
evalUnlessShortCircuit ->
|
439
|
+
values = invokeAll(patient, initialSpecificContext, valueFns)
|
440
|
+
trueValues = (value for value in values when value && value.isTrue())
|
441
|
+
hqmf.SpecificsManager.unionAll(new Boolean(trueValues.length>0), values)
|
416
442
|
@atLeastOneTrue = atLeastOneTrue
|
417
|
-
|
443
|
+
|
418
444
|
# Returns true if all of the supplied values are true
|
419
|
-
allTrue = (precondition,
|
420
|
-
|
421
|
-
|
445
|
+
allTrue = (precondition, patient, initialSpecificContext, valueFns...) ->
|
446
|
+
evalUnlessShortCircuit ->
|
447
|
+
values = []
|
448
|
+
for valueFn in valueFns
|
449
|
+
value = invokeOne(patient, initialSpecificContext, valueFn)
|
450
|
+
# break if the we have a false value and we're short circuiting.
|
451
|
+
#If we're not short circuiting then we want to calculate everything
|
452
|
+
break if value.isFalse() && Logger.short_circuit
|
453
|
+
values.push(value)
|
454
|
+
trueValues = (value for value in values when value && value.isTrue())
|
455
|
+
if trueValues.length==valueFns.length
|
456
|
+
hqmf.SpecificsManager.intersectAll(new Boolean(trueValues.length>0), trueValues)
|
457
|
+
else
|
458
|
+
# only intersect on false if we are not short circuiting.
|
459
|
+
# if we are not short circuiting then we want to have the specifics context returned for rationale
|
460
|
+
if Logger.short_circuit
|
461
|
+
value = new Boolean(false)
|
462
|
+
value.specificContext = hqmf.SpecificsManager.empty()
|
463
|
+
value
|
464
|
+
else
|
465
|
+
hqmf.SpecificsManager.intersectAll(new Boolean(false), values)
|
466
|
+
|
467
|
+
|
422
468
|
@allTrue = allTrue
|
423
469
|
|
424
470
|
# Returns true if one or more of the supplied values is false
|
425
|
-
atLeastOneFalse = (precondition,
|
426
|
-
|
427
|
-
|
471
|
+
atLeastOneFalse = (precondition, patient, initialSpecificContext, valueFns...) ->
|
472
|
+
# values = invokeAll(patient, initialSpecificContext, valueFns)
|
473
|
+
# falseValues = (value for value in values when value.isFalse())
|
474
|
+
# hqmf.SpecificsManager.intersectAll(new Boolean(falseValues.length>0), values, true)
|
475
|
+
evalUnlessShortCircuit ->
|
476
|
+
values = []
|
477
|
+
hasFalse = false
|
478
|
+
for valueFn in valueFns
|
479
|
+
value = invokeOne(patient, initialSpecificContext, valueFn)
|
480
|
+
values.push(value)
|
481
|
+
if value.isFalse()
|
482
|
+
hasFalse = true
|
483
|
+
break if Logger.short_circuit
|
484
|
+
hqmf.SpecificsManager.intersectAll(new Boolean(values.length>0 && hasFalse), values, true)
|
428
485
|
@atLeastOneFalse = atLeastOneFalse
|
429
486
|
|
430
487
|
# Returns true if all of the supplied values are false
|
431
|
-
allFalse = (precondition,
|
432
|
-
|
433
|
-
|
488
|
+
allFalse = (precondition, patient, initialSpecificContext, valueFns...) ->
|
489
|
+
evalUnlessShortCircuit ->
|
490
|
+
values = invokeAll(patient, initialSpecificContext, valueFns)
|
491
|
+
falseValues = (value for value in values when value.isFalse())
|
492
|
+
hqmf.SpecificsManager.unionAll(new Boolean(falseValues.length>0 && falseValues.length==values.length), values, true)
|
434
493
|
@allFalse = allFalse
|
435
494
|
|
436
495
|
# Return true if compareTo matches value
|
@@ -447,7 +506,7 @@ anyMatchingValue = (event, valueToMatch) ->
|
|
447
506
|
# Return only those events whose value matches the supplied value
|
448
507
|
filterEventsByValue = (events, value) ->
|
449
508
|
matchingEvents = (event for event in events when (anyMatchingValue(event, value)))
|
450
|
-
matchingEvents
|
509
|
+
hqmf.SpecificsManager.maintainSpecifics(matchingEvents, events)
|
451
510
|
@filterEventsByValue = filterEventsByValue
|
452
511
|
|
453
512
|
# Return only those events with a field that matches the supplied value
|
@@ -530,11 +589,14 @@ XPRODUCT = (eventLists...) ->
|
|
530
589
|
# Create a new list containing all the events from the supplied event lists
|
531
590
|
UNION = (eventLists...) ->
|
532
591
|
union = []
|
533
|
-
# keep track of the specific occurrences by encounter ID. This is used in
|
592
|
+
# keep track of the specific occurrences by encounter ID. This is used in
|
593
|
+
# eventsMatchBounds (specifically in buildRowsForMatching down the _.isObject path)
|
534
594
|
specific_occurrence = {}
|
535
595
|
for eventList in eventLists
|
536
596
|
for event in eventList
|
537
|
-
|
597
|
+
if eventList.specific_occurrence
|
598
|
+
specific_occurrence[event.id] ||= []
|
599
|
+
specific_occurrence[event.id].push eventList.specific_occurrence
|
538
600
|
union.push(event)
|
539
601
|
union.specific_occurrence = specific_occurrence unless _.isEmpty(specific_occurrence)
|
540
602
|
hqmf.SpecificsManager.unionAll(union, eventLists)
|
@@ -745,39 +807,52 @@ applySpecificOccurrenceSubset = (operator, result, range, calculateSpecifics) ->
|
|
745
807
|
result.specificContext = result.specificContext[operator]()
|
746
808
|
result
|
747
809
|
|
810
|
+
uniqueEvents = (events) ->
|
811
|
+
hash = {}
|
812
|
+
(hash[event.id] = event for event in events)
|
813
|
+
_.values(hash)
|
814
|
+
@uniqueEvents = uniqueEvents
|
815
|
+
|
816
|
+
# if we have multiple events at the same exact time and they happen to be the one selected by FIRST, RECENT, etc
|
817
|
+
# then we want to select all of these issues as the first, most recent, etc.
|
818
|
+
selectConcurrent = (target, events) ->
|
819
|
+
targetIVL = target.asIVL_TS()
|
820
|
+
uniqueEvents((result for result in events when result.asIVL_TS().equals(targetIVL)))
|
821
|
+
@selectConcurrent = selectConcurrent
|
822
|
+
|
748
823
|
FIRST = (events) ->
|
749
824
|
result = []
|
750
|
-
result =
|
825
|
+
result = selectConcurrent(events.sort(dateSortAscending)[0], events) if (events.length > 0)
|
751
826
|
applySpecificOccurrenceSubset('FIRST',hqmf.SpecificsManager.maintainSpecifics(result, events))
|
752
827
|
@FIRST = FIRST
|
753
828
|
|
754
829
|
SECOND = (events) ->
|
755
830
|
result = []
|
756
|
-
result =
|
831
|
+
result = selectConcurrent(events.sort(dateSortAscending)[1], events) if (events.length > 1)
|
757
832
|
applySpecificOccurrenceSubset('SECOND',hqmf.SpecificsManager.maintainSpecifics(result, events))
|
758
833
|
@SECOND = SECOND
|
759
834
|
|
760
835
|
THIRD = (events) ->
|
761
836
|
result = []
|
762
|
-
result =
|
837
|
+
result = selectConcurrent(events.sort(dateSortAscending)[2], events) if (events.length > 2)
|
763
838
|
applySpecificOccurrenceSubset('THIRD',hqmf.SpecificsManager.maintainSpecifics(result, events))
|
764
839
|
@THIRD = THIRD
|
765
840
|
|
766
841
|
FOURTH = (events) ->
|
767
842
|
result = []
|
768
|
-
result =
|
843
|
+
result = selectConcurrent(events.sort(dateSortAscending)[3], events) if (events.length > 3)
|
769
844
|
applySpecificOccurrenceSubset('FOURTH',hqmf.SpecificsManager.maintainSpecifics(result, events))
|
770
845
|
@FOURTH = FOURTH
|
771
846
|
|
772
847
|
FIFTH = (events) ->
|
773
848
|
result = []
|
774
|
-
result =
|
849
|
+
result = selectConcurrent(events.sort(dateSortAscending)[4], events) if (events.length > 4)
|
775
850
|
applySpecificOccurrenceSubset('FIFTH',hqmf.SpecificsManager.maintainSpecifics(result, events))
|
776
851
|
@FIFTH = FIFTH
|
777
852
|
|
778
853
|
RECENT = (events) ->
|
779
854
|
result = []
|
780
|
-
result =
|
855
|
+
result = selectConcurrent(events.sort(dateSortDescending)[0], events) if (events.length > 0)
|
781
856
|
applySpecificOccurrenceSubset('RECENT',hqmf.SpecificsManager.maintainSpecifics(result, events))
|
782
857
|
@RECENT = RECENT
|
783
858
|
|
@@ -4,11 +4,18 @@ class @Logger
|
|
4
4
|
@info: (string) ->
|
5
5
|
if @enable_logging
|
6
6
|
@logger.push("#{Logger.indent()}#{string}")
|
7
|
+
|
7
8
|
@record: (id, result) ->
|
8
9
|
if @enable_rationale and result? and typeof(result.isTrue) == 'function'
|
9
|
-
|
10
|
+
if result.isTrue() and result.length
|
11
|
+
json_results = _.map(result,(item) -> {id: item.id, json: item.json})
|
12
|
+
@rationale[id] = {results: json_results }
|
13
|
+
else
|
14
|
+
@rationale[id] = result.isTrue()
|
15
|
+
|
10
16
|
@enable_logging: true
|
11
17
|
@enable_rationale: true
|
18
|
+
@short_circuit: true
|
12
19
|
@initialized: false
|
13
20
|
@indentCount = 0
|
14
21
|
@indent: ->
|
@@ -67,9 +74,10 @@ class @Logger
|
|
67
74
|
Logger.indentCount--
|
68
75
|
|
69
76
|
|
70
|
-
@injectLogger = (hqmfjs, enable_logging, enable_rationale) ->
|
77
|
+
@injectLogger = (hqmfjs, enable_logging, enable_rationale, short_circuit) ->
|
71
78
|
Logger.enable_logging = enable_logging
|
72
79
|
Logger.enable_rationale = enable_rationale
|
80
|
+
Logger.short_circuit = short_circuit
|
73
81
|
|
74
82
|
# Wrap all of the data criteria functions generated from HQMF
|
75
83
|
_.each(_.functions(hqmfjs), (method) ->
|
@@ -98,20 +106,21 @@ class @Logger
|
|
98
106
|
|
99
107
|
# Wrap selected hQuery Patient API functions
|
100
108
|
_.each(_.functions(hQuery.Patient.prototype), (method) ->
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
109
|
+
if method != 'getEvents' && method != 'getAndCacheEvents'
|
110
|
+
if (hQuery.Patient.prototype[method].length == 0)
|
111
|
+
hQuery.Patient.prototype[method] = _.wrap(hQuery.Patient.prototype[method], (func) ->
|
112
|
+
Logger.info("called patient.#{method}():")
|
113
|
+
func = _.bind(func, this)
|
114
|
+
result = func()
|
115
|
+
Logger.info("patient.#{method}() -> #{Logger.stringify(result)}")
|
116
|
+
return result;);
|
117
|
+
else
|
118
|
+
hQuery.Patient.prototype[method] = _.wrap(hQuery.Patient.prototype[method], (func) ->
|
119
|
+
args = Array.prototype.slice.call(arguments,1)
|
120
|
+
Logger.info("called patient.#{method}(#{args}):")
|
121
|
+
result = func.apply(this, args)
|
122
|
+
Logger.info("patient.#{method}(#{args}) -> #{Logger.stringify(result)}")
|
123
|
+
return result;);
|
115
124
|
|
116
125
|
);
|
117
126
|
|