public boolean evaluate(
        InternalWorkingMemory workingMemory,
        final InternalReadAccessor extractor1,
        final Object object1,
        final InternalReadAccessor extractor2,
        final Object object2) {
      if (extractor1.isNullValue(workingMemory, object1)) {
        return false;
      }

      long obj1StartTS = -1;
      long obj1EndTS = -1;
      long obj2StartTS = -1;
      long obj2EndTS = -1;

      DefaultFactHandle obj1FH = (DefaultFactHandle) object1;

      if (obj1FH instanceof EventFactHandle) {
        obj1StartTS = ((EventFactHandle) obj1FH).getStartTimestamp();
        obj1EndTS = ((EventFactHandle) obj1FH).getEndTimestamp();
      } else {
        Object obj1Fact = workingMemory.getObject(obj1FH);
        if (obj1Fact instanceof SituationType) {
          obj1StartTS = ((SituationType) obj1Fact).getActivation().getTimestamp();
          if (!((SituationType) obj1Fact).isActive()) {
            obj1EndTS = ((SituationType) obj1Fact).getDeactivation().getTimestamp();
          }
        }
      }

      DefaultFactHandle obj2FH = (DefaultFactHandle) object2;

      if (obj2FH instanceof EventFactHandle) {
        obj2StartTS = ((EventFactHandle) obj2FH).getStartTimestamp();
        obj2EndTS = ((EventFactHandle) obj2FH).getEndTimestamp();
      } else {
        Object obj2Fact = workingMemory.getObject(obj2FH);
        if (obj2Fact instanceof SituationType) {
          obj2StartTS = ((SituationType) obj2Fact).getActivation().getTimestamp();
          // includes is not applicable when situationB is not finished
          if (!((SituationType) obj2Fact).isActive()) {
            obj2EndTS = ((SituationType) obj2Fact).getDeactivation().getTimestamp();
          } else return false;
        }
      }

      long distStart = obj2StartTS - obj1StartTS;
      if (obj1EndTS == (-1)) {
        return this.getOperator().isNegated()
            ^ (distStart >= this.startMinDev && distStart <= this.startMaxDev);
      } else {
        long distEnd = obj1EndTS - obj2EndTS;
        return this.getOperator().isNegated()
            ^ (distStart >= this.startMinDev
                && distStart <= this.startMaxDev
                && distEnd >= this.endMinDev
                && distEnd <= this.endMaxDev);
      }
    }
    public boolean evaluateCachedLeft(
        InternalWorkingMemory workingMemory,
        final VariableContextEntry context,
        final Object right) {
      if (context.extractor.isNullValue(workingMemory, right)) {
        return false;
      }

      long leftStartTS = -1;
      long leftEndTS = -1;
      long rightStartTS = -1;
      long rightEndTS = -1;

      DefaultFactHandle leftFH = (DefaultFactHandle) ((ObjectVariableContextEntry) context).left;

      if (leftFH instanceof EventFactHandle) {
        leftStartTS = ((EventFactHandle) leftFH).getStartTimestamp();
        leftEndTS = ((EventFactHandle) leftFH).getEndTimestamp();
      } else {
        Object leftFact = workingMemory.getObject(leftFH);
        if (leftFact instanceof SituationType) {
          leftStartTS = ((SituationType) leftFact).getActivation().getTimestamp();
          // includes is not applicable when situationB not finished
          if (!((SituationType) leftFact).isActive()) {
            leftEndTS = ((SituationType) leftFact).getDeactivation().getTimestamp();
          } else return false;
        }
      }

      DefaultFactHandle rightFH = (DefaultFactHandle) right;

      if (rightFH instanceof EventFactHandle) {
        rightStartTS = ((EventFactHandle) rightFH).getStartTimestamp();
        rightEndTS = ((EventFactHandle) rightFH).getEndTimestamp();
      } else {
        Object rightFact = workingMemory.getObject(rightFH);
        if (rightFact instanceof SituationType) {
          rightStartTS = ((SituationType) rightFact).getActivation().getTimestamp();
          if (!((SituationType) rightFact).isActive()) {
            rightEndTS = ((SituationType) rightFact).getDeactivation().getTimestamp();
          }
        }
      }

      long distStart = leftStartTS - rightStartTS;

      if (rightEndTS == (-1)) {
        return this.getOperator().isNegated()
            ^ (distStart >= this.startMinDev && distStart <= this.startMaxDev);
      } else {
        long distEnd = rightEndTS - leftEndTS;
        return this.getOperator().isNegated()
            ^ (distStart >= this.startMinDev
                && distStart <= this.startMaxDev
                && distEnd >= this.endMinDev
                && distEnd <= this.endMaxDev);
      }
    }