hqmf2js 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem 'rails'
3
+ gem 'rails', '3.2.9'
4
4
 
5
5
  group :assets do
6
6
  gem 'sass-rails'
@@ -8,17 +8,12 @@ group :assets do
8
8
  gem 'uglifier'
9
9
  end
10
10
 
11
- #gem "hquery-patient-api", :git => 'http://github.com/pophealth/patientapi.git', :branch => 'develop'
12
- #gem 'hquery-patient-api', :path => '../patientapi'
13
- gem 'hquery-patient-api', '~> 0.3.0'
14
- #gem 'hqmf-parser', :git => 'https://github.com/pophealth/hqmf-parser.git', :branch => 'develop'
15
- #gem 'hqmf-parser', :path => '../hqmf-parser'
16
- gem 'hqmf-parser', '~> 1.0.4'
17
- #gem "health-data-standards", :git => 'http://github.com/projectcypress/health-data-standards.git', :branch => 'develop'
18
- gem "health-data-standards", '~> 2.1.3'
11
+ gem "hquery-patient-api", '~> 1.0.0'
12
+ gem 'hqmf-parser', '~> 1.1.0'
13
+ gem "health-data-standards", '~> 2.2.0'
19
14
 
20
15
  gem 'nokogiri'
21
- gem 'sprockets'
16
+ gem 'sprockets', '~> 2.2.2'
22
17
  gem 'coffee-script'
23
18
  gem 'uglifier'
24
19
  gem 'tilt'
data/Gemfile.lock CHANGED
@@ -1,53 +1,53 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- actionmailer (3.2.3)
5
- actionpack (= 3.2.3)
4
+ actionmailer (3.2.9)
5
+ actionpack (= 3.2.9)
6
6
  mail (~> 2.4.4)
7
- actionpack (3.2.3)
8
- activemodel (= 3.2.3)
9
- activesupport (= 3.2.3)
7
+ actionpack (3.2.9)
8
+ activemodel (= 3.2.9)
9
+ activesupport (= 3.2.9)
10
10
  builder (~> 3.0.0)
11
11
  erubis (~> 2.7.0)
12
- journey (~> 1.0.1)
12
+ journey (~> 1.0.4)
13
13
  rack (~> 1.4.0)
14
14
  rack-cache (~> 1.2)
15
15
  rack-test (~> 0.6.1)
16
- sprockets (~> 2.1.2)
17
- activemodel (3.2.3)
18
- activesupport (= 3.2.3)
16
+ sprockets (~> 2.2.1)
17
+ activemodel (3.2.9)
18
+ activesupport (= 3.2.9)
19
19
  builder (~> 3.0.0)
20
- activerecord (3.2.3)
21
- activemodel (= 3.2.3)
22
- activesupport (= 3.2.3)
20
+ activerecord (3.2.9)
21
+ activemodel (= 3.2.9)
22
+ activesupport (= 3.2.9)
23
23
  arel (~> 3.0.2)
24
24
  tzinfo (~> 0.3.29)
25
- activeresource (3.2.3)
26
- activemodel (= 3.2.3)
27
- activesupport (= 3.2.3)
28
- activesupport (3.2.3)
25
+ activeresource (3.2.9)
26
+ activemodel (= 3.2.9)
27
+ activesupport (= 3.2.9)
28
+ activesupport (3.2.9)
29
29
  i18n (~> 0.6)
30
30
  multi_json (~> 1.0)
31
- ansi (1.4.2)
31
+ ansi (1.4.3)
32
32
  arel (3.0.2)
33
- awesome_print (1.0.2)
34
- builder (3.0.3)
33
+ awesome_print (1.1.0)
34
+ builder (3.0.4)
35
35
  choice (0.1.6)
36
- coderay (1.0.6)
36
+ coderay (1.0.8)
37
37
  coffee-rails (3.2.2)
38
38
  coffee-script (>= 2.2.0)
39
39
  railties (~> 3.2.0)
40
40
  coffee-script (2.2.0)
41
41
  coffee-script-source
42
42
  execjs
43
- coffee-script-source (1.3.1)
43
+ coffee-script-source (1.4.0)
44
44
  configatron (2.9.1)
45
45
  yamler (>= 0.1.0)
46
46
  cover_me (1.2.0)
47
47
  configatron
48
48
  hashie
49
49
  erubis (2.7.0)
50
- execjs (1.3.0)
50
+ execjs (1.4.0)
51
51
  multi_json (~> 1.0)
