ETH Price: $2,171.40 (+1.24%)

Transaction Decoder

Block:
6109994 at Aug-08-2018 10:40:47 AM +UTC
Transaction Fee:
0.02902914 ETH $63.03
Gas Used:
483,819 Gas / 60 Gwei

Emitted Events:

81 0x4c7b8591c50f4ad308d07d6294f2945e074420f5.0x3d5ef7f1526b591957095eba8ced14554e32e3401d04857a5899339b4449846e( 0x3d5ef7f1526b591957095eba8ced14554e32e3401d04857a5899339b4449846e, 0000000000000000000000000000000000000000000000000000000000000664, 000000000000000000000000000000000000000000000000089c667232fa1db7, 0000000000000000000000000000000000000000000000000000000000000003 )
82 0x4c7b8591c50f4ad308d07d6294f2945e074420f5.0x3d5ef7f1526b591957095eba8ced14554e32e3401d04857a5899339b4449846e( 0x3d5ef7f1526b591957095eba8ced14554e32e3401d04857a5899339b4449846e, 0000000000000000000000000000000000000000000000000000000000000665, 000000000000000000000000000000000000000000000000089c78a2cfdf5db9, 0000000000000000000000000000000000000000000000000000000000000003 )
83 FoMo3DSoon.onAffiliatePayout( affiliateID=79, affiliateAddress=0x5fB28287...9f018caee, affiliateName=6C69626572747900000000000000000000000000000000000000000000000000, roundID=143, buyerID=20695, amount=100000000000010, timeStamp=1533724847 )
84 FoMo3DSoon.onEndTx( compressedData=3301533724847001533723121000110, compressedIDs=1430000000000000000000000101700000000200000000000020695, playerName=0000000000000000000000000000000000000000000000000000000000000000, playerAddress=[Sender] 0x4e7e9f6d385532d2e2a5b13fdc5a6db5c9439580, ethIn=1000000000000100, keysBought=0, winnerAddr=0x11E53Fd8...13fd168b3, winnerName=6162736F6C7574656C792065766572796F6E6500000000000000000000000000, amountWon=2053431363685886, newPot=427798200767902, P3DAmount=935596401535794, genAmount=1285596401535821, potAmount=350000000000035, airDropPot=1267874921083352433 )

Account State Difference:

  Address   Before After State Difference Code
0x4C7B8591...e074420F5
254.032526826176505358 Eth254.032632385816658938 Eth0.00010555964015358
0x4e7e9f6D...5c9439580
0.534043655222076849 Eth
Nonce: 47
0.505014515222076849 Eth
Nonce: 48
0.02902914
0x4e8ecF79...1e0Bf00B8 184.48839088178205694 Eth184.487349725740367566 Eth0.001041156041689374
(Spark Pool)
2,358.665131983779118894 Eth2,358.694161123779118894 Eth0.02902914
0xC0c00114...F86929Ad0 0.436014577008093341 Eth0.436950173409629135 Eth0.000935596401535794

Execution Trace

