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

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

move DvAmount, DvCount test to spec

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