// Contract: OnChainBots
// Target function: function getTraits(Bot memory bot) internal view returns (string memory)
256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

// Bring on the OnChain Bots!
contract OnChainBots is ERC721Enumerable, ReentrancyGuard, Ownable {
  using Strings for uint256;

  uint256 public constant maxSupply = 10000;
  uint256 public numClaimed = 0;
  string[] private background = ["FFF","dda","e92","3DF","FEF","9de","367","ccc"]; // only trait that is uniform, no need for rarity weights
  
  string[] private fur1 = ["fd1","28F","324","3D4","ffc","81F","f89","F6F","049","901","fc5","ffe","574","bcc","d04","AAA","AB3","ff0","fd1"];
  string[] private fur2 = ["259","000","000","000","000","000","000","000","000","000","060","000","96e","56e","799","801","310","d9f","000"];
  uint8[] private fur_w =[249, 246, 223, 141, 116, 114, 93, 90, 89, 86, 74, 72, 55, 48, 39, 32, 28, 14, 8];
  string[] private eyes = ["abe","080","653","000","be7","abe","080","653","000","be7","cef","abe","080","653","000","be7","cef","abe","080","653","000","be7","cef"];
  uint8[] private eyes_w = [245, 121, 107, 101, 79, 78, 70, 68, 62, 58, 56, 51, 50, 48, 44, 38, 35, 33, 31, 22, 15, 10, 7];
  string[] private earring = ["999","fe7","999","999","fe7","bdd"];
  uint8[] private earring_w = [251, 32, 29, 17, 16, 8, 5];
  string[] private buttons1 = ["f00","f00","222","f00","f00","f00","f00","f00","f00","00f","00f","00f","00f","00f","00f","00f","222","00f","f0f","222","f0f","f0f","f0f","f0f","f0f","f0f","f0f","f80","f80","f80","f80","f80","f00","f80","f80","f80","90f","90f","00f","90f","90f","90f","222"];
  string[] private buttons2 = ["d00","00f","f00","f0f","f80","90f","f48","0f0","ff0","f00","00d","f0f","f80","90f","f48","0f0","ddd","ff0","f00","653","00f","d0d","f80","90f","f48","0f0","ff0","f00","f0f","00f","d60","f48","ddd","90f","0f0","ff0","f00","00f","fd1","f0f","f80","70d","fd1"];
  uint8[] private buttons_w = [251, 55, 45, 43, 38, 37, 34, 33, 32, 31, 31, 31, 31, 31, 30, 30, 29, 29, 28, 27, 27, 27, 26, 25, 24, 22, 21, 20, 19, 19, 19, 19, 19, 19, 18, 17, 16, 15, 14, 13, 11, 9, 8, 6];
  string[] private scar1 = ["f00","f00","f00","f00","f00","f00","f00","000","000","000","000","000","000","000","f00","080","080","080","080","080","080","080","808","808","808","808","808","808","f00","808","90f","f48","22d","90f","90f","ff0",""];
  string[] private scar2 = ["0f0","000","080","ff0","90f","080","f48","f00","0f0","000","080","ff0","90f","080","000","f00","0f0","000","080","ff0","90f","080","f00","0f0","000","080","ff0","90f","f00","080","f00","000","000","0f0","000","f48",""];  
  uint8[] private scar_w = [251, 64, 47, 42, 39, 38, 36, 35, 34, 34, 33, 29, 28, 26, 26, 25, 25, 25, 22, 21, 20, 20, 18, 17, 17, 15, 14, 14, 13, 13, 12, 12, 12, 10, 9, 8, 7];
  string[] private z = ['<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 500 500"><rect x="0" y="0" width="500" height="500" style="fill:#',
    '"/><polygon points="93 214, 13 393, 87 413, 165 220, 145 213, 93 214" style="fill:#', '"/><polygon points = "268 416, 270 489, 333 489, 339 416, 268 416" style="fill:#', '"/><polygon points= "177 416, 178 488, 243 489, 243 416, 177 416" style="fill:#',
    '"/><polygon points="176 368, 178 415, 268 416, 339 416, 345 368, 176 368" style="fill:#', '"/><polygon points =" 350 209, 433 399, 489 384, 399 207" style="fill:#', '"/><polygon points ="160 213, 171 367, 348 367, 343 209, 160 213" style="fill:#',
    '"/><polygon points="40 22, 56 209, 455 201, 452 10, 40 22 " style="fill:#', '"/><polygon points="252 142,223 162,284 161,252 142" style="fill:#', '"/><circle cx="174" cy="93" r="15" style="fill:#',
    '"/><circle cx="325" cy="93" r="15" style="fill:#',
    '"/>',
    '</svg>'];
  string private cross='<rect x="95" y="275" width="10" height="40" style="fill:#872"/><rect x="85" y="285" width="30" height="10" style="fill:#872"/>';
  string private but1='<circle cx="257" cy="250" r="5" style="fill:#';
  string private but2='"/><circle cx="257" cy="300" r="5" style="fill:#';
  string private hh1='<polygon points="76 169, 110 170, 77 172, 110 173, 76 169" style="fill:#';
  string private hh2='"/><polygon points="76 174, 110 175, 77 177, 110 178, 76 174" style="fill:#';
  string private sl1='<rect x="152" y="85" width="290" height="50" style="fill:#';
  string private sl2='<rect x="140" y="50" width="280" height="50" style="fill:#';
  string private ey1='<rect x="325" y="90" width="20" height="5" style="fill:#';
  string private ey2='"/><rect x="154" y="90" width="20" height="5" style="fill:#';
  string private zz='"/>';
  string private ea1='<circle cx="100" cy="290" r="14" style="fill:#';
  string private ea2='fe7';
  string private ea3='999';
  string private ea4='"/><circle cx="100" cy="290" r="4" style="fill:#000"/>';
  string private ea5='<circle cx="100" cy="290" r="12" style="fill:#';
  string private ea6='bdd';
  string private tr1='", "attributes": [{"trait_type": "Background","value": "';
  string private tr2='"},{"trait_type": "Fur","value": "';
  string private tr3='"},{"trait_type": "Tattoo","value": "';
  string private tr4='"},{"trait_type": "Scar","value": "';
  string private tr5='"},{"trait_type": "Eyes","value": "';
  string private tr6='"},{"trait_type": "Buttons","value": "';
  string private tr8='"}],"image": "data:image/svg+xml;base64,';
  string private ra1='A';
  string private ra2='C';
  string private ra4='E';
  string private ra5='F';
  string private ra6='G';
  string private co1=', ';
  string private rl1='{"name": "OnChain Bots #';
  string private rl3='"}';
  string private rl4='data:application/json;base64,';

  address[2] private _shareholders;
  uint[2] private _shares;

  uint256 public mintPrice = 30000000 gwei; // 0.03 ETH
  bool public saleIsActive = false;

  event PaymentReleased(address to, uint256 amount);

  struct Bot { // structure
    uint8 bg;
    uint8 fur;
    uint8 eyes;
    uint8 earring;
    uint8 buttons;
    uint8 scare;
  }

  // this was used to create the distributon of 10,000 and tested for uniqueness for the given parameters of this collection
  function random(string memory input) internal pure returns (uint256) {
    return uint256(keccak256(abi.encodePacked(input)));
  }

  function usew(uint8[] memory w,uint256 i) internal pure returns (uint8) {
    uint8 ind=0;
    uint256 j=uint256(w[0]);
    while (j<=i) {
      ind++;
      j+=uint256(w[ind]);
    }
    return ind;
  }

  function randomOne(uint256 tokenId) internal view returns (Bot memory) {
    tokenId=12839-tokenId; // avoid dupes
    Bot memory bot;
    bot.bg = uint8(random(string(abi.encodePacked(ra1,tokenId.toString()))) % 8);
    bot.fur = usew(fur_w,random(string(abi.encodePacked(but1,tokenId.toString())))%1817);
    bot.eyes = usew(eyes_w,random(string(abi.encodePacked(ra2,tokenId.toString())))%1429);
    bot.earring = usew(earring_w,random(string(abi.encodePacked(ra4,tokenId.toString())))%358);
    bot.buttons = usew(buttons_w,random(string(abi.encodePacked(ra5,tokenId.toString())))%1329);
    bot.scare = usew(scar_w,random(string(abi.encodePacked(ra6,tokenId.toString())))%1111);
    if (tokenId==6291) {
      bot.scare++; // perturb dupe
    }
    return bot;
  }