contract Naturals is ERC721Enumerable, ReentrancyGuard, Ownable {

//
//
//███████╗██╗░░░░░░██████╗██╗███████╗  ░██████╗░█████╗░██╗░░░██╗░██████╗░░░░░░░░░
//██╔════╝██║░░░░░██╔════╝██║██╔════╝  ██╔════╝██╔══██╗╚██╗░██╔╝██╔════╝░░░░░░░░░
//█████╗░░██║░░░░░╚█████╗░██║█████╗░░  ╚█████╗░███████║░╚████╔╝░╚█████╗░░░░░░░░░░
//██╔══╝░░██║░░░░░░╚═══██╗██║██╔══╝░░  ░╚═══██╗██╔══██║░░╚██╔╝░░░╚═══██╗░░░░░░░░░
//███████╗███████╗██████╔╝██║███████╗  ██████╔╝██║░░██║░░░██║░░░██████╔╝██╗██╗██╗
//╚══════╝╚══════╝╚═════╝░╚═╝╚══════╝  ╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═════╝░╚═╝╚═╝╚═╝
//
// 
//██████╗░░█████╗░██╗░░░░░██╗░░░░░  ███████╗░█████╗░██████╗░
//██╔══██╗██╔══██╗██║░░░░░██║░░░░░  ██╔════╝██╔══██╗██╔══██╗
//██████╔╝██║░░██║██║░░░░░██║░░░░░  █████╗░░██║░░██║██████╔╝
//██╔══██╗██║░░██║██║░░░░░██║░░░░░  ██╔══╝░░██║░░██║██╔══██╗
//██║░░██║╚█████╔╝███████╗███████╗  ██║░░░░░╚█████╔╝██║░░██║
//╚═╝░░╚═╝░╚════╝░╚══════╝╚══════╝  ╚═╝░░░░░░╚════╝░╚═╝░░╚═╝

//██╗███╗░░██╗██╗████████╗██╗░█████╗░████████╗██╗██╗░░░██╗███████╗
//██║████╗░██║██║╚══██╔══╝██║██╔══██╗╚══██╔══╝██║██║░░░██║██╔════╝
//██║██╔██╗██║██║░░░██║░░░██║███████║░░░██║░░░██║╚██╗░██╔╝█████╗░░
//██║██║╚████║██║░░░██║░░░██║██╔══██║░░░██║░░░██║░╚████╔╝░██╔══╝░░
//██║██║░╚███║██║░░░██║░░░██║██║░░██║░░░██║░░░██║░░╚██╔╝░░███████╗
//╚═╝╚═╝░░╚══╝╚═╝░░░╚═╝░░░╚═╝╚═╝░░╚═╝░░░╚═╝░░░╚═╝░░░╚═╝░░░╚══════╝
//
// this is the 10d11 version. there is a 5d21 version that i'm sure you can find.
//
// find me here: twitter.com/0xelsiesays
//               0xelsiesays@gmail.com        
//               https://discord.gg/YBVvwQ5gf7
//
//


    uint256 public constant TOTAL_SUPPLY = 8192;
    uint256 public constant PUBLIC_SUPPLY = 7680;

    // more verisons are coming....
    uint256 public constant VERSION = 0;

    constructor() ERC721("Roll 10d11","10d11") {}

    function claim(uint256 tokenId) public nonReentrant {
        require(tokenId > 0 && tokenId <= PUBLIC_SUPPLY, "Token ID invalid");
        require(!_exists(tokenId), "Can't have that one!");
        _safeMint(_msgSender(), tokenId);
    }
        
    function ownerClaim(uint256 tokenId) public nonReentrant onlyOwner {
        require(tokenId > PUBLIC_SUPPLY && tokenId <= TOTAL_SUPPLY, "Token ID invalid");
        _safeMint(owner(), tokenId);
    }

    function withdraw() public onlyOwner {
        payable(msg.sender).transfer(address(this).balance);
    }

    function ten_d_eleven(string memory seed) public pure returns (uint8) {
        uint8 result = 0;
        for (uint8 i = 0; i < 10; i++) {
            uint8 part = uint8(uint256(keccak256(abi.encodePacked(seed,toString(i)))) % 11); // values 0-10
            result += part;
        }
        return result;
    }


    function tokenURI(uint256 tokenId) public view override returns (string memory) {

        require(_exists(tokenId), "token has not been claimed!");
        
        string[17] memory svg;
        svg[0] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: white; font-family: serif; font-size: 20px; }</style><rect width="100%" height="100%" fill="#606eb2" /><text x="40" y="25" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[1] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"first"))));
        svg[2] = '</text><text x="40" y="50" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[3] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"second"))));
        svg[4] = '</text><text x="40" y="75" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[5] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"third"))));
        svg[6] = '</text><text x="40" y="100" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[7] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"fourth"))));
        svg[8] = '</text><text x="40" y="125" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[9] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"fifth"))));
        svg[10] = '</text><text x="40" y="150" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[11] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"sixth"))));
        svg[12] = '</text><text x="40" y="175" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[13] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"seventh"))));
        svg[14] = '</text><text x="40" y="200" dominant-baseline="middle" text-anchor="middle" class="base">';
        svg[15] = toString(ten_d_eleven(string(abi.encodePacked(toString(tokenId),"eighth"))));
        svg[16] = '</text></svg>';
        
        string memory svg_part_1 = string(abi.encodePacked(svg[0],svg[1],svg[2],svg[3],svg[4],svg[5],svg[6],svg[7],svg[8]));
        string memory svg_part_2 = string(abi.encodePacked(svg[9],svg[10],svg[11],svg[12],svg[13],svg[14],svg[15],svg[16]));
        string memory full_svg = string(abi.encodePacked(svg_part_1,svg_part_2));
        string memory encoded_svg = Base64.encode(bytes(full_svg));
        
        string[5] memory json;
        json[0] = '{"name": "Roll 10d11';
        json[2] = '", "description": "8 numbers between 0 and 100, inclusive, generated by summing 10 randomly generated numbers between 0 and 10. Approximates a natural distribution with numbers in the middle much more likely than numbers on the edge. Do whatever you want with these.", "image": "data:image/svg+xml;base64,';
        json[3] = encoded_svg;
        json[4] = '"}';
        string memory full_json = string(abi.encodePacked(json[0],json[1],json[2],json[3],json[4]));
        string memory encoded_json = Base64.encode(bytes(full_json));

        return string(abi.encodePacked('data:application/json;base64,', encoded_json));

    }

    



    // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT license
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}
function toString(uint256 value) internal pure returns (string memory) {
    // Inspired by OraclizeAPI's implementation - MIT license
    // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

    if (value == 0) {
        return "0";
    }
    uint256 temp = value;
    uint256 digits;
    while (temp != 0) {
        digits++;
        temp /= 10;
    }
    bytes memory buffer = new bytes(digits);
    while (value != 0) {
        digits -= 1;
        buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
        value /= 10;
    }
    return string(buffer);
}

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////