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

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

move ReferenceRange test to rspec

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