52
52
  faraday (0.8.4)
53
53
  multipart-post (~> 1.1)
@@ -56,24 +56,25 @@ GEM
56
56
  oauth (>= 0.3.6)
57
57
  oauth2 (>= 0.5.0)
58
58
  hashie (1.2.0)
59
- health-data-standards (2.1.3)
59
+ health-data-standards (2.2.0)
60
+ activesupport (~> 3.2.9)
60
61
  builder (~> 3.0.0)
61
62
  erubis (~> 2.7.0)
62
- mongoid (~> 3.0.6)
63
+ mongoid (~> 3.0.14)
63
64
  nokogiri (~> 1.5.5)
64
65
  rest-client (~> 1.6.7)
65
66
  uuid (~> 2.3.5)
66
67
  hike (1.2.1)
67
- hqmf-parser (1.0.4)
68
+ hqmf-parser (1.1.0)
68
69
  google-spreadsheet-ruby (= 0.1.8)
69
70
  roo (= 1.10.1)
70
71
  rubyzip
71
72
  spreadsheet (= 0.6.8)
72
- hquery-patient-api (0.3.0)
73
+ hquery-patient-api (1.0.0)
73
74
  httpauth (0.2.0)
74
75
  i18n (0.6.1)
75
- journey (1.0.3)
76
- json (1.7.3)
76
+ journey (1.0.4)
77
+ json (1.7.5)
77
78
  jwt (0.1.5)
78
79
  multi_json (>= 1.0)
79
80
  libv8 (3.3.10.4)
@@ -84,16 +85,16 @@ GEM
84
85
  i18n (>= 0.4.0)
85
86
  mime-types (~> 1.16)
86
87
  treetop (~> 1.4.8)
87
- method_source (0.7.1)
88
- mime-types (1.18)
89
- minitest (2.12.1)
90
- mongoid (3.0.13)
88
+ method_source (0.8.1)
89
+ mime-types (1.19)
90
+ minitest (4.3.2)
91
+ mongoid (3.0.15)
91
92
  activemodel (~> 3.1)
92
93
  moped (~> 1.1)
93
94
  origin (~> 1.0)
94
95
  tzinfo (~> 0.3.22)
95
- moped (1.2.9)
96
- multi_json (1.3.6)
96
+ moped (1.3.1)
97
+ multi_json (1.4.0)
97
98
  multipart-post (1.1.5)
98
99
  nokogiri (1.5.5)
99
100
  oauth (0.4.7)
@@ -103,35 +104,35 @@ GEM
103
104
  jwt (~> 0.1.4)
104
105
  multi_json (~> 1.0)
105
106
  rack (~> 1.2)
106
- origin (1.0.10)
107
+ origin (1.0.11)
107
108
  polyglot (0.3.3)
108
- pry (0.9.9.3)
109
+ pry (0.9.10)
109
110
  coderay (~> 1.0.5)
110
- method_source (~> 0.7.1)
111
- slop (>= 2.4.4, < 3)
111
+ method_source (~> 0.8)
112
+ slop (~> 3.3.1)
112
113
  rack (1.4.1)
113
114
  rack-cache (1.2)
114
115
  rack (>= 0.4)
115
116
  rack-ssl (1.3.2)
116
117
  rack
117
- rack-test (0.6.1)
118
+ rack-test (0.6.2)
118
119
  rack (>= 1.0)
119
- rails (3.2.3)
120
- actionmailer (= 3.2.3)
121
- actionpack (= 3.2.3)
122
- activerecord (= 3.2.3)
123
- activeresource (= 3.2.3)
124
- activesupport (= 3.2.3)
120
+ rails (3.2.9)
121
+ actionmailer (= 3.2.9)
122
+ actionpack (= 3.2.9)
123
+ activerecord (= 3.2.9)
124
+ activeresource (= 3.2.9)
125
+ activesupport (= 3.2.9)
125
126
  bundler (~> 1.0)
126
- railties (= 3.2.3)
127
- railties (3.2.3)
128
- actionpack (= 3.2.3)
129
- activesupport (= 3.2.3)
127
+ railties (= 3.2.9)
128
+ railties (3.2.9)
129
+ actionpack (= 3.2.9)
130
+ activesupport (= 3.2.9)
130
131
  rack-ssl (~> 1.3.2)
131
132
  rake (>= 0.8.7)
132
133
  rdoc (~> 3.4)
