// Contract: Role
// Target function: function addXp(uint _tokenId, uint _xp) external auth
0,0v-8.7c0-0.3,0.1-0.5,0.2-0.7c0.1-0.2,0.3-0.3,0.5-0.2c0.4,0,0.8,0.1,1.4,0.2c0.5,0.1,1.1,0.3,1.7,0.6c0.8,0.4,1.4,1,1.8,1.7c1,1.7,1.8,3,2.6,4.2c0.7,1.1,1.4,2.1,2.1,3c0.7,0.9,1.4,1.8,2.1,2.8c0.6,0.7,1.2,1.3,2,1.8c0.7,0.5,1.5,0.8,2.4,1.1C48.5,58.9,49.6,59,50.7,59z M33.2,42c-0.7,0-1.3-0.1-1.7-0.3c-0.4-0.2-0.6-0.7-0.6-1.4c0-1.8,0-3.3,0-4.6c0-1.3,0-2.3,0.1-3.1c0-1.7,0.2-2.9,0.5-3.5c0.3-0.6,0.9-0.9,1.8-0.9c1.7,0,3.1,0.3,4,0.9s1.6,1.4,1.9,2.5s0.5,2.3,0.5,3.6c0,1.2-0.3,2.3-0.8,3.4c-0.5,1-1.3,1.9-2.3,2.5C35.8,41.7,34.6,42,33.2,42z M68.6,36.1c0.3,0,0.4-0.2,0.4-0.5c0-0.1,0-0.2,0-0.4c0-0.2-0.1-0.3-0.1-0.5c-0.2-0.6-0.6-1.4-1-2.3c-0.5-0.9-0.9-1.8-1.4-2.7c-0.5-0.9-0.8-1.6-1.1-2c-0.2-0.3-0.4-0.6-0.7-0.7s-0.6-0.2-0.9-0.2c-0.7,0-1.3,0.1-1.8,0.2c-0.5,0.2-0.8,0.4-0.8,0.8c0,0.2,0,0.4,0.1,0.5c0.1,0.1,0.2,0.3,0.4,0.6c0.5,0.6,1,1.3,1.7,2.1c0.7,0.8,1.3,1.6,2,2.4c0.7,0.8,1.3,1.4,1.8,1.9C67.8,35.8,68.3,36.1,68.6,36.1z M66.3,58.7c2.5,0,4.5-0.5,6.2-1.6c1.6-1,2.9-2.4,3.7-4.1s1.2-3.5,1.2-5.4c0-1.8-0.4-3.4-1.3-4.8c-0.9-1.5-2.1-2.7-3.6-3.6c-1.5-0.9-3.2-1.4-5.1-1.4c-1.5,0-2.9,0.3-4.2,0.9s-2.5,1.5-3.5,2.5c-1,1.1-1.8,2.2-2.3,3.6c-0.5,1.3-0.8,2.7-0.8,4.1c0,1.9,0.4,3.6,1.3,5c0.9,1.5,2,2.6,3.5,3.5C62.8,58.2,64.5,58.7,66.3,58.7z M67.3,57c-1.2,0-2.2-0.4-3-1.3c-0.9-0.9-1.6-2-2.1-3.5c-0.5-1.4-0.8-2.9-0.8-4.4c0-1.4,0.1-2.6,0.3-3.8c0.2-1.2,0.6-2.1,1.2-2.9c0.5-0.6,1-1,1.6-1.2c0.6-0.2,1.3-0.4,2-0.4c1.2,0,2.3,0.4,3.2,1.3c0.9,0.9,1.6,2,2.1,3.4c0.5,1.4,0.8,2.9,0.8,4.5c0,1.1-0.1,2.2-0.2,3.3c-0.1,1.1-0.4,2-0.8,2.7c-0.4,0.8-1,1.3-1.7,1.7S68.2,57,67.3,57z M80.7,58.1c0.6,0,1.2,0,1.6-0.1s0.8-0.1,1.3-0.1c0.4,0,0.9,0,1.4,0c0.6,0,1.1,0,1.5,0c0.4,0,0.8,0.1,1.3,0.1c0.4,0,1,0.1,1.6,0.1c0.2,0,0.4,0,0.6-0.1c0.2-0.1,0.3-0.2,0.3-0.4c0-0.3-0.1-0.4-0.3-0.6c-0.2-0.1-0.5-0.2-0.8-0.3c-0.5-0.2-0.9-0.3-1.4-0.5s-0.6-0.6-0.6-1.3l0,0V30c0-1.7,0.1-2.9,0.2-3.7s0.1-1.4,0.1-1.6c0-0.1,0-0.2-0.1-0.3s-0.1-0.1-0.2-0.1c-0.1,0-0.2,0-0.4,0.1c-0.5,0.2-1.1,0.4-1.7,0.7c-0.6,0.3-1.3,0.5-2.1,0.8c-0.7,0.2-1.5,0.5-2.3,0.6c-0.3,0.1-0.4,0.3-0.4,0.6c0,0.4,0.1,0.6,0.4,0.7c0.8,0.2,1.3,0.6,1.6,1.2s0.4,1.4,0.4,2.3l0,0v23.8c0,0.7-0.2,1.1-0.6,1.3c-0.4,0.2-0.9,0.4-1.3,0.5c-0.3,0.1-0.5,0.2-0.8,0.3s-0.3,0.3-0.3,0.6c0,0.2,0.1,0.3,0.3,0.4C80.3,58.1,80.5,58.1,80.7,58.1z M101.4,58.7c1.1,0,2-0.2,3-0.5c0.9-0.3,1.7-0.8,2.4-1.3c0.7-0.6,1.3-1.2,1.7-1.9c0.5-0.7,0.7-1.3,0.7-1.8c0-0.3-0.1-0.5-0.4-0.5c-0.1,0-0.2,0-0.3,0.1c-0.1,0.1-0.2,0.2-0.3,0.3c-0.7,0.7-1.4,1.2-2.2,1.6c-0.8,0.4-1.7,0.5-2.6,0.5c-1.3,0-2.5-0.3-3.5-1c-1.1-0.7-1.9-1.6-2.5-2.8c-0.6-1.2-0.9-2.5-0.9-3.9c0-0.7,0.1-1.1,0.3-1.4c0.2-0.2,0.5-0.4,0.9-0.4l0,0h9.9c1,0,1.5-0.5,1.5-1.6c0-1.2-0.3-2.3-0.9-3.2c-0.6-0.9-1.4-1.7-2.4-2.2c-1-0.5-2.2-0.8-3.5-0.8c-1.8,0-3.4,0.5-4.8,1.4c-1.5,0.9-2.6,2.2-3.5,3.8c-0.9,1.6-1.3,3.3-1.3,5.2c0,2.1,0.4,3.9,1.1,5.5s1.8,2.8,3.1,3.7C98.1,58.3,99.6,58.7,101.4,58.7z M101.5,44h-3.8c-0.4,0-0.6-0.2-0.6-0.5c0-0.6,0.2-1.3,0.7-1.9c0.4-0.6,1-1.1,1.7-1.6c0.7-0.4,1.4-0.6,2.1-0.6c1,0,1.9,0.3,2.7,0.9s1.1,1.4,1.1,2.3c0,0.3,0,0.6-0.1,0.8c-0.1,0.2-0.2,0.3-0.3,0.4c-0.4,0.1-0.9,0.2-1.4,0.2C103,44,102.4,44,101.5,44L101.5,44z"/>';
        
        parts[5] = '<text x="20" y="100" class="base">';

        parts[6] = getGenus(tokenId);

        parts[7] = '</text><text x="20" y="120" class="base">';

        parts[8] = getGender(tokenId);

        parts[9] = '</text><text x="20" y="140" class="base">';

        parts[10] = getAge(tokenId);

        parts[11] = '</text><text x="20" y="160" class="base">';

        parts[12] = getMarriage(tokenId);

        parts[13] = '</text><text x="20" y="180" class="base">';

        parts[14] = getRegional(tokenId);

        parts[15] = '</text><text x="20" y="200" class="base">';

        parts[16] = getCareer(tokenId);

        parts[17] = '</text><text x="20" y="220" class="base">';

        parts[18] = getCharacter(tokenId);
        
        parts[19] = '</text><text x="20" y="240" class="base">Lv ';

        parts[20] = getLevel(tokenId);

        parts[21] = '</text><text x="20" y="260" class="base">XP ';

        parts[22] = getXp(tokenId);

        parts[23] = '</text><text x="20" y="280" class="base">LUK+';

        parts[24] = getLucky(tokenId);

        parts[25] = "</text></svg>";

        string memory output = string(
            abi.encodePacked(
                parts[0],
                parts[1],
                parts[2],
                parts[3],
                parts[4],
                parts[5],
                parts[6]
            )
        );
        output = string(
            abi.encodePacked(
                output,
                parts[7],
                parts[8],
                parts[9],
                parts[10],
                parts[11],
                parts[12],
                parts[13]
            )
        );
        output = string(
            abi.encodePacked(
                output,
                parts[14],
                parts[15],
                parts[16],
                parts[17],
                parts[18],
                parts[19],
                parts[20],
                parts[21]
            )
        );
        output = string(
            abi.encodePacked(
                output,
                parts[22],
                parts[23],
                parts[24],
                parts[25]
            )
        );

        string memory json = Base64.encode(
            bytes(
                string(
                    abi.encodePacked(
                        '{"name": "Role(for 0xAdventure) #',
                        toString(tokenId),
                        '", "description": "0xAdventure is a guild of Dimensional Breakers. We are willing to give precious life to become a beacon for all Dimensional Breakers.", "image": "data:image/svg+xml;base64,',
                        Base64.encode(bytes(output)),
                        '"}'
                    )
                )
            )
        );
        output = string(
            abi.encodePacked("data:application/json;base64,", json)
        );

        return output;
    }

    /*
     * Pause sale if active, make active if paused
     */
    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    function claim() public nonReentrant {
        require(saleIsActive, "Sale must be active to mint Role");
        uint _next_role = next_token;
        level[_next_role] = 1;
        _safeMint(_msgSender(), _next_role);
        next_token++;
    }

    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI"s implementation - MIT license
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }