<commit_before>/*
 * Battleship Game
 * http://experiments.bivainis.com/
 * Copyright 2014, Gediminas Bivainis
 * Free to use under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

/*
 // pseudo:
 // 1) for each ship inside ships array
 // 2) ranodmize orientation: 0 - horizontal, 1 - vertical
 // 3) random position in board array for ship start
 //  3a) make sure that positions are unique
 //      check if value already exists in array
 //      if yes, randomize a new value
 // 4) insert ship position id into _shipLocationsArr
 // 5) if ship orientation is 0:
 //    while ship.length,
 //      while ship position + ship length < board length
 //          insert another position after 1 element
 //          _shipLocationsArr.push(position);
 //          ship position++
 //      ship length--;
 //
 // if ship orientation 1:
 // while ship.length, insert another position after exactly board length
 */

/*
* todo:
* scoreboard
* player name
*
* */

/*
* Table of contents:

 ** [1] SET GAME VARS AND SETTINGS

 ** [2] CREATE GAME BOARD
 // [2a] create new letter array based on board size
 // [2b] create board element
 // [2c] create as many cells as needed based on the board size
 // [2d] add a separator to jump to a new row on a board
 // [2e] create container to hold body and sidebar
 // [2f] add the board to container
 // [2g] create sidebar and place the ships

 ** [3] CREATE BOARD SIDEBAR
 // [3a] for each ship, add ship representation to sidebar list, based on ship length, styled in style.css

 ** [4] PLACE SHIPS
 // [4a] randomize position and assign random cell value
 // [4b] determine current ship size (set in options)
 // [4c] ranodmize ship orientation: 0 - horizontal, 1 - vertical
 // [4d] get array of positions which aren't allowed, see [6]
 // [4e1] escape the loop if position is free OR continue to loop if position is taken, and generate a new random position, until it's unique
 // [4e2] if position is inside forbidden positions array, adjust it's position based on the ship size
 // [4e3] push ship cells to ship locations array for each individual ship cell

 ** [5] GET A RANDOM INDEX FROM PASSED ARRAY

 ** [6] CALCULATE FORBIDDEN POSITIONS
 // [6a] based on orientation and ship size calculate illegal ship start positions and return them as an array

 ** [7] CHECK IF THE POSITION IS NOT TAKEN BY ANOTHER CELL

 ** [8] ADD SHIP CELL TO SHIP LOCATIONS

 ** [9] FIRE
 // [9a] if a target set has data attribute of cell id, get the currently targeted cell by index
 // [9b] remove a target from array once hit
 // [9c] add hit class to sink the ship
 // [9d] if there are no more cells, run win function [10]

 ** [10] WIN NOTIFICATION

 ** [11] RETURN INIT FUNCTION
* */

