// File: contracts/main.sol



// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./Base64.sol";
import "./PartCombis.sol";
import "./Attributes.sol";

contract GenerativePudding is ERC721, Ownable, PartCombis, Attributes {
    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdCounter;
    uint256 private constant CLEAR_FOR_PARTS =
        0x000000000000000000000000000000000000000000000000000000000000ffff;
    uint256 private constant CLEAR_FOR_A_PART = 0x000f;
    string private constant SVG_HEAD =
        "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjMyMCIgaGVpZ2h0PSIzMjAiIHZpZXdCb3g9IjAgMCAzMjAgMzIwIj4g";
    string private constant SVG_TAIL = "PC9zdmc+";
    string[] private BASE_COLORS = [
        "PHJlY3Qgd2lkdGg9IjMyMCIgaGVpZ2h0PSIzMjAiIHN0eWxlPSJmaWxsOiNlMWZmZmY7Ii8+",
        "PHJlY3Qgd2lkdGg9IjMyMCIgaGVpZ2h0PSIzMjAiIHN0eWxlPSJmaWxsOiNmZmUxZmY7Ii8+",
        "PHJlY3Qgd2lkdGg9IjMyMCIgaGVpZ2h0PSIzMjAiIHN0eWxlPSJmaWxsOiNmZmZmZTE7Ii8+"
    ];
    string[] private PARTS_BOTTOM;
    string[] private PARTS_FACE;
    string[] private PARTS_PUDDING;
    string[] private PARTS_TOP;
    mapping(uint256 => Pudding) private puddingsToTokenId;
    struct Pudding {
        uint256 baseColor;
        uint256 bottom;
        uint256 face;
        uint256 pudding;
        uint256 top;
    }

    constructor() ERC721("Generative Pudding", "GSP") {}

    function safeMint(address to) public onlyOwner {
        _tokenIdCounter.increment();
        uint256 tokenId = _tokenIdCounter.current();
        Pudding memory pudding = cookPudding();
        puddingsToTokenId[tokenId] = pudding;
        _safeMint(to, tokenId);
    }

    function safeBatchMint(address to, uint8 num) public onlyOwner {
        for (uint8 i = 0; i < num; i++) {
            _tokenIdCounter.increment();
            uint256 tokenId = _tokenIdCounter.current();
            Pudding memory pudding = cookPudding();
            puddingsToTokenId[tokenId] = pudding;
            _safeMint(to, tokenId);
        }
    }

    function tokenURI(uint256 _tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        return buildMetadata(_tokenId);
    }

    function setBottom(string memory bottom) public onlyOwner {
        PARTS_BOTTOM.push(bottom);
    }

    function setFace(string memory bottom) public onlyOwner {
        PARTS_FACE.push(bottom);
    }

    function setPudding(string memory bottom) public onlyOwner {
        PARTS_PUDDING.push(bottom);
    }

    function setTop(string memory bottom) public onlyOwner {
        PARTS_TOP.push(bottom);
    }

    function getLength() public view onlyOwner returns (uint256[4] memory) {
        return [
            PARTS_BOTTOM.length,
            PARTS_FACE.length,
            PARTS_PUDDING.length,
            PARTS_TOP.length
        ];
    }

    // private
    function cookPudding() private returns (Pudding memory) {
        uint256 index = randomNum(PART_COMBIS.length);
        uint256 partCombis = PART_COMBIS[index];
        uint256 parts = partCombis & CLEAR_FOR_PARTS;
        (
            uint256 bottom,
            uint256 face,
            uint256 pudding,
            uint256 top
        ) = getPartsIndexes(parts);
        uint256 baseColor = randomNum(BASE_COLORS.length);
        partCombis >>= 16;
        PART_COMBIS[index] = partCombis;
        if (partCombis == 0) {
            deleteCombiArray(index);
        }
        return Pudding(baseColor, bottom, face, pudding, top);
    }

    function getPartsIndexes(uint256 parts)
        private
        pure
        returns (
            uint256 bottom,
            uint256 face,
            uint256 pudding,
            uint256 top
        )
    {
        top = parts & CLEAR_FOR_A_PART;
        parts >>= 4;
        pudding = parts & CLEAR_FOR_A_PART;
        parts >>= 4;
        face = parts & CLEAR_FOR_A_PART;
        parts >>= 4;
        bottom = parts & CLEAR_FOR_A_PART;
    }

    function randomNum(uint256 _mod) private view returns (uint256) {
        return
            uint256(
                keccak256(
                    abi.encodePacked(
                        block.timestamp,
                        msg.sender,
                        _tokenIdCounter.current()
                    )
                )
            ) % _mod;
    }

    function deleteCombiArray(uint256 index) private {
        uint256 last = PART_COMBIS[PART_COMBIS.length - 1];
        PART_COMBIS[index] = last;
        PART_COMBIS.pop();
    }

    function buildMetadata(uint256 _tokenId)
        private
        view
        returns (string memory)
    {
        Pudding memory pudding = puddingsToTokenId[_tokenId];
        return
            string(
                abi.encodePacked(
                    "data:application/json;base64,",
                    Base64.encode(
                        bytes(
                            abi.encodePacked(
                                '{"name":"Generative Pudding #',
                                Strings.toString(_tokenId),
                                '", "description":"NFT collection of puddings made by an engineer who used to be a pastry chef. It is a full on chain NFT. There are various combinations of parts and the number of the collection is 11760.',
                                '", "image": "',
                                "data:image/svg+xml;base64,",
                                buildImage(_tokenId),
                                '", "attributes": ',
                                "[",
                                '{"trait_type": "Back Ground",',
                                '"value":"',
                                metadataBackground(pudding.baseColor),
                                '"},',
                                '{"trait_type": "Bottom",',
                                '"value":"',
                                metadataBottom(pudding.bottom),
                                '"},',
                                '{"trait_type": "Face",',
                                '"value":"',
                                metadataFace(pudding.face),
                                '"},',
                                '{"trait_type": "Pudding",',
                                '"value":"',
                                metadataPudding(pudding.pudding),
                                '"},',
                                '{"trait_type": "Top",',
                                '"value":"',
                                metadataTop(pudding.top),
                                '"}',
                                "]",
                                "}"
                            )
                        )
                    )
                )
            );
    }

    function buildImage(uint256 _tokenId) private view returns (string memory) {
        Pudding memory pudding = puddingsToTokenId[_tokenId];
        return
            string(
                abi.encodePacked(
                    SVG_HEAD,
                    BASE_COLORS[pudding.baseColor],
                    PARTS_BOTTOM[pudding.bottom],
                    PARTS_PUDDING[pudding.pudding],
                    PARTS_FACE[pudding.face],
                    PARTS_TOP[pudding.top],
                    SVG_TAIL
                )
            );
    }
}

// File: contracts/Base64.sol



// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0;

/// @title Base64
/// @author Brecht Devos - <brecht@loopring.org>
/// @notice Provides functions for encoding/decoding base64
library Base64 {
    string internal constant TABLE_ENCODE =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    bytes internal constant TABLE_DECODE =
        hex"0000000000000000000000000000000000000000000000000000000000000000"
        hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"
        hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"
        hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return "";

        // load the table into memory
        string memory table = TABLE_ENCODE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {

            } lt(dataPtr, endPtr) {

            } {
                // read 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // write 4 characters
                mstore8(
                    resultPtr,
                    mload(add(tablePtr, and(shr(18, input), 0x3F)))
                )
                resultPtr := add(resultPtr, 1)
                mstore8(
                    resultPtr,
                    mload(add(tablePtr, and(shr(12, input), 0x3F)))
                )
                resultPtr := add(resultPtr, 1)
                mstore8(
                    resultPtr,
                    mload(add(tablePtr, and(shr(6, input), 0x3F)))
                )
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 {
                mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
            }
            case 2 {
                mstore(sub(resultPtr, 1), shl(248, 0x3d))
            }
        }

        return result;
    }

    function decode(string memory _data) internal pure returns (bytes memory) {
        bytes memory data = bytes(_data);

        if (data.length == 0) return new bytes(0);
        require(data.length % 4 == 0, "invalid base64 decoder input");

        // load the table into memory
        bytes memory table = TABLE_DECODE;

        // every 4 characters represent 3 bytes
        uint256 decodedLen = (data.length / 4) * 3;

        // add some extra buffer at the end required for the writing
        bytes memory result = new bytes(decodedLen + 32);

        assembly {
            // padding with '='
            let lastBytes := mload(add(data, mload(data)))
            if eq(and(lastBytes, 0xFF), 0x3d) {
                decodedLen := sub(decodedLen, 1)
                if eq(and(lastBytes, 0xFFFF), 0x3d3d) {
                    decodedLen := sub(decodedLen, 1)
                }
            }

            // set the actual output length
            mstore(result, decodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 4 characters at a time
            for {

            } lt(dataPtr, endPtr) {

            } {
                // read 4 characters
                dataPtr := add(dataPtr, 4)
                let input := mload(dataPtr)

                // write 3 bytes
                let output := add(
                    add(
                        shl(
                            18,
                            and(
                                mload(add(tablePtr, and(shr(24, input), 0xFF))),
                                0xFF
                            )
                        ),
                        shl(
                            12,
                            and(
                                mload(add(tablePtr, and(shr(16, input), 0xFF))),
                                0xFF
                            )
                        )
                    ),
                    add(
                        shl(
                            6,
                            and(
                                mload(add(tablePtr, and(shr(8, input), 0xFF))),
                                0xFF
                            )
                        ),
                        and(mload(add(tablePtr, and(input, 0xFF))), 0xFF)
                    )
                )
                mstore(resultPtr, shl(232, output))
                resultPtr := add(resultPtr, 3)
            }
        }

        return result;
    }
}

// File: contracts/PartCombis.sol



// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

