Module:Item2/upgrade

--- -- -- Upgrade paths for Module:Item2 -- ---

local m_cargo = require('Module:Cargo') local m_util = require('Module:Util')

local m_game = mw.loadData('Module:Game')

-- Lazy loading local f_modifier_link -- require('Module:Modifier link').modifier_link

-- Should we use the sandbox version of our submodules? local use_sandbox = m_util.misc.maybe_sandbox

-- The cfg table contains all localisable strings and configuration, to make it -- easier to port this module to another wiki. local cfg = use_sandbox and mw.loadData('Module:Item2/config/sandbox') or mw.loadData('Module:Item2/config')

local i18n = cfg.i18n.upgrade_paths

-- -- Helper functions --

local h = {}

-- Lazy loading for Module:Modifier link function h.modifier_link(args) if not f_modifier_link then f_modifier_link = require('Module:Modifier link').main end return f_modifier_link(args) end

h.conditions = {} h.conditions.factory = {}

function h.conditions.factory.arg(args) -- Required: -- arg: The argument to check against -- One must be specified --  value: check whether the argument equals this value --  values: check whether the argument is in this list of values --  values_assoc: check whether the argument is in this associative table --   -- Optional: -- negate: negates the check against the value, i.e. whether the value is not equal or not in the list/table. if args.negate == nil then args.negate = false end -- Inner type of function depending on whether to check a single value, a list of values or an associative list of values local inner if args.value ~= nil then inner = function (tpl) return tpl == args.value end elseif args.values ~= nil then inner = function (tpl) for _, value in ipairs(args.values) do               if tpl == value then return true end end return false end elseif args.values_assoc ~= nil then inner = function(tpl) return args.values_assoc[tpl] ~= nil end else error(string.format('Missing inner comparision function. Args: %s', mw.dumpObject(args))) end -- Outer type of function depending on whether to check a single value or against a table return function (tpl_args, frame) local tpl_value = tpl_args[args.arg] local rtr if type(tpl_value) == 'table' then rtr = false for key, value in pairs(tpl_value) do               if type(key) == 'number' then rtr = rtr or inner(value) else rtr = rtr or inner(key) end end else rtr = inner(tpl_value) end if args.negate then rtr = not rtr end return rtr end end

function h.conditions.factory.league(args) return function (tpl_args, frame) for _, league in ipairs(tpl_args.drop_leagues or {}) do           if league == args.league then return true end end return false end end

h.conditions.normal = h.conditions.factory.arg{arg='rarity_id', value='normal'} h.conditions.unique = h.conditions.factory.arg{arg='rarity_id', value='unique'}

function h.conditions.item_class_has_corrupted_implicits(tpl_args, frame) local groups = { cfg.class_groups.weapons.keys, cfg.class_groups.armor.keys, cfg.class_groups.jewellery.keys, {['Quiver'] = true, ['Jewel'] = true, ['AbyssJewel'] = true}, }   for _, g in ipairs(groups) do        if h.conditions.factory.arg{arg='class_id', values_assoc=g}(tpl_args, frame) then return true end end return false end

function h.conditions.item_class_has_influences(tpl_args, frame) local groups = { cfg.class_groups.weapons.keys, cfg.class_groups.armor.keys, cfg.class_groups.jewellery.keys, {['Quiver'] = true}, }   for _, g in ipairs(groups) do        if h.conditions.factory.arg{arg='class_id', values_assoc=g}(tpl_args, frame) and h.conditions.factory.arg{arg='class_id', value='FishingRod', negate=true}(tpl_args, frame) then return true end end return false end

-- -- Additional configuration --

local c = {}

