// Contract: Lore
// Target function: function claimForLoot(uint256 tokenId) public nonReentrant
Spy",
		"Tactician",
		"Torturer",
		"Warden",
		"Warmage",
		"Acolyte",
		"Archbishop",
		"Bishop",
		"Cardinal",
		"Chaplain",
		"Clergy",
		"Cleric",
		"Cultist",
		"Cult Leader",
		"Diviner",
		"Friar",
		"High Priest",
		"Inquisitor",
		"Missionary",
		"Monk",
		"Nun",
		"Paladin",
		"Pardoner",
		"Priest",
		"Prophet",
		"Sexton",
		"Templar",
		"Boatman",
		"Bosun",
		"Wagoner",
		"Caravaneer",
		"Caravan Guard",
		"Charioteer",
		"Ferryman",
		"First Mate",
		"Helmsman",
		"Navigator",
		"Purser",
		"Sailor",
		"Sea Captain",
		"Shipwright",
		"Swab"
    ];
    
	// The list of realms as of 9/1/2021 - 7AM EST.
	// Realms claimed after this date are not included.
	// Also realms with unparsable names are not included.
	// Filtered using [^\x00-\x7F] to remove all non-ASCII.
	// The realms were then chosen from that list with a 5% chance.
	// The realms listed below are the resulting list of realms.
    string[] private realms = [
		"Zarmaln",
		"Syushstes",
		"Shabe",
		"Waswashauk",
		"Onmomoton",
		"Ghieyalb",
		"Lellelnel",
		"Nitog",
		"Sqen nun San",
		"Wawanunu",
		"Nepene Zimdo",
		"Krimsismrap",
		"Tetsnonsgom",
		"Asukunis",
		"Skususskik",
		"Tohhlaheh",
		"Karssir",
		"Dashu",
		"Ulmnel",
		"ku Kubtur",
		"Kuosaupmao",
		"Sekputlukkol",
		"Toattik",
		"Vimmenponpon",
		"Nunata",
		"Lepuukewp",
		"Tipmumteh",
		"Imietietit",
		"Omonmot",
		"Menihem",
		"Ehpankonlun",
		"Hunmud",
		"Zoze Kalkal",
		"Rizhros",
		"Lim Istalkus",
		"Mupeptel",
		"Nasbrok",
		"Urnpel",
		"Tintemtemtun",
		"Ewonepil",
		"Snomeha",
		"Mammanmammas",
		"Tschin",
		"Okkamak Kom",
		"Kelokeluke",
		"Ninlamlam",
		"Wuchukkoh",
		"Winglwiq",
		"Mummon",
		"Pultilnul",
		"Tujtaerjoer",
		"Umnun",
		"Dotnob",
		"Moebnuegrua",
		"Momtonmo",
		"Pipumpaj",
		"Notket",
		"Urgmuldulmur",
		"Kis Kazkoz",
		"Kipkewm",
		"Susen Sessus",
		"Treknlun",
		"Slangpanlang",
		"Atalatat",
		"Shagimda",
		"Pamhunsnim",
		"Snussnek",
		"Tiattupsim",
		"os Umemulet",
		"Panpan",
		"tin Shlonkun",
		"Imiimmionnen",
		"Blambong",
		"Umhin Be",
		"Sviikmorkus",
		"Hrenleppek",
		"Xop-Met",
		"Onwimninon",
		"he Chichu",
		"Aupoopnauls",
		"Kekil",
		"Urongujureg",
		"Mrunvyingtis",
		"Pullelpulem",
		"Nukika",
		"Salninken",
		"Lullul",
		"she Shutiash",
		"Lutkamlaltak",
		"Nrilutok",
		"Ininni",
		"Snamnunu",
		"Kemkesmol",
		"Shnillel",
		"Bisigi",
		"Topseke",
		"Ittardunit",
		"Anip Mirkal",
		"Anbam",
		"Shkukmuk",
		"pat Lignluy",
		"Wunnin",
		"Ruxrugqaqrur",
		"Shnunhum",
		"Umap Amum",
		"Semsem",
		"Kudooklashe",
		"Kuksnot",
		"Neznisnasnis",
		"Ketlelsu",
		"seq Nliq",
		"Musdon",
		"Umootukom Up",
		"Vaenvaenraos",
		"Pitpitmirn", 
		"Lonkun", 
		"Nginjin", 
		"Temi-kem-Ned", 
		"nen-Tuntlin",
		"Ortlermurn",
		"Anotuneh"
    ];
    
    string[] private alignments = [
		"Lawful Good",
		"Neutral Good",
		"Chaotic Good",
		"Lawful Neutral",
		"Neutral",
		"Chaotic Neutral",
		"Lawful Evil",
		"Neutral Evil",
		"Chaotic Evil"
    ];
    
    string[] private pantheons = [
		"Egyptian Mythos",
		"Greek Mythos",
		"Hindu Mythos",
		"Celtic Mythos",
		"Norse Mythos",
		"Finnish Mythos",
		"Chinese Mythos",
		"Japanese Mythos",
		"Aztec Mythos",
		"Mayan Mythos",
		"Hyborea Mythos"
    ];
    
    string[] private deities = [
		"Auril, Goddess of Winter",
		"Azuth, God of Wizards",
		"Bane, God of Tyranny",
		"Beshaba, Goddess of Misfortune",
		"Bhaal, God of Murder",
		"Chauntea, Goddess of Agriculture",
		"Cyric, God of Lies",
		"Deneir, God of Writing",
		"Eldath, Goddess of Peace",
		"Gond, God of Craft",
		"Helm, God of Protection",
		"Ilmater, God of Endurance",
		"Kelemvor, God of the Dead",
		"Lathander, God of Renewal",
		"Leira, Goddess of Illusion",
		"Lliira, Goddess of Joy",
		"Loviatar, Goddess of Pain",
		"Malar, God of the Hunt",
		"Mask, God of Thieves",
		"Mielikki, Goddess of Forests",
		"Milil, God of Poetry and Song",
		"Myrkul, God of Death",
		"Mystra, Goddess of Magic",
		"Oghma, God of Knowledge",
		"Savras, god of Divination",
		"Selune, Goddess of the Moon",
		"Shar, Goddess of Darkness",
		"Silvanus, God of Wild Nature",
		"Sune, Goddess of Love",
		"Talona, Goddess of Disease",
		"Talos, God of Storms",
		"Tempus, God of War",
		"Torm, God of Courage",
		"Tymora, Goddess of Fortune",
		"Tyr, God of Justice",
		"Umberlee, Goddess of the Sea",
		"Waukeen, Goddess of Trade"
    ];
	
    string[] private races = [
        "Human",
        "Dwarf",
        "Elf",
        "Vampire",
        "Undead",
        "Goblin",
        "Demon",
        "Troll",
        "Ork",
        "Catfolk",
        "Angel",
        "Fairy",
        "Halfling",
        "Giant",
        "Lizardfolk",
        "Nymph"
    ];
    
    function random(string memory input) internal pure returns (uint256) {
        return uint256(keccak256(abi.encodePacked(input)));
    }
    
    function getOrigin(uint256 tokenId) public view returns (string memory) {
        return pluck(tokenId, "ORIGIN", origins);
    }
    
    function getRace(uint256 tokenId) public view returns (string memory) {
        return pluckRace(tokenId, "RACE");
    }
    
    function getJob(uint256 tokenId) public view returns (string memory) {
        return pluckJob(tokenId, "JOB");
    }
    
    function getRealm(uint256 tokenId) public view returns (string memory) {
        return pluckRealm(tokenId, "REALM");
    }
    
    function getAlignment(uint256 tokenId) public view returns (string memory) {
        return pluck(tokenId, "ALIGNMENT", alignments);
    }

    function getAge(uint256 tokenId) public view returns (string memory) {
        return pluckAge(tokenId, "AGE");
    }
    
    function getPantheon(uint256 tokenId) public view returns (string memory) {
        return pluck(tokenId, "PANTHEON", pantheons);
    }
	
    function getDeity(uint256 tokenId) public view returns (string memory) {
        return pluckDeity(tokenId, "DEITY");
    }
    
    function pluck(uint256 tokenId, string memory keyPrefix, string[] memory sourceArray) internal view returns (string memory) {
        uint256 rand = random(string(abi.encodePacked(keyPrefix, toString(tokenId))));
        string memory output = sourceArray[rand % sourceArray.length];
        return output;
    }
    
    function pluckAge(uint256 tokenId, string memory keyPrefix) internal view returns (string memory) {
        uint256 rand = random(string(abi.encodePacked(keyPrefix, toString(tokenId))));
        string memory output = toString(rand % 99 + 10);
        output = string(abi.encodePacked(output, " Years of Age"));
        return output;
    }
    
    function pluckRace(uint256 tokenId, string memory keyPrefix) internal view returns (string memory) {
        uint256 rand = random(string(abi.encodePacked(keyPrefix, toString(tokenId))));
        string memory output = races[rand % races.length];
        uint256 greatness = rand % 21;
		if (greatness == 0) {
            output = string(abi.encodePacked("Undesirable ", output));
        } else if (greatness > 10 && greatness < 14) {
            output = string(abi.encodePacked("Respected ", output));
        } else if (greatness >= 14 && greatness < 18) {
            output = string(abi.encodePacked("Renown ", output));
        } else if (greatness >= 18) {
            if (greatness < 20) {
                output = string(abi.encodePacked("Noble ", output));
            } else {
                output = string(abi.encodePacked("Legendary ", output));
            }
        }
        return output;
    }
    
    function pluckDeity(uint256 tokenId, string memory keyPrefix) internal view returns (string memory) {
        uint256 rand = random(string(abi.encodePacked(keyPrefix, toString(tokenId))));
        string memory output = deities[rand % deities.length];
        uint256 greatness = rand % 21;
		if (greatness == 0) {
            output = string(abi.encodePacked("Cursed by ", output));
        } else if (greatness < 14) {
            output = string(abi.encodePacked("Follower of ", output));
        } else if (greatness >= 14 && greatness < 18) {
            output = string(abi.encodePacked("Blessed by ", output));
        } else if (greatness >= 18) {
            if (greatness < 20) {
                output = string(abi.encodePacked("Chosen by ", output));
            } else {
                output = string(abi.encodePacked("Right Hand of ", output));
            }
        }
        return output;
    }
    
    function pluckJob(uint256 tokenId, string memory keyPrefix) internal view returns (string memory) {
        uint256 rand = random(string(abi.encodePacked(keyPrefix, toString(tokenId))));
        string memory output = jobs[rand % jobs.length];
        uint256 greatness = rand % 21;
		if (greatness == 0) {
            output = string(abi.encodePacked("Unskilled ", output));
        } else if (greatness > 10 && greatness < 14) {
            output = string(abi.encodePacked("Neophyte ", output));
        } else if (greatness >= 14 && greatness < 19) {
            output = string(abi.encodePacked("Journeyman ", output));
        } else if (greatness >= 19) {
            if (greatness == 19) {
                output = string(abi.encodePacked("Expert ", output));
            } else {
                output = string(abi.encodePacked("Master ", output));
            }
        }
        return output;
    }
    
    function pluckRealm(uint256 tokenId, string memory keyPrefix) internal view returns (string memory) {
        uint256 rand = random(string(abi.encodePacked(keyPrefix, toString(tokenId))));
        string memory output = realms[rand % realms.length];
        uint256 greatness = rand % 21;
		if (greatness == 0) {
            output = string(abi.encodePacked("Outcast of ", output));
        } else if (greatness > 0 && greatness <= 10) {
            output = string(abi.encodePacked("Refugee of ", output));
        } else if (greatness > 10 && greatness < 14) {
            output = string(abi.encodePacked("Serf of ", output));
        } else if (greatness >= 14 && greatness < 19) {
            output = string(abi.encodePacked("Citizen of ", output));
        } else if (greatness >= 19) {
            if (greatness == 19) {
                output = string(abi.encodePacked("Nobility of ", output));
            } else {
                output = string(abi.encodePacked("Royalty of ", output));
            }
        }
        return output;
    }

    function tokenURI(uint256 tokenId) override public view returns (string memory) {
        string[17] memory parts;
        parts[0] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: white; font-family: serif; font-size: 14px; }</style><rect width="100%" height="100%" fill="black" /><text x="10" y="20" class="base">';

        parts[1] = getOrigin(tokenId);

        parts[2] = '</text><text x="10" y="40" class="base">';

        parts[3] = getRace(tokenId);

        parts[4] = '</text><text x="10" y="60" class="base">';

        parts[5] = getJob(tokenId);

        parts[6] = '</text><text x="10" y="80" class="base">';

        parts[7] = getRealm(tokenId);

        parts[8] = '</text><text x="10" y="100" class="base">';

        parts[9] = getAlignment(tokenId);

        parts[10] = '</text><text x="10" y="120" class="base">';

        parts[11] = getAge(tokenId);

        parts[12] = '</text><text x="10" y="140" class="base">';

        parts[13] = getPantheon(tokenId);

        parts[14] = '</text><text x="10" y="160" class="base">';

        parts[15] = getDeity(tokenId);

        parts[16] = '</text></svg>';

        string memory output = string(abi.encodePacked(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6], parts[7], parts[8]));
        output = string(abi.encodePacked(output, parts[9], parts[10], parts[11], parts[12], parts[13], parts[14], parts[15], parts[16]));
        
        string memory json = Base64.encode(bytes(string(abi.encodePacked('{"name": "Lore #', toString(tokenId), '", "description": "Lore is randomized adventurer lore generated and stored on chain. Based on the popular loot token metadata, loot owners can claim their lore to match their loot.", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}'))));
        output = string(abi.encodePacked('data:application/json;base64,', json));

        return output;
    }

	// Because others need a chance too.
    function claim(uint256 tokenId) public nonReentrant {
        require(tokenId >= 8001 && tokenId < 9750, "Token ID invalid, public sales for 8001-9749.");
        _safeMint(_msgSender(), tokenId);
    }