class ContentOrderedEvaluator extends ContentFunctionEvaluator {

    @Override
    protected boolean evaluate(List<List<TermWeightPosition>> offsets) {
        if (offsets.isEmpty() || offsets.size() < terms.length) {
            return false;
        }
        
        NavigableSet<EvaluateTermPosition> termPositions = new TreeSet<>();
        int direction = FORWARD;
        
        // This is a little hokey, but because when the travers fails it falls back to looking for the first node
        // A short "first" or "last" list should make it fast.
        if (offsets.get(0).size() > offsets.get(offsets.size() - 1).size()) {
            direction = REVERSE;
        }
        
        int[] maxSkips = new int[terms.length];
        for (int i = 0; i < terms.length; i++) {
            int maxSkip = 0;
            for (TermWeightPosition twp : offsets.get(i)) {
                if (twp.getPrevSkips() > maxSkip) {
                    maxSkip = twp.getPrevSkips();
                }
                
                // Skip terms greater then the max score if it score is set
                if (twp.getScore() > maxScore) {
                    if (log.isTraceEnabled()) {
                        log.trace("[" + terms[i] + "] Skip score => " + twp);
                    }
                    continue;
                }
                
                EvaluateTermPosition etp = new EvaluateTermPosition(terms[i], i, twp);
                termPositions.add(etp);
            }
            maxSkips[i] = maxSkip;
        }
        
        // Low/High now needs to consider the distance of the skips
        EvaluateTermPosition[] lowHigh = getLowHigh(offsets, maxSkips);
        if (null == lowHigh) {
            return false;
        }
        termPositions = termPositions.subSet(lowHigh[0], true, lowHigh[1], true);
        
        if (log.isTraceEnabled()) {
            log.trace("Term Positions: " + termPositions);
        }
        
        // Number of matched terms
        termPositions = (direction == FORWARD) ? termPositions : termPositions.descendingSet();
        List<EvaluateTermPosition> found = traverse(termPositions, direction);
        
        if (null != found && found.size() == terms.length) {
            // to return offset => result.add(found.get(0).termWeightPosition.getOffset());
            return true;
        }
        
        // fail
        return false;
    }

    public  ContentOrderedEvaluator(Set<String> fields, int distance, float maxScore, Map<String,TermFrequencyList> termOffsetMap, String... terms);

}