License text

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER 
 * Copyright  2008, 2010 Oracle and/or its affiliates.  All rights reserved. 
 * Use is subject to license terms.
 * 
 * This file is available and licensed under the following license:
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met: 
 * 
 *   * Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer. 
 *
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *
 *   * Neither the name of Oracle Corporation nor the names of its contributors 
 *     may be used to endorse or promote products derived from this software 
 *     without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

    

package sudoku;

import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.stage.Alert;
import javafx.scene.layout.Tile;
import javafx.scene.layout.Container;

import sudoku.DataCell;

/**
 * @author Rakesh Menon
 */

def database = java.util.ResourceBundle.getBundle("sudoku.data");
def random = new java.util.Random();
def _gridLayoutXY = 1;
def _rectXY = 0;
def _rectWdthHgt = 269;
def _btntileX = 17;
def _btntileY = 280;
def _colms = 9;
def _rows = 9;

public class SudokuNode extends Container {
    var gridtile:Tile;
    var btntile:Tile;
    var dataGrid = Group { };
    var buttonGrid: Group = Group {
       var Button;

        layoutX: bind dataGrid.boundsInLocal.height + 12
        layoutY: bind (dataGrid.boundsInLocal.width - buttonGrid.boundsInLocal.width) / 2.0 + 11
    }

    var showHint = false;

    public function updateData() {
        var index = random.nextInt(100);
        var data = database.getString("data_{index}");
        var sudokuData = data.split(",");

        showHint = false;

        index = 0;
        for(cell in gridtile.content) {
            var dataCell = (cell as DataCell);
            dataCell.reset();
            dataCell.data = Integer.parseInt(sudokuData[index]);
            index++;
        }

        var showCount = 60 - random.nextInt(20);
        while (showCount != 0) {
            index = random.nextInt(81);
            var dataCell = (gridtile.content[index] as DataCell);
            if(not dataCell.show) {
                dataCell.show = true;
                showCount--;
            }
        }
        reset();
    }

    public function verifyData() {

        var win = true;

        for(cell in gridtile.content) {
            var dataCell = (cell as DataCell);
            if(not "{dataCell.data}".equals(dataCell.content)) {
                dataCell.error = true;
                win = false;
            }
            if(not dataCell.show) {
                dataCell.show = true;
            }
        }

        if(win) {
            Alert.inform("Sudoku - Result", "Congratulations! You Win!");
        } else {
            Alert.inform("Sudoku - Result", "You Lose! Please try again!");
        }
        reset();
    }

    public var selDataCell: DataCell;
    function onCellSelect(cell : DataCell) {
        if(cell.show) {
            selDataCell = null;
            return;
        }

        reset();
        showButtonHint(cell);

        selDataCell = cell;
        cell.selected = true;
    }

    function reset() {

        // Reset selection
        for(buttonCell in btntile.content) {
            (buttonCell as Button).selected = false;
        }
        for(dataCell in gridtile.content) {
            (dataCell as DataCell).selected = false;
        }

        selDataCell = null;
    }

    public function hint() {
        if(showHint) {
            if(selDataCell != null){
                selDataCell.cellText = "{selDataCell.data}";
            }
        } else {
            showHint = true;
            if(selDataCell != null){
                showButtonHint(selDataCell);
            }
        }
    }

    function showButtonHint(cell : DataCell) {

        if(not showHint) {
            return;
        }

        // Get Block Details
        var startRow = 0;
        var startCol = 0;
        if(cell.row < 3 and cell.col < 3) {
            startRow = 0;
            startCol = 0;
        } else if(cell.row < 6 and cell.col < 3) {
            startRow = 3;
            startCol = 0;
        } else if(cell.row < 9 and cell.col < 3) {
            startRow = 6;
            startCol = 0;
        } else if(cell.row < 3 and cell.col < 6) {
            startRow = 0;
            startCol = 3;
        } else if(cell.row < 6 and cell.col < 6) {
            startRow = 3;
            startCol = 3;
        } else if(cell.row < 9 and cell.col < 6) {
            startRow = 6;
            startCol = 3;
        } else if(cell.row < 3 and cell.col < 9) {
            startRow = 0;
            startCol = 6;
        } else if(cell.row < 6 and cell.col < 9) {
            startRow = 3;
            startCol = 6;
        } else if(cell.row < 9 and cell.col < 9) {
            startRow = 6;
            startCol = 6;
        }

        for(row in [startRow..
            (startRow + 2)]) {
            for(col in [startCol..
                (startCol + 2)]) {
                var dataIndex = row * 9 + col;
                var dataCell = gridtile.content[dataIndex] as DataCell;
                var buttonCell = (btntile.content[
                dataCell.data - 1] as Button);
                if(not dataCell.show) {
                    buttonCell.selected = true;
                } else {
                    buttonCell.selected = false;
                }
            }
        }
    }

    function createGrid() : Node {

        var grid = Group {
            layoutX: _gridLayoutXY
            layoutY: _gridLayoutXY
        };

        insert
        Rectangle {
            x: _rectXY
            y: _rectXY
            width: _rectWdthHgt
            height: _rectWdthHgt
            styleClass: "blockRectangle"
        } into grid.content;

        for(i in [1..2]) {
            insert
            Line {
                startX: 3
                startY: i * 90 - 2
                endX: 265
                endY: i * 90 - 4
                styleClass: "blockLine"
            } into grid.content;
            insert
            Line {
                startX: i * 90 - 2
                startY: 3
                endX: i * 90 - 4
                endY: 265
                styleClass: "blockLine"
            } into grid.content;
        }

        return grid;
    }

    init{
        blocksMouse = true;

        // Sudoku Cells
        gridtile = Tile {
            rows:_rows
            columns:_colms
            hgap:0
            content: [
                for(row in [0..8]) {
                for(col in [0..8]) {
                    DataCell {
                        data: 0
                        row: row
                        col: col
                        height:30
                        width:30
                        onMousePressed: function(e) {
                            onCellSelect(e.node as DataCell);
                        }
                    }
                }
               }
            ]
        }
       btntile = Tile {
           layoutX: _btntileX
           layoutY: _btntileY
           hgap: 6
           columns: _colms
           rows: 1 
           content:[
               for(i in [1..9]) {
                   Button {
                       data: "{(i)}"
                       col: 0
                       selected: false
                       onMousePressed: function(e) {
                           selDataCell.cellText = "{(e.node as Button).data}";
                       }
                   }
               }
           ]
       }

        // Sudoku Grid
        var grid = createGrid();
        children = [
        Group {
            content: [ grid, gridtile, btntile ];
        }
        ]
    }

    override var onKeyPressed = function( e : KeyEvent ) {

        if(selDataCell == null) {
            return;
        }

        if(e.code == KeyCode.VK_1) {
            selDataCell.cellText = "1";
        } else if(e.code == KeyCode.VK_2) {
            selDataCell.cellText = "2";
        } else if(e.code == KeyCode.VK_3) {
            selDataCell.cellText = "3";
        } else if(e.code == KeyCode.VK_4) {
            selDataCell.cellText = "4";
        } else if(e.code == KeyCode.VK_5) {
            selDataCell.cellText = "5";
        } else if(e.code == KeyCode.VK_6) {
            selDataCell.cellText = "6";
        } else if(e.code == KeyCode.VK_7) {
            selDataCell.cellText = "7";
        } else if(e.code == KeyCode.VK_8) {
            selDataCell.cellText = "8";
        } else if(e.code == KeyCode.VK_9) {
            selDataCell.cellText = "9";
        }
    }
}