contract JoysNFT is ERC721PresetMinterPauserAutoId, Ownable {
    using SafeMath for uint256;
    using Address for address;
    using Counters for Counters.Counter;

    // joys nft meta
    struct Meta {
        // the level of hero
        uint32 level;

        // strength
        uint32 sVal;

        // intelligence
        uint32 iVal;

        // agility
        uint32 aVal;
    }

    // mapping tokenID meta info
    mapping (uint256 => Meta) public metaSet;

    Counters.Counter private tokenIdTracker;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor (string memory name, string memory symbol) public
    ERC721PresetMinterPauserAutoId(name, symbol, "") {
    }

    /**
     * @dev public function to set the base URI for all token IDs. It is
     * automatically added as a prefix to the value returned in {tokenURI},
     * or to the token ID if {tokenURI} is empty.
     */
    function setBaseURI(string memory _baseURI) onlyOwner public {
        _setBaseURI(_baseURI);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function setRoleAdmin(bytes32 role, bytes32 adminRole) onlyOwner public {
        _setRoleAdmin(role, adminRole);
    }

    /*
    * @dev Creates a new token for `to`. Its token ID will be automatically
    * assigned (and available on the emitted {IERC721-Transfer} event), and the token
    * URI autogenerated based on the base URI passed at construction.
    */
    function mint(address _to, uint32 _level, uint32 _sVal, uint32 _iVal, uint32 _aVal) public {
        require(hasRole(MINTER_ROLE, _msgSender()), "JoysNFT: must have minter role to mint");

        _mint(_to, tokenIdTracker.current());
        metaSet[tokenIdTracker.current()] = Meta(_level, _sVal, _iVal, _aVal);
        tokenIdTracker.increment();
    }

    /*
    * @dev not supported function
    */
    function mint(address /*_to*/) public onlyOwner override(ERC721PresetMinterPauserAutoId) {
        require(false, "JoysNFT: not supported");
    }

    /*
    * @dev query special token hero info
    */
    function info(uint256 tokenId) public view returns (uint32, uint32, uint32, uint32) {
        require(_exists(tokenId), "JoysNFT: URI query for nonexistent token");

        Meta storage m = metaSet[tokenId];
        return (m.level, m.sVal, m.iVal, m.aVal);
    }
}
function mint(address _to, uint32 _level, uint32 _sVal, uint32 _iVal, uint32 _aVal) public {
    require(hasRole(MINTER_ROLE, _msgSender()), "JoysNFT: must have minter role to mint");

    _mint(_to, tokenIdTracker.current());
    metaSet[tokenIdTracker.current()] = Meta(_level, _sVal, _iVal, _aVal);
    tokenIdTracker.increment();
}

/*
 * @dev Creates a new token for `to`. Its token ID will be automatically
 * assigned (and available on the emitted {IERC721-Transfer} event), and the token
 * URI autogenerated based on the base URI passed at construction.
 */