FoMo3DSoon.reLoadXid( _affCode=0, _team=3, _eth=1000000000000100 )
  • ETH 0.000085559640153578 JIincForwarder.CALL( )
    • ETH 0.000085559640153578 0x4c7b8591c50f4ad308d07d6294f2945e074420f5.f340fa01( )
    • ETH 0.000855596401535786 Divies.CALL( )
    • ETH 0.000020000000000002 JIincForwarder.CALL( )
      • ETH 0.000020000000000002 0x4c7b8591c50f4ad308d07d6294f2945e074420f5.f340fa01( )
      • ETH 0.000080000000000008 Divies.CALL( )
        File 1 of 3: FoMo3DSoon
        pragma solidity ^0.4.24;
        /**
         * @title -FoMo-3D v0.7.1
         * ┌┬┐┌─┐┌─┐┌┬┐   ╦╦ ╦╔═╗╔╦╗  ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐
         *  │ ├┤ ├─┤│││   ║║ ║╚═╗ ║   ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐
         *  ┴ └─┘┴ ┴┴ ┴  ╚╝╚═╝╚═╝ ╩   ┴  ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘
         *                                  _____                      _____
         *                                 (, /     /)       /) /)    (, /      /)          /)
         *          ┌─┐                      /   _ (/_      // //       /  _   // _   __  _(/
         *          ├─┤                  ___/___(/_/(__(_/_(/_(/_   ___/__/_)_(/_(_(_/ (_(_(_
         *          ┴ ┴                /   /          .-/ _____   (__ /
         *                            (__ /          (_/ (, /                                      /)™
         *                                                 /  __  __ __ __  _   __ __  _  _/_ _  _(/
         * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐                          /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_
         * ├─┘├┬┘│ │ │││ ││   │                      (__ /              .-/  © Jekyll Island Inc. 2018
         * ┴  ┴└─└─┘─┴┘└─┘└─┘ ┴                                        (_/   .--,-``-.
         *========,---,.======================____==========================/   /     '.=======,---,====*
         *      ,'  .' |                    ,'  , `.                       / ../        ;    .'  .' `\
         *    ,---.'   |    ,---.        ,-+-,.' _ |    ,---.              \ ``\  .`-    ' ,---.'     \
         *    |   |   .'   '   ,'\    ,-+-. ;   , ||   '   ,'\      ,---,.  \___\/   \   : |   |  .`\  |
         *    :   :  :    /   /   |  ,--.'|'   |  ||  /   /   |   ,'  .' |       \   :   | :   : |  '  |
         *    :   |  |-, .   ; ,. : |   |  ,', |  |, .   ; ,. : ,---.'   |       /  /   /  |   ' '  ;  :
         *    |   :  ;/| '   | |: : |   | /  | |--'  '   | |: : |   |  .'        \  \   \  '   | ;  .  |
         *    |   |   .' '   | .; : |   : |  | ,     '   | .; : :   |.'      ___ /   :   | |   | :  |  '
         *    '   :  '   |   :    | |   : |  |/      |   :    | `---'       /   /\   /   : '   : | /  ;
         *    |   |  |    \   \  /  |   | |`-'        \   \  /             / ,,/  ',-    . |   | '` ,/
         *    |   :  \     `----'   |   ;/             `----'              \ ''\        ;  ;   :  .'
         *====|   | ,'=============='---'==========(soon edition)===========\   \     .'===|   ,.'======*
         *    `----'                                                         `--`-,,-'     '---'
         *             ╔═╗┌─┐┌─┐┬┌─┐┬┌─┐┬   ┌─────────────────────────┐ ╦ ╦┌─┐┌┐ ╔═╗┬┌┬┐┌─┐ 
         *             ║ ║├┤ ├┤ ││  │├─┤│   │   https://exitscam.me   │ ║║║├┤ ├┴┐╚═╗│ │ ├┤  
         *             ╚═╝└  └  ┴└─┘┴┴ ┴┴─┘ └─┬─────────────────────┬─┘ ╚╩╝└─┘└─┘╚═╝┴ ┴ └─┘ 
         *   ┌────────────────────────────────┘                     └──────────────────────────────┐
         *   │╔═╗┌─┐┬  ┬┌┬┐┬┌┬┐┬ ┬   ╔╦╗┌─┐┌─┐┬┌─┐┌┐┌   ╦┌┐┌┌┬┐┌─┐┬─┐┌─┐┌─┐┌─┐┌─┐   ╔═╗┌┬┐┌─┐┌─┐┬┌─│
         *   │╚═╗│ ││  │ │││ │ └┬┘ ═  ║║├┤ └─┐││ ┬│││ ═ ║│││ │ ├┤ ├┬┘├┤ ├─┤│  ├┤  ═ ╚═╗ │ ├─┤│  ├┴┐│
         *   │╚═╝└─┘┴─┘┴─┴┘┴ ┴  ┴    ═╩╝└─┘└─┘┴└─┘┘└┘   ╩┘└┘ ┴ └─┘┴└─└  ┴ ┴└─┘└─┘   ╚═╝ ┴ ┴ ┴└─┘┴ ┴│
         *   │    ┌──────────┐           ┌───────┐            ┌─────────┐              ┌────────┐  │
         *   └────┤ Inventor ├───────────┤ Justo ├────────────┤ Sumpunk ├──────────────┤ Mantso ├──┘
         *        └──────────┘           └───────┘            └─────────┘              └────────┘
         *   ┌─────────────────────────────────────────────────────────┐ ╔╦╗┬ ┬┌─┐┌┐┌┬┌─┌─┐  ╔╦╗┌─┐
         *   │ Ambius, Aritz Cracker, Cryptoknight, Crypto McPump,     │  ║ ├─┤├─┤│││├┴┐└─┐   ║ │ │
         *   │ Capex, JogFera, The Shocker, Daok, Randazzz, PumpRabbi, │  ╩ ┴ ┴┴ ┴┘└┘┴ ┴└─┘   ╩ └─┘
         *   │ Kadaz, Incognito Jo, Lil Stronghands, Maojk, Psaints,   └───────────────────────────┐
         *   │ P3DHeem, 3DCrypto, FaFiam, Crypto Yardi, Ninja Turtle, Psaints, Satoshi, Vitalik,   │ 
         *   │ Justin Sun, Nano 2nd, Bogdanoffs                        Isaac Newton, Nikola Tesla, │
         *   │ Le Comte De Saint Germain, Albert Einstein, Socrates, & all the volunteer moderator │
         *   │ & support staff, content, creators, autonomous agents, and indie devs for P3D.      │
         *   │              Without your help, we wouldn't have the time to code this.             │
         *   └─────────────────────────────────────────────────────────────────────────────────────┘
         * 
         * This product is protected under license.  Any unauthorized copy, modification, or use without 
         * express written consent from the creators is prohibited.
         * 
         * WARNING:  THIS PRODUCT IS HIGHLY ADDICTIVE.  IF YOU HAVE AN ADDICTIVE NATURE.  DO NOT PLAY.
         */
        
        //==============================================================================
        //     _    _  _ _|_ _  .
        //    (/_\/(/_| | | _\  .
        //==============================================================================
        contract F3Devents {
            // fired whenever a player registers a name
            event onNewName
            (
                uint256 indexed playerID,
                address indexed playerAddress,
                bytes32 indexed playerName,
                bool isNewPlayer,
                uint256 affiliateID,
                address affiliateAddress,
                bytes32 affiliateName,
                uint256 amountPaid,
                uint256 timeStamp
            );
            
            // fired at end of buy or reload
            event onEndTx
            (
                uint256 compressedData,     
                uint256 compressedIDs,      
                bytes32 playerName,
                address playerAddress,
                uint256 ethIn,
                uint256 keysBought,
                address winnerAddr,
                bytes32 winnerName,
                uint256 amountWon,
                uint256 newPot,
                uint256 P3DAmount,
                uint256 genAmount,
                uint256 potAmount,
                uint256 airDropPot
            );
            
        	// fired whenever theres a withdraw
            event onWithdraw
            (
                uint256 indexed playerID,
                address playerAddress,
                bytes32 playerName,
                uint256 ethOut,
                uint256 timeStamp
            );
            
            // fired whenever a withdraw forces end round to be ran
            event onWithdrawAndDistribute
            (
                address playerAddress,
                bytes32 playerName,
                uint256 ethOut,
                uint256 compressedData,
                uint256 compressedIDs,
                address winnerAddr,
                bytes32 winnerName,
                uint256 amountWon,
                uint256 newPot,
                uint256 P3DAmount,
                uint256 genAmount
            );
            
            // (fomo3d long only) fired whenever a player tries a buy after round timer 
            // hit zero, and causes end round to be ran.
            event onBuyAndDistribute
            (
                address playerAddress,
                bytes32 playerName,
                uint256 ethIn,
                uint256 compressedData,
                uint256 compressedIDs,
                address winnerAddr,
                bytes32 winnerName,
                uint256 amountWon,
                uint256 newPot,
                uint256 P3DAmount,
                uint256 genAmount
            );
            
            // (fomo3d long only) fired whenever a player tries a reload after round timer 
            // hit zero, and causes end round to be ran.
            event onReLoadAndDistribute
            (
                address playerAddress,
                bytes32 playerName,
                uint256 compressedData,
                uint256 compressedIDs,
                address winnerAddr,
                bytes32 winnerName,
                uint256 amountWon,
                uint256 newPot,
                uint256 P3DAmount,
                uint256 genAmount
            );
            
            // fired whenever an affiliate is paid
            event onAffiliatePayout
            (
                uint256 indexed affiliateID,
                address affiliateAddress,
                bytes32 affiliateName,
                uint256 indexed roundID,
                uint256 indexed buyerID,
                uint256 amount,
                uint256 timeStamp
            );
            
            // received pot swap deposit
            event onPotSwapDeposit
            (
                uint256 roundID,
                uint256 amountAddedToPot
            );
        }
        
        contract FoMo3DSoon is F3Devents{
            using SafeMath for uint256;
            using NameFilter for string;
            using F3DKeysCalcFast for uint256;
            
        	DiviesInterface constant private Divies = DiviesInterface(0xC0c001140319C5f114F8467295b1F22F86929Ad0);
            JIincForwarderInterface constant private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE);
        	PlayerBookInterface constant private PlayerBook = PlayerBookInterface(0xD60d353610D9a5Ca478769D371b53CEfAA7B6E4c);
        //==============================================================================
        //     _ _  _  |`. _     _ _ |_ | _  _  .
        //    (_(_)| |~|~|(_||_|| (_||_)|(/__\  .  (game settings)
        //=================_|===========================================================
            string constant public name = "FoMo3D Soon(tm) Edition";
            string constant public symbol = "F3D";
        	uint256 private rndGap_ = 60 seconds;                       // length of ICO phase, set to 1 year for EOS.
            uint256 constant private rndInit_ = 5 minutes;              // round timer starts at this
            uint256 constant private rndInc_ = 5 minutes;               // every full key purchased adds this much to the timer
            uint256 constant private rndMax_ = 5 minutes;               // max length a round timer can be
        //==============================================================================
        //     _| _ _|_ _    _ _ _|_    _   .
        //    (_|(_| | (_|  _\(/_ | |_||_)  .  (data used to store game info that changes)
        //=============================|================================================
        	uint256 public airDropPot_;             // person who gets the airdrop wins part of this pot
            uint256 public airDropTracker_ = 0;     // incremented each time a "qualified" tx occurs.  used to determine winning air drop
            uint256 public rID_;    // round id number / total rounds that have happened
        //****************
        // PLAYER DATA 
        //****************
            mapping (address => uint256) public pIDxAddr_;          // (addr => pID) returns player id by address
            mapping (bytes32 => uint256) public pIDxName_;          // (name => pID) returns player id by name
            mapping (uint256 => F3Ddatasets.Player) public plyr_;   // (pID => data) player data
            mapping (uint256 => mapping (uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_;    // (pID => rID => data) player round data by player id & round id
            mapping (uint256 => mapping (bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns.  (used so you can change your display name amongst any name you own)
        //****************
        // ROUND DATA 
        //****************
            mapping (uint256 => F3Ddatasets.Round) public round_;   // (rID => data) round data
            mapping (uint256 => mapping(uint256 => uint256)) public rndTmEth_;      // (rID => tID => data) eth in per team, by round id and team id
        //****************
        // TEAM FEE DATA 
        //****************
            mapping (uint256 => F3Ddatasets.TeamFee) public fees_;          // (team => fees) fee distribution by team
            mapping (uint256 => F3Ddatasets.PotSplit) public potSplit_;     // (team => fees) pot split distribution by team
        //==============================================================================
        //     _ _  _  __|_ _    __|_ _  _  .
        //    (_(_)| |_\ | | |_|(_ | (_)|   .  (initial data setup upon contract deploy)
        //==============================================================================
            constructor()
                public
            {
        		// Team allocation structures
                // 0 = whales
                // 1 = bears
                // 2 = sneks
                // 3 = bulls
        
        		// Team allocation percentages
                // (F3D, P3D) + (Pot , Referrals, Community)
                    // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot.
                fees_[0] = F3Ddatasets.TeamFee(30,6);   //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot
                fees_[1] = F3Ddatasets.TeamFee(43,0);   //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot
                fees_[2] = F3Ddatasets.TeamFee(56,10);  //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot
                fees_[3] = F3Ddatasets.TeamFee(43,8);   //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot
                
                // how to split up the final pot based on which team was picked
                // (F3D, P3D)
                potSplit_[0] = F3Ddatasets.PotSplit(15,10);  //48% to winner, 25% to next round, 2% to com
                potSplit_[1] = F3Ddatasets.PotSplit(25,0);   //48% to winner, 25% to next round, 2% to com
                potSplit_[2] = F3Ddatasets.PotSplit(20,20);  //48% to winner, 10% to next round, 2% to com
                potSplit_[3] = F3Ddatasets.PotSplit(30,10);  //48% to winner, 10% to next round, 2% to com
        	}
        //==============================================================================
        //     _ _  _  _|. |`. _  _ _  .
        //    | | |(_)(_||~|~|(/_| _\  .  (these are safety checks)
        //==============================================================================
            /**
             * @dev used to make sure no one can interact with contract until it has 
             * been activated. 
             */
            modifier isActivated() {
                require(activated_ == true, "its not ready yet.  check ?eta in discord"); 
                _;
            }
            
            /**
             * @dev prevents contracts from interacting with fomo3d 
             */
            modifier isHuman() {
                address _addr = msg.sender;
                require (_addr == tx.origin);
                
                uint256 _codeLength;
                
                assembly {_codeLength := extcodesize(_addr)}
                require(_codeLength == 0, "sorry humans only");
                _;
            }
        
            /**
             * @dev sets boundaries for incoming tx 
             */
            modifier isWithinLimits(uint256 _eth) {
                require(_eth >= 1000000000, "pocket lint: not a valid currency");
                require(_eth <= 100000000000000000000000, "no vitalik, no");    /** NOTE THIS NEEDS TO BE CHECKED **/
        		_;    
        	}
        //==============================================================================
        //     _    |_ |. _   |`    _  __|_. _  _  _  .
        //    |_)|_||_)||(_  ~|~|_|| |(_ | |(_)| |_\  .  (use these to interact with contract)
        //====|=========================================================================
            /**
             * @dev emergency buy uses last stored affiliate ID and team snek
             */
            function()
                isActivated()
                isHuman()
                isWithinLimits(msg.value)
                public
                payable
            {
                // set up our tx event data and determine if player is new or not
                F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_);
                
                // fetch player id
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // buy core 
                buyCore(_pID, plyr_[_pID].laff, 2, _eventData_);
            }
            
            /**
             * @dev converts all incoming ethereum to keys.
             * -functionhash- 0x8f38f309 (using ID for affiliate)
             * -functionhash- 0x98a0871d (using address for affiliate)
             * -functionhash- 0xa65b37a1 (using name for affiliate)
             * @param _affCode the ID/address/name of the player who gets the affiliate fee
             * @param _team what team is the player playing for?
             */
            function buyXid(uint256 _affCode, uint256 _team)
                isActivated()
                isHuman()
                isWithinLimits(msg.value)
                public
                payable
            {
                // set up our tx event data and determine if player is new or not
                F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_);
                
                // fetch player id
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // manage affiliate residuals
                // if no affiliate code was given or player tried to use their own, lolz
                if (_affCode == 0 || _affCode == _pID)
                {
                    // use last stored affiliate code 
                    _affCode = plyr_[_pID].laff;
                    
                // if affiliate code was given & its not the same as previously stored 
                } else if (_affCode != plyr_[_pID].laff) {
                    // update last affiliate 
                    plyr_[_pID].laff = _affCode;
                }
                
                // verify a valid team was selected
                _team = verifyTeam(_team);
                
                // buy core 
                buyCore(_pID, _affCode, _team, _eventData_);
            }
            
            function buyXaddr(address _affCode, uint256 _team)
                isActivated()
                isHuman()
                isWithinLimits(msg.value)
                public
                payable
            {
                // set up our tx event data and determine if player is new or not
                F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_);
                
                // fetch player id
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // manage affiliate residuals
                uint256 _affID;
                // if no affiliate code was given or player tried to use their own, lolz
                if (_affCode == address(0) || _affCode == msg.sender)
                {
                    // use last stored affiliate code
                    _affID = plyr_[_pID].laff;
                
                // if affiliate code was given    
                } else {
                    // get affiliate ID from aff Code 
                    _affID = pIDxAddr_[_affCode];
                    
                    // if affID is not the same as previously stored 
                    if (_affID != plyr_[_pID].laff)
                    {
                        // update last affiliate
                        plyr_[_pID].laff = _affID;
                    }
                }
                
                // verify a valid team was selected
                _team = verifyTeam(_team);
                
                // buy core 
                buyCore(_pID, _affID, _team, _eventData_);
            }
            
            function buyXname(bytes32 _affCode, uint256 _team)
                isActivated()
                isHuman()
                isWithinLimits(msg.value)
                public
                payable
            {
                // set up our tx event data and determine if player is new or not
                F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_);
                
                // fetch player id
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // manage affiliate residuals
                uint256 _affID;
                // if no affiliate code was given or player tried to use their own, lolz
                if (_affCode == '' || _affCode == plyr_[_pID].name)
                {
                    // use last stored affiliate code
                    _affID = plyr_[_pID].laff;
                
                // if affiliate code was given
                } else {
                    // get affiliate ID from aff Code
                    _affID = pIDxName_[_affCode];
                    
                    // if affID is not the same as previously stored
                    if (_affID != plyr_[_pID].laff)
                    {
                        // update last affiliate
                        plyr_[_pID].laff = _affID;
                    }
                }
                
                // verify a valid team was selected
                _team = verifyTeam(_team);
                
                // buy core 
                buyCore(_pID, _affID, _team, _eventData_);
            }
            
            /**
             * @dev essentially the same as buy, but instead of you sending ether 
             * from your wallet, it uses your unwithdrawn earnings.
             * -functionhash- 0x349cdcac (using ID for affiliate)
             * -functionhash- 0x82bfc739 (using address for affiliate)
             * -functionhash- 0x079ce327 (using name for affiliate)
             * @param _affCode the ID/address/name of the player who gets the affiliate fee
             * @param _team what team is the player playing for?
             * @param _eth amount of earnings to use (remainder returned to gen vault)
             */
            function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth)
                isActivated()
                isHuman()
                isWithinLimits(_eth)
                public
            {
                // set up our tx event data
                F3Ddatasets.EventReturns memory _eventData_;
                
                // fetch player ID
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // manage affiliate residuals
                // if no affiliate code was given or player tried to use their own, lolz
                if (_affCode == 0 || _affCode == _pID)
                {
                    // use last stored affiliate code 
                    _affCode = plyr_[_pID].laff;
                    
                // if affiliate code was given & its not the same as previously stored 
                } else if (_affCode != plyr_[_pID].laff) {
                    // update last affiliate 
                    plyr_[_pID].laff = _affCode;
                }
        
                // verify a valid team was selected
                _team = verifyTeam(_team);
                    
                // reload core
                reLoadCore(_pID, _affCode, _team, _eth, _eventData_);
            }
            
            function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth)
                isActivated()
                isHuman()
                isWithinLimits(_eth)
                public
            {
                // set up our tx event data
                F3Ddatasets.EventReturns memory _eventData_;
                
                // fetch player ID
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // manage affiliate residuals
                uint256 _affID;
                // if no affiliate code was given or player tried to use their own, lolz
                if (_affCode == address(0) || _affCode == msg.sender)
                {
                    // use last stored affiliate code
                    _affID = plyr_[_pID].laff;
                
                // if affiliate code was given    
                } else {
                    // get affiliate ID from aff Code 
                    _affID = pIDxAddr_[_affCode];
                    
                    // if affID is not the same as previously stored 
                    if (_affID != plyr_[_pID].laff)
                    {
                        // update last affiliate
                        plyr_[_pID].laff = _affID;
                    }
                }
                
                // verify a valid team was selected
                _team = verifyTeam(_team);
                
                // reload core
                reLoadCore(_pID, _affID, _team, _eth, _eventData_);
            }
            
            function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth)
                isActivated()
                isHuman()
                isWithinLimits(_eth)
                public
            {
                // set up our tx event data
                F3Ddatasets.EventReturns memory _eventData_;
                
                // fetch player ID
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // manage affiliate residuals
                uint256 _affID;
                // if no affiliate code was given or player tried to use their own, lolz
                if (_affCode == '' || _affCode == plyr_[_pID].name)
                {
                    // use last stored affiliate code
                    _affID = plyr_[_pID].laff;
                
                // if affiliate code was given
                } else {
                    // get affiliate ID from aff Code
                    _affID = pIDxName_[_affCode];
                    
                    // if affID is not the same as previously stored
                    if (_affID != plyr_[_pID].laff)
                    {
                        // update last affiliate
                        plyr_[_pID].laff = _affID;
                    }
                }
                
                // verify a valid team was selected
                _team = verifyTeam(_team);
                
                // reload core
                reLoadCore(_pID, _affID, _team, _eth, _eventData_);
            }
        
            /**
             * @dev withdraws all of your earnings.
             * -functionhash- 0x3ccfd60b
             */
            function withdraw()
                isActivated()
                isHuman()
                public
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // grab time
                uint256 _now = now;
                
                // fetch player ID
                uint256 _pID = pIDxAddr_[msg.sender];
                
                // setup temp var for player eth
                uint256 _eth;
                
                // check to see if round has ended and no one has run round end yet
                if (_now > round_[_rID].end && round_[_rID].ended == false)
                {
                    // set up our tx event data
                    F3Ddatasets.EventReturns memory _eventData_;
                    
                    // end the round (distributes pot)
        			round_[_rID].ended = true;
                    _eventData_ = endRound(_eventData_);
                    
        			// get their earnings
                    _eth = withdrawEarnings(_pID);
                    
                    // gib moni
                    if (_eth > 0)
                        plyr_[_pID].addr.transfer(_eth);    
                    
                    // build event data
                    _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000);
                    _eventData_.compressedIDs = _eventData_.compressedIDs + _pID;
                    
                    // fire withdraw and distribute event
                    emit F3Devents.onWithdrawAndDistribute
                    (
                        msg.sender, 
                        plyr_[_pID].name, 
                        _eth, 
                        _eventData_.compressedData, 
                        _eventData_.compressedIDs, 
                        _eventData_.winnerAddr, 
                        _eventData_.winnerName, 
                        _eventData_.amountWon, 
                        _eventData_.newPot, 
                        _eventData_.P3DAmount, 
                        _eventData_.genAmount
                    );
                    
                // in any other situation
                } else {
                    // get their earnings
                    _eth = withdrawEarnings(_pID);
                    
                    // gib moni
                    if (_eth > 0)
                        plyr_[_pID].addr.transfer(_eth);
                    
                    // fire withdraw event
                    emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now);
                }
            }
            
            /**
             * @dev use these to register names.  they are just wrappers that will send the
             * registration requests to the PlayerBook contract.  So registering here is the 
             * same as registering there.  UI will always display the last name you registered.
             * but you will still own all previously registered names to use as affiliate 
             * links.
             * - must pay a registration fee.
             * - name must be unique
             * - names will be converted to lowercase
             * - name cannot start or end with a space 
             * - cannot have more than 1 space in a row
             * - cannot be only numbers
             * - cannot start with 0x 
             * - name must be at least 1 char
             * - max length of 32 characters long
             * - allowed characters: a-z, 0-9, and space
             * -functionhash- 0x921dec21 (using ID for affiliate)
             * -functionhash- 0x3ddd4698 (using address for affiliate)
             * -functionhash- 0x685ffd83 (using name for affiliate)
             * @param _nameString players desired name
             * @param _affCode affiliate ID, address, or name of who referred you
             * @param _all set to true if you want this to push your info to all games 
             * (this might cost a lot of gas)
             */
            function registerNameXID(string _nameString, uint256 _affCode, bool _all)
                isHuman()
                public
                payable
            {
                bytes32 _name = _nameString.nameFilter();
                address _addr = msg.sender;
                uint256 _paid = msg.value;
                (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all);
                
                uint256 _pID = pIDxAddr_[_addr];
                
                // fire event
                emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now);
            }
            
            function registerNameXaddr(string _nameString, address _affCode, bool _all)
                isHuman()
                public
                payable
            {
                bytes32 _name = _nameString.nameFilter();
                address _addr = msg.sender;
                uint256 _paid = msg.value;
                (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all);
                
                uint256 _pID = pIDxAddr_[_addr];
                
                // fire event
                emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now);
            }
            
            function registerNameXname(string _nameString, bytes32 _affCode, bool _all)
                isHuman()
                public
                payable
            {
                bytes32 _name = _nameString.nameFilter();
                address _addr = msg.sender;
                uint256 _paid = msg.value;
                (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all);
                
                uint256 _pID = pIDxAddr_[_addr];
                
                // fire event
                emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now);
            }
        //==============================================================================
        //     _  _ _|__|_ _  _ _  .
        //    (_|(/_ |  | (/_| _\  . (for UI & viewing things on etherscan)
        //=====_|=======================================================================
            /**
             * @dev return the price buyer will pay for next 1 individual key.
             * - during live round.  this is accurate. (well... unless someone buys before 
             * you do and ups the price!  you better HURRY!)
             * - during ICO phase.  this is the max you would get based on current eth 
             * invested during ICO phase.  if others invest after you, you will receive
             * less.  (so distract them with meme vids till ICO is over)
             * -functionhash- 0x018a25e8
             * @return price for next key bought (in wei format)
             */
            function getBuyPrice()
                public 
                view 
                returns(uint256)
            {  
                // setup local rID
                uint256 _rID = rID_;
                    
                // grab time
                uint256 _now = now;
                
                // is ICO phase over??  & theres eth in the round?
                if (_now > round_[_rID].strt + rndGap_ && round_[_rID].eth != 0 && _now <= round_[_rID].end)
                    return ( (round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000) );
                else if (_now <= round_[_rID].end) // round hasn't ended (in ICO phase, or ICO phase is over, but round eth is 0)
                    return ( ((round_[_rID].ico.keys()).add(1000000000000000000)).ethRec(1000000000000000000) );
                else // rounds over.  need price for new round
                    return ( 100000000000000 ); // init
            }
            
            /**
             * @dev returns time left.  dont spam this, you'll ddos yourself from your node 
             * provider
             * -functionhash- 0xc7e284b8
             * @return time left in seconds
             */
            function getTimeLeft()
                public
                view
                returns(uint256)
            {
                // setup local rID 
                uint256 _rID = rID_;
                
                // grab time
                uint256 _now = now;
                
                // are we in ICO phase?
                if (_now <= round_[_rID].strt + rndGap_)
                    return( ((round_[_rID].end).sub(rndInit_)).sub(_now) );
                else 
                    if (_now < round_[_rID].end)
                        return( (round_[_rID].end).sub(_now) );
                    else
                        return(0);
            }
            
            /**
             * @dev returns player earnings per vaults 
             * -functionhash- 0x63066434
             * @return winnings vault
             * @return general vault
             * @return affiliate vault
             */
            function getPlayerVaults(uint256 _pID)
                public
                view
                returns(uint256 ,uint256, uint256)
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // if round has ended.  but round end has not been run (so contract has not distributed winnings)
                if (now > round_[_rID].end && round_[_rID].ended == false)
                {
                    uint256 _roundMask;
                    uint256 _roundEth;
                    uint256 _roundKeys;
                    uint256 _roundPot;
                    if (round_[_rID].eth == 0 && round_[_rID].ico > 0)
                    {
                        // create a temp round eth based on eth sent in during ICO phase
                        _roundEth = round_[_rID].ico;
                        
                        // create a temp round keys based on keys bought during ICO phase
                        _roundKeys = (round_[_rID].ico).keys();
                        
                        // create a temp round mask based on eth and keys from ICO phase
                        _roundMask = ((round_[_rID].icoGen).mul(1000000000000000000)) / _roundKeys;
                        
                        // create a temp rount pot based on pot, and dust from mask
                        _roundPot = (round_[_rID].pot).add((round_[_rID].icoGen).sub((_roundMask.mul(_roundKeys)) / (1000000000000000000)));
                    } else {
                        _roundEth = round_[_rID].eth;
                        _roundKeys = round_[_rID].keys;
                        _roundMask = round_[_rID].mask;
                        _roundPot = round_[_rID].pot;
                    }
                    
                    uint256 _playerKeys;
                    if (plyrRnds_[_pID][plyr_[_pID].lrnd].ico == 0)
                        _playerKeys = plyrRnds_[_pID][plyr_[_pID].lrnd].keys;
                    else
                        _playerKeys = calcPlayerICOPhaseKeys(_pID, _rID);
                    
                    // if player is winner 
                    if (round_[_rID].plyr == _pID)
                    {
                        return
                        (
                            (plyr_[_pID].win).add( (_roundPot.mul(48)) / 100 ),
                            (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _roundMask, _roundPot, _roundKeys, _playerKeys) ),
                            plyr_[_pID].aff
                        );
                    // if player is not the winner
                    } else {
                        return
                        (
                            plyr_[_pID].win,   
                            (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _roundMask, _roundPot, _roundKeys, _playerKeys) ),
                            plyr_[_pID].aff
                        );
                    }
                    
                // if round is still going on, we are in ico phase, or round has ended and round end has been ran
                } else {
                    return
                    (
                        plyr_[_pID].win,
                        (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)),
                        plyr_[_pID].aff
                    );
                }
            }
            
            /**
             * solidity hates stack limits.  this lets us avoid that hate 
             */
            function getPlayerVaultsHelper(uint256 _pID, uint256 _roundMask, uint256 _roundPot, uint256 _roundKeys, uint256 _playerKeys)
                private
                view
                returns(uint256)
            {
                return(  (((_roundMask.add((((_roundPot.mul(potSplit_[round_[rID_].team].gen)) / 100).mul(1000000000000000000)) / _roundKeys)).mul(_playerKeys)) / 1000000000000000000).sub(plyrRnds_[_pID][rID_].mask)  );
            }
            
            /**
             * @dev returns all current round info needed for front end
             * -functionhash- 0x747dff42
             * @return eth invested during ICO phase
             * @return round id 
             * @return total keys for round 
             * @return time round ends
             * @return time round started
             * @return current pot 
             * @return current team ID & player ID in lead 
             * @return current player in leads address 
             * @return current player in leads name
             * @return whales eth in for round
             * @return bears eth in for round
             * @return sneks eth in for round
             * @return bulls eth in for round
             * @return airdrop tracker # & airdrop pot
             */
            function getCurrentRoundInfo()
                public
                view
                returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256)
            {
                // setup local rID
                uint256 _rID = rID_;
                
                if (round_[_rID].eth != 0)
                {
                    return
                    (
                        round_[_rID].ico,               //0
                        _rID,                           //1
                        round_[_rID].keys,              //2
                        round_[_rID].end,               //3
                        round_[_rID].strt,              //4
                        round_[_rID].pot,               //5
                        (round_[_rID].team + (round_[_rID].plyr * 10)),     //6
                        plyr_[round_[_rID].plyr].addr,  //7
                        plyr_[round_[_rID].plyr].name,  //8
                        rndTmEth_[_rID][0],             //9
                        rndTmEth_[_rID][1],             //10
                        rndTmEth_[_rID][2],             //11
                        rndTmEth_[_rID][3],             //12
                        airDropTracker_ + (airDropPot_ * 1000)              //13
                    );
                } else {
                    return
                    (
                        round_[_rID].ico,               //0
                        _rID,                           //1
                        (round_[_rID].ico).keys(),      //2
                        round_[_rID].end,               //3
                        round_[_rID].strt,              //4
                        round_[_rID].pot,               //5
                        (round_[_rID].team + (round_[_rID].plyr * 10)),     //6
                        plyr_[round_[_rID].plyr].addr,  //7
                        plyr_[round_[_rID].plyr].name,  //8
                        rndTmEth_[_rID][0],             //9
                        rndTmEth_[_rID][1],             //10
                        rndTmEth_[_rID][2],             //11
                        rndTmEth_[_rID][3],             //12
                        airDropTracker_ + (airDropPot_ * 1000)              //13
                    );
                }
            }
        
            /**
             * @dev returns player info based on address.  if no address is given, it will 
             * use msg.sender 
             * -functionhash- 0xee0b5d8b
             * @param _addr address of the player you want to lookup 
             * @return player ID 
             * @return player name
             * @return keys owned (current round)
             * @return winnings vault
             * @return general vault 
             * @return affiliate vault 
        	 * @return player ico eth
             */
            function getPlayerInfoByAddress(address _addr)
                public 
                view 
                returns(uint256, bytes32, uint256, uint256, uint256, uint256, uint256)
            {
                // setup local rID
                uint256 _rID = rID_;
                
                if (_addr == address(0))
                {
                    _addr == msg.sender;
                }
                uint256 _pID = pIDxAddr_[_addr];
                
                if (plyrRnds_[_pID][_rID].ico == 0)
                {
                    return
                    (
                        _pID,                               //0
                        plyr_[_pID].name,                   //1
                        plyrRnds_[_pID][_rID].keys,         //2
                        plyr_[_pID].win,                    //3
                        (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)),       //4
                        plyr_[_pID].aff,                    //5
        				0						            //6
                    );
                } else {
                    return
                    (
                        _pID,                               //0
                        plyr_[_pID].name,                   //1
                        calcPlayerICOPhaseKeys(_pID, _rID), //2
                        plyr_[_pID].win,                    //3
                        (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)),       //4
                        plyr_[_pID].aff,                    //5
        				plyrRnds_[_pID][_rID].ico           //6
                    );
                }
                
            }
        
        //==============================================================================
        //     _ _  _ _   | _  _ . _  .
        //    (_(_)| (/_  |(_)(_||(_  . (this + tools + calcs + modules = our softwares engine)
        //=====================_|=======================================================
            /**
             * @dev logic runs whenever a buy order is executed.  determines how to handle 
             * incoming eth depending on if we are in ICO phase or not 
             */
            function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_)
                private
            {
                // check to see if round has ended.  and if player is new to round
                _eventData_ = manageRoundAndPlayer(_pID, _eventData_);
                
                // are we in ICO phase?
                if (now <= round_[rID_].strt + rndGap_) 
                {
                    // let event data know this is a ICO phase buy order
                    _eventData_.compressedData = _eventData_.compressedData + 2000000000000000000000000000000;
                
                    // ICO phase core
                    icoPhaseCore(_pID, msg.value, _team, _affID, _eventData_);
                
                
                // round is live
                } else {
                     // let event data know this is a buy order
                    _eventData_.compressedData = _eventData_.compressedData + 1000000000000000000000000000000;
                
                    // call core
                    core(_pID, msg.value, _affID, _team, _eventData_);
                }
            }
        
            /**
             * @dev logic runs whenever a reload order is executed.  determines how to handle 
             * incoming eth depending on if we are in ICO phase or not 
             */
            function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_)
                private 
            {
                // check to see if round has ended.  and if player is new to round
                _eventData_ = manageRoundAndPlayer(_pID, _eventData_);
                
                // get earnings from all vaults and return unused to gen vault
                // because we use a custom safemath library.  this will throw if player 
                // tried to spend more eth than they have.
                plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth);
                        
                // are we in ICO phase?
                if (now <= round_[rID_].strt + rndGap_) 
                {
                    // let event data know this is an ICO phase reload 
                    _eventData_.compressedData = _eventData_.compressedData + 3000000000000000000000000000000;
                        
                    // ICO phase core
                    icoPhaseCore(_pID, _eth, _team, _affID, _eventData_);
        
        
                // round is live
                } else {
                    // call core
                    core(_pID, _eth, _affID, _team, _eventData_);
                }
            }    
            
            /**
             * @dev during ICO phase all eth sent in by each player.  will be added to an 
             * "investment pool".  upon end of ICO phase, all eth will be used to buy keys.
             * each player receives an amount based on how much they put in, and the 
             * the average price attained.
             */
            function icoPhaseCore(uint256 _pID, uint256 _eth, uint256 _team, uint256 _affID, F3Ddatasets.EventReturns memory _eventData_)
                private
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // if they bought at least 1 whole key (at time of purchase)
                if ((round_[_rID].ico).keysRec(_eth) >= 1000000000000000000 || round_[_rID].plyr == 0)
                {
                    // set new leaders
                    if (round_[_rID].plyr != _pID)
                        round_[_rID].plyr = _pID;  
                    if (round_[_rID].team != _team)
                        round_[_rID].team = _team;
                    
                    // set the new leader bool to true
                    _eventData_.compressedData = _eventData_.compressedData + 100;
                }
                
                // add eth to our players & rounds ICO phase investment. this will be used 
                // to determine total keys and each players share 
                plyrRnds_[_pID][_rID].ico = _eth.add(plyrRnds_[_pID][_rID].ico);
                round_[_rID].ico = _eth.add(round_[_rID].ico);
                
                // add eth in to team eth tracker
                rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]);
                
                // send eth share to com, p3d, affiliate, and fomo3d long
                _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_);
                
                // calculate gen share 
                uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100;
                
                // add gen share to rounds ICO phase gen tracker (will be distributed 
                // when round starts)
                round_[_rID].icoGen = _gen.add(round_[_rID].icoGen);
                
        		// toss 1% into airdrop pot 
                uint256 _air = (_eth / 100);
                airDropPot_ = airDropPot_.add(_air);
                
                // calculate pot share pot (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) - gen
                uint256 _pot = (_eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100))).sub(_gen);
                
                // add eth to pot
                round_[_rID].pot = _pot.add(round_[_rID].pot);
                
                // set up event data
                _eventData_.genAmount = _gen.add(_eventData_.genAmount);
                _eventData_.potAmount = _pot;
                
                // fire event
                endTx(_rID, _pID, _team, _eth, 0, _eventData_);
            }
            
            /**
             * @dev this is the core logic for any buy/reload that happens while a round 
             * is live.
             */
            function core(uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_)
                private
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // check to see if its a new round (past ICO phase) && keys were bought in ICO phase
                if (round_[_rID].eth == 0 && round_[_rID].ico > 0)
                    roundClaimICOKeys(_rID);
                
                // if player is new to round and is owed keys from ICO phase 
                if (plyrRnds_[_pID][_rID].keys == 0 && plyrRnds_[_pID][_rID].ico > 0)
                {
                    // assign player their keys from ICO phase
                    plyrRnds_[_pID][_rID].keys = calcPlayerICOPhaseKeys(_pID, _rID);
                    // zero out ICO phase investment
                    plyrRnds_[_pID][_rID].ico = 0;
                }
                    
                // mint the new keys
                uint256 _keys = (round_[_rID].eth).keysRec(_eth);
                
                // if they bought at least 1 whole key
                if (_keys >= 1000000000000000000)
                {
                    updateTimer(_keys, _rID);
        
                    // set new leaders
                    if (round_[_rID].plyr != _pID)
                        round_[_rID].plyr = _pID;  
                    if (round_[_rID].team != _team)
                        round_[_rID].team = _team; 
                    
                    // set the new leader bool to true
                    _eventData_.compressedData = _eventData_.compressedData + 100;
                }
                
                // manage airdrops
                if (_eth >= 100000000000000000)
                {
                    airDropTracker_++;
                    if (airdrop() == true)
                    {
                        // gib muni
                        uint256 _prize;
                        if (_eth >= 10000000000000000000) 
                        {
                            // calculate prize and give it to winner
                            _prize = ((airDropPot_).mul(75)) / 100;
                            plyr_[_pID].win = (plyr_[_pID].win).add(_prize);
                            
                            // adjust airDropPot 
                            airDropPot_ = (airDropPot_).sub(_prize);
                            
                            // let event know a tier 3 prize was won 
                            _eventData_.compressedData += 300000000000000000000000000000000;
                        } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) {
                            // calculate prize and give it to winner
                            _prize = ((airDropPot_).mul(50)) / 100;
                            plyr_[_pID].win = (plyr_[_pID].win).add(_prize);
                            
                            // adjust airDropPot 
                            airDropPot_ = (airDropPot_).sub(_prize);
                            
                            // let event know a tier 2 prize was won 
                            _eventData_.compressedData += 200000000000000000000000000000000;
                        } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) {
                            // calculate prize and give it to winner
                            _prize = ((airDropPot_).mul(25)) / 100;
                            plyr_[_pID].win = (plyr_[_pID].win).add(_prize);
                            
                            // adjust airDropPot 
                            airDropPot_ = (airDropPot_).sub(_prize);
                            
                            // let event know a tier 1 prize was won 
                            _eventData_.compressedData += 100000000000000000000000000000000;
                        }
                        // set airdrop happened bool to true
                        _eventData_.compressedData += 10000000000000000000000000000000;
                        // let event know how much was won 
                        _eventData_.compressedData += _prize * 1000000000000000000000000000000000;
                        
                        // reset air drop tracker
                        airDropTracker_ = 0;
                    }
                }
        
                // store the air drop tracker number (number of buys since last airdrop)
                _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000);
                
                // update player 
                plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys);
                
                // update round
                round_[_rID].keys = _keys.add(round_[_rID].keys);
                round_[_rID].eth = _eth.add(round_[_rID].eth);
                rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]);
        
                // distribute eth
                _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_);
                _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_);
                
                // call end tx function to fire end tx event.
                endTx(_rID, _pID, _team, _eth, _keys, _eventData_);
            }
        //==============================================================================
        //     _ _ | _   | _ _|_ _  _ _  .
        //    (_(_||(_|_||(_| | (_)| _\  .
        //==============================================================================
            /**
             * @dev calculates unmasked earnings (just calculates, does not update mask)
             * @return earnings in wei format
             */
            function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast)
                private
                view
                returns(uint256)
            {
                // if player does not have unclaimed keys bought in ICO phase
                // return their earnings based on keys held only.
                if (plyrRnds_[_pID][_rIDlast].ico == 0)
                    return(  (((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)  );
                else
                    if (now > round_[_rIDlast].strt + rndGap_ && round_[_rIDlast].eth == 0)
                        return(  (((((round_[_rIDlast].icoGen).mul(1000000000000000000)) / (round_[_rIDlast].ico).keys()).mul(calcPlayerICOPhaseKeys(_pID, _rIDlast))) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)  );
                    else
                        return(  (((round_[_rIDlast].mask).mul(calcPlayerICOPhaseKeys(_pID, _rIDlast))) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)  );
                // otherwise return earnings based on keys owed from ICO phase
                // (this would be a scenario where they only buy during ICO phase, and never 
                // buy/reload during round)
            }
            
            /**
             * @dev average ico phase key price is total eth put in, during ICO phase, 
             * divided by the number of keys that were bought with that eth.
             * -functionhash- 0xdcb6af48
             * @return average key price 
             */
            function calcAverageICOPhaseKeyPrice(uint256 _rID)
                public 
                view 
                returns(uint256)
            {
                return(  (round_[_rID].ico).mul(1000000000000000000) / (round_[_rID].ico).keys()  );
            }
            
            /**
             * @dev at end of ICO phase, each player is entitled to X keys based on final 
             * average ICO phase key price, and the amount of eth they put in during ICO.
             * if a player participates in the round post ICO, these will be "claimed" and 
             * added to their rounds total keys.  if not, this will be used to calculate 
             * their gen earnings throughout round and on round end.
             * -functionhash- 0x75661f4c
             * @return players keys bought during ICO phase 
             */
            function calcPlayerICOPhaseKeys(uint256 _pID, uint256 _rID)
                public 
                view
                returns(uint256)
            {
                if (round_[_rID].icoAvg != 0 || round_[_rID].ico == 0 )
                    return(  ((plyrRnds_[_pID][_rID].ico).mul(1000000000000000000)) / round_[_rID].icoAvg  );
                else
                    return(  ((plyrRnds_[_pID][_rID].ico).mul(1000000000000000000)) / calcAverageICOPhaseKeyPrice(_rID)  );
            }
            
            /** 
             * @dev returns the amount of keys you would get given an amount of eth. 
             * - during live round.  this is accurate. (well... unless someone buys before 
             * you do and ups the price!  you better HURRY!)
             * - during ICO phase.  this is the max you would get based on current eth 
             * invested during ICO phase.  if others invest after you, you will receive
             * less.  (so distract them with meme vids till ICO is over)
             * -functionhash- 0xce89c80c
             * @param _rID round ID you want price for
             * @param _eth amount of eth sent in 
             * @return keys received 
             */
            function calcKeysReceived(uint256 _rID, uint256 _eth)
                public
                view
                returns(uint256)
            {
                // grab time
                uint256 _now = now;
                
                // is ICO phase over??  & theres eth in the round?
                if (_now > round_[_rID].strt + rndGap_ && round_[_rID].eth != 0 && _now <= round_[_rID].end)
                    return ( (round_[_rID].eth).keysRec(_eth) );
                else if (_now <= round_[_rID].end) // round hasn't ended (in ICO phase, or ICO phase is over, but round eth is 0)
                    return ( (round_[_rID].ico).keysRec(_eth) );
                else // rounds over.  need keys for new round
                    return ( (_eth).keys() );
            }
            
            /** 
             * @dev returns current eth price for X keys.  
             * - during live round.  this is accurate. (well... unless someone buys before 
             * you do and ups the price!  you better HURRY!)
             * - during ICO phase.  this is the max you would get based on current eth 
             * invested during ICO phase.  if others invest after you, you will receive
             * less.  (so distract them with meme vids till ICO is over)
             * -functionhash- 0xcf808000
             * @param _keys number of keys desired (in 18 decimal format)
             * @return amount of eth needed to send
             */
            function iWantXKeys(uint256 _keys)
                public
                view
                returns(uint256)
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // grab time
                uint256 _now = now;
                
                // is ICO phase over??  & theres eth in the round?
                if (_now > round_[_rID].strt + rndGap_ && round_[_rID].eth != 0 && _now <= round_[_rID].end)
                    return ( (round_[_rID].keys.add(_keys)).ethRec(_keys) );
                else if (_now <= round_[_rID].end) // round hasn't ended (in ICO phase, or ICO phase is over, but round eth is 0)
                    return ( (((round_[_rID].ico).keys()).add(_keys)).ethRec(_keys) );
                else // rounds over.  need price for new round
                    return ( (_keys).eth() );
            }
        //==============================================================================
        //    _|_ _  _ | _  .
        //     | (_)(_)|_\  .
        //==============================================================================
            /**
        	 * @dev receives name/player info from names contract 
             */
            function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff)
                external
            {
                require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm..");
                if (pIDxAddr_[_addr] != _pID)
                    pIDxAddr_[_addr] = _pID;
                if (pIDxName_[_name] != _pID)
                    pIDxName_[_name] = _pID;
                if (plyr_[_pID].addr != _addr)
                    plyr_[_pID].addr = _addr;
                if (plyr_[_pID].name != _name)
                    plyr_[_pID].name = _name;
                if (plyr_[_pID].laff != _laff)
                    plyr_[_pID].laff = _laff;
                if (plyrNames_[_pID][_name] == false)
                    plyrNames_[_pID][_name] = true;
            }
        
            /**
             * @dev receives entire player name list 
             */
            function receivePlayerNameList(uint256 _pID, bytes32 _name)
                external
            {
                require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm..");
                if(plyrNames_[_pID][_name] == false)
                    plyrNames_[_pID][_name] = true;
            }  
                
            /**
             * @dev gets existing or registers new pID.  use this when a player may be new
             * @return pID 
             */
            function determinePID(F3Ddatasets.EventReturns memory _eventData_)
                private
                returns (F3Ddatasets.EventReturns)
            {
                uint256 _pID = pIDxAddr_[msg.sender];
                // if player is new to this version of fomo3d
                if (_pID == 0)
                {
                    // grab their player ID, name and last aff ID, from player names contract 
                    _pID = PlayerBook.getPlayerID(msg.sender);
                    bytes32 _name = PlayerBook.getPlayerName(_pID);
                    uint256 _laff = PlayerBook.getPlayerLAff(_pID);
                    
                    // set up player account 
                    pIDxAddr_[msg.sender] = _pID;
                    plyr_[_pID].addr = msg.sender;
                    
                    if (_name != "")
                    {
                        pIDxName_[_name] = _pID;
                        plyr_[_pID].name = _name;
                        plyrNames_[_pID][_name] = true;
                    }
                    
                    if (_laff != 0 && _laff != _pID)
                        plyr_[_pID].laff = _laff;
                    
                    // set the new player bool to true
                    _eventData_.compressedData = _eventData_.compressedData + 1;
                } 
                return (_eventData_);
            }
            
            /**
             * @dev checks to make sure user picked a valid team.  if not sets team 
             * to default (sneks)
             */
            function verifyTeam(uint256 _team)
                private
                pure
                returns (uint256)
            {
                if (_team < 0 || _team > 3)
                    return(2);
                else
                    return(_team);
            }
            
            /**
             * @dev decides if round end needs to be run & new round started.  and if 
             * player unmasked earnings from previously played rounds need to be moved.
             */
            function manageRoundAndPlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_)
                private
                returns (F3Ddatasets.EventReturns)
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // grab time
                uint256 _now = now;
                
                // check to see if round has ended.  we use > instead of >= so that LAST
                // second snipe tx can extend the round.
                if (_now > round_[_rID].end)
                {
                    // check to see if round end has been run yet.  (distributes pot)
                    if (round_[_rID].ended == false)
                    {
                        _eventData_ = endRound(_eventData_);
                        round_[_rID].ended = true;
                    }
                    
                    // start next round in ICO phase
                    rID_++;
                    _rID++;
                    round_[_rID].strt = _now;
                    round_[_rID].end = _now.add(rndInit_).add(rndGap_);
                }
                
                // is player new to round?
                if (plyr_[_pID].lrnd != _rID)
                {
                    // if player has played a previous round, move their unmasked earnings
                    // from that round to gen vault.
                    if (plyr_[_pID].lrnd != 0)
                        updateGenVault(_pID, plyr_[_pID].lrnd);
                    
                    // update player's last round played
                    plyr_[_pID].lrnd = _rID;
                    
                    // set the joined round bool to true
                    _eventData_.compressedData = _eventData_.compressedData + 10;
                }
                
                return(_eventData_);
            }
            
            /**
             * @dev ends the round. manages paying out winner/splitting up pot
             */
            function endRound(F3Ddatasets.EventReturns memory _eventData_)
                private
                returns (F3Ddatasets.EventReturns)
            {
                // setup local rID
                uint256 _rID = rID_;
                
                // check to round ended with ONLY ico phase transactions
                if (round_[_rID].eth == 0 && round_[_rID].ico > 0)
                    roundClaimICOKeys(_rID);
                
                // grab our winning player and team id's
                uint256 _winPID = round_[_rID].plyr;
                uint256 _winTID = round_[_rID].team;
                
                // grab our pot amount
                uint256 _pot = round_[_rID].pot;
                
                // calculate our winner share, community rewards, gen share, 
                // p3d share, and amount reserved for next pot 
                uint256 _win = (_pot.mul(48)) / 100;
                uint256 _com = (_pot / 50);
                uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100;
                uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100;
                uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d);
                
                // calculate ppt for round mask
                uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys);
                uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000);
                if (_dust > 0)
                {
                    _gen = _gen.sub(_dust);
                    _res = _res.add(_dust);
                }
                
                // pay our winner
                plyr_[_winPID].win = _win.add(plyr_[_winPID].win);
                
                // community rewards
                if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()"))))
                {
                    // This ensures Team Just cannot influence the outcome of FoMo3D with
                    // bank migrations by breaking outgoing transactions.
                    // Something we would never do. But that's not the point.
                    // We spent 2000$ in eth re-deploying just to patch this, we hold the 
                    // highest belief that everything we create should be trustless.
                    // Team JUST, The name you shouldn't have to trust.
                    _p3d = _p3d.add(_com);
                    _com = 0;
                }
                    
                // distribute gen portion to key holders
                round_[_rID].mask = _ppt.add(round_[_rID].mask);
                
                // send share for p3d to divies
                if (_p3d > 0)
                    Divies.deposit.value(_p3d)();
                    
                // fill next round pot with its share
                round_[_rID + 1].pot += _res;
                
                // prepare event data
                _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000);
                _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000);
                _eventData_.winnerAddr = plyr_[_winPID].addr;
                _eventData_.winnerName = plyr_[_winPID].name;
                _eventData_.amountWon = _win;
                _eventData_.genAmount = _gen;
                _eventData_.P3DAmount = _p3d;
                _eventData_.newPot = _res;
                
                return(_eventData_);
            }
            
            /**
             * @dev takes keys bought during ICO phase, and adds them to round.  pays 
             * out gen rewards that accumulated during ICO phase 
             */
            function roundClaimICOKeys(uint256 _rID)
                private
            {
                // update round eth to account for ICO phase eth investment 
                round_[_rID].eth = round_[_rID].ico;
                        
                // add keys to round that were bought during ICO phase
                round_[_rID].keys = (round_[_rID].ico).keys();
                
                // store average ICO key price 
                round_[_rID].icoAvg = calcAverageICOPhaseKeyPrice(_rID);
                        
                // set round mask from ICO phase
                uint256 _ppt = ((round_[_rID].icoGen).mul(1000000000000000000)) / (round_[_rID].keys);
                uint256 _dust = (round_[_rID].icoGen).sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000));
                if (_dust > 0)
                    round_[_rID].pot = (_dust).add(round_[_rID].pot);   // <<< your adding to pot and havent updated event data
                        
                // distribute gen portion to key holders
                round_[_rID].mask = _ppt.add(round_[_rID].mask);
            }
            
            /**
             * @dev moves any unmasked earnings to gen vault.  updates earnings mask
             */
            function updateGenVault(uint256 _pID, uint256 _rIDlast)
                private 
            {
                uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast);
                if (_earnings > 0)
                {
                    // put in gen vault
                    plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen);
                    // zero out their earnings by updating mask
                    plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask);
                }
            }
            
            /**
             * @dev updates round timer based on number of whole keys bought.
             */
            function updateTimer(uint256 _keys, uint256 _rID)
                private
            {
                // calculate time based on number of keys bought
                uint256 _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end);
                
                // grab time
                uint256 _now = now;
                
                // compare to max and set new end time
                if (_newTime < (rndMax_).add(_now))
                    round_[_rID].end = _newTime;
                else
                    round_[_rID].end = rndMax_.add(_now);
            }
            
            /**
             * @dev generates a random number between 0-99 and checks to see if thats
             * resulted in an airdrop win
             * @return do we have a winner?
             */
            function airdrop()
                private 
                view 
                returns(bool)
            {
                uint256 seed = uint256(keccak256(abi.encodePacked(
                    
                    (block.timestamp).add
                    (block.difficulty).add
                    ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add
                    (block.gaslimit).add
                    ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add
                    (block.number)
                    
                )));
                if((seed - ((seed / 1000) * 1000)) < airDropTracker_)
                    return(true);
                else
                    return(false);
            }
        
            /**
             * @dev distributes eth based on fees to com, aff, and p3d
             */
            function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_)
                private
                returns(F3Ddatasets.EventReturns)
            {
                // pay 2% out to community rewards
                uint256 _com = _eth / 50;
                uint256 _p3d;
                if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()"))))
                {
                    // This ensures Team Just cannot influence the outcome of FoMo3D with
                    // bank migrations by breaking outgoing transactions.
                    // Something we would never do. But that's not the point.
                    // We spent 2000$ in eth re-deploying just to patch this, we hold the 
                    // highest belief that everything we create should be trustless.
                    // Team JUST, The name you shouldn't have to trust.
                    _p3d = _com;
                    _com = 0;
                }
                
                // pay 1% out to FoMo3D long
                uint256 _long = _eth / 100;
                round_[_rID + 1].pot += _long;
                
                // distribute share to affiliate
                uint256 _aff = _eth / 10;
                
                // decide what to do with affiliate share of fees
                // affiliate must not be self, and must have a name registered
                if (_affID != _pID && plyr_[_affID].name != '') {
                    plyr_[_affID].aff = _aff.add(plyr_[_affID].aff);
                    emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff, now);
                } else {
                    _p3d = _aff;
                }
                
                // pay out p3d
                _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100));
                if (_p3d > 0)
                {
                    // deposit to divies contract
                    Divies.deposit.value(_p3d)();
                    
                    // set up event data
                    _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount);
                }
                
                return(_eventData_);
            }
            
            function potSwap()
                external
                payable
            {
                // setup local rID
                uint256 _rID = rID_ + 1;
                
                round_[_rID].pot = round_[_rID].pot.add(msg.value);
                emit F3Devents.onPotSwapDeposit(_rID, msg.value);
            }
            
            /**
             * @dev distributes eth based on fees to gen and pot
             */
            function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_)
                private
                returns(F3Ddatasets.EventReturns)
            {
                // calculate gen share
                uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100;
                
                // toss 1% into airdrop pot 
                uint256 _air = (_eth / 100);
                airDropPot_ = airDropPot_.add(_air);
                
                // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share))
                _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100));
                
                // calculate pot 
                uint256 _pot = _eth.sub(_gen);
                
                // distribute gen share (thats what updateMasks() does) and adjust
                // balances for dust.
                uint256 _dust = updateMasks(_rID, _pID, _gen, _keys);
                if (_dust > 0)
                    _gen = _gen.sub(_dust);
                
                // add eth to pot
                round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot);
                
                // set up event data
                _eventData_.genAmount = _gen.add(_eventData_.genAmount);
                _eventData_.potAmount = _pot;
                
                return(_eventData_);
            }
        
            /**
             * @dev updates masks for round and player when keys are bought
             * @return dust left over 
             */
            function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys)
                private
                returns(uint256)
            {
                /* MASKING NOTES
                    earnings masks are a tricky thing for people to wrap their minds around.
                    the basic thing to understand here.  is were going to have a global
                    tracker based on profit per share for each round, that increases in
                    relevant proportion to the increase in share supply.
                    
                    the player will have an additional mask that basically says "based
                    on the rounds mask, my shares, and how much i've already withdrawn,
                    how much is still owed to me?"
                */
                
                // calc profit per key & round mask based on this buy:  (dust goes to pot)
                uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys);
                round_[_rID].mask = _ppt.add(round_[_rID].mask);
                    
                // calculate player earning from their own buy (only based on the keys
                // they just bought).  & update player earnings mask
                uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000);
                plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask);
                
                // calculate & return dust
                return(_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000)));
            }
            
            /**
             * @dev adds up unmasked earnings, & vault earnings, sets them all to 0
             * @return earnings in wei format
             */
            function withdrawEarnings(uint256 _pID)
                private
                returns(uint256)
            {
                // update gen vault
                updateGenVault(_pID, plyr_[_pID].lrnd);
                
                // from vaults 
                uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff);
                if (_earnings > 0)
                {
                    plyr_[_pID].win = 0;
                    plyr_[_pID].gen = 0;
                    plyr_[_pID].aff = 0;
                }
        
                return(_earnings);
            }
            
            /**
             * @dev prepares compression data and fires event for buy or reload tx's
             */
            function endTx(uint256 _rID, uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_)
                private
            {
                _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000);
                _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (_rID * 10000000000000000000000000000000000000000000000000000);
                
                emit F3Devents.onEndTx
                (
                    _eventData_.compressedData,
                    _eventData_.compressedIDs,
                    plyr_[_pID].name,
                    msg.sender,
                    _eth,
                    _keys,
                    _eventData_.winnerAddr,
                    _eventData_.winnerName,
                    _eventData_.amountWon,
                    _eventData_.newPot,
                    _eventData_.P3DAmount,
                    _eventData_.genAmount,
                    _eventData_.potAmount,
                    airDropPot_
                );
            }
        //==============================================================================
        //    (~ _  _    _._|_    .
        //    _)(/_(_|_|| | | \/  .
        //====================/=========================================================
            /** upon contract deploy, it will be deactivated.  this is a one time
             * use function that will activate the contract.  we do this so devs 
             * have time to set things up on the web end                            **/
            bool public activated_ = false;
            function activate()
                public
            {
                // only team just can activate 
                require(
                    msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C ||
                    msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D ||
                    msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 ||
                    msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C ||
        			msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3,
                    "only team just can activate"
                );
        
                // can only be ran once
                require(activated_ == false, "fomo3d already activated");
                
                // activate the contract 
                activated_ = true;
                
                // lets start first round in ICO phase
        		rID_ = 1;
                round_[1].strt = now;
                round_[1].end = now + rndInit_ + rndGap_;
            }
        }
        
        
        //==============================================================================
        //   __|_ _    __|_ _  .
        //  _\ | | |_|(_ | _\  .
        //==============================================================================
        library F3Ddatasets {
            //compressedData key
            // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0]
                // 0 - new player (bool)
                // 1 - joined round (bool)
                // 2 - new  leader (bool)
                // 3-5 - air drop tracker (uint 0-999)
                // 6-16 - round end time
                // 17 - winnerTeam
                // 18 - 28 timestamp 
                // 29 - team
                // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico)
                // 31 - airdrop happened bool
                // 32 - airdrop tier 
                // 33 - airdrop amount won
            //compressedIDs key
            // [77-52][51-26][25-0]
                // 0-25 - pID 
                // 26-51 - winPID
                // 52-77 - rID
            struct EventReturns {
                uint256 compressedData;
                uint256 compressedIDs;
                address winnerAddr;         // winner address
                bytes32 winnerName;         // winner name
                uint256 amountWon;          // amount won
                uint256 newPot;             // amount in new pot
                uint256 P3DAmount;          // amount distributed to p3d
                uint256 genAmount;          // amount distributed to gen
                uint256 potAmount;          // amount added to pot
            }
            struct Player {
                address addr;   // player address
                bytes32 name;   // player name
                uint256 win;    // winnings vault
                uint256 gen;    // general vault
                uint256 aff;    // affiliate vault
                uint256 lrnd;   // last round played
                uint256 laff;   // last affiliate id used
            }
            struct PlayerRounds {
                uint256 eth;    // eth player has added to round (used for eth limiter)
                uint256 keys;   // keys
                uint256 mask;   // player mask 
                uint256 ico;    // ICO phase investment
            }
            struct Round {
                uint256 plyr;   // pID of player in lead
                uint256 team;   // tID of team in lead
                uint256 end;    // time ends/ended
                bool ended;     // has round end function been ran
                uint256 strt;   // time round started
                uint256 keys;   // keys
                uint256 eth;    // total eth in
                uint256 pot;    // eth to pot (during round) / final amount paid to winner (after round ends)
                uint256 mask;   // global mask
                uint256 ico;    // total eth sent in during ICO phase
                uint256 icoGen; // total eth for gen during ICO phase
                uint256 icoAvg; // average key price for ICO phase
            }
            struct TeamFee {
                uint256 gen;    // % of buy in thats paid to key holders of current round
                uint256 p3d;    // % of buy in thats paid to p3d holders
            }
            struct PotSplit {
                uint256 gen;    // % of pot thats paid to key holders of current round
                uint256 p3d;    // % of pot thats paid to p3d holders
            }
        }
        
        //==============================================================================
        //  |  _      _ _ | _  .
        //  |<(/_\/  (_(_||(_  .
        //=======/======================================================================
        library F3DKeysCalcFast {
            using SafeMath for *;
            
            /**
             * @dev calculates number of keys received given X eth 
             * @param _curEth current amount of eth in contract 
             * @param _newEth eth being spent
             * @return amount of ticket purchased
             */
            function keysRec(uint256 _curEth, uint256 _newEth)
                internal
                pure
                returns (uint256)
            {
                return(keys((_curEth).add(_newEth)).sub(keys(_curEth)));
            }
            
            /**
             * @dev calculates amount of eth received if you sold X keys 
             * @param _curKeys current amount of keys that exist 
             * @param _sellKeys amount of keys you wish to sell
             * @return amount of eth received
             */
            function ethRec(uint256 _curKeys, uint256 _sellKeys)
                internal
                pure
                returns (uint256)
            {
                return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys))));
            }
        
            /**
             * @dev calculates how many keys would exist with given an amount of eth
             * @param _eth eth "in contract"
             * @return number of keys that would exist
             */
            function keys(uint256 _eth) 
                internal
                pure
                returns(uint256)
            {
                return ((((((_eth).mul(1000000000000000000)).mul(200000000000000000000000000000000)).add(2500000000000000000000000000000000000000000000000000000000000000)).sqrt()).sub(50000000000000000000000000000000)) / (100000000000000);
            }
            
            /**
             * @dev calculates how much eth would be in contract given a number of keys
             * @param _keys number of keys "in contract" 
             * @return eth that would exists
             */
            function eth(uint256 _keys) 
                internal
                pure
                returns(uint256)  
            {
                return ((50000000000000).mul(_keys.sq()).add(((100000000000000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq());
            }
        }
        
        //==============================================================================
        //  . _ _|_ _  _ |` _  _ _  _  .
        //  || | | (/_| ~|~(_|(_(/__\  .
        //==============================================================================
        interface DiviesInterface {
            function deposit() external payable;
        }
        
        interface JIincForwarderInterface {
            function deposit() external payable returns(bool);
            function status() external view returns(address, address, bool);
            function startMigration(address _newCorpBank) external returns(bool);
            function cancelMigration() external returns(bool);
            function finishMigration() external returns(bool);
            function setup(address _firstCorpBank) external;
        }
        
        interface PlayerBookInterface {
            function getPlayerID(address _addr) external returns (uint256);
            function getPlayerName(uint256 _pID) external view returns (bytes32);
            function getPlayerLAff(uint256 _pID) external view returns (uint256);
            function getPlayerAddr(uint256 _pID) external view returns (address);
            function getNameFee() external view returns (uint256);
            function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256);
            function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256);
            function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256);
        }
        
        /**
        * @title -Name Filter- v0.1.9
        * ┌┬┐┌─┐┌─┐┌┬┐   ╦╦ ╦╔═╗╔╦╗  ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐
        *  │ ├┤ ├─┤│││   ║║ ║╚═╗ ║   ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐
        *  ┴ └─┘┴ ┴┴ ┴  ╚╝╚═╝╚═╝ ╩   ┴  ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘
        *                                  _____                      _____
        *                                 (, /     /)       /) /)    (, /      /)          /)
        *          ┌─┐                      /   _ (/_      // //       /  _   // _   __  _(/
        *          ├─┤                  ___/___(/_/(__(_/_(/_(/_   ___/__/_)_(/_(_(_/ (_(_(_
        *          ┴ ┴                /   /          .-/ _____   (__ /                               
        *                            (__ /          (_/ (, /                                      /)™ 
        *                                                 /  __  __ __ __  _   __ __  _  _/_ _  _(/
        * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐                          /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_
        * ├─┘├┬┘│ │ │││ ││   │                      (__ /              .-/  © Jekyll Island Inc. 2018
        * ┴  ┴└─└─┘─┴┘└─┘└─┘ ┴                                        (_/
        *              _       __    _      ____      ____  _   _    _____  ____  ___  
        *=============| |\ |  / /\  | |\/| | |_ =====| |_  | | | |    | |  | |_  | |_)==============*
        *=============|_| \| /_/--\ |_|  | |_|__=====|_|   |_| |_|__  |_|  |_|__ |_| \==============*
        *
        * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐  ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐
        * ║  │ ││││ │ ├┬┘├─┤│   │   ║  │ │ ││├┤  │ Inventor │
        * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴   ╚═╝└─┘─┴┘└─┘ └──────────┘
        */
        
        library NameFilter {
            
            /**
             * @dev filters name strings
             * -converts uppercase to lower case.  
             * -makes sure it does not start/end with a space
             * -makes sure it does not contain multiple spaces in a row
             * -cannot be only numbers
             * -cannot start with 0x 
             * -restricts characters to A-Z, a-z, 0-9, and space.
             * @return reprocessed string in bytes32 format
             */
            function nameFilter(string _input)
                internal
                pure
                returns(bytes32)
            {
                bytes memory _temp = bytes(_input);
                uint256 _length = _temp.length;
                
                //sorry limited to 32 characters
                require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters");
                // make sure it doesnt start with or end with space
                require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space");
                // make sure first two characters are not 0x
                if (_temp[0] == 0x30)
                {
                    require(_temp[1] != 0x78, "string cannot start with 0x");
                    require(_temp[1] != 0x58, "string cannot start with 0X");
                }
                
                // create a bool to track if we have a non number character
                bool _hasNonNumber;
                
                // convert & check
                for (uint256 i = 0; i < _length; i++)
                {
                    // if its uppercase A-Z
                    if (_temp[i] > 0x40 && _temp[i] < 0x5b)
                    {
                        // convert to lower case a-z
                        _temp[i] = byte(uint(_temp[i]) + 32);
                        
                        // we have a non number
                        if (_hasNonNumber == false)
                            _hasNonNumber = true;
                    } else {
                        require
                        (
                            // require character is a space
                            _temp[i] == 0x20 || 
                            // OR lowercase a-z
                            (_temp[i] > 0x60 && _temp[i] < 0x7b) ||
                            // or 0-9
                            (_temp[i] > 0x2f && _temp[i] < 0x3a),
                            "string contains invalid characters"
                        );
                        // make sure theres not 2x spaces in a row
                        if (_temp[i] == 0x20)
                            require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces");
                        
                        // see if we have a character other than a number
                        if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39))
                            _hasNonNumber = true;    
                    }
                }
                
                require(_hasNonNumber == true, "string cannot be only numbers");
                
                bytes32 _ret;
                assembly {
                    _ret := mload(add(_temp, 32))
                }
                return (_ret);
            }
        }
        
        /**
         * @title SafeMath v0.1.9
         * @dev Math operations with safety checks that throw on error
         * change notes:  original SafeMath library from OpenZeppelin modified by Inventor
         * - added sqrt
         * - added sq
         * - added pwr 
         * - changed asserts to requires with error log outputs
         * - removed div, its useless
         */
        library SafeMath {
            
            /**
            * @dev Multiplies two numbers, throws on overflow.
            */
            function mul(uint256 a, uint256 b) 
                internal 
                pure 
                returns (uint256 c) 
            {
                if (a == 0) {
                    return 0;
                }
                c = a * b;
                require(c / a == b, "SafeMath mul failed");
                return c;
            }
        
            /**
            * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
            */
            function sub(uint256 a, uint256 b)
                internal
                pure
                returns (uint256) 
            {
                require(b <= a, "SafeMath sub failed");
                return a - b;
            }
        
            /**
            * @dev Adds two numbers, throws on overflow.
            */
            function add(uint256 a, uint256 b)
                internal
                pure
                returns (uint256 c) 
            {
                c = a + b;
                require(c >= a, "SafeMath add failed");
                return c;
            }
            
            /**
             * @dev gives square root of given x.
             */
            function sqrt(uint256 x)
                internal
                pure
                returns (uint256 y) 
            {
                uint256 z = ((add(x,1)) / 2);
                y = x;
                while (z < y) 
                {
                    y = z;
                    z = ((add((x / z),z)) / 2);
                }
            }
            
            /**
             * @dev gives square. multiplies x by x
             */
            function sq(uint256 x)
                internal
                pure
                returns (uint256)
            {
                return (mul(x,x));
            }
            
            /**
             * @dev x to the power of y 
             */
            function pwr(uint256 x, uint256 y)
                internal 
                pure 
                returns (uint256)
            {
                if (x==0)
                    return (0);
                else if (y==0)
                    return (1);
                else 
                {
                    uint256 z = x;
                    for (uint256 i=1; i < y; i++)
                        z = mul(z,x);
                    return (z);
                }
            }
        }

        File 2 of 3: JIincForwarder
        pragma solidity ^0.4.24;
        /*
         * @title -Jekyll Island- CORP BANK FORWARDER v0.4.6
         * ┌┬┐┌─┐┌─┐┌┬┐   ╦╦ ╦╔═╗╔╦╗  ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐
         *  │ ├┤ ├─┤│││   ║║ ║╚═╗ ║   ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐
         *  ┴ └─┘┴ ┴┴ ┴  ╚╝╚═╝╚═╝ ╩   ┴  ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘
         *                                  _____                      _____
         *                                 (, /     /)       /) /)    (, /      /)          /)
         *          ┌─┐                      /   _ (/_      // //       /  _   // _   __  _(/
         *          ├─┤                  ___/___(/_/(__(_/_(/_(/_   ___/__/_)_(/_(_(_/ (_(_(_
         *          ┴ ┴                /   /          .-/ _____   (__ /                               
         *                            (__ /          (_/ (, /                                      /)™ 
         *                                                 /  __  __ __ __  _   __ __  _  _/_ _  _(/
         * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐                          /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_
         * ├─┘├┬┘│ │ │││ ││   │                      (__ /              .-/  © Jekyll Island Inc. 2018
         * ┴  ┴└─└─┘─┴┘└─┘└─┘ ┴                                        (_/
         *====/$$$$$===========/$$=================/$$ /$$====/$$$$$$===========/$$===========================/$$=*
         *   |__  $$          | $$                | $$| $$   |_  $$_/          | $$                          | $$
         *      | $$  /$$$$$$ | $$   /$$ /$$   /$$| $$| $$     | $$    /$$$$$$$| $$  /$$$$$$  /$$$$$$$   /$$$$$$$
         *      | $$ /$$__  $$| $$  /$$/| $$  | $$| $$| $$     | $$   /$$_____/| $$ |____  $$| $$__  $$ /$$__  $$
         * /$$  | $$| $$$$$$$$| $$$$$$/ | $$  | $$| $$| $$     | $$  |  $$$$$$ | $$  /$$$$$$$| $$  \ $$| $$  | $$
         *| $$  | $$| $$_____/| $$_  $$ | $$  | $$| $$| $$     | $$   \____  $$| $$ /$$__  $$| $$  | $$| $$  | $$
         *|  $$$$$$/|  $$$$$$$| $$ \  $$|  $$$$$$$| $$| $$    /$$$$$$ /$$$$$$$/| $$|  $$$$$$$| $$  | $$|  $$$$$$$
         * \______/  \_______/|__/  \__/ \____  $$|__/|__/   |______/|_______/ |__/ \_______/|__/  |__/ \_______/
         *===============================/$$  | $$ Inc.  ╔═╗╔═╗╦═╗╔═╗  ╔╗ ╔═╗╔╗╔╦╔═  ┌─┐┌─┐┬─┐┬ ┬┌─┐┬─┐┌┬┐┌─┐┬─┐                                 
         *                              |  $$$$$$/=======║  ║ ║╠╦╝╠═╝  ╠╩╗╠═╣║║║╠╩╗  ├┤ │ │├┬┘│││├─┤├┬┘ ││├┤ ├┬┘  
         *                               \______/        ╚═╝╚═╝╩╚═╩    ╚═╝╩ ╩╝╚╝╩ ╩  └  └─┘┴└─└┴┘┴ ┴┴└──┴┘└─┘┴└─==*
         * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐  ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐                       
         * ║  │ ││││ │ ├┬┘├─┤│   │   ║  │ │ ││├┤  │ Inventor │                      
         * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴   ╚═╝└─┘─┴┘└─┘ └──────────┘                      
         *===========================================================================================*
         *                                ┌────────────────────┐
         *                                │ Setup Instructions │
         *                                └────────────────────┘
         * (Step 1) import the Jekyll Island Inc Forwarder Interface into your contract
         * 
         *    import "./JIincForwarderInterface.sol";
         *
         * (Step 2) set it to point to the forwarder
         * 
         *    JIincForwarderInterface private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE);
         *                                ┌────────────────────┐
         *                                │ Usage Instructions │
         *                                └────────────────────┘
         * whenever your contract needs to send eth to the corp bank, simply use the 
         * the following command:
         *
         *    Jekyll_Island_Inc.deposit.value(amount)()
         * 
         * OPTIONAL:
         * if you need to be checking wither the transaction was successful, the deposit function returns 
         * a bool indicating wither or not it was successful.  so another way to call this function 
         * would be:
         * 
         *    require(Jekyll_Island_Inc.deposit.value(amount)() == true, "Jekyll Island deposit failed");
         * 
         */
        
        interface JIincInterfaceForForwarder {
            function deposit(address _addr) external payable returns (bool);
            function migrationReceiver_setup() external returns (bool);
        }
        
        contract JIincForwarder {
            string public name = "JIincForwarder";
            JIincInterfaceForForwarder private currentCorpBank_;
            address private newCorpBank_;
            bool needsBank_ = true;
            
            constructor() 
                public
            {
                //constructor does nothing.
            }
            
            function()
                public
                payable
            {
                // done so that if any one tries to dump eth into this contract, we can
                // just forward it to corp bank.
                currentCorpBank_.deposit.value(address(this).balance)(address(currentCorpBank_));
            }
            
            function deposit()
                public 
                payable
                returns(bool)
            {
                require(msg.value > 0, "Forwarder Deposit failed - zero deposits not allowed");
                require(needsBank_ == false, "Forwarder Deposit failed - no registered bank");
                if (currentCorpBank_.deposit.value(msg.value)(msg.sender) == true)
                    return(true);
                else
                    return(false);
            }
        //==============================================================================
        //     _ _ . _  _ _ _|_. _  _   .
        //    | | ||(_|| (_| | |(_)| |  .
        //===========_|=================================================================    
            function status()
                public
                view
                returns(address, address, bool)
            {
                return(address(currentCorpBank_), address(newCorpBank_), needsBank_);
            }
        
            function startMigration(address _newCorpBank)
                external
                returns(bool)
            {
                // make sure this is coming from current corp bank
                require(msg.sender == address(currentCorpBank_), "Forwarder startMigration failed - msg.sender must be current corp bank");
                
                // communicate with the new corp bank and make sure it has the forwarder 
                // registered 
                if(JIincInterfaceForForwarder(_newCorpBank).migrationReceiver_setup() == true)
                {
                    // save our new corp bank address
                    newCorpBank_ = _newCorpBank;
                    return (true);
                } else 
                    return (false);
            }
            
            function cancelMigration()
                external
                returns(bool)
            {
                // make sure this is coming from the current corp bank (also lets us know 
                // that current corp bank has not been killed)
                require(msg.sender == address(currentCorpBank_), "Forwarder cancelMigration failed - msg.sender must be current corp bank");
                
                // erase stored new corp bank address;
                newCorpBank_ = address(0x0);
                
                return (true);
            }
            
            function finishMigration()
                external
                returns(bool)
            {
                // make sure its coming from new corp bank
                require(msg.sender == newCorpBank_, "Forwarder finishMigration failed - msg.sender must be new corp bank");
        
                // update corp bank address        
                currentCorpBank_ = (JIincInterfaceForForwarder(newCorpBank_));
                
                // erase new corp bank address
                newCorpBank_ = address(0x0);
                
                return (true);
            }
        //==============================================================================
        //    . _ ._|_. _ |   _ _ _|_    _   .
        //    || || | |(_||  _\(/_ | |_||_)  .  (this only runs once ever)
        //==============================|===============================================
            function setup(address _firstCorpBank)
                external
            {
                require(needsBank_ == true, "Forwarder setup failed - corp bank already registered");
                currentCorpBank_ = JIincInterfaceForForwarder(_firstCorpBank);
                needsBank_ = false;
            }
        }

        File 3 of 3: Divies
        pragma solidity ^0.4.24;
        /** title -Divies- v0.7.1
         * ┌┬┐┌─┐┌─┐┌┬┐   ╦╦ ╦╔═╗╔╦╗  ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐
         *  │ ├┤ ├─┤│││   ║║ ║╚═╗ ║   ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐
         *  ┴ └─┘┴ ┴┴ ┴  ╚╝╚═╝╚═╝ ╩   ┴  ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘
         *                                  _____                      _____
         *                                 (, /     /)       /) /)    (, /      /)          /)
         *          ┌─┐                      /   _ (/_      // //       /  _   // _   __  _(/
         *          ├─┤                  ___/___(/_/(__(_/_(/_(/_   ___/__/_)_(/_(_(_/ (_(_(_
         *          ┴ ┴                /   /          .-/ _____   (__ /                               
         *                            (__ /          (_/ (, /                                      /)™ 
         *                                                 /  __  __ __ __  _   __ __  _  _/_ _  _(/
         * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐                          /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_
         * ├─┘├┬┘│ │ │││ ││   │                      (__ /              .-/  © Jekyll Island Inc. 2018
         * ┴  ┴└─└─┘─┴┘└─┘└─┘ ┴                                        (_/
         *          ______      .-./`)  ,---.  ,---. .-./`)      .-''-.      .-'''-.   .---.  
         *=========|    _ `''.  \ .-.') |   /  |   | \ .-.')   .'_ _   \    / _     \  \   /=========*
         *         | _ | ) _  \ / `-' \ |  |   |  .' / `-' \  / ( ` )   '  (`' )/`--'  |   |  
         *         |( ''_'  ) |  `-'`"` |  | _ |  |   `-'`"` . (_ o _)  | (_ o _).      \ /   
         *         | . (_) `. |  .---.  |  _( )_  |   .---.  |  (_,_)___|  (_,_). '.     v    
         *         |(_    ._) '  |   |  \ (_ o._) /   |   |  '  \   .---. .---.  \  :   _ _   
         *         |  (_.\.' /   |   |   \ (_,_) /    |   |   \  `-'    / \    `-'  |  (_I_)  
         *=========|       .'    |   |    \     /     |   |    \       /   \       /  (_(=)_)========* 
         *         '-----'`      '---'     `---`      '---'     `'-..-'     `-...-'    (_I_)  
         * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐  ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐
         * ║  │ ││││ │ ├┬┘├─┤│   │   ║  │ │ ││├┤  │ Inventor │
         * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴   ╚═╝└─┘─┴┘└─┘ └──────────┘
         *         ┌──────────────────────────────────────────────────────────────────────┐
         *         │ Divies!, is a contract that adds an external dividend system to P3D. │
         *         │ All eth sent to this contract, can be distributed to P3D holders.    │
         *         └──────────────────────────────────────────────────────────────────────┘
         *                                ┌────────────────────┐
         *                                │ Setup Instructions │
         *                                └────────────────────┘
         * (Step 1) import this contracts interface into your contract
         * 
         *    import "./DiviesInterface.sol";
         * 
         * (Step 2) set up the interface and point it to this contract
         * 
         *    DiviesInterface private Divies = DiviesInterface(0xC0c001140319C5f114F8467295b1F22F86929Ad0);
         *                                ┌────────────────────┐
         *                                │ Usage Instructions │
         *                                └────────────────────┘
         * call as follows anywhere in your code:
         *   
         *    Divies.deposit.value(amount)();
         *          ex:  Divies.deposit.value(232000000000000000000)();
         */
        interface HourglassInterface {
            function() payable external;
            function buy(address _playerAddress) payable external returns(uint256);
            function sell(uint256 _amountOfTokens) external;
            function reinvest() external;
            function withdraw() external;
            function exit() external;
            function dividendsOf(address _playerAddress) external view returns(uint256);
            function balanceOf(address _playerAddress) external view returns(uint256);
            function transfer(address _toAddress, uint256 _amountOfTokens) external returns(bool);
            function stakingRequirement() external view returns(uint256);
        }
        
        contract Divies {
            using SafeMath for uint256;
            using UintCompressor for uint256;
        
            HourglassInterface constant P3Dcontract_ = HourglassInterface(0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe);
            
            uint256 public pusherTracker_ = 100;
            mapping (address => Pusher) public pushers_;
            struct Pusher
            {
                uint256 tracker;
                uint256 time;
            }
            uint256 public rateLimiter_;
            
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            // MODIFIERS
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            modifier isHuman() {
                address _addr = msg.sender;
                require(_addr == tx.origin);
                uint256 _codeLength;
                
                assembly {_codeLength := extcodesize(_addr)}
                require(_codeLength == 0, "sorry humans only");
                _;
            }
            
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            // BALANCE
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            function balances()
                public
                view
                returns(uint256)
            {
                return (address(this).balance);
            }
            
            
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            // DEPOSIT
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            function deposit()
                external
                payable
            {
                
            }
            
            // used so the distribute function can call hourglass's withdraw
            function() external payable {}
            
            
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            // EVENTS
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            event onDistribute(
                address pusher,
                uint256 startingBalance,
                uint256 finalBalance,
                uint256 compressedData
            );
            /* compression key
            [0-14] - timestamp
            [15-29] - caller pusher tracker 
            [30-44] - global pusher tracker 
            [45-46] - percent
            [47] - greedy
            */  
            
            
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            // DISTRIBUTE
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            function distribute(uint256 _percent)
                public
                isHuman()
            {
                // make sure _percent is within boundaries
                require(_percent > 0 && _percent < 100, "please pick a percent between 1 and 99");
                
                // data setup
                address _pusher = msg.sender;
                uint256 _bal = address(this).balance;
                uint256 _compressedData;
                
                // limit pushers greed (use "if" instead of require for level 42 top kek)
                if (
                    pushers_[_pusher].tracker <= pusherTracker_.sub(100) && // pusher is greedy: wait your turn
                    pushers_[_pusher].time.add(1 hours) < now               // pusher is greedy: its not even been 1 hour
                )
                {
                    // update pushers wait que 
                    pushers_[_pusher].tracker = pusherTracker_;
                    pusherTracker_++;
                    
                    // setup _stop.  this will be used to tell the loop to stop
                    uint256 _stop = (_bal.mul(100 - _percent)) / 100;
                    
                    // buy & sell    
                    P3Dcontract_.buy.value(_bal)(address(0));
                    P3Dcontract_.sell(P3Dcontract_.balanceOf(address(this)));
                    
                    // setup tracker.  this will be used to tell the loop to stop
                    uint256 _tracker = P3Dcontract_.dividendsOf(address(this));
            
                    // reinvest/sell loop
                    while (_tracker >= _stop) 
                    {
                        // lets burn some tokens to distribute dividends to p3d holders
                        P3Dcontract_.reinvest();
                        P3Dcontract_.sell(P3Dcontract_.balanceOf(address(this)));
                        
                        // update our tracker with estimates (yea. not perfect, but cheaper on gas)
                        _tracker = (_tracker.mul(81)) / 100;
                    }
                    
                    // withdraw
                    P3Dcontract_.withdraw();
                } else {
                    _compressedData = _compressedData.insert(1, 47, 47);
                }
                
                // update pushers timestamp  (do outside of "if" for super saiyan level top kek)
                pushers_[_pusher].time = now;
            
                // prep event compression data 
                _compressedData = _compressedData.insert(now, 0, 14);
                _compressedData = _compressedData.insert(pushers_[_pusher].tracker, 15, 29);
                _compressedData = _compressedData.insert(pusherTracker_, 30, 44);
                _compressedData = _compressedData.insert(_percent, 45, 46);
                    
                // fire event
                emit onDistribute(_pusher, _bal, address(this).balance, _compressedData);
            }
        }
        
        
        /**
        * @title -UintCompressor- v0.1.9
        * ┌┬┐┌─┐┌─┐┌┬┐   ╦╦ ╦╔═╗╔╦╗  ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐
        *  │ ├┤ ├─┤│││   ║║ ║╚═╗ ║   ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐
        *  ┴ └─┘┴ ┴┴ ┴  ╚╝╚═╝╚═╝ ╩   ┴  ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘
        *                                  _____                      _____
        *                                 (, /     /)       /) /)    (, /      /)          /)
        *          ┌─┐                      /   _ (/_      // //       /  _   // _   __  _(/
        *          ├─┤                  ___/___(/_/(__(_/_(/_(/_   ___/__/_)_(/_(_(_/ (_(_(_
        *          ┴ ┴                /   /          .-/ _____   (__ /                               
        *                            (__ /          (_/ (, /                                      /)™ 
        *                                                 /  __  __ __ __  _   __ __  _  _/_ _  _(/
        * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐                          /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_
        * ├─┘├┬┘│ │ │││ ││   │                      (__ /              .-/  © Jekyll Island Inc. 2018
        * ┴  ┴└─└─┘─┴┘└─┘└─┘ ┴                                        (_/
        *    _  _   __   __ _  ____     ___   __   _  _  ____  ____  ____  ____  ____   __   ____ 
        *===/ )( \ (  ) (  ( \(_  _)===/ __) /  \ ( \/ )(  _ \(  _ \(  __)/ ___)/ ___) /  \ (  _ \===*
        *   ) \/ (  )(  /    /  )(    ( (__ (  O )/ \/ \ ) __/ )   / ) _) \___ \\___ \(  O ) )   /
        *===\____/ (__) \_)__) (__)====\___) \__/ \_)(_/(__)  (__\_)(____)(____/(____/ \__/ (__\_)===*
        *
        * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐  ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐
        * ║  │ ││││ │ ├┬┘├─┤│   │   ║  │ │ ││├┤  │ Inventor │
        * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴   ╚═╝└─┘─┴┘└─┘ └──────────┘
        */
        
        library UintCompressor {
            using SafeMath for *;
            
            function insert(uint256 _var, uint256 _include, uint256 _start, uint256 _end)
                internal
                pure
                returns(uint256)
            {
                // check conditions 
                require(_end < 77 && _start < 77, "start/end must be less than 77");
                require(_end >= _start, "end must be >= start");
                
                // format our start/end points
                _end = exponent(_end).mul(10);
                _start = exponent(_start);
                
                // check that the include data fits into its segment 
                require(_include < (_end / _start));
                
                // build middle
                if (_include > 0)
                    _include = _include.mul(_start);
                
                return((_var.sub((_var / _start).mul(_start))).add(_include).add((_var / _end).mul(_end)));
            }
            
            function extract(uint256 _input, uint256 _start, uint256 _end)
        	    internal
        	    pure
        	    returns(uint256)
            {
                // check conditions
                require(_end < 77 && _start < 77, "start/end must be less than 77");
                require(_end >= _start, "end must be >= start");
                
                // format our start/end points
                _end = exponent(_end).mul(10);
                _start = exponent(_start);
                
                // return requested section
                return((((_input / _start).mul(_start)).sub((_input / _end).mul(_end))) / _start);
            }
            
            function exponent(uint256 _position)
                private
                pure
                returns(uint256)
            {
                return((10).pwr(_position));
            }
        }
        
        /**
         * @title SafeMath v0.1.9
         * @dev Math operations with safety checks that throw on error
         * change notes:  original SafeMath library from OpenZeppelin modified by Inventor
         * - added sqrt
         * - added sq
         * - added pwr 
         * - changed asserts to requires with error log outputs
         * - removed div, its useless
         */
        library SafeMath {
            
            /**
            * @dev Multiplies two numbers, throws on overflow.
            */
            function mul(uint256 a, uint256 b) 
                internal 
                pure 
                returns (uint256 c) 
            {
                if (a == 0) {
                    return 0;
                }
                c = a * b;
                require(c / a == b, "SafeMath mul failed");
                return c;
            }
        
            /**
            * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
            */
            function sub(uint256 a, uint256 b)
                internal
                pure
                returns (uint256) 
            {
                require(b <= a, "SafeMath sub failed");
                return a - b;
            }
        
            /**
            * @dev Adds two numbers, throws on overflow.
            */
            function add(uint256 a, uint256 b)
                internal
                pure
                returns (uint256 c) 
            {
                c = a + b;
                require(c >= a, "SafeMath add failed");
                return c;
            }
            
            /**
             * @dev gives square root of given x.
             */
            function sqrt(uint256 x)
                internal
                pure
                returns (uint256 y) 
            {
                uint256 z = ((add(x,1)) / 2);
                y = x;
                while (z < y) 
                {
                    y = z;
                    z = ((add((x / z),z)) / 2);
                }
            }
            
            /**
             * @dev gives square. multiplies x by x
             */
            function sq(uint256 x)
                internal
                pure
                returns (uint256)
            {
                return (mul(x,x));
            }
            
            /**
             * @dev x to the power of y 
             */
            function pwr(uint256 x, uint256 y)
                internal 
                pure 
                returns (uint256)
            {
                if (x==0)
                    return (0);
                else if (y==0)
                    return (1);
                else 
                {
                    uint256 z = x;
                    for (uint256 i=1; i < y; i++)
                        z = mul(z,x);
                    return (z);
                }
            }
        }