lib/health-data-standards/models/entry.rb in health-data-standards-0.3.0 vs lib/health-data-standards/models/entry.rb in health-data-standards-0.5.0

- old
+ new

@@ -6,22 +6,48 @@ field :description, type: String field :time, type: Integer field :start_time, type: Integer field :end_time, type: Integer - field :status, type: Symbol - field :codes, type: Hash - field :value, type: Hash + field :status, type: String + field :codes, type: Hash, default: {} + field :value, type: Hash, default: {} def single_code_value? codes.size == 1 && codes.first[1].size == 1 end def codes_to_s codes.map {|code_set, codes| "#{code_set}: #{codes.join(', ')}"}.join(' ') end + # Will return a single code and code set if one exists in the code sets that are + # passed in. Returns a hash with a key of code and code_set if found, nil otherwise + def preferred_code(preferred_code_sets) + matching_code_sets = preferred_code_sets & codes.keys + if matching_code_sets.present? + code_set = matching_code_sets.first + {'code' => codes[code_set].first, 'code_set' => code_set} + else + nil + end + end + + # Will return an Array of code and code_set hashes for all codes for this entry + # except for the preferred_code. It is intended that these codes would be used in + # the translation elements as childern of a CDA code element + def translation_codes(preferred_code_sets) + tx_codes = [] + codes.each_pair do |code_set, code_list| + code_list.each do |code| + tx_codes << {'code' => code, 'code_set' => code_set} + end + end + + tx_codes - [preferred_code(preferred_code_sets)] + end + def times_to_s if start_time.present? || end_time.present? start_string = start_time ? Time.at(start_time).to_formatted_s(:long_ordinal) : 'UNK' end_string = end_time ? Time.at(end_time).to_formatted_s(:long_ordinal) : 'UNK' "#{start_string} - #{end_string}" @@ -45,7 +71,109 @@ else xml.high("nullFlavor" => "UNK") end end end + end + + def self.from_event_hash(event) + entry = Entry.new + if event['code'] + entry.add_code(event['code'], event['code_set']) + end + entry.time = event['time'] + if event['value'] + entry.set_value(event['value'], event['unit']) + end + if event['description'] + entry.description = event['description'] + end + if event['status'] + entry.status = event['status'] + end + entry + end + + # Add a code into the Entry + # @param [String] code the code to add + # @param [String] code_system the code system that the code belongs to + def add_code(code, code_system) + self.codes[code_system] ||= [] + self.codes[code_system] << code + end + + # Sets the value for the entry + # @param [String] scalar the value + # @param [String] units the units of the scalar value + def set_value(scalar, units=nil) + self.value[:scalar] = scalar + self.value[:units] = units + end + + # Checks if a code is in the list of possible codes + # @param [Array] code_set an Array of Hashes that describe the values for code sets + # @return [true, false] whether the code is in the list of desired codes + def is_in_code_set?(code_set) + codes.keys.each do |code_system| + all_codes_in_system = code_set.find_all {|set| set['set'] == code_system} + all_codes_in_system.each do |codes_in_system| + matching_codes = codes_in_system['values'] & codes[code_system] + if matching_codes.length > 0 + return true + end + end + end + false + end + + # Tries to find a single point in time for this entry. Will first return time if it is present, + # then fall back to start_time and finally end_time + def as_point_in_time + if time + time + elsif start_time + start_time + else + end_time + end + end + + # Checks to see if this Entry can be used as a date range + # @return [true, false] If the Entry has a start and end time returns true, false otherwise. + def is_date_range? + start_time.present? && end_time.present? + end + + # Checks to see if this Entry is usable for measure calculation. This means that it contains + # at least one code and has one of its time properties set (start, end or time) + # @return [true, false] + def usable? + codes.present? && (start_time.present? || end_time.present? || time.present?) + end + + # Creates a Hash for this Entry + # @return [Hash] a Hash representing the Entry + def to_hash + entry_hash = {} + entry_hash['codes'] = codes + unless value.empty? + entry_hash['value'] = value + end + + if is_date_range? + entry_hash['start_time'] = start_time + entry_hash['end_time'] = end_time + else + entry_hash['time'] = as_point_in_time + end + + if status + entry_hash['status'] = status + end + + if description + entry_hash['description'] = description + end + + entry_hash end end \ No newline at end of file