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, 11 years ago

move ReferenceRange? test to rspec

File size: 12.7 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            self.normal_range = args[:normal_range]
15            self.normal_status = args[:normal_status]
16            self.other_reference_ranges = args[:other_reference_ranges]
17          end         
18
19          def is_normal?
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
27          end
28
29          def is_simple?
30            return @other_reference_ranges.nil?
31          end
32
33          def <=>(other)
34            raise NotImplementedError, 'This method should be implemented'
35          end
36
37          def other_reference_ranges=(other_reference_ranges)
38            if !other_reference_ranges.nil? && other_reference_ranges.empty?
39              raise ArgumentError, "Other reference ranges validity error"
40            end
41            @other_reference_ranges = other_reference_ranges
42          end
43
44          def is_strictly_comparable_to?(other)
45            raise NotImplementedError, 'this method should be implemented'
46          end
47        end
48
49        class DvInterval < OpenEHR::AssumedLibraryTypes::Interval
50
51        end
52
53        class DvQuantified < DvOrdered
54          attr_reader :magnitude, :magnitude_status
55
56          def initialize(magnitude, magnitude_status=nil,
57                         normal_range=nil, normal_status = nil,
58                         other_reference_ranges=nil)
59            super(normal_range, normal_status, other_reference_ranges)
60            self.magnitude = magnitude
61            self.magnitude_status = magnitude_status
62          end
63
64          def <=>(others)
65            @value <=> others.value
66          end
67
68          def magnitude=(magnitude)
69            raise ArgumentError, 'magnitude should not be nil' if magnitude.nil?
70            @magnitude = magnitude
71          end
72
73          def magnitude_status=(magnitude_status)
74            if magnitude_status.nil?
75              @magnitude_status = '='
76            elsif DvQuantified.valid_magnitude_status?(magnitude_status)
77              @magnitude_status = magnitude_status
78            else
79              raise ArgumentError, 'magnitude_status invalid'
80            end
81          end
82
83          def accuracy_unknown?
84            return @accuracy.nil?
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
95        end
96
97        class DvOrdinal < DvOrdered
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)
106          end
107
108          def value=(value)
109            raise ArgumentError, 'value should not be nil' if value.nil?
110            @value = value
111          end
112
113          def symbol=(symbol)
114            raise ArgumentError,'symbol should not be nil' if symbol.nil?
115            @symbol = symbol
116          end
117
118          def is_strictly_comparable_to?(others)
119            unless others.instance_of? OpenEHR::RM::DataTypes::Quantity::DvOrdinal
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
129          def <=>(other)
130            @value <=> other.value
131          end
132
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
139          end
140        end
141
142        class DvAbsoluteQuantity < DvQuantified
143          attr_accessor :accuracy
144
145          def initialize(magnitude, magnitude_status=nil, accuracy=nil,
146                         normal_range=nil, normal_status = nil,
147                         other_reference_ranges=nil)
148            super(magnitude, magnitude_status, normal_range,
149                   normal_status, other_reference_ranges)
150            self.accuracy = accuracy
151          end
152
153          def add(a_diff)
154            raise NotImplementedError, 'add must be implemented'
155          end
156
157          def diff(other)
158            raise NotImplementedError, 'diff must be implemented'
159          end
160
161          def subtract(a_diff)
162            raise NotImplementedError, 'subtract must be implemented'
163          end
164        end
165
166        class DvAmount < DvQuantified
167          attr_reader :accuracy, :accuracy_percent
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)
173            unless accuracy.nil?
174              set_accuracy(accuracy, 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            return DvAmount.new(@magnitude+other.magnitude, @magnitude_status,
185                                 @accuracy, @accuracy_percent, @normal_range,
186                                 @normal_status, @other_reference_ranges)
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          def is_strictly_comparable_to?(others)
259            return false if others.nil?
260            if others.instance_of?(DvCount)
261              return true
262            else
263              return false
264            end
265          end
266        end
267
268        class ReferenceRange
269          attr_reader :meaning, :range
270
271          def initialize(args = {})
272            self.meaning = args[:meaning]
273            self.range = args[:range]
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
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
293        end
294
295        module ProportionKind
296          PK_RATIO = 0
297          PK_UNITARY = 1
298          PK_PERCENT = 2
299          PK_FRACTION = 3
300          PK_INTEGER_FRACTION = 4
301
302          def ProportionKind.valid_proportion_kind?(kind)
303            return true if kind >= 0 && kind <= 4
304            return false
305          end
306        end # end of ProportionKind
307
308        class DvProportion < DvAmount
309          include ProportionKind
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
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
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)
358            if ProportionKind.valid_proportion_kind?(type)
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)
384            unless other.instance_of?(DvProportion)
385              return false
386            end
387            if other.type == @type
388              return true
389            else
390              return false
391            end
392          end
393        end # end of DvProportion
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.