133
- thor (~> 0.14.6)
134
- rake (0.9.2.2)
134
+ thor (>= 0.14.6, < 2.0)
135
+ rake (10.0.2)
135
136
  rdoc (3.12)
136
137
  json (~> 1.4)
137
138
  rest-client (1.6.7)
@@ -143,37 +144,38 @@ GEM
143
144
  rubyzip (>= 0.9.4)
144
145
  spreadsheet (> 0.6.4)
145
146
  todonotes (>= 0.1.0)
146
- ruby-ole (1.2.11.5)
147
+ ruby-ole (1.2.11.6)
147
148
  rubyzip (0.9.9)
148
- sass (3.1.15)
149
+ sass (3.2.3)
149
150
  sass-rails (3.2.5)
150
151
  railties (~> 3.2.0)
151
152
  sass (>= 3.1.10)
152
153
  tilt (~> 1.3)
153
- slop (2.4.4)
154
+ slop (3.3.3)
154
155
  spreadsheet (0.6.8)
155
156
  ruby-ole (>= 1.0)
156
- sprockets (2.1.2)
157
+ sprockets (2.2.2)
157
158
  hike (~> 1.2)
159
+ multi_json (~> 1.0)
158
160
  rack (~> 1.0)
159
161
  tilt (~> 1.1, != 1.3.0)
160
162
  systemu (2.5.2)
161
163
  therubyracer (0.10.2)
162
164
  libv8 (~> 3.3.10)
163
- thor (0.14.6)
165
+ thor (0.16.0)
164
166
  tilt (1.3.3)
165
- todonotes (0.1.0)
167
+ todonotes (0.1.1)
166
168
  log4r
167
- treetop (1.4.10)
169
+ treetop (1.4.12)
168
170
  polyglot
169
171
  polyglot (>= 0.3.1)
170
- turn (0.9.5)
172
+ turn (0.9.6)
171
173
  ansi
172
- tzinfo (0.3.33)
173
- uglifier (1.2.4)
174
+ tzinfo (0.3.35)
175
+ uglifier (1.3.0)
174
176
  execjs (>= 0.3.0)
175
- multi_json (>= 1.0.2)
176
- uuid (2.3.5)
177
+ multi_json (~> 1.0, >= 1.0.2)
178
+ uuid (2.3.6)
177
179
  macaddr (~> 1.0)
178
180
  yamler (0.1.0)
179
181
 
@@ -185,16 +187,16 @@ DEPENDENCIES
185
187
  coffee-rails
186
188
  coffee-script
187
189
  cover_me (~> 1.2.0)
188
- health-data-standards (~> 2.1.3)
189
- hqmf-parser (~> 1.0.4)
190
- hquery-patient-api (~> 0.3.0)
190
+ health-data-standards (~> 2.2.0)
191
+ hqmf-parser (~> 1.1.0)
192
+ hquery-patient-api (~> 1.0.0)
191
193
  minitest
192
194
  nokogiri
193
195
  pry
194
- rails
196
+ rails (= 3.2.9)
195
197
  rake
196
198
  sass-rails
197
- sprockets
199
+ sprockets (~> 2.2.2)
198
200
  therubyracer
199
201
  therubyrhino
200
202
  tilt
