# Path: craft_ai/errors.py
# class CraftAiError(Exception):
#     """Base class for exceptions in the craft ai client."""
# 
#     def __init__(self, message=None, metadata=None):
#         self.message = message
#         self.metadata = metadata
#         super(CraftAiError, self).__init__(message, metadata)
# 
#     def __str__(self):
#         return repr(self.message)
# 
# Path: craft_ai/formatters.py
# def format_decision_rules(rules):
#     return " and ".join([_format_decision_rule(rule) for rule in rules])
# 
# Path: craft_ai/operators.py
# OPERATORS = OPERATORS_V2


from functools import reduce as ft_reduce
from .errors import CraftAiError
from .formatters import format_decision_rules
from .operators import OPERATORS
        #   |    op_1    |
        #      |  op_2  |
        return rule_2

    if op_2_from_in_op_1 and op_1_to_in_op_2:
        # overlap 1
        #       |    op_1    |
        #           |   op_2   |
        return {
            "property": rule_1["property"],
            "operator": OPERATORS["IN_INTERVAL"],
            "operand": [op_2_from, op_1_to],
        }

    if op_2_to_in_op_1 and op_1_from_in_op_2:
        # overlap 2
        #        |    op_1    |
        #     |   op_2   |
        return {
            "property": rule_1["property"],
            "operator": OPERATORS["IN_INTERVAL"],
            "operand": [op_1_from, op_2_to],
        }

    # disjointed
    #    |    op_1    |
    #                  |   op_2   |
    raise CraftAiError(
        """Unable to reduce decision rules '{}' and '{}': """
        """the resulting rule is not fulfillable.""".format(

# Path: craft_ai/errors.py
# class CraftAiError(Exception):
#     """Base class for exceptions in the craft ai client."""
# 
#     def __init__(self, message=None, metadata=None):
#         self.message = message
#         self.metadata = metadata
#         super(CraftAiError, self).__init__(message, metadata)
# 
#     def __str__(self):
#         return repr(self.message)
# 
# Path: craft_ai/formatters.py
# def format_decision_rules(rules):
#     return " and ".join([_format_decision_rule(rule) for rule in rules])
# 
# Path: craft_ai/operators.py
# OPERATORS = OPERATORS_V2


# Path: craft_ai/reducer.py
from functools import reduce as ft_reduce
from .errors import CraftAiError
from .formatters import format_decision_rules
from .operators import OPERATORS

        #   |    op_1    |
        #      |  op_2  |
        return rule_2

    if op_2_from_in_op_1 and op_1_to_in_op_2:
        # overlap 1
        #       |    op_1    |
        #           |   op_2   |
        return {
            "property": rule_1["property"],
            "operator": OPERATORS["IN_INTERVAL"],
            "operand": [op_2_from, op_1_to],
        }

    if op_2_to_in_op_1 and op_1_from_in_op_2:
        # overlap 2
        #        |    op_1    |
        #     |   op_2   |
        return {
            "property": rule_1["property"],
            "operator": OPERATORS["IN_INTERVAL"],
            "operand": [op_1_from, op_2_to],
        }

    # disjointed
    #    |    op_1    |
    #                  |   op_2   |
    raise CraftAiError(
        """Unable to reduce decision rules '{}' and '{}': """
        """the resulting rule is not fulfillable.""".format(

            format_decision_rules([rule_1]), format_decision_rules([rule_2])