abstract contract PartCombis {
    uint256[] PART_COMBIS = [
        0x03181825136c551a291e7d63445b4b3e65512b0a6c5c463e0962486a17456c14,
        0x674a7a500a243b670d450740040b3d1c613b01125138751d7257063d03000b1a,
        0x421b0906162e4410486c13636c0c0a3c70372917523b5b0b1a433304070c5963,
        0x511b30412c35002d324e635c6158611369382a42494746332c474c663a543636,
        0x5230093d30010c161a6c0b592165494a67475c6d355d68083c395c6848213361,
        0x33085a6709410045252e134b69416344316e11532a19763c6431604b44552268,
        0x5362092c3c652c27710b1c030c54676974282d55640a471d3d5e775c231a1d50,
        0x772b1d2d711b656134670764354d30383b1b4253072901551d16725d05314151,
        0x573c386805697040034d065531546309680b1608155d360326696d32656d7155,
        0x4125553b794153583b1806615a517a232532236c125c153b65103a48421c6c31,
        0x790d47124d0930066c1e0a23205056412d6b2943361e28224b4812042b17226c,
        0x4703672246242439042e0a54440c2057700b0b570711470d0d290b5b6358700e,
        0x5739194b3563514e2b3a4d1b682a540d770b321e40665809432e263207540967,
        0x166874263405160347447a296531181618532c534b3124206869212632123c69,
        0x7d5d5b0c7a38236a14602d5d0a1a502e23194b14742259641322656e37693630,
        0x21304b6d083409074652492043014d27780c27417853592e0c347d4479096434,
        0x7223500e223b264b52012d1071320c496b0172616d3672313c6058064a634a44,
        0x700254025a4e65227d623452445c4c2e27326041360e7c67712a75607907201a,
        0x783140293746273e004a2401234b4a335910552d6c5e07375906734a33583a31,
        0x62656d12390d0804575c1652066a273474547959445d4167156b4319605b714a,
        0x0a126d615b6810325558795549045d38296559502a63376a54152a154b2c6234,
        0x024c3d3a52171d2a2068230704122b535c620663195002172a5c100d1c311502,
        0x4d110c0d4d587b0c3b4500686850066250591a11070d2b01405b3b46011a5260,
        0x51255850591a540006265c17624472307c130463194825430c22024161371442,
        0x762974451a4201191447234c2d4a32095704375c7c5d1d1143177742446a0250,
        0x062c731873092a55736857663b0d0d307a523c6345352b2229060a630b033241,
        0x54121d6c193b792358612d41663e03233a221a011c524b2a016649267d542628,
        0x372a66672759705b200c034a2d19753d394c130770086432531e140827295539,
        0x464204590a6a0321791c704c20520c113b5b2b023c13406200120c0c4544763a,
        0x2749364037554334164877343623744a51610306660779394b3d6c4a24261903,
        0x2d2334252d2d682715171857494c0862044400484d546c5246271c0221044c48,
        0x0b0b5a1c326d604d1846445e2342464d103d4c54320a35040822084c7b0a2829,
        0x7d3c556b251c440761471962070a526a1c553d54103a315e161234344c421c33,
        0x5c532218736331057d3e6b647a13555774533c107944753739355437331c1b23,
        0x52152c1c10696c29252d00663311142545382501443c334d443d4720534e174d,
        0x2a250402492c260241547b487641290d5c46735c1b4a5a2655293b6461181229,
        0x324c6d2c5d541b5d59343407102c3837443b7b275b423521510224256b03621b,
        0x425b40276168605a0a65214b290a62617966151d06124a5839056d51140a1d09,
        0x6928246e6542393a736d083a1a056351484e7919143c08115d44673c57476828,
        0x732652140748774e7c0d5a6d550441493416766050392422080a710a60603a2e,
        0x6b0c13604a1e4d214558172e7a671c4b6a51074a09564c6047055c69171e4967,
        0x394e462b0d0d5a5a3d2104627d5a5d594d631814163d0b6c041465383d40075a,
        0x513b6a6d590e323d7d064035070e26643927480a0603384004492c2510627a4e,
        0x561e740b1256126a493d443103071d33724b1564334a253512364956260e0b64,
        0x390c205d79540a4d4c5c7241433b7a545c303b4b3726175e3448686026433605,
        0x56611a3b3b49695461603a652c095a5e36372d3e0d5462517d584b0e53634d1e,
        0x6b484345616e0016480b475e5044273009271d0e1163316111583d1676042b36,
        0x57382b4838655930275d314e513a110b7d3631093501480657675c3b4339353c,
        0x323466173c64575378510b362542550e72032d63192917331d3755252a483433,
        0x4b3651494a4b47091b452a51460e092e453d042960207c447108565224294719,
        0x5361256e0659735054665903204e270e493e5d6d345432207605496a35170365,
        0x4157334c46621c682b2a113402374404731d09646b385368376d564a70206c6c,
        0x55367d39273d7a1e6a3b4759716c1953054c553d6b286c370c3d050b5855064b,
        0x0965172612172521604a64524269530b76163b326843586d685d6d4e04286140,
        0x1044055d392c78542046170b561545431540744130353562705a5049050a1b04,
        0x245a241148261c1b4c043850125a646954486c19355409306039353e7b1d3b2d,
        0x386e474d296e0a6675651a6e4511484677253d3b6037494338694733424c7d20,
        0x6d3c1124341c151b284e14266c2d5d474d4912550665520e7b2a6c36752d4602,
        0x023d1829472b22200664245512517866414e2427245146397124683a2711171c,
        0x62045225113166604d48542a1c3825645c0e560e6b5d4c27624c61260314375e,
        0x4b554840725c6d3d301367546a310745132631484a1378344b68062e531d3233,
        0x26663c1259665d36065256001709410b2a1e6a5b03572a17244c482d272b510a,
        0x6b427b38703879217c3326680c4d591b473a0c586430406e1d300854130a181c,
        0x515e090d6c1d2d3c71413459360c755914030620006708121b6e526530311855,
        0x054d7d0d20380d2c2b6c334119597c1c01271a187726702e1c6d5c1651690b54,
        0x28457360171772022c593251354a5b63165c76336b6949131b5a5b12626c0843,
        0x65252227070901492562343639392c5c4d37632a616163212c2921326c441305,
        0x3c414963024e094a630503436231076844197a2c2b076b5a61572a2a19631008,
        0x082d506e2a695d5c1c1a230d0b3c065324076d5d446519310746160c16182152,
        0x23611361096c642359247d14342a740a206d14685200265c4701614c1327613a,
        0x7c52536e452b6109222a4045114951653922230b5423345308485d6901357c55,
        0x4059353b7323401a7d2b35091a4e521c24474a2a5b0e78205d5224520a0c254b,
        0x64432212701e694a6a3c6a54542e124255357a4d222b58440231022830256d4c,
        0x4a2c3527193751375c5e76246d486817425635575c40356848453335515d3826,
        0x7d08212c0b5276154b4d3c093d5246685947250903200a3228067b3e55532d48,
        0x15197310750c18216d2a6a5a546925373a690824710d40424d2205662c34763d,
        0x55490d1726337c5175385d33584a116661297a6e3d62510c4b650b660504593c,
        0x13364d15675b5b4d73447406462907574c2833327750656c666c3b6d1d6a630b,
        0x5d10360b552a0c535367521d232d313767610d1a59127131765878503b3a7666,
        0x2d5a3036614d2b197a1c1c5c3a202816176e066953434a0850645b444434380b,
        0x724e2603325959195932012d7c636645314d1b03096b5d253462214611020537,
        0x2a4e664d221342615b5d461d68480c00193a796d58333830643b19574b3b3a0e,
        0x645c11595851032b3368150433376c6e42157b046b440a50002210501810093e,
        0x701a3b5c085b31065c5150201c6671100827475075124b1540601c516d6c072b,
        0x3564754c4048011d301221605b35282b5823663105090461611e57212d07346b,
        0x45087d65741a05337c473b294b6b79115d6702094d42126573206148764a4708,
        0x646577363845762751590c0e1944505e482a00500235724322070931205b331a,
        0x7a51612c0337646701443c477a41314b365755206949385a0d597d675028466c,
        0x58634a11530e035843052469012a3d332b0613692b6e54551115496d7d2a6333,
        0x50460118703b4c2d7343645e0a68525500250037395e711942590056705c5d3b,
        0x3037103610491c4e1a6d2534671742127828062b520a1830092a5b08613d6b1d,
        0x320808396001333c14285962514d37131d182864121e6b091958756b46285868,
        0x660350633a64463025631b6c2d1264577d4a576a403c77577442321c5d4c4039,
        0x023905143618392d61417025051a5a367a30612a0a2757451b342b262b670929,
        0x694c50052a2705437116152620496b2738516905312d595d432a0d4a4a665730,
        0x3a52770a0331145179046608180902040305080d51544038255d043430672033,
        0x45335a2b7d68612e783b741849392605241331037c35475d4d19445953427044,
        0x061d4a223c45604e27646227585b71571522781a653d361c66441104521a3b69,
        0x7532426d66523342353833003d11342d140d02242b4b0c57293445196d2e5004,
        0x0060455d7c145b2a085e4b031b1837650b277a60376740133216693603693c33,
        0x673d062411132329116b236238550c677b4d560c37304743256a58402639424d,
        0x67436a5d4b1b003152226868705e28192067781d102d7769070304694d4d6950,
        0x5409484704161420682e6d131a076d063138721e1b6847400c1733204c584860,
        0x725225394935615c02467012026b7a436011170054612432373b2b4115282966,
        0x35141c420a591663453a0d053a603d0a144c43542c1b7905120c073945457d1c,
        0x222c0515623b185a081b07425b0d480239454722261a3c28185202141464775d,
        0x6d10065d5c6c2008695d1d58105173491151201b7c642368172402472923616b,
        0x410a6a1a0b150563533b14186c254307180544204d5d5b38403b066618046665,
        0x4b4e3c5338626055794842442a0c33547505612d592853301001094b75612235,
        0x23672444433d0938674b59565c5d7b211b19445872103456343a282e4b504312,
        0x08553957163317414b542c3e7b3423265c1d16671842561b3052704d0c5b442b,
        0x4207512c711a03506d6a0a115360192b793b4b3027472c673366671b206c1a15,
        0x3954544915664c0c0814050c43497b09300e7469580517205114172266617a55,
        0x294a0802643a3121172300021503715c00031644301c716a7525293334697b69,
        0x6b19311629256a322d054b646025422c511725363d0d3b285a5215204b25144e,
        0x5d4b37026c0748513534724434292a6c095b622b3066582d3622164d694b4203,
        0x68636a0a5b60006332632031096a3540070723510a473d0067080a51555d6a28,
        0x631c203a6b204c57252c373624064d3146553809564458350311253d042d5b53,
        0x620b1650002e042b7a66222972553b545a1a79341a384c103d04031c090e0c06,
        0x7c0965664221136544307a2d0b695d2a571218352968640225456b66645a6620,
        0x1c1919672d56544e651a00112c52555a392422514714326c622c74593b606669,
        0x6a6023443b3b6705475846234213142d4813061b2a305d344a04393d0a191936,
        0x735e3c242d0e24084c3465067547571858133b0a69436c0674486d600d234202,
        0x55626b680846325b1d042421414a576e6c2c366e3b563968224d1d56533e2a13,
        0x666823252244260c2d1c796e2a673a184b345d2648376738786c0b1918315508,
        0x55446d3054333607514860092064023e211542432b09536b745227253c542b66,
        0x223d0b4311212b4a7a24651b645348613c2b334349447c0832654348145e0a15,
        0x3c02155c052a600e4313234012570240356c3804421a33242b14511e2847792e,
        0x03475756556d5c1252380d082d5b026c306d13096146746c20276a2a353d5108,
        0x1524220b355a1d10633747360c27072e01097d377c3e5a3d21091d0055300567,
        0x2c62352e6d02454b052667060937754a565b2b1a3832522d372e364e4c590b55,
        0x23434c205c4a6d17451250086b0e4a0301547a404528120874445d133c561b51,
        0x44257010505a4919624545045a287729652645315a662419570c184004503418,
        0x224b7a450d64014d2830201c706037646317426c3d4c14353b11345a431d385e,
        0x785d6435091b661d483b501130462b006b524a286150322c7a141844746a692a,
        0x5d58750a192136311119582a02524829423078166d20175d104d534c166e1313,
        0x111b5c577a28752a3c263b5d74603140723955166a575a003d63215722034a06,
        0x484c5713062817645b5e211652207c393d361a486d3554444107356745685c3c,
        0x560779464726315c262121633a094a3a47322c43112c563b665b21671b00231e,
        0x0759386a212908256537580e173c5867333d2264355044471605473b596c1763,
        0x5434575b0c480c44295b2b317018263b23140519311e1c18762a602d50382959,
        0x0c420b685043795310531a3214136a501b2254187714751e1c1038391034034b,
        0x461403660629556e6128222e57406946252b420e43512504765a5c6109133414,
        0x170a35287842673105181b5b024350343663782b7214626d7d66743024600928,
        0x74562b3c76565a3e434429213634033361446920466a6501494e111e3b1a0c28,
        0x451e31591461573d501e57465b267535681d671538195c31215149230b121551,
        0x036340151c3a1218663d073d63252111265b4d1a392e584171011a413c35515b,
        0x1d596a12071a794e285554325c377a156a530259641c17191d06554e4446652a,
        0x370a581b5d634c620c2b715204370123002c752268121507693e686a375b0004,
        0x56293c5d7504632e600b0721012e31571207210a7644503c35006061543a7534,
        0x16590326695c342b1c582138286e6a4b150e3321564e5d11686e294c412d3543,
        0x13305a4c5357114d53644d4122602b396a4d2c3b5042565c5943301408403152,
        0x4a5244363532305a1c17721365054c074c2b116049212a35262d146916653921,
        0x6838220a1a5c10681769254812373a6e35021947400048686557014018127226,
        0x145352355b3b49163a21436534302c2d4908623819662a6b23551b321a5b2150,
        0x592d2861680e2136785e562c5c607a581b47146d6b13171a1354372b4a313b58,
        0x7d2e7a5e3b234b4623131c502037364b373e1d1b526b02135468601967635666,
        0x163427390c09184a1268586e28331c39571a38277d172d312549630752133738,
        0x20634021495c442849617b377420442422614d017b1a052c5d232b52381b7a59,
        0x594264244b0b093a38004801101046433b1464007a16600d580806003230365e,
        0x48393d42720916103d656906076a28565732072c6000206e0d475b3978182a1b,
        0x7306221e030b706173533367465c613e624a561965695053481413120b614006,
        0x30304a4940674550054e3d6a16302c493118643e745e720719496a2045661d14,
        0x446d1d5e115c765b3b6e03406d5b55057539315346360d3a5c3831600d1e6b29,
        0x1d6e145b046679641c5429385635265e23327c117567670d5760475a684c3027,
        0x474b3b0557237204155b09511c445b3d1c2772561002606b6042606c082b4448,
        0x3b55132d71382c147d3d7a0c6b31705617356554530469240916570d5a0b2017,
        0x2848306a4257652312525a58516b3329651e2a57393b52197720045e45247438,
        0x154c2243326b7552766a35565c26374b37586a3640197500035d716048530d68,
        0x330115295937260d136675093b3c613c0d18596e442d2b3b32312b4d284d4748,
        0x172b1a1c112d385316093b571c5d1602071b1a65445374345a20032566666102,
        0x29085b033a323b5e341b64371d4b693d5323705573051023711c1d3d0332614b,
        0x0946444407445c3a106b19406130043c5127616a7b2b380a29360a1676111043,
        0x3055384962685146283e0d6a5417116d702a186541127d23764d3b401c055359,
        0x040e423e74643b342b232d090647512609687134030c451c52322d3b46573360,
        0x26370c41774c2b62183c17667c5847555c4d404c00082b2c7d6d543862172568,
        0x611b041d763133133542752c6d3a6013756d74037c2a176a716e333a2b461107,
        0x714e212e7865380830171925044e166a544d3d242a0d07673d1560456355692e,
        0x1d6d322b4c0d026a090463424231210e0c6868476b60633c7c325003660c571c,
        0x1311713c5c6a020c6d39131c060e2a0028256445126b5216696a6d2b0a3b6254,
        0x4306494652431a3016271b62210053404a39226760087b0b170145361b1b632b,
        0x3b6c014e7d4974022655603d0d497d0b7107002962074650766b40684751082a,
        0x62124b6c2c644a0a06467d28666b786e556322524626165d3b274d692808302a,
        0x632c7507065e726e605122015422056b2445362d6962166c615d7b563d56684a,
        0x746e400b5b246c107d0345635b01076e0a42001d2c4b5a0a3d08490e7d123d43,
        0x5d03143d755e061a11271457292263304a644238091764423131400e6c1b5a22,
        0x4d1332490546526e6c4c175102662c070b39380c302d5d455a551c34184c0355,
        0x26403d076a6e1a69643d232126595518272a67496c401b01471071514843603b,
        0x583036464c454648780e2c6c74332b10112850543045754e1c6546416221652d,
        0x7130410409527b2e32262607523648277c2466466d31570a006e3621312c196b,
        0x642674513b501323306b045d5d3a5837450d3811071e186a2d0c6451774d5d5e,
        0x513c1747213771174254561822091a3c3727523c2743766d2c42554a41015b3e,
        0x044c133a2d5e4c532b6301245621772210460d3e652b0621541d1d4d31296252,
        0x402a5a6406444a430c633b524a2759162262113d5657620357633844294e554b,
        0x27173d3c3a6d1a0019306a4c62116d587837285a5c427338025c56232a2d255c,
        0x516d045a673339636837326070167c2d30331262331b680a12312d523135772d,
        0x3d6d264e0a2113565a16753647491b3c1325731a792b125b235e420b500a2a23,
        0x3c583d32614a465e4415191a7a181b6b070255123a57535240243a3e195c683b,
        0x4605792c6c34132002603a2545606012271a592979224b373d4d340465344c03,
        0x7d593d015a42372927050a4648112c3a336a03293d5d7d09660e4b5a77674a47,
        0x1333006d7b656902300d5b13564c0439473d3a2d0a200a2c1367685726180b16,
        0x5a5d7a4a6d1b6859300a661c6106226609196411164676123b2a6b511328316a,
        0x130416316d373b6b583d321d3a073b0c47460608146a2a5448042b436c2e0828,
        0x5103091e75243706140142497c2042183752133e233a2059351372625b477251,
        0x1d61470e4c635509436a323b725331224553145c113e553a21355954453b0126,
        0x7342545b20037c3175290c3c2c3931454b5c57102c221c35110d2912630e2551,
        0x7667142267114b433a40461c7523355e7c6a3d1055457c1d2147432d610d1359,
        0x35052b40385860654a48130103672b5b08372d580609032d2531174641102b0b,
        0x2a3b3164470641220147363c590941373d257c59086c0b32624e6a42543b6741,
        0x152705350d6c4c06426a032c41616925730b66115936485248050d0a593e5b1a,
        0x043a2a596865345c33172756443244404d337840174b023b6728165b6208771e,
        0x7a11606652053c2c671c756660103069402c3c0b2d3428107427471519546d44,
        0x1c6a33334a4053176a684b382b4e4d085331760776352d67325430537c3d2820,
        0x1b644a1510146d2203306169645b7b33630c27575939762c4d0e3353285c0d66,
        0x7847465b4958730e2767491a33497b6a362c7819532e160d690c451a100c4217,
        0x11657b5b04032312401d1450180808614061445a1d45131b373d7c125023611a,
        0x36551a141a5541345946610556503721055b6b34101c7700193e7c5c21233110,
        0x23410244286628343042210724100b22456d7c56004e3d6c59684c6c7632023a,
        0x3328206b20414423322d74431b573445403e154a40363c16353136424031135e,
        0x1b3848100604703637015366794c456542426d6625501137183a03282c611b52,
        0x6a2d3c0d725e3057603e5d686814165e4817796068250120000e301641693c48,
        0x24420c432d6411541c1644122c323c22600261654c222c213757000507267501,
        0x6116464b3d1930597162142c4220705d16297b55365d5838581c5c0d21062021,
        0x46344c615021741b376e602442056c28743263202b47174073596a583253513d,
        0x66146104676008002d390d5c66056a65521b762532571767044a6b2366630c55,
        0x150c246c7000660d2c480616010d64590d517623235b444b405277464d6a286d,
        0x22197961471739194c0521275a0504075310434c4d67323a571d2654391d3d58,
        0x6a2767244b412525121c1340250039076d651d2b4255235879173c2a7c1e7653,
        0x495405303147700c7a5d36024d29686720610b0116397867173205230a6c5633,
        0x18606b103516271d2a4c033c036c063240170b1c58244a3c62393327181e2d38,
        0x25077463396b2347370c6756554d546a061323036d5c0b4b2256296d58125515,
        0x764b5026374d684e153c7b5d6641380d0a533c4e5c244d4c4d3b7b4c480d0b25,
        0x68091a5d2530040c5c282745455a550758623a08241615127218553e076c1142,
        0x1b071a541d4233482320045801346b6c7412276d5c0a1654031955646d467b24,
        0x30294c6a3d6e0842315b1d3e560a38381054142b095d352b4b094741723c593a,
        0x3a277843665a1132752e534171541861661b2456242b2a58495d640349603315,
        0x2b25301a5b04241d102009320d1b732a67012048630469274d5a574a5827106e,
        0x5513305b293b13482a24715e713a2b505c276858231c42110a6b274010306136,
        0x77160c3367585d373940641e1b09155a196d07133c066369124517577a20775e,
        0x161a0a403a26343869191d2e22314d1878387a474619220073277603790e0705,
        0x4d35174a2963670c57001933041a105a093c3958355b4c4d420c03537a21583e,
        0x2723122d654d354c69345338092d2d6c152d6550122468221711720d734e6803,
        0x1d1220366b26596b482e0d335b101c1d38436a302a5d3a59555b431649116a2e,
        0x02300c6e27083048320763576225035a53006151331e73641d43761a0649450e,
        0x2a1d6748024d3214632669370404223e1d5b3964444c625e54132714432c615e,
        0x11686650433738541d24606e244d59256815326e743a39156c1279632d024b13,
        0x2900061970216b061c26292034404c0e511c725847376b05124d7b392b64184e,
        0x440d4831425c134a066d056512636c357c5b72274a4664177c061169476d6912,
        0x4c1c0b0e7c233c1536394a1d0b0c674c66194c016c39185c7c49533761536d45,
        0x782d20281233495232406c2645405d3c6b5560641a3d6947563147565c322d36,
        0x0c453c52534b0b62495e582e102b043d0364770c754b29056d405935153a404b,
        0x093423546219212220135326143e103c68107137760b7a004b572b2e474e2c46,
        0x1c1c3338504a1d57352d306c69097a62051d7017760271237c68370d38053546,
        0x2a526d15532c2852726375441b1072127c69134c51430911406c2700430d2327,
        0x1437655c22155a5745022b334216341d5c154a55490d3507492a1201293e545c,
        0x301b061c205e0d035a6b2612126e642b55067d0c4d1228180b45031b00193222,
        0x3c1d33070b67565478462812411c6b430d614a0b58474906751516363c5a492d,
        0x48090035754101582a3d253a7224261c1516335d5231344237662d4d56131a37,
        0x056004326a6b602c62132a4a6d2154367b286405110a631d7a3c704a5859114a,
        0x29541b3004211851795b2a0a126704643c43314c65532d32653631265c4e0254,
        0x2657493a7b573a44564659047d6e281b356646126054634c3d3847356b6b371d,
        0x4c43413c0a14706a2b117803705131506a43123c740c4a0e501828444a295d50,
        0x1b5e304b233e064839033235014a431b273b00174c290d5518037908683e343d,
        0x1c63245d3463726a2c017708404a216e36453a10051650360d2636474b391d54,
        0x320c3617114b36562d2c301d0c2d2d5c2a66170d1d510c4a183b123454144336,
        0x1536016b615b203519066629104271400d5651504854602859170a1301680945,
        0x09337540116a574368461220254e575d46450a03164a013b6725620a423a3415,
        0x36086830272279100110704b75140d652860005d1625462e54114461750d7c5e,
        0x0b1b264a211e640965563a0067355c06683c226d7b505d0c754d136e2d6a644c,
        0x3b124d6e3b15415c1d08346e4a2666260b340010574e3d143a3d6b16156e276c,
        0x3b4c581054055462192a55340162490c4a5a340d293c441437685b5160692946,
        0x0020271e350d7825245908446418265d1c11504121642c666923136838134004,
        0x3b2c5b28654c1b5c4012382e34270b05295104602c022c0b785a61123a551028,
        0x041832170c250d503120461773076131031e793210130d431205071d23564338,
        0x1c09665950003232540665297b23181820422102460c31663100300447001661,
        0x7067141b6154230c45395324383a771c6a0770450423662d52494c1e330e2069,
        0x075c1b373402776b731434465024794011202d402c5a4c15410528152b5e493b,
        0x24174925315a4c19476b33266b505a1374502c1a5c201d41280c7003084a2918,
        0x6c67325a2b4c42391d07144b65162c132c042a683b66543e1057742c583c733e,
        0x623d49572d4567180b3d452a751734174b26122c5d245d491d52616234230c23,
        0x5758200a533c576b36287111124a7b014011380234281a1a1c133559170e534a,
        0x6d6d202d46202704661e72695c564807123b0b211c2179265d2278026d632311,
        0x005e6b612d0126443d2d5c19411e741335496c59770e7c1b284a5369363e1d39,
        0x565a7468535c44493d557b495d39723b52562769194e15520c13373c67271d26,
        0x6d5e755c6b2b4a0c3a126046753a336b65674526102e5b6469306753094d4625,
        0x4b456d5a563054542c1e5b5218194c25685a65025502045c034535443c556807,
        0x46355b166b4d61110308316d291b594e403d21555b597a610a43756e45203005,
        0x382a4517491e702b696c261d0d00584b424a07205a4961155c04222142467609,
        0x74395c551a444233063b210d7d15003b394117523d4e7901713d1c6b286c0229,
        0x5a40074e15091c6908501c040b2b41656c68124b1765071754073a0b6b6a320b,
        0x243b6c3a171d425d406964016903720c2728250d390a090a31675c03762d143b,
        0x0336043b6d3e22161402516e2a3a00405742466420472b243743262938591228,
        0x3d3421207139035923087d295d201d3b70594c2370397628075875274d245145,
        0x3211242e28503a2951071a024a672660294969671b08584d3113340b182e3007,
        0x1d6543334033712b094e05247128485d34413000330d7d32671d574466326d4d,
        0x480e5d12675e2a3279293227095900362c303712224c760c716b321a3b035c05,
        0x0316290e151a635b1854274d2d44316574474a2e4a617c2659571b53044d5c39,
        0x3b015d644222125d6c21366a1514601e11091531405142254c0b1a17054b6b45,
        0x7741416d1824190c482c171338015b4e05083a02070818064166142a3c6a1b13,
        0x1c57192d2438064e7b116a3e744e5a633a5e362a14272d572a20105b1d292365,
        0x34096056680c59675500343c2b2b61215638704864406d676742263812277d05,
        0x0a065d5b19004c3317394b40163a61521c5e540e563a635e4d174d6c02056915,
        0x62435849632340085c66095c4d50146e0736461e5d574d100611433166516c09,
        0x296158562c196b393d29175b4b5d1c56275c3b411a2000654666092265042652,
        0x68136a060d027d5335227d30591e40583a4c4929710c1664035119454450042a,
        0x373a41064d3435102c4077531600062d72340338586b10006c63095732381006,
        0x791429422768390e430a5755372215380a2546186d014146194131321534735b,
        0x2a64386c580b12212804660457544164115212136c58783966252b137b5c094c,
        0x2b206c2a642e56597813620652282b6d2962011346535246226a764249691a35,
        0x620d0151220543430a41043e7419454a0a29183714161c0b43640c4728243c21,
        0x625d6d54772e2c57050d15377b47111068665b2e7249282a7569684420142c50,
        0x1655283640561c23773b015b290158202a4015153c667a532750382b371b7956,
        0x60386338736636497b2576631754016e066c7809344a1316180a6c0e3a0a7554,
        0x22060c026021362469525264750b550b6831122a1429622414196c042b043934,
        0x5d31640e65004b3c5717052547657817223c1a2b77492349013e1d2349383569,
        0x68192b49526735350b58416b6c383c674d263c426d334c1a5a460c0543691753,
        0x58584321663c570259210b466c224a4c6c0828115062733c2d14676a32473821,
        0x0d13161d2a06760e180e573b194a5a4342642927262c6d092809171045291031,
        0x10655a39442c4c35590a486777034724055a483a163e17036855306522483a5c,
        0x17164c1b7313315504464361224921101914551d60223c5b3339241c7c575b2c,
        0x0d141c600b0d603665122b1b0a0b0322034e20004834791b4b075b37551c2623,
        0x49025453572e24355920462d422e783c223a270a2d1e2a05302063287a092518,
        0x031503442610355c7730675d14674043692d5526761c29671c12126021132842,
        0x402b7c4d17077a19703a56147762320e7d5245212d1b6b67172a6007642d5815,
        0x7047025529580a314d652630141a656374372916526d1969642533460409401e,
        0x5b305d17590869583444226e05273552474a1b1445647329261e296c75163553,
        0x021a3a1d341a02423c23460a665e6a645902144453067c3b1649454126355128,
        0x29447860692b1329781049153627120943592a4d0153225c2245060252476a19,
        0x106306565b5c3062075361323866132463632948790a4910283d7b227a6c1448,
        0x35362b3d763e53332c2a3846222d7d187b444b1e3a357d1e596d242a745c284c,
        0x124c431a372d0b2623244c513c3c3011520d3b0e4500654a6908272108107409,
        0x1d1c215a10214d3a22365b27784c5269634d49685c5224304c5d3a681b413b38,
        0x116210182d1a2c26794341553a5a0a61545d325d3518245e5d1471152b1d3306,
        0x0130400d325c012167647a2e6b306b046c113408101d6913455b163236296062,
        0x026174057050094749032b0e1657481527011834181a5a110a1d791d62160d34,
        0x26473829621019195a34772775206c5b4a320d245b5737393d1d4065776c240b,
        0x486b714456454d6231424637621c381c7b304616796c6c601b21240568523a06,
        0x7a4b475b063c5061132c5d655d6e4c4a2250144678441215515c0769154b0d67,
        0x4a07631e473875515a4a0049530a556c0b4c2143085d393e54657431635d2555,
        0x706d035b004722411729585c465a56266854695a6801441c7b68021e700a0a60,
        0x3432411a04205c4939671433612236167436186c6737594b140c412c563e365b,
        0x0741234e11234649201d7267172c69641607515145556b5b5b23782225381a57,
        0x142e7d0a022d2a0230106d1d6c201004062717501037435712122c05251b2224,
        0x471b37607c294757111673456a3a43623d5005217a2520050d325764035e1144,
        0x346c361504063748623c77391a4d42413229212806185a035a1d173065325239,
        0x58184763661339121a1307193d036d420264771238187265463b3162396d3643,
        0x636d2a077069241b6a3845496b496767141014494b621920231b2b35470c4729,
        0x150d031a32065c444a3b346a4d2a42685d421c43515a462c18207c6508206d0b,
        0x5346550c4b00336212502c373626512d442251190426301800595a69765d1569,
        0x7b05400c220c590c386b58322d043b397d610654706b132a4b104c4116170622,
        0x524c6a6c456b693273160a107a64620925401b4d5846015d5354595573284050,
        0x4063245b6730611023164030063e3537025627022a60605e6654026739324103,
        0x30281c1456106b6d392b345803617600404465443d177d6a2606703449454007,
        0x5647412857116215680d296a49485c413c383c4d5831692271035c293d64062a,
        0x4b1c6220702d0b0717377221434e436060170a580b3343112a53106d02030a02,
        0x543558347d0433450b06485e28272c066b147d3102080b653731546775106200,
        0x262414071a47441e675100095d056c167410021d2c557c0a662b6c277a5c2b58,
        0x790c2c00383b510d4c4605622a1600244a500c045166145d270b592268415a07,
        0x233c2118394748380a624767003277477a171b46771337284d594c4b30032237,
        0x2c4a1d463b593334340c6c186b2a555c175c58604d38631b544b365a3022524d,
        0x69146a3422330c6c4c245b5b0007734c5667132e61005b327c03355541244c68,
        0x22142105256d6a10696679500c2e6940672e5b6b040a5a622d3a033b7a652615,
        0x3d13253e225836413c0e23335314392033166638015a013756342d4e5040602b,
        0x0b5659691669481a186671272020256b7348494d6642333b1a51366b52610405,
        0x4a1b152519565938751b670e744b4466041024005167294565400d5b6c3c2346,
        0x7a1059006b023533610a213109257423311c3515060b733d355144274d1c642c,
        0x7c0b190511415c5a2029525a79153d47093572085067755b4b663c1c51627408,
        0x633e560d0143006175483d61410e6507650d1916653a2d034761310e0d380141,
        0x3b2505493a2a50303a3653206404203b06602d08746b133b1858662762425457,
        0x5b410108106a1d196a6a2667575e7339044b2a62752b2a2961353c1e5839463c,
        0x233b11186b657c6174400a336a215336413a123d1b4952061856003a12225168,
        0x2428216b071c26342b5c512a7827210132186c4d74657125676e5913435b671a,
        0x374008350d12543917143960206a59273d4160272c6e182648222c38526c1b20,
        0x136a78156d26622d606d02621a0658165637304e180b224e094207514260566d,
        0x270607637933770536663909286b066e7b1e69267c1575587d101c2962692616,
        0x5c1a6427736e7120031000263732020d7b3d7d2d432212024b1622421a524542,
        0x5c430639342175305d1d506d7d5734207c37303d0362235d64124a684c1d6541,
        0x0c39105965494451494020252862722b0b517007502b271b701910387758130c,
        0x165a3a4a6b33370e325201527610795c652e7a0d79273213562d384c4a532516,
        0x645514045d0b49516c504001545677452529170258262b450625115a63653833,
        0x693c383d64467a122761401b32685608691a4a252519235c515669353d355257,
        0x1917016d57053d0c3d6659417b1c14552857196a266c0903631879427064100b,
        0x27122760275e306e14116125384a15430413412e794552111a216b0d1b241108,
        0x5a35382c5b14101e7407214c332d171b6c6a0028123e79475164152c42237414,
        0x1a5615610159240c452e3a3a65477d485b1d385d531a7829690d481d26271568,
        0x46690a1e313b0651616d72284b28602a5616522b2b561b503b6a1b4e0039240d,
        0x5c0049312019286806147b136b1e764c4d642066395a08053a6215307d33364a,
        0x351e5a531b0b560b1759236e660123644865542b472e70431a2350324a105002,
        0x5319374a6528781e4d2e614e7d6447457354352c003e3d5c782459586b4c645d,
        0x7467524a71595d0863142c2b0723466d673b344c315860676005464e402d3b19,
        0x15550c6b460d3d69784b251412062a5e6a15726d540a5b250c1877485d02682d,
        0x111d715d44520b6a735112490851244e14386315794964545d512c58096e1843,
        0x0248081949536d272a016917556028671a593906762b742b33142d27736b562b,
        0x5b565d43724771214516425833185428065a552118077109532b6b24661a1d17,
        0x7b0815013d2857031a49252a371e6a0b595313063c36192e3708413b2c285250,
        0x4c506a1e3908686457071431506c0b3a2026731e595a63533d6b065058291122,
        0x463a37506b1a2d6d54200b0a523d604441276b15434d4766183d7b622503254d,
        0x232a455434607129430005076d3830405025435a46676b07444a014b384d4d3c,
        0x4c3937091041371a53075339104837236c3b5a6a0b44520345371052085a190d,
        0x63417046004d7049730c17555b1958286d502457165806104b350606444d676d,
        0x48566729275b031d5c58005778327d2612543950585d2950633d371547536324,
        0x664b53483d57706c69187a691b2a5648133c735605381926065c483e30492a6e,
        0x6c012034244a5a14045b0a5e335114394515656b693a66555a470d15324a2b27,
        0x75263814576167203925083e28026a1b786231150a495a602c4e0a345b092865,
        0x075219517c4849270334453460491d643d31032e480c025d10257a22411d5424,
        0x0513131e65334113542c73044020681c156561433a1e5316715a213a1b2c1310,
        0x41582b1c3d2215333b24074c310a3719594d186e26467d5101147a48522c5056,
        0x190e58026035396902120d35164c393375184116513e282d294046086a661742,
        0x582c0d0e5a312831620e51055d5a22396d25646b10031145053d646a1d2c3d45,
        0x7706251310173512244938162645253b4368644b0b48472c13416b4e336c5a12,
        0x72011440303e40021845430b755a51180750351a09605c23365c6c3354307d21,
        0x49241b16012b6a1c204d52041c48110573211434690b525c6648486268115d3d,
        0x65432b2907436c554d40203e10266c0b361b273110293a41250c664354290700,
        0x1a247751661544212a6d780749597355522370043c4677216a556c23056d3763,
        0x1748776e5006064c4d3d1c204041753b662437187b2d493670095d2d35196612,
        0x253c650c642877332508105e551e294d550d52296d68684b3d1e466b7b35590d,
        0x4651701563015001472867261c46725b29316a5c6c4901327b5445220b5d4764,
        0x1c3c2a5624530c260b143262405a580c001b274428141567415d236d58650303,
        0x530815440c0170301c643c17156c486e26563a2c79061a2222320236673e7546,
        0x2742670a47230015523a67441a1b503a6752525e0808372c6600051e471e2a36,
        0x7c22732b7352083029035301006c574127242a22030e6d0317363a63574d152b,
        0x43027d115a4b4622161526265a6e10354140195b1604750e5458161461385852,
        0x691c3d3924651558632955285d0a20534c264358374e52406142655868205c18,
        0x76527a4978354b0638281454623755567d00640612532d546b3c073b0b2d0215,
        0x5748112a443e406d602e423b6904401437493d44412a6a2202656c62153d3741,
        0x69074937526348692859773a23177968544155694b56060c0d63541e5a017136,
        0x4d280111303b054542620c32446b45301027605d683d2c170b3b432531431b12,
        0x2d2e343b62647b660a354820533d1150634636013a39211d44260301272d1a4a,
        0x35580d0b4118005572197c43025b356a121a2718302c41020c650a442b30446c,
        0x495a05326c3236134009574b634a7b025b2b272753110d366734014c163c3d06,
        0x42677d5538151c2c24244d46091d213c714c6a692a46073e6559164b09120d11,
        0x69536a3d164e6545091413473305060751391c37733524311b6a56061b567400,
        0x3b445b31331d7938155e7d1b244158030165504b77173419173d6c1a220e6a0d,
        0x56553d4617153d6057284a57691d276e42520924131a652707617c256031024b,
        0x7233272e490b2d0a124657200c667c4e0b6e730a06361b0a0d2a690a07473255,
        0x67124a204501785912037d356b5c0909246277355010283a5d0d6a2c6b6e245c,
        0x2b121c2e7a4c001360585d190317203032190c3663314046402310160c3b3363,
        0x093b505b17315d0e3b200d4051116b114121723553127a0b36537b030553120b,
        0x1a0d2a1179675546535b0131545a4d660411701b3a010c0b483d30320552176d,
        0x11353d201d031749616433192a101214496c4b227c414a0108523751740d1d1e,
        0x442a14066d0d2d5170292b2d1904243e193456023034641b204a713e4d00030d,
        0x745d404d4b491911263a274b181b4b2003244c116635631a6c02555579626a49,
        0x2108180004276511464a503d055137626a041d3a16377a0558645c1b066b5749,
        0x16434640714b450978631b2967166959250e04657b64716d18010d6e4a421811,
        0x5058796537545347746d672c771015576336191c0b47654e763954475926233d,
        0x39553a58163578496956063471027c4032154b6a31305817344e721b6d56400a,
        0x41300c356610343756686d4a0540283c581a11261a28000a34496d6b46320d5e,
        0x2838021b2d2649283127453e77540b5c4d5b7b6b622628077918104e53037b53,
        0x284b74290d527b5e4c3e421e6246265a151c5d04783a232e251d451d214d246a,
        0x346163220b1d422b7812271577013a51091539112d3d385b663b27524b420847,
        0x7b3c3d493c1a661812394d43215c46582955173408234a623c3e0d447a635365,
        0x324268367b630440653574173c045b6c5715745b266a1b400d2743274227670b,
        0x7d1d4b19022a2a34173b520c795e07343a61413d305c4d45051110645d154132,
        0x40401562336d794d112b7b1439174d2d696e0949644970523a420148732d0425,
        0x276b45236a5911173a0447600d2e6c5d2d1545106c571a4b1728095a25116d57,
        0x7b4625156d6e774072004245491824681a39646d3937780403130816036d7d41,
        0x06311942414542355d661b1c18171b66492e4907312a6b4b36697d430b28483c,
        0x3b307d194c2c7a32711e6818626666167a5b464c44083c0c205428540601571e,
        0x105d49140146366748233224241a123a0a1c4c217c2826135b3a671322653759,
        0x284064221b2b6519360422545b06173a5266664c120e712e27466d62256c732c,
        0x6b635356175a2b557a6d395c6310202e79522162693310110c3a0b4d44371645,
        0x5c1e0227003819274656225d1d2773002558414b724c304d7a01470b0b233023,
        0x38410b18374555035d4e14240c59205a68160d3c4b0477606d4115504a4d4559,
        0x4c5b4b17094333095b005440090b5949786940343a346b18793c4c3861596a41,
        0x6b3b636770063c3b0454290b275a182713447a0e396e436e4a37315626314032,
        0x51152c2c29573c620a6e7a310522000c58424a386d435c6e6b5911475a44381d,
        0x101b790024662a5a71454d5763321d13731103687b072a2b496e32233a535658,
        0x08134800243c055433595134160a5b4a6d071210420a3411211c4120204b2737,
        0x2d66053a013a48244d612c45176211381a0e1521780671581353795861194d20,
        0x6c65512425051200565e37142d60426e2941211258696509321b42107d405814,
        0x5b6d515367595a2e4162794a00536704472d333e576248505649785673346267,
        0x3a6b7503271612114d06084b3a466448010c575737335a450d5a291429534d51,
        0x261b4a21334b556824334a65332a76061943065b4c0a484a694e5c3e77567164,
        0x48192828735d0c1e064d220d12476c4e524864083a2b1c5b76340a4c0c600a0d,
        0x6034050e28631938291a0749420410050b205a3055314c5256430766034c2832,
        0x3a332c0a56173900563c273c0408380e696544576b414a050d53723637241828,
        0x4250720b34131409762e70625b0a386718363c68442e7704783d266275506117,
        0x1a4c0568560433253a4e0901693b611c3026582200003050323e49666b476d4b,
        0x501a0233240948441d015952782a73583063706868355736603c05051a126c00,
        0x57371a0a595148322304580a7063555e6340501c4a692228741111296c472835,
        0x4d4e3a3b2a2c69162a494b2d4532543120163163013c425e1619141407273401,
        0x334e1443186b4a603717595e21486364695e5c2c56364c183a1b443a31493c29,
        0x3c504a3d2a31405439626a292d333a175329235a3c2d786a5706723e5620634e,
        0x3c323117364d5d6b710027073d2e052e6c3d11064752185d76307823254c450b,
        0x4d3e31693b2e4c447b262d35211a63565c5b7c2b31364d0d545914323a05332c,
        0x4c560d0c1b63524b4b33666d3d0e574c58435a32666431072a440528240e0001,
        0x7a0a4c3b603355507d5c0b4e38647149193564447723264d190a26191a45184b,
        0x59331a584547394d46076a174d5e785b775b7216162c1d05190b721d30685517,
        0x700d50334003545e19180302081d23571d321758072419096d533716685e6521,
        0x0506013d396a0d1920026d495724363b1c325c450735154e7d34604823220354,
        0x0d06424b586a144d485b1c066d19722e2703494b5a19675773402b5a315d6416,
        0x4c13455c0d481d15074b0714300b642170572c113b532c162a3e39424731262e,
        0x19280a6d195d57221d1a0150702862623b17005176011a0b723d5031660b1b55,
        0x79122d61730248417808221c5318122e7765591834517c6b0b311b600a645d53,
        0x42401b0e3357072d45483928020b4d04585a3944330366495202340036143008,
        0x5548766945610d6d4b5e60183b427b431125115e022313491c1e722544037032,
        0x1a197a273225086876461a40646c764506406a6754434518060d6b1c7d226832,
        0x6b3e6b3a191321347c3053355d1e3c011b69033e27137c0276191b4b5c2a1d69,
        0x5b6135085501282154456d1c3530436c411b78681a6b7167335a7461503e0221,
        0x28175915543d102a734b460b626a02201b1729647a5755274b1228033b04544a,
        0x7c54414262551c0e14300d4b48551332540b7d6064620c1b1405085c13181613,
        0x1a3124025c4c32056d0a44095c65665d480878413044522673170c4b29477250,
        0x3141676b313e230a701c4a4a68056a0020186101575217681b267d3a33561441,
        0x525820093b4e4263240473221c400b245022501d161b6a47326a042409661a3a,
        0x2b0c281e335b6228312b55523d5b1d1d280b2969356569315522616745135c09,
        0x4901165645571b4c4b691513292b0d4d1258072a0b4a05297229046a20323a13,
        0x193c7113756202584129701d756c535e250b5d2724507054376c3a371c6e2d25,
        0x5a6c48636d1a664a285d7a02573e4c3727193665435d4b1d5a5b37614833082e,
        0x795a345053050b303d1225672056415e70145427405d604c6b0a0a2d20625302,
        0x520b566051602b5442652544635a63066d0c77114a194506342e4a340815686d,
        0x422924481c0c3c25275176261651255a0926234848581548005a27360c5d294b,
        0x5b057c0c600a79361b334c6b2305581d713b195e052b5345381e68005d2e7a46,
        0x002a2117150b310156566345513233445328133873032b6b5a3c7c34041e6515,
        0x271c0006081e350b5514490566475c08706e01076d24406478643c05000d422a,
        0x44134d0246215208561d0c4e3200313a3b1e6709306148366b2c0c5c1d0c2211,
        0x1b486439554038422d286732592a7a377d245051221b67145d32312e30152b44,
        0x2d24425a230e7d471c4c394a771d166b2a6a3747423d141d4c496951561a3245,
        0x1a044d2c506a3561405c103e6d14281343187b001423722d011762402159130d,
        0x176c0064311d1d38201210220b377c1a12430944640d44021511423c7b6d5c64,
        0x2246744c12486c2b04575b1516214b054546491b295e1a2d551937113d593447,
        0x150849321d0b61033a11015e1d4056030623653b563914172552396510567665,
        0x486d226b441a390444540c3777312007651739384100531c0c246029070b0550,
        0x572d67505b6e696347540a5b39561314702733025b1c38030c2c191d72151832,
        0x1a082b5d57355538423224433056552332284464651475216229161e28517a1d,
        0x182c26115a25391b126617443d3e514c7b3a766e293d594a1518546c06426755,
        0x02226b350a300548134d6a611d3467463a03395b684948185c131232354b712c,
        0x345d610708651b0d610c5a230b1027650438780062025d6a052d283918391216,
        0x552c05005147636077286910305e233640164c085800724a350a595c39166466,
        0x190232013b22242d18384123534d74494400391846540106461b685c43461a5e,
        0x483039143d2c62353648323c6b0827265c253b025669281a733b49414a6e641d,
        0x0d3762366c540453720a59054417005b3340632d106773125c4b1867340a6a25,
        0x09235c2d3b165b4b2149730d07620536113977094109523e09020d4e5b43403a,
        0x350e56530b023720592c464718337d256a625116672a1a6269425663406b5d46,
        0x0a451b3942005254152a1d55276a195a301e140e57293c18241525233c4c5a61,
        0x125940283952080c114842082826393c460350131a4621145b6672062d6e591c,
        0x34063d5143671c0132373024585428415d556861584c095839612d2b03565632,
        0x2c23410d25695a2c43107d5019235a385b542a4562337b316a5229294320185e,
        0x765764131506461a62142022544c5037316c3c0a52243d37075b363a77687b20,
        0x4b025c345c502d1866537b4a091c33653c6d773c6d05650b1939765c4866593d,
        0x4b4a51206548413e6343082c470a741c36595719423642513139450363523b07,
        0x562223347058352a6050285e5b204c322c0d06371c59054151441a2a3949060a,
        0x7a2b4c173b627c4a68565c21063076495d29703d7d690617436b354719150d6b,
        0x241e4615434b60140342514b030920451542782c4b59061e32466433440a6c46,
        0x0b402533676c2522286a1541795d4439154d532d083c193d2c0c225709487b16,
        0x2a5062050a17492b15633c3d10405734324d501b7508451b215b67661d3c7331,
        0x4b0c121b54464769552e3c44776a580752595b2d416e15451b425d0163494b23,
        0x652c4661390219103c197c04043070014909753c186d332e1303716543667367,
        0x300c086d485a0a392011734d256042011a2959075129715b6a033c1b5a0c5819,
        0x0a4a3b2161634a5908565d2c6d000100556a50170a562a1a65600046033d630d,
        0x4356171209633435354e266e0a093612194c29042226264261453632023c113a,
        0x141e680600524556126160040c62221a3b43214a07164c5e6263651353327833,
        0x4d1d4704304a09101d44621a383e41630838203d354131344a0d69687c176762,
        0x56120136651c5559500c261472376b212c20042c3a1c6d290a0842485923594c,
        0x581e434a2c5b563d3d05522e4a6a68216c131d607264785c356b0a4b2d005d30,
        0x0327352477243d02554c642a244b2058733611012753135d162b711232433b1d,
        0x263652103c27564b5100641a161c09003835703e4d0a243d432b7b2c6b5e6218,
        0x0d047268010470421a6a650e216d602634245a2902693d5a0a520b0402346a18,
        0x50472339506b444102630c6d643c2d532748444e611d484d0041086055672a0b,
        0x7c661b28120d0103754200301704625c0d5d7c5a125e11141339650a3c3a5542,
        0x7d4b2c3d69016508120a472a64560a186a115b1130472547132b6d282907384e,
        0x4659274c0c64745a5d1a64646a26780124640953655e43094b63755d33555a04,
        0x665c5408511d743b5510186331110807252740051b432360262a395916414b47,
        0x644a7c42070447023d4b4d6d7d46185963035b226c69270974582d170d073c14,
        0x7b06030a4d6846040918446200445a0e7b5973331b1e6939136400546d23512e,
        0x36357d6c2c564b6e76175d0046655b40685b3a1a37053a432d423b064135510b,
        0x742e246d3c57535362593951251763271b052300736111645547366d2b693b37,
        0x6a16363835604a0923023a505a1b3d53776d4b083b332d691d676b625a376a02,
        0x4b4b01603264083b21532c6a73467b290d396b2d511a4b5b4324664e0c306520,
        0x4d5c67361c614718392379206b3605424326135c056a75112269146c463d0658,
        0x48352649025a3742636816231c157d5e075d14664d323d3d3836582b210b270d,
        0x5b18532702183a0c180c456e012c422604435027314608324c02430e053b4b2e,
        0x1d201d22674d51132c1d5d6c64381d62402e4d562c415731751a624b5d072a43,
        0x31026609314a761e67407c182b051c307a351c24580127334347092b47074d0b,
        0x3239051b38224a5b04510a00143a79312a080c50361d0c294d23606a7c60566c,
        0x196e6258660a38314401725a0b2c21613503083148121c2a7a424c6440260102,
        0x4a6c4406621e08215a0d3901572c6a5e476e452d66373700625a2363496b694d,
        0x5a5c25121c53223471634a24416c262575330c214a36593b2b15502c5a09236b,
        0x4b2977156546154662231539263d4644461150151b251968773e0905682c7466,
        0x1a66742d1924780d671e5765744d7d07505708014139366801613a162353345b,
        0x7053041955510452460973417d6b1a60201062474a170517073122474323173e,
        0x6a080d3b146303042b6007154234651d7b103b4d6366150a2204344314566361,
        0x2c5441521c004c3c3c03605c0d425a272a287d4243043a38255971185c2b0034,
        0x004c7238673a5a652d20444326080c4c753e4c695262022e5811162814121400,
        0x365855331a364c6d62537a085425083315596063272c783e4308135523315b36,
        0x74214a4e2b59162a24367d273625213d3a3c18697b6c774a226343036127743d,
        0x31245714320240221066521e1662196438126b577a267d022a18434244051738,
        0x181376371549360a4b1a75565c35221d6114415326516a453051055975555c14,
        0x6a631156162044295a177d1a76597621020223286d591a03160e293a79131346,
        0x674e0955610e52421626615a03482144054a2458473c3a1527662b57295c2d62,
        0x242c5b6a72465625591441683660075e692c051c0615313c4160793d22222902,
        0x5c220829566b63505b67456a416a71567266525b6316156a5640041b11555158,
        0x5253421479357557662c586c4d6b3a661c3e291002514335262b75133a232a4b,
        0x3422620c13025b55630211672d0b5d1b08532c102345570b681b404e26047545,
        0x71463c5c0969666a240a662e6d476c4b1505170843506c171a64435c2641055c,
        0x0643601626610502144a454e0d216b2e5c107c4b2039311b73574b247c19732e,
        0x46063457596541430c126311146b466e1c6c756a66235d403a6c21566b00654b,
        0x7a1a1d68025e4828016a3a45351b1b3a3c00001870415b6240536a5620400257,
        0x546b285839260633036e216c435e13353c2e662275535a3b5b454468140b5135,
        0x7254310b512b771a1235283737342800191b3b650539184d5c59465d2418234a,
        0x0556093907280b0832483a14093665685c0b411767231d63146566024b180b49,
        0x2065291d723a631933101960073c386d7531230908362c152043550a2c4c1c4d,
        0x4c4071691a3e1b27385c5b1e1c49330c686c6d044a5c056e660636202528362b,
        0x64075014454d7a5a2b284d5370131b2e15567457712d212112412d115d4a7668,
        0x0c1477430116792d320d7126384b346612256059652447252c030645514a104c,
        0x24030a04356d6032250a13347b36391a77664c4c44605b4c322e1a333204551b,
        0x2a12156d36641a5a6c304949435525247a074a2b415b28057161254a51224047,
        0x233865641c36096d383479690d41751943417a363431481c4228670241441a50,
        0x105c5727566a1b1122403b680d2b09507b0d14452935431c703c12443c314930,
        0x5c01371c736c52374567591d2004202c341004153c370c08485c603008584803,
        0x28462b0872423323365253097506675a1908022c15532546623e216a1c4a3426,
        0x27637c2113514c4e392a215450667d38010e594066577613630a7a441230266d,
        0x59016804763850606d11081c233705471a1e295d0d014d607c070442441d2d50,
        0x3b2b3966484b7a3b552b3d481007572a0b6346633606491c395367035404504c,
        0x0d6274554b6758575c674b2b2b1e711d770d491d0c0a7a3e54105b5a656a5245,
        0x0c5a4c550c46626b3b00503b4c0002321c0a111a17435a59462a6b3726204a51,
        0x554177380219200b50507924780a3d1b01675b69212d04336250266b6c511a61,
        0x512105587b3b2434010554641c250d31766100145009541c516c11004c670445,
        0x622e01385012100e3b26796a113071333c087308412b37101a27624172220335,
        0x141c122b6313382506680c1508183c6c7b416410083d666230392a3c7c16452c,
        0x58484d365d2b47340a2a684078264768281d5460303a1c0820151d0208663c07,
        0x626e7b125605143659451660153e741e1849596a3b63296b790b6c0a0d57135a,
        0x295a1a097707204c0a1b0c2038071345255773246552502d4551541637072c60,
        0x5944773d3d277b4b21241a1d6a0e4b533a6a003300434b511b3b094033645664,
        0x354569217a3a5016686212192b51010b76184a141055175641486c5a0d094d39,
        0x2a371a26260a5140080b1624793a504e2330450c47626b464049116e64632754,
        0x1d0a433e794b055e04482758302b15234a5d1c2b375a0a01260b551107331d35,
        0x51230122292a0c69124041502849722c340e7c466b1229135130612b74151822,
        0x76506420424e160619520806426b604758210c52630050351d28702329151c3d,
        0x57695a4833361c2d48592c24213350557805172557510a077143626079517d4d,
        0x4b6064616139702c4a305a4d022b7655270c764716387d4c2502743c7664151e,
        0x0417756415107b585b46655b0436570e2b3239315d0960430a5c5c1c0c5e4328,
        0x17271b316249516a0142572574041b0c5d1c00275a560145786d575967686518,
        0x356e4d1675436c4813425959566538204a1c436d5142305d43305b21691b2a38,
        0x6256362e32503128415a302e352538526826446e2c127a6843156842003d583b,
        0x5322542666404a6b40377b514a021a2e3610335e524e100a4025553c44693753,
        0x0730133d220263622510540c4d2573253468130e0b6b70267957466055667b19,
        0x02533d4a313322537c3a3312412678217d3b3611666e4864665615000a2b1a63,
        0x6719541a532a2d163b1c760a560904350c51601c62487c45532121390d161352,
        0x59616b3d6a1d136d2d465b3c1b5426483a5d21252d1d731c510676361039456c,
        0x490a03520b385268401c4b614340376b502a113356011a6826174b3252096d64,
        0x3a244922793030214d1469555733292839307848176b06573523156044332d13,
        0x29602c63326901695b4831687369006b21665c48713577592c3c2238004b0510,
        0x24374d0c4c471b44076b122337442b3e280d28694721002315326a017b323c51,
        0x6658292d5b5805612a61024a6530126c364c6d086a4a5a3338571d5d5a2a6562,
        0x6a23440b366c43632d43704e152e3520056c010a231d0216460178305a212553,
        0x5068114663122051181d6a2b7446003c3b3e086b3d0b406a3b097b1b6c6d1c0d,
        0x724567000a383810071039433735001e58045931610b332b484230584209005c,
        0x4d55454c60403c5e0b5a126922595d06091a07010c070b2e71500b5324145960,
        0x63393d263a5b2d655b500d207a0602010b600c38335c71144525342c72115065,
        0x1a2c682470311d366d556134251a5c112a211b352145764e19657c380b351955,
        0x754964680a3d0503663044186b54290910157c627b4e6a4854507d0140554b27,
        0x020761203756474c772c3d2b2c087852481e381779034108013359484c126634,
        0x446708033d187105636a1c280b111c627c4c2b0305647066476c274e7c0e3c4a,
        0x64191a534247533a64155d412c36295623520128142100697857426678116a09,
        0x3403476a536a5136422d2738505c5d3e1b3d57262c440164556119614c3d784a,
        0x336e1103636b330b300941366201174e71487620092067211864772a210c5048,
        0x616c721c530c46104638543c6c41095e69294527522741114b216b320a366429,
        0x4747313d421d561c2c697232291c576c000b7248495b5a180641450507183119,
        0x653e160b1653202b4a1635110a0a2a6521035a1501567b4526651847562a2663,
        0x542d14595244316b2d06135737034739001a4a6d751c3c4b3455282304224456,
        0x291925411d310d2852417845104b5a3a46137755006a113b263e615523230863,
        0x3a4d183e662a58365403471c595b04562c314b0d0b29303c5351562403412d59,
        0x2a263d68443519461157110c0a696108116151335c544b52584e3b5a2a0e3b61,
        0x205c7b17311a38242c6b0447796b0534485710121a34086e6c2436092d303221,
        0x2a5b6636293053137b5a70116c03382d24636b1b69442d2a1308736a4a5e7b40,
        0x1b612d4c69486a465c0279286a3768234a127c3620241d4c6a3921680c100a05,
        0x5611672b5d61752878141a10021066287643046b040046463b365c475b077a56,
        0x475c726c7c2e310c215d4c6e2055420d5768035c41381350784e0a4e21405451,
        0x1c452d4b45624965410c032a7c5373320809182b49001d4e282c1300621d5c0c,
        0x225b293207650a5a71664c09363d6d527104680275685c33432930641d48002b,
        0x2a1440104825510e1b1a36622b38285b101a7c106911682b1b5825206c6b433a,
        0x084e3d1a24234219251e222558666957033a2952782e726b344d793e0c6a3236,
        0x5218686b0725163b060538063210566e0101115d760805010961353a6c663114,
        0x5c5c62307301456936541136601516222d473b3d111c644d381a354803460042,
        0x6123786b3a6771220a3a4c364d476c1c1d213861394649125a543c6b2b683600,
        0x7365540178616d6909543b0b1601350651040b6d36516006134e68510d602c51,
        0x344b76226d2d40184a3e4156546e6b22036a0c1c624d414c580d0a5d11436539,
        0x5a0855657d2c0849106149551331612452345b3379161850130b4917213b136b,
        0x440e206031086c1563590d4625560129444517605c63023801396068080e0921,
        0x7a3304314c16473e4a2d02267401592b26534b44562e074d374c7b524d036853,
        0x0638742507601901341e57503644663a6c43292e4d07536d0817066731252217,
        0x5708441623692c6d23014d4a791e225525614d4b69005a24212a216976547b15,
        0x2c4d533419323369655a103b046d493c721763472412740e0a287c013a300a57,
        0x08450c1a525d720e1d6b51520b4220014a5623185d624b580712640b214e4224,
        0x10452b180c615d21733767077259775a121d0a2625541a0c3267174c4b4c280a,
        0x77021554162d7c6d3b356a0c4c2a3b31634b0a3e5233285333470c566960453c,
        0x284326224950414122080859292c396c225e5d5d172d62227a6a565d7022771b,
        0x2d210062691e54523a4b77445a50535a774b020a200d756319221b6512383704,
        0x1c3b6003600c1315015c39100b17081a2c2e726017210d2d0c1d070651092939,
        0x0312232c384714627c05714d785539364d52126d76620d4c450a7c6c346d0512,
        0x7c273144330a02003c490b0934125642622a5a105716073a5a683948274a350c,
        0x765e66335c3d7b67504d674569691907153511125101053c18680544255b535d,
        0x721a4848633b2440776416406565351d0b41386044113d2a45141c07590b0441,
        0x746218230a2e046762575b650c03182d25062926360d3054375d256573301317,
        0x5a41225a67392c5e78364a0021420225761b0d2576515a2d571b0a6715474933,
        0x011c13430b5053491802433c4a417a34383c35293c34766c0557776113217732,
        0x3b482c334b0a4a547c2c5628531b046e3633513170245a1e36616b53482b020e,
        0x53255d566414684d281c720533300a0e68294a1867651264741613624942264c,
        0x011b3b4a64473d301b1d384826583b1068347a6b343e4114741d086a34647a1b,
        0x390b2a33166d001c430c4442182a186277180b2a31231d5c4c31690e0455046c,
        0x2446761d0c3116471226576d4631653c03392d0d50690c3e1d4a394b646e6a4e,
        0x26012c6863082454696d04685b29411507325b0214153c6e57014816211b733a,
        0x481b71474a3521581c410864310d040d58454d053a47455e4a451642283b1140,
        0x7c3c50076d3451572a393151431e760d22102b34505d6b4a170c11112d297b61,
        0x1c227c6e7d5b135825660d226b407a04124e722a3d23625b2762605771531019,
        0x53440b1e090c3650623276484c3a42372a41791a385661567a033c201b3e575a,
        0x703343143b1374243043546d301918481c47603a5d602006553741191458585e,
        0x0b130d1c041c2d685221166645525d4d4b113a564159441b60230a48114e053e,
        0x4600064a232b32440d10104a2a04113c56623261601b2d37414d78585d286053,
        0x1d5351106a35405e325e1b6d361943531a256c0d64365252105841332b612b16,
        0x54190349573a6c53112e0b002b6533526d16036b196c255e6a14215e56276961,
        0x39292a1c0857200e5a026b0b13196c42145267105d355315116c0d5810091841,
        0x20234c65234d33222c18021c011e08261d667c5052515c361b15780b02683439,
        0x6b2529377b18106c040170653d674d4476403c3009085d48731954421b061d0d,
        0x5141640c64412315194d65553a4930020c1932561337614971065b34636e2c5d,
        0x0a223a1937251b2d471133501060672d601a5b17536c0d690635405702451b67,
        0x07562526273a23107d165155585379252a09420659112d225c07572b4438781c,
        0x161105555a06222302496c646d186c560360734771680c407a3923506c3e2359,
        0x601d413128017d4524670a553c61504564587d4e4742623a4d2b763b7502345e,
        0x016c6c4526500d3d6b17710e1912325858255651290c792a66211761202a5019,
        0x6348472755243b082b6a66394b3a7a3d3526243a1d477d13731b4962696b2d49,
        0x23064c302b216a24322a05202b421b596a053112535020444716450708416a44,
        0x2924084d6845583a0c2a1b36170538232a2e633a742a7142192c43521d490b5e,
        0x7902063a41477c002a472c6507382335135b5c6b761423666d3b3913681a500b,
        0x2230564d086769452c0e5d1635390d1d6c61213e541b77377b0e73623d092710,
        0x7d0e21416354735a633533316d1e18154964185b27204d304a2363346a13131d,
        0x70051c6726091706784d391c6503246b72203b5130604730724d110e4b01026d,
        0x771902115c2e212b64500a37433268333203026e3b47145a5554530d1d5a1c5a,
        0x5207675c51632b0d1616115b395d0115002152121b026a40781b346508694934,
        0x471a7b426c053a281a673a0d2a030b3e3c590157553224611d250722201e3266,
        0x4849743e10331a164a1a370b681e5d186d0e1024655d4c14644e70356b56522a,
        0x005827356133304c5b496166793753557240114c5543203c351c104773156460,
        0x7b6e280e743538633c1127557a2a21194713324b263c500d50522b373c404c5a,
        0x502944637d5601256052391e695b224a54215b1b075531046b58361a54637752,
        0x17182911076d570901632600191e636c6a337b603737020668397763180d5112
    ];
}

