// Contract: JackPot
// Target function: function transferFrom(address _from, address _to, uint256 _value) public returns (bool)
6(abi.encodePacked(seed1, seed2, seed3, seed4, seed5, seed6, seed7));
        uint randomNumber = uint(randomHash);

        if (randomNumber == 0){
            randomNumber = 1;
        }

        uint winningNumber = randomNumber % 10000;

        if (1 <= winningNumber && winningNumber <= probabilityOfDragons){
            winner = 1;
        }

        if (probabilityOfDragons < winningNumber && winningNumber <= 10000){
            winner = 2;
        }
    }

    /**
    * @dev Payable function for take prize
    */
    function () external payable {
        if (msg.value == 0 &&  !getState() && winner > 0){
            require(depositDragons[msg.sender] > 0 || depositHamsters[msg.sender] > 0);

            uint payout = 0;
            uint payoutDEEX = 0;

            if (winner == 1 && depositDragons[msg.sender] > 0) {
                payout = calculateETHPrize(msg.sender);
            }
            if (winner == 2 && depositHamsters[msg.sender] > 0) {
                payout = calculateETHPrize(msg.sender);
            }

            if (payout > 0) {
                depositDragons[msg.sender] = 0;
                depositHamsters[msg.sender] = 0;
                msg.sender.transfer(payout);
            }

            if ((winner == 1 && depositDragons[msg.sender] == 0) || (winner == 2 && depositHamsters[msg.sender] == 0)) {
                payoutDEEX = calculateDEEXPrize(msg.sender);
                if (DEEXContract.balanceOf(address(HamstersContract)) > 0)
                    DEEXContract.transferFrom(
                        address(HamstersContract),
                        address(this),
                        DEEXContract.balanceOf(address(HamstersContract))
                    );
                if (DEEXContract.balanceOf(address(DragonsContract)) > 0)
                    DEEXContract.transferFrom(
                        address(DragonsContract),
                        address(this),
                        DEEXContract.balanceOf(address(DragonsContract))
                    );
                if (payoutDEEX > 0){
                    DEEXContract.transfer(msg.sender, payoutDEEX);
                }
            }

            if (msg.sender == lastHero) {
                lastHeroHistory = lastHero;
                lastHero = address(0x0);
                msg.sender.transfer(jackPot);
            }
        }
    }

    /**
    * @dev Getting ETH prize of participant
    * @param participant Address of participant
    */
    function calculateETHPrize(address participant) public view returns(uint) {
        uint payout = 0;

        uint256 totalSupply = totalSupplyOfDragons.add(totalSupplyOfHamsters);
        if (totalSupply > 0) {
            if (depositDragons[participant] > 0) {
                payout = totalSupply.mul(depositDragons[participant]).div(totalSupplyOfDragons);
            }

            if (depositHamsters[participant] > 0) {
                payout = totalSupply.mul(depositHamsters[participant]).div(totalSupplyOfHamsters);
            }
        }
        return payout;
    }

    /**
    * @dev Getting DEEX Token prize of participant
    * @param participant Address of participant
    */
    function calculateDEEXPrize(address participant) public view returns(uint) {
        uint payout = 0;

        if (totalDEEXSupplyOfDragons.add(totalDEEXSupplyOfHamsters) > 0){
            uint totalSupply = (totalDEEXSupplyOfDragons.add(totalDEEXSupplyOfHamsters)).mul(80).div(100);

            if (depositDragons[participant] > 0) {
                payout = totalSupply.mul(depositDragons[participant]).div(totalSupplyOfDragons);
            }

            if (depositHamsters[participant] > 0) {
                payout = totalSupply.mul(depositHamsters[participant]).div(totalSupplyOfHamsters);
            }

            return payout;
        }
        return payout;
    }
}

