"""合成分组规则树:只接受声明节点,不执行任意表达式。""" import itertools import json tree = {"op": "and", "children": [ {"op": "or", "children": [{"leaf": "route_a"}, {"leaf": "route_b"}]}, {"op": "not", "children": [{"leaf": "suspended"}]}]} def evaluate(node, inputs): if "leaf" in node: value = inputs[node["leaf"]] if type(value) is not bool: raise ValueError("boolean_required") return value op, children = node["op"], node["children"] if op not in {"and", "or", "not"} or not children or (op == "not" and len(children) != 1): raise ValueError("invalid_node") values = [evaluate(child, inputs) for child in children] return all(values) if op == "and" else any(values) if op == "or" else not values[0] stocks = {"AAA": (True, False, False), "BBB": (False, True, False), "CCC": (True, True, False), "DDD": (True, False, True), "EEE": (False, False, False)} results = {symbol: evaluate(tree, dict(zip(("route_a", "route_b", "suspended"), flags))) for symbol, flags in stocks.items()} assert results == {"AAA": True, "BBB": True, "CCC": True, "DDD": False, "EEE": False} for a, b, suspended in itertools.product([False, True], repeat=3): assert evaluate(tree, {"route_a": a, "route_b": b, "suspended": suspended}) == ((a or b) and not suspended) wrong = {s: a or (b and not suspended) for s, (a, b, suspended) in stocks.items()} assert [s for s in results if results[s] != wrong[s]] == ["DDD"] try: evaluate({"op": "xor", "children": [{"leaf": "route_a"}]}, {"route_a": True}) except ValueError as exc: assert str(exc) == "invalid_node" else: raise AssertionError("未知节点必须拒绝") print(json.dumps({"passed": sorted(s for s, v in results.items() if v), "truth": results, "changed_by_wrong_grouping": ["DDD"], "boolean_combinations_checked": 8}, sort_keys=True))