Module:Crafting Upgrades
From Valheim Wiki
Documentation for this module may be created at Module:Crafting Upgrades/doc
-- Table is registered at /Template:Crafting_Upgrades local item_link = require('Module:Item').go local is_crafting_station = require('Module:Item').is_crafting_station local trim = mw.text.trim local cargo = mw.ext.cargo local cache = require 'mw.ext.LuaCache' local currentFrame -- global cache for current frame object. local inputArgs -- global args cache. local lang -- cache current lang. local resultanchor local l10n = function(key) return key end local extCols_stationBefore = nil local extCols_stationAfter = nil local extCols_A = nil local extCols_B = nil local extCols_C = nil local extCols_D = nil local countStationCells = 0 function getArg(key) local v = trim(inputArgs[key] or '') if v == '' then return nil else return v end end function firstToUpper(str) return (str:gsub("^%l", string.upper)) end local itemLink = (function() local cache = {} return function(name, args) local key = name.."|" if args then for k, v in pairs(args) do key = key..k..'='..tostring(v)..'|' end end if not cache[key] then local args = args and mw.clone(args) or {} args[1] = name if (not args[2]) or args[2]=='' then args[2] = currentFrame:expandTemplate{ title = 'tr', args = {name, lang=lang} } end args['small'] = 'y' args['lang'] = lang or 'en' args['nolink'] = args['nolink'] and 'y' or nil cache[key] = item_link(currentFrame, args) end return cache[key] end end)() -- credit: http://richard.warburton.it -- this version is with trim. local explode = function(div,str) if (div=='') then return false end local pos,arr = 0,{} -- for each divider found for st,sp in function() return string.find(str,div,pos,true) end do table.insert(arr, trim(string.sub(str,pos,st-1))) -- Attach chars left of current divider pos = sp + 1 -- Jump past current divider end table.insert(arr, trim(string.sub(str,pos))) -- Attach chars right of last divider return arr end -- retuan a array of itemname, split xxx/yyy to item1=xxx, item2=yyy. If it's something like "Lead/Iron Bar", it will normalize as item1 = Iron Bar, item2 = Lead Bar. local split = (function() local metals = { ['Copper/Tin'] = 1, ['Tin/Copper'] = 2, } return function(name) local count = select(2, name:gsub("/", "/", 2)) if count == 0 then -- only 1 item return { trim(name) } elseif count == 1 then -- 2 items local item1a, item1b, item2a, item2b = name:match("^%s*(%S+)%s*(.-)/%s*(%S+)%s*(.-)$") local x = metals[item1a..'/'..item2a] if tostring(item1b) == '' and x then item1b = item2b end if x == 2 then return {trim(item2a..' '..item2b), trim(item1a..' '..item1b)} else return {trim(item1a..' '..item1b), trim(item2a..' '..item2b)} end else -- 3 or more items return explode('/', name) end end end)() -- return 1 or 2 value(s), when input is name[note], return item, note. local itemname = function(str) local item, note = str:match("^(.-)(%b[])$") if item then return item, note else return str end end -- normalize ingredient name input, Lead Bar=>¦Lead Bar¦, Iron/Lead Bar => ¦Iron Bar¦Lead Bar¦, Lead/Iron Bar => ¦Iron Bar¦Lead Bar¦ .... local normalize = function(name) local result = '¦' for k, v in ipairs(split(name)) do result = result .. itemname(v) .. '¦' end return result end local escape = function(str) return str:gsub("'", "\\'"):gsub("'", "\\'") end local enclose = function(str) return "'" .. escape(str) .. "'" end local getItemGroupName = function(item) if item == 'Wood' or item == 'Wood2' or item == 'Wood3' then return 'Any Wood' elseif item == 'Copper Bar' or item == 'Tin Bar' then return 'Any Bar' end end local normalizeStation = function(station) if station == 'Altar' then station = 'Altar2' end return station end local normalizeVersion = function(_version) return '' end local criStr = function(args) local constraints = {} -- station = ? and station != ? local _station = trim(args['station'] or '') local _stationnot = trim(args['stationnot'] or '') local str = '' if _station ~= '' then for _, v in ipairs(explode('/', _station)) do if str ~= '' then str = str .. ' OR ' end str = str .. "station = " .. enclose(normalizeStation(v)) end end if _stationnot ~= '' then if str ~= '' then str = '(' .. str .. ')' end for _, v in ipairs(explode('/', _stationnot)) do if str ~= '' then str = str .. ' AND ' end str = str .. 'station <> ' .. enclose(normalizeStation(v)) end end constraints['station'] = str local _result = trim(args['result'] or '') local _resultnot = trim(args['resultnot'] or '') local str = '' if _result ~= '' then for _, v in ipairs(explode('/', _result)) do if str ~= '' then str = str .. ' OR ' end if mw.ustring.sub(v, 1, 5) == 'LIKE ' then str = str .. "result LIKE " .. enclose(trim(mw.ustring.sub(v, 6))) else str = str .. 'result=' .. enclose(v) end end end if _resultnot ~= '' then if str ~= '' then str = '(' .. str .. ')' end for _, v in ipairs(explode('/', _resultnot)) do if str ~= '' then str = str .. ' AND ' end if mw.ustring.sub(v, 1, 5) == 'LIKE ' then str = str .. "result NOT LIKE " .. enclose(trim(mw.ustring.sub(v, 6))) else str = str .. 'result <> ' .. enclose(v) end end end if str ~= '' then constraints['result'] = str end -- ingredient = ? local _ingredient = trim(args['ingredient'] or '') if _ingredient ~= '' then local str = '' for _, v in ipairs(explode('/', _ingredient)) do if str ~= '' then str = str .. ' OR ' end if mw.ustring.sub(v, 1, 1) == '#' then str = str .. "ingredients HOLDS LIKE '%¦" .. escape(mw.ustring.sub(v, 2)) .. "¦%'" elseif mw.ustring.sub(v, 1, 5) == 'LIKE ' then str = str .. "ingredients HOLDS LIKE '%¦" .. escape(trim(mw.ustring.sub(v, 6))) .. "¦%'" else str = str .. "ingredients HOLDS LIKE '%¦" .. escape(v) .. "¦%'" -- any xxx local group = getItemGroupName(v) if group then str = str .. " OR ingredients HOLDS LIKE '%¦" .. escape(group) .. "¦%'" end end end constraints['ingredient'] = str end --versions local _version = normalizeVersion(args['version'] or args['versions'] or '') if _version ~= '' then constraints['version'] = 'version = '..enclose(_version) end local where = '' if constraints['station'] then where = constraints['station'] end if constraints['result'] then if where ~= '' then where = where .. ' AND ' end where = where .. '(' .. constraints['result'] .. ')' end if constraints['ingredient'] then if where ~= '' then where = where .. ' AND ' end where = where .. '(' .. constraints['ingredient'] .. ')' end if constraints['version'] then if where ~= '' then where = where .. ' AND ' end where = where .. '(' .. constraints['version'] .. ')' end return where end local resultCell = function(row, showResultId, needLink, noVersion, template) local result, amount, quality = row['result'], row['amount'], row['quality'] local str = '' local args = {anchor = resultanchor, nolink = not needLink, class='multi-line'} if showResultId then args['id'] = resultid end if resultimage then args['image'] = resultimage end if resulttext then args[2] = resulttext end if quality ~= '' then args['icons'] = 'n' end str = str .. itemLink(result, args) if amount ~= '1' then str = str .. ' <span class="note-text">('..amount..')</span>' end if template then local template_str = currentFrame:expandTemplate{ title = template, args = { link = needLink, showid = showResultId, noversion = noVersion, result=result, amount=amount, } } str = template_str:gsub('@@@@', str) end return str end local ingredientsCell = function(args) local str = '<ul>' for _, v in ipairs(explode('^', args)) do str = str .. '<li>' local item, amount = v:match('^(.-)¦(.-)$') local s for _, itemname in ipairs(split(item)) do if s then s = s .. l10n('ingredients_sep') .. itemLink(itemname) else s = itemLink(itemname) end end str = str .. s if amount ~= '1' then str = str .. ' <span class="note-text">('..amount..')</span>' end str = str .. '</li>' end str = str .. '</ul>' return str end local stationLevelLink = function(station, level) return '<div class="station-level-container" title="' .. l10n('Required station level') .. '">' .. '[[File:Crafting Station Level Star.png|link=' .. station .. ']]' .. '<span>' .. level .. '</span>' .. '</div>' end local stationCell = function(station, level, options) options = options or {wrap = 'y', suffixLinkWithItemTag = false} if station == 'By Hand' then return l10n('By Hand') elseif true == is_crafting_station(station) then -- station == 'Workbench' or station == 'Forge' or station == 'Cauldron' or station == 'Fermenter' then local linkItem = itemLink(station, options) if (level or '') ~= '' then linkItem = linkItem .. '<br>' .. stationLevelLink(station, level) end return linkItem -- return itemLink(station, options) elseif station == "Station One and Station Two" then return itemLink("Station One", options) .. l10n('And').. itemLink('Station Two', {mode = 'text'}) else return station end end -- for extract. local compactStation = function(station) if station == 'By Hand' then return '' else return l10n('compact_before') .. station .. l10n('compact_after') end end local propCell = function(prop) if prop == 'args' then return 'Ingredients' elseif prop == 'stationlevel' then return 'Station level' elseif prop == 'blockpower' then return 'Blocking power' elseif prop == 'movementspeed' then return 'Movement speed' elseif prop == 'parrybonus' then return 'Parry bonus' elseif prop == 'parryforce' then return 'Parry force' end return firstToUpper(prop) end local getFlags = function(args) local needCate = 1 local needLink = true local _cate = trim(args['cate'] or '') if _cate == 'force' or _cate == 'all' then needCate = 2 elseif _cate == 'n' or _cate == 'no' then needCate = nil end local _link = trim(args['link'] or '') if _link == 'y' or _link == 'yes' or _link == 'force' then needLink = true elseif _link == 'n' or _link == 'no' then needLink = false end return needCate, needLink end local addCate, cateStr -- for table body. init in p.query local tableStart = function() local header_ local str = '<div class="crafts crafts-upgrades '.. (getArg('class') or '') local _id = (getArg('id') or '') if _id ~= '' then str = str .. '" id="'.. _id end local _css = (getArg('css') or getArg('style') or '') if _css ~= '' then str = str .. '" style="'.. _css end str = str .. '"><div class="wrap"><table ' str = str .. 'cellpadding="0" cellspacing="0">' str = str .. '<th class="result">' .. (getArg('header-property') or l10n('Property')) .. '</th>' return str end local tableEnd = function(rows_count, expectedrows) local str = '</table><div style="display: none">total: '..rows_count..' row(s)</div></div></div>' if expectedrows and rows_count ~= expectedrows then str = str .. '[[Category:'.. l10n('cate_unexpected_rows_count') .. ']]' end if not expectedrows and rows_count == 0 then str = str .. '[[Category:'.. l10n('cate_no_row') .. ']]' end return str end local tableBodyUpgrades = function(noResultsText, result, showResultId, withStation, needGroup, needCate, needLink, rootpagename, title, expectedrows, template, stationGroup) if next(result) == nil then return "''" .. (noResultsText or 'No results') .. "''" end propertyOrder = { quality = 10, station = 20, stationlevel = 30, durability = 40, armor = 45, slash = 50, blunt = 60, pierce = 70, backstab = 80, knockback = 90, spirit = 100, poison = 110, fire = 112, frost = 114, lightning = 116, blockpower = 120, movementspeed = 130, parryforce = 140, parrybonus = 150, weight = 160, args = 999, } -- inputArgs = {} -- @TODO: Mave -- matches the definition and order in Template:Crafting_Upgrades properties = { 'quality', 'station', 'stationlevel', 'args', 'durability', 'armor', 'blockpower', 'movementspeed', 'parryforce', 'parrybonus', 'slot', 'weight', 'slash', 'blunt', 'pierce', 'backstab', 'knockback', 'spirit', 'poison', 'fire', 'frost', 'lightning', } local count = 0 local output = {} -- local output2 = {} -- local iOutput = 0; for _, row in ipairs(result) do count = count + 1 for _, prop in ipairs(properties) do arg = row[prop] or '' if prop == 'args' and arg ~= '' then arg = ingredientsCell(arg) elseif prop == 'quality' and arg ~= '' then arg = 'Quality ' .. arg end local k = {} output[prop] = (output[prop] or '') .. 'xxxyyyzzz' .. arg -- k["prop"] = prop -- k["value"] = output[prop] -- output2[iOutput] = k -- iOutput = iOutput + 1 end end local countToCompare = count - 1 emptyString = '' for i=1, countToCompare do emptyString = emptyString .. 'xxxyyyzzz' end local tableStart = tableStart() local tableContents = '' lastOrder = 800 for prop, str in pairs(output) do -- for _, var in ipairs(output2) do -- prop = var["prop"] -- str = var["value"] stringContents = string.sub(str, 10) if stringContents ~= emptyString then if prop == 'quality' then tableStart = tableStart .. str:gsub('xxxyyyzzz', '</th><th>') else order = (propertyOrder[prop] or lastOrder) lastOrder = lastOrder - 1 tableContents = tableContents .. '<tr data-prop="' .. prop .. '" data-order="' .. order .. '>' local td = '<td' local class = prop if prop == 'args' then class = 'ingredients' end td = td .. ' class="' .. class .. '"' td = td .. ' data-prop="' .. prop .. '"' td = td .. '>' -- local replaced, _ = str:gsub('xxxyyyzzz', '</td>' .. td) local rowContents = '' for _, v in ipairs(explode('xxxyyyzzz', str)) do if v ~= '' then if prop == 'station' then v = stationCell(v) end rowContents = rowContents .. td .. v .. '</td>' end end -- local rowContents = replaced tableContents = tableContents .. '<td data-propHeader="' .. prop .. '">' .. propCell(prop) .. '</td>' .. rowContents tableContents = tableContents .. '</tr>' end end end return tableStart .. tableContents .. tableEnd(-1, -1) end local tableRow = function(str, row, current_station, station_count, rows_count, showResultId, withStation, needCate, needLink, needGroup, current_result, result_count, current_result_ext, result_ext_count, template, stationGroup) local str_w = '' -- before result col local str_x = '' -- between result and ingredients cols local str_y = '' -- between ingredients and station cols local str_z = '' -- after station local str_resultCell = '' local result_index = getArg('result-index-#'..rows_count) or getArg('result-index-'..row['result']) or getArg('result-index-'..row['result']) str = str .. '<tr data-rowid="'..tostring(rows_count)..'">' if needGroup then local result = row['result']..'|'..row['amount']..'|'..row['quality'] -- grouping result col if current_result == result then -- is same group ?? result_count = result_count + 1 else --new group: -- rowspan value for prev group, if needed. if result_count then str = str:gsub("yyyrowspanyyy", tostring(result_count)) end -- begin this group current_result = result result_count = 1 str_resultCell = '<td class="result" rowspan="yyyrowspanyyy">'.. resultCell(row, showResultId, needLink, false, template).. '</td>' end -- grouping ext cols if result_index and (current_result_ext == result_index) then -- is same group ?? result_ext_count = result_ext_count + 1 else --new group: -- rowspan value for prev group, if needed. if result_ext_count then str = str:gsub("zzzrowspanzzz", tostring(result_ext_count)) end -- begin this group current_result_ext = result_index result_ext_count = 1 if extCols_A then for _, v in ipairs(extCols_A) do if result_index then str_w = str_w .. '<td class="'..v..'" rowspan="zzzrowspanzzz">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_w = str_w .. '<td class="'..v..'" rowspan="zzzrowspanzzz"></td>' end end end if extCols_B then for _, v in ipairs(extCols_B) do if result_index then str_x = str_x .. '<td class="'..v..'" rowspan="zzzrowspanzzz">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_x = str_x .. '<td class="'..v..'" rowspan="zzzrowspanzzz"></td>' end end end if extCols_C then for _, v in ipairs(extCols_C) do if result_index then str_y = str_y .. '<td class="'..v..'" rowspan="zzzrowspanzzz">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_y = str_y .. '<td class="'..v..'" rowspan="zzzrowspanzzz"></td>' end end end if extCols_D then for _, v in ipairs(extCols_D) do if result_index then str_z = str_z .. '<td class="'..v..'" rowspan="zzzrowspanzzz">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_z = str_z .. '<td class="'..v..'" rowspan="zzzrowspanzzz"></td>' end end end end else if extCols_A then for _, v in ipairs(extCols_A) do if result_index then str_w = str_w .. '<td class="'..v..'">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_w = str_w .. '<td class="'..v..'"></td>' end end end if extCols_B then for _, v in ipairs(extCols_B) do if result_index then str_x = str_x .. '<td class="'..v..'">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_x = str_x .. '<td class="'..v..'"></td>' end end end if extCols_C then for _, v in ipairs(extCols_C) do if result_index then str_y = str_y .. '<td class="'..v..'">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_y = str_y .. '<td class="'..v..'"></td>' end end end if extCols_D then for _, v in ipairs(extCols_D) do if result_index then str_z = str_z .. '<td class="'..v..'">' .. (getArg(result_index .. '-row-' .. v) or '') .. '</td>' else str_z = str_z .. '<td class="'..v..'"></td>' end end end str_resultCell = '<td class="result">'.. resultCell(row, showResultId, needLink, false, template).. '</td>' end str = str .. str_w .. str_resultCell .. str_x .. '<td class="ingredients">' .. ingredientsCell(row['args']).. '</td>' .. str_y if withStation then local stationName = row['station'] or '' local stationLevel = row['stationlevel'] or '' local station = stationName .. stationLevel -- @TODO: Mave if stationGroup then if current_station == station then -- is same group ?? station_count = station_count + 1 else --new group: -- rowspan value for prev group, if needed. if station_count then str = str:gsub("xxxrowspanxxx", tostring(station_count)) end -- begin this group current_station = station station_count = 1 local station_index = getArg('station-index-'..station) -- station before: if extCols_stationBefore then for _, v in ipairs(extCols_stationBefore) do if station_index then str = str .. '<td class="station station-7 station- '..v..'" rowspan="xxxrowspanxxx">' .. (getArg(station_index .. '-row-' .. v) or '') .. '</td>' else str = str .. '<td class="station station-8 '..v..'" rowspan="xxxrowspanxxx"></td>' end end end str = str .. '<td class="station station-15" data-station="' .. stationName .. '" data-stationlevel="' .. stationLevel .. '" rowspan="xxxrowspanxxx">'.. stationCell(stationName, stationLevel) ..'</td>' -- station after: if extCols_stationAfter then for _, v in ipairs(extCols_stationAfter) do if station_index then str = str .. '<td class="station station-9 '..v..'" rowspan="xxxrowspanxxx">' .. (getArg(station_index .. '-row-' .. v) or '') .. '</td>' else str = str .. '<td class="station station-10 '..v..'" rowspan="xxxrowspanxxx"></td>' end end end end else if current_station == station then -- is same group ?? station_count = station_count + 1 else current_station = station station_count = 1 end local station_index = getArg('station-index-'..station) -- station before: if extCols_stationBefore then for _, v in ipairs(extCols_stationBefore) do if station_index then str = str .. '<td class="station station-11 '..v..'">' .. (getArg(station_index .. '-row-' .. v) or '') .. '</td>' else str = str .. '<td class="station station-12 '..v..'"></td>' end end end str = str .. '<td class="station station-1">'.. stationCell(stationName, stationLevel) ..'</td>' -- station after: if extCols_stationAfter then for _, v in ipairs(extCols_stationAfter) do if station_index then str = str .. '<td class="station station-13 '..v..'">' .. (getArg(station_index .. '-row-' .. v) or '') .. '</td>' else str = str .. '<td class="station station-14 '..v..'"></td>' end end end end end str = str .. str_z ..'</tr>' return str, current_station, station_count, current_result, result_count, current_result_ext, result_ext_count end local extRows = function(withStation, isTop) local prefix if isTop then prefix = 'topextrow-' else prefix = 'extrow-' end local returnstr = '' local valid = true local p local str local _i = 1 local temp while valid do local i = tostring(_i) .. '-' p = prefix .. i valid = false str = '<tr data-'..prefix..'id="'..tostring(_i)..'">' if extCols_A then for _, v in ipairs(extCols_A) do temp = getArg(p..v) if temp then valid = true str = str .. '<td class="'..v..'">' .. temp .. '</td>' else str = str .. '<td class="'..v..'"></td>' end end end temp = getArg(p..'col-result') if temp then valid = true str = str .. '<td class="result">' .. temp .. '</td>' else str = str .. '<td class="result"></td>' end if extCols_B then for _, v in ipairs(extCols_B) do temp = getArg(p..v) if temp then valid = true str = str .. '<td class="'..v..'">' .. temp .. '</td>' else str = str .. '<td class="'..v..'"></td>' end end end temp = getArg(p..'col-ingredients') if temp then valid = true str = str .. '<td class="ingredients">' .. temp .. '</td>' else str = str .. '<td class="ingredients"></td>' end if extCols_C then for _, v in ipairs(extCols_C) do temp = getArg(p..v) if temp then valid = true str = str .. '<td class="'..v..'">' .. temp .. '</td>' else str = str .. '<td class="'..v..'"></td>' end end end if withStation then -- station before: if extCols_stationBefore then for _, v in ipairs(extCols_stationBefore) do temp = getArg(p..v) if temp then valid = true str = str .. '<td class="station station-1 '..v..'">' .. temp .. '</td>' else str = str .. '<td class="station station-2 '..v..'"></td>' end end end temp = getArg(p..'col-station') if temp then valid = true str = str .. '<td class="station station-3">' .. temp .. '</td>' else str = str .. '<td class="station station-4"></td>' end -- station after: if extCols_stationAfter then for _, v in ipairs(extCols_stationAfter) do temp = getArg(p..v) if temp then valid = true str = str .. '<td class="station station-5 '..v..'">' .. temp .. '</td>' else str = str .. '<td class="station station-6 '..v..'"></td>' end end end end if extCols_D then for _, v in ipairs(extCols_D) do temp = getArg(p..v) if temp then valid = true str = str .. '<td class="'..v..'">' .. temp .. '</td>' else str = str .. '<td class="'..v..'"></td>' end end end str = str .. '</tr>' if valid then _i = _i + 1 returnstr = returnstr .. str end end return returnstr end local tableBody = function(result, showResultId, withStation, needGroup, needCate, needLink, rootpagename, title, expectedrows, template, stationGroup) local str = tableStart() -- top ext rows: str = str .. extRows(withStation, true) -- main rows: local current_station local station_count local rows_count = 0 local current_result local result_count local current_result_ext local result_ext_count for _, row in ipairs(result) do rows_count = rows_count + 1 -- table row: -- str, current_station, station_count, current_result, result_count, current_result_ext, result_ext_count = tableRow(str, row, current_station, station_count, rows_count, showResultId, withStation, needCate, needLink, needGroup, current_result, result_count, current_result_ext, result_ext_count, template, stationGroup) str2 = tableRow(str, row, current_station, station_count, rows_count, showResultId, withStation, needCate, needLink, needGroup, current_result, result_count, current_result_ext, result_ext_count, template, stationGroup) -- cate: -- if needCate then -- if needCate == 2 or rootpagename == currentFrame:expandTemplate{ title = 'tr', args = {row['result'], lang=lang} } then -- addCate(row['station']) -- end -- end end -- -- rowspan value for last station group and result group -- if withStation and station_count and stationGroup then -- str = str:gsub("xxxrowspanxxx", tostring(station_count)) -- end -- if needGroup then -- str = str:gsub("yyyrowspanyyy", tostring(result_count)) -- str = str:gsub("zzzrowspanzzz", tostring(result_ext_count)) -- end -- -- ext rows: -- str = str .. extRows(withStation) -- -- table end str2 = str2 .. tableEnd(rows_count, expectedrows) -- cate -- if needCate then -- str = str .. cateStr() -- end return str2 end ----------------------------------------------------------------- local p = {} -- for {{Crafting Upgrades/register}} p.register = function(frame) local args = frame:getParent().args -- {{{ingredients}}} local ingredients = {} -- list of {index, itemname, amount} for k, v in pairs(args) do if(type(k) == 'number') then if k % 2 == 1 then -- 2n-1, nth item local index, item, amount = (k+1)/2, trim(v), trim(args[k+1]) ingredients[index] = {item, amount} end end end local serialized = '' -- serialized ingredients list for _, v in ipairs(ingredients) do serialized = serialized .. '^' .. v[1] .. '¦' .. v[2] end serialized = mw.ustring.sub(serialized, 2) table.sort(ingredients, function(a , b) return a[1] < b[1] end) -- sort by ingredient item name local ingredients_string = '' local ingredients_string_full = '' for _, v in ipairs(ingredients) do local name, amount = unpack(v) local ingstr = normalize(name) ingredients_string = ingredients_string .. '^' .. ingstr ingredients_string_full = ingredients_string_full .. '^' .. ingstr .. amount end --{{{version}}}, normalize version = normalizeVersion(args['version'] or '') --store frame:callParserFunction('#cargo_store:_table=CraftingUpgrades',{ result = trim(args['result'] or ''), amount = trim(args['amount'] or ''), quality = trim(args['quality'] or ''), station = normalizeStation(trim(args['station'] or '')), stationlevel = trim(args['stationlevel'] or ''), repairstationlevel = trim(args['repairstationlevel'] or ''), durability = trim(args['durability'] or ''), armor = trim(args['armor'] or ''), blockpower = trim(args['blockpower'] or ''), movementspeed = trim(args['movementspeed'] or ''), parryforce = trim(args['parryforce'] or ''), parrybonus = trim(args['parrybonus'] or ''), slot = trim(args['slot'] or ''), weight = trim(args['weight'] or ''), slash = trim(args['slash'] or ''), blunt = trim(args['blunt'] or ''), pierce = trim(args['pierce'] or ''), backstab = trim(args['backstab'] or ''), knockback = trim(args['knockback'] or ''), spirit = trim(args['spirit'] or ''), poison = trim(args['poison'] or ''), fire = trim(args['fire'] or ''), frost = trim(args['frost'] or ''), lightning = trim(args['lightning'] or ''), ingredients = mw.ustring.sub(ingredients_string, 2), ings = mw.ustring.sub(ingredients_string_full, 2), args = serialized, }) end -- p.register -- for {{craftingrecipes}} p.query = function(frame) currentFrame = frame -- global frame cache local args = frame:getParent().args inputArgs = args lang = frame.args['lang'] or 'en' resultanchor = trim(args['resultanchor'] or '') addCate, cateStr = (function() local cate = l10n('station_cate') local cateCache = {} local addCate = function(station) cateCache[station] = true end local cateStr = function() local str = '' for station, _ in pairs(cateCache) do str = str .. '[[Category:'..(cate[station] or frame:expandTemplate{ title = 'tr', args = {station, lang=lang, link='y'}})..']]' end if str ~= '' then str = '[[Category:'.. l10n('cate_craftable').. ']]' .. str end return str end return addCate, cateStr end)() local where = trim(args['where'] or '') if where == '' then where = criStr(args) end -- no constraint no result. if where == '' then return '<span style="color:red;font-weight:bold;">CraftingRecipes: No constraint</span>' end -- format: local needCate, needLink = getFlags(args) local needGroup = true if (getArg('grouping') or 'y'):sub(1,1) == 'n' then needGroup = false end local showResultId = false if trim(args['showresultid'] or '') ~= '' then showResultId = true end local _title = trim(args['title'] or '') local _expectedrows = trim(args['expectedrows'] or '') if _expectedrows ~= '' then _expectedrows = tonumber(_expectedrows) else _expectedrows = nil end local rootpagename = mw.title.getCurrentTitle().rootText local noResultsText = 'No results' if args['result'] or '' ~= '' then noResultsText = 'This item cannot be upgraded' end if trim(args['nostation'] or '') ~= '' then -- no station -- query, still need contain station field for cate. local result = mw.ext.cargo.query('CraftingUpgrades', 'result, amount, quality, durability, armor, blockpower, movementspeed, parryforce, parrybonus, weight, slot, slash, blunt, pierce, spirit, poison, fire, frost, lightning, backstab, knockback, repairstationlevel, station, stationlevel, args', { where = where, groupBy = "result, amount, quality, ings", orderBy = "result, quality, amount DESC", -- Don't order by station limit = 2000, }) return tableBodyUpgrades(noResultsText, result, showResultId, false, needGroup, needCate, needLink, rootpagename, _title, _expectedrows, getArg('resulttemplate'), false) else -- with station local stationGroup = true if (getArg('stationgrouping') or 'y'):sub(1,1) == 'n' then stationGroup = false end -- query local result = mw.ext.cargo.query('CraftingUpgrades', 'result, amount, quality, durability, armor, blockpower, movementspeed, parryforce, parrybonus, weight, slot, slash, blunt, pierce, spirit, poison, fire, frost, lightning, backstab, knockback, repairstationlevel, station, stationlevel, args', { where = where, groupBy = "result, amount, quality, ings", orderBy = "station, stationlevel, result, quality, amount DESC, ings", -- order by station first for station grouping. limit = 2000, }) return tableBodyUpgrades(noResultsText, result, showResultId, true, needGroup, needCate, needLink, rootpagename, _title, _expectedrows, getArg('resulttemplate'), stationGroup) end end -- p.query -- for {{craftingrecipes/extract}} p.extract = function(frame) currentFrame = frame -- global frame cache local args = frame:getParent().args inputArgs = args lang = frame.args['lang'] or 'en' --l10n_table = l10n_info[lang] or l10n_info['en'] local where = trim(args['where'] or '') if where == '' then where = criStr(args) end -- no constraint no result. if where == '' then return '<span style="color:red;font-weight:bold;">CraftingRecipes/extract: No constraint</span>' end -- query: local result = mw.ext.cargo.query('CraftingUpgrades', 'result, amount, quality, durability, armor, blockpower, movementspeed, parryforce, parrybonus, weight, slot, slash, blunt, pierce, spirit, poison, fire, frost, lightning, backstab, knockback, repairstationlevel, station, stationlevel, args', { where = where, groupBy = "result, amount, quality, ings", orderBy = "result, amount DESC", -- Don't order by station limit = 20, -- enough. }) -- output local mode = getArg('mode') local sep = getArg('sep') or getArg('seperator') if not mode or mode == 'compact' or mode == '' then --default mode = compact local sep = sep or l10n('default_sep_compact') local withResult = getArg('withresult') local withStation = not getArg('nostation') local withVersion = not getArg('noversion') local str = nil for _, row in ipairs(result) do if str then str = str .. sep else str = '' end str = str .. '<span class="recipe compact">' if withVersion then if row['version'] ~= '' then str = str ..currentFrame:expandTemplate{ title = 'version icons', args = {row['version']} }..': ' end end local ingFlag = nil for _, v in ipairs(explode('^', row['args'])) do if ingFlag then str = str .. ' + ' else ingFlag = true end local item, amount = v:match('^(.-)¦(.-)$') if amount ~= '1' then str = str .. amount .. ' ' end local s for _, itemname in ipairs(split(item)) do if s then s = s .. " / " .. itemLink(itemname, {mode='image'}) else s = itemLink(itemname, {mode='image'}) end end str = str .. s end if withResult then str = str .. ' = ' if row['amount'] ~= '1' then str = str .. row['amount'] .. ' ' end local args = {mode='image'} if row['resultimage'] then args['image'] = row['resultimage'] end str = str .. itemLink(row['result'], args) end if withStation then str = str .. compactStation(row['station']) end str = str..'</span>' end return str elseif mode == 'ingredients' then local sep = sep or l10n('default_sep_ingredients') local str = '' for _, row in ipairs(result) do if str ~= '' then str = str .. sep end str = str .. ingredientsCell(row['args']) end return '<div class="crafting-ingredients">'..str..'</div>' elseif mode == 'station' then -- only return first row. for _, row in ipairs(result) do return stationCell(row['station'], '', {}) end elseif mode == 'result' then -- only return first row. local needCate, needLink = getFlags(args) for _, row in ipairs(result) do return resultCell(row, getArg('showresultid'), needLink, true, getArg('resulttemplate')) end elseif mode == 'ingredients-buy' then -- only process first row. for _, row in ipairs(result) do local value = 0 for _, v in ipairs(explode('^', row['args'])) do local item, amount = v:match('^(.-)¦(.-)$') value = value + require('Module:Iteminfo').getItemStat( tonumber(currentFrame:expandTemplate{ title = 'itemIdFromName', args = {item, lang='en'} }) or 0, 'value' ) * amount end return value end elseif mode == 'ingredients-sell' then -- only process first row. for _, row in ipairs(result) do local value = 0 for _, v in ipairs(explode('^', row['args'])) do local item, amount = v:match('^(.-)¦(.-)$') value = value + math.floor(require('Module:Iteminfo').getItemStat( tonumber(currentFrame:expandTemplate{ title = 'itemIdFromName', args = {item, lang='en'} }) or 0, 'value' )/5) * amount end return value end else return '<span style="color:red;font-weight:bold;">CraftingRecipes/extract: Invalid mode</span>' end end -- p.extract -- count p.count = function(frame) local args = frame:getParent().args local where = trim(args['where'] or '') if where == '' then where = criStr(args) end -- no constraint no result. if where == '' then return end -- query: since we must use group by to eliminate duplicates, so we can not use COUNT() to get row count directly. local result = mw.ext.cargo.query('CraftingUpgrades', 'result, amount, quality, durability, armor, blockpower, movementspeed, parryforce, parrybonus, weight, slot, slash, blunt, pierce, spirit, poison, fire, frost, lightning, backstab, knockback, repairstationlevel, station, stationlevel, args', { where = where, groupBy = "result, amount, quality, ings", limit = 2000, }) -- count local count = 0 for _, row in ipairs(result) do count = count + 1 end return count end -- p.count -- return "yes" or "" p.exist = function(frame) local args = frame:getParent().args local where = trim(args['where'] or '') if where == '' then where = criStr(args) end -- no constraint no result. if where == '' then return end -- query: local result = mw.ext.cargo.query('CraftingUpgrades', 'result', { where = where, limit = 1, -- enough. }) -- output for _, row in ipairs(result) do return 'yes' end end -- p.exist p.tableBodyUpgrades = tableBodyUpgrades return p