@@ -0,0 +1,72 @@
1
+ @hqmf.CustomCalc = {}
2
+
3
+ class @hqmf.CustomCalc.PercentTTREntries extends hQuery.CodedEntryList
4
+
5
+ constructor: (events) ->
6
+ super()
7
+ events = events.sort(dateSortAscending)
8
+ @push(event) for event in events
9
+ @minInr = 2.0
10
+ @maxInr = 3.0
11
+ # sort entries ascending
12
+ # filter duplicates to those closest to 2.5
13
+ # remove duplicate results on entries
14
+
15
+ calculateDaysInRange: (firstInr, secondInr) ->
16
+
17
+ if ((@belowRange(firstInr) and @belowRange(secondInr)) or (@aboveRange(firstInr) and @aboveRange(secondInr)))
18
+ 0
19
+ else if (@inRange(firstInr) and @inRange(secondInr))
20
+ @differenceInDays(firstInr,secondInr)
21
+ else if (@outsideRange(firstInr) and @inRange(secondInr))
22
+ @calculateCrossingRange(firstInr,secondInr)
23
+ else if (@inRange(firstInr) and @outsideRange(secondInr))
24
+ @calculateCrossingRange(secondInr, firstInr)
25
+ else
26
+ @calculateSpanningRange(firstInr, secondInr)
27
+
28
+ calculateCrossingRange: (outside,inside) ->
29
+ outsideInr = @inrValue(outside)
30
+ insideInr = @inrValue(inside)
31
+ boundary = @maxInr
32
+ boundary = @minInr if (@belowRange(outside))
33
+ (Math.abs(boundary - insideInr)/Math.abs(insideInr-outsideInr))*@differenceInDays(outside,inside)
34
+
35
+ calculateSpanningRange: (first,second) ->
36
+ (1.0/Math.abs(@inrValue(first)-@inrValue(second)))*@differenceInDays(first,second)
37
+
38
+ inRange: (entry) ->
39
+ inr = @inrValue(entry)
40
+ inr >= @minInr and inr <= @maxInr
41
+
42
+ outsideRange: (entry) ->
43
+ !@inRange(entry)
44
+
45
+ belowRange: (entry) ->
46
+ inr = @inrValue(entry)
47
+ inr < @minInr
48
+
49
+ aboveRange: (entry) ->
50
+ inr = @inrValue(entry)
51
+ inr > @maxInr
52
+
53
+ differenceInDays: (first, second) ->
54
+ getIVL(first).low.difference(getIVL(second).low, 'd')
55
+
56
+ inrValue: (entry) ->
57
+ entry.values()[0].scalar()
58
+
59
+ totalNumberOfDays: () ->
60
+ @differenceInDays(this[0],this[this.length-1])
61
+
62
+ calculateTTR: () ->
63
+ total = 0
64
+ for left, i in this
65
+ if (i < this.length-1)
66
+ right = this[i+1]
67
+ total += @calculateDaysInRange(left, right)
68
+ total
69
+
70
+ calculatePercentTTR: () ->
71
+ @calculateTTR()/@totalNumberOfDays()*100
72
+
@@ -15,7 +15,7 @@ class TS
15
15
  minute = parseInt(hl7ts.substring(10,12), 10)
16
16
  if isNaN(minute)
17
17
  minute = 0
18
- @date = new Date(year, month, day, hour, minute)
18
+ @date = new Date(Date.UTC(year, month, day, hour, minute))
19
19
  else
20
20
  @date = new Date()
21
21
 
@@ -24,17 +24,17 @@ class TS
24
24
  # wk (week), d (day), h (hour) and min (minute).
25
25
  add: (pq) ->
26
26
  if pq.unit=="a"
27
- @date.setFullYear(@date.getFullYear()+pq.value)
27
+ @date.setUTCFullYear(@date.getUTCFullYear()+pq.value)
28
28
  else if pq.unit=="mo"
29
- @date.setMonth(@date.getMonth()+pq.value)
29
+ @date.setUTCMonth(@date.getUTCMonth()+pq.value)
30
30
  else if pq.unit=="wk"
31
- @date.setDate(@date.getDate()+(7*pq.value))
31
+ @date.setUTCDate(@date.getUTCDate()+(7*pq.value))
32
32
  else if pq.unit=="d"
33
- @date.setDate(@date.getDate()+pq.value)
33
+ @date.setUTCDate(@date.getUTCDate()+pq.value)
34
34
  else if pq.unit=="h"
35
- @date.setHours(@date.getHours()+pq.value)
35
+ @date.setUTCHours(@date.getUTCHours()+pq.value)
36
36
  else if pq.unit=="min"
37
- @date.setMinutes(@date.getMinutes()+pq.value)
37
+ @date.setUTCMinutes(@date.getUTCMinutes()+pq.value)
38
38
  else
39
39
  throw "Unknown time unit: "+pq.unit
40
40
  this
@@ -76,7 +76,7 @@ class TS
76
76
  if @date==null || other.date==null
77
77
  return false
78
78
  if other.inclusive
79
- beforeOrConcurrent(other)
79
+ @beforeOrConcurrent(other)
80
80
  else
81
81
  [a,b] = TS.dropSeconds(@date, other.date)
82
82
  a.getTime() < b.getTime()
@@ -86,7 +86,7 @@ class TS
86
86
  if @date==null || other.date==null
87
87
  return false
88
88
  if other.inclusive
89
- afterOrConcurrent(other)
89
+ @afterOrConcurrent(other)
90
90
  else
91
91
  [a,b] = TS.dropSeconds(@date, other.date)