-- Default for all entries, but can be disabled by specific ones. c.automatic_upgraded_from_defaults = { is_drop_restricted = h.conditions.factory.arg{arg='is_drop_restricted', value=false}, is_corrupted = h.conditions.factory.arg{arg='is_corrupted', value=false}, is_replica = h.conditions.factory.arg{arg='is_replica', value=false}, } -- Order matters! -- Put most specific outcome at the top and the least specific at the bottom. c.automatic_upgraded_from = { --   {        defaults = {            arg_key = function (tpl_args, frame) end,        },        condition = {            function (tpl_args, frame) end,        },        text = ,        groups = {            {                name = ,                item_id = ,                amount = 0,                notes = ,            },        },    }, --   -- Item base specific --   {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Amulets/Amulet9'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.agate_amulet)) end, groups = { {               -- Lysah's Respite item_id = "Metadata/Items/DivinationCards/DivinationCardLysahsRespite", amount = 6, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Rings/Ring15'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.unset_ring)) end, groups = { {               -- The Penitent item_id = "Metadata/Items/DivinationCards/DivinationCardThePenitent", amount = 5, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Rings/Ring4'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.gold_ring)) end, groups = { {               -- Glimmer of Hope item_id = "Metadata/Items/DivinationCards/DivinationCardGlimmerOfHope", amount = 8, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Rings/Ring8'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.prismatic_ring)) end, groups = { {               -- Hope item_id = "Metadata/Items/DivinationCards/DivinationCardHope", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='metadata_id', values={'Metadata/Items/Rings/Ring12', 'Metadata/Items/Rings/Ring13', 'Metadata/Items/Rings/Ring14'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('rare', i18n.two_stone_ring)) end, groups = { {               -- Lantador's Lost Love item_id = "Metadata/Items/DivinationCards/DivinationCardLantadorsLostLove", amount = 7, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', values={'Metadata/Items/Rings/Ring12', 'Metadata/Items/Rings/Ring13', 'Metadata/Items/Rings/Ring14'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.two_stone_ring)) end, groups = { {               -- Heterochromia item_id = "Metadata/Items/DivinationCards/DivinationCardHeterochromia", amount = 2, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Weapons/OneHandWeapons/OneHandMaces/Sceptre11'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.crystal_sceptre)) end, groups = { {               -- Light and Truth (Свет и правда) item_id = "Metadata/Items/DivinationCards/DivinationCardLightAndTruth", amount = 2, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Flasks/FlaskUtility5'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.granite_flask)) end, groups = { {               -- Earth Drinker (Пьющий землю) item_id = "Metadata/Items/DivinationCards/DivinationCardEarthDrinker", amount = 5, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Armours/Helmets/HelmetStrDex10'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.nightmare_bascinet)) end, groups = { {               -- The Gladiator (Гладиатор) item_id = "Metadata/Items/DivinationCards/DivinationCardTheGladiator", amount = 5, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Belts/Belt1'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.rustic_sash)) end, groups = { {               -- The Standoff (Противоборство) item_id = "Metadata/Items/DivinationCards/DivinationCardTheStandoff", amount = 3, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Jewels/JewelTimeless'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.timeless_jewel)) end, groups = { {               -- Peaceful Moments (Безмятежные минуты) item_id = "Metadata/Items/DivinationCards/DivinationCardPeacefulMoments", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Jewels/JewelTimeless'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_two_implicit_corrupted, m_util.html.poe_color('unique', i18n.timeless_jewel)) end, groups = { {               -- The Eternal War (Вечная война) item_id = "Metadata/Items/DivinationCards/DivinationCardTheEternalWar", amount = 4, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.factory.arg{arg='base_item_id', value='Metadata/Items/Currency/CurrencyItemisedProphecy'}, function (tpl_args, frame) local patterns = {'Fated', 'AddsSpecificMod'} for _, p in ipairs(patterns) do                   if string.find(tpl_args.prophecy_id, p, 1, true) then return true end end return false end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('prophecy', i18n.fated_unique_item_prophecy)) end, groups = { {               -- Akil's Prophecy item_id = "Metadata/Items/DivinationCards/DivinationCardAkilsProphecy", amount = 3, },       },    },    --     -- Item name --    {        defaults = { is_drop_restricted = false, is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='name', value=i18n.precursors_emblem}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.precursors_emblem)) end, groups = { {               -- Remembrance (Поминовение) item_id = "Metadata/Items/DivinationCards/DivinationCardRemembrance", amount = 8, },       },    },    --     -- Item name like --    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.atziri, 1, true) end, h.conditions.factory.arg{arg='is_fated', value=false}, -- Excludes Atziri's Reflection },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, i18n.atziri))) end, groups = { {               -- The Admirer item_id = "Metadata/Items/DivinationCards/DivinationCardTheAdmirer", amount = 9, },       },    },    {        condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.doedre, 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, i18n.doedre))) end, groups = { {               -- Doedre's Madness item_id = "Metadata/Items/DivinationCards/DivinationCardDoedresMadness", amount = 9, },       },    },    {        condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.shavronne, 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, i18n.shavronne))) end, groups = { {               -- The Aesthete item_id = "Metadata/Items/DivinationCards/DivinationCardTheAesthete", amount = 8, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.rigwald, 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, i18n.rigwald))) end, groups = { {               -- The Wolf item_id = "Metadata/Items/DivinationCards/DivinationCardTheWolf", amount = 5, },       },    },    {        condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.lioneye, 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, i18n.lioneye))) end, groups = { {               -- The Lion item_id = "Metadata/Items/DivinationCards/DivinationCardTheLion", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.farrul, 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, i18n.farrul))) end, groups = { {               -- Council of Cats (Кошачий совет) item_id = "Metadata/Items/DivinationCards/DivinationCardCouncilOfCats", amount = 4, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, function (tpl_args, frame) return string.find(tpl_args.name, i18n.farrul, 1, true) or string.find(tpl_args.name, i18n.fenumus, 1, true) or string.find(tpl_args.name, i18n.saqawal, 1, true) or string.find(tpl_args.name, i18n.craiceann, 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Bestiary'].name))) end, groups = { {               -- Boon of the First Ones (Дар Первых) item_id = 'Metadata/Items/DivinationCards/DivinationCardBoonOfTheFirstOnes', amount = 6, },       },    },    --     -- League-specific items --   {        condition = { h.conditions.unique, h.conditions.factory.league{league = m_game.constants.leagues['Nemesis'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Nemesis'].name))) end, groups = { {               -- The Valkyrie item_id = "Metadata/Items/DivinationCards/DivinationCardTheValkyrie", amount = 8, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.league{league = m_game.constants.leagues['Nemesis'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Nemesis'].name))) end, groups = { {               -- The Undaunted item_id = "Metadata/Items/DivinationCards/DivinationCardTheUndaunted", amount = 5, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.league{league = m_game.constants.leagues['Beyond'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Beyond'].name))) end, groups = { {               -- The Calling item_id = "Metadata/Items/DivinationCards/DivinationCardTheCalling", amount = 6, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, h.conditions.factory.league{league = m_game.constants.leagues['Breach'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Breach'].name))) end, groups = { {               -- The Breach item_id = "Metadata/Items/DivinationCards/DivinationCardTheBreach", amount = 4, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.league{league = m_game.constants.leagues['Delve'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Delve'].name))) end, groups = { {               -- Alone in the Darkness item_id = "Metadata/Items/DivinationCards/DivinationCardAloneInTheDarkness", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, h.conditions.factory.league{league = m_game.constants.leagues['Metamorph'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', string.format(i18n.fmt.x_item, m_game.constants.leagues['Metamorph'].name))) end, groups = { {               -- Haunting Shadows (Преследующие тени) item_id = "Metadata/Items/DivinationCards/DivinationCardHauntingShadows", amount = 4, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.normal, h.conditions.factory.league{league = m_game.constants.leagues['Abyss'].name}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('rare', string.format(i18n.fmt.x_item, m_game.constants.leagues['Abyss'].name))) end, groups = { {               -- Abyssal Incubator (Инкубатор Бездны) item_id = "Metadata/Items/Currency/CurrencyIncubationAbyss", amount = 1, },       },    },    --    -- Subset of item class --   {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Jewel'}, function(tpl_args, frame) -- Get Primordial modifier from stats if tpl_args._stats.primordial_jewel_count then return true end return false end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, string.format('%s %s', m_util.html.poe_color('mod', i18n.primordial), m_util.html.poe_color('unique', i18n.jewel))) end, groups = { {               -- The Primordial (Первородный) item_id = "Metadata/Items/DivinationCards/DivinationCardThePrimordial", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='is_talisman', value=true}, h.conditions.factory.arg{arg='talisman_tier', value=1}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('rare', i18n.tier_1_talisman)) end, groups = { {               -- Call to the First Ones item_id = "Metadata/Items/DivinationCards/DivinationCardCallToTheFirstOnes", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, is_corrupted = false, },       condition = { h.conditions.factory.arg{arg='is_talisman', value=true}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, i18n.talisman) end, groups = { {               -- Primal Incubator item_id = "Metadata/Items/Currency/CurrencyIncubationTalismans", amount = 1, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, h.conditions.factory.arg{arg='tags', value='atziri1'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.sacrifice_fragment)) end, groups = { {               -- Her Mask (Её маска) item_id = "Metadata/Items/DivinationCards/DivinationCardHerMask", amount = 4, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, h.conditions.factory.arg{arg='tags', value='atziri2'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.mortal_fragment)) end, groups = { {               -- Sambodhi's Vow (Клятва Самбодхи) item_id = "Metadata/Items/DivinationCards/DivinationCardSambodhisVow", amount = 3, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'UberElderFragment', 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.uber_elder_fragment)) end, groups = { {               -- The Eldritch Decay (Аномальное увядание) item_id = "Metadata/Items/DivinationCards/DivinationCardTheEldritchDecay", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'MapFragments', 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.fragment)) end, groups = { {               -- Fragmented Incubator (Раздробленный инкубатор) item_id = "Metadata/Items/Currency/CurrencyIncubationFragments", amount = 1, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, h.conditions.factory.arg{arg='tags', value='breachstone'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.breachstone)) end, groups = { {               -- The Obscured item_id = "Metadata/Items/DivinationCards/DivinationCardTheObscured", amount = 7, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, h.conditions.factory.arg{arg='tags', value='breachstone4'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.pure_breachstone)) end, groups = { {               -- The Bargain (Сделка) item_id = "Metadata/Items/DivinationCards/DivinationCardTheBargain", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='is_essence', value=true}, h.conditions.factory.arg{arg='essence_level', value=7}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.deafening_essence), 3) end, groups = { {               -- The Cacophony item_id = "Metadata/Items/DivinationCards/DivinationCardTheCacophony", amount = 8, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='is_essence', value=true}, h.conditions.factory.arg{arg='essence_level', value=6}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.shrieking_essence), 9) end, groups = { {               -- Harmony of Souls item_id = "Metadata/Items/DivinationCards/DivinationCardHarmonyOfSouls", amount = 9, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='is_essence', value=true}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.essence), 3) end, groups = { {               -- Three Voices item_id = "Metadata/Items/DivinationCards/DivinationCardThreeVoices", amount = 3, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='is_essence', value=true}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.essence), 3) end, groups = { {               -- Whispering Incubator (Шепчущий инкубатор) item_id = "Metadata/Items/Currency/CurrencyIncubationEssence", amount = 1, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, h.conditions.factory.arg{arg='map_tier', value=5}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', string.format(i18n.fmt.tier_x_map, 5))) end, groups = { {               -- Cartographer's Delight item_id = "Metadata/Items/DivinationCards/DivinationCardCartographersDelight", amount = 3, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, h.conditions.factory.arg{arg='map_tier', value=14}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', string.format(i18n.fmt.tier_x_map, 14))) end, groups = { {               -- The Surveyor item_id = "Metadata/Items/DivinationCards/DivinationCardTheSurveyor", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, h.conditions.factory.arg{arg='map_tier', value=15}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', string.format(i18n.fmt.tier_x_map, 15))) end, groups = { {               -- Lost Worlds item_id = "Metadata/Items/DivinationCards/DivinationCardLostWorlds", amount = 8, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, h.conditions.factory.arg{arg='map_tier', value=15}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('rare', string.format(i18n.fmt.tier_x_map, 15))) end, groups = { {               -- The Trial item_id = "Metadata/Items/DivinationCards/DivinationCardTheTrial", amount = 7, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, h.conditions.factory.arg{arg='map_tier', value=16}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_unidentified_corrupted, m_util.html.poe_color('rare', string.format(i18n.fmt.tier_x_map, 16))) end, groups = { {               -- Left to Fate item_id = "Metadata/Items/DivinationCards/DivinationCardLeftToFate", amount = 4, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, h.conditions.factory.arg{arg='map_tier', value=13}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, string.format(i18n.fmt.triskaidekaphobia, m_util.html.poe_color('rare', string.format(i18n.fmt.tier_x_map, 13)))) end, groups = { {               -- Triskaidekaphobia item_id = 'Metadata/Items/DivinationCards/DivinationCardTriskaidekaphobia', amount = 13, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Active Skill Gem'}, h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.golem.tag}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.level_x_y_gem, 21, m_game.constants.item.gem_tags.golem.tag))) end, groups = { {               -- The Rite of Elements item_id = "Metadata/Items/DivinationCards/DivinationCardTheRiteOfElements", amount = 5, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.trap.tag}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_level_x_y_gem_q_z, 21, m_game.constants.item.gem_tags.trap.tag, 23))) end, groups = { {               -- Deathly Designs (Смертельные замыслы) item_id = "Metadata/Items/DivinationCards/DivinationCardDeathlyDesigns", amount = 7, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Support Skill Gem'}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('gem', string.format(i18n.fmt.level_x_y_gem, 20, m_game.constants.item.gem_tags.support.tag))) end, groups = { {               -- Gift of the Gemling Queen item_id = "Metadata/Items/DivinationCards/DivinationCardGiftOfTheGemlingQueen", amount = 9, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Support Skill Gem'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_x_gem_q_y, m_game.constants.item.gem_tags.support.tag, 23))) end, groups = { {               -- Dialla's Subjugation item_id = "Metadata/Items/DivinationCards/DivinationCardDiallasSubjugation", amount = 7, },       },    },    {        defaults = { is_drop_restricted = false, is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Support Skill Gem'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'Plus', 1, true) end, h.conditions.factory.arg{arg='max_level', value=5}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_level_x_support_plus_gem_q_y, 6, 20))) end, groups = { {               -- The Cheater (Ловкач) item_id = "Metadata/Items/DivinationCards/DivinationCardTheCheater", amount = 3, },       },    },    {        defaults = { is_drop_restricted = false, is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Support Skill Gem'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'Plus', 1, true) end, h.conditions.factory.arg{arg='max_level', value=5}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_level_x_support_plus_gem_q_y, 6, 23))) end, groups = { {               -- Desecrated Virtue (Осквернённая добродетель) item_id = "Metadata/Items/DivinationCards/DivinationCardDesecratedVirtue", amount = 9, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.chaos.tag}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function(tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_level_x_y_gem_q_z, 21, m_game.constants.item.gem_tags.chaos.tag, 23))) end, groups = { {               -- The Bitter Blossom (Колючее соцветие) item_id = "Metadata/Items/DivinationCards/DivinationCardTheBitterBlossom", amount = 3, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Active Skill Gem'}, h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.vaal.tag}, },       text = function(tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_x_gem_q_y, m_game.constants.item.gem_tags.vaal.tag, 20))) end, groups = { {               -- Volatile Power item_id = "Metadata/Items/DivinationCards/DivinationCardVolatilePower", amount = 9, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, h.conditions.factory.arg{arg='max_level', value=20}, function (tpl_args, frame) return tpl_args._flags.is_alt_quality_gem == true -- Flag is set in Module:Skill end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('gem', string.format(i18n.fmt.alt_level_x_gem_q_y, 19, 19))) end, groups = { {               -- Dying Anguish (Смертельная тоска) item_id = "Metadata/Items/DivinationCards/DivinationCardDyingAnguish", amount = 8, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_gem))) end, groups = { {               -- Gemcutter's Incubator (Инкубатор камнереза) item_id = "Metadata/Items/Currency/CurrencyIncubationGemLow", amount = 1, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'Scarab', 1, true) end, h.conditions.factory.arg{arg='tags', value='gilded_scarab'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.gilded_scarab)) end, groups = { {               -- More is Never Enough item_id = "Metadata/Items/DivinationCards/DivinationCardMoreIsNeverEnough", amount = 7, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'Scarab', 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.scarab)) end, groups = { {               -- Cameria's Cut item_id = "Metadata/Items/DivinationCards/DivinationCardCameriasCut", amount = 2, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='MapFragment'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'Scarab', 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.scarab)) end, groups = { {               -- Skittering Incubator item_id = "Metadata/Items/Currency/CurrencyIncubationScarabs", amount = 1, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='StackableCurrency'}, h.conditions.factory.arg{arg='tags', value='breachstone_splinter'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.breachstone_splinter), 5) end, groups = { {               -- The Puzzle (Головоломка) item_id = "Metadata/Items/DivinationCards/DivinationCardThePuzzle", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='StackableCurrency'}, h.conditions.factory.arg{arg='tags', value='quality_currency'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.quality_currency), 20) end, groups = { {               -- The Master Artisan (Мастер-ремесленник) item_id = "Metadata/Items/DivinationCards/DivinationCardTheMasterArtisan", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='StackableCurrency'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'CurrencyDelve', 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_amount, m_util.html.poe_color('currency', i18n.fossil), 5) end, groups = { {               -- The Tinkerer's Table (Верстак умельца) item_id = "Metadata/Items/DivinationCards/DivinationCardTheTinkerersTable", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='StackableCurrency'}, function (tpl_args, frame) return tpl_args.metadata_id and string.find(tpl_args.metadata_id, 'CurrencyDelve', 1, true) end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('currency', i18n.fossil)) end, groups = { {               -- Fossilised Incubator (Ископаемый инкубатор) item_id = "Metadata/Items/Currency/CurrencyIncubationFossils", amount = 1, },       },    },    --    -- Single item class --   {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='UniqueFragment'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.harbinger_fragment)) end, groups = { {               -- The Messenger item_id = "Metadata/Items/DivinationCards/DivinationCardTheMessenger", amount = 4, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Body Armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.body_armour)) end, groups = { {               -- The Body item_id = "Metadata/Items/DivinationCards/DivinationCardTheBody", amount = 4, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Shield'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.shield)) end, groups = { {               -- The Mercenary item_id = "Metadata/Items/DivinationCards/DivinationCardTheMercenary", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Helmet'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_two_veiled, m_util.html.poe_color('rare', i18n.helmet)) end, groups = { {               -- The Journalist (Журналист) item_id = "Metadata/Items/DivinationCards/DivinationCardTheJournalist", amount = 10, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Helmet'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_eternal_labyrinth_enchantment, m_util.html.poe_color('unique', i18n.helmet)) end, groups = { {               -- Divine Justice (Божественное правосудие) item_id = "Metadata/Items/DivinationCards/DivinationCardDivineJustice", amount = 1, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Claw'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.claw)) end, groups = { {               -- The Wolverine item_id = "Metadata/Items/DivinationCards/DivinationCardTheWolverine", amount = 4, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', values={'Dagger', 'Rune Dagger'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.dagger)) end, groups = { {               -- Assassin's Favour item_id = "Metadata/Items/DivinationCards/DivinationCardAssassinsFavour", amount = 9, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Sceptre'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_shaper, m_util.html.poe_color('magic', string.format('%s %s', i18n.sceptre, h.modifier_link{id='LocalIncreasedAttackSpeed8'}))) end, groups = { {               -- The Lord of Celebration item_id = "Metadata/Items/DivinationCards/DivinationCardTheLordOfCelebration", amount = 4, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Bow'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.bow)) end, groups = { {               -- Hunter's Resolve item_id = "Metadata/Items/DivinationCards/DivinationCardHuntersResolve", amount = 8, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Jewel'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.jewel)) end, groups = { {               -- The Garish Power item_id = "Metadata/Items/DivinationCards/DivinationCardTheGarishPower", amount = 4, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Jewel'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.jewel)) end, groups = { {               -- The Eye of the Dragon item_id = "Metadata/Items/DivinationCards/DivinationCardTheEyeOfTheDragon", amount = 10, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Jewel'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='PercentIncreasedLifeJewel'}, i18n.jewel))) end, groups = { {               -- Shard of Fate (Осколок рока) item_id = "Metadata/Items/DivinationCards/DivinationCardShardOfFate", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Jewel'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', i18n.jewel, h.modifier_link{id='CriticalStrikeMultiplierJewel'}))) end, groups = { {               -- The Mountain (Гора) item_id = "Metadata/Items/DivinationCards/DivinationCardTheMountain", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Amulet'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='IncreasedEnergyShieldPercent7'}, i18n.amulet))) end, groups = { {               -- The Sigil item_id = "Metadata/Items/DivinationCards/DivinationCardTheSigil", amount = 3, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Amulet'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('rare', i18n.amulet)) end, groups = { {               -- The Warden item_id = "Metadata/Items/DivinationCards/DivinationCardTheWarden", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Ring'}, function (tpl_args, frame) return tpl_args.drop_level <= 83 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 83, m_util.html.poe_color('magic', string.format('%s %s', i18n.ring, h.modifier_link{id='ChaosResist6'}))) end, groups = { {               -- The Lord in Black item_id = "Metadata/Items/DivinationCards/DivinationCardTheLordInBlack", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Ring'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 100, m_util.html.poe_color('rare', i18n.ring)) end, groups = { {               -- The Opulent item_id = "Metadata/Items/DivinationCards/DivinationCardTheOpulecent", amount = 5, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Ring'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.ring)) end, groups = { {               -- Hubris item_id = "Metadata/Items/DivinationCards/DivinationCardHubris", amount = 5, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Ring'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.ring)) end, groups = { {               -- Blind Venture item_id = "Metadata/Items/DivinationCards/DivinationCardBlindVenture", amount = 7, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Belt'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.belt)) end, groups = { {               -- The Wretched item_id = "Metadata/Items/DivinationCards/DivinationCardTheWretched", amount = 6, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Map'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.map)) end, groups = { {               -- The Encroaching Darkness item_id = "Metadata/Items/DivinationCards/DivinationCardTheEncroachingDarkness", amount = 8, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Map'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.map)) end, groups = { {               -- Otherworldly Incubator item_id = "Metadata/Items/Currency/CurrencyIncubationUniqueMaps", amount = 8, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Wand'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.wand)) end, groups = { {               -- The Traitor item_id = "Metadata/Items/DivinationCards/DivinationCardTheTraitor", amount = 4, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', values={'Staff', 'Warstaff'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.staff)) end, groups = { {               -- The Tower item_id = "Metadata/Items/DivinationCards/DivinationCardTheTower", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Staff', 'Warstaff'}}, h.conditions.factory.arg{arg='tags', value='small_staff', negate=true}, -- Small staves excluded because they don't have enough sockets function (tpl_args, frame) return tpl_args.drop_level <= 66 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_link_item_level_y, 5, 66, m_util.html.poe_color('normal', i18n.staff)) end, groups = { {               -- The Flora's Gift item_id = "Metadata/Items/DivinationCards/DivinationCardTheFlorasGift", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Staff', 'Warstaff'}}, h.conditions.factory.arg{arg='tags', value='small_staff', negate=true}, -- Small staves excluded because they don't have enough sockets function (tpl_args, frame) return tpl_args.drop_level <= 55 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_link_item_level_y, 6, 55, m_util.html.poe_color('normal', i18n.staff)) end, groups = { {               -- The Dark Mage item_id = "Metadata/Items/DivinationCards/DivinationCardTheDarkMage", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Body Armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_link_item_level_y, 6, 100, m_util.html.poe_color('normal', i18n.body_armour)) end, groups = { {               -- The Dapper Prodigy item_id = "Metadata/Items/DivinationCards/DivinationCardTheDapperProdigy", amount = 6, },       },    },        {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Body Armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_link_item_level_y_random_influenced, 6, 100, m_util.html.poe_color('normal', i18n.body_armour)) end, groups = { {               -- Draped in Dreams (Облачённый в мечты) item_id = "Metadata/Items/DivinationCards/DivinationCardDrapedInDreams", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Body Armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_link, 6, m_util.html.poe_color('normal', i18n.body_armour)) end, groups = { {               -- The Chains that Bind item_id = "Metadata/Items/DivinationCards/DivinationCardTheChainsThatBind", amount = 11, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Body Armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_x_link, 6, m_util.html.poe_color('normal', i18n.body_armour)) end, groups = { {               -- Geomancer's Incubator (Инкубатор геоманта) item_id = "Metadata/Items/Currency/CurrencyIncubationArmour6Linked", amount = 1, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Body Armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 100, m_util.html.poe_color('rare', i18n.body_armour)) end, groups = { {               -- Destined to Crumble item_id = "Metadata/Items/DivinationCards/DivinationCardDestinedToCrumble", amount = 5, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('normal', i18n.map)) end, groups = { {               -- Boundless Realms item_id = "Metadata/Items/DivinationCards/DivinationCardBoundlessRealms", amount = 4, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Map'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('rare', i18n.map)) end, groups = { {               -- The Explorer item_id = "Metadata/Items/DivinationCards/DivinationCardTheExplorer", amount = 6, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', value='Gloves'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.gloves)) end, groups = { {               -- Mitts item_id = "Metadata/Items/DivinationCards/DivinationCardMitts", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='DivinationCard'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('divination', i18n.divination_card)) end, groups = { {               -- The Gambler item_id = "Metadata/Items/DivinationCards/DivinationCardTheGambler", amount = 5, },       },    },    {        defaults = { is_drop_restricted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='DivinationCard'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('divination', i18n.divination_card)) end, groups = { {               -- Stacked Deck item_id = "Metadata/Items/DivinationCards/DivinationCardDeck", amount = 1, },       },    },    --    -- Multiple item classes --   {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', values={'One Hand Axe', 'Two Hand Axe'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.axe)) end, groups = { {               -- The Battle Born item_id = "Metadata/Items/DivinationCards/DivinationCardTheBattleBorn", amount = 5, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', value='Active Skill Gem'}, h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.aura.tag}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.level_x_y_gem, 21, m_game.constants.item.gem_tags.aura.tag))) end, groups = { {               -- The Wilted Rose item_id = "Metadata/Items/DivinationCards/DivinationCardTheWiltedRose", amount = 7, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('gem', string.format(i18n.fmt.level_x_gem, 20))) end, groups = { {               -- The Fox item_id = "Metadata/Items/DivinationCards/DivinationCardTheFox", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.minion.tag}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_x_gem_q_y, m_game.constants.item.gem_tags.minion.tag, 20))) end, groups = { {               -- The Summoner item_id = "Metadata/Items/DivinationCards/DivinationCardTheSummoner", amount = 6, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, -- since this is checking against an array, it will check if it contains the "Spell" value h.conditions.factory.arg{arg='gem_tags', value=m_game.constants.item.gem_tags.spell.tag}, h.conditions.factory.arg{arg='max_level', value=20}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('gem', string.format(i18n.fmt.level_x_y_gem, 21, m_game.constants.item.gem_tags.spell.tag))) end, groups = { {               --The Cataclysm item_id = "Metadata/Items/DivinationCards/DivinationCardTheCataclysm", amount = 13, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.gems.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('gem', string.format(i18n.fmt.superior_gem_q_x, 20))) end, groups = { {               -- Gemcutter's Promise item_id = "Metadata/Items/DivinationCards/DivinationCardGemcuttersPromise", amount = 3, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.armor.keys}, h.conditions.factory.arg{arg='tags', value='int_armour'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='LocalIncreasedEnergyShieldPercentAndStunRecovery6'}, i18n.armour))) end, groups = { {               -- The Inoculated item_id = "Metadata/Items/DivinationCards/DivinationCardTheInoculated", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.armor.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', i18n.life, i18n.armour))) end, groups = { {               -- The Carrion Crow item_id = "Metadata/Items/DivinationCards/DivinationCardTheCarrionCrow", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.jewellery.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_shaper_item_level_x, 100, m_util.html.poe_color('rare', i18n.jewellery)) end, groups = { {               -- Perfection item_id = "Metadata/Items/DivinationCards/DivinationCardPerfection", amount = 5, },       },    },    {        condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.jewellery.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.jewellery)) end, groups = { {               -- The Cache (Тайник) item_id = "Metadata/Items/DivinationCards/DivinationCardTheCache", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.jewellery.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_two_influenced_item_level_x, 86, m_util.html.poe_color('rare', i18n.jewellery)) end, groups = { {               -- The Awakened (Пробуждённые) item_id = "Metadata/Items/DivinationCards/DivinationCardTheAwakened", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.jewellery.keys}, function (tpl_args, frame) return tpl_args.drop_level <= 79 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 79, m_util.html.poe_color('rare', i18n.jewellery)) end, groups = { {               -- The Lover item_id = "Metadata/Items/DivinationCards/DivinationCardTheLover", amount = 2, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Ring', 'Amulet'}}, function (tpl_args, frame) return tpl_args.drop_level <= 85 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 85, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='ReduceGlobalFlatManaCostStrIntMasterVendor'}, i18n.jewellery))) end, groups = { {               -- Blessing of God item_id = "Metadata/Items/DivinationCards/DivinationCardBlessingOfGod", amount = 3, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Ring', 'Amulet'}}, function (tpl_args, frame) return tpl_args.drop_level <= 76 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 76, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='AddedLightningDamage9'}, i18n.jewellery))) end, groups = { {               --Struck by Lightning item_id = "Metadata/Items/DivinationCards/DivinationCardStruckByLightning", amount = 3, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.jewellery.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_shaper_hunter_item_level_x, 100, m_util.html.poe_color('magic', string.format('%s %s', i18n.jewellery, h.modifier_link{id='GrantsCatAspectCrafted'}))) end, groups = { {               -- A Familiar Call (Знакомый зов) item_id = "Metadata/Items/DivinationCards/DivinationCardAFamiliarCall", amount = 3, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Two Hand Sword', 'Two Hand Axe', 'Two Hand Mace', 'Staff', 'Bow', 'Warstaff'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 100, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='LocalIncreasedPhysicalDamagePercent8'}, i18n.two_hand_weapon))) end, groups = { {               -- Merciless Armament item_id = "Metadata/Items/DivinationCards/DivinationCardMercilessArmament", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Thrusting One Hand Sword', 'One Hand Sword', 'One Hand Axe', 'One Hand Mace', 'Sceptre', 'Dagger', 'Claw', 'Wand', 'Rune Dagger'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_two_influenced_item_level_x, 100, m_util.html.poe_color('rare', i18n.one_hand_weapon)) end, groups = { {               -- Prometheus' Armoury (Кузня Прометея) item_id = "Metadata/Items/DivinationCards/DivinationCardPrometheusArmoury", amount = 6, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Thrusting One Hand Sword', 'One Hand Sword', 'One Hand Axe', 'One Hand Mace', 'Sceptre', 'Dagger', 'Claw', 'Wand', 'Rune Dagger'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 100, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='LocalIncreasedPhysicalDamagePercent8'}, i18n.one_hand_weapon))) end, groups = { {               -- The Jester item_id = "Metadata/Items/DivinationCards/DivinationCardTheJester", amount = 9, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values={'Sceptre', 'Wand', 'Rune Dagger'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 100, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='SpellDamageOnWeapon8_'}, i18n.one_hand_weapon))) end, groups = { {               -- The Road to Power item_id = "Metadata/Items/DivinationCards/DivinationCardTheRoadToPower", amount = 7, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', values={'Thrusting One Hand Sword', 'One Hand Sword', 'Two Hand Sword'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.sword)) end, groups = { {               -- The Gentleman item_id = "Metadata/Items/DivinationCards/DivinationCardTheGentleman", amount = 4, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.weapons.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_item_level_x, 100, m_util.html.poe_color('magic',string.format('%s %s', h.modifier_link{id='LocalIncreasedPhysicalDamagePercent8'}, i18n.weapon))) end, groups = { {               -- The Tyrant item_id = "Metadata/Items/DivinationCards/DivinationCardTheTyrant", amount = 9, },       },    },    {        condition = { h.conditions.normal, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.weapons.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', i18n.weapon, h.modifier_link{id='StrIntMasterItemGenerationCanHaveMultipleCraftedMods'}))) end, groups = { {               -- The Web item_id = "Metadata/Items/DivinationCards/DivinationCardTheWeb", amount = 8, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.factory.arg{arg='class_id', values_assoc=cfg.class_groups.weapons.keys}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_corrupted, m_util.html.poe_color('unique', i18n.weapon)) end, groups = { {               -- Atziri's Arsenal item_id = "Metadata/Items/DivinationCards/DivinationCardAtzirisArsenal", amount = 4, },       },    },    {        condition = { h.conditions.normal, -- specifically exclude crit flasks h.conditions.factory.arg{arg='class_id', values={'LifeFlask', 'ManaFlask', 'HybridFlask', 'UtilityFlask'}}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('magic', string.format('%s %s', h.modifier_link{id='FlaskChanceRechargeOnCrit1'}, i18n.flask))) end, groups = { {               -- The Surgeon item_id = "Metadata/Items/DivinationCards/DivinationCardTheSurgeon", amount = 4, },       },    },    {        condition = { h.conditions.unique, h.conditions.item_class_has_corrupted_implicits, h.conditions.item_class_has_influences, function (tpl_args, frame) return tpl_args.drop_leagues ~= nil and #tpl_args.drop_leagues ~= 0 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_two_implicit_corrupted_two_influenced_item_level_x, 97, m_util.html.poe_color('unique', i18n.league_specific_item)) end, groups = { {               -- Fateful Meeting (Судьбоносная встреча) item_id = "Metadata/Items/DivinationCards/DivinationCardFatefulMeeting", amount = 9, },       },    },    {        condition = { h.conditions.unique, h.conditions.item_class_has_influences, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_influenced, m_util.html.poe_color('unique', i18n.item)) end, groups = { {               -- Prejudice (Предрассудки) item_id = "Metadata/Items/DivinationCards/DivinationCardPrejudice", amount = 7, },       },    },    {        defaults = { is_corrupted = false, },       condition = { h.conditions.unique, h.conditions.item_class_has_corrupted_implicits, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_two_implicit_corrupted, m_util.html.poe_color('unique', i18n.item)) end, groups = { {               -- Arrogance of the Vaal item_id = "Metadata/Items/DivinationCards/DivinationCardArroganceOfTheVaal", amount = 8, },       },    },    --    -- Generic items --   {        condition = { h.conditions.unique, function (tpl_args, frame) return tpl_args.drop_leagues ~= nil and #tpl_args.drop_leagues ~= 0 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.league_specific_item)) end, groups = { {               -- Time-Lost Relic item_id = "Metadata/Items/DivinationCards/DivinationCardTimeLostRelic", amount = 10, },       },    },    {        condition = { h.conditions.unique, function (tpl_args, frame) return tpl_args.drop_leagues ~= nil and #tpl_args.drop_leagues ~= 0 end, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.league_specific_item)) end, groups = { {               -- Time-Lost Incubator (Затерянный во времени инкубатор) item_id = "Metadata/Items/Currency/CurrencyIncubationUniqueLeague", amount = 1, },       },    },    {        condition = { h.conditions.normal, -- should exclude all items that can't be rare h.conditions.factory.arg{arg='drop_rarities_ids', value='rare'}, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random_elder_item_level_x, 100, m_util.html.poe_color('rare', i18n.item)) end, groups = { {               -- The Hale Heart item_id = "Metadata/Items/DivinationCards/DivinationCardTheHaleHeart", amount = 4, },       },    },    {        condition = { h.conditions.unique, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.item)) end, groups = { {               -- Jack in the Box item_id = "Metadata/Items/DivinationCards/DivinationCardJackInTheBox", amount = 4, },       },    },    {        condition = { h.conditions.unique, },       text = function (tpl_args, frame) return string.format(i18n.fmt.random, m_util.html.poe_color('unique', i18n.item)) end, groups = { {               -- Singular Incubator (Необычный инкубатор) item_id = "Metadata/Items/Currency/CurrencyIncubationUniques", amount = 1, },       },    },    -- TODO: The void? }

