abstract contract ERC1155Supply is ERC1155 {

    uint private _totalSupply;
    uint private _totalMinted;

    mapping(uint256 => uint256) private _totalSupplyById;
    mapping(uint256 => uint256) private _totalMintedById;

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalSupplyById(uint256 id) internal view virtual returns (uint256) {
        return _totalSupplyById[id];
    }

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalMintedById(uint256 id) internal view returns (uint256) {
        return _totalMintedById[id];
    }

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Total amount of tokens in with a given id.
     */
    function totalMinted() internal view virtual returns (uint256) {
        return _totalMinted;
    }

    /**
     * @dev Indicates whether any token exist with a given id, or not.
     */
    function exists(uint256 id) public view virtual returns (bool) {
        return ERC1155Supply.totalSupplyById(id) > 0;
    }

    /**
     * @dev See {ERC1155-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual override {
        super._beforeTokenTransfer(operator, from, to, ids, amounts, data);

        if (from == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                _totalSupplyById[ids[i]] += amounts[i];
                _totalMintedById[ids[i]] += amounts[i];
                _totalSupply += amounts[i];
                if(ids[i] < 64){
                    _totalMinted += amounts[i];
                }
            }
        }

        if (to == address(0)) {
            for (uint256 i = 0; i < ids.length; ++i) {
                _totalSupplyById[ids[i]] -= amounts[i];
                _totalSupply -= amounts[i];
            }
        }
    }
}
/**
 * @dev Extension of ERC1155 that adds tracking of total supply per id.
 *
 * Useful for scenarios where Fungible and Non-fungible tokens have to be
 * clearly identified. Note: While a totalSupply of 1 might mean the
 * corresponding is an NFT, there is no guarantees that no other token with the
 * same id are not going to be minted.
 */
function totalSupplyById(uint256 id) internal view virtual returns (uint256) {
    return _totalSupplyById[id];
}

/**
 * @dev Total amount of tokens in with a given id.
 */