Module:CharacterTier
From Another Eden Wiki
Documentation for this module may be created at Module:CharacterTier/doc
local p = {}
local ROW_GRANULARITY = 0.5
local rate_dict = {
["10"] = "SS",
["9.5"] = "S+",
["9.0"] = "S",
["8.5"] = "S-",
["8.0"] = "A",
["7.5"] = "B",
["7.0"] = "C",
["6.0"] = "D",
["5.0"] = "D-"
}
local team_dict = {
["Fire"] = "Fire",
["Water"] = "Water",
["Earth"] = "Earth",
["Wind"] = "Wind",
["Slash"] = "Slash",
["Pierce"] = "Pierce",
["Blunt"] = "Blunt",
["Magic"] = "Magic",
["Lunar"] = "Thunder_Shadow_Crystal",
["Thunder"] = "Thunder",
["Crystal"] = "Crystal",
["Shade"] = "Shade"
}
function p.render(frame)
mw.log('Module:CharacterTier: render start: ' .. os.clock())
-- collect team filter
local filter = {}
if frame.args['team'] then
filter['team'] = frame.args['team']
end
-- fetch character ratings
mw.log('Module:CharacterTier: fetch characters start: ' .. os.clock())
local data = p.fetchCharacters(frame, filter)
mw.log('Module:CharacterTier: fetch characters end: ' .. os.clock())
local teams = {}
local teamcount = 0
for ix,character in pairs(data) do
if (character.team ~= nil) and not (teams[character.team]) then
teams[character.team] = true
teamcount = teamcount + 1
if teamcount > 1 then
break
end
end
end
local result = {}
if teamcount > 1 then
table.insert(result, '<table class="wikitable tierlist tierlist-multi"><tr><th>Rating</th><th>Fire</th><th>Water</th><th>Earth</th><th>Wind</th><th>Slash</th><th>Pierce</th><th>Blunt</th><th>Magic</th><th>Lunar</th><th>Thunder</th><th>Crystal</th><th>Shade</th></tr>')
table.insert(result, p.makeRatingTable(data, 'teams', 70))
table.insert(result, '</table>')
else
table.insert(result, '<table class="wikitable tierlist tierlist-single">')
table.insert(result, '<tr><th>Rating</th><th>Characters</th></tr>')
table.insert(result, p.makeRatingTable(data, nil, 100))
table.insert(result, '</table>')
end
table.insert(result, '<table class="wikitable tierlist-details" style="max-width: 725px;"><tr><th>Icon</th><th>Name/Type/Rating</th><th style="min-width: 475px">Remarks</th></tr>')
table.insert(result, p.makeRemarksTable(data))
table.insert(result, '</table>')
mw.log('Module:CharacterTier: render end: ' .. os.clock())
return table.concat(result, '')
end
function p.fetchCharacters(f, filter)
mw.log('Module:CharacterTier: fetchCharacters start: ' .. os.clock())
local queryFields = 'id,name,icon,element,weapon,team,rating,reasons'
local queryArgs = {limit = 1000}
if type(filter) == "table" then
local v = filter['team']
if type(v) == "string" then
queryArgs.where = ('team=%s'):format(v)
end
end
local result = {}
for _, row in ipairs(mw.ext.cargo.query('CharacterRatings', queryFields, queryArgs)) do
result[#result+1] = row
local args = row
args.ix = #result
end
mw.log('Module:Character.fetchCharacters end: ' .. os.clock())
return result
end
function p.makeRatingTable(data, columns, iconsize)
local result = {}
local ratings = {}
local teams = {}
if columns == 'teams' then
teams = {'Fire','Water','Earth','Wind','Slash','Pierce','Blunt','Magic','Lunar','Thunder','Crystal','Shade'}
elseif #data > 0 then
teams = {data[1].team}
end
local rating_keys = {}
for _, charInfo in pairs(data) do
local realRating = tonumber(charInfo.rating)
if realRating then
local rating
if #teams > 1 then
rating = realRating - realRating % ROW_GRANULARITY
else
rating = realRating
end
if ratings[rating] == nil then
ratings[rating] = {}
rating_keys[#rating_keys + 1] = rating
end
charInfo.numRating = realRating
table.insert(ratings[rating], charInfo)
end
end
table.sort(rating_keys)
for i=#rating_keys, 1, -1 do
local characters = ratings[rating_keys[i]]
table.sort(characters, function(a,b)
if a.numRating ~= b.numRating then
return a.numRating > b.numRating
end
return a.name < b.name
end)
table.insert(result, '<tr style="vertical-align: top;">')
local label, hasRatingRange = "?", false
if characters[1].rating ~= characters[#characters].rating then
label, hasRatingRange = characters[1].rating .. " - " .. characters[#characters].rating, true
elseif (tonumber(characters[1].rating) or 0) ~= 0 then
label = characters[1].rating
end
table.insert(result, '<td style="font-weight: bold;vertical-align: middle;text-align: center;">' .. rate_dict[label] .. '</td>')
for ix2,team in pairs(teams) do
table.insert(result, '<td>')
local lastRating = false
for key,character in pairs(characters) do
if character.team == team then
if hasRatingRange and lastRating ~= character.numRating then
if lastRating then
table.insert(result, '<hr class="filterable-divider" title="' .. character.rating .. '">')
end
lastRating = character.numRating
end
table.insert(result, '<span data-short-id="' .. character.icon .. '">[[File:' .. character.icon .. ' rank5_command.png|'..iconsize..'px|link=#ref' .. character.ix .. '|' .. character.name .. ']]</span>')
end
end
table.insert(result, '</td>\n')
end
table.insert(result, '</tr>\n')
end
return table.concat(result, '')
end
function p.makeRemarksTable(data)
table.sort(data, function(a,b)
if a.name == b.name then
if a.team == "Fire" then
return true
elseif a.team == "Water" then
if b.team == "Fire" then
return false
end
return true
elseif a.team == "Earth" then
for index, value in ipairs({"Fire","Water"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Wind" then
for index, value in ipairs({"Fire","Water","Earth"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Slash" then
for index, value in ipairs({"Fire","Water","Earth","Wind"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Pierce" then
for index, value in ipairs({"Fire","Water","Earth","Wind","Slash"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Blunt" then
for index, value in ipairs({"Fire","Water","Earth","Wind","Slash","Pierce"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Magic" then
for index, value in ipairs({"Fire","Water","Earth","Wind","Slash","Pierce","Blunt"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Lunar" then
for index, value in ipairs({"Fire","Water","Earth","Wind","Slash","Pierce","Blunt","Magic"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Thunder" then
for index, value in ipairs({"Fire","Water","Earth","Wind","Slash","Pierce","Blunt","Magic","Lunar"}) do
if value == b.team then
return false
end
end
return true
elseif a.team == "Crystal" then
for index, value in ipairs({"Fire","Water","Earth","Wind","Slash","Pierce","Blunt","Magic","Lunar","Thunder"}) do
if value == b.team then
return false
end
end
return true
end
return false
else
return a.name < b.name
end
end)
local result = {}
local frame = mw.getCurrentFrame()
local weaponsCache = {}
for ix,character in pairs(data) do
if (character ~= nil) and (character.name ~= nil) then
local name = character.name
local icon = character.icon
local rating = character.rating or 0
local remarks = '-'
if character.reasons ~= nil then
remarks = character.reasons
end
local element = frame:expandTemplate{ title = 'Element icon', args = { character.element, size = '23px' } }
local weapon = frame:expandTemplate{ title = 'Weapon icon', args = { character.weapon, size = '23px' } }
table.insert(result, '<tr style="text-align: center;">')
table.insert(result, '<td><div id="ref'..character.ix..'">[[File:' .. icon .. ' rank5_command.png|80px|link=[[' .. name .. ']]]]</div></td>')
table.insert(result, '<td style="white-space: nowrap;">[['..name..']]<hr>'..element..' '..weapon..'<hr>[[File:Stance '..team_dict[character.team]..'.png|x23px]]<hr>'..rate_dict[rating]..'</td>')
table.insert(result, '<td style="text-align: left; vertical-align: top; min-width: 475px;">\n'..remarks..'\n</td>')
table.insert(result, '</tr>')
end
end
return table.concat(result, '\n')
end
return p