Editing Module:LoRUtility
Jump to navigation
Jump to search
Always explain the reason in the edit summary rather than using only the default message, unless you are undoing vandalism.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
-- <pre> |
-- <pre> |
||
-- Inherit from https://github.com/SwitchbladeBot/runeterra |
|||
local lib = require('Module:Feature') |
local lib = require('Module:Feature') |
||
local MAX_KNOWN_VERSION = |
local MAX_KNOWN_VERSION = 2 |
||
local p = {} |
local p = {} |
||
local VarInt = {} |
local VarInt = {} |
||
Line 16: | Line 17: | ||
[6] = {code = "SI", name = "Shadow Isles"}, |
[6] = {code = "SI", name = "Shadow Isles"}, |
||
[7] = {code = "BW", name = "Bilgewater"}, |
[7] = {code = "BW", name = "Bilgewater"}, |
||
[ |
[10] = {code = "MT", name = "Targon"} |
||
[10] = {code = "MT", name = "Targon"}, |
|||
[11] = {code = "BC", name = "Bandle City"}, |
|||
[13] = {code = "RU", name = "Runeterra"} |
|||
} |
} |
||
--To test debug this line mw.executeFunction(p.test) |
|||
function p.test(frame) |
|||
output = p.adventureRegions{"RUIODE--"} |
|||
mw.log(output) |
|||
end |
|||
function base32_decode(str) |
function base32_decode(str) |
||
Line 55: | Line 47: | ||
function p.deckDataFromCode(frame) |
function p.deckDataFromCode(frame) |
||
local args = lib. |
local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end |
||
local lorData = mw.loadData("Module:LoRData/data") |
local lorData = mw.loadData("Module:LoRData/data") |
||
Line 61: | Line 53: | ||
local firstByte = bytes[1] |
local firstByte = bytes[1] |
||
local deckList = {} |
local deckList = {} |
||
table.remove(bytes, 1) |
table.remove(bytes, 1) |
||
local version = BitOperator.AND(tonumber(firstByte), 0xF) |
local version = BitOperator.AND(tonumber(firstByte), 0xF) |
||
Line 73: | Line 65: | ||
local followerCount = 0 |
local followerCount = 0 |
||
local spellCount = 0 |
local spellCount = 0 |
||
local landmarkCount = 0 |
|||
local equipmentCount = 0 |
|||
local rarities = {} |
local rarities = {} |
||
local champions = {} |
local champions = {} |
||
Line 86: | Line 76: | ||
local topChampion = nil |
local topChampion = nil |
||
local topFollower = nil |
local topFollower = nil |
||
local runeterranChampions = {} |
|||
local allCards = {} |
|||
function handleCardData(cardData, count, cardCode, regionName) |
function handleCardData(cardData, count, cardCode, regionName) |
||
Line 94: | Line 82: | ||
if cardData.supertype ~= nil and cardData.supertype == "Champion" then |
if cardData.supertype ~= nil and cardData.supertype == "Champion" then |
||
cardType = "Champion" |
cardType = "Champion" |
||
if regionName == "Runeterra" then |
|||
table.insert(runeterranChampions,cardData.name) |
|||
end |
|||
else |
else |
||
cardType = "Follower" |
cardType = "Follower" |
||
Line 102: | Line 87: | ||
end |
end |
||
table.insert(allCards,{code=cardCode, count=count, regionName=regionName}) |
|||
regions[regionName] = (regions[regionName] or 0) + count |
|||
if args['detail'] then |
if args['detail'] then |
||
totalShards = totalShards + shardValues[cardData.rarity] * count |
totalShards = totalShards + shardValues[cardData.rarity] * count |
||
Line 139: | Line 122: | ||
followerCount = followerCount + count |
followerCount = followerCount + count |
||
end |
end |
||
else |
|||
spellCount = spellCount + count |
spellCount = spellCount + count |
||
elseif cardType == "Landmark" then |
|||
landmarkCount = landmarkCount + count |
|||
elseif cardType == "Equipment" then |
|||
equipmentCount = equipmentCount + count |
|||
end |
end |
||
regions[regionName] = (regions[regionName] or 0) + count |
|||
else |
else |
||
table.insert( |
table.insert( |
||
Line 161: | Line 141: | ||
end |
end |
||
for i = 3, |
for i = 3, 0, -1 do |
||
local numGroupOfs = tonumber(VarInt.Pop(bytes)) or 0 |
local numGroupOfs = tonumber(VarInt.Pop(bytes)) or 0 |
||
for j = 1, numGroupOfs, 1 do |
for j = 1, numGroupOfs, 1 do |
||
Line 185: | Line 165: | ||
end |
end |
||
end |
end |
||
--For cards with over 3 copies |
|||
while true do |
|||
local count = tonumber(VarInt.Pop(bytes)) or nil |
|||
local set = VarInt.Pop(bytes) |
|||
local region = VarInt.Pop(bytes) |
|||
local card = VarInt.Pop(bytes) |
|||
if not count or not set or not region or not card then |
|||
break --end of stream |
|||
end |
|||
local setString = Utility.padLeft(tostring(set), 2, "0") |
|||
local regionData = REGIONS[region + 1] |
|||
local cardString = Utility.padLeft(tostring(card), 3, "0") |
|||
local cardCode = setString .. regionData.code .. cardString |
|||
if (not lorData[cardCode]) then |
|||
return 'Card Code "' .. cardCode .. '" does not exist' |
|||
end |
|||
handleCardData(lorData[cardCode], count, cardCode, regionData.name) |
|||
end |
|||
while #bytes > 0 do |
while #bytes > 0 do |
||
local fourPlusCount = VarInt.Pop(bytes) |
local fourPlusCount = VarInt.Pop(bytes) |
||
Line 226: | Line 183: | ||
if (not lorData[cardCode]) then |
if (not lorData[cardCode]) then |
||
return 'Card Code "' .. cardCode .. '" |
return 'Card Code "' .. cardCode .. '" is not exist' |
||
end |
end |
||
handleCardData(lorData[cardCode], |
handleCardData(lorData[cardCode], fourPlusNumber, cardCode, regionData.name) |
||
end |
end |
||
local multiregion = {} |
|||
if args['detail'] then |
if args['detail'] then |
||
for _, champion in ipairs(runeterranChampions) do |
|||
for _, data in ipairs(allCards) do |
|||
if p.isFromRuneterran{data.code,champion} then |
|||
regions["Runeterra"] = (regions["Runeterra"] or 0) + data.count |
|||
regions[data.regionName] = (regions[data.regionName] or 0) - data.count |
|||
data.regionName = "Runeterra" |
|||
end |
|||
end |
|||
end |
|||
for _, data in ipairs(allCards) do |
|||
if data.regionName ~= "Runeterra" and lorData[data.code].categoryRefs and lorData[data.code].regions then |
|||
for _,ref in ipairs(lorData[data.code].categoryRefs) do |
|||
if ref == "Multi-region" then |
|||
regions[data.regionName] = (regions[data.regionName] or 0) - data.count |
|||
local region1 = data.regionName |
|||
local region2 = nil |
|||
for _,region in ipairs(lorData[data.code].regions) do |
|||
if region1 ~= region then |
|||
region2 = region |
|||
break |
|||
end |
|||
end |
|||
table.insert(multiregion,{ |
|||
count=data.count, |
|||
region1=region1, |
|||
region2=region2 |
|||
}) |
|||
break |
|||
end |
|||
end |
|||
end |
|||
end |
|||
for _,data in pairs(multiregion) do |
|||
if not data.region2 or (regions[data.region1] and regions[data.region1] > 0) then |
|||
regions[data.region1] = (regions[data.region1] or 0) + data.count |
|||
elseif regions[data.region2] and regions[data.region2] > 0 then |
|||
regions[data.region2] = (regions[data.region2] or 0) + data.count |
|||
else |
|||
regions[data.region1] = (regions[data.region1] or 0) + data.count |
|||
end |
|||
end |
|||
for region, count in pairs(regions) do |
|||
if count <= 0 then |
|||
regions[region] = nil |
|||
end |
|||
end |
|||
return { |
return { |
||
shards = totalShards, |
shards = totalShards, |
||
Line 287: | Line 197: | ||
followerCount = followerCount, |
followerCount = followerCount, |
||
spellCount = spellCount, |
spellCount = spellCount, |
||
landmarkCount = landmarkCount, |
|||
equipmentCount = equipmentCount, |
|||
rarities = rarities |
rarities = rarities |
||
} |
} |
||
else |
else |
||
for _, champion in ipairs(runeterranChampions) do |
|||
for _, data in ipairs(deckList) do |
|||
if p.isFromRuneterran{data.code,champion} then |
|||
data.region = "Runeterra" |
|||
end |
|||
end |
|||
end |
|||
for _, data in ipairs(allCards) do |
|||
if lorData[data.code].categoryRefs and lorData[data.code].regions then |
|||
for _,ref in ipairs(lorData[data.code].categoryRefs) do |
|||
if ref == "Multi-region" then |
|||
regions[data.regionName] = (regions[data.regionName] or 0) - data.count |
|||
break |
|||
end |
|||
end |
|||
end |
|||
end |
|||
for _, data in ipairs(deckList) do |
|||
if data.region ~= "Runeterra" and lorData[data.code].categoryRefs and lorData[data.code].regions then |
|||
for _,ref in ipairs(lorData[data.code].categoryRefs) do |
|||
if ref == "Multi-region" then |
|||
local region1 = data.region |
|||
local region2 = nil |
|||
for _,region in ipairs(lorData[data.code].regions) do |
|||
if region1 ~= region then |
|||
region2 = region |
|||
break |
|||
end |
|||
end |
|||
if not region2 or (regions[region1] and regions[region1] > 0) then |
|||
data.region = region1 |
|||
elseif regions[region2] and regions[region2] > 0 then |
|||
data.region = region2 |
|||
else |
|||
data.region = region1 |
|||
end |
|||
break |
|||
end |
|||
end |
|||
end |
|||
end |
|||
return deckList |
return deckList |
||
end |
end |
||
end |
|||
function p.isFromRuneterran(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local lorData = require("Module:LoRData/data") |
|||
local cardCode = args['code'] or args[1] or nil |
|||
local region = args['region'] or args['champion'] or args[2] or nil |
|||
if not cardCode or not region or not lorData[cardCode] then |
|||
return false |
|||
end |
|||
local card = lorData[cardCode] |
|||
if card.supertype == "Champion" then |
|||
return false |
|||
end |
|||
if region == "Aatrox" and card.subtype then |
|||
for _, subtype in ipairs(card.subtype) do |
|||
if subtype == "Darkin" then |
|||
return true |
|||
end |
|||
end |
|||
elseif region == "Bard" then |
|||
local CHIME_CARDS = { ["06BC011"] = true, ["06BC026"] = true, ["06BC031"] = true, |
|||
["06BC032"] = true, ["06BC044"] = true, ["06MT029"] = true, ["06MT047"] = true, |
|||
["08BC005"] = true, ["08SI021"] = true |
|||
} |
|||
if CHIME_CARDS[cardCode] then return true end |
|||
elseif region == "Elder Dragon" then |
|||
if card.cost >= 6 then return true end |
|||
elseif region == "Evelynn" and card.categoryRefs then |
|||
for _, ref in ipairs(card.categoryRefs) do |
|||
if ref == "Husk-generating" then |
|||
return true |
|||
end |
|||
end |
|||
elseif region == "Jax" and card.subtype then |
|||
for _, subtype in ipairs(card.subtype) do |
|||
if subtype == "Weaponmaster" then |
|||
return true |
|||
end |
|||
end |
|||
elseif region == "Jhin" and card.keywordRefs then |
|||
for _, ref in ipairs(card.keywordRefs) do |
|||
if ref == "Skill-generating" then |
|||
return true |
|||
end |
|||
end |
|||
elseif (region == "Kayn" or region == "Varus") and card.subtype then |
|||
for _, subtype in ipairs(card.subtype) do |
|||
if subtype == "Cultist" then |
|||
return true |
|||
end |
|||
end |
|||
elseif region == "Neeko" and card.subtype then |
|||
local SUBTYPES = { ["Bird"] = true, ["Cat"] = true, ["Dog"] = true, |
|||
["Elnuk"] = true, ["Fae"] = true, ["Reptile"] = true, ["Spider"] = true |
|||
} |
|||
for _, subtype in ipairs(card.subtype) do |
|||
if SUBTYPES[subtype] then |
|||
return true |
|||
end |
|||
end |
|||
elseif region == "Ryze" and card.type == "Spell" and card.keywords then |
|||
for _, keyword in ipairs(card.keywords) do |
|||
if keyword == "Burst" or keyword == "Focus" then |
|||
return true |
|||
end |
|||
end |
|||
elseif region == "The Poro King" then |
|||
local PORO_CARDS = { ["01FR016"] = true, ["01FR025"] = true, ["02FR003"] = true, |
|||
["03FR018"] = true, ["03PZ018"] = true, ["06BC043"] = true, ["09FR009"] = true, |
|||
["99FR001"] = true, ["99FR002"] = true, ["99PZ118"] = true |
|||
} |
|||
if PORO_CARDS[cardCode] then return true end |
|||
if card.subtype then |
|||
for _, subtype in ipairs(card.subtype) do |
|||
if subtype == "Poro" then |
|||
return true |
|||
end |
|||
end |
|||
end |
|||
end |
|||
return false |
|||
end |
|||
function p.adventureRegions(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local str = args[1] or nil |
|||
local size = args["size"] or args[2] or "20px" |
|||
local sep = args["sep"] or " " |
|||
if not str then return nil end -- Exit if no input |
|||
local result = {} |
|||
local REGION_CODES = { |
|||
DE = "Demacia", |
|||
FR = "Freljord", |
|||
IO = "Ionia", |
|||
NX = "Noxus", |
|||
PZ = "Piltover and Zaun", |
|||
SI = "Shadow Isles", |
|||
BW = "Bilgewater", |
|||
SH = "Shurima", |
|||
MT = "Targon", |
|||
BC = "Bandle City", |
|||
RU = "Runeterra" |
|||
} |
|||
for i = 1, #str, 2 do |
|||
local pair = str:sub(i, i + 1):upper() |
|||
mw.log(pair) |
|||
local region = REGION_CODES[pair] or "Neutral" |
|||
table.insert(result, "[[File: " .. region .. " LoR Region.png|" .. size .. "|link=]]") |
|||
end |
|||
return table.concat(result, sep) |
|||
end |
|||
function p.adventureRewards(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local step = args["step"] or "5" |
|||
step = tonumber(step) |
|||
if not step then |
|||
return "Step Error." |
|||
end |
|||
local base_start = "<center><table style=\"border-collapse: collapse;\"><tr>" |
|||
local base_end = "</tr></table></center>" |
|||
local r = "" |
|||
local count = 0 |
|||
for i, a in ipairs(args) do |
|||
count = i |
|||
end |
|||
local rows = math.ceil(count/step) |
|||
local index_lastrow = ((rows-1)*step)+1 |
|||
for i, a in ipairs(args) do |
|||
if i % step == 1 then |
|||
if i ~= 1 then |
|||
r = r .. base_end |
|||
end |
|||
r = r .. base_start |
|||
if i < index_lastrow then |
|||
r = r .. "<td style=\"text-align: center; padding: 5px; border-right: 1px solid #3e4452; border-left: 1px solid #3e4452; border-bottom: 1px solid #3e4452;\"> " |
|||
else |
|||
r = r .. "<td style=\"text-align: center; padding: 5px; border-right: 1px solid #3e4452; border-left: 1px solid #3e4452;\"> " |
|||
end |
|||
else |
|||
if i < index_lastrow then |
|||
r = r .. "<td style=\"text-align: center; padding: 5px; border-right: 1px solid #3e4452; border-bottom: 1px solid #3e4452;\"> " |
|||
else |
|||
r = r .. "<td style=\"text-align: center; padding: 5px; border-right: 1px solid #3e4452;\"> " |
|||
end |
|||
end |
|||
r = r .. args[i] .. "</td>" |
|||
end |
|||
r = r .. base_end |
|||
return frame:preprocess(r) |
|||
end |
end |
||
function p.headerDeck(frame) |
function p.headerDeck(frame) |
||
local args = lib. |
local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end |
||
local builder = require("Module:SimpleHTMLBuilder") |
|||
args['name'] = args['name'] or 'Untitled Deck' |
args['name'] = args['name'] or 'Untitled Deck' |
||
Line 522: | Line 226: | ||
local followerCount = deckDetail['followerCount'] or nil |
local followerCount = deckDetail['followerCount'] or nil |
||
local spellCount = deckDetail['spellCount'] or nil |
local spellCount = deckDetail['spellCount'] or nil |
||
local landmarkCount = deckDetail['landmarkCount'] or nil |
|||
local equipmentCount = deckDetail['equipmentCount'] or nil |
|||
local rarities = deckDetail['rarities'] or nil |
local rarities = deckDetail['rarities'] or nil |
||
local template = |
local template = mw.html.create('div') |
||
:css('position', 'relative') |
:css('position', 'relative') |
||
:css('font-family', 'BeaufortLoL') |
:css('font-family', 'BeaufortLoL') |
||
Line 534: | Line 236: | ||
:done() |
:done() |
||
local deckHeader = |
local deckHeader = mw.html.create('div') |
||
:addClass('deck-header') |
:addClass('deck-header') |
||
:css('position', 'absolute') |
:css('position', 'absolute') |
||
Line 551: | Line 253: | ||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File:' .. regionName .. ' LoR Region.png|60px|link= |
:wikitext('[[File:' .. regionName .. ' LoR Region.png|60px|link=' .. regionName .. ' (Legends of Runeterra)]]') |
||
:done() |
:done() |
||
end |
end |
||
Line 560: | Line 262: | ||
:css('color', '#FFE3B0') |
:css('color', '#FFE3B0') |
||
:css('font-size', '16px') |
:css('font-size', '16px') |
||
:wikitext('[[File:Shard icon.png|40px|link= |
:wikitext('[[File:Shard icon.png|40px|link=Shard (Legends of Runeterra)]]' .. Utility.comma_value(totalShards)) |
||
:done() |
:done() |
||
deckHeader:done() |
deckHeader:done() |
||
local deckInfo = |
local deckInfo = mw.html.create('div') |
||
:addClass('deck-info') |
:addClass('deck-info') |
||
:css('position', 'absolute') |
:css('position', 'absolute') |
||
Line 589: | Line 291: | ||
:addClass('deck-info') |
:addClass('deck-info') |
||
:css('position', 'absolute') |
:css('position', 'absolute') |
||
:css('top', ' |
:css('top', '170px') |
||
:css('left', ' |
:css('left', '20px') |
||
:css('font-size', '20px') |
:css('font-size', '20px') |
||
:css('color', '#FFE3B0') |
:css('color', '#FFE3B0') |
||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File:Follower card. |
:wikitext('[[File:Follower card.svg|25px|link=Follower (Legends of Runeterra)]]' .. followerCount .. ' ') |
||
:done() |
:done() |
||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File:Spell card. |
:wikitext('[[File:Spell card.svg|25px|link=Spell (Legends of Runeterra)]]' .. spellCount .. ' ') |
||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Keyword Landmark.png|25px|link=LoR:Landmark]]' .. landmarkCount .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Keyword Equipment.png|25px|link=LoR:Equipment]]' .. equipmentCount .. ' ') |
|||
:done() |
:done() |
||
:tag('br') |
:tag('br') |
||
Line 613: | Line 307: | ||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File: |
:wikitext('[[File:Common rarity.svg|25px|link=Card_types_(Legends_of_Runeterra)#By_rarity]]' .. (rarities[1] or 0) .. ' ') |
||
:done() |
:done() |
||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File: |
:wikitext('[[File:Rare rarity.svg|25px|link=Card_types_(Legends_of_Runeterra)#By_rarity]]' .. (rarities[2] or 0) .. ' ') |
||
:done() |
:done() |
||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File: |
:wikitext('[[File:Epic rarity.svg|25px|link=Card_types_(Legends_of_Runeterra)#By_rarity]]' .. (rarities[3] or 0) .. ' ') |
||
:done() |
:done() |
||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File: |
:wikitext('[[File:Champion rarity.svg|25px|link=Card_types_(Legends_of_Runeterra)#By_rarity]]' .. (rarities[4] or 0) .. ' ') |
||
:done() |
:done() |
||
:done() |
:done() |
||
if #champions then |
if #champions then |
||
local deckChampions = |
local deckChampions = mw.html.create('div') |
||
:addClass('deck-champions') |
:addClass('deck-champions') |
||
:css('position', 'absolute') |
:css('position', 'absolute') |
||
:css('bottom', '20px') |
:css('bottom', '20px') |
||
:css('left', ' |
:css('left', '20px') |
||
:css('font-size', '20px') |
:css('font-size', '20px') |
||
:css('color', '#FFE3B0') |
:css('color', '#FFE3B0') |
||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File:Champion card. |
:wikitext('[[File:Champion card.svg|25px|link=Champion (Legends of Runeterra)]]') |
||
:done() |
:done() |
||
for _, deckData in pairs(champions) do |
for _, deckData in pairs(champions) do |
||
Line 645: | Line 339: | ||
:tag('span') |
:tag('span') |
||
:addClass('inline-image') |
:addClass('inline-image') |
||
:wikitext('[[File:' .. deckData.code .. '.png|60px|link= |
:wikitext('[[File:' .. deckData.code .. '.png|60px|link='.. deckData.code .. ' (Legends of Runeterra)]]') |
||
:done() |
:done() |
||
:tag('span') |
:tag('span') |
||
Line 664: | Line 358: | ||
function p.deckDecoder(frame) |
function p.deckDecoder(frame) |
||
local args = lib. |
local args; if frame.args == nil then args = lib.arguments(frame) else args = lib.arguments(frame.args) end |
||
if args['code'] == nil then |
if args['code'] == nil then |
||
Line 674: | Line 368: | ||
if Utility.table_contains(groupByValues, groupBy) == false then |
if Utility.table_contains(groupByValues, groupBy) == false then |
||
return 'Only support Group By "region", "type" or none' |
return 'Only support Group By "region", "type" or none' |
||
end |
|||
local header = args['header'] or true |
|||
if header == 'false' then |
|||
header = false |
|||
end |
end |
||
Line 693: | Line 382: | ||
groupByKey = deckData.region |
groupByKey = deckData.region |
||
elseif groupBy == 'type' then |
elseif groupBy == 'type' then |
||
groupByKey = |
groupByKey = cardType .. 's' |
||
else |
else |
||
groupByKey = 'List' |
groupByKey = 'List' |
||
Line 720: | Line 409: | ||
local template = "" |
local template = "" |
||
template = template .. p.headerDeck{code = args['code'], name = args['name'], description = args['description']} |
|||
if header then |
|||
template = template .. p.headerDeck{code = args['code'], name = args['name'], description = args['description']} |
|||
end |
|||
local newline = "\n" |
local newline = "\n" |
||
Line 731: | Line 418: | ||
template = template .. "|-|" .. newline |
template = template .. "|-|" .. newline |
||
end |
end |
||
template = template .. groupByKey .. "=" .. newline .. " |
template = template .. groupByKey .. "=" .. newline .. "Code: " .. args['code'] .. newline |
||
local regionData = result[groupByKey] |
local regionData = result[groupByKey] |
||
Line 775: | Line 462: | ||
return frame:preprocess(template) |
return frame:preprocess(template) |
||
end |
|||
function p.pocHeaderDeck(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local builder = require("Module:SimpleHTMLBuilder") |
|||
local adventureData = require("Module:LoRPoCData/adventure") |
|||
local lorData = require("Module:LoRData/data") |
|||
args['name'] = args['name'] or args['foe'] or 'Untitled Deck' |
|||
local cmp = args['campaign'] or "World Adventures" |
|||
if args['adventure'] == nil or not adventureData[cmp][args['adventure']] then |
|||
return 'Adventure missing or invalid' |
|||
end |
|||
local adventure = adventureData[cmp][args['adventure']] |
|||
if args['foe'] == nil or not adventure[args['foe']] then |
|||
return 'Foe missing or invalid' |
|||
end |
|||
local foe = adventure[args['foe']] |
|||
local stars = adventure.stars or false |
|||
local adventureType = adventure["type"] or false |
|||
args['code'] = args['code'] or foe.deck or nil |
|||
if args['code'] == nil then |
|||
return 'Empty Code' |
|||
end |
|||
local hasPower = foe.power or false |
|||
local hasPowerArgs = args['powername'] or args['powerdesc'] or false |
|||
local powername = nil |
|||
local powerdesc = nil |
|||
local powericon = nil |
|||
local powerrarity = nil |
|||
if hasPower then |
|||
powername = foe.power.name or 'Power Name' |
|||
powerdesc = foe.power.desc or 'Power Description.' |
|||
powericon = foe.power.icon or nil |
|||
powerrarity = foe.power.rarity or 'Common' |
|||
end |
|||
if hasPowerArgs then |
|||
powername = args['powername'] or powername or 'Power Name' |
|||
powerdesc = args['powerdesc'] or powerdesc or 'Power Description.' |
|||
powericon = args['powericon'] or powericon or nil |
|||
powerrarity = args['powerrarity'] or powerrarity or 'Common' |
|||
hasPower = true |
|||
end |
|||
local deckDetail = p.deckDataFromCode{code = args['code'], detail = true} |
|||
if type(deckDetail) ~= 'table' then |
|||
return deckDetail |
|||
end |
|||
local deckSimple = p.deckDataFromCode{code = args['code'], detail = false} |
|||
if type(deckSimple) ~= 'table' then |
|||
return deckSimple |
|||
end |
|||
local topUnitCode = args['topUnitCode'] or foe.code or deckDetail['topUnitCode'] or nil |
|||
local regions = deckDetail['regions'] or nil |
|||
local champions = deckDetail['champions'] or nil |
|||
local followerCount = deckDetail['followerCount'] or nil |
|||
local spellCount = deckDetail['spellCount'] or nil |
|||
local landmarkCount = deckDetail['landmarkCount'] or nil |
|||
local equipmentCount = deckDetail['equipmentCount'] or nil |
|||
local MAX_MOBILE_ITEMS = 3 |
|||
local MAX_ITEMS = 7 |
|||
--Extract items on cards |
|||
local items = foe.items or nil |
|||
--Fuse champions with items |
|||
local championsItem = {} |
|||
if items then |
|||
for code, data in pairs(items) do |
|||
if lorData[code] and lorData[code]["supertype"] == "Champion" then |
|||
table.insert(championsItem,{ |
|||
code=code, |
|||
count=0, |
|||
items=data |
|||
}) |
|||
end |
|||
end |
|||
end |
|||
for _, deckData in pairs(champions) do |
|||
local found = false |
|||
for _, data in pairs(championsItem) do |
|||
if data.code == deckData.code then |
|||
found = true |
|||
data.count=deckData.count |
|||
break |
|||
end |
|||
end |
|||
if not found then |
|||
table.insert(championsItem, { |
|||
code=deckData.code, |
|||
count=deckData.count, |
|||
items=nil |
|||
}) |
|||
end |
|||
end |
|||
table.sort(championsItem, function(a, b) |
|||
if (lorData[a.code].name == args['foe']) ~= (lorData[b.code].name == args['foe']) then -- 1. Priority if "name" is the foe |
|||
return lorData[a.code].name == args['foe'] |
|||
end |
|||
local aitems = {} |
|||
local bitems = {} |
|||
if a.items then aitems = a.items end |
|||
if b.items then bitems = b.items end |
|||
if #aitems ~= #bitems then -- 2. Sort by the number of items (higher count first) |
|||
return #aitems > #bitems |
|||
end |
|||
if lorData[a.code].cost ~= lorData[b.code].cost then -- 3. Sort by "cost" (lowest to highest) |
|||
return lorData[a.code].cost < lorData[b.code].cost |
|||
end |
|||
return lorData[a.code].name < lorData[b.code].name -- 4. Sort alphabetically by "name" |
|||
end) |
|||
--detailed cards with items list |
|||
local detailedItems = {} |
|||
if items then |
|||
for code, data in pairs(items) do |
|||
table.insert(detailedItems, { |
|||
code=code, |
|||
name=lorData[code].name, |
|||
cost=lorData[code].cost, |
|||
items=data |
|||
}) |
|||
end |
|||
end |
|||
table.sort(detailedItems, function(a, b) |
|||
if (a.name == args['foe']) ~= (b.name == args['foe']) then -- 1. Priority if "name" is the foe |
|||
return a.name == args['foe'] |
|||
end |
|||
if #a.items ~= #b.items then -- 2. Sort by the number of items (higher count first) |
|||
return #a.items > #b.items |
|||
end |
|||
if a.cost ~= b.cost then -- 3. Sort by "cost" (lowest to highest) |
|||
return a.cost < b.cost |
|||
end |
|||
return a.name < b.name -- 4. Sort alphabetically by "name" |
|||
end) |
|||
local template = builder.create('div') |
|||
:css('display', 'inline-block') |
|||
:css('position', 'relative') |
|||
:css('font-family', 'BeaufortLoL') |
|||
:tag('div') |
|||
:css('opacity', '0.5') |
|||
:wikitext('[[File:' .. topUnitCode .. '-full.png|800px|link=]]') |
|||
:done() |
|||
local deckHeader = builder.create('div') |
|||
:addClass('deck-header') |
|||
:css('position', 'absolute') |
|||
:css('max-width', '650px') |
|||
:css('top', '10px') |
|||
:css('left', '10px') |
|||
:tag('span') |
|||
:css('font-weight', 'bold') |
|||
:css('color', '#FFE3B0') |
|||
:css('font-size', '30px') |
|||
:css('margin-left', '10px') |
|||
:css('margin-right', '10px') |
|||
:wikitext(args['name']) |
|||
:done() |
|||
local regionSize = 60 |
|||
local count = 0 |
|||
for _ in pairs(regions) do |
|||
count = count + 1 |
|||
if count > 9 then |
|||
regionSize = 50 |
|||
break |
|||
end |
|||
end |
|||
for regionName, regionCount in pairs(regions) do |
|||
deckHeader |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:' .. regionName .. ' LoR Region.png|' .. tostring(regionSize) .. 'px|link=LoR:' .. regionName .. ']]') |
|||
:done() |
|||
end |
|||
if stars then |
|||
local starHeader= builder.create('div') |
|||
:addClass('deck-header') |
|||
:css('position', 'absolute') |
|||
:css('top', '10px') |
|||
:css('left', '730px') |
|||
:tag('span') |
|||
:css('font-weight', 'bold') |
|||
:css('color', 'white') |
|||
:css('font-size', '18px') |
|||
:tag('span') |
|||
:addClass('PoC-Star-Difficulty') |
|||
:css('white-space', 'nowrap') |
|||
:tag('span') |
|||
:css('position', 'relative') |
|||
:css('text-indent', '0') |
|||
:css('top', '-3px') |
|||
:wikitext('[[File:PoC Star icon.png|60px|link=]]') |
|||
:tag('span') |
|||
:css('position', 'absolute') |
|||
:css('left', '17px') |
|||
:css('top', '30%') |
|||
:css('user-select', 'none') |
|||
:css('line-height', '1.5') |
|||
:css('text-align', 'center') |
|||
:css('width', '25px') |
|||
:css('height', '25px') |
|||
:css('transform', 'translateY(-25%)') |
|||
:css('text-shadow', '0.5px 0.5px 1px #000, 0.5px 0.5px 1px #000, -0.5px -0.5px 1px #000, -0.5px -0.5px 1px #000, 0.5px -0.5px 1px #000, 0.5px -0.5px 1px #000, -0.5px 0.5px 1px #000, -0.5px 0.5px 1px #000, 0.5px 0.5px 1px #000, 0.5px 0.5px 1px #000;') |
|||
:wikitext(stars) |
|||
:done() |
|||
:done() |
|||
:done() |
|||
:done() |
|||
template |
|||
:node(starHeader) |
|||
end |
|||
if adventureType then |
|||
local leftOffset = '660px' |
|||
if not stars then leftOffset = '730px' end |
|||
local typeImage = '' |
|||
if adventureData.Icons[adventureType] then |
|||
typeImage = '[[File:' .. adventureData.Icons[adventureType] .. '|60x60px|link=LoR:World Adventures]]' |
|||
end |
|||
local typeHeader= builder.create('div') |
|||
:addClass('deck-header') |
|||
:css('position', 'absolute') |
|||
:css('top', '8px') |
|||
:css('left', leftOffset) |
|||
:tag('span') |
|||
:wikitext(typeImage) |
|||
:done() |
|||
template |
|||
:node(typeHeader) |
|||
end |
|||
if #championsItem > 0 then |
|||
local deckChampions = builder.create('div') |
|||
:addClass('deck-champions') |
|||
:css('position', 'absolute') |
|||
:css('top', '70px') |
|||
:css('left', '20px') |
|||
:css('font-size', '20px') |
|||
:css('color', '#FFE3B0') |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Champion card.png|25px|link=LoR:Champion]]') |
|||
:done() |
|||
local n = 0 |
|||
for _, deckData in pairs(championsItem) do |
|||
if (n == MAX_MOBILE_ITEMS and args['mobile']) or (n == MAX_ITEMS) then |
|||
deckChampions |
|||
:tag('span') |
|||
:css('font-weight', 'bold') |
|||
:css('font-size', '30px') |
|||
:addClass('inline-image') |
|||
:wikitext(frame:preprocess(' ...')) |
|||
:done() |
|||
break |
|||
end |
|||
if deckData.items then |
|||
local s = '{{PoCCardItems|size=70|' .. deckData.code |
|||
for _, item in pairs(deckData.items) do |
|||
s = s .. '|' .. item |
|||
end |
|||
s = s .. '}}' |
|||
deckChampions |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext(frame:preprocess(s)) |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext(' x' .. deckData.count .. ' ') |
|||
:done() |
|||
else |
|||
deckChampions |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:' .. deckData.code .. '.png|70px|link=LoR:'.. deckData.code .. ']]') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('x' .. deckData.count .. ' ') |
|||
:done() |
|||
end |
|||
n = n+1 |
|||
end |
|||
deckChampions: |
|||
done() |
|||
template |
|||
:node(deckChampions) |
|||
end |
|||
if items then |
|||
local deckItems = builder.create('div') |
|||
:addClass('deck-champions') |
|||
:css('position', 'absolute') |
|||
:css('top', '175px') |
|||
:css('left', '20px') |
|||
:css('font-size', '20px') |
|||
:css('color', '#FFE3B0') |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:PoC Relic icon.png|25px]]') |
|||
:done() |
|||
local n = 0 |
|||
for _, itemList in ipairs(detailedItems) do |
|||
if (n == MAX_MOBILE_ITEMS and args['mobile']) or (n == MAX_ITEMS) then |
|||
deckItems |
|||
:tag('span') |
|||
:css('font-weight', 'bold') |
|||
:css('font-size', '30px') |
|||
:addClass('inline-image') |
|||
:wikitext(frame:preprocess(' ...')) |
|||
:done() |
|||
break |
|||
end |
|||
local count = 0; |
|||
local nonChampion = true |
|||
for _, data in pairs(championsItem) do |
|||
if data.code == itemList.code then |
|||
nonChampion = false |
|||
break |
|||
end |
|||
end |
|||
if nonChampion then |
|||
for _, data in pairs(deckSimple) do |
|||
if data.code == itemList.code then |
|||
count = data.count |
|||
break |
|||
end |
|||
end |
|||
local s = '{{PoCCardItems|size=70|' .. itemList.code |
|||
for _, item in ipairs(itemList.items) do |
|||
s = s .. '|' .. item |
|||
end |
|||
s = s .. '}}' |
|||
deckItems |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext(frame:preprocess(s)) |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext(' x' .. count .. ' ') |
|||
:done() |
|||
n = n+1 |
|||
end |
|||
end |
|||
deckItems: |
|||
done() |
|||
template |
|||
:node(deckItems) |
|||
end |
|||
local powerImage |
|||
local powerTitle |
|||
local powerInfo |
|||
if hasPower then |
|||
local image_leftOffset = 230 |
|||
if args['mobile'] then image_leftOffset = 200 end |
|||
powerImage = builder.create('div') |
|||
:addClass('deck-info') |
|||
:css('position', 'absolute') |
|||
:css('top', '300px') |
|||
:css('left', tostring(image_leftOffset) .. 'px') |
|||
if powericon then |
|||
powerImage |
|||
:tag('span') |
|||
:css('display', 'inline-block') |
|||
:wikitext(frame:preprocess('{{PoCPowerIconOverlay|' .. powericon .. '|' .. powerrarity .. '|80}}')) |
|||
:done() |
|||
end |
|||
powerImage |
|||
:done() |
|||
powerTitle = builder.create('div') |
|||
:addClass('deck-info') |
|||
:css('position', 'absolute') |
|||
:css('top', '300px') |
|||
:css('left', tostring(image_leftOffset+100) .. 'px') |
|||
:css('color', '#FFE3B0') |
|||
:css('font-weight', 'bold') |
|||
:tag('span') |
|||
:css('display', 'inline-block') |
|||
:css('font-size', '16px') |
|||
:wikitext(powername) |
|||
:done() |
|||
powerTitle:done() |
|||
powerInfo = builder.create('div') |
|||
:addClass('deck-info') |
|||
:css('position', 'absolute') |
|||
:css('top', '330px') |
|||
:css('left', tostring(image_leftOffset+100) .. 'px') |
|||
:css('color', '#FFE3B0') |
|||
:tag('span') |
|||
:css('display', 'inline-block') |
|||
:css('max-width', '460px') |
|||
:css('font-size', '14px') |
|||
:wikitext(frame:preprocess(powerdesc)) |
|||
:done() |
|||
powerInfo:done() |
|||
end |
|||
local health = foe.health or '?' |
|||
local mana = foe.mana or '?' |
|||
local hand = foe.hand or '?' |
|||
local vicious = foe.vicious or false |
|||
if hasPower then |
|||
template |
|||
:node(deckHeader) |
|||
:node(powerImage) |
|||
:node(powerTitle) |
|||
:node(powerInfo) |
|||
else |
|||
template |
|||
:node(deckHeader) |
|||
end |
|||
local color = '#FFE3B0' |
|||
if vicious then |
|||
color = '#FF7474' |
|||
if tonumber(health) then health = tostring(tonumber(health) + 10) end |
|||
if tonumber(mana) then mana = tostring(tonumber(mana) + 1) end |
|||
if tonumber(hand) then hand = tostring(tonumber(hand) + 1) end |
|||
end |
|||
template |
|||
:tag('div') |
|||
:addClass('deck-info') |
|||
:css('position', 'absolute') |
|||
:css('top', '320px') |
|||
:css('left', '15px') |
|||
:css('font-size', '20px') |
|||
:css('color', '#FFE3B0') |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Follower card.png|25px|link=LoR:Follower]]' .. followerCount .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Spell card.png|25px|link=LoR:Spell]]' .. spellCount .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Keyword Landmark.png|25px|link=LoR:Landmark]]' .. landmarkCount .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Keyword Equipment.png|25px|link=LoR:Equipment]]' .. equipmentCount .. ' ') |
|||
:done() |
|||
:done() |
|||
:tag('div') |
|||
:addClass('deck-info') |
|||
:css('position', 'absolute') |
|||
:css('top', '360px') |
|||
:css('left', '15px') |
|||
:css('font-size', '20px') |
|||
:css('color', color) |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:PoC Health icon.png|25px|link=LoR:Nexus Health]]' .. health .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:LoR mana icon alt.png|25px|link=LoR:Terminology#Mana]]' .. mana .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext('[[File:Keyword Draw.png|25px|link=]]' .. hand .. ' ') |
|||
:done() |
|||
:tag('span') |
|||
:addClass('inline-image') |
|||
:wikitext(lib.ternary(vicious,frame:preprocess(' {{PoCPowerIconOverlay|04SI017-full.png|Special|30}}'),'')) |
|||
:done() |
|||
:done() |
|||
template:allDone() |
|||
return tostring(template) |
|||
end |
|||
function p.pocDeckDecoder(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local adventureData = require("Module:LoRPoCData/adventure") |
|||
local cmp = args['campaign'] or "World Adventures" |
|||
local groupBy = args['groupBy'] or 'none' |
|||
local groupByValues = {'region', 'type', 'none'} |
|||
if Utility.table_contains(groupByValues, groupBy) == false then |
|||
return 'Only support Group By "region", "type" or none' |
|||
end |
|||
if args['adventure'] == nil or not adventureData[cmp][args['adventure']] then |
|||
return 'Adventure missing or invalid' |
|||
end |
|||
local adventure = adventureData[cmp][args['adventure']] |
|||
if args['foe'] == nil or not adventure[args['foe']] then |
|||
return 'Foe missing or invalid' |
|||
end |
|||
local foe = adventure[args['foe']] |
|||
local items = foe.items or {} |
|||
local deckItems = {} |
|||
args['code'] = args['code'] or foe.deck or nil |
|||
if args['code'] == nil then |
|||
return 'Empty Code' |
|||
end |
|||
local header = args['header'] or true |
|||
if header == 'false' then |
|||
header = false |
|||
end |
|||
local result = {} |
|||
local deckList = p.deckDataFromCode{code = args['code']} |
|||
if type(deckList) ~= 'table' then |
|||
return deckList |
|||
end |
|||
for _, deckData in pairs(deckList) do |
|||
local groupByKey = '' |
|||
if groupBy == 'region' then |
|||
groupByKey = deckData.region |
|||
elseif groupBy == 'type' then |
|||
groupByKey = deckData.type .. 's' |
|||
else |
|||
groupByKey = 'List' |
|||
end |
|||
if result[groupByKey] == nil then |
|||
result[groupByKey] = {} |
|||
end |
|||
if items[deckData.code] then |
|||
table.insert(deckItems,deckData.code) |
|||
end |
|||
table.insert( |
|||
result[groupByKey], |
|||
{ |
|||
code = deckData.code, |
|||
count = deckData.count, |
|||
name = deckData.name, |
|||
type = deckData.type |
|||
} |
|||
) |
|||
end |
|||
local sortedKeys = {} |
|||
for k in pairs(result) do |
|||
table.insert(sortedKeys, k) |
|||
end |
|||
table.sort(sortedKeys) |
|||
local template = "" |
|||
if header then |
|||
template = template .. p.pocHeaderDeck(frame) |
|||
end |
|||
local newline = "\n" |
|||
template = template .. "<tabber>" .. newline |
|||
template = template .. "Hide=" .. newline .. '|-|' .. newline |
|||
for i, groupByKey in ipairs(sortedKeys) do |
|||
if i ~= 1 then |
|||
template = template .. "|-|" .. newline |
|||
end |
|||
template = template .. groupByKey .. "=" .. newline .. "'''Code:''' <span style='word-wrap: break-word;'>" .. args['code'] .. '</span>' .. newline |
|||
local regionData = result[groupByKey] |
|||
table.sort( |
|||
regionData, |
|||
function(a, b) |
|||
if (a.type == b.type) then |
|||
return a.name < b.name |
|||
end |
|||
return a.type < b.type |
|||
end |
|||
) |
|||
local type = "" |
|||
local isFirst = true |
|||
for _, cardData in ipairs(regionData) do |
|||
if cardData.type ~= type then |
|||
if (type ~= "") then |
|||
template = template .. "|}" .. newline |
|||
end |
|||
template = template .. "{| class=\"wikitable\"" .. newline .. "! colspan=5 style=\"background-color: #374b65; text-align: left;\" |" .. cardData.type .. "s" .. newline .. "|-" .. newline |
|||
isFirst = true |
|||
type = cardData.type |
|||
end |
|||
local cardCodeTemplate = "" |
|||
if isFirst then |
|||
cardCodeTemplate = cardCodeTemplate .. '|-' .. newline |
|||
isFirst = false |
|||
else |
|||
cardCodeTemplate = cardCodeTemplate .. '|' .. newline |
|||
isFirst = true |
|||
end |
|||
cardCodeTemplate = cardCodeTemplate .."| {{LoR|" .. cardData.name |
|||
if cardData.type ~= "Champion" then |
|||
cardCodeTemplate = cardCodeTemplate .. "|code=" .. cardData.code |
|||
end |
|||
cardCodeTemplate = cardCodeTemplate .. "}}" .. " (x" .. cardData.count .. ")" .. newline |
|||
cardCodeTemplate = cardCodeTemplate .. "| " |
|||
if items[cardData.code] then |
|||
for _, item in ipairs(items[cardData.code]) do |
|||
if item:sub(1, 1) == "I" then |
|||
cardCodeTemplate = cardCodeTemplate .. "{{PoC|item|code=" .. item .. "}} " |
|||
else |
|||
cardCodeTemplate = cardCodeTemplate .. "{{PoC|relic|code=" .. item .. "}} " |
|||
end |
|||
end |
|||
end |
|||
template = template .. cardCodeTemplate .. newline |
|||
end |
|||
template = template .. "|}" .. newline |
|||
end |
|||
local extraItems = "" |
|||
local isFirst = true |
|||
for key, itemList in pairs(items) do |
|||
if true then |
|||
end |
|||
if not Utility.table_contains(deckItems,key) then |
|||
if isFirst then |
|||
extraItems = extraItems .. '|-' .. newline |
|||
isFirst = false |
|||
else |
|||
extraItems = extraItems .. '|' .. newline |
|||
isFirst = true |
|||
end |
|||
extraItems = extraItems .. "| {{LoR|code=" .. key .. "}}" .. newline .. "| " |
|||
for _, item in ipairs(itemList) do |
|||
if item:sub(1, 1) == "I" then |
|||
extraItems = extraItems .. "{{PoC|item|code=" .. item .. "}} " |
|||
else |
|||
extraItems = extraItems .. "{{PoC|relic|code=" .. item .. "}} " |
|||
end |
|||
end |
|||
extraItems = extraItems .. newline |
|||
end |
|||
end |
|||
if extraItems ~= "" then |
|||
if groupBy == 'region' or groupBy == 'type' then |
|||
template = template .. "|-|" .. newline .. "Non-deck=" .. newline .. "'''Code:''' " .. args['code'] .. newline |
|||
else |
|||
-- template = template .. ";Non-deck cards with items" .. newline |
|||
end |
|||
template = template .. "{| class=\"wikitable\"" .. newline .. "! colspan=5 style=\"background-color: #374b65; text-align: left;\" | Non-deck cards with items" .. newline .. "|-" .. newline .. extraItems .. "|}" .. newline |
|||
end |
|||
template = template .. "</tabber>" |
|||
return frame:preprocess(template) |
|||
end |
|||
function p.championRoster(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local size = args["size"] or "120px" |
|||
local lorData = require('Module:LoRData/data') |
|||
local lorTable = {} |
|||
local s = "" |
|||
local REGION_CODES = { |
|||
DE = "Demacia", |
|||
FR = "Freljord", |
|||
IO = "Ionia", |
|||
NX = "Noxus", |
|||
PZ = "Piltover and Zaun", |
|||
SI = "Shadow Isles", |
|||
BW = "Bilgewater", |
|||
SH = "Shurima", |
|||
MT = "Targon", |
|||
BC = "Bandle City", |
|||
RU = "Runeterra" |
|||
} |
|||
local cardtable = {} |
|||
for cardcode in pairs(lorData) do |
|||
table.insert(cardtable, cardcode) |
|||
end |
|||
table.sort(cardtable) |
|||
local championtable = {} |
|||
for i, cardcode in pairs(cardtable) do |
|||
repeat |
|||
local t = lorData[cardcode] |
|||
if t.rarity ~= 'Champion' then |
|||
break |
|||
end |
|||
t['code'] = cardcode |
|||
table.insert(championtable, t) |
|||
break |
|||
until true |
|||
end |
|||
-- END |
|||
table.sort(championtable, function(a, b) return a['name'] < b['name'] end) |
|||
local rosterText = '' -- Temporarily will be class poc-roster |
|||
rosterText = rosterText .. '<div class="poc-roster-container" style="display: flex; flex-direction: column; margin: 0 auto; padding: 5px; text-align: center;">' |
|||
rosterText = rosterText .. '<div class="poc-roster" style="display: flex; justify-content: space-evenly; flex-wrap: wrap;">' |
|||
for _, card in pairs(championtable) do |
|||
rosterText = rosterText .. '<div class="poc-roster-champion" style="padding:0.5em;" data-champion="' .. card.name .. '" data-searchname="' .. card.name .. '" data-game="lor"' |
|||
if card.regions then |
|||
rosterText = rosterText .. ' data-region="' .. table.concat(card.regions, ", ") .. '">' |
|||
else |
|||
rosterText = rosterText .. ' data-region="' .. REGION_CODES[card.code:sub(3,4):upper()] .. '">' |
|||
end |
|||
rosterText = rosterText .. '[[File:' .. card.code .. '.png|' .. size .. '|link=LoR:' .. card.name .. ']] <br> [[LoR:' .. card.name .. '|' .. card.name .. ']]</div>' |
|||
end |
|||
rosterText = rosterText .. '</div>' |
|||
rosterText = rosterText .. '</div>' |
|||
return rosterText |
|||
end |
|||
function p.championRosterPoC(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local size = args["size"] or "120px" |
|||
local pocData = require('Module:LoRPoCData/data') |
|||
local lorTable = {} |
|||
local s = "" |
|||
local rosterText = '' |
|||
rosterText = rosterText .. '<div class="poc-roster-container" style="display: flex; flex-direction: column; margin: 0 auto; padding: 5px; text-align: center;">' |
|||
rosterText = rosterText .. '<div class="poc-roster" style="display: flex; justify-content: space-evenly; flex-wrap: wrap;">' |
|||
pocData = pocData["Champion"] |
|||
local championtable = {} |
|||
for champion, data in pairs(pocData) do |
|||
if (data["playable"]) then |
|||
table.insert(championtable, data) |
|||
end |
|||
end |
|||
table.sort(championtable, function(a, b) return a.name < b.name end) |
|||
for _, data in pairs(championtable) do |
|||
rosterText = rosterText .. '<div class="poc-roster-champion" style="padding:0.5em;" data-champion="' .. data.name .. '" data-searchname="' .. data.name .. '" ' |
|||
rosterText = rosterText .. 'data-game="lor" data-playstyle="' .. (data.playable.style or "no") .. '" data-difficulty="' .. (data.playable.difficulty or "no") .. '" ' |
|||
rosterText = rosterText .. 'data-region="' .. table.concat(data.playable.region, ", ") .. '" ' |
|||
if data.playable.constellationRegion then |
|||
rosterText = rosterText ..'data-constellation="' .. data.playable.constellationRegion .. ', hasConstellation" ' |
|||
else |
|||
rosterText = rosterText ..'data-constellation="constellation-none" ' |
|||
end |
|||
rosterText = rosterText .. '>[[File:' .. data.id .. '.png|' .. size .. '|link=LoR:' .. data.name .. '/PoC]] <br> [[LoR:' .. data.name .. '/PoC|' .. data.name .. ']]</div>' |
|||
end |
|||
rosterText = rosterText .. '</div>' |
|||
rosterText = rosterText .. '</div>' |
|||
return rosterText |
|||
end |
|||
function p.getPoCChampionGrid(frame) |
|||
-- Author: @Bladenite |
|||
local args = lib.frameArguments(frame) |
|||
local size = args["size"] or "120px" |
|||
local pocData = require('Module:LoRPoCData/data') |
|||
local gridText = '' |
|||
-- Creating outer container |
|||
gridText = gridText .. '<div class="poc-champions-flexbox-container" style="display: flex; flex-wrap: wrap; gap: 7.5px; justify-content: space-around;">' |
|||
-- Getting playable champions data |
|||
pocData = pocData["Champion"] |
|||
local championtable = {} |
|||
for champion, data in pairs(pocData) do |
|||
if (data["playable"]) then |
|||
table.insert(championtable, data) |
|||
end |
|||
end |
|||
table.sort(championtable, function(a, b) return a.name < b.name end) |
|||
for _, data in pairs(championtable) do |
|||
gridText = gridText .. '<div class="poc-champion-container" ' |
|||
-- Adding data for search parameters |
|||
gridText = gridText .. 'data-champion="' .. data.name .. '" data-searchname="' .. data.name .. '" ' |
|||
gridText = gridText .. 'data-game="lor" data-playstyle="' .. (data.playable.style or "no") .. '" data-difficulty="' .. (data.playable.difficulty or "no") .. '" ' |
|||
gridText = gridText .. 'data-region="' .. table.concat(data.playable.region, ", ") .. '" ' |
|||
if data.playable.constellationRegion then |
|||
gridText = gridText ..'data-constellation="' .. data.playable.constellationRegion .. ', hasConstellation" ' |
|||
else |
|||
gridText = gridText ..'data-constellation="constellation-none" ' |
|||
end |
|||
gridText = gridText .. '>' --closing div |
|||
-- Building champion board |
|||
gridText = gridText .. '<div class="poc-champion-circle"> [[File:' .. data.id .. '-circle.png|75px|link=LoR:' .. data.name .. '/PoC]]</div>' |
|||
gridText = gridText .. '<div class="poc-champion-name"> [[LoR:' .. data.name .. '/PoC|' .. data.name .. ']]</div>' |
|||
gridText = gridText .. '<div class="poc-champion-region">' |
|||
if #data.playable.region == 1 then |
|||
gridText = gridText .. '[[File:' .. data.playable.region[1] .. ' LoR Region.png|35px|link=]]</div>' |
|||
elseif #data.playable.region == 2 then |
|||
gridText = gridText .. '[[File:' .. data.playable.region[1] .. ' LoR Region.png|35px|link=]] ' |
|||
gridText = gridText .. '[[File:' .. data.playable.region[2] .. ' LoR Region.png|35px|link=]]</div>' |
|||
end |
|||
if data.playable.style then |
|||
gridText = gridText .. '<div class="poc-champion-info"><span class="poc-' .. data.playable.style:lower() .. '">[[File:' .. data.playable.style .. ' LoR icon.png|20px|link=]] ' .. data.playable.style .. '</span> • ' |
|||
end |
|||
if data.playable.difficulty then |
|||
gridText = gridText .. '<span class="poc-' .. data.playable.difficulty:lower() .. '"> ' .. data.playable.difficulty .. '</span></div>' |
|||
end |
|||
gridText = gridText .. '<div class="poc-champion-power" style="display: inline-flex; flex-wrap: wrap; justify-content: center;' |
|||
if data.name ~= 'Aurelion Sol' then |
|||
gridText = gridText .. 'width: 120px;' -- Controls the number of powers in one line (120px -> 3 powers per line) |
|||
end |
|||
gridText = gridText .. '>' |
|||
-- Ordering the powers correctly |
|||
for i, power in ipairs(data.playable.power) do |
|||
if power.code then |
|||
gridText = gridText .. '<span class="skin-icon" style="white-space: nowrap; order: ' .. tostring(i) .. ';"' |
|||
gridText = gridText .. ' data-game="lor" data-skin="PoC" data-champion="' .. power.code .. '"><span style="position:relative;text-indent:0;">' |
|||
gridText = gridText .. '[[File:' .. power.code .. '.png|30px|link=LoR:' .. data.name .. '/PoC]]  </span></span>' |
|||
end |
|||
end |
|||
gridText = gridText .. '</div>' |
|||
if data.support then |
|||
gridText = gridText .. '<div class="poc-champion-reinforcement"><span class="lor-tooltip" data-param="' .. data.id .. ',' .. data.support[1] .. ',' .. data.support[2] .. ', 50%">[[File:LoR Card icon.png|17px|link=|alt=Reinforcements]]</span></div>' |
|||
end |
|||
-- Closing champion container |
|||
gridText = gridText .. '</div>' |
|||
end |
|||
-- Closing grid container |
|||
gridText = gridText .. '</div>' |
|||
return gridText |
|||
end |
|||
function p.pocChampionNavigation(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local size = args["size"] or "80px" |
|||
local constellationOnly = args["constellationOnly"] or false |
|||
local pocData = require('Module:LoRPoCData/data') |
|||
local lorTable = {} |
|||
local s = "" |
|||
local navText = "" |
|||
pocData = pocData["Champion"] |
|||
local championtable = {} |
|||
for champion, data in pairs(pocData) do |
|||
if constellationOnly ~= false then |
|||
if (data["playable"]) and (data["playable"]["constellationRegion"]) then |
|||
table.insert(championtable, data) |
|||
end |
|||
else |
|||
if (data["playable"]) then |
|||
table.insert(championtable, data) |
|||
end |
|||
end |
|||
end |
|||
table.sort(championtable, function(a, b) return a.name < b.name end) |
|||
for _, data in pairs(championtable) do |
|||
navText = navText .. '[[File:' .. data.id .. '.png|' .. size .. '|link=LoR:' .. data.name .. '/PoC]]' |
|||
end |
|||
return navText |
|||
end |
|||
function p.pocWeekliesDateRange() |
|||
local today = os.date("*t") |
|||
local current_wday = today.wday |
|||
local days_to_add = (2 - current_wday) % 7 -- 2 corresponds to Monday |
|||
if days_to_add == 0 then |
|||
days_to_add = 7 |
|||
end |
|||
days_to_add = days_to_add - 1 -- Last day is non-inclusive |
|||
local next_sunday_time = os.time(today) + days_to_add * 86400 -- 86400 seconds in a day |
|||
local next_sunday = os.date("*t", next_sunday_time) |
|||
local next_month_name = os.date("%B", next_sunday_time) |
|||
local prev_monday_time = next_sunday_time - 6 * 86400 |
|||
local prev_monday = os.date("*t", prev_monday_time) |
|||
local prev_month_name = os.date("%B", prev_monday_time) |
|||
return string.format("%s %d – %s %d", prev_month_name, prev_monday.day, next_month_name, next_sunday.day) |
|||
end |
|||
function p.subtypeContent(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local cardcode = args['code'] or args[1] or nil |
|||
if not cardcode then |
|||
return '' |
|||
end |
|||
local lorData = mw.loadData('Module:LoRData/data') |
|||
subtypetext = '' |
|||
for _, subtype in pairs(lorData[cardcode].subtype) do |
|||
subtypelink = '[[LoR:' .. subtype .. '|' .. subtype .. ']]' |
|||
if subtypetext ~= '' then |
|||
subtypetext = subtypetext .. ", " .. subtypelink |
|||
else |
|||
subtypetext = subtypetext .. subtypelink |
|||
end |
|||
subtypetext = subtypetext .. "[[" .. "Category:LoR " .. subtype .. "]]" |
|||
end |
|||
return frame:preprocess(subtypetext) |
|||
end |
|||
function p.regionContent(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local cardcode = args['code'] or args[1] or nil |
|||
if not cardcode then |
|||
return '' |
|||
end |
|||
local lorData = mw.loadData('Module:LoRData/data') |
|||
if not lorData[cardcode] then |
|||
return '' |
|||
end |
|||
local regions = {} |
|||
if not lorData[cardcode].regions then |
|||
local regionCode = string.sub(cardcode, 3, 4) |
|||
for _, regionData in pairs(REGIONS) do |
|||
if regionData.code == regionCode then |
|||
table.insert(regions, regionData.name) |
|||
break |
|||
end |
|||
end |
|||
else |
|||
regions = lorData[cardcode].regions |
|||
end |
|||
regiontext = '' |
|||
for _, region in pairs(regions) do |
|||
regionlink = '[[File:' .. region .. ' LoR Region.png|20px]] ' |
|||
regionlink = regionlink .. '[[LoR:' .. region .. '|' .. region .. ']]' |
|||
if regiontext ~= '' then |
|||
regiontext = regiontext .. ", " .. regionlink |
|||
else |
|||
regiontext = regiontext .. regionlink |
|||
end |
|||
regiontext = regiontext .. "[[" .. "Category:LoR " .. region .. "]]" |
|||
end |
|||
if regiontext == '' then |
|||
regiontext = 'N/A' |
|||
end |
|||
return frame:preprocess(regiontext) |
|||
end |
|||
function p.artworkContent(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local cardcode = args['code'] or args[1] or nil |
|||
if not cardcode then |
|||
return '' |
|||
end |
|||
local lorData = mw.loadData('Module:LoRData/data') |
|||
local imageSize = '125px' |
|||
artworkText = "<ul style='margin-left:0;'>" |
|||
artworkText = artworkText .. "<li style='display:inline-block;text-indent:0px;'>[[File:" .. cardcode .. "-full.png|thumb|" |
|||
.. imageSize .. "|Primary|left]]</li>" |
|||
if lorData[cardcode].alternate then |
|||
artworkText = artworkText .. "<li style='display:inline-block;text-indent:0px;'>[[File:" .. cardcode |
|||
.. "-alt-full.png|thumb|" .. imageSize .. "|Censored|left]]" |
|||
end |
|||
for _, artwork in pairs(lorData[cardcode].artworks or {}) do |
|||
local extension = 'png' |
|||
local artworkParts = lib.split(artwork, "-") |
|||
local HD = false |
|||
local alternate = false |
|||
local display = false |
|||
local prerelease = false |
|||
local old = false |
|||
for k, v in pairs(artworkParts) do |
|||
if (v == 'hd') then |
|||
HD = true |
|||
end |
|||
if (v == 'alt') then |
|||
alternate = true |
|||
end |
|||
if (v == 'display') then |
|||
display = true |
|||
end |
|||
if (v == 'pre') then |
|||
prerelease = true |
|||
end |
|||
if (v == 'old') then |
|||
old = true |
|||
end |
|||
end |
|||
local artworkContents = {} |
|||
if HD then |
|||
table.insert(artworkContents, 'HD') |
|||
extension = 'jpg' |
|||
end |
|||
if prerelease then |
|||
table.insert(artworkContents, 'Pre-Release') |
|||
end |
|||
if alternate then |
|||
table.insert(artworkContents, '[[LoR:List of cards/Alternate|Censored]]') |
|||
end |
|||
if display then |
|||
table.insert(artworkContents, '[[League Displays]]') |
|||
extension = 'jpg' |
|||
end |
|||
if old then |
|||
table.insert(artworkContents, 'Old') |
|||
end |
|||
if #artworkContents >= 1 then |
|||
artworkContent = table.concat(artworkContents, " ") |
|||
else |
|||
artworkContent = 'Uncategorized' |
|||
end |
|||
artworkLink = "<li style='display:inline-block;text-indent:0px;'>[[File:" .. cardcode .. "-" |
|||
.. artwork .. "-full." .. extension .. "|thumb|" .. imageSize .. "|" .. artworkContent .. "|left]]</li>" |
|||
if artworkText ~= '' then |
|||
artworkText = artworkText .. " " .. artworkLink |
|||
else |
|||
artworkText = artworkText .. artworkLink |
|||
end |
|||
end |
|||
artworkText = artworkText .. "</ul>" |
|||
return frame:preprocess(artworkText) |
|||
end |
|||
function p.artworkTooltip(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local artworkCode = args['code'] or args[1] or nil |
|||
if not artworkCode then |
|||
return '' |
|||
end |
|||
local artworkList = lib.split(artworkCode, ",") |
|||
local width = 250 |
|||
if string.find(artworkList[1], '-full') then |
|||
width = 300 |
|||
end |
|||
if string.find(artworkList[#artworkList], '%%') then |
|||
width = math.floor(width * (tonumber(string.match(artworkList[#artworkList], '%d+')/100) or 1)) |
|||
table.remove(artworkList, #artworkList) |
|||
end |
|||
if (#artworkList > 4) then |
|||
width = width / 2 |
|||
end |
|||
local artworkTooltip = '<div style="display:inline-flex; flex-wrap:wrap; width:' .. math.min(width * 4, width * #artworkList) .. 'px; box-shadow: rgb(1, 10, 19) 0px 0px 25px 15px;">' |
|||
for k, v in pairs(artworkList) do |
|||
artworkTooltip = artworkTooltip .. '<div style="display:inline-block; background-color: rgb(1, 10, 19); flex: 1 1;">' |
|||
artworkTooltip = artworkTooltip .. '[[File:' .. v .. '.png|' .. width .. 'px]]' |
|||
artworkTooltip = artworkTooltip .. '</div>' |
|||
end |
|||
artworkTooltip = artworkTooltip .. '</div>' |
|||
return artworkTooltip |
|||
end |
|||
function p.randomCard(frame) |
|||
local args = lib.frameArguments(frame) |
|||
local lorData = mw.loadData('Module:LoRData/data') |
|||
local keys = {} |
|||
for key, _ in pairs(lorData) do |
|||
keys[#keys+1] = key --Store keys in another table |
|||
end |
|||
local randomCode |
|||
-- Random |
|||
math.randomseed(os.time()) |
|||
math.random(); math.random(); math.random() |
|||
for x = 1,10 do |
|||
randomCode = keys[math.random(1, #keys)] |
|||
end |
|||
local randomCard = lorData[randomCode] |
|||
local link = 'LoR:' .. randomCode |
|||
local text = '[[File:' .. randomCode .. '.png|250px|link=' .. link .. ']]' |
|||
text = text .. '[[' .. link .. '|' .. randomCard.name .. ']]' |
|||
local cardMode = randomCard.mode |
|||
if cardMode then |
|||
text = text .. ' ([[LoR:List of cards/' .. cardMode .. '|' .. cardMode .. ']])' |
|||
end |
|||
return frame:preprocess(text) |
|||
end |
end |
||
Line 1,940: | Line 476: | ||
bytesPopped = bytesPopped + 1 |
bytesPopped = bytesPopped + 1 |
||
local current = BitOperator.AND(bytes[i], VarInt.AllButMSB) |
local current = BitOperator.AND(bytes[i], VarInt.AllButMSB) |
||
result = BitOperator.OR(result, BitOperator. |
result = BitOperator.OR(result, BitOperator.RIGHT_SHIFT(current, currentShift)) |
||
if BitOperator.AND(bytes[i], VarInt.JustMSB) ~= VarInt.JustMSB then |
if BitOperator.AND(bytes[i], VarInt.JustMSB) ~= VarInt.JustMSB then |