var ShipGame = (function(){

    // [1] - set object vars and options
    var _gameContainerEl,
        _boardEl, // board container element
        _lettersArr = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','w','x','y','z'],
        _boardLettersArr,
        _shipLocationsArr = [],
        _boardArr = [],
        _options = {
            boardSize : 7,
            ships : [3,2,1]
        },
        _score = 0,
        _playerName = '';

    var _setOptions = function(options){

        var largestShip; // to use below

        // [1a] set local options if options are passed after initializing the game
        _options.ships = options.ships ? options.ships : _options.ships;
        _options.boardSize = options.boardSize ? options.boardSize : _options.boardSize;

        // [1b] - check what is the largest ship,
        // warn a user that the board is too small,
        // adjust board size on confirm
        largestShip = Math.max.apply(Math, _options.ships);

        while (_options.boardSize <= largestShip) {

            var prmt = confirm('Board size must be 1 square larger than the largest ship. Adjust board size?');
            _options.boardSize = prmt ? _options.boardSize = largestShip + 1 : confirm('Board size must be 1 square larger than the largest ship. Adjust boardsize?');
        }

    };
    // [2] create the board
    var _createBoard = function(opts){

        // [2a] create new letter array based on board size
        _boardLettersArr = _lettersArr.splice(0, _options.boardSize);

        // [2b] create board element
        _boardEl = document.createElement('div');
        _boardEl.setAttribute('id', 'board');

        // [2c] create as many cells as needed based on the board size
        for (var i=0; i < _options.boardSize; i++){

            for (var j=0; j < _options.boardSize; j++){

                var cell, cellText, toPush;

                cell = document.createElement('span');
                cellText = document.createTextNode(_boardLettersArr[i]+(j+1));
                cell.dataset.cellid = _boardLettersArr[i]+j;
                cell.className = 'cell';
                cell.appendChild(cellText);

                _boardEl.appendChild(cell);

                toPush = _boardLettersArr[i]+j;
                _boardArr.push(toPush);

            }
            // [2d] add a separator to jump to a new row on a board
            _boardEl.appendChild(document.createElement('br'));
        }

        // [2e] create container to hold body and sidebar
        _gameContainerEl = document.createElement('div');
        _gameContainerEl.id = 'container';
        _gameContainerEl.className = 'container';
        _gameContainerEl.setAttribute("style", "margin-top:" + opts.boardSize * (-1) * 30 / 2 + "px");
        _gameContainerEl.style.width = opts.boardSize * 30 + 200 + 'px';
        _gameContainerEl.appendChild(_boardEl);

        // [2f] add the board to container
        document.body.appendChild(_gameContainerEl);

        // [2g] create sidebar and place the ships
        _createSidebar();
        _placeShips();
    };
    // [3] CREATE BOARD SIDEBAR
    var _createSidebar = function(){

        var sidebarEl = document.createElement('div');
        sidebarEl.id = 'sidebar';

        var title = document.createElement('h4');
        var titleText = document.createTextNode('Destroy these ships');
        var scoreResultEl = document.createElement('div');

        title.appendChild(titleText);
        sidebarEl.appendChild(title);

        // [3a] for each ship,
        //      add ship representation to sidebar list,
        //      based on ship length,
        //      styled in style.css
        for (var i = 0; i < _options.ships.length; i++){

            var shipTag = document.createElement('div');

            for (var j = 0; j < _options.ships[i]; j++){

                var spn = document.createElement('span');
                spn.className = 'sidebarCell';

                shipTag.appendChild(spn);
            }

            sidebarEl.appendChild(shipTag);
        }
        title = document.createElement('h4');
        titleText = document.createTextNode('Score');
        title.appendChild(titleText);
        sidebarEl.appendChild(title);

        scoreResultEl.id = 'scoreResult';
        sidebarEl.appendChild(scoreResultEl);

        _gameContainerEl.appendChild(sidebarEl);
    };
    // [4] PLACE SHIPS
    var _placeShips = function(){

        for (var i=0; i < _options.ships.length; i++){

            var randomPosition,
                randomCell,
                shipSize,
                badPosArr,
                shipOrientation,
                j;

            // [4a] randomize position and assign random cell value
            randomPosition = _getRandomArrayIndex(_boardArr);
            randomCell = _boardArr[randomPosition];

            // [4b] determine current ship size (set in options)
            shipSize = _options.ships[i];

            // [4c] ranodmize ship orientation: 0 - horizontal, 1 - vertical
            shipOrientation = Math.floor(Math.random() * [0,1].length);

            // [4d] get array of positions which aren't allowed (to prevent board overflow), see [6]
            badPosArr = _calcForbiddenPositions(shipSize, shipOrientation, _boardArr);

            // [4e] based on ships orientation
            //      check if the position is not taken, also see [7]
            if(shipOrientation == 0){

                while(1){

                    // [4e1] escape the loop if position is free
                    // OR continue to loop if position is taken,
                    // and generate a new random position, until it's unique
                    if(_isPositionFree(randomPosition, shipSize, shipOrientation)){

                        break;

                    } else {

                        randomPosition = _getRandomArrayIndex(_boardArr);
                    }
                }

                // [4e2] if position is inside forbidden positions array,
                //      adjust it's position based on the ship size
                if(badPosArr.indexOf(randomPosition) != -1){

                    randomPosition -= (shipSize - 1);
                }

                // [4e3] push ship cells to ship locations array for each individual ship cell
                for (j=0; j < _options.ships[i];j++){

                    _addShipCell(_boardArr[randomPosition]);
                    randomPosition++;
                }

            } else if (shipOrientation == 1){

                while(1){
                    if(_isPositionFree(randomPosition, shipSize, shipOrientation)){

                        break;
                    } else{

                        randomPosition = _getRandomArrayIndex(_boardArr);
                        continue;
                    }
                }

                if(badPosArr.indexOf(randomPosition) != -1){

                    randomPosition -= (shipSize -1) * _options.boardSize;
                }

                for (j=0; j < _options.ships[i];j++){

                    _addShipCell(_boardArr[randomPosition]);
                    randomPosition+= _options.boardSize;
                }
            }
        }
    };
    // [5] GET A RANDOM INDEX FROM PASSED ARRAY
    var _getRandomArrayIndex = function(arr){

        return Math.floor(Math.random() * arr.length);
    };
    // [6] CALCULATE FORBIDDEN POSSITIONS
    var _calcForbiddenPositions = function(shipSize, orientation, board){

        // [6a] based on orientation and ship size
        //      calculate illegal ship start positions
        //      and return them as an array
        if (orientation == 0){

            var badPosArr = [];
            var badPos = _options.boardSize - shipSize + 1;

            for(var k = 0; k < _options.boardSize; k++){

                for(var l=0; l < shipSize - 1; l++){

                    badPosArr.push(badPos+l);
                }

                badPos += _options.boardSize;
            }

            return badPosArr;

        } else if (orientation == 1) {

            var badPosArr = [];
            var slicedArr = board.slice(-(_options.boardSize * (shipSize-1)));

            for(var i = 0; i < slicedArr.length; i++){
                badPosArr.push(board.indexOf(slicedArr[i]));
            }

            return badPosArr;
        }
    };
    // [7] CHECK IF THE POSITION IS NOT TAKEN BY ANOTHER CELL
    var _isPositionFree = function(pos, shipSize, orientation){

        if(orientation == 0){

            for(var i = 0; i < shipSize; i++){

                if(_shipLocationsArr.indexOf(_boardArr[pos+i]) != -1){

                    return false;
                }
            }
        } else if (orientation == 1){

            for(var i = 0; i < shipSize; i++){

                if(_shipLocationsArr.indexOf(_boardArr[pos+_options.boardSize]) != -1){

                    return false;
                }
            }
        }

        return true;
    };
    // [8] ADD SHIP CELL TO SHIP LOCATIONS
    var _addShipCell = function(cell){

        _shipLocationsArr.push(cell);
    };
    // [9] FIRE
    var _fire = function(e){

        // [9a] if a target set has data attribute of cellid
        //      get the currently targeted cell by index
        if(e.target.dataset.cellid){

            var targetId = e.target.dataset.cellid;
            var arrayIndex = _shipLocationsArr.indexOf(targetId);

            if(arrayIndex != -1){

                // [9b] remove a target from array once hit
                _shipLocationsArr.splice(arrayIndex, 1);

                // [9c] add hit class to sink the ship
                e.target.className += ' hit';
                _score+=10;
                // [9d] if there are no more cells, run win function [10]
                if(_shipLocationsArr.length < 1){

                    _win(_score);
                }
            } else {
                if(_score>0) {
                    _score--;
                }

                e.target.className += ' miss';
            }

            // update score sidebar with current score
            _updateScores(_score);
        }
    };
    // [10] WIN NOTIFICATION
    var _win = function(score){

        alert('Congratulations, '+ _playerName + ' you have won the game, score is ' + score);

        _storeTheScore(score);
    };
    var _updateScores = function(score){

        var scoreEl = document.getElementById('scoreResult');
        var scoreText = document.createTextNode(score);
        //scoreEl.removeChild(scoreText);
        scoreEl.innerHTML = score;
    };
    var _storeTheScore = function(score){

        var currentScoreBoard = localStorage.shipGameScores ? JSON.parse(localStorage.shipGameScores) : [];
        currentScoreBoard.push({"name": _playerName,"score" : score});
        localStorage.shipGameScores = JSON.stringify(currentScoreBoard);
    };
    var _createScoreBoard = function(){

        var scoreBoardEl = document.createElement('div');
        var scoreBoardListEl = document.createElement('ul');
        var html = '';

        scoreBoardEl.style.clear = "both";
        scoreBoardListEl.id = 'scoreBoard';

        if (localStorage.shipGameScores){

            var scores = JSON.parse(localStorage.shipGameScores);
            var i = 0;

            for (;i < scores.length; i++){

                html += ('
' + scores[i].score + ' ' + scores[i].name + '
');
            }

        } else {
            html = '
No scores yet
'
        }
        scoreBoardListEl.innerHTML = html;
        scoreBoardEl.appendChild(scoreBoardListEl);

        document.getElementById('container').appendChild(scoreBoardEl);
    };
    // [11] RETURN INIT FUNCTION
    var init = function(opts){

        _playerName = prompt('Your name?');
        _setOptions(opts);
        _createBoard(_options);
        _createScoreBoard();
        document.onclick = _fire;
    };

    return {
        init : init
    };
})();<commit_msg>move prompt for player name to after the game<commit_after>/*
 * Battleship Game
 * http://experiments.bivainis.com/
 * Copyright 2014, Gediminas Bivainis
 * Free to use under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

/*
 // pseudo:
 // 1) for each ship inside ships array
 // 2) ranodmize orientation: 0 - horizontal, 1 - vertical
 // 3) random position in board array for ship start
 //  3a) make sure that positions are unique
 //      check if value already exists in array
 //      if yes, randomize a new value
 // 4) insert ship position id into _shipLocationsArr
 // 5) if ship orientation is 0:
 //    while ship.length,
 //      while ship position + ship length < board length
 //          insert another position after 1 element
 //          _shipLocationsArr.push(position);
 //          ship position++
 //      ship length--;
 //
 // if ship orientation 1:
 // while ship.length, insert another position after exactly board length
 */

/*
* todo:
* scoreboard
*
* */

/*
* Table of contents:

 ** [1] SET GAME VARS AND SETTINGS

 ** [2] CREATE GAME BOARD
 // [2a] create new letter array based on board size
 // [2b] create board element
 // [2c] create as many cells as needed based on the board size
 // [2d] add a separator to jump to a new row on a board
 // [2e] create container to hold body and sidebar
 // [2f] add the board to container
 // [2g] create sidebar and place the ships

 ** [3] CREATE BOARD SIDEBAR
 // [3a] for each ship, add ship representation to sidebar list, based on ship length, styled in style.css

 ** [4] PLACE SHIPS
 // [4a] randomize position and assign random cell value
 // [4b] determine current ship size (set in options)
 // [4c] ranodmize ship orientation: 0 - horizontal, 1 - vertical
 // [4d] get array of positions which aren't allowed, see [6]
 // [4e1] escape the loop if position is free OR continue to loop if position is taken, and generate a new random position, until it's unique
 // [4e2] if position is inside forbidden positions array, adjust it's position based on the ship size
 // [4e3] push ship cells to ship locations array for each individual ship cell

 ** [5] GET A RANDOM INDEX FROM PASSED ARRAY

 ** [6] CALCULATE FORBIDDEN POSITIONS
 // [6a] based on orientation and ship size calculate illegal ship start positions and return them as an array

 ** [7] CHECK IF THE POSITION IS NOT TAKEN BY ANOTHER CELL

 ** [8] ADD SHIP CELL TO SHIP LOCATIONS

 ** [9] FIRE
 // [9a] if a target set has data attribute of cell id, get the currently targeted cell by index
 // [9b] remove a target from array once hit
 // [9c] add hit class to sink the ship
 // [9d] if there are no more cells, run win function [10]

 ** [10] WIN NOTIFICATION

 ** [11] RETURN INIT FUNCTION
* */

var ShipGame = (function(){

    // [1] - set object vars and options
    var _gameContainerEl,
        _boardEl, // board container element
        _lettersArr = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','w','x','y','z'],
        _boardLettersArr,
        _shipLocationsArr = [],
        _boardArr = [],
        _options = {
            boardSize : 7,
            ships : [3,2,1]
        },
        _score = 0,
        _playerName = '';

    var _setOptions = function(options){

        var largestShip; // to use below

        // [1a] set local options if options are passed after initializing the game
        _options.ships = options.ships ? options.ships : _options.ships;
        _options.boardSize = options.boardSize ? options.boardSize : _options.boardSize;

        // [1b] - check what is the largest ship,
        // warn a user that the board is too small,
        // adjust board size on confirm
        largestShip = Math.max.apply(Math, _options.ships);

        while (_options.boardSize <= largestShip) {

            var prmt = confirm('Board size must be 1 square larger than the largest ship. Adjust board size?');
            _options.boardSize = prmt ? _options.boardSize = largestShip + 1 : confirm('Board size must be 1 square larger than the largest ship. Adjust boardsize?');
        }

    };
    // [2] create the board
    var _createBoard = function(opts){

        // [2a] create new letter array based on board size
        _boardLettersArr = _lettersArr.splice(0, _options.boardSize);

        // [2b] create board element
        _boardEl = document.createElement('div');
        _boardEl.setAttribute('id', 'board');

        // [2c] create as many cells as needed based on the board size
        for (var i=0; i < _options.boardSize; i++){

            for (var j=0; j < _options.boardSize; j++){

                var cell, cellText, toPush;

                cell = document.createElement('span');
                cellText = document.createTextNode(_boardLettersArr[i]+(j+1));
                cell.dataset.cellid = _boardLettersArr[i]+j;
                cell.className = 'cell';
                cell.appendChild(cellText);

                _boardEl.appendChild(cell);

                toPush = _boardLettersArr[i]+j;
                _boardArr.push(toPush);

            }
            // [2d] add a separator to jump to a new row on a board
            _boardEl.appendChild(document.createElement('br'));
        }

        // [2e] create container to hold body and sidebar
        _gameContainerEl = document.createElement('div');
        _gameContainerEl.id = 'container';
        _gameContainerEl.className = 'container';
        _gameContainerEl.setAttribute("style", "margin-top:" + opts.boardSize * (-1) * 30 / 2 + "px");
        _gameContainerEl.style.width = opts.boardSize * 30 + 200 + 'px';
        _gameContainerEl.appendChild(_boardEl);

        // [2f] add the board to container
        document.body.appendChild(_gameContainerEl);

        // [2g] create sidebar and place the ships
        _createSidebar();
        _placeShips();
    };
    // [3] CREATE BOARD SIDEBAR
    var _createSidebar = function(){

        var sidebarEl = document.createElement('div');
        sidebarEl.id = 'sidebar';

        var title = document.createElement('h4');
        var titleText = document.createTextNode('Destroy these ships');
        var scoreResultEl = document.createElement('div');

        title.appendChild(titleText);
        sidebarEl.appendChild(title);

        // [3a] for each ship,
        //      add ship representation to sidebar list,
        //      based on ship length,
        //      styled in style.css
        for (var i = 0; i < _options.ships.length; i++){

            var shipTag = document.createElement('div');

            for (var j = 0; j < _options.ships[i]; j++){

                var spn = document.createElement('span');
                spn.className = 'sidebarCell';

                shipTag.appendChild(spn);
            }

            sidebarEl.appendChild(shipTag);
        }
        title = document.createElement('h4');
        titleText = document.createTextNode('Score');
        title.appendChild(titleText);
        sidebarEl.appendChild(title);

        scoreResultEl.id = 'scoreResult';
        sidebarEl.appendChild(scoreResultEl);

        _gameContainerEl.appendChild(sidebarEl);
    };
    // [4] PLACE SHIPS
    var _placeShips = function(){

        for (var i=0; i < _options.ships.length; i++){

            var randomPosition,
                randomCell,
                shipSize,
                badPosArr,
                shipOrientation,
                j;

            // [4a] randomize position and assign random cell value
            randomPosition = _getRandomArrayIndex(_boardArr);
            randomCell = _boardArr[randomPosition];

            // [4b] determine current ship size (set in options)
            shipSize = _options.ships[i];

            // [4c] ranodmize ship orientation: 0 - horizontal, 1 - vertical
            shipOrientation = Math.floor(Math.random() * [0,1].length);

            // [4d] get array of positions which aren't allowed (to prevent board overflow), see [6]
            badPosArr = _calcForbiddenPositions(shipSize, shipOrientation, _boardArr);

            // [4e] based on ships orientation
            //      check if the position is not taken, also see [7]
            if(shipOrientation == 0){

                while(1){

                    // [4e1] escape the loop if position is free
                    // OR continue to loop if position is taken,
                    // and generate a new random position, until it's unique
                    if(_isPositionFree(randomPosition, shipSize, shipOrientation)){

                        break;

                    } else {

                        randomPosition = _getRandomArrayIndex(_boardArr);
                    }
                }

                // [4e2] if position is inside forbidden positions array,
                //      adjust it's position based on the ship size
                if(badPosArr.indexOf(randomPosition) != -1){

                    randomPosition -= (shipSize - 1);
                }

                // [4e3] push ship cells to ship locations array for each individual ship cell
                for (j=0; j < _options.ships[i];j++){

                    _addShipCell(_boardArr[randomPosition]);
                    randomPosition++;
                }

            } else if (shipOrientation == 1){

                while(1){
                    if(_isPositionFree(randomPosition, shipSize, shipOrientation)){

                        break;
                    } else{

                        randomPosition = _getRandomArrayIndex(_boardArr);
                        continue;
                    }
                }

                if(badPosArr.indexOf(randomPosition) != -1){

                    randomPosition -= (shipSize -1) * _options.boardSize;
                }

                for (j=0; j < _options.ships[i];j++){

                    _addShipCell(_boardArr[randomPosition]);
                    randomPosition+= _options.boardSize;
                }
            }
        }
    };
    // [5] GET A RANDOM INDEX FROM PASSED ARRAY
    var _getRandomArrayIndex = function(arr){

        return Math.floor(Math.random() * arr.length);
    };
    // [6] CALCULATE FORBIDDEN POSSITIONS
    var _calcForbiddenPositions = function(shipSize, orientation, board){

        // [6a] based on orientation and ship size
        //      calculate illegal ship start positions
        //      and return them as an array
        if (orientation == 0){

            var badPosArr = [];
            var badPos = _options.boardSize - shipSize + 1;

            for(var k = 0; k < _options.boardSize; k++){

                for(var l=0; l < shipSize - 1; l++){

                    badPosArr.push(badPos+l);
                }

                badPos += _options.boardSize;
            }

            return badPosArr;

        } else if (orientation == 1) {

            var badPosArr = [];
            var slicedArr = board.slice(-(_options.boardSize * (shipSize-1)));

            for(var i = 0; i < slicedArr.length; i++){
                badPosArr.push(board.indexOf(slicedArr[i]));
            }

            return badPosArr;
        }
    };
    // [7] CHECK IF THE POSITION IS NOT TAKEN BY ANOTHER CELL
    var _isPositionFree = function(pos, shipSize, orientation){

        if(orientation == 0){

            for(var i = 0; i < shipSize; i++){

                if(_shipLocationsArr.indexOf(_boardArr[pos+i]) != -1){

                    return false;
                }
            }
        } else if (orientation == 1){

            for(var i = 0; i < shipSize; i++){

                if(_shipLocationsArr.indexOf(_boardArr[pos+_options.boardSize]) != -1){

                    return false;
                }
            }
        }

        return true;
    };
    // [8] ADD SHIP CELL TO SHIP LOCATIONS
    var _addShipCell = function(cell){

        _shipLocationsArr.push(cell);
    };
    // [9] FIRE
    var _fire = function(e){

        // [9a] if a target set has data attribute of cellid
        //      get the currently targeted cell by index
        if(e.target.dataset.cellid){

            var targetId = e.target.dataset.cellid;
            var arrayIndex = _shipLocationsArr.indexOf(targetId);

            if(arrayIndex != -1){

                // [9b] remove a target from array once hit
                _shipLocationsArr.splice(arrayIndex, 1);

                // [9c] add hit class to sink the ship
                e.target.className += ' hit';
                _score+=10;
                // [9d] if there are no more cells, run win function [10]
                if(_shipLocationsArr.length < 1){

                    _win(_score);
                }
            } else {
                if(_score>0) {
                    _score--;
                }

                e.target.className += ' miss';
            }

            // update score sidebar with current score
            _updateScores(_score);
        }
    };
    // [10] WIN NOTIFICATION
    var _win = function(score){

        alert('Congratulations, '+ _playerName + ' you have won the game, score is ' + score);

        _storeTheScore(score);
    };
    var _updateScores = function(score){

        var scoreEl = document.getElementById('scoreResult');
        var scoreText = document.createTextNode(score);
        //scoreEl.removeChild(scoreText);
        scoreEl.innerHTML = score;
    };
    var _storeTheScore = function(score){
        _playerName = prompt('Your name?');
        var currentScoreBoard = localStorage.shipGameScores ? JSON.parse(localStorage.shipGameScores) : [];
        currentScoreBoard.push({"name": _playerName,"score" : score});
        localStorage.shipGameScores = JSON.stringify(currentScoreBoard);
    };
    var _createScoreBoard = function(){

        var scoreBoardEl = document.createElement('div');
        var scoreBoardListEl = document.createElement('ul');
        var html = '';

        scoreBoardEl.style.clear = "both";
        scoreBoardListEl.id = 'scoreBoard';

        if (localStorage.shipGameScores){

            var scores = JSON.parse(localStorage.shipGameScores);
            var i = 0;

            for (;i < scores.length; i++){

                html += ('
' + scores[i].score + ' ' + scores[i].name + '
');
            }

        } else {
            html = '
No scores yet
'
        }
        scoreBoardListEl.innerHTML = html;
        scoreBoardEl.appendChild(scoreBoardListEl);

        document.getElementById('container').appendChild(scoreBoardEl);
    };
    // [11] RETURN INIT FUNCTION
    var init = function(opts){

        _setOptions(opts);
        _createBoard(_options);
        _createScoreBoard();
        document.onclick = _fire;
    };

    return {
        init : init
    };
})();<|endoftext|>


<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters hypotheek':
      //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say('Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee, bedankt](postback:update_nee)'))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja - graag':
            return bot.say(`Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.' `)
            .then(() => 'update_ja');
          break;
          case 'Nee, bedankt':
              receive: () => 'bye'
              break;
          default:
            return bot.say(`...`)
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailVisitor = message.text;
          return bot.setProp('emailVisitor', emailVisitor)
              .then(() => bot.say('op'))
  //          //return bot.setProp('emailVisitor', emailVisitor)
  //           .then(()  => bot.say('Ok - dan hou ik je via ${emailVisitor} op de hoogte.'))
  //           .then(()  =>'processing')
    }
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say(`Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`),
    receive: () => 'processing'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :)`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
    }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    // prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen? %[JA](postback:nogietsanders) %[NEE](postback:bye) '),
    // .then(()  => 'processing');
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>sql<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters hypotheek':
      //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say('Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee, bedankt](postback:update_nee)'))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja - graag':
            return bot.say(`Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.' `)
            .then(() => 'update_ja');
          break;
          case 'Nee, bedankt':
              receive: () => 'bye'
              break;
          default:
            return bot.say(`...`)
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailVisitor = message.text;
          return bot.setProp('emailVisitor', emailVisitor)
              .then(() => bot.say('op'))
  //          //return bot.setProp('emailVisitor', emailVisitor)
  //           .then(()  => bot.say('Ok - dan hou ik je via ${emailVisitor} op de hoogte.'))
            .then(()  =>'processing')
    }
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say(`Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`),
    receive: () => 'processing'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :)`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
    }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    // prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen? %[JA](postback:nogietsanders) %[NEE](postback:bye) '),
    // .then(()  => 'processing');
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>window.onload=main;

var IMU = {
  absolute: NaN,
  alpha: NaN,
  beta: NaN,
  gamma: NaN,
  acceleration: {x: NaN, y:NaN, z:NaN},
  accelerationIncludingGravity: {x: NaN, y:NaN, z:NaN},
  interval: NaN,
  rotationRate: NaN,
  motion_event: null,
  orientation_event: null,
  abs_accel: NaN
}

function calc() {
  var ddx = IMU.accelerationIncludingGravity.x;
  var ddy = IMU.accelerationIncludingGravity.y;
  var ddz = IMU.accelerationIncludingGravity.z;
  IMU.abs_accel = Math.sqrt(ddx*ddx+ddy*ddy+ddz*ddz);
}

function render() {
  var elem = document.getElementById("aText");
  var s = "";
  s += "absolute: "+IMU.absolute+"
";
  s += "alpha: "+IMU.alpha+"
";
  s += "beta: "+IMU.beta+"
";
  s += "gamma: "+IMU.gamma+"
";
  s += "acceleration.x: "+IMU.acceleration.x+"
";
  s += "acceleration.y: "+IMU.acceleration.y+"
";
  s += "acceleration.z: "+IMU.acceleration.z+"
";
  s += "accelerationRaw.x: "+IMU.accelerationIncludingGravity.x+"
";
  s += "accelerationRaw.y: "+IMU.accelerationIncludingGravity.y+"
";
  s += "accelerationRaw.z: "+IMU.accelerationIncludingGravity.z+"
";
  s += "abs_accel: "+IMU.abs_accel+"
";
  s += "interval: "+IMU.interval+"
";
  s += "rotationRate.alpha: "+IMU.rotationRate.alpha+"
";
  s += "rotationRate.beta: "+IMU.rotationRate.beta+"
";
  s += "rotationRate.gamma: "+IMU.rotationRate.gamma+"
";

  elem.innerHTML = s;
}

function prepareListeners() {
	window.addEventListener("deviceorientation", handleOrientation, true);
	window.addEventListener('devicemotion',  handleMotion, true);
}

function handleOrientation(event) {
  IMU.absolute = event.absolute;
  IMU.alpha    = event.alpha;
  IMU.beta     = event.beta;
  IMU.gamma    = event.gamma;

  render();
}

function handleMotion(event) {
  IMU.acceleration = event.acceleration;
  IMU.accelerationIncludingGravity = event.accelerationIncludingGravity;
  IMU.interval = event.interval;
  IMU.rotationRate = event.rotationRate;

  calc();

  render();
}

function main() {
	render("Ein Test.");
	prepareListeners();
}

<commit_msg>GPS hinzu.<commit_after>window.onload=main;

var IMU = {
  absolute: NaN,
  alpha: NaN,
  beta: NaN,
  gamma: NaN,
  acceleration: {x: NaN, y:NaN, z:NaN},
  accelerationIncludingGravity: {x: NaN, y:NaN, z:NaN},
  interval: NaN,
  rotationRate: NaN,
  motion_event: null,
  orientation_event: null,
  abs_accel: NaN,
  gps: {watchID: null, position: {}, error: false}
}

function calc() {
  var ddx = IMU.accelerationIncludingGravity.x;
  var ddy = IMU.accelerationIncludingGravity.y;
  var ddz = IMU.accelerationIncludingGravity.z;
  IMU.abs_accel = Math.sqrt(ddx*ddx+ddy*ddy+ddz*ddz);
}

function render() {
  var elem = document.getElementById("aText");
  var s = "";
  s += "absolute: "+IMU.absolute+"
";
  s += "alpha: "+IMU.alpha+"
";
  s += "beta: "+IMU.beta+"
";
  s += "gamma: "+IMU.gamma+"
";
  s += "acceleration.x: "+IMU.acceleration.x+"
";
  s += "acceleration.y: "+IMU.acceleration.y+"
";
  s += "acceleration.z: "+IMU.acceleration.z+"
";
  s += "accelerationRaw.x: "+IMU.accelerationIncludingGravity.x+"
";
  s += "accelerationRaw.y: "+IMU.accelerationIncludingGravity.y+"
";
  s += "accelerationRaw.z: "+IMU.accelerationIncludingGravity.z+"
";
  s += "abs_accel: "+IMU.abs_accel+"
";
  s += "interval: "+IMU.interval+"
";
  s += "rotationRate.alpha: "+IMU.rotationRate.alpha+"
";
  s += "rotationRate.beta: "+IMU.rotationRate.beta+"
";
  s += "rotationRate.gamma: "+IMU.rotationRate.gamma+"
";
  s += "gps.position.longitude (WE): "+IMU.gps.position.longitude+"
";
  s += "gps.position.latitude (NS): "+IMU.gps.position.latitude+"
";
  s += "gps.position.altitude (m): "+IMU.gps.position.altitude+"
";
  s += "gps.error: "+IMU.gps.error+"
";

  elem.innerHTML = s;
}

function prepareListeners() {
	window.addEventListener("deviceorientation", handleOrientation, true);
	window.addEventListener('devicemotion',  handleMotion, true);
	IMU.gps.watchID = navigator.geolocation.watchPosition(handleGPSsuccess);
}

function handleOrientation(event) {
  IMU.absolute = event.absolute;
  IMU.alpha    = event.alpha;
  IMU.beta     = event.beta;
  IMU.gamma    = event.gamma;

  render();
}

function handleMotion(event) {
  IMU.acceleration = event.acceleration;
  IMU.accelerationIncludingGravity = event.accelerationIncludingGravity;
  IMU.interval = event.interval;
  IMU.rotationRate = event.rotationRate;

  calc();

  render();
}

function handleGPSsuccess(position) {
  IMU.gps.error = false;
  IMU.gps.position.latitude  = position.coords.latitude;
  IMU.gps.position.longitude = position.coords.longitude;
  IMU.gps.position.altitude = position.coords.altitude;
  render();
}

function handleGPSerror() {
  IMU.gps.error = true;
  render();
}

function main() {
	render("Ein Test.");
	prepareListeners();
}

<|endoftext|>


<commit_before>$(document).ready(function(){

    $("#parsedeck").click(function(){
        $("textarea").hide();
    });

    $("#hand").click(function(event) {

        //alert(event.target.innerHTML)

        discardCount++;
        //alert(discardCount);
        updateDebug();

        $("#discard").append("<img src = '" + event.target.src + "'
");
        $(event.target).remove();

        if (event.target.src == "https://s3.amazonaws.com/pokemontcg/bw5/96.png" && !supporterPlayed)
        {
          alert("N!");
          N();
        }
    });
});

function play()
{
  $("#discard").empty();
  $("#discard").append("

");

  document.getElementById("hand").innerHTML = "";

  deck = [];
  prizes = [];
  discardCount = 0;

  parse();
  deck = shuffle(deck);
  deal(7);
  dealPrizes();

  //deal(1);

  updateDebug();
}

function parse()
{
   var lines = document.getElementById('deckIn').value.split('\n');

   var target = "";
   var badLine = false;

   var totalCount = 0;

   for(var i = 0;i < lines.length;i++){

   	  if (lines[i].includes("on -"))
   	  {
      		target = "pokemon";
      		badLine = true;
   	  }
   	  else if (lines[i].includes("Trainer Cards -"))
   	  {
   	  		target = "trainers"
   	  		badLine = true;
   	  }
   	  else if (lines[i].includes("Energy -"))
   	  {
   	  		target = "energy"
   	  		badLine = true;
   	  }
   	  else if (lines[i].includes("Total Cards"))
   	  {
   	  		badLine = true;
   	  }
   	  else
   	  	badLine = false;

      if (lines[i][0] != '*' && lines[i] != "" && !badLine)
      {
      	var num = lines[i].substr(0, lines[i].indexOf(' '));
      	var j;
      	lines[i] = lines[i].slice(2); // removes the number of card

        var index = lines[i].indexOf(' ');

        var set = lines[i].slice(index);
        //var setUpper = set.toUpper();

        while (set.charAt(2) == set.charAt(2).toLowerCase())
        {
          set = set.slice(1);
          index = set.indexOf(' ');
          set = set.slice(index);
          //set = set.charAt(2);
        }

        var setNo = set.substr(4);
        set = set.substr(0,4);
        var tempset = set.split(' ').join('');
        set = tempset;
        var tempsetNo = setNo.split(' ').join('');
        setNo = tempsetNo;

        var convertedSet = setConvert(set);
        set = convertedSet;

      	for (j = 0; j < num; j++)
      	{
      		if (target == "pokemon")
      			var tempCard = new card(lines[i], "pokemon", set, setNo);
      		else if (target == "trainers")
      			var tempCard = new card(lines[i], "trainer", set, setNo);
      		else if (target == "energy")
      			var tempCard = new card(lines[i], "energy", set, setNo);

          totalCount++;
          deck.push(tempCard);
      	}
	  }
   }
   //document.getElementById("sometext").innerHTML = deck[i].recallName() + " " + deck[i].recallType();
}

function pictodeck(url){
      $.getJSON(url, function(data) {
      var tempCard = new card(data.card.name, "idk", data.card.setCode, data.card.number)
      deck.push(tempCard);
    });
}

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

function deal(num) {
  var i;
  var initialHandLength = hand.length;
  var pos;
  var url;

  for (i = 0; i < num; i++)
  {
    url = 'https://api.pokemontcg.io/v1/cards/' + deck[deck.length - 1].set + "-" + deck[deck.length - 1].setNo;

    $.getJSON(url, function(data) {
      $("#hand").append("");
    });

    //$("#hand").append("
" + deck[deck.length - 1].name + "
");
    deck.pop();
  }
}

function dealPrizes()
{
  var i;

  for (i = 0; i < 6; i++)
  {
    prizes.push(deck[deck.length - 1]);
    deck.pop();
    //document.getElementById("sometext").innerHTML = hand[i].recallName();
  }
}

function playCard(pos)
{
  discard.push(hand[pos]);
/*
  var para = document.createElement("P");
  para.setAttribute("id", "deadcard" + pos);
  para.setAttribute("innerHTML", hand[pos].recallName());
  var node = document.createTextNode(hand[pos].recallName());
  para.appendChild(node);
  document.getElementById("discard").appendChild(para);
*/
  hand.splice(pos, 1);

  var cardsS = document.getElementById('hand');
  cardsS.removeChild(cardsS.childNodes[pos]);

  //alert('card' + pos)
}

function shuffleHandInDeck()
{
  var handLength = $("#hand").children().length;
  var i;
  for (i = 0; i < handLength; i++)
  {
    pictodeck($('#hand').children().first().src)
    $('#hand').children().first().remove();
  }

  shuffle(deck);
}

function updateDebug()
{
  document.getElementById("deckSize").innerHTML = "Deck: " + deck.length;
  document.getElementById("remainingPrizes").innerHTML = "Prizes: " + prizes.length;
  document.getElementById("noDiscard").innerHTML = "Discard: " + discardCount;
}
<commit_msg>Delete script.js<commit_after><|endoftext|>


<commit_before>// Constants
var EVENT_TYPES = ['onclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout'];
var EVENT_TYPES_LENGTH = EVENT_TYPES.length;
var IS_BROWSER = typeof document != 'undefined';
var TEXT_ALIGNMENTS = ['left', 'center', 'right'];

// Constructor
function Entity(defaultAttrHashName, name, canviz, rootGraph, parentGraph, immediateGraph) {
  if (!(this instanceof Entity)) return new Entity(defaultAttrHashName, name, canviz, rootGraph, parentGraph, immediateGraph);
  this.defaultAttrHashName = defaultAttrHashName;
  this.name = name;
  this.canviz = canviz;
  this.rootGraph = rootGraph;
  this.parentGraph = parentGraph;
  this.immediateGraph = immediateGraph;
  this.attrs = {};
  this.drawAttrs = {};
}

// Prototype
Entity.prototype = {
  constructor: Entity,
  initBB: function () {
    var xy = this.getAttr('pos').split(',');
    var x = Number(xy[0]);
    var y = Number(xy[1]);
    this.bbRect = Rect(x, y, x, y);
  },
  getAttr: function (attrName, escString) {
    if (typeof escString == 'undefined') escString = false;
    var self = this;
    var attrValue = this.attrs[attrName];
    if (typeof attrValue == 'undefined') {
      var graph = this.parentGraph;
      while (typeof graph != 'undefined') {
        attrValue = graph[this.defaultAttrHashName][attrName];
        if (typeof attrValue != 'undefined') break;
        graph = graph.parentGraph;
      }
    }
    if (attrValue && escString) {
      attrValue = attrValue.replace(this.ESC_STRING_MATCH_RE, function (match, p1) {
        switch (p1) {
          case 'N': // fall through
          case 'E': return self.name;
          case 'T': return self.tailNode;
          case 'H': return self.headNode;
          case 'G': return self.immediateGraph.name;
          case 'L': return self.getAttr('label', true);
        }
        return match;
      });
    }
    return attrValue;
  },
  draw: function (ctx, ctxScale, redrawCanvasOnly) {
    var i, tokens, fillColor, strokeColor;
    if (!redrawCanvasOnly) {
      this.initBB();
      if (IS_BROWSER) {
        var bbDiv = document.createElement('div');
        var bbScale = this.canviz.bbScale;
        this.canviz.elements.appendChild(bbDiv);
      }
    }
    ctx.lineWidth = 1;
    var keys = objectKeys(this.drawAttrs),
      keysLength = keys.length;
    for (var k = 0; k < keysLength; ++k) {
      var command = this.drawAttrs[keys[k]],
        tokenizer = Tokenizer(command),
        token = tokenizer.takeChars();
//      debug(command);
      if (token) {
        var dashStyle = 'solid';
        ctx.save();
        while (token) {
//          debug('processing token ' + token);
          switch (token) {
            case 'E': // filled ellipse
            case 'e': // unfilled ellipse
              var filled = ('E' == token);
              var cx = tokenizer.takeNumber();
              var cy = tokenizer.takeNumber();
              var rx = tokenizer.takeNumber();
              var ry = tokenizer.takeNumber();
              var path = Ellipse(cx, cy, rx, ry);
              break;
            case 'P': // filled polygon
            case 'p': // unfilled polygon
            case 'L': // polyline
              var filled = ('P' == token);
              var closed = ('L' != token);
              var numPoints = tokenizer.takeNumber();
              tokens = tokenizer.takeNumber(2 * numPoints); // points
              var path = Path();
              for (i = 2; i < 2 * numPoints; i += 2) {
                path.addBezier([
                  Point(tokens[i - 2], tokens[i - 1]),
                  Point(tokens[i], tokens[i + 1])
                ]);
              }
              if (closed) {
                path.addBezier([
                  Point(tokens[2 * numPoints - 2], tokens[2 * numPoints - 1]),
                  Point(tokens[0], tokens[1])
                ]);
              }
              break;
            case 'B': // unfilled b-spline
            case 'b': // filled b-spline
              var filled = ('b' == token);
              var numPoints = tokenizer.takeNumber();
              tokens = tokenizer.takeNumber(2 * numPoints); // points
              var path = Path();
              for (i = 2; i < 2 * numPoints; i += 6) {
                path.addBezier([
                  Point(tokens[i - 2], tokens[i - 1]),
                  Point(tokens[i], tokens[i + 1]),
                  Point(tokens[i + 2], tokens[i + 3]),
                  Point(tokens[i + 4], tokens[i + 5])
                ]);
              }
              break;
            case 'I': // image
              var l = tokenizer.takeNumber();
              var b = tokenizer.takeNumber();
              var w = tokenizer.takeNumber();
              var h = tokenizer.takeNumber();
              var src = tokenizer.takeString();
              if (!this.canviz.images[src]) {
                this.canviz.images[src] = CanvizImage(this.canviz, src);
              }

              ctx.save();
              ctx.translate(l, b);
              // Uninvert the coordinate system so the image isn't drawn upside down.
              if (this.canviz.invertY) ctx.scale(1, -1);
              this.canviz.images[src].draw(ctx, 0, -h, w, h);
              ctx.restore();
              break;
            case 'T': // text
              var x = tokenizer.takeNumber(),
                baseline = tokenizer.takeNumber(),
                textAlignIndex = 1 + tokenizer.takeNumber(),
                textAlign = TEXT_ALIGNMENTS[textAlignIndex],
                textWidth = tokenizer.takeNumber(),
                str = tokenizer.takeString();

              if (!/^\s*$/.test(str)) {
                // Prior to xdotversion 1.5 (Graphviz version 2.33.20130906.0446,
                // git commit 5059989a0e35c3423da5b870480748569c61fb4a) the
                // Y-coordinate of text operations in xdot neglects to take
                // into account the yoffset_centerline. The error for "simple"
                // strings is 0.2 * fontSize and 1 for complex ones;
                // unfortunately xdot does not tell us whether a string is
                // simple or complex. We adjust for the more common simple
                // case, though this causes complex strings to look worse.
                // http://www.graphviz.org/mantisbt/view.php?id=2333
                var yError = this.canviz.bugs.textY * 0.2 * fontSize;
                switch (this.canviz.textMode) {
                  case 'canvas':
                    ctx.save();
                    ctx.translate(x - textAlignIndex * textWidth / 2, baseline);
                    // Uninvert the coordinate system so the text isn't drawn upside down.
                    if (this.canviz.invertY) ctx.scale(1, -1);
                    ctx.font = fontSize + 'px ' + fontFamily;
                    // xdot uses pen color for text, but canvas uses fill color
                    ctx.fillStyle = ctx.strokeStyle;
                    ctx.fillText(str, 0, -yError);
                    ctx.restore();
                    break;
                  case 'dom':
                    if (!redrawCanvasOnly) {
                      str = escapeHtml(str).replace(/ /g, ' ');
                      var left = this.canviz.marginX + bbScale * (this.canviz.paddingX + x - textAlignIndex * textWidth);
                      var top = this.canviz.marginY + bbScale * (this.canviz.paddingY + (this.canviz.invertY ? this.canviz.height - baseline : baseline) - fontSize);
                      var text;
                      var href = this.getAttr('URL', true) || this.getAttr('href', true);
                      if (href) {
                        var target = this.getAttr('target', true) || '_self';
                        var tooltip = this.getAttr('tooltip', true) || this.getAttr('label', true);
//                        debug(this.name + ', href ' + href + ', target ' + target + ', tooltip ' + tooltip);
                        text = document.createElement('a');
                        text.setAttribute('href', href);
                        text.setAttribute('target', target);
                        text.setAttribute('title', tooltip);
                        for (var e = 0; e < EVENT_TYPES_LENGTH; ++e) {
                          var attrName = EVENT_TYPES[e];
                          var attrValue = this.getAttr(attrName, true);
                          if (attrValue) {
                            text.setAttribute(attrName, attrValue);
                          }
                        }
                        text.style.textDecoration = 'none';
                      } else {
                        text = document.createElement('span');
                      }
                      text.innerHTML = str;
                      text.style.fontSize = ctxScale * bbScale * fontSize + 'px';
                      text.style.fontFamily = fontFamily;
                      text.style.color = strokeColor.textColor;
                      text.style.position = 'absolute';
                      text.style.textAlign = textAlign;
                      text.style.left = ctxScale * left + 'px';
                      text.style.top = ctxScale * top + 'px';
                      text.style.width = ctxScale * bbScale * 2 * textWidth + 'px';
                      if (strokeColor.opacity < 1) setOpacity(text, strokeColor.opacity);
                      this.canviz.elements.appendChild(text);
                    }
                    break;
                }
              }
              break;
            case 'C': // set fill color
            case 'c': // set pen color
              var fill = ('C' == token);
              var color = this.parseColor(tokenizer.takeString());
              if (fill) {
                fillColor = color;
                ctx.fillStyle = color.canvasColor;
              } else {
                strokeColor = color;
                ctx.strokeStyle = color.canvasColor;
              }
              break;
            case 'F': // set font
              var fontSize = tokenizer.takeNumber();
              var fontFamily = tokenizer.takeString();
              if (fontFamily == 'Times-Roman') fontFamily = 'Times';
//              debug('set font ' + fontSize + 'pt ' + fontFamily);
              break;
            case 'S': // set style
              var style = tokenizer.takeString();
              switch (style) {
                case 'dashed':
                case 'dotted':
                  dashStyle = style;
                  break;
                case 'bold':
                  ctx.lineWidth = 2;
                  break;
                default:
                  var matches = style.match(/^setlinewidth\((.*)\)$/);
                  if (matches) {
                    ctx.lineWidth = Number(matches[1]);
                  }
              }
              break;
            default:
              debug('unknown token ' + token);
              return;
          }
          if (path) {
            this.canviz.drawPath(ctx, path, filled, dashStyle);
            if (!redrawCanvasOnly) this.bbRect.expandToInclude(path.getBB());
            path = undefined;
          }
          token = tokenizer.takeChars();
        }
        if (IS_BROWSER && !redrawCanvasOnly) {
          bbDiv.style.position = 'absolute';
          bbDiv.style.left = Math.round(ctxScale * (this.canviz.marginX + bbScale * (this.canviz.paddingX + this.bbRect.l))) + 'px';
          var y = Math.round(ctxScale * (this.canviz.marginY + bbScale * (this.canviz.paddingY + this.bbRect.t)));
          var h = Math.round(ctxScale * bbScale * this.bbRect.getHeight());
          bbDiv.style.top = (this.canviz.invertY ? this.canviz.canvas.height - y - h : y) + 'px';
          bbDiv.style.width = Math.round(ctxScale * bbScale * this.bbRect.getWidth()) + 'px';
          bbDiv.style.height = h + 'px';
        }
        ctx.restore();
      }
    }
  },
  parseColor: function (color) {
    var parsedColor = {opacity: 1};
    // rgb/rgba
    if (/^#(?:[0-9a-f]{2}\s*){3,4}$/i.test(color)) {
      return parseHexColor(color);
    }
    // hsv
    var matches = color.match(/^(\d+(?:\.\d+)?)[\s,]+(\d+(?:\.\d+)?)[\s,]+(\d+(?:\.\d+)?)$/);
    if (matches) {
      parsedColor.canvasColor = parsedColor.textColor = hsvToRgbColor(matches[1], matches[2], matches[3]);
      return parsedColor;
    }
    // gradient
    matches = color.match(/^(\[[^\]]+\]|\(([^)]+)\))$/);
    if (matches) {
      var ctx = this.canviz.ctx;
      var match = matches[1];
      var radial = matches[2];
      var tokenizer = Tokenizer(match.substr(1, match.length - 2));
      var x0 = tokenizer.takeNumber();
      var y0 = tokenizer.takeNumber();
      var r0, x1, y1, r1, colorStops, gradient;
      if (radial) r0 = tokenizer.takeNumber();
      x1 = tokenizer.takeNumber();
      y1 = tokenizer.takeNumber();
      if (this.canviz.bugs.gradY) {
        // Prior to xdotversion 1.5 (Graphviz version 2.33.20130907.0446, git
        // commit 7baedbfdd2607942bd74cc22fe6130aceb5dc0fc) the gradient
        // Y-coordinate is inadvertently mirrored across the bottom edge of the
        // graph. http://graphviz.org/mantisbt/view.php?id=2336
        if (this.canviz.invertY) {
          y0 *= -1;
          y1 *= -1;
        } else {
          y0 -= this.canviz.height;
          y1 -= this.canviz.height;
          r1 = y1;
          y1 = y0;
          y0 = r1;
        }
      }
      if (radial) {
        r1 = tokenizer.takeNumber();
        gradient = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
      } else {
        gradient = ctx.createLinearGradient(x0, y0, x1, y1);
      }
      colorStops = tokenizer.takeNumber();
      while (colorStops--) {
        gradient.addColorStop(tokenizer.takeNumber(), tokenizer.takeString());
      }
      parsedColor.canvasColor = gradient;
      return parsedColor;
    }
    // named color
    var colorScheme = this.getAttr('colorscheme') || 'X11';
    var colorName = color;
    matches = color.match(/^\/(.*)\/(.*)$/);
    if (matches) {
      if (matches[1]) {
        colorScheme = matches[1];
      }
      colorName = matches[2];
    } else {
      matches = color.match(/^\/(.*)$/);
      if (matches) {
        colorScheme = 'X11';
        colorName = matches[1];
      }
    }
    colorName = colorName.toLowerCase();
    var colorSchemeName = colorScheme.toLowerCase();
    var colorSchemeData = Canviz.colors[colorSchemeName];
    if (colorSchemeData) {
      var colorData = colorSchemeData[colorName];
      if (colorData) {
        return parseHexColor('#' + colorData);
      }
    }
    colorData = Canviz.colors.fallback[colorName];
    if (colorData) {
      return parseHexColor('#' + colorData);
    }
    if (!colorSchemeData) {
      debug('unknown color scheme ' + colorScheme);
    }
    // unknown
    debug('unknown color ' + color + '; color scheme is ' + colorScheme);
    parsedColor.canvasColor = parsedColor.textColor = '#000000';
    return parsedColor;
  }
};

// Exports
module.exports = Entity;

// Dependencies
var Canviz = require('./Canviz.js');
var CanvizImage = require('./Image.js');
var debug = require('./debug.js');
var Ellipse = require('./path/Ellipse.js');
var escapeHtml = require('escape-html');
var hsvToRgbColor = require('./hsvToRgbColor.js');
var objectKeys = require('./path/objectKeys.js');
var parseHexColor = require('./parseHexColor.js');
var Path = require('./path/Path.js');
var Point = require('./path/Point.js');
var Rect = require('./path/Rect.js');
var setOpacity = require('./setOpacity.js');
var Tokenizer = require('./Tokenizer.js');
<commit_msg>update comment<commit_after>// Constants
var EVENT_TYPES = ['onclick', 'onmousedown', 'onmouseup', 'onmouseover', 'onmousemove', 'onmouseout'];
var EVENT_TYPES_LENGTH = EVENT_TYPES.length;
var IS_BROWSER = typeof document != 'undefined';
var TEXT_ALIGNMENTS = ['left', 'center', 'right'];

// Constructor
function Entity(defaultAttrHashName, name, canviz, rootGraph, parentGraph, immediateGraph) {
  if (!(this instanceof Entity)) return new Entity(defaultAttrHashName, name, canviz, rootGraph, parentGraph, immediateGraph);
  this.defaultAttrHashName = defaultAttrHashName;
  this.name = name;
  this.canviz = canviz;
  this.rootGraph = rootGraph;
  this.parentGraph = parentGraph;
  this.immediateGraph = immediateGraph;
  this.attrs = {};
  this.drawAttrs = {};
}

// Prototype
Entity.prototype = {
  constructor: Entity,
  initBB: function () {
    var xy = this.getAttr('pos').split(',');
    var x = Number(xy[0]);
    var y = Number(xy[1]);
    this.bbRect = Rect(x, y, x, y);
  },
  getAttr: function (attrName, escString) {
    if (typeof escString == 'undefined') escString = false;
    var self = this;
    var attrValue = this.attrs[attrName];
    if (typeof attrValue == 'undefined') {
      var graph = this.parentGraph;
      while (typeof graph != 'undefined') {
        attrValue = graph[this.defaultAttrHashName][attrName];
        if (typeof attrValue != 'undefined') break;
        graph = graph.parentGraph;
      }
    }
    if (attrValue && escString) {
      attrValue = attrValue.replace(this.ESC_STRING_MATCH_RE, function (match, p1) {
        switch (p1) {
          case 'N': // fall through
          case 'E': return self.name;
          case 'T': return self.tailNode;
          case 'H': return self.headNode;
          case 'G': return self.immediateGraph.name;
          case 'L': return self.getAttr('label', true);
        }
        return match;
      });
    }
    return attrValue;
  },
  draw: function (ctx, ctxScale, redrawCanvasOnly) {
    var i, tokens, fillColor, strokeColor;
    if (!redrawCanvasOnly) {
      this.initBB();
      if (IS_BROWSER) {
        var bbDiv = document.createElement('div');
        var bbScale = this.canviz.bbScale;
        this.canviz.elements.appendChild(bbDiv);
      }
    }
    ctx.lineWidth = 1;
    var keys = objectKeys(this.drawAttrs),
      keysLength = keys.length;
    for (var k = 0; k < keysLength; ++k) {
      var command = this.drawAttrs[keys[k]],
        tokenizer = Tokenizer(command),
        token = tokenizer.takeChars();
//      debug(command);
      if (token) {
        var dashStyle = 'solid';
        ctx.save();
        while (token) {
//          debug('processing token ' + token);
          switch (token) {
            case 'E': // filled ellipse
            case 'e': // unfilled ellipse
              var filled = ('E' == token);
              var cx = tokenizer.takeNumber();
              var cy = tokenizer.takeNumber();
              var rx = tokenizer.takeNumber();
              var ry = tokenizer.takeNumber();
              var path = Ellipse(cx, cy, rx, ry);
              break;
            case 'P': // filled polygon
            case 'p': // unfilled polygon
            case 'L': // polyline
              var filled = ('P' == token);
              var closed = ('L' != token);
              var numPoints = tokenizer.takeNumber();
              tokens = tokenizer.takeNumber(2 * numPoints); // points
              var path = Path();
              for (i = 2; i < 2 * numPoints; i += 2) {
                path.addBezier([
                  Point(tokens[i - 2], tokens[i - 1]),
                  Point(tokens[i], tokens[i + 1])
                ]);
              }
              if (closed) {
                path.addBezier([
                  Point(tokens[2 * numPoints - 2], tokens[2 * numPoints - 1]),
                  Point(tokens[0], tokens[1])
                ]);
              }
              break;
            case 'B': // unfilled b-spline
            case 'b': // filled b-spline
              var filled = ('b' == token);
              var numPoints = tokenizer.takeNumber();
              tokens = tokenizer.takeNumber(2 * numPoints); // points
              var path = Path();
              for (i = 2; i < 2 * numPoints; i += 6) {
                path.addBezier([
                  Point(tokens[i - 2], tokens[i - 1]),
                  Point(tokens[i], tokens[i + 1]),
                  Point(tokens[i + 2], tokens[i + 3]),
                  Point(tokens[i + 4], tokens[i + 5])
                ]);
              }
              break;
            case 'I': // image
              var l = tokenizer.takeNumber();
              var b = tokenizer.takeNumber();
              var w = tokenizer.takeNumber();
              var h = tokenizer.takeNumber();
              var src = tokenizer.takeString();
              if (!this.canviz.images[src]) {
                this.canviz.images[src] = CanvizImage(this.canviz, src);
              }

              ctx.save();
              ctx.translate(l, b);
              // Uninvert the coordinate system so the image isn't drawn upside down.
              if (this.canviz.invertY) ctx.scale(1, -1);
              this.canviz.images[src].draw(ctx, 0, -h, w, h);
              ctx.restore();
              break;
            case 'T': // text
              var x = tokenizer.takeNumber(),
                baseline = tokenizer.takeNumber(),
                textAlignIndex = 1 + tokenizer.takeNumber(),
                textAlign = TEXT_ALIGNMENTS[textAlignIndex],
                textWidth = tokenizer.takeNumber(),
                str = tokenizer.takeString();

              if (!/^\s*$/.test(str)) {
                // Prior to xdotversion 1.5 (Graphviz version 2.33.20130906.0446,
                // git commit 5059989a0e35c3423da5b870480748569c61fb4a) the
                // Y-coordinate of text operations in xdot neglects to take
                // into account the yoffset_centerline. The error for "simple"
                // strings is 0.2 * fontSize and 1 for complex ones;
                // unfortunately xdot does not tell us whether a string is
                // simple or complex. We adjust for the more common simple
                // case, though this causes complex strings to look worse.
                // http://www.graphviz.org/mantisbt/view.php?id=2333
                var yError = this.canviz.bugs.textY * 0.2 * fontSize;
                switch (this.canviz.textMode) {
                  case 'canvas':
                    ctx.save();
                    ctx.translate(x - textAlignIndex * textWidth / 2, baseline);
                    // Uninvert the coordinate system so the text isn't drawn upside down.
                    if (this.canviz.invertY) ctx.scale(1, -1);
                    ctx.font = fontSize + 'px ' + fontFamily;
                    // xdot uses pen color for text, but canvas uses fill color
                    ctx.fillStyle = ctx.strokeStyle;
                    ctx.fillText(str, 0, -yError);
                    ctx.restore();
                    break;
                  case 'dom':
                    if (!redrawCanvasOnly) {
                      str = escapeHtml(str).replace(/ /g, ' ');
                      var left = this.canviz.marginX + bbScale * (this.canviz.paddingX + x - textAlignIndex * textWidth);
                      var top = this.canviz.marginY + bbScale * (this.canviz.paddingY + (this.canviz.invertY ? this.canviz.height - baseline : baseline) - fontSize);
                      var text;
                      var href = this.getAttr('URL', true) || this.getAttr('href', true);
                      if (href) {
                        var target = this.getAttr('target', true) || '_self';
                        var tooltip = this.getAttr('tooltip', true) || this.getAttr('label', true);
//                        debug(this.name + ', href ' + href + ', target ' + target + ', tooltip ' + tooltip);
                        text = document.createElement('a');
                        text.setAttribute('href', href);
                        text.setAttribute('target', target);
                        text.setAttribute('title', tooltip);
                        for (var e = 0; e < EVENT_TYPES_LENGTH; ++e) {
                          var attrName = EVENT_TYPES[e];
                          var attrValue = this.getAttr(attrName, true);
                          if (attrValue) {
                            text.setAttribute(attrName, attrValue);
                          }
                        }
                        text.style.textDecoration = 'none';
                      } else {
                        text = document.createElement('span');
                      }
                      text.innerHTML = str;
                      text.style.fontSize = ctxScale * bbScale * fontSize + 'px';
                      text.style.fontFamily = fontFamily;
                      text.style.color = strokeColor.textColor;
                      text.style.position = 'absolute';
                      text.style.textAlign = textAlign;
                      text.style.left = ctxScale * left + 'px';
                      text.style.top = ctxScale * top + 'px';
                      text.style.width = ctxScale * bbScale * 2 * textWidth + 'px';
                      if (strokeColor.opacity < 1) setOpacity(text, strokeColor.opacity);
                      this.canviz.elements.appendChild(text);
                    }
                    break;
                }
              }
              break;
            case 'C': // set fill color
            case 'c': // set pen color
              var fill = ('C' == token);
              var color = this.parseColor(tokenizer.takeString());
              if (fill) {
                fillColor = color;
                ctx.fillStyle = color.canvasColor;
              } else {
                strokeColor = color;
                ctx.strokeStyle = color.canvasColor;
              }
              break;
            case 'F': // set font
              var fontSize = tokenizer.takeNumber();
              var fontFamily = tokenizer.takeString();
              if (fontFamily == 'Times-Roman') fontFamily = 'Times';
//              debug('set font ' + fontSize + 'pt ' + fontFamily);
              break;
            case 'S': // set style
              var style = tokenizer.takeString();
              switch (style) {
                case 'dashed':
                case 'dotted':
                  dashStyle = style;
                  break;
                case 'bold':
                  ctx.lineWidth = 2;
                  break;
                default:
                  var matches = style.match(/^setlinewidth\((.*)\)$/);
                  if (matches) {
                    ctx.lineWidth = Number(matches[1]);
                  }
              }
              break;
            default:
              debug('unknown token ' + token);
              return;
          }
          if (path) {
            this.canviz.drawPath(ctx, path, filled, dashStyle);
            if (!redrawCanvasOnly) this.bbRect.expandToInclude(path.getBB());
            path = undefined;
          }
          token = tokenizer.takeChars();
        }
        if (IS_BROWSER && !redrawCanvasOnly) {
          bbDiv.style.position = 'absolute';
          bbDiv.style.left = Math.round(ctxScale * (this.canviz.marginX + bbScale * (this.canviz.paddingX + this.bbRect.l))) + 'px';
          var y = Math.round(ctxScale * (this.canviz.marginY + bbScale * (this.canviz.paddingY + this.bbRect.t)));
          var h = Math.round(ctxScale * bbScale * this.bbRect.getHeight());
          bbDiv.style.top = (this.canviz.invertY ? this.canviz.canvas.height - y - h : y) + 'px';
          bbDiv.style.width = Math.round(ctxScale * bbScale * this.bbRect.getWidth()) + 'px';
          bbDiv.style.height = h + 'px';
        }
        ctx.restore();
      }
    }
  },
  parseColor: function (color) {
    var parsedColor = {opacity: 1};
    // rgb/rgba
    if (/^#(?:[0-9a-f]{2}\s*){3,4}$/i.test(color)) {
      return parseHexColor(color);
    }
    // hsv
    var matches = color.match(/^(\d+(?:\.\d+)?)[\s,]+(\d+(?:\.\d+)?)[\s,]+(\d+(?:\.\d+)?)$/);
    if (matches) {
      parsedColor.canvasColor = parsedColor.textColor = hsvToRgbColor(matches[1], matches[2], matches[3]);
      return parsedColor;
    }
    // gradient
    matches = color.match(/^(\[[^\]]+\]|\(([^)]+)\))$/);
    if (matches) {
      var ctx = this.canviz.ctx;
      var match = matches[1];
      var radial = matches[2];
      var tokenizer = Tokenizer(match.substr(1, match.length - 2));
      var x0 = tokenizer.takeNumber();
      var y0 = tokenizer.takeNumber();
      var r0, x1, y1, r1, colorStops, gradient;
      if (radial) r0 = tokenizer.takeNumber();
      x1 = tokenizer.takeNumber();
      y1 = tokenizer.takeNumber();
      if (this.canviz.bugs.gradY) {
        // Prior to xdotversion 1.5 (Graphviz version 2.34.0, git commit
        // 7baedbfdd2607942bd74cc22fe6130aceb5dc0fc) the gradient Y-coordinate
        // is inadvertently mirrored across the bottom edge of the graph.
        // http://graphviz.org/mantisbt/view.php?id=2336
        if (this.canviz.invertY) {
          y0 *= -1;
          y1 *= -1;
        } else {
          y0 -= this.canviz.height;
          y1 -= this.canviz.height;
          r1 = y1;
          y1 = y0;
          y0 = r1;
        }
      }
      if (radial) {
        r1 = tokenizer.takeNumber();
        gradient = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
      } else {
        gradient = ctx.createLinearGradient(x0, y0, x1, y1);
      }
      colorStops = tokenizer.takeNumber();
      while (colorStops--) {
        gradient.addColorStop(tokenizer.takeNumber(), tokenizer.takeString());
      }
      parsedColor.canvasColor = gradient;
      return parsedColor;
    }
    // named color
    var colorScheme = this.getAttr('colorscheme') || 'X11';
    var colorName = color;
    matches = color.match(/^\/(.*)\/(.*)$/);
    if (matches) {
      if (matches[1]) {
        colorScheme = matches[1];
      }
      colorName = matches[2];
    } else {
      matches = color.match(/^\/(.*)$/);
      if (matches) {
        colorScheme = 'X11';
        colorName = matches[1];
      }
    }
    colorName = colorName.toLowerCase();
    var colorSchemeName = colorScheme.toLowerCase();
    var colorSchemeData = Canviz.colors[colorSchemeName];
    if (colorSchemeData) {
      var colorData = colorSchemeData[colorName];
      if (colorData) {
        return parseHexColor('#' + colorData);
      }
    }
    colorData = Canviz.colors.fallback[colorName];
    if (colorData) {
      return parseHexColor('#' + colorData);
    }
    if (!colorSchemeData) {
      debug('unknown color scheme ' + colorScheme);
    }
    // unknown
    debug('unknown color ' + color + '; color scheme is ' + colorScheme);
    parsedColor.canvasColor = parsedColor.textColor = '#000000';
    return parsedColor;
  }
};

// Exports
module.exports = Entity;

// Dependencies
var Canviz = require('./Canviz.js');
var CanvizImage = require('./Image.js');
var debug = require('./debug.js');
var Ellipse = require('./path/Ellipse.js');
var escapeHtml = require('escape-html');
var hsvToRgbColor = require('./hsvToRgbColor.js');
var objectKeys = require('./path/objectKeys.js');
var parseHexColor = require('./parseHexColor.js');
var Path = require('./path/Path.js');
var Point = require('./path/Point.js');
var Rect = require('./path/Rect.js');
var setOpacity = require('./setOpacity.js');
var Tokenizer = require('./Tokenizer.js');
<|endoftext|>