-- -- Exported functions --

local p = {}

function p.process_upgraded_from(tpl_args, frame) local query_data = { id = {}, name = {}, page = {}, }   local sets = {} --    -- Manual data --    local setid = #sets + 1 local set repeat local prefix = string.format('upgraded_from_set%s_', setid) local groupid = 1 local group set = { groups = {}, text = m_util.cast.text(tpl_args[prefix .. 'text']), automatic = false, }       repeat local group_prefix = string.format('%sgroup%s_', prefix, groupid) group = { item_name = tpl_args[group_prefix .. 'item_name'], item_id = tpl_args[group_prefix .. 'item_id'], item_page = tpl_args[group_prefix .. 'item_page'], amount = tonumber(tpl_args[group_prefix .. 'amount']), notes = m_util.cast.text(tpl_args[group_prefix .. 'notes']), }           if group.item_name ~= nil or group.item_id ~= nil or group.item_page ~= nil then if group.amount == nil then error(string.format(i18n.errors.missing_amount, group_prefix .. 'amount')) else for key, array in pairs(query_data) do                       local value = group['item_' .. key] if value then if array[value] then table.insert(array[value], {setid, groupid}) else array[value] = {{setid, groupid}, } end end end set.groups[#set.groups+1] = group end end groupid = groupid + 1 until group.item_name == nil and group.item_id == nil and group.item_page == nil -- set was empty, can terminate safely if #set.groups == 0 then set = nil else setid = setid + 1 sets[#sets+1] = set end until set == nil --    -- Automatic --    --    --  maps --   local automatic_index = #sets + 1 -- TODO: 3.9.0 Unsure how this works yet, so disabled for now --if tpl_args.atlas_connections and tpl_args.rarity_id == "normal" then       local results = m_cargo.query(            {'items', 'maps'},            {'items._pageName',  'items.name'},            {                join='items._pageID=maps._pageID',                where=string.format('items.class_id = "Map" AND items.rarity_id = "normal" AND maps.tier < %s AND items._pageName IN ("%s")', tpl_args.map_tier, table.concat(tpl_args.atlas_connections, '", "')),            }        )        for _, row in ipairs(results) do            sets[ --   -- oils --   if tpl_args._flags.is_blight_item and tpl_args.blight_item_tier > 1 then local results = m_cargo.query(           {'items', 'blight_items'},            {'items._pageName',  'items.name'},            {                join='items._pageID=blight_items._pageID',                where=string.format('blight_items.tier = %s', tpl_args.blight_item_tier - 1),            }        ) for _, row in ipairs(results) do           sets[#sets+1] = { text = nil, groups = { {                       item_name = row['items.name'], item_page = row['items._pageName'], amount = 3, notes = nil, },               },                automatic = true, }       end end --   -- essences --   -- exclude remnant of corruption via type if tpl_args.is_essence and tpl_args.essence_type > 0 then local results = m_cargo.query(           {'items', 'essences'},            {                'items._pageName',                  'items.name',                 'items.metadata_id',                'essences.category',                'essences.type',            },            {                join='items._pageID=essences._pageID',                where=string.format(                        (essences.category="%s" AND essences.level = %s)                        OR (essences.type = %s AND essences.level = %s)                        OR items.metadata_id = 'Metadata/Items/Currency/CurrencyCorruptMonolith'                        OR (%s = 6 AND essences.type = 5 AND essences.level >= 5)                     , tpl_args.essence_category, tpl_args.essence_level - 1, tpl_args.essence_type - 1, tpl_args.essence_level, -- special case for corruption only essences tpl_args.essence_type ),               orderBy='essences.level ASC, essences.type ASC',            }        ) local remnant = results[1] if remnant['items.metadata_id'] ~= 'Metadata/Items/Currency/CurrencyCorruptMonolith' then error(string.format('Something went seriously wrong here. Got results: %s', mw.dumpObject(results))) end for i=2, #results do           local row = results[i] if row['essences.category'] == tpl_args.essence_category then -- 3 to 1 recipe sets[#sets+1] = { automatic = true, text = nil, groups = { {                           item_id = row['items.metadata_id'], item_page = row['items._pageName'], item_name = row['items.name'], amount = 3, },                   },                }                -- corruption +1 sets[#sets+1] = { automatic = true, text = i18n.essence_plus_one_level, groups = { {                           item_id = row['items.metadata_id'], item_page = row['items._pageName'], item_name = row['items.name'], amount = 1, },                       {                            item_id = remnant['items.metadata_id'], item_page = remnant['items._pageName'], item_name = remnant['items.name'], amount = 1, },                   },                }            elseif tonumber(row['essences.type']) == tpl_args.essence_type - 1 then -- corruption type change sets[#sets+1] = { automatic = true, text = i18n.essence_type_change, groups = { {                           item_id = row['items.metadata_id'], item_page = row['items._pageName'], item_name = row['items.name'], amount = 1, },                       {                            item_id = remnant['items.metadata_id'], item_page = remnant['items._pageName'], item_name = remnant['items.name'], amount = 1, },                   },                }            end end end -- data based on mapping if tpl_args.drop_enabled and not tpl_args.upgraded_from_disabled then for _, data in ipairs(c.automatic_upgraded_from) do           data.defaults = data.defaults or {} local continue = true for key, value in pairs(c.automatic_upgraded_from_defaults) do               local func local v = data.defaults[key] if v == false then -- check is disabled specifically, continue elseif v == nil then func = value elseif type(v) == 'function' then func = v               else error(string.format('Invalid value for defaults at data %s', mw.dumpObject(data))) end if func then continue = func(tpl_args, frame) and continue if not continue then break end end end for _, condition in ipairs(data.condition) do               continue = condition(tpl_args, frame) and continue if not continue then break end end if continue then sets[#sets+1] = { automatic = true, text = data.text(tpl_args, frame), groups = data.groups, }               for groupid, row in ipairs(data.groups) do                    if query_data['id'][row.item_id] then table.insert(query_data['id'][row.item_id], {#sets, groupid}) else query_data['id'][row.item_id] = {{#sets, groupid}, } end end end end end if #sets == 0 then return end --   -- Fetch item data in a single query to sacrifice database load with a lot of upgraded_from references --   local query_data_array = { id = {}, name = {}, page = {}, }   local query_fields = { id = 'items.metadata_id', page = 'items._pageName', name = 'items.name', }   local where = {} local expected_count = 0 for key, thing_array in pairs(query_data) do       for thing, _ in pairs(thing_array) do            table.insert(query_data_array[key], thing) end if #query_data_array[key] > 0 then expected_count = expected_count + #query_data_array[key] local q_data = table.concat(query_data_array[key], '", "') table.insert(where, string.format('%s IN ("%s")', query_fields[key], q_data)) end end local results = m_cargo.query(       {'items'},        {'items._pageName',  'items.name', 'items.metadata_id'},        {            where=table.concat(where, ' OR '),        }    ) for _, row in ipairs(results) do       for key, thing_array in pairs(query_data) do            local set_groups = thing_array[row[query_fields[key]]] if set_groups then for _, set_group in ipairs(set_groups) do                   local entry = sets[set_group[1]].groups[set_group[2]] for entry_key, data_key in pairs(query_fields) do                       -- metadata_id may be nil, since we don't know them for unique items if row[data_key] then entry['item_' .. entry_key] = row[data_key] end end end -- set this to nil for error checking in later step thing_array[row[query_fields[key]]] = nil end end end -- sbow the broken references if needed if #results ~= expected_count then -- query data was pruned of existing keys earlier, so only broken keys remain for key, array in pairs(query_data) do           for thing, set_groups in pairs(array) do                for _, set_group in ipairs(set_groups) do                    tpl_args._flags.broken_upgraded_from_reference = true tpl_args._errors[#tpl_args._errors+1] = string.format(i18n.errors.upgraded_from_broken_reference, string.format('upgraded_from_set%s_group%s_item_%s', set_group[1], set_group[2], key), thing) end end end end --   -- Check for duplicates --   local delete_sets = {} for i=automatic_index, #sets do       for j=1, automatic_index-1 do            if #sets[i].groups == #sets[j].groups then local match = true for row_id, row in ipairs(sets[i].groups) do                   -- Only the fields from the database query are matched since we can be sure they're correct. Other fields may be subject to user error. for _, key in ipairs({'item_id', 'item_name', 'item_page'}) do                        match = match and (row[key] == sets[j].groups[row_id][key]) end end if match then tpl_args._flags.duplicate_upgraded_from_reference = true tpl_args._errors[#tpl_args._errors+1] = string.format(i18n.errors.upgraded_from_duplicate, j)                   delete_sets[#delete_sets+1] = j                 end end end end for offset, index in ipairs(delete_sets) do       table.remove(sets, index-(offset-1)) end --   -- Set data --    tpl_args.upgrade_from_sets = sets -- set upgraded_from data for i, set in ipairs(sets) do       tpl_args._subobjects[#tpl_args._subobjects+1] = { _table = 'upgraded_from_sets', set_id = i,           text = set.text, automatic = set.automatic, }       for j, group in ipairs(set.groups) do            tpl_args._subobjects[#tpl_args._subobjects+1] = { _table = 'upgraded_from_groups', group_id = j,               set_id = i,                item_name = group.item_name, item_id = group.item_id, item_page = group.item_page, amount = group.amount, notes = group.notes, }       end end end

