contract Eth2x is usingOraclize {
    
     using strings for *;
     using SafeMath for uint256;

    /*
     * checks game is currently active
    */
    modifier gameIsActive {
        if(gamePaused == true) throw;
		_;
    }    

    /*
     * checks payouts are currently active
    */
    modifier payoutsAreActive {
        if(payoutsPaused == true) throw;
		_;
    }    

    /*
     * checks only Oraclize address is calling
    */
    modifier onlyOraclize {
        if (msg.sender != oraclize_cbAddress()) throw;
        _;
    }

    /*
     * checks only owner address is calling
    */
    modifier onlyOwner {
         if (msg.sender != owner) throw;
         _;
    }
    

    /*
     * game vars
    */     
    uint public maxNumber = 15; 
    uint constant public minNumber = 0;
    uint256 public lastamountSent = 0;
    
	bool public gamePaused;
    uint32 public gasForOraclize;
    address public owner;
    bool public payoutsPaused;
    uint public contractBalance;                  
    uint public minBet; 
    //init discontinued contract data       
    uint public maxPlayers = 100;
    uint public maxPendingPayouts;
    //init discontinued contract data   
    uint public totalWeiWon = 0;
    //init discontinued contract data     
    uint public totalWeiWagered = 0; 
    uint public randomQueryID;
    uint public ownerProfitInPercent = 2;
    

    /*
     * player vars
    */
    address[] public players;
    address[] public playersRollsZero;
    address[] public playersRollsOneToSeven;
    address[] public playersRollsEightToFourteen;
    mapping(address => bytes32) public playerBetNo;
    mapping(address => uint256) public playerBetAmountOnZero;
    mapping(address => uint256) public playerBetAmountOnOneToSeven;
    mapping(address => uint256) public playerBetAmountOnEightToFourteen;
    
    uint public TotalBetAmount;
    uint public TotalBetOnZero;
    uint public TotalBetOneToSeven;
    uint public TotalBetEightToFourteen;

    mapping (address => uint) playerPendingWithdrawals;        

    /*
     * events
    */
    /* log manual refunds */
    event LogRefund(bytes32 BetID, address PlayerAddress, uint RefundValue);
    
    /* log owner transfers */
    event LogOwnerTransfer(address SentToAddress, uint AmountTransferred);               

    event LogPlayerTransfer(address SentToAddress, uint AmountTransferred);
    
    event logResult(uint _chosenNumber);

    /*
     * init
    */
    function Eth2x() {

        owner = msg.sender;
        oraclize_setNetwork(networkID_auto);        
        /* use TLSNotary for oraclize call */
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);

        /* init min bet (0.1 ether) */
        ownerSetMinBet(100000000000000000);        
        /* init gas for oraclize */        
        gasForOraclize = 535000;  
        /* init gas price for callback (default 20 gwei)*/
        oraclize_setCustomGasPrice(26000000000 wei);              

    }

    /* enter into the game */
    function enter(bytes32 _playerBetNo) public gameIsActive payable {
        require (msg.value >= minBet);
        require (players.length <= maxPlayers);
        
        playerBetNo[msg.sender] = _playerBetNo;
        TotalBetAmount = TotalBetAmount.add(msg.value);
        
        if(_playerBetNo == sha3("Zero") ){
            
            //check for duplicate entry
            if(playerBetAmountOnZero[msg.sender] == 0){
                players.push(msg.sender);
                playersRollsZero.push(msg.sender);
            }
            
            playerBetAmountOnZero[msg.sender] = playerBetAmountOnZero[msg.sender].add(msg.value);
            TotalBetOnZero = TotalBetOnZero.add(msg.value);
        } 
        else if(_playerBetNo == sha3("OneToSeven") ){
            
            //check for duplicate entry
            if(playerBetAmountOnOneToSeven[msg.sender] == 0){
                players.push(msg.sender);
                playersRollsOneToSeven.push(msg.sender);
            }
            
            playerBetAmountOnOneToSeven[msg.sender] = playerBetAmountOnOneToSeven[msg.sender].add(msg.value);
            TotalBetOneToSeven = TotalBetOneToSeven.add(msg.value);
        }
        else if(_playerBetNo == sha3("EightToFourteen") ){
            
            //check for duplicate entry
            if(playerBetAmountOnEightToFourteen[msg.sender] == 0){
                players.push(msg.sender);
                playersRollsEightToFourteen.push(msg.sender);
            }
            
            playerBetAmountOnEightToFourteen[msg.sender] = playerBetAmountOnEightToFourteen[msg.sender].add(msg.value);
            TotalBetEightToFourteen = TotalBetEightToFourteen.add(msg.value);
        }
    }
    
    /*
    * get players
    */
    function getAllPlayers() view public returns (address[])
    {
        return players;
    }
    
    function getPlayersRollsZero() view public returns (address[])
    {
        return playersRollsZero;
    }
    
    function getPlayersRollsOneToSeven() view public returns (address[])
    {
        return playersRollsOneToSeven;
    }
    
    function getPlayersRollsEightToFourteen() view public returns (address[])
    {
        return playersRollsEightToFourteen;
    }
    
    /*
    * get players bet no and amount
    */
    function getPlayerBetNo(address _player) constant public returns (bytes32 betNo) {
        return playerBetNo[_player];
    }
    
    function getPlayerBetAmountOnZero(address _player) constant public returns (uint256 getAmount) {
        return playerBetAmountOnZero[_player];
    }
    
    function getPlayerBetAmountOnOneToSeven(address _player) constant public returns (uint256 getAmount) {
        return playerBetAmountOnOneToSeven[_player];
    }
    
    function getPlayerBetAmountOnEightToFourteen(address _player) constant public returns (uint256 getAmount) {
        return playerBetAmountOnEightToFourteen[_player];
    }
    
    /*
    * get players bet amount
    */
    function getTotalBetAmount() constant public returns (uint256 _totalBetAmount) {
        return TotalBetAmount;
    }
    
    function getTotalBetOnZero() constant public returns (uint256 _totalBetOnZero) {
        return TotalBetOnZero;
    }
    
    function getTotalBetOneToSeven() constant public returns (uint256 _totalBetOneToSeven) {
        return TotalBetOneToSeven;
    }
    
    function getTotalBetEightToFourteen() constant public returns (uint256 _totalBetEightToFourteen) {
        return TotalBetEightToFourteen;
    }
    
    function getLastamountSent() constant public returns (uint256 _lastamountSent) {
        return lastamountSent;
    }
    
    
    /*
     * public function
     * player submit bet
     * only if game is active & bet is valid can query oraclize and set player vars     
    */
    function pickWinner(uint randomNo) internal {
       uint TotalBetAmount1 = TotalBetAmount.mul(ownerProfitInPercent);
            TotalBetAmount1 = TotalBetAmount1.div(100);
            TotalBetAmount1 = TotalBetAmount.sub(TotalBetAmount1);
       
       lastamountSent = 0;    
       uint playerLength; address sendTo; uint betamount; uint percnt; uint i; uint ethToSend;
       if(randomNo == 0){
            playerLength = playersRollsZero.length;
            for (i=0; i<playerLength; i++) {
                /*get percentage of player bet amount*/
                betamount = playerBetAmountOnZero[playersRollsZero[i]].mul(100);
                percnt = betamount.div(TotalBetOnZero);
                
                ethToSend = TotalBetAmount1.mul(percnt);
                ethToSend = ethToSend.div(100);
                
                //player should win max 14x amount
                if(ethToSend > (playerBetAmountOnZero[playersRollsZero[i]].mul(14))){
                    ethToSend = playerBetAmountOnZero[playersRollsZero[i]].mul(14);
                }
                
                sendTo = playersRollsZero[i];
                
                if(!sendTo.send(ethToSend)){
                    playerPendingWithdrawals[sendTo] = playerPendingWithdrawals[sendTo].add(betamount);
                }
                
                lastamountSent = lastamountSent.add(ethToSend);
                LogPlayerTransfer(sendTo, ethToSend);
            }
            
        } 
        else if(randomNo > 0 && randomNo < 8){
            playerLength = playersRollsOneToSeven.length;
            for (i=0; i<playerLength; i++) {
                /*get percentage of player bet amount*/
                betamount = playerBetAmountOnOneToSeven[playersRollsOneToSeven[i]].mul(100);
                percnt = betamount.div(TotalBetOneToSeven);
                
                ethToSend = TotalBetAmount1.mul(percnt);
                ethToSend = ethToSend.div(100);
                
                //player should win max 14x amount
                if(ethToSend > (playerBetAmountOnOneToSeven[playersRollsOneToSeven[i]].mul(2))){
                    ethToSend = playerBetAmountOnOneToSeven[playersRollsOneToSeven[i]].mul(2);
                }
                
                sendTo = playersRollsOneToSeven[i];
                
                if(!sendTo.send(ethToSend)){
                    playerPendingWithdrawals[sendTo] = playerPendingWithdrawals[sendTo].add(betamount);
                }
                
                lastamountSent = lastamountSent.add(ethToSend);
                LogPlayerTransfer(sendTo, ethToSend);
            }
        }
        else if(randomNo > 7 && randomNo <= 14){
            playerLength = playersRollsEightToFourteen.length;
            for (i=0; i<playerLength; i++) {
                /*get percentage of player bet amount*/
                betamount = playerBetAmountOnEightToFourteen[playersRollsEightToFourteen[i]].mul(100);
                percnt = betamount.div(TotalBetEightToFourteen);
                
                ethToSend = TotalBetAmount1.mul(percnt);
                ethToSend = ethToSend.div(100);
                
                //player should win max 14x amount
                if(ethToSend > (playerBetAmountOnEightToFourteen[playersRollsEightToFourteen[i]].mul(2))){
                    ethToSend = playerBetAmountOnEightToFourteen[playersRollsEightToFourteen[i]].mul(2);
                }
                
                sendTo = playersRollsEightToFourteen[i];
                
                if(!sendTo.send(ethToSend)){
                    playerPendingWithdrawals[sendTo] = playerPendingWithdrawals[sendTo].add(betamount);
                }
                
                lastamountSent = lastamountSent.add(ethToSend);
                LogPlayerTransfer(sendTo, ethToSend);
            }
        }
        
        //store log
        logResult(randomNo);
        
        //clear vars
        TotalBetAmount = 0;
        TotalBetOnZero = 0;
        TotalBetOneToSeven = 0;
        TotalBetEightToFourteen = 0;
        
        playersRollsZero.length = 0;
        playersRollsOneToSeven.length = 0;
        playersRollsEightToFourteen.length = 0;
        
        uint j;
        for(j=0; j<players.length; j++){
            playerBetAmountOnZero[players[j]] = 0;
            playerBetAmountOnOneToSeven[players[j]] = 0;
            playerBetAmountOnEightToFourteen[players[j]] = 0;
            playerBetNo[players[j]] = 0;
        }
        
        players.length = 0;
       
    }
             

    function rollIt() public onlyOwner {
        oraclize_setProof(proofType_Ledger); // sets the Ledger authenticity proof
        uint N = 4; // number of random bytes we want the datasource to return
        uint delay = 0; // number of seconds to wait before the execution takes place
        
        bytes32 queryId = oraclize_newRandomDSQuery(delay, N, gasForOraclize); // this function internally generates the correct oraclize_query and returns its queryId
    }
    /*
    * semi-public function - only oraclize can call
    */
    /*TLSNotary for oraclize call */
	function __callback(bytes32 _queryId, string _result, bytes _proof) public   
		onlyOraclize
		payoutsAreActive
	{  
	    if (bytes(_result).length != 0 || bytes(_proof).length != 0) {
        
            uint randomNumber = uint(sha3(_result)) % maxNumber; // this is an efficient way to get the uint out in the [0, maxRange] range
            
            pickWinner(randomNumber); //call winner funation
         }
    }
    
    /*
    * public function
    * in case of a failed refund or win send
    */
    function playerWithdrawPendingTransactions() public 
        payoutsAreActive
        returns (bool)
    {
        uint withdrawAmount = playerPendingWithdrawals[msg.sender];
        playerPendingWithdrawals[msg.sender] = 0;
        /* external call to untrusted contract */
        if (msg.sender.send(withdrawAmount)) {
            return true;
        } else {
            /* if send failed revert playerPendingWithdrawals[msg.sender] = 0; */
            /* player can try to withdraw again later */
            playerPendingWithdrawals[msg.sender] = withdrawAmount;
            return false;
        }
    }

    /* check for pending withdrawals  */
    function playerGetPendingTxByAddress(address addressToCheck) public constant returns (uint) {
        return playerPendingWithdrawals[addressToCheck];
    }      

    /* set gas price for oraclize callback */
    function ownerSetCallbackGasPrice(uint newCallbackGasPrice) public 
		onlyOwner
	{
        oraclize_setCustomGasPrice(newCallbackGasPrice);
    }     

    /* set gas limit for oraclize query */
    function ownerSetOraclizeSafeGas(uint32 newSafeGasToOraclize) public 
		onlyOwner
	{
    	gasForOraclize = newSafeGasToOraclize;
    }
    

    /* only owner address can set ownerProfitInPercent */
    function setOwnerProfitInPercent(uint newMaxProfitAsPercent) public 
		onlyOwner
    {
        ownerProfitInPercent = newMaxProfitAsPercent;
    }

    /* only owner address can set minBet */
    function ownerSetMinBet(uint newMinimumBet) public 
		onlyOwner
    {
        minBet = newMinimumBet;
    }
    
    /* only owner address can set maxNumber */
    function ownerSetmaxNumber(uint newmaxNumber) public 
		onlyOwner
    {
        maxNumber = newmaxNumber;
    }
    
    /* only owner address can set maxPlayers */
    function ownerSetmaxPlayers(uint newmaxPlayers) public 
		onlyOwner
    {
        maxPlayers = newmaxPlayers;
    }

    /* only owner address can transfer ether */
    function ownerTransferEther(address sendTo, uint amount) public 
		onlyOwner
    {        
        /* update max profit */
        if(!sendTo.send(amount)) throw;
        LogOwnerTransfer(sendTo, amount); 
    }
    

    /* only owner address can set emergency pause #1 */
    function ownerPauseGame(bool newStatus) public 
		onlyOwner
    {
		gamePaused = newStatus;
    }

    /* only owner address can set emergency pause #2 */
    function ownerPausePayouts(bool newPayoutStatus) public 
		onlyOwner
    {
		payoutsPaused = newPayoutStatus;
    }   

    /* only owner address can set owner address */
    function ownerChangeOwner(address newOwner) public 
		onlyOwner
	{
        owner = newOwner;
    }

    /* only owner address can suicide - emergency */
    function ownerkill() public 
		onlyOwner
	{
		suicide(owner);
	}    

}
function ownerPausePayouts(bool newPayoutStatus) public 
lyOwner
{
youtsPaused = newPayoutStatus;
}   

/* only owner address can set emergency pause #2 */