import junit.framework.TestCase;
import junit.framework.Assert;

/**
 * A JUnit test case class.
 * Every method starting with the word "test" will be called when running
 * the test with JUnit.
 */
public class SudokuLibTest extends TestCase {

  
  // NOTE: For these methods, the indices of rows and columns
  // go from 0 to 8 (and not from 1 to 9 as in the game)
   
  /**
   * Verifies the comparison with a good result
   */
  public void testGenerateConstraints() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 0, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] expected = 
    {
      {true, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, false, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean [][] constraints = new boolean[9][9];
    SudokuLib.generateConstraints(sudoku, constraints);
    
    // Comparison. Some work to do...
    int r, c;
    for (r = 0; r < 9; r = r + 1)
    {
      for (c = 0; c < 9; c = c + 1)
      {
        Assert.assertEquals( " (row:" + r + ", column:" + c + ")", expected[r][c], constraints[r][c] );
      }
    }     
  }
  
/*****************************************************************************/  

  /**
   * Verifies that we solved a sudoku
   */
  public void testSolved() {
    
    int [][] sudoku =  // GIVENS
    { 
      {1, 2, 7, 4, 3, 5, 9, 6, 8},        
      {5, 9, 6, 7, 8, 2, 4, 1, 3},        
      {4, 3, 8, 9, 6, 1, 7, 2, 5},        
      {2, 5, 1, 8, 4, 3, 6, 9, 7},        
      {3, 8, 9, 6, 2, 7, 5, 4, 1},        
      {6, 7, 4, 1, 5, 9, 8, 3, 2},        
      {7, 6, 2, 3, 9, 8, 1, 5, 4},        
      {8, 4, 3, 5, 1, 6, 2, 7, 9},        
      {9, 1, 5, 2, 7, 4, 3, 8, 6},        
    };
    
    boolean expected = true;
    boolean returned;
    
    returned = SudokuLib.solved(sudoku);
    Assert.assertEquals( expected, returned );
  }
  
  /**
   * Verifies that we did not solve an incomplete sudoku
   */
  public void testNotSolved() {
    
    int [][] sudoku =  // GIVENS
    { 
      {1, 2, 7, 4, 3, 5, 9, 6, 8},        
      {5, 9, 6, 7, 8, 2, 4, 1, 3},        
      {4, 3, 8, 9, 6, 1, 7, 2, 5},        
      {2, 5, 1, 8, 4, 3, 6, 9, 7},        
      {3, 8, 9, 6, 2, 7, 5, 4, 1},        
      {6, 7, 4, 1, 5, 9, 8, 3, 2},        
      {7, 6, 2, 3, 9, 8, 1, 5, 4},        
      {8, 4, 3, 5, 1, 6, 2, 7, 9},        
      {9, 1, 5, 2, 7, 4, 3, 8, 0},        
    };
    
    boolean expected = false;
    boolean returned;
    
    returned = SudokuLib.solved(sudoku);
    Assert.assertEquals( expected, returned );
  }

/*****************************************************************************/  

  /**
   * Verifies that we can insert a valid value
   */
  public void testVerifyGuessValid() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 0, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] constraints = 
    {
      {true, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, false, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean expected = true;
    boolean returned;
    
    returned = SudokuLib.verifyGuess(4, 4, 5, sudoku, constraints, false);
    Assert.assertEquals( expected, returned );
  }
  
  /**
   * Verifies that we cannot insert over an initial value
   */
  public void testVerifyGuessRefuseConstraint() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 0, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] constraints = 
    {
      {true, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, false, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean expected = false;
    boolean returned;
    
    returned = SudokuLib.verifyGuess(0, 0, 7, sudoku, constraints, false);
    Assert.assertEquals( expected, returned );
  }
  
  /**
   * Verifies that we can insert a 0 in a position that does not contain an initial value
   */
  public void testVerifyGuessAccept0() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 0, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] constraints = 
    {
      {false, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, false, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean expected = true;
    boolean returned;
    
    returned = SudokuLib.verifyGuess(0, 0, 0, sudoku, constraints, false);
    Assert.assertEquals( expected, returned );
  }
  
  /**
   * Verifies the case when the value exists in the row
   */
  public void testVerifyGuessRefuseRow() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 0, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] constraints = 
    {
      {true, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, false, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean expected = false;
    boolean returned;
    
    returned = SudokuLib.verifyGuess(4, 4, 6, sudoku, constraints, false);
    Assert.assertEquals( expected, returned );
  }
  
  /**
   * Verifies the case when the value exists in the column
   */
  public void testVerifyGuessRefuseColumn() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 0, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] constraints = 
    {
      {true, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, false, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean expected = false;
    boolean returned;
    
    returned = SudokuLib.verifyGuess(4, 4, 4, sudoku, constraints, false);
    Assert.assertEquals( expected, returned );
  }
  
  /**
   * Verifies the case when the value exists in the 3x3 zone
   */
  public void testVerifyGuessRefuseZone() {
    
    int [][] sudoku =  // GIVENS
    { 
      {5, 4, 0, 6, 0, 0, 3, 0, 0},        
      {0, 0, 0, 3, 1, 0, 0, 0, 4},        
      {0, 3, 9, 0, 7, 0, 1, 0, 0},        
      {0, 0, 0, 8, 0, 0, 0, 2, 1},        
      {0, 0, 0, 0, 0, 1, 6, 8, 3},        
      {2, 1, 8, 0, 3, 5, 0, 0, 0},        
      {1, 9, 0, 0, 0, 0, 4, 6, 0},        
      {0, 8, 0, 1, 0, 0, 0, 3, 0},        
      {6, 7, 3, 0, 4, 8, 0, 0, 0},        
    };
    
    boolean [][] constraints = 
    {
      {true, true, false, true, false, false, true, false, false},        
      {false, false, false, true, true, false, false, false, true},        
      {false, true, true, false, true, false, true, false, false},        
      {false, false, false, true, false, false, false, true, true},        
      {false, false, false, false, false, true, true, true, true},        
      {true, true, true, false, true, true, false, false, false},        
      {true, true, false, false, false, false, true, true, false},        
      {false, true, false, true, false, false, false, true, false},        
      {true, true, true, false, true, true, false, false, false}, 
    };
    
    boolean expected = false;
    boolean returned;
    
    returned = SudokuLib.verifyGuess(4, 4, 5, sudoku, constraints, false);
    Assert.assertEquals( expected, returned );
  }
  
}
