app/assets/javascripts/specifics.js.coffee in hqmf2js-1.2.1 vs app/assets/javascripts/specifics.js.coffee in hqmf2js-1.3.0

- old
+ new

@@ -39,11 +39,15 @@ product , [[]]) identity: -> new hqmf.SpecificOccurrence([new Row(undefined)]) - + + setIfNull: (events,subsets) -> + if (!events.specificContext? || events.length == 0) + events.specificContext=hqmf.SpecificsManager.identity() + getColumnIndex: (occurrenceID) -> columnIndex = @indexLookup[occurrenceID] if typeof columnIndex == "undefined" throw "Unknown occurrence identifier: "+occurrenceID columnIndex @@ -52,11 +56,11 @@ new hqmf.SpecificOccurrence([]) extractEventsForLeftMost: (rows) -> events = [] for row in rows - events.push(@extractEvent(row.leftMost, row)) + events.push(@extractEvent(row.leftMost, row)) if row.leftMost? || row.tempValue? events extractEvents: (key, rows) -> events = [] for row in rows @@ -141,21 +145,29 @@ if value.specificContext? and (value.isTrue() or negate) result = result.union(value.specificContext) if value.specificContext? if negate and (!result.hasRows() or result.hasSpecifics()) result = result.negate() - # this is a little odd, but it appears when we have a negation with specifics we can ignore the logical result of the negation. See comment in intersectAll. + # this is a little odd, but it appears when we have a negation with specifics we can + # ignore the logical result of the negation. See comment in intersectAll. # we need to verify that we actually have some occurrences boolVal = new Boolean(true) if @occurrences.length > 0 boolVal.specificContext = result boolVal # copy the specifics parameters from an existing element onto the new value element maintainSpecifics: (newElement, existingElement) -> newElement.specificContext = existingElement.specificContext newElement.specific_occurrence = existingElement.specific_occurrence newElement + + flattenToIds: (specificContext) -> + specificContext?.flattenToIds() || [] + + storeFinal: (key, result, target) -> + target[key] = hqmf.SpecificsManager.flattenToIds(result.specificContext) + @hqmf.SpecificsManager = new hqmf.SpecificsManagerSingleton class hqmf.SpecificOccurrence constructor: (rows=[])-> @@ -192,11 +204,21 @@ uniqueEvents: (columnIndices) -> eventIds = [] for columnIndex in columnIndices for row in @rows event = row.values[columnIndex] - eventIds.push(event.id) if event != hqmf.SpecificsManager.any and not (event.id in eventIds) + if event != hqmf.SpecificsManager.any and not (event.id in eventIds) + onlyOneMatch = true + # we want to check that we do not have multiple episodes of care matching on this row. If we do, then that means + # that we have a reliance on multiple episodes of care for this row when we can only rely on one. If we have multiple + # then we want to disregard this row. + if (columnIndices.length > 1) + for columnIndexInside in columnIndices + onlyOneMatch = false if (columnIndexInside != columnIndex and row.values[columnIndexInside] != hqmf.SpecificsManager.any) + + if onlyOneMatch + eventIds.push(event.id) eventIds.length hasExactRow: (other) -> for row in @rows return true if row.equals(other) @@ -322,24 +344,35 @@ LAST: -> @applySubset(LAST) RECENT: -> @applySubset(RECENT) + + hasLeftMost: -> + for row in @rows + if row.leftMost? || row.tempValue? + return true + return false applySubset: (func) -> - return this if !@hasSpecifics() + return this if !@hasSpecifics() || !@hasLeftMost() resultRows = [] groupedRows = @group() for groupKey, group of groupedRows entries = func(hqmf.SpecificsManager.extractEventsForLeftMost(group)) - if entries.length > 0 - resultRows.push(entries[0].specificRow) + resultRows.push(entry.specificRow) for entry in entries new hqmf.SpecificOccurrence(resultRows) addIdentityRow: -> @addRows(hqmf.SpecificsManager.identity().rows) + flattenToIds: -> + result = [] + for row in @rows + result.push(row.flattenToIds()) + result + class Row # {'OccurrenceAEncounter':1, 'OccurrenceBEncounter'2} constructor: (leftMost, occurrences={}) -> throw "left most key must be a string or undefined was: #{leftMost}" if typeof(leftMost) != 'string' and typeof(leftMost) != 'undefined' @length = hqmf.SpecificsManager.occurrences.length @@ -436,28 +469,41 @@ # build specific for an entry given matching rows (with temporal references) @buildRowsForMatching: (entryKey, entry, matchesKey, matches) -> rows = [] for match in matches - occurrences={} - occurrences[entryKey] = entry + # from unions and crossproducts we may have a matches key that is a hash of object ids mapped to the specific occurrence key. # this is because we may have multiple different specific occurrences on the right hand side if it came from a group - if (_.isObject(matchesKey)) - occurrences[matchesKey[match.id]] = match - else - occurrences[matchesKey] = match - rows.push(new Row(entryKey, occurrences)) + # we may also have the same event mapping to multiple occurrences, so if we have a hash the value will be an array. + # we make both the UNION and CROSS casses look the same as the standard case by turning the standard into an array + matchKeys = (if _.isObject(matchesKey) then matchesKey[match.id] else [matchesKey]) + if (matchKeys) + for matchKey in matchKeys + occurrences = {} + occurrences[entryKey] = entry + occurrences[matchKey] = match + rows.push(new Row(entryKey, occurrences)) rows # build specific for a given entry (there are no temporal references) @buildForDataCriteria: (entryKey, entries) -> rows = [] for entry in entries occurrences={} occurrences[entryKey] = entry rows.push(new Row(entryKey, occurrences)) rows + + flattenToIds: -> + result = [] + for value in @values + if (value == hqmf.SpecificsManager.any) + result.push(value) + else + result.push(value.id) + result + @Row = Row ### Wrap methods to maintain specificContext and specific_occurrence