Module:SkillHeroList

local Util = require('Module:Util') local HeroUtil = require 'Module:HeroUtil' local cargo = mw.ext.cargo local p = {} local List = require 'Module:ListUtil' local Hash = require 'Module:HashUtil' local escq = require 'Module:EscQ'.main1

-- unobtainable rarity value local BAD_RARITY = 5 + 1

-- breadth-first search, input node goes to index 0 local bfs = function (node, graph) local i = 0 local list = {[i] = node} local included = {[node] = true}

while true do		local current = list[i] if not current then break end i = i + 1 local neighbours = graph[current] if neighbours then for _, v in ipairs(neighbours) do				if not included[v] then list[#list + 1] = v					included[v] = true end end end end

return list end

local getPreEvolved = function (wikiName, pagename) local frame = mw.getCurrentFrame local baseWeaponQuery = cargo.query('WeaponEvolutions,Skills', 'Skills.Name=name', {		join = 'WeaponEvolutions.BaseWeapon=Skills.WikiName',		where = ("EvolvesInto='%s'"):format(escq(wikiName)),		groupBy = 'BaseWeapon',	}) if #baseWeaponQuery > 0 then local links = List.map(baseWeaponQuery, function (v)			return frame:expandTemplate{title = 'Wt', args = {v.name}}		end) local last = table.remove(links) local wepList = #links == 0 and last or (table.concat(links, ', ') .. (#links >= 2 and ', or ' or ' or ') .. last) return ('%s can be evolved from %s using the Weapon Refinery. '):format(pagename, wepList) else return '' end end

local heroList = function (args) local pagename = args[1] -- any skill from the page can be used local skillQuery = cargo.query('Skills', 'WikiName,Scategory', {		where = ("_pageName='%s'"):format(escq(pagename)),		limit = 1,	})[1] or {} local wikiName = skillQuery.WikiName or '' local cat = skillQuery.Scategory or '' local header = cat == 'weapon' and getPreEvolved(wikiName, pagename) or ''

local heroesWithSkill = cargo.query(		'Units,UnitSkills',		"Units._pageName=page,Units.WikiName=wikiname,IFNULL(CONCAT(Name,': ',Title),Name)=name", {			join = 'Units.WikiName=UnitSkills.WikiName',			where = ("skill='%s'"):format(escq(wikiName)),			groupBy = 'Units._pageName',			orderBy = "IFNULL(Properties__full,'') NOT LIKE '%%enemy%%'",			limit = 500,		}) if #heroesWithSkill == 0 then return header .. "This skill is currently not owned by any unit." end

local avail = HeroUtil.getLowestRarities {current = true}

local heroSkills = Hash.from_ipairs(heroesWithSkill, function (hero)		local lowestRarity = avail[hero.page] and avail[hero.page]:bounds or BAD_RARITY		return hero.name, List.map_self(cargo.query('UnitSkills,Skills', 'Skills.WikiName=tag,Skills.Name=name,Skills._pageName=page,defaultRarity=dr,unlockRarity=ur', {			join = 'Skills.WikiName=UnitSkills.skill',			where = ("UnitSkills.WikiName='%s' AND Scategory='%s'"):format(escq(hero.wikiname), escq(cat)),			limit = 1000,		}), function (v) v.rarity = math.max(math.min(tonumber(v.dr) or BAD_RARITY, tonumber(v.ur) or BAD_RARITY), lowestRarity) return v		end)	end)

local skillSet = {} for _, skills in pairs(heroSkills) do		for _, skill in ipairs(skills) do			skillSet[skill.tag] = true end end

local prereq_graph, after_graph = Util.getSkillChains(Hash.keys(skillSet)) local prereqs = List.reverse_self(bfs(wikiName, prereq_graph)) local afters = bfs(wikiName, after_graph) local skillOrder = Hash.invert(List.concat(prereqs, List.concat({wikiName}, afters))) Hash.map_self(heroSkills, function (skills)		local chainSkills = List.select(skills, function (skill) return skillOrder[skill.tag] end)		table.sort(chainSkills, function (lhs, rhs) return skillOrder[lhs.tag] < skillOrder[rhs.tag] end)		return chainSkills	end)

local maxColumns = math.max(0, unpack(List.map(Hash.values(heroSkills), function (skills) return #skills end)))

-- Initialize the table local tbl = mw.html.create('table') :addClass('wikitable striped sortable') :css('text-align','center')

-- Table Headers tbl:tag('th') :wikitext('Unit') tbl:tag('th') :attr('colspan', maxColumns) :wikitext('Skill chain') local RARITY_TXT = Util.getRarityTexts RARITY_TXT[BAD_RARITY] = 'N/A'

for _, hero in ipairs(heroesWithSkill) do		local cells = List.map(heroSkills[hero.name], function (skill)			return ("%s%s %s"):format(skill.page, skill.page == skill.name and '' or ('|' .. skill.name), RARITY_TXT[skill.rarity])		end)

local tr = tbl:tag('tr')

-- Hero Name tr:tag('td') :tag('div') :wikitext(Util.getHeroIcon(hero.page, '50px') .. ' ') :css('margin-top','5px') :done :tag('div') :wikitext( .. hero.name .. )

for j = 1, maxColumns do			tr:tag('td') :wikitext(cells[j] or '–') :css('min-width','80px') end end

return header .. tostring(tbl) end

return require 'Module:MakeMWModule'.makeMWModule {heroList = heroList}