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
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 = {})
[246]14 super(args)
[216]15 self.normal_range = args[:normal_range]
16 self.normal_status = args[:normal_status]
17 self.other_reference_ranges = args[:other_reference_ranges]
[4]18 end
[122]19
[4]20 def is_normal?
[124]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
[4]28 end
[122]29
[4]30 def is_simple?
[243]31 return @other_reference_ranges.nil?
[4]32 end
[122]33
34 def <=>(other)
[124]35 raise NotImplementedError, 'This method should be implemented'
[122]36 end
37
38 def other_reference_ranges=(other_reference_ranges)
[243]39 if !other_reference_ranges.nil? && other_reference_ranges.empty?
[4]40 raise ArgumentError, "Other reference ranges validity error"
41 end
[123]42 @other_reference_ranges = other_reference_ranges
[4]43 end
[123]44
[142]45 def is_strictly_comparable_to?(other)
[137]46 raise NotImplementedError, 'this method should be implemented'
47 end
[4]48 end
[88]49
[216]50 class DvInterval < OpenEHR::AssumedLibraryTypes::Interval
[141]51
52 end
[142]53
[167]54 class DvQuantified < DvOrdered
[146]55 attr_reader :magnitude, :magnitude_status
[137]56
[247]57 def initialize(args = {})
58 super(args)
59 self.magnitude = args[:magnitude]
60 self.magnitude_status = args[:magnitude_status]
[137]61 end
62
63 def <=>(others)
[247]64 @magnitude <=> others.magnitude
[137]65 end
66
[144]67 def magnitude=(magnitude)
68 raise ArgumentError, 'magnitude should not be nil' if magnitude.nil?
69 @magnitude = magnitude
70 end
[140]71
[144]72 def magnitude_status=(magnitude_status)
73 if magnitude_status.nil?
74 @magnitude_status = '='
[167]75 elsif DvQuantified.valid_magnitude_status?(magnitude_status)
[144]76 @magnitude_status = magnitude_status
77 else
78 raise ArgumentError, 'magnitude_status invalid'
79 end
[4]80 end
[144]81
82 def accuracy_unknown?
[148]83 return @accuracy.nil?
[144]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
[4]94 end
[88]95
[167]96 class DvOrdinal < DvOrdered
[142]97 attr_reader :value, :symbol, :limits
98
[246]99 def initialize(args = {})
100 super(args)
101 self.symbol = args[:symbol]
102 self.limits = args[:limits]
[140]103 end
[137]104
[142]105 def value=(value)
106 raise ArgumentError, 'value should not be nil' if value.nil?
107 @value = value
108 end
[140]109
[142]110 def symbol=(symbol)
111 raise ArgumentError,'symbol should not be nil' if symbol.nil?
112 @symbol = symbol
[88]113 end
[137]114
[142]115 def is_strictly_comparable_to?(others)
[216]116 unless others.instance_of? OpenEHR::RM::DataTypes::Quantity::DvOrdinal
[142]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
[139]126 def <=>(other)
[142]127 @value <=> other.value
[139]128 end
[140]129
[142]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
[88]136 end
137 end
138
[167]139 class DvAbsoluteQuantity < DvQuantified
[148]140 attr_accessor :accuracy
[88]141
[148]142 def initialize(magnitude, magnitude_status=nil, accuracy=nil,
143 normal_range=nil, normal_status = nil,
144 other_reference_ranges=nil)
[149]145 super(magnitude, magnitude_status, normal_range,
[148]146 normal_status, other_reference_ranges)
147 self.accuracy = accuracy
148 end
149
[88]150 def add(a_diff)
[149]151 raise NotImplementedError, 'add must be implemented'
[88]152 end
153
154 def diff(other)
[149]155 raise NotImplementedError, 'diff must be implemented'
[88]156 end
157
158 def subtract(a_diff)
[149]159 raise NotImplementedError, 'subtract must be implemented'
[88]160 end
161 end
[120]162
[167]163 class DvAmount < DvQuantified
[146]164 attr_reader :accuracy, :accuracy_percent
[145]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)
[146]170 unless accuracy.nil?
171 set_accuracy(accuracy, accuracy_percent)
172 else
173 @accuracy, @accuracy_percent = nil, nil
174 end
[145]175 end
[147]176
[145]177 def +(other)
[147]178 unless self.is_strictly_comparable_to?(other)
179 raise ArgumentError, 'type mismatch'
180 end
[167]181 return DvAmount.new(@magnitude+other.magnitude, @magnitude_status,
[147]182 @accuracy, @accuracy_percent, @normal_range,
183 @normal_status, @other_reference_ranges)
[145]184 end
[140]185
[145]186 def -(other)
[147]187 other.magnitude = - other.magnitude
188 self+(other)
[122]189 end
[145]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
[122]198 end
[145]199
200 def accuracy_is_percent?
201 return @accuracy_percent
202 end
[122]203 end
204
[167]205 class DvQuantity < DvAmount
[146]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
[140]215
[146]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?
[167]230 if others.instance_of?(DvQuantity) && others.units == @units
[146]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)
[147]246 dv_amount = super(other)
[167]247 return DvQuantity.new(dv_amount.magnitude, @units,
[146]248 @magnitude_status, @precision,
249 @accuracy, @accuracy_percent, @normal_range,
250 @normal_status, @other_reference_ranges)
251 end
[147]252 end
253
[167]254 class DvCount < DvAmount
[147]255 def is_strictly_comparable_to?(others)
256 return false if others.nil?
[167]257 if others.instance_of?(DvCount)
[147]258 return true
259 else
260 return false
261 end
[146]262 end
[140]263 end
264
[167]265 class ReferenceRange
[144]266 attr_reader :meaning, :range
[141]267
[245]268 def initialize(args = {})
269 self.meaning = args[:meaning]
270 self.range = args[:range]
[141]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
[144]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
[124]290 end
[139]291
[167]292 module ProportionKind
[139]293 PK_RATIO = 0
294 PK_UNITARY = 1
295 PK_PERCENT = 2
296 PK_FRACTION = 3
297 PK_INTEGER_FRACTION = 4
298
[167]299 def ProportionKind.valid_proportion_kind?(kind)
[139]300 return true if kind >= 0 && kind <= 4
301 return false
302 end
[167]303 end # end of ProportionKind
[147]304
[167]305 class DvProportion < DvAmount
306 include ProportionKind
[147]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
[148]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
[147]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)
[167]355 if ProportionKind.valid_proportion_kind?(type)
[147]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)
[167]381 unless other.instance_of?(DvProportion)
[147]382 return false
383 end
384 if other.type == @type
385 return true
386 else
387 return false
388 end
389 end
[167]390 end # end of DvProportion
[4]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.