/**
* @dev Base contract for teams
*/
contract Team {
    using SafeMath for uint256;

    //DEEX fund address
    address payable public DEEXFund = 0xA2A3aD8319D24f4620Fbe06D2bC57c045ECF0932;

    JackPot public JPContract;
    DEEX public DEEXContract;

    /**
    * @dev Payable function. 10% will send to DEEX fund and 90% will send to JackPot contract.
    * Also setting info about player.
    */
    function () external payable {
        require(JPContract.getState() && msg.value >= 0.05 ether);

        JPContract.setInfo(msg.sender, msg.value.mul(90).div(100));

        DEEXFund.transfer(msg.value.mul(10).div(100));

        address(JPContract).transfer(msg.value.mul(90).div(100));
    }
}

/*
* @dev Dragons contract. To play game with Dragons send ETH to this contract
*/
contract Dragons is Team {

    /*
    * @dev Approving JackPot contract for spending token from Dragons contract.
    * Also setting Dragons address in JackPot contract
    */
    constructor(address payable _jackPotAddress, address payable _DEEXAddress) public {
        JPContract = JackPot(_jackPotAddress);
        JPContract.setDragonsAddress(address(this));
        DEEXContract = DEEX(_DEEXAddress);
        DEEXContract.approve(_jackPotAddress, 9999999999999999999000000000000000000);
    }
}

/*
* @dev Hamsters contract. To play game with Hamsters send ETH to this contract
*/
contract Hamsters is Team {

    /*
    * @dev Approving JackPot contract for spending token from Hamsters contract.
    * Also setting Hamsters address in JackPot contract
    */
    constructor(address payable _jackPotAddress, address payable _DEEXAddress) public {
        JPContract = JackPot(_jackPotAddress);
        JPContract.setHamstersAddress(address(this));
        DEEXContract = DEEX(_DEEXAddress);
        DEEXContract.approve(_jackPotAddress, 9999999999999999999000000000000000000);
    }
}

/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error. Latest version on 05.01.2019
 */
library SafeMath {
    int256 constant private INT256_MIN = -2**255;

    /**
    * @dev Multiplies two unsigned integers, reverts on overflow.
    */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
    * @dev Multiplies two signed integers, reverts on overflow.
    */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below

        int256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
    * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
    */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0); // Solidity only automatically asserts when dividing by 0
        require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow

        int256 c = a / b;

        return c;
    }

    /**
    * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
    * @dev Subtracts two signed integers, reverts on overflow.
    */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a));

        return c;
    }

    /**
    * @dev Adds two unsigned integers, reverts on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
    * @dev Adds two signed integers, reverts on overflow.
    */
    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a));

        return c;
    }

    /**
    * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

/*
*  deex.exchange pre-ICO tokens smart contract
*  implements [ERC-20 Token Standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md)
*
*  Style
*  1) before start coding, run Python and type 'import this' in Python console.
*  2) we avoid using inheritance (contract B is A) as it makes code less clear for observer
*  ("Flat is better than nested", "Readability counts")
*  3) we avoid using -= ; =- ; +=; =+
*  see: https://github.com/ether-camp/virtual-accelerator/issues/8
*  https://www.ethnews.com/ethercamps-hkg-token-has-a-bug-and-needs-to-be-reissued
*  4) always explicitly mark variables and functions visibility ("Explicit is better than implicit")
*  5) every function except constructor should trigger at leas one event.
*  6) smart contracts have to be audited and reviewed, comment your code.
*
*  Code is published on https://github.com/thedeex/thedeex.github.io
*/


/* "Interfaces" */

//  this is expected from another contracts
//  if it wants to spend tokens of behalf of the token owner in our contract
//  this can be used in many situations, for example to convert pre-ICO tokens to ICO tokens
//  see 'approveAndCall' function
contract allowanceRecipient {
    function receiveApproval(address _from, uint256 _value, address _inContract, bytes memory _extraData) public returns (bool success);
}


// see:
// https://github.com/ethereum/EIPs/issues/677
contract tokenRecipient {
    function tokenFallback(address _from, uint256 _value, bytes memory _extraData) public returns (bool success);
}


