source: ruby/branches/0.5/lib/open_ehr/rm/data_types/quantity.rb@ 247

Last change on this file since 247 was 247, checked in by KOBAYASHI, Shinji, 15 years ago

move DvQuantified test to rspec

File size: 12.4 KB
Line 
1# This modules are implemented from the UML shown bellow
2# http://www.openehr.org/uml/release-1.0.1/Browsable/_9_0_76d0249_1109599337877_94556_1510Report.html
3# Ticket refs #50
4#require 'assumed_library_types'
5module OpenEHR
6 module RM
7 module DataTypes
8 module Quantity
9 class DvOrdered < OpenEHR::RM::DataTypes::Basic::DataValue
10 include Comparable
11 attr_accessor :normal_range, :other_refference_ranges, :normal_status
12
13 def initialize(args = {})
14 super(args)
15 self.normal_range = args[:normal_range]
16 self.normal_status = args[:normal_status]
17 self.other_reference_ranges = args[:other_reference_ranges]
18 end
19
20 def is_normal?
21 if @normal_range.nil? and @normal_status.nil?
22 return false
23 elsif !@normal_range.nil?
24 return @normal_range.has(@value)
25 elsif !@normal_status.nil?
26 return @normal_status.code_string == 'N'
27 end
28 end
29
30 def is_simple?
31 return @other_reference_ranges.nil?
32 end
33
34 def <=>(other)
35 raise NotImplementedError, 'This method should be implemented'
36 end
37
38 def other_reference_ranges=(other_reference_ranges)
39 if !other_reference_ranges.nil? && other_reference_ranges.empty?
40 raise ArgumentError, "Other reference ranges validity error"
41 end
42 @other_reference_ranges = other_reference_ranges
43 end
44
45 def is_strictly_comparable_to?(other)
46 raise NotImplementedError, 'this method should be implemented'
47 end
48 end
49
50 class DvInterval < OpenEHR::AssumedLibraryTypes::Interval
51
52 end
53
54 class DvQuantified < DvOrdered
55 attr_reader :magnitude, :magnitude_status
56
57 def initialize(args = {})
58 super(args)
59 self.magnitude = args[:magnitude]
60 self.magnitude_status = args[:magnitude_status]
61 end
62
63 def <=>(others)
64 @magnitude <=> others.magnitude
65 end
66
67 def magnitude=(magnitude)
68 raise ArgumentError, 'magnitude should not be nil' if magnitude.nil?
69 @magnitude = magnitude
70 end
71
72 def magnitude_status=(magnitude_status)
73 if magnitude_status.nil?
74 @magnitude_status = '='
75 elsif DvQuantified.valid_magnitude_status?(magnitude_status)
76 @magnitude_status = magnitude_status
77 else
78 raise ArgumentError, 'magnitude_status invalid'
79 end
80 end
81
82 def accuracy_unknown?
83 return @accuracy.nil?
84 end
85
86 def self.valid_magnitude_status?(s)
87 if s == '=' || s == '>' || s == '<' || s == '<=' ||
88 s == '>=' || s == '~'
89 return true
90 else
91 return false
92 end
93 end
94 end
95
96 class DvOrdinal < DvOrdered
97 attr_reader :value, :symbol, :limits
98
99 def initialize(args = {})
100 super(args)
101 self.symbol = args[:symbol]
102 self.limits = args[:limits]
103 end
104
105 def value=(value)
106 raise ArgumentError, 'value should not be nil' if value.nil?
107 @value = value
108 end
109
110 def symbol=(symbol)
111 raise ArgumentError,'symbol should not be nil' if symbol.nil?
112 @symbol = symbol
113 end
114
115 def is_strictly_comparable_to?(others)
116 unless others.instance_of? OpenEHR::RM::DataTypes::Quantity::DvOrdinal
117 return false
118 end
119 unless others.symbol.defining_code.terminology_id.value ==
120 @symbol.defining_code.terminology_id.value
121 return false
122 end
123 return true
124 end
125
126 def <=>(other)
127 @value <=> other.value
128 end
129
130 def limits=(limits)
131 unless limits.nil? or limits.meaning.value == 'limits'
132 raise ArgumentError, 'invalid limits'
133 else
134 @limits = limits
135 end
136 end
137 end
138
139 class DvAbsoluteQuantity < DvQuantified
140 attr_accessor :accuracy
141
142 def initialize(magnitude, magnitude_status=nil, accuracy=nil,
143 normal_range=nil, normal_status = nil,
144 other_reference_ranges=nil)
145 super(magnitude, magnitude_status, normal_range,
146 normal_status, other_reference_ranges)
147 self.accuracy = accuracy
148 end
149
150 def add(a_diff)
151 raise NotImplementedError, 'add must be implemented'
152 end
153
154 def diff(other)
155 raise NotImplementedError, 'diff must be implemented'
156 end
157
158 def subtract(a_diff)
159 raise NotImplementedError, 'subtract must be implemented'
160 end
161 end
162
163 class DvAmount < DvQuantified
164 attr_reader :accuracy, :accuracy_percent
165 def initialize(magnitude, magnitude_status=nil, accuracy=nil,
166 accuracy_percent=nil, normal_range=nil,
167 normal_status = nil, other_reference_ranges=nil)
168 super(magnitude, magnitude_status, normal_range,
169 normal_status, other_reference_ranges)
170 unless accuracy.nil?
171 set_accuracy(accuracy, accuracy_percent)
172 else
173 @accuracy, @accuracy_percent = nil, nil
174 end
175 end
176
177 def +(other)
178 unless self.is_strictly_comparable_to?(other)
179 raise ArgumentError, 'type mismatch'
180 end
181 return DvAmount.new(@magnitude+other.magnitude, @magnitude_status,
182 @accuracy, @accuracy_percent, @normal_range,
183 @normal_status, @other_reference_ranges)
184 end
185
186 def -(other)
187 other.magnitude = - other.magnitude
188 self+(other)
189 end
190
191 def set_accuracy(accuracy, accuracy_percent)
192 if accuracy_percent
193 raise ArgumentError, 'accuracy invalid' if accuracy < 0.0 || accuracy > 100.0
194 else
195 raise ArgumentError, 'accuracy invaild' if accuracy < 0.0 || accuracy > 1.0
196 end
197 @accuracy, @accuracy_percent = accuracy, accuracy_percent
198 end
199
200 def accuracy_is_percent?
201 return @accuracy_percent
202 end
203 end
204
205 class DvQuantity < DvAmount
206 attr_reader :units, :precision
207 def initialize(magnitude, units, magnitude_status=nil, precision=nil,
208 accuracy=nil, accuracy_percent=nil, normal_range=nil,
209 normal_status = nil, other_reference_ranges=nil)
210 super(magnitude, magnitude_status, accuracy, accuracy_percent,
211 normal_range, normal_status, other_reference_ranges)
212 self.units = units
213 self.precision = precision
214 end
215
216 def units=(units)
217 raise ArgumentError, 'units should not be nil' if units.nil?
218 @units = units
219 end
220
221 def precision=(precision)
222 unless precision.nil? || precision >= -1
223 raise ArgumentError, 'precision invalid'
224 end
225 @precision = precision
226 end
227
228 def is_strictly_comparable_to?(others)
229 return false if others.nil?
230 if others.instance_of?(DvQuantity) && others.units == @units
231 return true
232 else
233 return false
234 end
235 end
236
237 def is_integral?
238 if @precision.nil? || precision != 0
239 return false
240 else
241 return true
242 end
243 end
244# accuracy???
245 def +(other)
246 dv_amount = super(other)
247 return DvQuantity.new(dv_amount.magnitude, @units,
248 @magnitude_status, @precision,
249 @accuracy, @accuracy_percent, @normal_range,
250 @normal_status, @other_reference_ranges)
251 end
252 end
253
254 class DvCount < DvAmount
255 def is_strictly_comparable_to?(others)
256 return false if others.nil?
257 if others.instance_of?(DvCount)
258 return true
259 else
260 return false
261 end
262 end
263 end
264
265 class ReferenceRange
266 attr_reader :meaning, :range
267
268 def initialize(args = {})
269 self.meaning = args[:meaning]
270 self.range = args[:range]
271 end
272
273 def meaning=(meaning)
274 if meaning.nil?
275 raise ArgumentError, 'meaning should not be nil'
276 end
277 @meaning = meaning
278 end
279
280 def range=(range)
281 if range.nil?
282 raise ArgumentError, 'range should not be nil'
283 end
284 @range = range
285 end
286
287 def is_in_range?(val)
288 return @range.has?(val)
289 end
290 end
291
292 module ProportionKind
293 PK_RATIO = 0
294 PK_UNITARY = 1
295 PK_PERCENT = 2
296 PK_FRACTION = 3
297 PK_INTEGER_FRACTION = 4
298
299 def ProportionKind.valid_proportion_kind?(kind)
300 return true if kind >= 0 && kind <= 4
301 return false
302 end
303 end # end of ProportionKind
304
305 class DvProportion < DvAmount
306 include ProportionKind
307 attr_reader :numerator, :denominator, :type, :precision
308
309 def initialize(numerator, denominator, type, precision=nil,
310 magnitude_status=nil, accuracy=nil,
311 accuracy_percent=nil, normal_range=nil,
312 normal_status = nil, other_reference_ranges=nil)
313 self.type = type
314 self.numerator = numerator
315 self.denominator = denominator
316 self.precision = precision
317 self.magnitude_status = magnitude_status
318 unless accuracy.nil?
319 set_accuracy(accuracy, accuracy_percent)
320 else
321 @accuracy, @accuracy_percent = nil, nil
322 end
323 self.normal_range = normal_range
324 self.normal_status = normal_status
325 self.other_reference_ranges = other_reference_ranges
326 end
327
328 def numerator=(numerator)
329 raise ArgumentError, 'numerator should not be nil' if numerator.nil?
330 if (@type == PK_FRACTION || @type == PK_INTEGER_FRACTION) &&
331 !numerator.integer?
332 raise ArgumentError, 'numerator invalid for type'
333 end
334 @numerator = numerator
335 end
336
337 def denominator=(denominator)
338 if denominator.nil? or denominator == PK_RATIO
339 raise ArgumentError, 'denominator invalid'
340 end
341 if (@type == PK_FRACTION || @type == PK_INTEGER_FRACTION) &&
342 !denominator.integer?
343 raise ArgumentError, 'denominator invalid for type'
344 end
345 if @type == PK_UNITARY && denominator != 1
346 raise ArgumentError, 'denominator invalid for type'
347 end
348 if @type == PK_PERCENT && denominator != 100
349 raise ArgumentError, 'denominator invaild for type'
350 end
351 @denominator = denominator
352 end
353
354 def type=(type)
355 if ProportionKind.valid_proportion_kind?(type)
356 @type = type
357 else
358 raise ArgumentError, 'type invalid'
359 end
360 end
361
362 def magnitude
363 return numerator.to_f/denominator.to_f
364 end
365
366 def precision=(precision)
367 unless precision.nil?
368 unless precision == 0 || self.is_integral?
369 @precision = precision
370 else
371 raise ArgumentError, 'precision invalid'
372 end
373 end
374 end
375
376 def is_integral?
377 return denominator.integer? && numerator.integer?
378 end
379
380 def is_strictly_comparable_to?(other)
381 unless other.instance_of?(DvProportion)
382 return false
383 end
384 if other.type == @type
385 return true
386 else
387 return false
388 end
389 end
390 end # end of DvProportion
391 end # of Quantity
392 end # of Data_Types
393 end # of RM
394end # of OpenEHR
Note: See TracBrowser for help on using the repository browser.