-- -- Debugging --

function p.debug_validate_auto_upgraded_from(frame) frame = m_util.misc.get_frame(frame) local q = {} local chk = {} for _, data in ipairs(c.automatic_upgraded_from) do       for _, group in ipairs(data.groups) do            q[#q+1] = group.item_id chk[group.item_id] = { amount=group.amount, text=data.text({}, frame), }       end end local results = m_cargo.array_query{ tables={'items', 'stackables'}, fields={'items.name', 'items.class_id', 'items.description', 'stackables.stack_size'}, id_field='items.metadata_id', id_array=q, query={ join='items._pageName=stackables._pageName', },   }    for _, row in ipairs(results) do        if row['items.class_id'] == 'DivinationCard' and chk[row['items.metadata_id']].amount ~= tonumber(row['stackables.stack_size']) then mw.logObject(string.format('Amount mismatch %s, expected %s', row['items.metadata_id'], row['stackables.stack_size'])) end end tbl = mw.html.create('table') tbl:attr('class', 'wikitable sortable') for _, row in ipairs(results) do       tbl :tag('tr') :tag('td') :wikitext(row['items.name']) :done :tag('td') :wikitext(chk[row['items.metadata_id']].text) :done :tag('td') :wikitext(row['items.description']) :done :done end return tostring(tbl) end

return p