/*-
 * #%L
 * JSQLParser library
 * %%
 * Copyright (C) 2004 - 2019 JSQLParser
 * %%
 * Dual licensed under GNU LGPL 2.1 or Apache License 2.0
 * #L%
 */
package net.sf.jsqlparser.util.cnfexpression;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

public class CNFTest {

    /**
     * The purpose of this method is to check when there is a Not Operator at the root. Which means the root must be
     * switched.
     *
     * Here is the expression tree:
     *
     * NOT | ( ) | AND / \ ( ) ( ) | | OR OR / \ / \
     * <               =             != >= / \ / \ / \ / \ 1.2 2.3 3.5 4.6 1.1 2.5 8.0 7.2
     *
     * Here is the converted expression tree:
     *
     * AND / \ AND ( ) / \ | AND ( ) OR / \ | / \ ( ) ( ) OR NOT NOT | | / \ | | OR OR NOT NOT = >= / \ / \ | | / \ / \
     * NOT NOT NOT NOT = != 3.5 4.6 8.0 7.2 | | | | / \ / \ < !=           < >= / \ / \ / \ / \ 1.2 2.3 1.1 2.5 1.2 2.3 8.0 7.2
     *
     */
    @Test
    public void test1() throws Exception {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "NOT ((1.2 < 2.3 OR 3.5 = 4.6) AND (1.1 <> 2.5 OR 8.0 >= 7.2))");
        Expression expected = CCJSqlParserUtil.parseCondExpression(
                "(NOT 1.2 < 2.3 OR NOT 1.1 <> 2.5) AND (NOT 1.2 < 2.3 OR NOT 8.0 >= 7.2) AND"
                + " (NOT 3.5 = 4.6 OR NOT 1.1 <> 2.5) AND (NOT 3.5 = 4.6 OR NOT 8.0 >= 7.2)");
        Expression result = CNFConverter.convertToCNF(expr);
        assertEquals(expected.toString(), result.toString());
    }

    /**
     * The purpose is to test the double negation law. As you can see when you build the tree, there will be two Not
     * Operators together on the line. It is there when we use the double negation law.
     *
     * Here is the expression tree: ( ) | OR / \ ( ) ( ) | | NOT AND | / \ ( ) LIKE = | / \ / \ OR S.A "%%%" S.B "orz" /
     * \ NOT        <
     *                |       /   \
     * >= 3.3 4.5 / \ 1.1 2.3
     *
     * Here is the converted expression tree:
     *
     * AND / \ AND ( ) / \ | AND ( ) OR / \ | / \ ( ) ( ) OR NOT = | | / \ | / \ OR OR NOT LIKE       <           S.B   "orz"
     *       /         \             /       \       |      /      \   /   \
     * >= LIKE >= = < S.A "%%%" 3.3 4.5 / \ / \ / \ / \ 1.1 2.3 S.A "%%%" 1.1 2.3 S.B "orz"
     *
     */
    @Test
    public void test2() throws Exception {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "((NOT (NOT 1.1 >= 2.3 OR 3.3 < 4.5)) OR "
                + "(S.A LIKE '\"%%%\"' AND S.B = '\"orz\"'))");
        Expression expected = CCJSqlParserUtil.parseCondExpression(
                "(1.1 >= 2.3 OR S.A LIKE '\"%%%\"') AND (1.1 >= 2.3 OR S.B = '\"orz\"')"
                + " AND (NOT 3.3 < 4.5 OR S.A LIKE '\"%%%\"') AND (NOT 3.3 < 4.5 OR S.B = '\"orz\"')");
        Expression result = CNFConverter.convertToCNF(expr);
        assertEquals(expected.toString(), result.toString());
    }

    /**
     * This is the case when we test a more complex tree structure, Notice you could see the amount of line to build up
     * the CNF tree. You could tell how complicated the CNF could be.
     *
     * OR / \ ( ) ( ) | | AND OR / \ / \ >= <= ( ) NOT / \ / \ | | 7.0 8.0 9.0 10.0 AND OR / \ / \ ( ) = != ( ) | / \ /
     * \ | AND 11.0 12.0 13.0 14.0 AND / \ / \ < > = ( )
     *                               / \ / \ / \ |
     * 7.0 8.0 9.0 10.0 15.0 16.0 OR / \ = > / \ / \ 17.0 18.0 19.0 20.0
     *
     * Here is the converted expression tree:
     *
     * AND / \ AND ( ) / \ | AND ( ) part18 / \ | AND ( ) part17 / \ | AND ( ) part16 / \ | AND ( ) part15 / \ | AND ( )
     * part14 / \ | AND ( ) part13 / \ | AND ( ) part12 / \ | AND ( ) part11 / \ | AND ( ) part10 / \ | AND ( ) part9 /
     * \ | AND ( ) part8 / \ | AND ( ) part7 / \ | AND ( ) part6 / \ | AND ( ) part5 / \ | AND ( ) part4 / \ | ( ) ( )
     * part3 | | part1 part2
     *
     * part1: OR / \ OR NOT / \ | >=     <        !=
     *                         /     \  /   \    /   \
     *                        3.0   4.0 7.0 8.0 13.0 14.0
     *
     *     part2:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       17.0   18.0
     *              /        \   /    \   /   \
     *             3.0      4.0 7.0  8.0 15.0 16.0
     *
     *     part3:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       19.0   20.0
     *              /        \   /    \   /   \
     *             3.0      4.0 7.0  8.0 15.0 16.0
     *
     *     part4:                            OR
     *                                 /          \
     *                                OR          NOT
     *                             /     \         |
     * >=     <        !=
     *                         /     \  /   \    /   \
     *                        3.0   4.0 9.0 10.0 13.0 14.0
     *
     *     part5:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       17.0   18.0
     *              /        \   /    \   /   \
     *             3.0      4.0 9.0  10.0 15.0 16.0
     *
     *     part6:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       19.0   20.0
     *              /        \   /    \   /   \
     *             3.0      4.0 9.0  10.0 15.0 16.0
     *
     *     part7:                            OR
     *                                 /            \
     *                                OR            NOT
     *                             /     \           |
     * >=     <          !=
     *                         /     \  /    \      /   \
     *                        3.0   4.0 11.0 12.0 13.0 14.0
     *
     *     part8:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       17.0   18.0
     *              /        \   /    \   /   \
     *             3.0      4.0 11.0  12.0 15.0 16.0
     *
     *     part9:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       19.0   20.0
     *              /        \   /    \   /   \
     *             3.0      4.0 11.0  12.0 15.0 16.0
     *
     *     part10:                           OR
     *                                 /          \
     *                                OR          NOT
     *                             /     \         |
     * >=     <        !=
     *                         /     \  /   \    /   \
     *                        5.0   6.0 7.0 8.0 13.0 14.0
     *
     *     part11:                            OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       17.0   18.0
     *              /        \   /    \   /   \
     *             5.0      6.0 7.0  8.0 15.0 16.0
     *
     *     part12:                            OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       19.0   20.0
     *              /        \   /    \   /   \
     *             5.0      6.0 7.0  8.0 15.0 16.0
     *
     *     part13:                           OR
     *                                 /          \
     *                                OR          NOT
     *                             /     \         |
     * >=     <        !=
     *                         /     \  /   \    /   \
     *                        5.0   6.0 9.0 10.0 13.0 14.0
     *
     *     part14:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       17.0   18.0
     *              /        \   /    \   /   \
     *             5.0      6.0 9.0  10.0 15.0 16.0
     *
     *     part15:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       19.0   20.0
     *              /        \   /    \   /   \
     *             5.0      6.0 9.0  10.0 15.0 16.0
     *
     *     part16:                            OR
     *                                 /            \
     *                                OR            NOT
     *                             /     \           |
     * >=     <          !=
     *                         /     \  /    \      /   \
     *                        5.0   6.0 11.0 12.0 13.0 14.0
     *
     *     part17:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >=         <        =       17.0   18.0
     *              /        \   /    \   /   \
     *             5.0      6.0 11.0  12.0 15.0 16.0
     *
     *     part18:                             OR
     *                                /                \
     *                               OR                NOT
     *                         /           \            |
     *                        OR           NOT          =
     *                   /         \        |        /     \
     * >= < = 19.0 20.0 / \ / \ / \ 5.0 6.0 11.0 12.0 15.0 16.0
     *
     */
    @Test
    public void test3() throws Exception {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "(3.0 >= 4.0 AND 5.0 <= 6.0) OR "
                + "(((7.0 < 8.0 AND 9.0 > 10.0) AND 11.0 = 12.0) OR "
                + "NOT (13.0 <> 14.0 OR (15.0 = 16.0 AND (17.0 = 18.0 OR 19.0 > 20.0))))");
        Expression expected = CCJSqlParserUtil.parseCondExpression(
                "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 13.0 <> 14.0) AND "
                + "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND "
                + "(3.0 >= 4.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND "
                + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 13.0 <> 14.0) AND "
                + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND "
                + "(3.0 >= 4.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND "
                + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 13.0 <> 14.0) AND "
                + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND "
                + "(3.0 >= 4.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND "
                + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 13.0 <> 14.0) AND "
                + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND "
                + "(5.0 <= 6.0 OR 7.0 < 8.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND "
                + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 13.0 <> 14.0) AND "
                + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND "
                + "(5.0 <= 6.0 OR 9.0 > 10.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0) AND "
                + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 13.0 <> 14.0) AND "
                + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 17.0 = 18.0) AND "
                + "(5.0 <= 6.0 OR 11.0 = 12.0 OR NOT 15.0 = 16.0 OR NOT 19.0 > 20.0)");
        Expression result = CNFConverter.convertToCNF(expr);
        assertEquals(expected.toString(), result.toString());
    }

    /**
     * This is the case when we test a very simple tree structure that has neither AND operator or OR operator.
     *
     * Here is the expression tree:
     *
     * NOT | > / \ S.D {d '2017-03-25'}
     *
     * Here is the converted expression tree:
     *
     * NOT | > / \ S.D {d '2017-03-25'}
     *
     */
    @Test
    public void test4() throws Exception {
        Expression expr = CCJSqlParserUtil.parseCondExpression("NOT S.D > {d '2017-03-25'}");
        Expression expected = CCJSqlParserUtil.parseCondExpression("NOT S.D > {d '2017-03-25'}");
        Expression result = CNFConverter.convertToCNF(expr);
        assertEquals(expected.toString(), result.toString());
    }

    /**
     * This is the case when we test the tree that only contains AND operator without having an OR operator.
     *
     * Here is the original expression tree: NOT | ( ) | OR / \ ( ) ( ) | | NOT OR | / \ AND LIKE = / \ / \ / \ >              <         S.C      "%%"   S.D   {t '12:04:34'}
     *    /     \         /    \
     *  S.A     3.5      S.B    4
     *
     * Here is the converted expression tree:
     *
     *                                                AND
     *                                           /             \
     *                                         AND              =
     *                                  /            \        /   \
     *                                AND         NOT LIKE   S.D  {t '12:04:34'}
     *                         /             \    /      \
     * > < S.C "%%" / \ / \ S.A 3.5 S.B 4
     *
     */
    @Test
    public void test5() throws Exception {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "NOT ((NOT (S.A > 3.5 AND S.B < 4)) OR "
                + "(S.C LIKE '\"%%\"' OR S.D = {t '12:04:34'}))");
        Expression expected = CCJSqlParserUtil.parseCondExpression(
                "S.A > 3.5 AND S.B < 4 AND NOT S.C LIKE '\"%%\"' "
                + "AND NOT S.D = {t '12:04:34'}");
        Expression result = CNFConverter.convertToCNF(expr);
        assertEquals(expected.toString(), result.toString());
    }

    @Test
    public void testStackOverflowIssue1576() throws JSQLParserException {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "((3.0 >= 4.0 AND 5.0 <= 6.0) OR "
                + "(7.0 < 8.0 AND 9.0 > 10.0) OR "
                + "(11.0 = 11.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 14.0 AND 19.0 > 17.0) OR "
                + "(17.0 = 18.0 AND 20.0 > 20.0) OR "
                + "(17.0 = 16.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 22.0 AND 19.0 > 20.0) OR "
                + "(18.0 = 18.0 AND 22.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0) OR "
                + "(18.0 = 18.0 AND 22.0 > 20.0) OR "
                + "(18.0 = 19.0 AND 22.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0))"
        );
        Expression result = CNFConverter.convertToCNF(expr);
        assertThat(result).asString().hasSize(3448827);
    }
    
    
    @Test
    @Disabled
    public void testStackOverflowIssue1576_veryLarge() throws JSQLParserException {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "((3.0 >= 4.0 AND 5.0 <= 6.0) OR "
                + "(7.0 < 8.0 AND 9.0 > 10.0) OR "
                + "(11.0 = 11.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 14.0 AND 19.0 > 17.0) OR "
                + "(17.0 = 18.0 AND 20.0 > 20.0) OR "
                + "(17.0 = 16.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 22.0 AND 19.0 > 20.0) OR "
                + "(18.0 = 18.0 AND 22.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0) OR "
                + "(18.0 = 18.0 AND 22.0 > 20.0) OR "
                + "(18.0 = 19.0 AND 22.0 > 20.0) OR "
                + "(117.0 = 22.0 AND 19.0 > 20.0) OR "
                + "(118.0 = 18.0 AND 22.0 > 20.0) OR "
                + "(117.0 = 18.0 AND 19.0 > 20.0) OR "
                //+ "(118.0 = 18.0 AND 22.0 > 20.0) OR "
                //+ "(118.0 = 19.0 AND 22.0 > 20.0) OR "
                + "(17.0 = 18.0 AND 19.0 > 20.0))"
        );
        Expression result = CNFConverter.convertToCNF(expr);
        assertThat(result).asString().hasSize(33685499);
    }
    
    @Test
    public void testStackOverflowIssue1576_2() throws JSQLParserException {
        Expression expr = CCJSqlParserUtil.parseCondExpression(
                "((3.0 >= 4.0 AND 5.0 <= 6.0) OR "
                + "(7.0 < 8.0 AND 9.0 > 10.0) OR "
                + "(11.0 = 11.0 AND 19.0 > 20.0) OR "
                + "(17.0 = 14.0 AND 19.0 > 17.0) OR "
                + "(17.0 = 18.0 AND 20.0 > 20.0) OR "
                + "(17.0 = 16.0 AND 19.0 > 20.0))"
        );

        Expression result = CNFConverter.convertToCNF(expr);
        assertThat(result).asString().isEqualTo("(3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (3.0 >= 4.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 7.0 < 8.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 11.0 = 11.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 17.0 = 14.0 OR 20.0 > 20.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 17.0 = 18.0 OR 19.0 > 20.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 17.0 = 16.0) AND (5.0 <= 6.0 OR 9.0 > 10.0 OR 19.0 > 20.0 OR 19.0 > 17.0 OR 20.0 > 20.0 OR 19.0 > 20.0)");
    }
}
