Skip to content

Commit

Permalink
Update math - plus and minus
Browse files Browse the repository at this point in the history
  • Loading branch information
atuonufure committed Jan 10, 2024
1 parent f5a6428 commit e4e3a12
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
19 changes: 13 additions & 6 deletions fhirpathpy/engine/invocations/math.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from decimal import Decimal
from fhirpathpy.engine.invocations.equality import remove_duplicate_extension
import fhirpathpy.engine.util as util
import fhirpathpy.engine.nodes as nodes

Expand Down Expand Up @@ -42,10 +43,13 @@ def amp(ctx, x="", y=""):
return x + y


def minus(ctx, xs, ys):
def minus(ctx, xs_, ys_):
xs = remove_duplicate_extension(xs_)
ys = remove_duplicate_extension(ys_)

if len(xs) == 1 and len(ys) == 1:
x = util.get_data(xs[0])
y = util.get_data(ys[0])
x = util.get_data(util.val_data_converted(xs[0]))
y = util.get_data(util.val_data_converted(ys[0]))

if util.is_number(x) and util.is_number(y):
return x - y
Expand Down Expand Up @@ -81,12 +85,15 @@ def mod(ctx, x, y):

# HACK: for only polymorphic function
# Actually, "minus" is now also polymorphic
def plus(ctx, xs, ys):
def plus(ctx, xs_, ys_):
xs = remove_duplicate_extension(xs_)
ys = remove_duplicate_extension(ys_)

if len(xs) != 1 or len(ys) != 1:
raise Exception("Cannot " + str(xs) + " + " + str(ys))

x = util.get_data(xs[0])
y = util.get_data(ys[0])
x = util.get_data(util.val_data_converted(xs[0]))
y = util.get_data(util.val_data_converted(ys[0]))

"""
In the future, this and other functions might need to return ResourceNode
Expand Down
46 changes: 39 additions & 7 deletions fhirpathpy/engine/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,14 @@ def deep_equal(self, other):
else:
if self.unit != other.unit:
converted = FP_Quantity.conv_unit_to(self.unit, self.value, other.unit)
reverse_converted = FP_Quantity.conv_unit_to(converted.unit, converted.value, self.unit)
reverse_converted = FP_Quantity.conv_unit_to(
converted.unit, converted.value, self.unit
)
if converted is not None:
return self.value == reverse_converted.value and self.unit == reverse_converted.unit
return (
self.value == reverse_converted.value
and self.unit == reverse_converted.unit
)
return self.__eq__(other)
else:
return super().__eq__(other)
Expand Down Expand Up @@ -257,7 +262,9 @@ def conv_unit_to(fromUnit, value, toUnit):
to_g_mg_magnitude = FP_Quantity._g_mg_conversion_factor.get(toUnit)
if from_g_mg_magnitude and to_g_mg_magnitude:
value = Decimal(value) * Decimal(FP_Quantity._g_mg_conversion_factor[fromUnit])
result = (value / Decimal(FP_Quantity._g_mg_conversion_factor[toUnit])).quantize(Decimal('1.'), rounding=ROUND_HALF_UP)
result = (value / Decimal(FP_Quantity._g_mg_conversion_factor[toUnit])).quantize(
Decimal("1."), rounding=ROUND_HALF_UP
)
return FP_Quantity(result, toUnit)
return None

Expand Down Expand Up @@ -528,6 +535,11 @@ def plus(self, time_quantity):
self._extractTimeByPrecision(result, precision if precision < 3 else 4) + dt_list[4]
)

@staticmethod
def check_string(cls, str_val):
val = cls(str_val)
return val


class FP_Time(FP_TimeBase):
matchGroupsIndices = [
Expand Down Expand Up @@ -667,7 +679,7 @@ def __init__(self, dateStr):
self._precision = self._calculatePrecision(self._dateTimeAsList)

def __str__(self):
if re.match(r'^\d{4}-\d{2}-\d{2}$', self.asStr):
if re.match(r"^\d{4}-\d{2}-\d{2}$", self.asStr):
return self.asStr
if self.asStr and len(self.asStr) <= 4:
return self.asStr
Expand Down Expand Up @@ -787,7 +799,7 @@ def get_type_info(self):
if not TypeInfo.model:
return TypeInfo.create_by_value_in_namespace(namespace=namespace, value=self.data)

return TypeInfo(namespace=namespace, name='BackboneElement')
return TypeInfo(namespace=namespace, name="BackboneElement")

def toJSON(self):
return json.dumps(self.data)
Expand All @@ -798,12 +810,25 @@ def create_node(data, path=None, _data=None):
return data
return ResourceNode(data, path, _data)

def convert_data(self):
data = self.data
cls = TypeInfo.type_to_class_with_check_string.get(self.path)
if cls:
data = FP_TimeBase.check_string(cls, data) or data
return data


class TypeInfo:
model = None
System = "System"
FHIR = "FHIR"

type_to_class_with_check_string = {
"date": FP_DateTime,
"dateTime": FP_DateTime,
"time": FP_Time,
}

def __init__(self, name, namespace):
self.name = name
self.namespace = namespace
Expand All @@ -813,8 +838,15 @@ def is_type(type_name, super_type):
while type_name:
if type_name == super_type:
return True
# TODO: Double check it
type_name = TypeInfo.model.get("type2Parent").get(type_name) or TypeInfo.model.get("path2Type").get(type_name)

if TypeInfo.model is not None:
parent_type = TypeInfo.model.get("type2Parent", {}).get(type_name)
if parent_type is None:
parent_type = TypeInfo.model.get("path2Type", {}).get(type_name)
type_name = parent_type
else:
return False

return False

def is_(self, other):
Expand Down
6 changes: 6 additions & 0 deletions fhirpathpy/engine/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,9 @@ def uniq(arr):
key = str(x)
ordered_dict[key] = x
return list(ordered_dict.values())

def val_data_converted(val):
if isinstance(val, ResourceNode):
val = val.convert_data()

return val

0 comments on commit e4e3a12

Please sign in to comment.