/*
 * Copyright 2018 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.optaplanner.examples.nqueens.solver.score;

import org.optaplanner.core.api.score.buildin.simple.SimpleScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
import org.optaplanner.core.api.score.stream.common.Joiners;
import org.optaplanner.examples.nqueens.domain.Queen;

public class NQueensConstraintProvider implements ConstraintProvider {

    @Override
    public void defineConstraints(ConstraintFactory constraintFactory) {
        horizontalConflict(constraintFactory);
        ascendingDiagonalConflict(constraintFactory);
        descendingDiagonalConflict(constraintFactory);
    }

    protected void horizontalConflict(ConstraintFactory constraintFactory) {
        Constraint c = constraintFactory.newConstraintWithWeight(
                "Horizontal conflict", SimpleScore.of(1));
        c.from(Queen.class)
                .join(Queen.class,
                        Joiners.equalTo(Queen::getRowIndex),
                        Joiners.lessThan(Queen::getId))
                .penalize();
    }

    protected void ascendingDiagonalConflict(ConstraintFactory constraintFactory) {
        Constraint c = constraintFactory.newConstraintWithWeight(
                "Ascending diagonal conflict", SimpleScore.of(1));
        c.from(Queen.class)
                .join(Queen.class,
                        Joiners.equalTo(Queen::getAscendingDiagonalIndex),
                        Joiners.lessThan(Queen::getId))
                .penalize();
    }

    protected void descendingDiagonalConflict(ConstraintFactory constraintFactory) {
        Constraint c = constraintFactory.newConstraintWithWeight(
                "Descending diagonal conflict", SimpleScore.of(1));
        c.from(Queen.class)
                .join(Queen.class,
                        Joiners.equalTo(Queen::getDescendingDiagonalIndex),
                        Joiners.lessThan(Queen::getId))
                .penalize();
    }

}

@@ -1569,32 +1569,42 @@
 ;%0A        c.from
+UniquePair
 (Queen.class)%0A  
@@ -1591,34 +1591,226 @@
 Pair(Queen.class
-)%0A
+,%0A                Joiners.equalTo(Queen::getRowIndex)%0A        ).penalize();%0A        // fromUniquePair() is syntactic sugar for from().join(..., lessThan(getId())%0A//        c.from(Queen.class)%0A//
                 
@@ -1820,32 +1820,34 @@
 in(Queen.class,%0A
+//
                 
@@ -1883,32 +1883,34 @@
 ::getRowIndex),%0A
+//
                 
@@ -1941,32 +1941,34 @@
 (Queen::getId))%0A
+//
                 
@@ -2222,43 +2222,18 @@
 from
-(Queen.class)%0A                .join
+UniquePair
 (Que
@@ -2238,32 +2238,24 @@
 ueen.class,%0A
-        
             
@@ -2299,33 +2299,32 @@
 ngDiagonalIndex)
-,
 %0A               
@@ -2320,72 +2320,9 @@
     
-                Joiners.lessThan(Queen::getId))%0A                
+)
 .pen
@@ -2574,43 +2574,18 @@
 from
-(Queen.class)%0A                .join
+UniquePair
 (Que
@@ -2590,32 +2590,24 @@
 ueen.class,%0A
-        
             
@@ -2660,17 +2660,16 @@
 alIndex)
-,
 %0A       
@@ -2673,72 +2673,9 @@
     
-                Joiners.lessThan(Queen::getId))%0A                
+)
 .pen

Use fromUniquePair() in NQueens