bryan-stearns
Fixing print for prim-exists obj class
9bedfdd
from collections import defaultdict
from enum import Enum
class SMEM_Obj():
def __init__(self):
self.processed = False
self.obj_type = None
self.id_var = None
self.class_str = None
self.wme_list = []
self.description = None
def set_id_var(self, var):
self.id_var = var
def add_wme(self, attr, val):
self.wme_list.append((attr,val))
def get_class(self):
if self.class_str != None:
return self.class_str
for (attr,val) in self.wme_list:
if attr == "^class":
self.class_str = val
break
return self.class_str
def get_description(self):
if self.description != None:
return self.description
# Search for the description
for (attr,val) in self.wme_list:
if attr == "^description":
self.description = val
break
return self.description
def get_referenced_features(self, dict_of_values=None):
# Collect a map of feature fields to possible values, as referenced by descendants from this object
if not dict_of_values:
dict_of_values = defaultdict(set)
children = self.get_child_objects(compact=False)
for child in children:
_, short_label, desc = child.to_string()
# Trim the label based on the object type
if child.get_class() == "prim":
if desc and desc != "()":
str_to_use = desc
try:
ind = str_to_use.index(" is ")
feature, value = str_to_use.replace("(","").replace(")","").split(" is ",maxsplit=1)
dict_of_values[feature].add(value)
except:
print("ERROR: str_to_use missing 'is'. Value was: '"+str(str_to_use)+"'")
else:
str_to_use = short_label
try:
ind = str_to_use.index(" = ")
feature, value = str_to_use.replace("(","").replace(")","").split(" = ",maxsplit=1)
dict_of_values[feature].add(value)
except:
print("ERROR: str_to_use missing '='. Value was: '"+str(str_to_use)+"'")
# Merge this dict of sets with results from each branch of children
child_dict = child.get_referenced_features(dict_of_values)
for key, val in child_dict.items():
if key in dict_of_values:
dict_of_values[key].update(val)
else:
dict_of_values[key] = val
return dict_of_values
def get_compact_printable_object(self):
""" Return this object if printable in compact mode, else return the set of next printable descendants.
"""
if self.obj_type == None:
print("Warning: No obj_type for obj '"+self.id_var+"' in get_compact_printable_object().")
return None
retval = set()
returnSelf = False
if self.obj_type == ObjType.COND_PRIM:
for (attr,val) in self.wme_list:
if attr == "^supplies-condition":
val.obj_type = ObjType.COND_CONJ
retval.update(val.get_compact_printable_object())
elif self.obj_type == ObjType.COND_CONJ:
for (attr,val) in self.wme_list:
if attr == "^satisfies-op":
val.obj_type = ObjType.OP
returnSelf = True
break
elif attr == "^activates-context":
val.obj_type = ObjType.CONTEXT
returnSelf = True
break
elif attr == "^supplies-condition":
val.obj_type = ObjType.COND_CONJ
retval.update(val.get_compact_printable_object())
elif self.obj_type == ObjType.CONTEXT:
for (attr,val) in self.wme_list:
if attr == "^primes-condition":
val.obj_type = ObjType.COND_PRIM
retval.update(val.get_compact_printable_object())
else:
returnSelf = True
if returnSelf:
retval = set()
retval.add(self)
return retval
def get_child_objects(self, compact=True):
""" If compact=True, skip condition prims and contexts, only get conjunctions and action groups
"""
if self.obj_type == None:
print("Warning: No obj_type for obj '"+self.id_var+"'")
return None
retval = set()
for (attr,val) in self.wme_list:
if self.obj_type == ObjType.CONTEXT:
if attr == "^primes-condition":
val.obj_type = ObjType.COND_PRIM
if compact:
retval.update(val.get_compact_printable_object())
else:
retval.add(val)
elif self.obj_type == ObjType.COND_PRIM:
if attr == "^supplies-condition":
val.obj_type = ObjType.COND_CONJ
if compact:
retval.update(val.get_compact_printable_object())
else:
retval.add(val)
elif self.obj_type == ObjType.COND_CONJ:
if attr == "^satisfies-op":
val.obj_type = ObjType.OP
retval.add(val)
elif attr == "^activates-context":
val.obj_type = ObjType.CONTEXT
if compact:
retval.update(val.get_compact_printable_object())
else:
retval.add(val)
elif attr == "^supplies-condition":
val.obj_type = ObjType.COND_CONJ
if compact:
retval.update(val.get_compact_printable_object())
else:
retval.add(val)
elif self.obj_type == ObjType.OP:
if attr == "^activates-action":
val.obj_type = ObjType.ACT_GROUP
retval.add(val)
elif self.obj_type == ObjType.ACT_GROUP:
if attr == "^action":
val.obj_type = ObjType.ACT_PRIM
retval.add(val)
return retval
def get_prim_cond_string(self, negate=False):
if len(self.wme_list) == 0:
return "", ""
if negate:
if self.class_str == "prim-exists":
op_join_str = " not provided"
else:
op_join_str = " is not "
else:
if self.class_str == "prim-exists":
op_join_str = " provided"
else:
op_join_str = " is "
if self.class_str == None:
self.get_class()
retval_long, retval_short, retval_desc = ["(", "(", None]
if self.class_str == "prim" or self.class_str == "prim-exists":
group_str, attr_str, val_str = ["","",""]
for (attr,val) in self.wme_list:
if attr == "^group":
group_str = val
elif attr == "^attribute":
attr_str = val
elif attr == "^value":
val_str = val
elif attr == "^description":
self.description = val
retval_desc = val
retval_long += group_str+"."+attr_str+op_join_str+val_str
retval_short += attr_str+op_join_str+val_str
return retval_long+")", retval_short+")", retval_desc
def get_cond_string(self):
retval_long, retval_short, retval_desc = ["","",None]
# Compile the parent prim descriptions
parent_conds = []
# child_conjs = []
is_negation = (self.get_class() == "negation")
for (attr,val) in self.wme_list:
if attr == "^receives-condition":
parent_conds.append(val)
if attr == "^description":
self.description = val
retval_desc = val
# if attr == "^supplies-condition":
# child_conjs.append(val)
compile_component_descs = (retval_desc == None)
if compile_component_descs:
retval_desc = ""
for i,cond in enumerate(parent_conds):
if i > 0:
retval_long += " \nAND "
retval_short += " AND "
if compile_component_descs:
retval_desc += " AND "
if cond.obj_type == ObjType.COND_CONJ:
long, short, desc = cond.get_cond_string()
else:
long, short, desc = cond.get_prim_cond_string(negate=is_negation)
retval_long += long
retval_short += short
if compile_component_descs:
if desc:
retval_desc += "("+desc+")"
else:
retval_desc = None
compile_component_descs = False
return retval_long, retval_short, retval_desc
def get_op_string(self):
retval_long, retval_short, retval_desc = ["", "", None]
numeric_pref = None
for (attr,val) in self.wme_list:
if attr == "^name":
retval_long = val
retval_short = val
elif attr == "^numeric-preference":
try:
numeric_pref = str(float(val)*100)+"%"
except Exception as e:
print("ERROR in get_op_string() converting numeric_pref to string: "+str(e))
numeric_pref = None
elif attr == "^description":
self.description = val
retval_desc = val
if numeric_pref:
retval_long += "\nPercentage: "+numeric_pref
# print(self.id_var+": "+retval)
return retval_long, retval_short, retval_desc
def get_prim_act_string(self):
if len(self.wme_list) == 0:
return ""
if self.class_str == None:
self.get_class()
retval_long = "("
retval_short = "("
if self.class_str == "prim":
type_str, attr_str, val_str = ["","",""]
for (attr,val) in self.wme_list:
if attr == "^type":
type_str = val
elif attr == "^attribute":
attr_str = val
elif attr == "^value":
val_str = val
retval_long += type_str+"."+attr_str+" = "+val_str
retval_short += attr_str+" = "+val_str
elif self.class_str == "prim-message":
type_str, flag_str, msg_str = ["","",""]
for (attr,val) in self.wme_list:
if attr == "^type":
type_str = val
elif attr == "^flag":
flag_str = val
elif attr == "^message":
msg_str = val
retval_long += type_str+".flag = "+flag_str+" AND "+type_str+'.message = "'+msg_str+'"'
retval_short += 'message: "'+msg_str+'"'
return retval_long+")", retval_short+")"
def get_act_group_string(self):
retval_long, retval_short, retval_desc = ["", "", None]
# Compile the child prim action descriptions
child_prims = []
for (attr,val) in self.wme_list:
if attr == "^action":
child_prims.append(val)
elif attr == "^description":
self.description = val
retval_desc = val
for i,prim in enumerate(child_prims):
if i > 0:
retval_long += " AND "
retval_short += " AND "
long, short = prim.get_prim_act_string()
retval_long += long
retval_short += short
return retval_long, retval_short, retval_desc
def to_string(self):
long = self.id_var
short = self.id_var
description = None
if self.obj_type == ObjType.CONTEXT:
return "", "", self.get_description()
if self.obj_type == ObjType.COND_PRIM:
long, short, description = self.get_prim_cond_string()
# long = "IF "+long
# short = "IF "+short
if self.obj_type == ObjType.COND_CONJ:
long, short, description = self.get_cond_string()
if self.obj_type == ObjType.OP:
long, short, description = self.get_op_string()
if self.obj_type == ObjType.ACT_GROUP:
long, short, description = self.get_act_group_string()
if self.obj_type == ObjType.ACT_PRIM:
long, short = self.get_prim_act_string()
return long, short, description
class ObjType(Enum):
CONTEXT = 0
COND_PRIM = 1
COND_CONJ = 2
OP = 3
ACT_GROUP = 4
ACT_PRIM = 5