// File: contracts/Attributes.sol



// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

abstract contract Attributes {
    function metadataBackground(uint256 index)
        internal
        pure
        returns (string memory)
    {
        if (index == 0) {
            return "Blue";
        } else if (index == 1) {
            return "Pink";
        } else {
            return "Yellow";
        }
    }

    function metadataBottom(uint256 index)
        internal
        pure
        returns (string memory)
    {
        if (index == 0) {
            return "Dish";
        } else if (index == 1) {
            return "Glass Cup";
        } else if (index == 2) {
            return "With Strawberry And Ice Cream";
        } else if (index == 3) {
            return "Cake";
        } else if (index == 4) {
            return "Ice Cream Cone";
        } else if (index == 5) {
            return "Soda";
        } else if (index == 6) {
            return "Crepe";
        } else {
            return "Rolled Cake";
        }
    }

    function metadataFace(uint256 index) internal pure returns (string memory) {
        if (index == 0) {
            return "Normal";
        } else if (index == 1) {
            return "Glasses";
        } else if (index == 2) {
            return "Mustache";
        } else if (index == 3) {
            return "Beh";
        } else if (index == 4) {
            return "Dress Up";
        } else if (index == 5) {
            return "Shy Smile";
        } else if (index == 6) {
            return "Sloping";
        } else if (index == 7) {
            return "Surprised";
        } else if (index == 8) {
            return "Sad";
        } else if (index == 9) {
            return "Happy";
        } else if (index == 10) {
            return "Full Stomach";
        } else if (index == 11) {
            return "Calm";
        } else if (index == 12) {
            return "Confident";
        } else {
            return "Awakened";
        }
    }

    function metadataPudding(uint256 index)
        internal
        pure
        returns (string memory)
    {
        if (index == 0) {
            return "Egg";
        } else if (index == 1) {
            return "Chocolate";
        } else if (index == 2) {
            return "Green Tea";
        } else if (index == 3) {
            return "Strawberry";
        } else if (index == 4) {
            return "Jelly";
        } else if (index == 5) {
            return "Black Sesame";
        } else {
            return "Orange";
        }
    }

    function metadataTop(uint256 index) internal pure returns (string memory) {
        if (index == 0) {
            return "None";
        } else if (index == 1) {
            return "Cherry";
        } else if (index == 2) {
            return "Cat";
        } else if (index == 3) {
            return "Mint Cream";
        } else if (index == 4) {
            return "Hamster";
        } else if (index == 5) {
            return "Anko";
        } else if (index == 6) {
            return "Bear";
        } else if (index == 7) {
            return "Strawberry And Cookie";
        } else if (index == 8) {
            return "Rabbit";
        } else if (index == 9) {
            return "Mix Berry";
        } else if (index == 10) {
            return "Pig";
        } else if (index == 11) {
            return "Caramel";
        } else if (index == 12) {
            return "Cream Boy";
        } else if (index == 13) {
            return "Pudding";
        } else {
            return "Bird";
        }
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: @openzeppelin/contracts/utils/Counters.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // 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);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

// File: @openzeppelin/contracts/token/ERC721/ERC721.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, _data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

// File: @openzeppelin/contracts/utils/Context.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// File: @openzeppelin/contracts/utils/Address.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}