@Override
  public Explanation explain(LeafReaderContext context, int doc) throws IOException {
    final Scorer s = scorer(context);
    final boolean exists;
    if (s == null) {
      exists = false;
    } else {
      final TwoPhaseIterator twoPhase = s.twoPhaseIterator();
      if (twoPhase == null) {
        exists = s.iterator().advance(doc) == doc;
      } else {
        exists = twoPhase.approximation().advance(doc) == doc && twoPhase.matches();
      }
    }

    if (exists) {
      return Explanation.match(
          queryWeight,
          getQuery().toString() + ", product of:",
          Explanation.match(boost, "boost"),
          Explanation.match(queryNorm, "queryNorm"));
    } else {
      return Explanation.noMatch(getQuery().toString() + " doesn't match id " + doc);
    }
  }
 /** Explain the score we computed for doc */
 @Override
 public Explanation explain(LeafReaderContext context, int doc) throws IOException {
   boolean match = false;
   float max = 0.0f, sum = 0.0f;
   List<Explanation> subs = new ArrayList<>();
   for (Weight wt : weights) {
     Explanation e = wt.explain(context, doc);
     if (e.isMatch()) {
       match = true;
       subs.add(e);
       sum += e.getValue();
       max = Math.max(max, e.getValue());
     }
   }
   if (match) {
     final float score = max + (sum - max) * tieBreakerMultiplier;
     final String desc =
         tieBreakerMultiplier == 0.0f
             ? "max of:"
             : "max plus " + tieBreakerMultiplier + " times others of:";
     return Explanation.match(score, desc, subs);
   } else {
     return Explanation.noMatch("No matching clause");
   }
 }