92
92
  a.getTime() > b.getTime()
@@ -113,21 +113,21 @@ class TS
113
113
 
114
114
  # Number of whole years between the two time stamps (as Date objects)
115
115
  @yearsDifference: (earlier, later) ->
116
- if (later.getMonth() < earlier.getMonth())
117
- later.getFullYear()-earlier.getFullYear()-1
118
- else if (later.getMonth() == earlier.getMonth() && later.getDate() >= earlier.getDate())
119
- later.getFullYear()-earlier.getFullYear()
120
- else if (later.getMonth() == earlier.getMonth() && later.getDate() < earlier.getDate())
121
- later.getFullYear()-earlier.getFullYear()-1
116
+ if (later.getUTCMonth() < earlier.getUTCMonth())
117
+ later.getUTCFullYear()-earlier.getUTCFullYear()-1
118
+ else if (later.getUTCMonth() == earlier.getUTCMonth() && later.getUTCDate() >= earlier.getUTCDate())
119
+ later.getUTCFullYear()-earlier.getUTCFullYear()
120
+ else if (later.getUTCMonth() == earlier.getUTCMonth() && later.getUTCDate() < earlier.getUTCDate())
121
+ later.getUTCFullYear()-earlier.getUTCFullYear()-1
122
122
  else
123
- later.getFullYear()-earlier.getFullYear()
123
+ later.getUTCFullYear()-earlier.getUTCFullYear()
124
124
 
125
125
  # Number of whole months between the two time stamps (as Date objects)
126
126
  @monthsDifference: (earlier, later) ->
127
- if (later.getDate() >= earlier.getDate())
128
- (later.getFullYear()-earlier.getFullYear())*12+later.getMonth()-earlier.getMonth()
127
+ if (later.getUTCDate() >= earlier.getUTCDate())
128
+ (later.getUTCFullYear()-earlier.getUTCFullYear())*12+later.getUTCMonth()-earlier.getUTCMonth()
129
129
  else
130
- (later.getFullYear()-earlier.getFullYear())*12+later.getMonth()-earlier.getMonth()-1
130
+ (later.getUTCFullYear()-earlier.getUTCFullYear())*12+later.getUTCMonth()-earlier.getUTCMonth()-1
131
131
 
132
132
  # Number of whole minutes between the two time stamps (as Date objects)
133
133
  @minutesDifference: (earlier, later) ->
@@ -140,10 +140,8 @@ class TS
140
140
  # Number of days betweem the two time stamps (as Date objects)
141
141
  @daysDifference: (earlier, later) ->
142
142
  # have to discard time portion for day difference calculation purposes
143
- e = new Date(earlier.getFullYear(), earlier.getMonth(), earlier.getDate())
144
- e.setUTCHours(0)
145
- l = new Date(later.getFullYear(), later.getMonth(), later.getDate())
146
- l.setUTCHours(0)
143
+ e = new Date(Date.UTC(earlier.getUTCFullYear(), earlier.getUTCMonth(), earlier.getUTCDate()))
144
+ l = new Date(Date.UTC(later.getUTCFullYear(), later.getUTCMonth(), later.getUTCDate()))
147
145
  Math.floor(TS.hoursDifference(e,l)/24)
148
146
 
149
147
  # Number of whole weeks between the two time stmaps (as Date objects)
@@ -413,25 +411,25 @@ class ANYNonNull
413
411
  atLeastOneTrue = (values...) ->
414
412
  trueValues = (value for value in values when value && value.isTrue())
415
413
  trueValues.length>0
416
- Specifics.unionAll(new Boolean(trueValues.length>0), values)
414
+ hqmf.SpecificsManager.unionAll(new Boolean(trueValues.length>0), values)
417
415
  @atLeastOneTrue = atLeastOneTrue
418
416
 
419
417
  # Returns true if all of the supplied values are true
420
418
  allTrue = (values...) ->
421
419
  trueValues = (value for value in values when value && value.isTrue())
422
- Specifics.intersectAll(new Boolean(trueValues.length>0 && trueValues.length==values.length), values)
420
+ hqmf.SpecificsManager.intersectAll(new Boolean(trueValues.length>0 && trueValues.length==values.length), values)
423
421
  @allTrue = allTrue
424
422
 
425
423
  # Returns true if one or more of the supplied values is false
426
424
  atLeastOneFalse = (values...) ->
427
425
  falseValues = (value for value in values when value.isFalse())
