hqmf2js 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|