hqmf2js 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -3
- data/Gemfile.lock +33 -22
- data/app/assets/javascripts/custom_calculations.js.coffee +63 -5
- data/app/assets/javascripts/hqmf_util.js.coffee +38 -5
- data/app/assets/javascripts/logging_utils.js.coffee +15 -8
- data/app/assets/javascripts/patient_api_extension.js.coffee +4 -0
- data/hqmf2js.gemspec +3 -1
- data/lib/generator/codes_to_json.rb +5 -4
- data/lib/generator/data_criteria.js.erb +2 -2
- data/lib/generator/derived_data.js.erb +1 -1
- data/lib/generator/js.rb +8 -3
- data/lib/generator/measure_period.js.erb +2 -1
- data/lib/generator/observation_criteria.js.erb +4 -0
- data/lib/generator/population_criteria.js.erb +2 -2
- data/lib/generator/precondition.js.erb +5 -3
- data/lib/tasks/convert.rake +13 -9
- data/test/fixtures/json/59New.json +3 -3
- data/test/fixtures/patients/larry_vanderman.json +1 -1
- data/test/unit/custom_calculations_test.rb +66 -0
- data/test/unit/library_function_test.rb +16 -16
- data/test/unit/specifics_test.rb +23 -0
- metadata +35 -2
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hqmf2js (1.2.0)
|
5
|
+
coffee-script (~> 2.2.0)
|
6
|
+
health-data-standards (~> 3.0.1)
|
7
|
+
hquery-patient-api (~> 1.0.1)
|
8
|
+
nokogiri (~> 1.5.5)
|
9
|
+
sprockets (~> 2.2.2)
|
10
|
+
tilt (~> 1.3.3)
|
11
|
+
|
1
12
|
GEM
|
2
13
|
remote: http://rubygems.org/
|
3
14
|
specs:
|
@@ -49,28 +60,28 @@ GEM
|
|
49
60
|
erubis (2.7.0)
|
50
61
|
execjs (1.4.0)
|
51
62
|
multi_json (~> 1.0)
|
52
|
-
faraday (0.8.
|
63
|
+
faraday (0.8.6)
|
53
64
|
multipart-post (~> 1.1)
|
54
65
|
google-spreadsheet-ruby (0.1.8)
|
55
66
|
nokogiri (>= 1.4.3.1)
|
56
67
|
oauth (>= 0.3.6)
|
57
68
|
oauth2 (>= 0.5.0)
|
58
69
|
hashie (1.2.0)
|
59
|
-
health-data-standards (
|
70
|
+
health-data-standards (3.0.1)
|
60
71
|
activesupport (~> 3.2.9)
|
61
72
|
builder (~> 3.0.0)
|
62
73
|
erubis (~> 2.7.0)
|
63
|
-
|
74
|
+
google-spreadsheet-ruby (= 0.1.8)
|
75
|
+
log4r (~> 1.1.10)
|
76
|
+
mongoid (~> 3.1.0)
|
64
77
|
nokogiri (~> 1.5.5)
|
65
78
|
rest-client (~> 1.6.7)
|
66
|
-
uuid (~> 2.3.5)
|
67
|
-
hike (1.2.1)
|
68
|
-
hqmf-parser (1.1.0)
|
69
|
-
google-spreadsheet-ruby (= 0.1.8)
|
70
79
|
roo (= 1.10.1)
|
71
80
|
rubyzip
|
72
81
|
spreadsheet (= 0.6.8)
|
73
|
-
|
82
|
+
uuid (~> 2.3.5)
|
83
|
+
hike (1.2.1)
|
84
|
+
hquery-patient-api (1.0.1)
|
74
85
|
httpauth (0.2.0)
|
75
86
|
i18n (0.6.1)
|
76
87
|
journey (1.0.4)
|
@@ -86,23 +97,25 @@ GEM
|
|
86
97
|
mime-types (~> 1.16)
|
87
98
|
treetop (~> 1.4.8)
|
88
99
|
method_source (0.8.1)
|
89
|
-
mime-types (1.
|
100
|
+
mime-types (1.20.1)
|
90
101
|
minitest (4.3.2)
|
91
|
-
mongoid (3.
|
92
|
-
activemodel (~> 3.
|
93
|
-
moped (~> 1.
|
102
|
+
mongoid (3.1.2)
|
103
|
+
activemodel (~> 3.2)
|
104
|
+
moped (~> 1.4.2)
|
94
105
|
origin (~> 1.0)
|
95
106
|
tzinfo (~> 0.3.22)
|
96
|
-
moped (1.
|
97
|
-
multi_json (1.
|
98
|
-
|
99
|
-
|
107
|
+
moped (1.4.2)
|
108
|
+
multi_json (1.5.0)
|
109
|
+
multi_xml (0.5.3)
|
110
|
+
multipart-post (1.2.0)
|
111
|
+
nokogiri (1.5.6)
|
100
112
|
oauth (0.4.7)
|
101
|
-
oauth2 (0.
|
113
|
+
oauth2 (0.9.1)
|
102
114
|
faraday (~> 0.8)
|
103
115
|
httpauth (~> 0.1)
|
104
116
|
jwt (~> 0.1.4)
|
105
117
|
multi_json (~> 1.0)
|
118
|
+
multi_xml (~> 0.5)
|
106
119
|
rack (~> 1.2)
|
107
120
|
origin (1.0.11)
|
108
121
|
polyglot (0.3.3)
|
@@ -110,7 +123,7 @@ GEM
|
|
110
123
|
coderay (~> 1.0.5)
|
111
124
|
method_source (~> 0.8)
|
112
125
|
slop (~> 3.3.1)
|
113
|
-
rack (1.4.
|
126
|
+
rack (1.4.4)
|
114
127
|
rack-cache (1.2)
|
115
128
|
rack (>= 0.4)
|
116
129
|
rack-ssl (1.3.2)
|
@@ -175,7 +188,7 @@ GEM
|
|
175
188
|
uglifier (1.3.0)
|
176
189
|
execjs (>= 0.3.0)
|
177
190
|
multi_json (~> 1.0, >= 1.0.2)
|
178
|
-
uuid (2.3.
|
191
|
+
uuid (2.3.7)
|
179
192
|
macaddr (~> 1.0)
|
180
193
|
yamler (0.1.0)
|
181
194
|
|
@@ -187,9 +200,7 @@ DEPENDENCIES
|
|
187
200
|
coffee-rails
|
188
201
|
coffee-script
|
189
202
|
cover_me (~> 1.2.0)
|
190
|
-
|
191
|
-
hqmf-parser (~> 1.1.0)
|
192
|
-
hquery-patient-api (~> 1.0.0)
|
203
|
+
hqmf2js!
|
193
204
|
minitest
|
194
205
|
nokogiri
|
195
206
|
pry
|
@@ -1,16 +1,74 @@
|
|
1
1
|
@hqmf.CustomCalc = {}
|
2
2
|
|
3
|
+
@hqmf.CustomCalc.ADE_TTR_OBSERV = (patient, hqmfjs) ->
|
4
|
+
inrReadings = DURING(hqmfjs.LaboratoryTestResultInr(patient), hqmfjs.MeasurePeriod(patient));
|
5
|
+
inrReadings = new hqmf.CustomCalc.PercentTTREntries(inrReadings)
|
6
|
+
[inrReadings.calculatePercentTTR()]
|
7
|
+
|
3
8
|
class @hqmf.CustomCalc.PercentTTREntries extends hQuery.CodedEntryList
|
4
9
|
|
5
10
|
constructor: (events) ->
|
6
11
|
super()
|
7
|
-
events = events.sort(dateSortAscending)
|
8
|
-
@push(event) for event in events
|
9
12
|
@minInr = 2.0
|
10
13
|
@maxInr = 3.0
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
@minOutOfRange = 0.8
|
15
|
+
@maxOutOfRange = 10
|
16
|
+
@closestSetpoint = 2.5
|
17
|
+
|
18
|
+
clonedEvents = []
|
19
|
+
clonedEvents.push(new event.constructor(event.json)) for event in events
|
20
|
+
|
21
|
+
# remove entries < 0.8
|
22
|
+
# reset > 10 to be 10
|
23
|
+
# remove duplicate results on entries to those closest to 2.5
|
24
|
+
for entry in clonedEvents
|
25
|
+
currentClosestValue = null
|
26
|
+
for value in entry.values()
|
27
|
+
if value.scalar() > @maxOutOfRange
|
28
|
+
value.json['scalar'] = '10.0'
|
29
|
+
if value.scalar() >= @minOutOfRange && value.scalar() <= @maxOutOfRange
|
30
|
+
currentClosestValue = @closestValueToSetpoint(currentClosestValue, value)
|
31
|
+
|
32
|
+
passingValues = []
|
33
|
+
passingValues = [currentClosestValue.json] if currentClosestValue?
|
34
|
+
entry.json['values'] = passingValues
|
35
|
+
|
36
|
+
# filter duplicates to those closest to 2.5 on the same day
|
37
|
+
# remove any entries with no values (removed because the value was below 0.8, or no value on source data)
|
38
|
+
entriesByDay = {}
|
39
|
+
for entry in clonedEvents
|
40
|
+
date = entry.timeStamp()
|
41
|
+
key = "#{date.getUTCFullYear()}_#{date.getUTCMonth()}_#{date.getUTCDate()}"
|
42
|
+
entriesByDay[key] = [] unless entriesByDay[key]
|
43
|
+
entriesByDay[key].push(entry) if entry.values().length > 0
|
44
|
+
|
45
|
+
# keep the closest entry to 2.5 when there are multiple entries per day
|
46
|
+
finalEvents = []
|
47
|
+
for key in _.keys(entriesByDay)
|
48
|
+
if (entriesByDay[key].length > 1)
|
49
|
+
currentClosestValue = null
|
50
|
+
selectedEntry = null
|
51
|
+
for entry in entriesByDay[key]
|
52
|
+
currentClosestValue = @closestValueToSetpoint(currentClosestValue, entry.values()[0])
|
53
|
+
if currentClosestValue.scalar() == entry.values()[0].scalar()
|
54
|
+
selectedEntry = entry
|
55
|
+
finalEvents.push(selectedEntry)
|
56
|
+
else
|
57
|
+
finalEvents = finalEvents.concat(entriesByDay[key])
|
58
|
+
|
59
|
+
finalEvents = finalEvents.sort(dateSortAscending)
|
60
|
+
|
61
|
+
@push(event) for event in finalEvents
|
62
|
+
|
63
|
+
|
64
|
+
closestValueToSetpoint: (one, two) ->
|
65
|
+
return two if one == null
|
66
|
+
return one if two == null
|
67
|
+
if (Math.abs(one.scalar() - @closestSetpoint) > Math.abs(two.scalar() - @closestSetpoint))
|
68
|
+
return two
|
69
|
+
else
|
70
|
+
return one
|
71
|
+
|
14
72
|
|
15
73
|
calculateDaysInRange: (firstInr, secondInr) ->
|
16
74
|
|
@@ -408,26 +408,26 @@ class ANYNonNull
|
|
408
408
|
@ANYNonNull = ANYNonNull
|
409
409
|
|
410
410
|
# Returns true if one or more of the supplied values is true
|
411
|
-
atLeastOneTrue = (values...) ->
|
411
|
+
atLeastOneTrue = (precondition, values...) ->
|
412
412
|
trueValues = (value for value in values when value && value.isTrue())
|
413
413
|
trueValues.length>0
|
414
414
|
hqmf.SpecificsManager.unionAll(new Boolean(trueValues.length>0), values)
|
415
415
|
@atLeastOneTrue = atLeastOneTrue
|
416
416
|
|
417
417
|
# Returns true if all of the supplied values are true
|
418
|
-
allTrue = (values...) ->
|
418
|
+
allTrue = (precondition, values...) ->
|
419
419
|
trueValues = (value for value in values when value && value.isTrue())
|
420
420
|
hqmf.SpecificsManager.intersectAll(new Boolean(trueValues.length>0 && trueValues.length==values.length), values)
|
421
421
|
@allTrue = allTrue
|
422
422
|
|
423
423
|
# Returns true if one or more of the supplied values is false
|
424
|
-
atLeastOneFalse = (values...) ->
|
424
|
+
atLeastOneFalse = (precondition, values...) ->
|
425
425
|
falseValues = (value for value in values when value.isFalse())
|
426
426
|
hqmf.SpecificsManager.intersectAll(new Boolean(falseValues.length>0), values, true)
|
427
427
|
@atLeastOneFalse = atLeastOneFalse
|
428
428
|
|
429
429
|
# Returns true if all of the supplied values are false
|
430
|
-
allFalse = (values...) ->
|
430
|
+
allFalse = (precondition, values...) ->
|
431
431
|
falseValues = (value for value in values when value.isFalse())
|
432
432
|
hqmf.SpecificsManager.unionAll(new Boolean(falseValues.length>0 && falseValues.length==values.length), values, true)
|
433
433
|
@allFalse = allFalse
|
@@ -514,6 +514,8 @@ class CrossProduct extends Array
|
|
514
514
|
@eventLists.push eventList
|
515
515
|
for event in eventList
|
516
516
|
this.push(event)
|
517
|
+
listCount: -> @eventLists.length
|
518
|
+
childList: (index) -> @eventLists[index]
|
517
519
|
|
518
520
|
# Create a CrossProduct of the supplied event lists.
|
519
521
|
XPRODUCT = (eventLists...) ->
|
@@ -545,7 +547,7 @@ getIVL = (eventOrTimeStamp) ->
|
|
545
547
|
ts.date = eventOrTimeStamp
|
546
548
|
new IVL_TS(ts, ts)
|
547
549
|
@getIVL = getIVL
|
548
|
-
|
550
|
+
|
549
551
|
eventAccessor = {
|
550
552
|
'DURING': 'low',
|
551
553
|
'OVERLAP': 'low',
|
@@ -820,6 +822,37 @@ DATEDIFF = (events, range) ->
|
|
820
822
|
hqmf.SpecificsManager.maintainSpecifics(new Boolean(withinRange('DATEDIFF', getIVL(events[0]), getIVL(events[1]), range)), events)
|
821
823
|
@DATEDIFF = DATEDIFF
|
822
824
|
|
825
|
+
# Calculate the set of time differences in minutes between pairs of events
|
826
|
+
# events - a XPRODUCT of two event lists
|
827
|
+
# range - ignored
|
828
|
+
# initialSpecificContext - the specific context containing one row per permissible
|
829
|
+
# combination of events
|
830
|
+
TIMEDIFF = (events, range, initialSpecificContext) ->
|
831
|
+
if events.listCount() != 2
|
832
|
+
throw "TIMEDIFF can only process 2 lists of events"
|
833
|
+
eventList1 = events.childList(0)
|
834
|
+
eventList2 = events.childList(1)
|
835
|
+
eventIndex1 = hqmf.SpecificsManager.getColumnIndex(eventList1.specific_occurrence)
|
836
|
+
eventIndex2 = hqmf.SpecificsManager.getColumnIndex(eventList2.specific_occurrence)
|
837
|
+
eventMap1 = {}
|
838
|
+
eventMap2 = {}
|
839
|
+
for event in eventList1
|
840
|
+
eventMap1[event.id] = event
|
841
|
+
for event in eventList2
|
842
|
+
eventMap2[event.id] = event
|
843
|
+
results = []
|
844
|
+
for row in initialSpecificContext.rows
|
845
|
+
event1 = row.values[eventIndex1]
|
846
|
+
event2 = row.values[eventIndex2]
|
847
|
+
if event1 and event2 and event1 != hqmf.SpecificsManager.any and event2 != hqmf.SpecificsManager.any
|
848
|
+
# The maps contain the actual events we want to work with since these may contain
|
849
|
+
# time shifted clones of the events in the specificContext, e.g. via adjustBoundsForField
|
850
|
+
shiftedEvent1 = eventMap1[event1.id]
|
851
|
+
shiftedEvent2 = eventMap2[event2.id]
|
852
|
+
if shiftedEvent1 and shiftedEvent2
|
853
|
+
results.push(shiftedEvent1.asTS().difference(shiftedEvent2.asTS(), 'min'))
|
854
|
+
results
|
855
|
+
@TIMEDIFF = TIMEDIFF
|
823
856
|
|
824
857
|
@OidDictionary = {};
|
825
858
|
|
@@ -1,7 +1,11 @@
|
|
1
1
|
class @Logger
|
2
2
|
@logger: []
|
3
|
+
@rationale: {}
|
3
4
|
@info: (string) ->
|
4
5
|
@logger.push("#{Logger.indent()}#{string}")
|
6
|
+
@record: (id, result) ->
|
7
|
+
if result? and typeof(result.isTrue) == 'function'
|
8
|
+
@rationale[id] = result.isTrue()
|
5
9
|
@enabled: true
|
6
10
|
@initialized: false
|
7
11
|
@indentCount = 0
|
@@ -40,12 +44,17 @@ class @Logger
|
|
40
44
|
|
41
45
|
@enableMeasureLogging = (hqmfjs) ->
|
42
46
|
_.each(_.functions(hqmfjs), (method) ->
|
43
|
-
hqmfjs[method] = _.wrap(hqmfjs[method], (func
|
47
|
+
hqmfjs[method] = _.wrap(hqmfjs[method], (func) ->
|
48
|
+
|
49
|
+
args = Array.prototype.slice.call(arguments,1)
|
50
|
+
|
44
51
|
Logger.info("#{method}:")
|
45
52
|
Logger.indentCount++
|
46
|
-
result = func(
|
53
|
+
result = func.apply(this, args)
|
54
|
+
|
47
55
|
Logger.indentCount--
|
48
56
|
Logger.info("#{method} -> #{Logger.asBoolean(result)}")
|
57
|
+
Logger.record(method,result)
|
49
58
|
return result;
|
50
59
|
);
|
51
60
|
);
|
@@ -73,12 +82,6 @@ class @Logger
|
|
73
82
|
);
|
74
83
|
|
75
84
|
hQuery.CodedEntryList.prototype.match = _.wrap(hQuery.CodedEntryList.prototype.match, (func, codeSet, start, end) ->
|
76
|
-
|
77
|
-
# if (codeSet)
|
78
|
-
# Logger.info("matching: codeSets(#{_.keys(codeSet).join(",")}), #{start}, #{end}")
|
79
|
-
# else
|
80
|
-
# Logger.info("matching: WARNING: CODE SETS ARE NULL, #{start}, #{end}")
|
81
|
-
|
82
85
|
func = _.bind(func, this, codeSet,start,end)
|
83
86
|
result = func(codeSet,start,end)
|
84
87
|
Logger.info("matched -> #{Logger.stringify(result)}")
|
@@ -98,6 +101,7 @@ class @Logger
|
|
98
101
|
result = func.apply(this, args)
|
99
102
|
Logger.indentCount--
|
100
103
|
Logger.info("atLeastOneTrue -> #{result}")
|
104
|
+
Logger.record("precondition_#{args[0]}",result)
|
101
105
|
result
|
102
106
|
)
|
103
107
|
|
@@ -108,6 +112,7 @@ class @Logger
|
|
108
112
|
result = func.apply(this, args)
|
109
113
|
Logger.indentCount--
|
110
114
|
Logger.info("allTrue -> #{result}")
|
115
|
+
Logger.record("precondition_#{args[0]}",result)
|
111
116
|
result
|
112
117
|
)
|
113
118
|
|
@@ -118,6 +123,7 @@ class @Logger
|
|
118
123
|
result = func.apply(this, args)
|
119
124
|
Logger.indentCount--
|
120
125
|
Logger.info("allFalse -> #{result}")
|
126
|
+
Logger.record("precondition_#{args[0]}",result)
|
121
127
|
result
|
122
128
|
)
|
123
129
|
|
@@ -128,6 +134,7 @@ class @Logger
|
|
128
134
|
result = func.apply(this, args)
|
129
135
|
Logger.indentCount--
|
130
136
|
Logger.info("atLeastOneFalse -> #{result}")
|
137
|
+
Logger.record("precondition_#{args[0]}",result)
|
131
138
|
result
|
132
139
|
)
|
133
140
|
|
@@ -13,6 +13,10 @@ hQuery.CodedEntry::asIVL_TS = ->
|
|
13
13
|
tsHigh = new TS()
|
14
14
|
tsHigh.date = this.endDate() || this.date() || null
|
15
15
|
new IVL_TS(tsLow, tsHigh)
|
16
|
+
hQuery.CodedEntry::asTS = ->
|
17
|
+
ts = new TS()
|
18
|
+
ts.date = this.timeStamp()
|
19
|
+
ts
|
16
20
|
|
17
21
|
hQuery.CodedEntry::respondTo = (functionName) ->
|
18
22
|
typeof(@[functionName]) == "function"
|
data/hqmf2js.gemspec
CHANGED
@@ -7,13 +7,15 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.email = "hquery-talk@googlegroups.com"
|
8
8
|
s.homepage = "http://github.com/hquery/hqmf2js"
|
9
9
|
s.authors = ["Marc Hadley", "Andre Quina", "Andy Gregorowicz"]
|
10
|
-
s.version = '1.
|
10
|
+
s.version = '1.2.0'
|
11
11
|
|
12
12
|
s.add_dependency 'nokogiri', '~> 1.5.5'
|
13
13
|
s.add_dependency 'tilt', '~> 1.3.3'
|
14
14
|
s.add_dependency 'coffee-script', '~> 2.2.0'
|
15
15
|
s.add_dependency 'sprockets', '~> 2.2.2'
|
16
16
|
s.add_development_dependency "awesome_print", "~> 1.1.0"
|
17
|
+
s.add_dependency 'health-data-standards', '~> 3.0.1'
|
18
|
+
s.add_dependency 'hquery-patient-api', '~> 1.0.1'
|
17
19
|
|
18
20
|
s.files = s.files = `git ls-files`.split("\n")
|
19
21
|
end
|
@@ -16,9 +16,9 @@ module HQMF2JS
|
|
16
16
|
translation = {}
|
17
17
|
value_sets.each do |value_set|
|
18
18
|
code_sets = {}
|
19
|
-
value_set["
|
20
|
-
code_sets[code_set["
|
21
|
-
code_sets[code_set["
|
19
|
+
value_set["concepts"].each do |code_set|
|
20
|
+
code_sets[code_set["code_system_name"]] ||= []
|
21
|
+
code_sets[code_set["code_system_name"]].concat(code_set["code"].to_a)
|
22
22
|
end
|
23
23
|
|
24
24
|
translation[value_set["oid"]] = code_sets
|
@@ -35,6 +35,7 @@ module HQMF2JS
|
|
35
35
|
# <ValueSet id="2.16.840.1.113883.3.464.1.14" displayName="birth date">
|
36
36
|
# <ConceptList xml:lang="en-US">
|
37
37
|
# <Concept code="00110" codeSystemName="HL7" displayName="Date/Time of birth (TS)"
|
38
|
+
|
38
39
|
# codeSystemVersion="3"/>
|
39
40
|
# </ConceptList>
|
40
41
|
# </ValueSet>
|
@@ -78,4 +79,4 @@ module HQMF2JS
|
|
78
79
|
|
79
80
|
end
|
80
81
|
end
|
81
|
-
end
|
82
|
+
end
|
@@ -6,7 +6,7 @@ var <%= js_name(criteria) %> = <%= js_for_value(criteria.value) %>;
|
|
6
6
|
|
7
7
|
// Data critera
|
8
8
|
<%- all_criteria.select {|c| c.type != :variable}.each do |criteria| -%>
|
9
|
-
hqmfjs.<%= js_name(criteria) %> = function(patient) {
|
9
|
+
hqmfjs.<%= js_name(criteria) %> = function(patient, initialSpecificContext) {
|
10
10
|
<%- if criteria.type == :characteristic and !criteria.property.nil? -%>
|
11
11
|
<%= js_for_characteristic(criteria) %>
|
12
12
|
<%- else -%>
|
@@ -37,7 +37,7 @@ hqmfjs.<%= js_name(criteria) %> = function(patient) {
|
|
37
37
|
<%- end -%>
|
38
38
|
<%- if criteria.subset_operators -%>
|
39
39
|
<%- criteria.subset_operators.select {|subset_operator| subset_operator.type}.each do |subset_operator| -%>
|
40
|
-
events = <%= subset_operator.type %>(events<%= ", #{js_for_bounds(subset_operator.value)}" if subset_operator.value
|
40
|
+
events = <%= subset_operator.type %>(events<%= ", #{js_for_bounds(subset_operator.value)}" if subset_operator.value %>, initialSpecificContext);
|
41
41
|
<%- end # each operator -%>
|
42
42
|
<%- end # subset operators -%>
|
43
43
|
return events;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
var events = <%= criteria.derivation_operator %>(
|
2
2
|
<%- criteria.children_criteria.each_with_index do |child, index| -%>
|
3
|
-
<%= "hqmfjs.#{child}(patient)" %><%= "," if index<criteria.children_criteria.length-1 %>
|
3
|
+
<%= "hqmfjs.#{child}(patient, initialSpecificContext)" %><%= "," if index<criteria.children_criteria.length-1 %>
|
4
4
|
<%- end -%>
|
5
5
|
);
|
data/lib/generator/js.rb
CHANGED
@@ -138,8 +138,8 @@ module HQMF2JS
|
|
138
138
|
end
|
139
139
|
|
140
140
|
# Returns the JavaScript generated for a HQMF::Precondition
|
141
|
-
def js_for_precondition(precondition, indent)
|
142
|
-
HQMF2JS::Generator.render_template('precondition', {'doc' => doc, 'precondition' => precondition, 'indent' => indent})
|
141
|
+
def js_for_precondition(precondition, indent, context=false)
|
142
|
+
HQMF2JS::Generator.render_template('precondition', {'doc' => doc, 'precondition' => precondition, 'indent' => indent, 'context' => context})
|
143
143
|
end
|
144
144
|
|
145
145
|
def patient_api_method(criteria)
|
@@ -202,6 +202,7 @@ module HQMF2JS
|
|
202
202
|
#{js_for(population[HQMF::PopulationCriteria::DENEXCEP], HQMF::PopulationCriteria::DENEXCEP)}
|
203
203
|
// CV
|
204
204
|
#{js_for(population[HQMF::PopulationCriteria::MSRPOPL], HQMF::PopulationCriteria::MSRPOPL)}
|
205
|
+
#{js_for(population[HQMF::PopulationCriteria::OBSERV], HQMF::PopulationCriteria::OBSERV)}
|
205
206
|
"
|
206
207
|
end
|
207
208
|
|
@@ -224,7 +225,11 @@ module HQMF2JS
|
|
224
225
|
type ||= criteria_code
|
225
226
|
criteria = @doc.population_criteria(criteria_code)
|
226
227
|
if criteria && criteria.preconditions && criteria.preconditions.length > 0
|
227
|
-
|
228
|
+
if type==HQMF::PopulationCriteria::OBSERV
|
229
|
+
HQMF2JS::Generator.render_template('observation_criteria', {'doc' => @doc, 'criteria' => criteria, 'type'=>type})
|
230
|
+
else
|
231
|
+
HQMF2JS::Generator.render_template('population_criteria', {'doc' => @doc, 'criteria' => criteria, 'type'=>type})
|
232
|
+
end
|
228
233
|
else
|
229
234
|
"hqmfjs.#{type} = function(patient) { return new Boolean(#{when_not_found}); }"
|
230
235
|
end
|
@@ -13,6 +13,7 @@ hqmfjs.MeasurePeriod = function(patient) {
|
|
13
13
|
}
|
14
14
|
if (typeof effective_date === 'number') {
|
15
15
|
MeasurePeriod.high.date = new Date(1000*effective_date);
|
16
|
-
|
16
|
+
// add one minute before pulling off the year. This turns 12-31-2012 23:59 into 1-1-2013 00:00 => 1-1-2012 00:00
|
17
|
+
MeasurePeriod.low.date = new Date(1000*(effective_date+60));
|
17
18
|
MeasurePeriod.low.date.setFullYear(MeasurePeriod.low.date.getFullYear()-1);
|
18
19
|
}
|
@@ -1,14 +1,16 @@
|
|
1
1
|
<%- if precondition.conjunction? -%>
|
2
2
|
<%- if indent>0 -%>
|
3
|
-
<%= "\n#{' '*(indent+1)}#{conjunction_code_for(precondition)}(" -%>
|
3
|
+
<%= "\n#{' '*(indent+1)}#{conjunction_code_for(precondition)}('#{precondition.id}'," -%>
|
4
4
|
<%- else -%>
|
5
|
-
<%= "#{conjunction_code_for(precondition)}(" -%>
|
5
|
+
<%= "#{conjunction_code_for(precondition)}('#{precondition.id}'," -%>
|
6
6
|
<%- end -%>
|
7
7
|
<%- precondition.preconditions.each_with_index do |child, index| -%>
|
8
|
-
<%= "#{' '*(indent+1)}#{js_for_precondition(child, indent+1)}" -%>
|
8
|
+
<%= "#{' '*(indent+1)}#{js_for_precondition(child, indent+1, context)}" -%>
|
9
9
|
<%= "," if index < precondition.preconditions.length-1 -%>
|
10
10
|
<%- end -%>
|
11
11
|
<%= "\n#{' '*(indent+1)})" -%>
|
12
|
+
<%- elsif context -%>
|
13
|
+
<%= " hqmfjs.#{js_name(precondition.reference)}(patient, initialSpecificContext)" -%>
|
12
14
|
<%- else -%>
|
13
15
|
<%= "\n#{' '*(indent+1)}hqmfjs.#{js_name(precondition.reference)}(patient)" -%>
|
14
16
|
<%- end -%>
|
data/lib/tasks/convert.rake
CHANGED
@@ -29,15 +29,19 @@ namespace :hqmf do
|
|
29
29
|
f.write("// #########################\n\n")
|
30
30
|
|
31
31
|
f.write("// INITIAL PATIENT POPULATION\n")
|
32
|
-
f.write(gen.js_for(
|
33
|
-
f.write("// DENOMINATOR\n")
|
34
|
-
f.write(gen.js_for(
|
35
|
-
f.write("// NUMERATOR\n")
|
36
|
-
f.write(gen.js_for(
|
37
|
-
f.write("// EXCLUSIONS\n")
|
38
|
-
f.write(gen.js_for(
|
39
|
-
f.write("// DENOMINATOR EXCEPTIONS\n")
|
40
|
-
f.write(gen.js_for(
|
32
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::IPP))
|
33
|
+
f.write("\n// DENOMINATOR\n")
|
34
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::DENOM))
|
35
|
+
f.write("\n// NUMERATOR\n")
|
36
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::NUMER))
|
37
|
+
f.write("\n// EXCLUSIONS\n")
|
38
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::DENEX))
|
39
|
+
f.write("\n// DENOMINATOR EXCEPTIONS\n")
|
40
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::DENEXCEP))
|
41
|
+
f.write("\n// MSRPOPL\n")
|
42
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::MSRPOPL))
|
43
|
+
f.write("\n// OBSERV\n")
|
44
|
+
f.write(gen.js_for(HQMF::PopulationCriteria::OBSERV))
|
41
45
|
end
|
42
46
|
|
43
47
|
puts "wrote javascript to: #{out_file}"
|
@@ -893,7 +893,7 @@
|
|
893
893
|
{
|
894
894
|
"type": "SUMMARY",
|
895
895
|
"value": {
|
896
|
-
"type": "
|
896
|
+
"type": "IVL_PQ",
|
897
897
|
"low": {
|
898
898
|
"type": "PQ",
|
899
899
|
"value": "2",
|
@@ -1118,7 +1118,7 @@
|
|
1118
1118
|
{
|
1119
1119
|
"type": "COUNT",
|
1120
1120
|
"value": {
|
1121
|
-
"type": "
|
1121
|
+
"type": "IVL_PQ",
|
1122
1122
|
"low": {
|
1123
1123
|
"type": "PQ",
|
1124
1124
|
"value": "3",
|
@@ -1145,7 +1145,7 @@
|
|
1145
1145
|
{
|
1146
1146
|
"type": "COUNT",
|
1147
1147
|
"value": {
|
1148
|
-
"type": "
|
1148
|
+
"type": "IVL_PQ",
|
1149
1149
|
"low": {
|
1150
1150
|
"type": "PQ",
|
1151
1151
|
"value": "5",
|
@@ -34,6 +34,42 @@ class CustomCalculationsTest < Test::Unit::TestCase
|
|
34
34
|
inr_b9 = new hQuery.CodedEntry({time:#{Time.gm(2010,10,31).to_i}, values:[{scalar:'1.8'}]})
|
35
35
|
|
36
36
|
list2 = new hqmf.CustomCalc.PercentTTREntries([inr_b1,inr_b2,inr_b3,inr_b4,inr_b5,inr_b6,inr_b7,inr_b8,inr_b9])
|
37
|
+
|
38
|
+
inr_c1 = new hQuery.CodedEntry({time:#{Time.gm(2010,1,5).to_i}, values:[{scalar:'2.8'}]})
|
39
|
+
inr_c2 = new hQuery.CodedEntry({time:#{Time.gm(2010,1,18).to_i}, values:[{scalar:'3.5'}]})
|
40
|
+
inr_c3 = new hQuery.CodedEntry({time:#{Time.gm(2010,2,2).to_i}, values:[{scalar:'3.4'}]})
|
41
|
+
inr_c4 = new hQuery.CodedEntry({time:#{Time.gm(2010,2,15).to_i}, values:[{scalar:'3.9'}]})
|
42
|
+
inr_c5 = new hQuery.CodedEntry({time:#{Time.gm(2010,3,10).to_i}, values:[{scalar:'1.7'}]})
|
43
|
+
inr_c6 = new hQuery.CodedEntry({time:#{Time.gm(2010,3,24).to_i}, values:[{scalar:'2.3'}]})
|
44
|
+
inr_c7 = new hQuery.CodedEntry({time:#{Time.gm(2010,4,12).to_i}, values:[{scalar:'2.4'}]})
|
45
|
+
inr_c8 = new hQuery.CodedEntry({time:#{Time.gm(2010,5,13).to_i}, values:[{scalar:'3.2'}]})
|
46
|
+
inr_c9 = new hQuery.CodedEntry({time:#{Time.gm(2010,5,27).to_i}, values:[{scalar:'3.5'}]})
|
47
|
+
inr_c10 = new hQuery.CodedEntry({time:#{Time.gm(2010,6,10).to_i}, values:[{scalar:'3.5'}]})
|
48
|
+
inr_c11 = new hQuery.CodedEntry({time:#{Time.gm(2010,6,24).to_i}, values:[{scalar:'3.4'}]})
|
49
|
+
inr_c12 = new hQuery.CodedEntry({time:#{Time.gm(2010,7,8).to_i}, values:[{scalar:'2.1'}]})
|
50
|
+
inr_c13 = new hQuery.CodedEntry({time:#{Time.gm(2010,7,22).to_i}, values:[{scalar:'2.6'}]})
|
51
|
+
|
52
|
+
list3 = new hqmf.CustomCalc.PercentTTREntries([inr_c10,inr_c2,inr_c6,inr_c9,inr_c5,inr_c3,inr_c7,inr_c8,inr_c4,inr_c1,inr_c11,inr_c12,inr_c13])
|
53
|
+
|
54
|
+
inr_c1 = new hQuery.CodedEntry({time:#{Time.gm(2010,1,5).to_i}, values:[{scalar:'2.8'}]})
|
55
|
+
inr_c2 = new hQuery.CodedEntry({time:#{Time.gm(2010,1,18).to_i}, values:[{scalar:'3.5'}]})
|
56
|
+
inr_c3 = new hQuery.CodedEntry({time:#{Time.gm(2010,2,2).to_i}, values:[{scalar:'3.4'}]})
|
57
|
+
inr_c4 = new hQuery.CodedEntry({time:#{Time.gm(2010,2,2).to_i}, values:[{scalar:'2.1'}]})
|
58
|
+
inr_c5 = new hQuery.CodedEntry({time:#{Time.gm(2010,2,15).to_i}, values:[{scalar:'3.9'}]})
|
59
|
+
inr_c6 = new hQuery.CodedEntry({time:#{Time.gm(2010,3,10).to_i}, values:[{scalar:'1.7'}]})
|
60
|
+
inr_c7 = new hQuery.CodedEntry({time:#{Time.gm(2010,3,11).to_i}, values:[{scalar:'0.7'}]})
|
61
|
+
inr_c8 = new hQuery.CodedEntry({time:#{Time.gm(2010,3,24).to_i}, values:[{scalar:'2.9'},{scalar:'2.3'}]})
|
62
|
+
inr_c9 = new hQuery.CodedEntry({time:#{Time.gm(2010,4,12).to_i}, values:[{scalar:'2.4'}]})
|
63
|
+
inr_c10 = new hQuery.CodedEntry({time:#{Time.gm(2010,5,13).to_i}, values:[{scalar:'3.2'}]})
|
64
|
+
inr_c11 = new hQuery.CodedEntry({time:#{Time.gm(2010,5,13).to_i}, values:[{scalar:'3.6'}]})
|
65
|
+
inr_c12 = new hQuery.CodedEntry({time:#{Time.gm(2010,5,27).to_i}, values:[{scalar:'13.5'}]})
|
66
|
+
inr_c13 = new hQuery.CodedEntry({time:#{Time.gm(2010,6,10).to_i}, values:[{scalar:'3.5'}]})
|
67
|
+
inr_c14 = new hQuery.CodedEntry({time:#{Time.gm(2010,6,24).to_i}, values:[{scalar:'3.4'}]})
|
68
|
+
inr_c15 = new hQuery.CodedEntry({time:#{Time.gm(2010,7,8).to_i}, values:[{scalar:'12.1'}]})
|
69
|
+
inr_c16 = new hQuery.CodedEntry({time:#{Time.gm(2010,7,22).to_i}, values:[{scalar:'2.6'}, {scalar:'2.1'}]})
|
70
|
+
|
71
|
+
list4 = new hqmf.CustomCalc.PercentTTREntries([inr_c9,inr_c8,inr_c3,inr_c14,inr_c10,inr_c6,inr_c7,inr_c2,inr_c1,inr_c5,inr_c11,inr_c12,inr_c13,inr_c4,inr_c15,inr_c16])
|
72
|
+
|
37
73
|
"
|
38
74
|
@context.eval(test_initialize_js)
|
39
75
|
|
@@ -69,6 +105,36 @@ class CustomCalculationsTest < Test::Unit::TestCase
|
|
69
105
|
def test_calculate_percent_ttr
|
70
106
|
assert @context.eval("Math.abs(list.calculatePercentTTR() - 43.99552468) < .001")
|
71
107
|
end
|
108
|
+
|
109
|
+
def test_calculate_ttr_testdeck_record
|
110
|
+
assert @context.eval("Math.abs(list2.calculateTTR() - 203.66666666) < .001")
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_calculate_percent_ttr_testdeck_record
|
114
|
+
assert @context.eval("Math.abs(list2.calculatePercentTTR() - 95.6181533646322) < .001")
|
115
|
+
end
|
72
116
|
|
117
|
+
def test_calculate_ttr_out_of_order
|
118
|
+
assert @context.eval("Math.abs(list3.calculateTTR() - 87.11113886) < .001")
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_calculate_percent_ttr_out_of_order
|
122
|
+
assert @context.eval("Math.abs(list3.calculatePercentTTR() - 43.99552468) < .001")
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_cleanup_of_inr_values
|
126
|
+
|
127
|
+
cleaned_inrs = [2.8, 3.5, 2.1, 3.9, 1.7, 2.3, 2.4, 3.2, 10.0, 3.5, 3.4, 10.0, 2.6]
|
128
|
+
|
129
|
+
assert @context.eval("list4.length == #{cleaned_inrs.size}")
|
130
|
+
cleaned_inrs.each_with_index do |inr,index|
|
131
|
+
assert @context.eval("list4[#{index}].values()[0].scalar() == #{inr}")
|
132
|
+
end
|
133
|
+
|
134
|
+
assert @context.eval("Math.abs(list4.calculateTTR() - 80.3184450684) < .001")
|
135
|
+
assert @context.eval("Math.abs(list4.calculatePercentTTR() - 40.56487124668) < .001")
|
136
|
+
|
137
|
+
end
|
138
|
+
|
73
139
|
|
74
140
|
end
|
@@ -17,31 +17,31 @@ class LibraryFunctionTest < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_all_true
|
20
|
-
@context.eval('allTrue(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal false
|
21
|
-
@context.eval('allTrue(new Boolean(false),new Boolean(true),new Boolean(false)).isTrue()').must_equal false
|
22
|
-
@context.eval('allTrue(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal true
|
23
|
-
@context.eval('allTrue().isTrue()').must_equal false
|
20
|
+
@context.eval('allTrue(1,new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal false
|
21
|
+
@context.eval('allTrue(1,new Boolean(false),new Boolean(true),new Boolean(false)).isTrue()').must_equal false
|
22
|
+
@context.eval('allTrue(1,new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal true
|
23
|
+
@context.eval('allTrue(1).isTrue()').must_equal false
|
24
24
|
end
|
25
25
|
|
26
26
|
def test_at_least_one_true
|
27
|
-
@context.eval('atLeastOneTrue(new Boolean(true),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
28
|
-
@context.eval('atLeastOneTrue(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal true
|
29
|
-
@context.eval('atLeastOneTrue(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal false
|
30
|
-
@context.eval('atLeastOneTrue().isTrue()').must_equal false
|
27
|
+
@context.eval('atLeastOneTrue(1,new Boolean(true),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
28
|
+
@context.eval('atLeastOneTrue(1,new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal true
|
29
|
+
@context.eval('atLeastOneTrue(1,new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal false
|
30
|
+
@context.eval('atLeastOneTrue(1).isTrue()').must_equal false
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_all_false
|
34
|
-
@context.eval('allFalse(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
35
|
-
@context.eval('allFalse(new Boolean(false),new Boolean(true),new Boolean(false)).isTrue()').must_equal false
|
36
|
-
@context.eval('allFalse(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal false
|
37
|
-
@context.eval('allFalse().isTrue()').must_equal false
|
34
|
+
@context.eval('allFalse(1,new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
35
|
+
@context.eval('allFalse(1,new Boolean(false),new Boolean(true),new Boolean(false)).isTrue()').must_equal false
|
36
|
+
@context.eval('allFalse(1,new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal false
|
37
|
+
@context.eval('allFalse(1).isTrue()').must_equal false
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_at_least_one_false
|
41
|
-
@context.eval('atLeastOneFalse(new Boolean(true),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
42
|
-
@context.eval('atLeastOneFalse(new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal false
|
43
|
-
@context.eval('atLeastOneFalse(new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
44
|
-
@context.eval('atLeastOneFalse().isTrue()').must_equal false
|
41
|
+
@context.eval('atLeastOneFalse(1,new Boolean(true),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
42
|
+
@context.eval('atLeastOneFalse(1,new Boolean(true),new Boolean(true),new Boolean(true)).isTrue()').must_equal false
|
43
|
+
@context.eval('atLeastOneFalse(1,new Boolean(false),new Boolean(false),new Boolean(false)).isTrue()').must_equal true
|
44
|
+
@context.eval('atLeastOneFalse(1).isTrue()').must_equal false
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_patient_extensions
|
data/test/unit/specifics_test.rb
CHANGED
@@ -202,6 +202,29 @@ class SpecificsTest < Test::Unit::TestCase
|
|
202
202
|
|
203
203
|
end
|
204
204
|
|
205
|
+
def test_specifics_timediff
|
206
|
+
init_rows = "
|
207
|
+
var row1 = new Row('OccurrenceAEncounter',{'OccurrenceAEncounter':{'id':1},'OccurrenceBEncounter':{'id':20}});
|
208
|
+
var row2 = new Row('OccurrenceAEncounter',{'OccurrenceAEncounter':{'id':2},'OccurrenceBEncounter':{'id':20}});
|
209
|
+
var row3 = new Row('OccurrenceAEncounter',{'OccurrenceAEncounter':{'id':3},'OccurrenceBEncounter':{'id':30}});
|
210
|
+
|
211
|
+
var specific = new hqmf.SpecificOccurrence([row1,row2,row3]);
|
212
|
+
|
213
|
+
var ts1 = new TS('20100101100000');
|
214
|
+
var ts2 = new TS('20100101101000');
|
215
|
+
|
216
|
+
var events1 = [{'id': 1, 'asTS': function() {return ts1;}}];
|
217
|
+
events1.specific_occurrence = 'OccurrenceAEncounter';
|
218
|
+
var events2 = [{'id': 20, 'asTS': function() {return ts2;}},{'id': 30, 'asTS': function() {return ts2;}}];
|
219
|
+
events2.specific_occurrence = 'OccurrenceBEncounter';
|
220
|
+
var timediffs = TIMEDIFF(XPRODUCT(events1, events2), null, specific);
|
221
|
+
"
|
222
|
+
|
223
|
+
@context.eval(init_rows)
|
224
|
+
@context.eval("timediffs.length").must_equal 1
|
225
|
+
@context.eval("timediffs[0]").must_equal 10
|
226
|
+
end
|
227
|
+
|
205
228
|
def test_specifics_event_counting
|
206
229
|
|
207
230
|
init_rows = "
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hqmf2js
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2013-02-27 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: nokogiri
|
@@ -93,6 +93,38 @@ dependencies:
|
|
93
93
|
- - ~>
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: 1.1.0
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: health-data-standards
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.0.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 3.0.1
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: hquery-patient-api
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ~>
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 1.0.1
|
120
|
+
type: :runtime
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ~>
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: 1.0.1
|
96
128
|
description: A library for converting HQMF files to executable JavaScript suitable
|
97
129
|
for use with the hQuery Gateway
|
98
130
|
email: hquery-talk@googlegroups.com
|
@@ -124,6 +156,7 @@ files:
|
|
124
156
|
- lib/generator/derived_data.js.erb
|
125
157
|
- lib/generator/js.rb
|
126
158
|
- lib/generator/measure_period.js.erb
|
159
|
+
- lib/generator/observation_criteria.js.erb
|
127
160
|
- lib/generator/patient_data.js.erb
|
128
161
|
- lib/generator/population_criteria.js.erb
|
129
162
|
- lib/generator/precondition.js.erb
|