428
- Specifics.intersectAll(new Boolean(falseValues.length>0), values, true)
426
+ hqmf.SpecificsManager.intersectAll(new Boolean(falseValues.length>0), values, true)
429
427
  @atLeastOneFalse = atLeastOneFalse
430
428
 
431
429
  # Returns true if all of the supplied values are false
432
430
  allFalse = (values...) ->
433
431
  falseValues = (value for value in values when value.isFalse())
434
- Specifics.unionAll(new Boolean(falseValues.length>0 && falseValues.length==values.length), values, true)
432
+ hqmf.SpecificsManager.unionAll(new Boolean(falseValues.length>0 && falseValues.length==values.length), values, true)
435
433
  @allFalse = allFalse
436
434
 
437
435
  # Return true if compareTo matches value
@@ -454,12 +452,56 @@ filterEventsByValue = (events, value) ->
454
452
  # Return only those events with a field that matches the supplied value
455
453
  filterEventsByField = (events, field, value) ->
456
454
  respondingEvents = (event for event in events when event.respondTo(field))
457
- event for event in respondingEvents when value.match(event[field]())
455
+ result = (event for event in respondingEvents when value.match(event[field]()))
456
+ hqmf.SpecificsManager.maintainSpecifics(result, events)
458
457
  @filterEventsByField = filterEventsByField
459
458
 
459
+ shiftTimes = (event, field) ->
460
+ shiftedEvent = new event.constructor(event.json)
461
+ shiftedEvent.setTimestamp(shiftedEvent[field]())
462
+ shiftedEvent
463
+ @shiftTimes = shiftTimes
464
+
465
+ adjustBoundsForField = (events, field) ->
466
+ validEvents = (event for event in events when (event.respondTo(field) and event[field]()))
467
+ shiftedEvents = (shiftTimes(event, field) for event in validEvents)
468
+ hqmf.SpecificsManager.maintainSpecifics(shiftedEvents, events)
469
+ @adjustBoundsForField = adjustBoundsForField
470
+
471
+ # Clone the supplied event and replace any facilities with just the supplied one
472
+ narrowEventForFacility = (event, facility) ->
473
+ narrowed = new event.constructor(event.json)
474
+ # uncomment the following line when patient API is modified to support multiple
475
+ # facilities
476
+ # narrowed._facilities = [facility]
477
+ narrowed
478
+ @narrowEventForFacility = narrowEventForFacility
479
+
480
+ # Return a cloned set of events, each with just one of the original facilities
481
+ denormalizeEvent = (event) ->
482
+ # the following line should be changed when the patient API is modified to support
483
+ # more than one facility per encounter
484
+ # narrowed = (narrowEventForFacility(event, facility) for facility in event.facilities)
485
+ narrowed = (narrowEventForFacility(event, facility) for facility in [event.facility])
486
+ @denormalizeEvent = denormalizeEvent
487
+
488
+ # Creates a new set of events with one location per event. Input events with more than
489
+ # one location will be duplicated once per location and each resulting event will
490
+ # be assigned one location. Start and end times of the event will be adjusted to match the
491
+ # value of the supplied field
492
+ denormalizeEventsByLocation = (events, field) ->
493
+ respondingEvents = (event for event in events when event.respondTo("facility") and event.facility())
494
+ denormalizedEvents = (denormalizeEvent(event) for event in respondingEvents)
495
+ denormalizedEvents = [].concat denormalizedEvents...
496
+ result = adjustBoundsForField(denormalizedEvents, field)
497
+ hqmf.SpecificsManager.maintainSpecifics(result, events)
498
+ @denormalizeEventsByLocation = denormalizeEventsByLocation
499
+
460
500
  # Utility method to obtain the value set for an OID
461
501
  getCodes = (oid) ->
462
- OidDictionary[oid]
502
+ codes = OidDictionary[oid]
503
+ throw "value set oid could not be found: #{oid}" unless codes?
504
+ codes
463
505
  @getCodes = getCodes
464
506
 
465
507
  # Used for representing XPRODUCTs of arrays, holds both a flattened array that contains
@@ -475,7 +517,7 @@ class CrossProduct extends Array
475
517
 
476
518
  # Create a CrossProduct of the supplied event lists.
477
519
  XPRODUCT = (eventLists...) ->
478
- Specifics.intersectAll(new CrossProduct(eventLists), eventLists)
520
+ hqmf.SpecificsManager.intersectAll(new CrossProduct(eventLists), eventLists)
479
521
  @XPRODUCT = XPRODUCT