contract DEEX {

    // ver. 2.0

    /* ---------- Variables */

    /* --- ERC-20 variables */

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#name
    // function name() constant returns (string name)
    string public name = "deex";

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#symbol
    // function symbol() constant returns (string symbol)
    string public symbol = "deex";

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#decimals
    // function decimals() constant returns (uint8 decimals)
    uint8 public decimals = 0;

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#totalsupply
    // function totalSupply() constant returns (uint256 totalSupply)
    // we start with zero and will create tokens as SC receives ETH
    uint256 public totalSupply;

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#balanceof
    // function balanceOf(address _owner) constant returns (uint256 balance)
    mapping (address => uint256) public balanceOf;

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#allowance
    // function allowance(address _owner, address _spender) constant returns (uint256 remaining)
    mapping (address => mapping (address => uint256)) public allowance;

    /* ----- For tokens sale */

    uint256 public salesCounter = 0;

    uint256 public maxSalesAllowed;

    bool private transfersBetweenSalesAllowed;

    // initial value should be changed by the owner
    uint256 public tokenPriceInWei = 0;

    uint256 public saleStartUnixTime = 0; // block.timestamp
    uint256 public saleEndUnixTime = 0;  // block.timestamp

    /* --- administrative */
    address public owner;

    // account that can set prices
    address public priceSetter;

    // 0 - not set
    uint256 private priceMaxWei = 0;
    // 0 - not set
    uint256 private priceMinWei = 0;

    // accounts holding tokens for for the team, for advisers and for the bounty campaign
    mapping (address => bool) public isPreferredTokensAccount;

    bool public contractInitialized = false;


    /* ---------- Constructor */
    // do not forget about:
    // https://medium.com/@codetractio/a-look-into-paritys-multisig-wallet-bug-affecting-100-million-in-ether-and-tokens-356f5ba6e90a
    constructor () public {
        owner = msg.sender;

        // for testNet can be more than 2
        // --------------------------------2------------------------------------------------------change  in production!
        maxSalesAllowed = 2;
        //
        transfersBetweenSalesAllowed = true;
    }


    function initContract(address team, address advisers, address bounty) public onlyBy(owner) returns (bool){

        require(contractInitialized == false);
        contractInitialized = true;

        priceSetter = msg.sender;

        totalSupply = 100000000;

        // tokens for sale go SC own account
        balanceOf[address(this)] = 75000000;

        // for the team
        balanceOf[team] = balanceOf[team] + 15000000;
        isPreferredTokensAccount[team] = true;

        // for advisers
        balanceOf[advisers] = balanceOf[advisers] + 7000000;
        isPreferredTokensAccount[advisers] = true;

        // for the bounty campaign
        balanceOf[bounty] = balanceOf[bounty] + 3000000;
        isPreferredTokensAccount[bounty] = true;

    }

    /* ---------- Events */

    /* --- ERC-20 events */
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#events

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#transfer-1
    event Transfer(address indexed from, address indexed to, uint256 value);

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#approval
    event Approval(address indexed _owner, address indexed spender, uint256 value);

    /* --- Administrative events:  */
    event OwnerChanged(address indexed oldOwner, address indexed newOwner);

    /* ---- Tokens creation and sale events  */

    event PriceChanged(uint256 indexed newTokenPriceInWei);

    event SaleStarted(uint256 startUnixTime, uint256 endUnixTime, uint256 indexed saleNumber);

    event NewTokensSold(uint256 numberOfTokens, address indexed purchasedBy, uint256 indexed priceInWei);

    event Withdrawal(address indexed to, uint sumInWei);

    /* --- Interaction with other contracts events  */
    event DataSentToAnotherContract(address indexed _from, address indexed _toContract, bytes _extraData);

    /* ---------- Functions */

    /* --- Modifiers  */
    modifier onlyBy(address _account){
        require(msg.sender == _account);

        _;
    }

    /* --- ERC-20 Functions */
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#methods

    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md#transfer
    function transfer(address _to, uint256 _value) public returns (bool){
        return transferFrom(msg.sender, _to, _value);
    }