hqmf2js 1.1.0 → 1.2.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.
- 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
|