480
522
 
481
523
  # Create a new list containing all the events from the supplied event lists
@@ -484,14 +526,14 @@ UNION = (eventLists...) ->
484
526
  for eventList in eventLists
485
527
  for event in eventList
486
528
  union.push(event)
487
- Specifics.unionAll(union, eventLists)
529
+ hqmf.SpecificsManager.unionAll(union, eventLists)
488
530
  @UNION = UNION
489
531
 
490
532
  # Return true if the number of events matches the supplied range
491
533
  COUNT = (events, range) ->
492
534
  count = events.length
493
535
  result = new Boolean(range.match(count))
494
- applySpecificOccurrenceSubset('COUNT', Specifics.maintainSpecifics(result, events), range)
536
+ applySpecificOccurrenceSubset('COUNT', hqmf.SpecificsManager.maintainSpecifics(result, events), range)
495
537
  @COUNT = COUNT
496
538
 
497
539
  # Convert an hQuery.CodedEntry or JS Date into an IVL_TS
@@ -521,7 +563,8 @@ eventAccessor = {
521
563
  'SCW': 'low',
522
564
  'ECWS': 'high'
523
565
  'SCWE': 'low',
524
- 'CONCURRENT': 'low'
566
+ 'CONCURRENT': 'low',
567
+ 'DATEDIFF': 'low'
525
568
  }
526
569
 
527
570
  boundAccessor = {
@@ -541,7 +584,8 @@ boundAccessor = {
541
584
  'SCW': 'low',
542
585
  'ECWS': 'low'
543
586
  'SCWE': 'high',
544
- 'CONCURRENT': 'low'
587
+ 'CONCURRENT': 'low',
588
+ 'DATEDIFF': 'low'
545
589
  }
546
590
 
547
591
  # Determine whether the supplied event falls within range of the supplied bound
@@ -563,7 +607,7 @@ eventMatchesBounds = (event, bounds, methodName, range) ->
563
607
  currentMatches = eventMatchesBounds(event, boundList, methodName, range)
564
608
  return [] if (currentMatches.length == 0)
565
609
  matchingBounds = matchingBounds.concat(currentMatches)
566
- return Specifics.maintainSpecifics(matchingBounds,bounds)
610
+ return hqmf.SpecificsManager.maintainSpecifics(matchingBounds,bounds)
567
611
  else
568
612
  eventIVL = getIVL(event)
569
613
  matchingBounds = (bound for bound in bounds when (
@@ -573,7 +617,7 @@ eventMatchesBounds = (event, bounds, methodName, range) ->
573
617
  result &&= withinRange(methodName, eventIVL, boundIVL, range)
574
618
  result
575
619
  ))
576
- Specifics.maintainSpecifics(matchingBounds, bounds)
620
+ hqmf.SpecificsManager.maintainSpecifics(matchingBounds, bounds)
577
621
  @eventMatchesBounds = eventMatchesBounds
578
622
 
579
623
  # Determine which event match one of the supplied bounds
@@ -583,7 +627,7 @@ eventsMatchBounds = (events, bounds, methodName, range) ->
583
627
  if (events.length==undefined)
584
628
  events = [events]
585
629
 
586
- specificContext = new Specifics()
630
+ specificContext = new hqmf.SpecificOccurrence()
587
631
  hasSpecificOccurrence = (events.specific_occurrence? || bounds.specific_occurrence?)
588
632
  matchingEvents = []
589
633
  matchingEvents.specific_occurrence = events.specific_occurrence
@@ -593,7 +637,7 @@ eventsMatchBounds = (events, bounds, methodName, range) ->
593
637
 
594
638
  if hasSpecificOccurrence
595
639
  matchingEvents.specific_occurrence = events.specific_occurrence
596
- # TODO: we'll need a temporary variable for non specific occurrences on the left so that we can do rejections based on restrictions in the data criteria
640
+ # TODO: well need a temporary variable for non specific occurrences on the left so that we can do rejections based on restrictions in the data criteria
597
641
  specificContext.addRows(Row.buildRowsForMatching(events.specific_occurrence, event, bounds.specific_occurrence, matchingBounds))
598
642
  else
599
643
  # add all stars
@@ -693,37 +737,37 @@ applySpecificOccurrenceSubset = (operator, result, range, calculateSpecifics) ->
693
737
  FIRST = (events) ->
694
738
  result = []
695
739
  result = [events.sort(dateSortAscending)[0]] if (events.length > 0)
696
- applySpecificOccurrenceSubset('FIRST',Specifics.maintainSpecifics(result, events))
740
+ applySpecificOccurrenceSubset('FIRST',hqmf.SpecificsManager.maintainSpecifics(result, events))
697
741
  @FIRST = FIRST
698
742
 
699
743
  SECOND = (events) ->
700
744
  result = []
701
745
  result = [events.sort(dateSortAscending)[1]] if (events.length > 1)
702
- applySpecificOccurrenceSubset('SECOND',Specifics.maintainSpecifics(result, events))
746
+ applySpecificOccurrenceSubset('SECOND',hqmf.SpecificsManager.maintainSpecifics(result, events))
703
747
  @SECOND = SECOND
704
748
 
705
749
  THIRD = (events) ->
706
750
  result = []
707
751
  result = [events.sort(dateSortAscending)[2]] if (events.length > 2)
708
- applySpecificOccurrenceSubset('THIRD',Specifics.maintainSpecifics(result, events))
752
+ applySpecificOccurrenceSubset('THIRD',hqmf.SpecificsManager.maintainSpecifics(result, events))
709
753
  @THIRD = THIRD
710
754
 
711
755
  FOURTH = (events) ->
712
756
  result = []
713
757
  result = [events.sort(dateSortAscending)[3]] if (events.length > 3)
714
- applySpecificOccurrenceSubset('FOURTH',Specifics.maintainSpecifics(result, events))
758
+ applySpecificOccurrenceSubset('FOURTH',hqmf.SpecificsManager.maintainSpecifics(result, events))
715
759
  @FOURTH = FOURTH
716
760
 
717
761
  FIFTH = (events) ->
718
762
  result = []
719
763
  result = [events.sort(dateSortAscending)[4]] if (events.length > 4)
720
- applySpecificOccurrenceSubset('FIFTH',Specifics.maintainSpecifics(result, events))
764
+ applySpecificOccurrenceSubset('FIFTH',hqmf.SpecificsManager.maintainSpecifics(result, events))
721
765
  @FIFTH = FIFTH
722
766
 
723
767
  RECENT = (events) ->
724
768
  result = []
725
769
  result = [events.sort(dateSortDescending)[0]] if (events.length > 0)
726
- applySpecificOccurrenceSubset('RECENT',Specifics.maintainSpecifics(result, events))
770
+ applySpecificOccurrenceSubset('RECENT',hqmf.SpecificsManager.maintainSpecifics(result, events))
727
771
  @RECENT = RECENT
728
772
 
729
773
  LAST = (events) ->
@@ -759,7 +803,7 @@ MIN = (events, range) ->
759
803
  if (events.length > 0)
760
804
  minValue = events.sort(valueSortAscending)[0].value()["scalar"]
761
805
  result = new Boolean(range.match(minValue))
762
- applySpecificOccurrenceSubset('MIN',Specifics.maintainSpecifics(result, events), range)
806
+ applySpecificOccurrenceSubset('MIN',hqmf.SpecificsManager.maintainSpecifics(result, events), range)
763
807
  @MIN = MIN
764
808
 
765
809
  MAX = (events, range) ->
@@ -767,9 +811,16 @@ MAX = (events, range) ->
767
811
  if (events.length > 0)
768
812
  maxValue = events.sort(valueSortDescending)[0].value()["scalar"]
769
813
  result = new Boolean(range.match(maxValue))
770
- applySpecificOccurrenceSubset('MAX',Specifics.maintainSpecifics(result, events), range)
814
+ applySpecificOccurrenceSubset('MAX',hqmf.SpecificsManager.maintainSpecifics(result, events), range)
771
815
  @MAX = MAX
772
816
 
817
+ DATEDIFF = (events, range) ->
818
+ return hqmf.SpecificsManager.maintainSpecifics(new Boolean(false), events) if events.length < 2
819
+ throw "cannot calculate against more than 2 events" if events.length > 2
820
+ hqmf.SpecificsManager.maintainSpecifics(new Boolean(withinRange('DATEDIFF', getIVL(events[0]), getIVL(events[1]), range)), events)
821
+ @DATEDIFF = DATEDIFF
822
+
823
+
773
824
  @OidDictionary = {};
774
825
 
775
826
  hqmfjs = hqmfjs||{}